diff options
Diffstat (limited to 'nixos/modules/services')
124 files changed, 2321 insertions, 524 deletions
diff --git a/nixos/modules/services/admin/salt/master.nix b/nixos/modules/services/admin/salt/master.nix index 4346022970e12..e10a10efae652 100644 --- a/nixos/modules/services/admin/salt/master.nix +++ b/nixos/modules/services/admin/salt/master.nix @@ -20,7 +20,7 @@ in { options = { services.salt.master = { - enable = mkEnableOption (lib.mdDoc "Salt master service"); + enable = mkEnableOption (lib.mdDoc "Salt configuration management system master service"); configuration = mkOption { type = types.attrs; default = {}; diff --git a/nixos/modules/services/admin/salt/minion.nix b/nixos/modules/services/admin/salt/minion.nix index 3ae02a4cc5d5d..28b52e07c40bd 100644 --- a/nixos/modules/services/admin/salt/minion.nix +++ b/nixos/modules/services/admin/salt/minion.nix @@ -21,7 +21,7 @@ in { options = { services.salt.minion = { - enable = mkEnableOption (lib.mdDoc "Salt minion service"); + enable = mkEnableOption (lib.mdDoc "Salt configuration management system minion service"); configuration = mkOption { type = types.attrs; default = {}; diff --git a/nixos/modules/services/audio/mpdscribble.nix b/nixos/modules/services/audio/mpdscribble.nix index 132d9ad325886..e58fcdd25f63c 100644 --- a/nixos/modules/services/audio/mpdscribble.nix +++ b/nixos/modules/services/audio/mpdscribble.nix @@ -77,7 +77,7 @@ in { options.services.mpdscribble = { - enable = mkEnableOption (lib.mdDoc "mpdscribble"); + enable = mkEnableOption (lib.mdDoc "mpdscribble, an MPD client which submits info about tracks being played to Last.fm (formerly AudioScrobbler)"); proxy = mkOption { default = null; diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix index 6f4455d3be605..7d5714499f3a9 100644 --- a/nixos/modules/services/backup/borgbackup.nix +++ b/nixos/modules/services/backup/borgbackup.nix @@ -123,6 +123,7 @@ let }; # if remote-backup wait for network after = optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target"; + wants = optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target"; }; # utility function around makeWrapper @@ -147,6 +148,9 @@ let let settings = { inherit (cfg) user group; }; in lib.nameValuePair "borgbackup-job-${name}" ({ + # Create parent dirs separately, to ensure correct ownership. + "${config.users.users."${cfg.user}".home}/.config".d = settings; + "${config.users.users."${cfg.user}".home}/.cache".d = settings; "${config.users.users."${cfg.user}".home}/.config/borg".d = settings; "${config.users.users."${cfg.user}".home}/.cache/borg".d = settings; } // optionalAttrs (isLocalPath cfg.repo && !cfg.removableDevice) { diff --git a/nixos/modules/services/backup/restic-rest-server.nix b/nixos/modules/services/backup/restic-rest-server.nix index 105a05caf3048..c9d5a37116a13 100644 --- a/nixos/modules/services/backup/restic-rest-server.nix +++ b/nixos/modules/services/backup/restic-rest-server.nix @@ -12,7 +12,7 @@ in enable = mkEnableOption (lib.mdDoc "Restic REST Server"); listenAddress = mkOption { - default = ":8000"; + default = "8000"; example = "127.0.0.1:8080"; type = types.str; description = lib.mdDoc "Listen on a specific IP address and port."; @@ -61,14 +61,19 @@ in }; config = mkIf cfg.enable { + assertions = [{ + assertion = lib.substring 0 1 cfg.listenAddress != ":"; + message = "The restic-rest-server now uses systemd socket activation, which expects only the Port number: services.restic.server.listenAddress = \"${lib.substring 1 6 cfg.listenAddress}\";"; + }]; + systemd.services.restic-rest-server = { description = "Restic REST Server"; - after = [ "network.target" ]; + after = [ "network.target" "restic-rest-server.socket" ]; + requires = [ "restic-rest-server.socket" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = '' ${cfg.package}/bin/rest-server \ - --listen ${cfg.listenAddress} \ --path ${cfg.dataDir} \ ${optionalString cfg.appendOnly "--append-only"} \ ${optionalString cfg.privateRepos "--private-repos"} \ @@ -80,16 +85,40 @@ in Group = "restic"; # Security hardening - ReadWritePaths = [ cfg.dataDir ]; + CapabilityBoundingSet = ""; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateNetwork = true; PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectProc = "invisible"; ProtectSystem = "strict"; ProtectKernelTunables = true; ProtectKernelModules = true; ProtectControlGroups = true; PrivateDevices = true; + ReadWritePaths = [ cfg.dataDir ]; + RemoveIPC = true; + RestrictAddressFamilies = "none"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service"; + UMask = 027; }; }; + systemd.sockets.restic-rest-server = { + listenStreams = [ cfg.listenAddress ]; + wantedBy = [ "sockets.target" ]; + }; + systemd.tmpfiles.rules = mkIf cfg.privateRepos [ "f ${cfg.dataDir}/.htpasswd 0700 restic restic -" ]; diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix index 2ebe8ad2f69ae..f1f7433a39cdd 100644 --- a/nixos/modules/services/backup/znapzend.nix +++ b/nixos/modules/services/backup/znapzend.nix @@ -465,5 +465,5 @@ in }; }; - meta.maintainers = with maintainers; [ infinisil SlothOfAnarchy ]; + meta.maintainers = with maintainers; [ SlothOfAnarchy ]; } diff --git a/nixos/modules/services/databases/hbase-standalone.nix b/nixos/modules/services/databases/hbase-standalone.nix index 08ae7625d50ab..de295a57193f7 100644 --- a/nixos/modules/services/databases/hbase-standalone.nix +++ b/nixos/modules/services/databases/hbase-standalone.nix @@ -43,7 +43,7 @@ in { enable = mkEnableOption (lib.mdDoc '' HBase master in standalone mode with embedded regionserver and zookeper. - Do not use this configuration for production nor for evaluating HBase performance. + Do not use this configuration for production nor for evaluating HBase performance ''); package = mkPackageOption pkgs "hbase" { }; diff --git a/nixos/modules/services/databases/lldap.nix b/nixos/modules/services/databases/lldap.nix index 033de7af886f2..75ce1ca54f87b 100644 --- a/nixos/modules/services/databases/lldap.nix +++ b/nixos/modules/services/databases/lldap.nix @@ -6,7 +6,7 @@ let in { options.services.lldap = with lib; { - enable = mkEnableOption (mdDoc "lldap"); + enable = mkEnableOption (mdDoc "lldap, a lightweight authentication server that provides an opinionated, simplified LDAP interface for authentication"); package = mkPackageOption pkgs "lldap" { }; diff --git a/nixos/modules/services/databases/victoriametrics.nix b/nixos/modules/services/databases/victoriametrics.nix index 0ad2028c95b08..3d8ada394d20c 100644 --- a/nixos/modules/services/databases/victoriametrics.nix +++ b/nixos/modules/services/databases/victoriametrics.nix @@ -2,7 +2,7 @@ let cfg = config.services.victoriametrics; in { options.services.victoriametrics = with lib; { - enable = mkEnableOption (lib.mdDoc "victoriametrics"); + enable = mkEnableOption (lib.mdDoc "VictoriaMetrics, a time series database, long-term remote storage for Prometheus"); package = mkPackageOption pkgs "victoriametrics" { }; listenAddress = mkOption { default = ":8428"; diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix index 5f1f2cec79e8d..bc64397d5d882 100644 --- a/nixos/modules/services/desktop-managers/plasma6.nix +++ b/nixos/modules/services/desktop-managers/plasma6.nix @@ -170,7 +170,17 @@ in { breeze.qt5 plasma-integration.qt5 pkgs.plasma5Packages.kwayland-integration - pkgs.plasma5Packages.kio + ( + # Only symlink the KIO plugins, so we don't accidentally pull any services + # like KCMs or kcookiejar + let + kioPluginPath = "${pkgs.plasma5Packages.qtbase.qtPluginPrefix}/kf5/kio"; + inherit (pkgs.plasma5Packages) kio; + in pkgs.runCommand "kio5-plugins-only" {} '' + mkdir -p $out/${kioPluginPath} + ln -s ${kio}/${kioPluginPath}/* $out/${kioPluginPath} + '' + ) kio-extras-kf5 ] # Optional hardware support features @@ -246,11 +256,11 @@ in { xdg.portal.configPackages = mkDefault [kdePackages.xdg-desktop-portal-kde]; services.pipewire.enable = mkDefault true; - services.xserver.displayManager = { + services.displayManager = { sessionPackages = [kdePackages.plasma-workspace]; defaultSession = mkDefault "plasma"; }; - services.xserver.displayManager.sddm = { + services.displayManager.sddm = { package = kdePackages.sddm; theme = mkDefault "breeze"; wayland.compositor = "kwin"; diff --git a/nixos/modules/services/desktops/blueman.nix b/nixos/modules/services/desktops/blueman.nix index fad2f21bce5bd..f09dd91c9af51 100644 --- a/nixos/modules/services/desktops/blueman.nix +++ b/nixos/modules/services/desktops/blueman.nix @@ -9,7 +9,7 @@ in { ###### interface options = { services.blueman = { - enable = mkEnableOption (lib.mdDoc "blueman"); + enable = mkEnableOption (lib.mdDoc "blueman, a bluetooth manager"); }; }; diff --git a/nixos/modules/services/desktops/deepin/dde-api.nix b/nixos/modules/services/desktops/deepin/dde-api.nix index 459876febf21f..ece1599f5cc85 100644 --- a/nixos/modules/services/desktops/deepin/dde-api.nix +++ b/nixos/modules/services/desktops/deepin/dde-api.nix @@ -15,7 +15,7 @@ with lib; services.deepin.dde-api = { enable = mkEnableOption (lib.mdDoc '' - some dbus interfaces that is used for screen zone detecting, + the DDE API, which provides some dbus interfaces that is used for screen zone detecting, thumbnail generating, and sound playing in Deepin Desktop Environment ''); diff --git a/nixos/modules/services/desktops/neard.nix b/nixos/modules/services/desktops/neard.nix index 9130b8d3d216d..846297dfc1ad2 100644 --- a/nixos/modules/services/desktops/neard.nix +++ b/nixos/modules/services/desktops/neard.nix @@ -7,7 +7,7 @@ with lib; ###### interface options = { services.neard = { - enable = mkEnableOption (lib.mdDoc "neard, NFC daemon"); + enable = mkEnableOption (lib.mdDoc "neard, an NFC daemon"); }; }; diff --git a/nixos/modules/services/desktops/zeitgeist.nix b/nixos/modules/services/desktops/zeitgeist.nix index 0eb2a4c9c371b..caa2835316b03 100644 --- a/nixos/modules/services/desktops/zeitgeist.nix +++ b/nixos/modules/services/desktops/zeitgeist.nix @@ -14,7 +14,7 @@ with lib; options = { services.zeitgeist = { - enable = mkEnableOption (lib.mdDoc "zeitgeist"); + enable = mkEnableOption (lib.mdDoc "zeitgeist, a service which logs the users' activities and events"); }; }; diff --git a/nixos/modules/services/development/distccd.nix b/nixos/modules/services/development/distccd.nix index c33bf436bffb5..af59e1febd86b 100644 --- a/nixos/modules/services/development/distccd.nix +++ b/nixos/modules/services/development/distccd.nix @@ -8,7 +8,7 @@ in { options = { services.distccd = { - enable = mkEnableOption (lib.mdDoc "distccd"); + enable = mkEnableOption (lib.mdDoc "distccd, a distributed C/C++ compiler"); allowedClients = mkOption { type = types.listOf types.str; diff --git a/nixos/modules/services/development/gemstash.nix b/nixos/modules/services/development/gemstash.nix index eb7ccb98bde89..650c6680ee693 100644 --- a/nixos/modules/services/development/gemstash.nix +++ b/nixos/modules/services/development/gemstash.nix @@ -24,7 +24,7 @@ let in { options.services.gemstash = { - enable = mkEnableOption (lib.mdDoc "gemstash service"); + enable = mkEnableOption (lib.mdDoc "gemstash, a cache for rubygems.org and a private gem server"); openFirewall = mkOption { type = types.bool; diff --git a/nixos/modules/services/display-managers/default.nix b/nixos/modules/services/display-managers/default.nix new file mode 100644 index 0000000000000..7f5db9fbb509b --- /dev/null +++ b/nixos/modules/services/display-managers/default.nix @@ -0,0 +1,257 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.displayManager; + + installedSessions = pkgs.runCommand "desktops" + { # trivial derivation + preferLocalBuild = true; + allowSubstitutes = false; + } + '' + mkdir -p "$out/share/"{xsessions,wayland-sessions} + + ${lib.concatMapStrings (pkg: '' + for n in ${lib.concatStringsSep " " pkg.providedSessions}; do + if ! test -f ${pkg}/share/wayland-sessions/$n.desktop -o \ + -f ${pkg}/share/xsessions/$n.desktop; then + echo "Couldn't find provided session name, $n.desktop, in session package ${pkg.name}:" + echo " ${pkg}" + return 1 + fi + done + + if test -d ${pkg}/share/xsessions; then + ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${pkg}/share/xsessions $out/share/xsessions + fi + if test -d ${pkg}/share/wayland-sessions; then + ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${pkg}/share/wayland-sessions $out/share/wayland-sessions + fi + '') cfg.sessionPackages} + ''; + + dmDefault = config.services.xserver.desktopManager.default; + # fallback default for cases when only default wm is set + dmFallbackDefault = if dmDefault != null then dmDefault else "none"; + wmDefault = config.services.xserver.windowManager.default; + defaultSessionFromLegacyOptions = dmFallbackDefault + lib.optionalString (wmDefault != null && wmDefault != "none") "+${wmDefault}"; +in +{ + options = { + services.displayManager = { + enable = lib.mkEnableOption "systemd's display-manager service"; + + preStart = lib.mkOption { + type = lib.types.lines; + default = ""; + example = "rm -f /var/log/my-display-manager.log"; + description = lib.mdDoc "Script executed before the display manager is started."; + }; + + execCmd = lib.mkOption { + type = lib.types.str; + example = lib.literalExpression ''"''${pkgs.lightdm}/bin/lightdm"''; + description = lib.mdDoc "Command to start the display manager."; + }; + + environment = lib.mkOption { + type = with lib.types; attrsOf unspecified; + default = {}; + description = lib.mdDoc "Additional environment variables needed by the display manager."; + }; + + hiddenUsers = lib.mkOption { + type = with lib.types; listOf str; + default = [ "nobody" ]; + description = lib.mdDoc '' + A list of users which will not be shown in the display manager. + ''; + }; + + logToFile = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Whether the display manager redirects the output of the + session script to {file}`~/.xsession-errors`. + ''; + }; + + logToJournal = lib.mkOption { + type = lib.types.bool; + default = true; + description = lib.mdDoc '' + Whether the display manager redirects the output of the + session script to the systemd journal. + ''; + }; + + # Configuration for automatic login. Common for all DM. + autoLogin = lib.mkOption { + type = lib.types.submodule ({ config, options, ... }: { + options = { + enable = lib.mkOption { + type = lib.types.bool; + default = config.user != null; + defaultText = lib.literalExpression "config.${options.user} != null"; + description = lib.mdDoc '' + Automatically log in as {option}`autoLogin.user`. + ''; + }; + + user = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + description = lib.mdDoc '' + User to be used for the automatic login. + ''; + }; + }; + }); + + default = {}; + description = lib.mdDoc '' + Auto login configuration attrset. + ''; + }; + + defaultSession = lib.mkOption { + type = lib.types.nullOr lib.types.str // { + description = "session name"; + check = d: + lib.assertMsg (d != null -> (lib.types.str.check d && lib.elem d config.services.displayManager.sessionData.sessionNames)) '' + Default graphical session, '${d}', not found. + Valid names for 'services.displayManager.defaultSession' are: + ${lib.concatStringsSep "\n " cfg.displayManager.sessionData.sessionNames} + ''; + }; + default = + if dmDefault != null || wmDefault != null then + defaultSessionFromLegacyOptions + else + null; + defaultText = lib.literalMD '' + Taken from display manager settings or window manager settings, if either is set. + ''; + example = "gnome"; + description = lib.mdDoc '' + Graphical session to pre-select in the session chooser (only effective for GDM, LightDM and SDDM). + + On GDM, LightDM and SDDM, it will also be used as a session for auto-login. + ''; + }; + + sessionData = lib.mkOption { + description = lib.mdDoc "Data exported for display managers’ convenience"; + internal = true; + default = {}; + }; + + sessionPackages = lib.mkOption { + type = lib.types.listOf (lib.types.package // { + description = "package with provided sessions"; + check = p: lib.assertMsg + (lib.types.package.check p && p ? providedSessions + && p.providedSessions != [] && lib.all lib.isString p.providedSessions) + '' + Package, '${p.name}', did not specify any session names, as strings, in + 'passthru.providedSessions'. This is required when used as a session package. + + The session names can be looked up in: + ${p}/share/xsessions + ${p}/share/wayland-sessions + ''; + }); + default = []; + description = lib.mdDoc '' + A list of packages containing x11 or wayland session files to be passed to the display manager. + ''; + }; + }; + }; + + imports = [ + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "autoLogin" ] [ "services" "displayManager" "autoLogin" ]) + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "defaultSession" ] [ "services" "displayManager" "defaultSession" ]) + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "environment" ] [ "services" "displayManager" "environment" ]) + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "execCmd" ] [ "services" "displayManager" "execCmd" ]) + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logToFile" ] [ "services" "displayManager" "logToFile" ]) + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logToJournal" ] [ "services" "displayManager" "logToJournal" ]) + (lib.mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "preStart" ] [ "services" "displayManager" "preStart" ]) + ]; + + config = lib.mkIf cfg.enable { + assertions = [ + { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null; + message = '' + services.displayManager.autoLogin.enable requires services.displayManager.autoLogin.user to be set + ''; + } + ]; + + warnings = + lib.mkIf (dmDefault != null || wmDefault != null) [ + '' + The following options are deprecated: + ${lib.concatStringsSep "\n " (map ({c, t}: t) (lib.filter ({c, t}: c != null) [ + { c = dmDefault; t = "- services.xserver.desktopManager.default"; } + { c = wmDefault; t = "- services.xserver.windowManager.default"; } + ]))} + Please use + services.displayManager.defaultSession = "${defaultSessionFromLegacyOptions}"; + instead. + '' + ]; + + # Make xsessions and wayland sessions available in XDG_DATA_DIRS + # as some programs have behavior that depends on them being present + environment.sessionVariables.XDG_DATA_DIRS = lib.mkIf (cfg.sessionPackages != [ ]) [ + "${cfg.sessionData.desktops}/share" + ]; + + services.displayManager.sessionData = { + desktops = installedSessions; + sessionNames = lib.concatMap (p: p.providedSessions) config.services.displayManager.sessionPackages; + # We do not want to force users to set defaultSession when they have only single DE. + autologinSession = + if cfg.defaultSession != null then + cfg.defaultSession + else if cfg.sessionData.sessionNames != [] then + lib.head cfg.sessionData.sessionNames + else + null; + }; + + # so that the service won't be enabled when only startx is used + systemd.services.display-manager.enable = + let dmConf = config.services.xserver.displayManager; + noDmUsed = !(dmConf.gdm.enable + || cfg.sddm.enable + || dmConf.xpra.enable + || dmConf.lightdm.enable); + in lib.mkIf noDmUsed (lib.mkDefault false); + + systemd.services.display-manager = { + description = "Display Manager"; + after = [ "acpid.service" "systemd-logind.service" "systemd-user-sessions.service" ]; + restartIfChanged = false; + + environment = lib.optionalAttrs config.hardware.opengl.setLdLibraryPath { + LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.addOpenGLRunpath.driverLink ]; + } // cfg.environment; + + preStart = cfg.preStart; + script = lib.mkIf (config.systemd.services.display-manager.enable == true) cfg.execCmd; + + # Stop restarting if the display manager stops (crashes) 2 times + # in one minute. Starting X typically takes 3-4s. + startLimitIntervalSec = 30; + startLimitBurst = 3; + serviceConfig = { + Restart = "always"; + RestartSec = "200ms"; + SyslogIdentifier = "display-manager"; + }; + }; + }; +} diff --git a/nixos/modules/services/display-managers/greetd.nix b/nixos/modules/services/display-managers/greetd.nix index 5ce67c3fb3fd2..0f0205f9e0e48 100644 --- a/nixos/modules/services/display-managers/greetd.nix +++ b/nixos/modules/services/display-managers/greetd.nix @@ -8,7 +8,7 @@ let in { options.services.greetd = { - enable = mkEnableOption (lib.mdDoc "greetd"); + enable = mkEnableOption (lib.mdDoc "greetd, a minimal and flexible login manager daemon"); package = mkPackageOption pkgs [ "greetd" "greetd" ] { }; diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/display-managers/sddm.nix index a315a3ebf3224..16efec04e6194 100644 --- a/nixos/modules/services/x11/display-managers/sddm.nix +++ b/nixos/modules/services/display-managers/sddm.nix @@ -2,8 +2,8 @@ let xcfg = config.services.xserver; - dmcfg = xcfg.displayManager; - cfg = dmcfg.sddm; + dmcfg = config.services.displayManager; + cfg = config.services.displayManager.sddm; xEnv = config.systemd.services.display-manager.environment; sddm = cfg.package.override (old: { @@ -21,12 +21,12 @@ let xserverWrapper = pkgs.writeShellScript "xserver-wrapper" '' ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} - exec systemd-cat -t xserver-wrapper ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} "$@" + exec systemd-cat -t xserver-wrapper ${xcfg.displayManager.xserverBin} ${toString xcfg.displayManager.xserverArgs} "$@" ''; Xsetup = pkgs.writeShellScript "Xsetup" '' ${cfg.setupScript} - ${dmcfg.setupCommands} + ${xcfg.displayManager.setupCommands} ''; Xstop = pkgs.writeShellScript "Xstop" '' @@ -40,7 +40,7 @@ let Numlock = if cfg.autoNumlock then "on" else "none"; # on, off none # Implementation is done via pkgs/applications/display-managers/sddm/sddm-default-session.patch - DefaultSession = optionalString (dmcfg.defaultSession != null) "${dmcfg.defaultSession}.desktop"; + DefaultSession = optionalString (config.services.displayManager.defaultSession != null) "${config.services.displayManager.defaultSession}.desktop"; DisplayServer = if cfg.wayland.enable then "wayland" else "x11"; } // optionalAttrs (cfg.wayland.compositor == "kwin") { @@ -66,7 +66,7 @@ let HideShells = "/run/current-system/sw/bin/nologin"; }; - X11 = { + X11 = optionalAttrs xcfg.enable { MinimumVT = if xcfg.tty != null then xcfg.tty else 7; ServerPath = toString xserverWrapper; XephyrPath = "${pkgs.xorg.xorgserver.out}/bin/Xephyr"; @@ -128,23 +128,36 @@ let in { imports = [ + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "autoLogin" "minimumUid" ] [ "services" "displayManager" "sddm" "autoLogin" "minimumUid" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "autoLogin" "relogin" ] [ "services" "displayManager" "sddm" "autoLogin" "relogin" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "autoNumlock" ] [ "services" "displayManager" "sddm" "autoNumlock" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "enable" ] [ "services" "displayManager" "sddm" "enable" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "enableHidpi" ] [ "services" "displayManager" "sddm" "enableHidpi" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "extraPackages" ] [ "services" "displayManager" "sddm" "extraPackages" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "package" ] [ "services" "displayManager" "sddm" "package" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "settings" ] [ "services" "displayManager" "sddm" "settings" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "setupScript" ] [ "services" "displayManager" "sddm" "setupScript" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "stopScript" ] [ "services" "displayManager" "sddm" "stopScript" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "theme" ] [ "services" "displayManager" "sddm" "theme" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "wayland" "enable" ] [ "services" "displayManager" "sddm" "wayland" "enable" ]) + (mkRemovedOptionModule - [ "services" "xserver" "displayManager" "sddm" "themes" ] - "Set the option `services.xserver.displayManager.sddm.package' instead.") + [ "services" "displayManager" "sddm" "themes" ] + "Set the option `services.displayManager.sddm.package' instead.") (mkRenamedOptionModule - [ "services" "xserver" "displayManager" "sddm" "autoLogin" "enable" ] - [ "services" "xserver" "displayManager" "autoLogin" "enable" ]) + [ "services" "displayManager" "sddm" "autoLogin" "enable" ] + [ "services" "displayManager" "autoLogin" "enable" ]) (mkRenamedOptionModule - [ "services" "xserver" "displayManager" "sddm" "autoLogin" "user" ] - [ "services" "xserver" "displayManager" "autoLogin" "user" ]) + [ "services" "displayManager" "sddm" "autoLogin" "user" ] + [ "services" "displayManager" "autoLogin" "user" ]) (mkRemovedOptionModule - [ "services" "xserver" "displayManager" "sddm" "extraConfig" ] - "Set the option `services.xserver.displayManager.sddm.settings' instead.") + [ "services" "displayManager" "sddm" "extraConfig" ] + "Set the option `services.displayManager.sddm.settings' instead.") ]; options = { - services.xserver.displayManager.sddm = { + services.displayManager.sddm = { enable = mkOption { type = types.bool; default = false; @@ -268,19 +281,24 @@ in assertions = [ { - assertion = xcfg.enable; + assertion = xcfg.enable || cfg.wayland.enable; message = '' - SDDM requires services.xserver.enable to be true + SDDM requires either services.xserver.enable or services.displayManager.sddm.wayland.enable to be true ''; } { - assertion = dmcfg.autoLogin.enable -> autoLoginSessionName != null; + assertion = config.services.displayManager.autoLogin.enable -> autoLoginSessionName != null; message = '' - SDDM auto-login requires that services.xserver.displayManager.defaultSession is set. + SDDM auto-login requires that services.displayManager.defaultSession is set. ''; } ]; + services.displayManager = { + enable = true; + execCmd = "exec /run/current-system/sw/bin/sddm"; + }; + security.pam.services = { sddm.text = '' auth substack login @@ -338,7 +356,6 @@ in services = { dbus.packages = [ sddm ]; xserver = { - displayManager.job.execCmd = "exec /run/current-system/sw/bin/sddm"; # To enable user switching, allow sddm to allocate TTYs/displays dynamically. tty = null; display = null; diff --git a/nixos/modules/services/finance/odoo.nix b/nixos/modules/services/finance/odoo.nix index aa9bd0014d985..3a3b3c2fa6eec 100644 --- a/nixos/modules/services/finance/odoo.nix +++ b/nixos/modules/services/finance/odoo.nix @@ -9,7 +9,7 @@ in { options = { services.odoo = { - enable = mkEnableOption (lib.mdDoc "odoo"); + enable = mkEnableOption (lib.mdDoc "odoo, an open source ERP and CRM system"); package = mkPackageOption pkgs "odoo" { }; diff --git a/nixos/modules/services/games/mchprs.nix b/nixos/modules/services/games/mchprs.nix index 71e546049c58b..36f7ea71d6351 100644 --- a/nixos/modules/services/games/mchprs.nix +++ b/nixos/modules/services/games/mchprs.nix @@ -22,7 +22,7 @@ in { options = { services.mchprs = { - enable = mkEnableOption "MCHPRS"; + enable = mkEnableOption "MCHPRS, a Minecraft server"; declarativeSettings = mkOption { type = types.bool; diff --git a/nixos/modules/services/games/openarena.nix b/nixos/modules/services/games/openarena.nix index 14e485b06a0df..592cec9a552f2 100644 --- a/nixos/modules/services/games/openarena.nix +++ b/nixos/modules/services/games/openarena.nix @@ -7,7 +7,7 @@ in { options = { services.openarena = { - enable = mkEnableOption (lib.mdDoc "OpenArena"); + enable = mkEnableOption (lib.mdDoc "OpenArena game server"); package = lib.mkPackageOption pkgs "openarena" { }; openPorts = mkOption { diff --git a/nixos/modules/services/hardware/kanata.nix b/nixos/modules/services/hardware/kanata.nix index 05e76d8432154..fa589f685a028 100644 --- a/nixos/modules/services/hardware/kanata.nix +++ b/nixos/modules/services/hardware/kanata.nix @@ -151,7 +151,7 @@ let in { options.services.kanata = { - enable = mkEnableOption (mdDoc "kanata"); + enable = mkEnableOption (mdDoc "kanata, a tool to improve keyboard comfort and usability with advanced customization"); package = mkPackageOption pkgs "kanata" { example = "kanata-with-cmd"; extraDescription = '' diff --git a/nixos/modules/services/hardware/lirc.nix b/nixos/modules/services/hardware/lirc.nix index 5b1a8d10c7299..c182c3895fb87 100644 --- a/nixos/modules/services/hardware/lirc.nix +++ b/nixos/modules/services/hardware/lirc.nix @@ -11,7 +11,7 @@ in { options = { services.lirc = { - enable = mkEnableOption (lib.mdDoc "LIRC daemon"); + enable = mkEnableOption (lib.mdDoc "the LIRC daemon, to receive and send infrared signals"); options = mkOption { type = types.lines; diff --git a/nixos/modules/services/hardware/openrgb.nix b/nixos/modules/services/hardware/openrgb.nix index 81b199e50778e..b400f77049f75 100644 --- a/nixos/modules/services/hardware/openrgb.nix +++ b/nixos/modules/services/hardware/openrgb.nix @@ -6,7 +6,7 @@ let cfg = config.services.hardware.openrgb; in { options.services.hardware.openrgb = { - enable = mkEnableOption (lib.mdDoc "OpenRGB server"); + enable = mkEnableOption (lib.mdDoc "OpenRGB server, for RGB lighting control"); package = mkPackageOption pkgs "openrgb" { }; diff --git a/nixos/modules/services/hardware/pcscd.nix b/nixos/modules/services/hardware/pcscd.nix index 77c2d9b53f03d..34df1f3e91ba3 100644 --- a/nixos/modules/services/hardware/pcscd.nix +++ b/nixos/modules/services/hardware/pcscd.nix @@ -18,7 +18,7 @@ let in { options.services.pcscd = { - enable = mkEnableOption (lib.mdDoc "PCSC-Lite daemon"); + enable = mkEnableOption (lib.mdDoc "PCSC-Lite daemon, to access smart cards using SCard API (PC/SC)"); plugins = mkOption { type = types.listOf types.package; diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 670b9087f1107..2bf86a535fc10 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -200,7 +200,7 @@ in }; services.udev = { - enable = mkEnableOption (lib.mdDoc "udev") // { + enable = mkEnableOption (lib.mdDoc "udev, a device manager for the Linux kernel") // { default = true; }; diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix index c4d4c6791a21b..ea4d60eac7c2c 100644 --- a/nixos/modules/services/hardware/undervolt.nix +++ b/nixos/modules/services/hardware/undervolt.nix @@ -37,7 +37,7 @@ in enable = mkEnableOption (lib.mdDoc '' Undervolting service for Intel CPUs. - Warning: This service is not endorsed by Intel and may permanently damage your hardware. Use at your own risk! + Warning: This service is not endorsed by Intel and may permanently damage your hardware. Use at your own risk ''); verbose = mkOption { diff --git a/nixos/modules/services/hardware/vdr.nix b/nixos/modules/services/hardware/vdr.nix index 689d83f7eedcd..0c9cc0abf798d 100644 --- a/nixos/modules/services/hardware/vdr.nix +++ b/nixos/modules/services/hardware/vdr.nix @@ -9,7 +9,7 @@ in options = { services.vdr = { - enable = mkEnableOption (mdDoc "Start VDR"); + enable = mkEnableOption (mdDoc "VDR, a video disk recorder"); package = mkPackageOption pkgs "vdr" { example = "wrapVdr.override { plugins = with pkgs.vdrPlugins; [ hello ]; }"; diff --git a/nixos/modules/services/home-automation/ebusd.nix b/nixos/modules/services/home-automation/ebusd.nix index f68a8bdb6bfa2..e1dcfb338421f 100644 --- a/nixos/modules/services/home-automation/ebusd.nix +++ b/nixos/modules/services/home-automation/ebusd.nix @@ -44,7 +44,7 @@ in meta.maintainers = with maintainers; [ nathan-gs ]; options.services.ebusd = { - enable = mkEnableOption (lib.mdDoc "ebusd service"); + enable = mkEnableOption (lib.mdDoc "ebusd, a daemon for communication with eBUS heating systems"); device = mkOption { type = types.str; diff --git a/nixos/modules/services/home-automation/esphome.nix b/nixos/modules/services/home-automation/esphome.nix index 3c0fd8aed08a4..ac623cf36b3a9 100644 --- a/nixos/modules/services/home-automation/esphome.nix +++ b/nixos/modules/services/home-automation/esphome.nix @@ -24,7 +24,7 @@ in meta.maintainers = with maintainers; [ oddlama ]; options.services.esphome = { - enable = mkEnableOption (mdDoc "esphome"); + enable = mkEnableOption (mdDoc "esphome, for making custom firmwares for ESP32/ESP8266"); package = lib.mkPackageOption pkgs "esphome" { }; diff --git a/nixos/modules/services/logging/awstats.nix b/nixos/modules/services/logging/awstats.nix index 708775bfcf03a..642118650c65e 100644 --- a/nixos/modules/services/logging/awstats.nix +++ b/nixos/modules/services/logging/awstats.nix @@ -95,7 +95,7 @@ in ]; options.services.awstats = { - enable = mkEnableOption (lib.mdDoc "awstats"); + enable = mkEnableOption (lib.mdDoc "awstats, a real-time logfile analyzer"); dataDir = mkOption { type = types.path; diff --git a/nixos/modules/services/logging/fluentd.nix b/nixos/modules/services/logging/fluentd.nix index c8718f26db383..cfc584309835c 100644 --- a/nixos/modules/services/logging/fluentd.nix +++ b/nixos/modules/services/logging/fluentd.nix @@ -12,7 +12,7 @@ in { options = { services.fluentd = { - enable = mkEnableOption (lib.mdDoc "fluentd"); + enable = mkEnableOption (lib.mdDoc "fluentd, a data/log collector"); config = mkOption { type = types.lines; diff --git a/nixos/modules/services/logging/graylog.nix b/nixos/modules/services/logging/graylog.nix index 673930c4cb5c6..853539d4d63bf 100644 --- a/nixos/modules/services/logging/graylog.nix +++ b/nixos/modules/services/logging/graylog.nix @@ -33,7 +33,7 @@ in services.graylog = { - enable = mkEnableOption (lib.mdDoc "Graylog"); + enable = mkEnableOption (lib.mdDoc "Graylog, a log management solution"); package = mkOption { type = types.package; diff --git a/nixos/modules/services/logging/heartbeat.nix b/nixos/modules/services/logging/heartbeat.nix index 768ffe5315fe0..84c15b1caeb28 100644 --- a/nixos/modules/services/logging/heartbeat.nix +++ b/nixos/modules/services/logging/heartbeat.nix @@ -18,7 +18,7 @@ in services.heartbeat = { - enable = mkEnableOption (lib.mdDoc "heartbeat"); + enable = mkEnableOption (lib.mdDoc "heartbeat, uptime monitoring"); package = mkPackageOption pkgs "heartbeat" { example = "heartbeat7"; diff --git a/nixos/modules/services/logging/logcheck.nix b/nixos/modules/services/logging/logcheck.nix index 5d87fc87d4161..44763afa9d238 100644 --- a/nixos/modules/services/logging/logcheck.nix +++ b/nixos/modules/services/logging/logcheck.nix @@ -109,7 +109,7 @@ in { options = { services.logcheck = { - enable = mkEnableOption (lib.mdDoc "logcheck cron job"); + enable = mkEnableOption (lib.mdDoc "logcheck cron job, to mail anomalies in the system logfiles to the administrator"); user = mkOption { default = "logcheck"; diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix index ba1445f083975..49cca0cb8112a 100644 --- a/nixos/modules/services/logging/logrotate.nix +++ b/nixos/modules/services/logging/logrotate.nix @@ -104,9 +104,12 @@ in default = { }; description = lib.mdDoc '' logrotate freeform settings: each attribute here will define its own section, - ordered by priority, which can either define files to rotate with their settings + ordered by {option}`services.logrotate.settings.<name>.priority`, + which can either define files to rotate with their settings or settings common to all further files settings. - Refer to <https://linux.die.net/man/8/logrotate> for details. + All attribute names not explicitly defined as sub-options here are passed through + as logrotate config directives, + refer to <https://linux.die.net/man/8/logrotate> for details. ''; example = literalExpression '' { @@ -125,6 +128,14 @@ in "/var/log/second.log" ]; }; + # specify custom order of sections + "/var/log/myservice/*.log" = { + # ensure lower priority + priority = 110; + postrotate = ''' + systemctl reload myservice + '''; + }; }; ''; type = types.attrsOf (types.submodule ({ name, ... }: { diff --git a/nixos/modules/services/logging/ulogd.nix b/nixos/modules/services/logging/ulogd.nix index 05c9797bb28bc..9beb0859cef52 100644 --- a/nixos/modules/services/logging/ulogd.nix +++ b/nixos/modules/services/logging/ulogd.nix @@ -8,7 +8,7 @@ let in { options = { services.ulogd = { - enable = mkEnableOption (lib.mdDoc "ulogd"); + enable = mkEnableOption (lib.mdDoc "ulogd, a userspace logging daemon for netfilter/iptables related logging"); settings = mkOption { example = { diff --git a/nixos/modules/services/logging/vector.nix b/nixos/modules/services/logging/vector.nix index 9ccf8a4fa0610..92605c4030873 100644 --- a/nixos/modules/services/logging/vector.nix +++ b/nixos/modules/services/logging/vector.nix @@ -6,7 +6,7 @@ let cfg = config.services.vector; in { options.services.vector = { - enable = mkEnableOption (lib.mdDoc "Vector"); + enable = mkEnableOption (lib.mdDoc "Vector, a high-performance observability data pipeline"); package = mkPackageOption pkgs "vector" { }; diff --git a/nixos/modules/services/mail/goeland.nix b/nixos/modules/services/mail/goeland.nix index 13092a65ed90e..a39d0d27d537b 100644 --- a/nixos/modules/services/mail/goeland.nix +++ b/nixos/modules/services/mail/goeland.nix @@ -8,7 +8,7 @@ let in { options.services.goeland = { - enable = mkEnableOption (mdDoc "goeland"); + enable = mkEnableOption (mdDoc "goeland, an alternative to rss2email"); settings = mkOption { description = mdDoc '' diff --git a/nixos/modules/services/mail/mailcatcher.nix b/nixos/modules/services/mail/mailcatcher.nix index d0f4550c19264..60abf3f2c5a02 100644 --- a/nixos/modules/services/mail/mailcatcher.nix +++ b/nixos/modules/services/mail/mailcatcher.nix @@ -11,7 +11,7 @@ in options = { services.mailcatcher = { - enable = mkEnableOption (lib.mdDoc "MailCatcher"); + enable = mkEnableOption (lib.mdDoc "MailCatcher, an SMTP server and web interface to locally test outbound emails"); http.ip = mkOption { type = types.str; diff --git a/nixos/modules/services/mail/mailhog.nix b/nixos/modules/services/mail/mailhog.nix index 7ae62de291bab..14df891fbb1a4 100644 --- a/nixos/modules/services/mail/mailhog.nix +++ b/nixos/modules/services/mail/mailhog.nix @@ -27,7 +27,7 @@ in options = { services.mailhog = { - enable = mkEnableOption (lib.mdDoc "MailHog"); + enable = mkEnableOption (lib.mdDoc "MailHog, web and API based SMTP testing"); storage = mkOption { type = types.enum [ "maildir" "memory" ]; diff --git a/nixos/modules/services/matrix/mautrix-meta.nix b/nixos/modules/services/matrix/mautrix-meta.nix new file mode 100644 index 0000000000000..f0905c3af1297 --- /dev/null +++ b/nixos/modules/services/matrix/mautrix-meta.nix @@ -0,0 +1,562 @@ +{ config, pkgs, lib, ... }: + +let + settingsFormat = pkgs.formats.yaml {}; + + upperConfig = config; + cfg = config.services.mautrix-meta; + upperCfg = cfg; + + fullDataDir = cfg: "/var/lib/${cfg.dataDir}"; + + settingsFile = cfg: "${fullDataDir cfg}/config.yaml"; + settingsFileUnsubstituted = cfg: settingsFormat.generate "mautrix-meta-config.yaml" cfg.settings; + + metaName = name: "mautrix-meta-${name}"; + + enabledInstances = lib.filterAttrs (name: config: config.enable) config.services.mautrix-meta.instances; + registerToSynapseInstances = lib.filterAttrs (name: config: config.enable && config.registerToSynapse) config.services.mautrix-meta.instances; +in { + options = { + services.mautrix-meta = { + + package = lib.mkPackageOption pkgs "mautrix-meta" { }; + + instances = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ({ config, name, ... }: { + + options = { + + enable = lib.mkEnableOption "Mautrix-Meta, a Matrix <-> Facebook and Matrix <-> Instagram hybrid puppeting/relaybot bridge"; + + dataDir = lib.mkOption { + type = lib.types.str; + default = metaName name; + description = '' + Path to the directory with database, registration, and other data for the bridge service. + This path is relative to `/var/lib`, it cannot start with `../` (it cannot be outside of `/var/lib`). + ''; + }; + + registrationFile = lib.mkOption { + type = lib.types.path; + readOnly = true; + description = '' + Path to the yaml registration file of the appservice. + ''; + }; + + registerToSynapse = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Whether to add registration file to `services.matrix-synapse.settings.app_service_config_files` and + make Synapse wait for registration service. + ''; + }; + + settings = lib.mkOption rec { + apply = lib.recursiveUpdate default; + inherit (settingsFormat) type; + default = { + homeserver = { + software = "standard"; + + domain = ""; + address = ""; + }; + + appservice = { + id = ""; + + database = { + type = "sqlite3-fk-wal"; + uri = "file:${fullDataDir config}/mautrix-meta.db?_txlock=immediate"; + }; + + bot = { + username = ""; + }; + + hostname = "localhost"; + port = 29319; + address = "http://${config.settings.appservice.hostname}:${toString config.settings.appservice.port}"; + }; + + meta = { + mode = ""; + }; + + bridge = { + # Enable encryption by default to make the bridge more secure + encryption = { + allow = true; + default = true; + require = true; + + # Recommended options from mautrix documentation + # for additional security. + delete_keys = { + dont_store_outbound = true; + ratchet_on_decrypt = true; + delete_fully_used_on_decrypt = true; + delete_prev_on_new_session = true; + delete_on_device_delete = true; + periodically_delete_expired = true; + delete_outdated_inbound = true; + }; + + verification_levels = { + receive = "cross-signed-tofu"; + send = "cross-signed-tofu"; + share = "cross-signed-tofu"; + }; + }; + + permissions = {}; + }; + + logging = { + min_level = "info"; + writers = lib.singleton { + type = "stdout"; + format = "pretty-colored"; + time_format = " "; + }; + }; + }; + defaultText = '' + { + homeserver = { + software = "standard"; + address = "https://''${config.settings.homeserver.domain}"; + }; + + appservice = { + database = { + type = "sqlite3-fk-wal"; + uri = "file:''${fullDataDir config}/mautrix-meta.db?_txlock=immediate"; + }; + + hostname = "localhost"; + port = 29319; + address = "http://''${config.settings.appservice.hostname}:''${toString config.settings.appservice.port}"; + }; + + bridge = { + # Require encryption by default to make the bridge more secure + encryption = { + allow = true; + default = true; + require = true; + + # Recommended options from mautrix documentation + # for optimal security. + delete_keys = { + dont_store_outbound = true; + ratchet_on_decrypt = true; + delete_fully_used_on_decrypt = true; + delete_prev_on_new_session = true; + delete_on_device_delete = true; + periodically_delete_expired = true; + delete_outdated_inbound = true; + }; + + verification_levels = { + receive = "cross-signed-tofu"; + send = "cross-signed-tofu"; + share = "cross-signed-tofu"; + }; + }; + }; + + logging = { + min_level = "info"; + writers = lib.singleton { + type = "stdout"; + format = "pretty-colored"; + time_format = " "; + }; + }; + }; + ''; + description = '' + {file}`config.yaml` configuration as a Nix attribute set. + Configuration options should match those described in + [example-config.yaml](https://github.com/mautrix/meta/blob/main/example-config.yaml). + + Secret tokens should be specified using {option}`environmentFile` + instead + ''; + }; + + environmentFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + description = '' + File containing environment variables to substitute when copying the configuration + out of Nix store to the `services.mautrix-meta.dataDir`. + + Can be used for storing the secrets without making them available in the Nix store. + + For example, you can set `services.mautrix-meta.settings.appservice.as_token = "$MAUTRIX_META_APPSERVICE_AS_TOKEN"` + and then specify `MAUTRIX_META_APPSERVICE_AS_TOKEN="{token}"` in the environment file. + This value will get substituted into the configuration file as as token. + ''; + }; + + serviceDependencies = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = + [ config.registrationServiceUnit ] ++ + (lib.lists.optional upperConfig.services.matrix-synapse.enable upperConfig.services.matrix-synapse.serviceUnit) ++ + (lib.lists.optional upperConfig.services.matrix-conduit.enable "matrix-conduit.service") ++ + (lib.lists.optional upperConfig.services.dendrite.enable "dendrite.service"); + + defaultText = '' + [ config.registrationServiceUnit ] ++ + (lib.lists.optional upperConfig.services.matrix-synapse.enable upperConfig.services.matrix-synapse.serviceUnit) ++ + (lib.lists.optional upperConfig.services.matrix-conduit.enable "matrix-conduit.service") ++ + (lib.lists.optional upperConfig.services.dendrite.enable "dendrite.service"); + ''; + description = '' + List of Systemd services to require and wait for when starting the application service. + ''; + }; + + serviceUnit = lib.mkOption { + type = lib.types.str; + readOnly = true; + description = '' + The systemd unit (a service or a target) for other services to depend on if they + need to be started after matrix-synapse. + + This option is useful as the actual parent unit for all matrix-synapse processes + changes when configuring workers. + ''; + }; + + registrationServiceUnit = lib.mkOption { + type = lib.types.str; + readOnly = true; + description = '' + The registration service that generates the registration file. + + Systemd unit (a service or a target) for other services to depend on if they + need to be started after mautrix-meta registration service. + + This option is useful as the actual parent unit for all matrix-synapse processes + changes when configuring workers. + ''; + }; + }; + + config = { + serviceUnit = (metaName name) + ".service"; + registrationServiceUnit = (metaName name) + "-registration.service"; + registrationFile = (fullDataDir config) + "/meta-registration.yaml"; + }; + })); + + description = '' + Configuration of multiple `mautrix-meta` instances. + `services.mautrix-meta.instances.facebook` and `services.mautrix-meta.instances.instagram` + come preconfigured with meta.mode, appservice.id, bot username, display name and avatar. + ''; + + example = '' + { + facebook = { + enable = true; + settings = { + homeserver.domain = "example.com"; + }; + }; + + instagram = { + enable = true; + settings = { + homeserver.domain = "example.com"; + }; + }; + + messenger = { + enable = true; + settings = { + meta.mode = "messenger"; + homeserver.domain = "example.com"; + appservice = { + id = "messenger"; + bot = { + username = "messengerbot"; + displayname = "Messenger bridge bot"; + avatar = "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak"; + }; + }; + }; + }; + } + ''; + }; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf (enabledInstances != {}) { + assertions = lib.mkMerge (lib.attrValues (lib.mapAttrs (name: cfg: [ + { + assertion = cfg.settings.homeserver.domain != "" && cfg.settings.homeserver.address != ""; + message = '' + The options with information about the homeserver: + `services.mautrix-meta.instances.${name}.settings.homeserver.domain` and + `services.mautrix-meta.instances.${name}.settings.homeserver.address` have to be set. + ''; + } + { + assertion = builtins.elem cfg.settings.meta.mode [ "facebook" "facebook-tor" "messenger" "instagram" ]; + message = '' + The option `services.mautrix-meta.instances.${name}.settings.meta.mode` has to be set + to one of: facebook, facebook-tor, messenger, instagram. + This configures the mode of the bridge. + ''; + } + { + assertion = cfg.settings.bridge.permissions != {}; + message = '' + The option `services.mautrix-meta.instances.${name}.settings.bridge.permissions` has to be set. + ''; + } + { + assertion = cfg.settings.appservice.id != ""; + message = '' + The option `services.mautrix-meta.instances.${name}.settings.appservice.id` has to be set. + ''; + } + { + assertion = cfg.settings.appservice.bot.username != ""; + message = '' + The option `services.mautrix-meta.instances.${name}.settings.appservice.bot.username` has to be set. + ''; + } + ]) enabledInstances)); + + users.users = lib.mapAttrs' (name: cfg: lib.nameValuePair "mautrix-meta-${name}" { + isSystemUser = true; + group = "mautrix-meta"; + extraGroups = [ "mautrix-meta-registration" ]; + description = "Mautrix-Meta-${name} bridge user"; + }) enabledInstances; + + users.groups.mautrix-meta = {}; + users.groups.mautrix-meta-registration = { + members = lib.lists.optional config.services.matrix-synapse.enable "matrix-synapse"; + }; + + services.matrix-synapse = lib.mkIf (config.services.matrix-synapse.enable) (let + registrationFiles = lib.attrValues + (lib.mapAttrs (name: cfg: cfg.registrationFile) registerToSynapseInstances); + in { + settings.app_service_config_files = registrationFiles; + }); + + systemd.services = lib.mkMerge [ + { + matrix-synapse = lib.mkIf (config.services.matrix-synapse.enable) (let + registrationServices = lib.attrValues + (lib.mapAttrs (name: cfg: cfg.registrationServiceUnit) registerToSynapseInstances); + in { + wants = registrationServices; + after = registrationServices; + }); + } + + (lib.mapAttrs' (name: cfg: lib.nameValuePair "${metaName name}-registration" { + description = "Mautrix-Meta registration generation service - ${metaName name}"; + + path = [ + pkgs.yq + pkgs.envsubst + upperCfg.package + ]; + + script = '' + # substitute the settings file by environment variables + # in this case read from EnvironmentFile + rm -f '${settingsFile cfg}' + old_umask=$(umask) + umask 0177 + envsubst \ + -o '${settingsFile cfg}' \ + -i '${settingsFileUnsubstituted cfg}' + + config_has_tokens=$(yq '.appservice | has("as_token") and has("hs_token")' '${settingsFile cfg}') + registration_already_exists=$([[ -f '${cfg.registrationFile}' ]] && echo "true" || echo "false") + + echo "There are tokens in the config: $config_has_tokens" + echo "Registration already existed: $registration_already_exists" + + # tokens not configured from config/environment file, and registration file + # is already generated, override tokens in config to make sure they are not lost + if [[ $config_has_tokens == "false" && $registration_already_exists == "true" ]]; then + echo "Copying as_token, hs_token from registration into configuration" + yq -sY '.[0].appservice.as_token = .[1].as_token + | .[0].appservice.hs_token = .[1].hs_token + | .[0]' '${settingsFile cfg}' '${cfg.registrationFile}' \ + > '${settingsFile cfg}.tmp' + mv '${settingsFile cfg}.tmp' '${settingsFile cfg}' + fi + + # make sure --generate-registration does not affect config.yaml + cp '${settingsFile cfg}' '${settingsFile cfg}.tmp' + + echo "Generating registration file" + mautrix-meta \ + --generate-registration \ + --config='${settingsFile cfg}.tmp' \ + --registration='${cfg.registrationFile}' + + rm '${settingsFile cfg}.tmp' + + # no tokens configured, and new were just generated by generate registration for first time + if [[ $config_has_tokens == "false" && $registration_already_exists == "false" ]]; then + echo "Copying newly generated as_token, hs_token from registration into configuration" + yq -sY '.[0].appservice.as_token = .[1].as_token + | .[0].appservice.hs_token = .[1].hs_token + | .[0]' '${settingsFile cfg}' '${cfg.registrationFile}' \ + > '${settingsFile cfg}.tmp' + mv '${settingsFile cfg}.tmp' '${settingsFile cfg}' + fi + + # Make sure correct tokens are in the registration file + if [[ $config_has_tokens == "true" || $registration_already_exists == "true" ]]; then + echo "Copying as_token, hs_token from configuration to the registration file" + yq -sY '.[1].as_token = .[0].appservice.as_token + | .[1].hs_token = .[0].appservice.hs_token + | .[1]' '${settingsFile cfg}' '${cfg.registrationFile}' \ + > '${cfg.registrationFile}.tmp' + mv '${cfg.registrationFile}.tmp' '${cfg.registrationFile}' + fi + + umask $old_umask + + chown :mautrix-meta-registration '${cfg.registrationFile}' + chmod 640 '${cfg.registrationFile}' + ''; + + serviceConfig = { + Type = "oneshot"; + UMask = 0027; + + User = "mautrix-meta-${name}"; + Group = "mautrix-meta"; + + SystemCallFilter = [ "@system-service" ]; + + ProtectSystem = "strict"; + ProtectHome = true; + + ReadWritePaths = fullDataDir cfg; + StateDirectory = cfg.dataDir; + EnvironmentFile = cfg.environmentFile; + }; + + restartTriggers = [ (settingsFileUnsubstituted cfg) ]; + }) enabledInstances) + + (lib.mapAttrs' (name: cfg: lib.nameValuePair "${metaName name}" { + description = "Mautrix-Meta bridge - ${metaName name}"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ] ++ cfg.serviceDependencies; + after = [ "network-online.target" ] ++ cfg.serviceDependencies; + + serviceConfig = { + Type = "simple"; + + User = "mautrix-meta-${name}"; + Group = "mautrix-meta"; + PrivateUsers = true; + + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + Restart = "on-failure"; + RestartSec = "30s"; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = ["@system-service"]; + UMask = 0027; + + WorkingDirectory = fullDataDir cfg; + ReadWritePaths = fullDataDir cfg; + StateDirectory = cfg.dataDir; + EnvironmentFile = cfg.environmentFile; + + ExecStart = lib.escapeShellArgs [ + (lib.getExe upperCfg.package) + "--config=${settingsFile cfg}" + ]; + }; + restartTriggers = [ (settingsFileUnsubstituted cfg) ]; + }) enabledInstances) + ]; + }) + { + services.mautrix-meta.instances = let + inherit (lib.modules) mkDefault; + in { + instagram = { + settings = { + meta.mode = mkDefault "instagram"; + + bridge = { + username_template = mkDefault "instagram_{{.}}"; + }; + + appservice = { + id = mkDefault "instagram"; + port = mkDefault 29320; + bot = { + username = mkDefault "instagrambot"; + displayname = mkDefault "Instagram bridge bot"; + avatar = mkDefault "mxc://maunium.net/JxjlbZUlCPULEeHZSwleUXQv"; + }; + }; + }; + }; + facebook = { + settings = { + meta.mode = mkDefault "facebook"; + + bridge = { + username_template = mkDefault "facebook_{{.}}"; + }; + + appservice = { + id = mkDefault "facebook"; + port = mkDefault 29321; + bot = { + username = mkDefault "facebookbot"; + displayname = mkDefault "Facebook bridge bot"; + avatar = mkDefault "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak"; + }; + }; + }; + }; + }; + } + ]; + + meta.maintainers = with lib.maintainers; [ rutherther ]; +} diff --git a/nixos/modules/services/matrix/synapse.nix b/nixos/modules/services/matrix/synapse.nix index 7291c0fcbcdda..e6b8462642dda 100644 --- a/nixos/modules/services/matrix/synapse.nix +++ b/nixos/modules/services/matrix/synapse.nix @@ -367,7 +367,7 @@ in { }); in { services.matrix-synapse = { - enable = mkEnableOption (lib.mdDoc "matrix.org synapse"); + enable = mkEnableOption (lib.mdDoc "matrix.org synapse, the reference homeserver"); enableRegistrationScript = mkOption { type = types.bool; diff --git a/nixos/modules/services/misc/ankisyncd.nix b/nixos/modules/services/misc/ankisyncd.nix index f5acfbb0ee969..cb8671ebc5e67 100644 --- a/nixos/modules/services/misc/ankisyncd.nix +++ b/nixos/modules/services/misc/ankisyncd.nix @@ -22,7 +22,7 @@ let in { options.services.ankisyncd = { - enable = mkEnableOption (lib.mdDoc "ankisyncd"); + enable = mkEnableOption (lib.mdDoc "ankisyncd, a standalone unofficial anky sync server"); package = mkPackageOption pkgs "ankisyncd" { }; diff --git a/nixos/modules/services/misc/autorandr.nix b/nixos/modules/services/misc/autorandr.nix index aa96acb613067..22d1fb727477c 100644 --- a/nixos/modules/services/misc/autorandr.nix +++ b/nixos/modules/services/misc/autorandr.nix @@ -260,6 +260,12 @@ in { description = lib.mdDoc "Treat outputs as connected even if their lids are closed"; }; + matchEdid = mkOption { + default = false; + type = types.bool; + description = lib.mdDoc "Match displays based on edid instead of name"; + }; + hooks = mkOption { type = hooksModule; description = lib.mdDoc "Global hook scripts"; @@ -351,7 +357,8 @@ in { --batch \ --change \ --default ${cfg.defaultTarget} \ - ${optionalString cfg.ignoreLid "--ignore-lid"} + ${optionalString cfg.ignoreLid "--ignore-lid"} \ + ${optionalString cfg.matchEdid "--match-edid"} ''; Type = "oneshot"; RemainAfterExit = false; diff --git a/nixos/modules/services/misc/bepasty.nix b/nixos/modules/services/misc/bepasty.nix index 70d07629493b6..1061a78983784 100644 --- a/nixos/modules/services/misc/bepasty.nix +++ b/nixos/modules/services/misc/bepasty.nix @@ -13,7 +13,7 @@ let in { options.services.bepasty = { - enable = mkEnableOption (lib.mdDoc "Bepasty servers"); + enable = mkEnableOption (lib.mdDoc "bepasty, a binary pastebin server"); servers = mkOption { default = {}; diff --git a/nixos/modules/services/misc/calibre-server.nix b/nixos/modules/services/misc/calibre-server.nix index 66ae5fa91bb68..efc4b17c88747 100644 --- a/nixos/modules/services/misc/calibre-server.nix +++ b/nixos/modules/services/misc/calibre-server.nix @@ -32,7 +32,7 @@ in options = { services.calibre-server = { - enable = mkEnableOption (lib.mdDoc "calibre-server"); + enable = mkEnableOption (lib.mdDoc "calibre-server (e-book software)"); package = lib.mkPackageOption pkgs "calibre" { }; libraries = mkOption { diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix index 93731547ede8b..98776f6e839f7 100644 --- a/nixos/modules/services/misc/confd.nix +++ b/nixos/modules/services/misc/confd.nix @@ -17,7 +17,7 @@ let in { options.services.confd = { - enable = mkEnableOption (lib.mdDoc "confd service"); + enable = mkEnableOption (lib.mdDoc "confd, a service to manage local application configuration files using templates and data from etcd/consul/redis/zookeeper"); backend = mkOption { description = lib.mdDoc "Confd config storage backend to use."; diff --git a/nixos/modules/services/misc/etesync-dav.nix b/nixos/modules/services/misc/etesync-dav.nix index ae2b5ad043433..ef2ba9086af46 100644 --- a/nixos/modules/services/misc/etesync-dav.nix +++ b/nixos/modules/services/misc/etesync-dav.nix @@ -7,7 +7,7 @@ let in { options.services.etesync-dav = { - enable = mkEnableOption (lib.mdDoc "etesync-dav"); + enable = mkEnableOption (lib.mdDoc "etesync-dav, end-to-end encrypted sync for contacts, calendars and tasks"); host = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/evdevremapkeys.nix b/nixos/modules/services/misc/evdevremapkeys.nix index 11ea6a5f03f23..d623c038b174f 100644 --- a/nixos/modules/services/misc/evdevremapkeys.nix +++ b/nixos/modules/services/misc/evdevremapkeys.nix @@ -8,7 +8,7 @@ let in { options.services.evdevremapkeys = { - enable = mkEnableOption (lib.mdDoc ''evdevremapkeys''); + enable = mkEnableOption (lib.mdDoc ''evdevremapkeys, a daemon to remap events on linux input devices''); settings = mkOption { type = format.type; diff --git a/nixos/modules/services/misc/forgejo.nix b/nixos/modules/services/misc/forgejo.nix index 2b1700626870f..d9fd33ddedb1a 100644 --- a/nixos/modules/services/misc/forgejo.nix +++ b/nixos/modules/services/misc/forgejo.nix @@ -55,7 +55,7 @@ in options = { services.forgejo = { - enable = mkEnableOption (mdDoc "Forgejo"); + enable = mkEnableOption (mdDoc "Forgejo, a software forge"); package = mkPackageOption pkgs "forgejo" { }; diff --git a/nixos/modules/services/misc/geoipupdate.nix b/nixos/modules/services/misc/geoipupdate.nix index 27c1157e9a8c7..f18645ffb5895 100644 --- a/nixos/modules/services/misc/geoipupdate.nix +++ b/nixos/modules/services/misc/geoipupdate.nix @@ -12,7 +12,7 @@ in options = { services.geoipupdate = { enable = lib.mkEnableOption (lib.mdDoc '' - periodic downloading of GeoIP databases using geoipupdate. + periodic downloading of GeoIP databases using geoipupdate ''); interval = lib.mkOption { diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix index e31eeaf8a30a8..04ac89970e3f6 100644 --- a/nixos/modules/services/misc/gollum.nix +++ b/nixos/modules/services/misc/gollum.nix @@ -8,7 +8,7 @@ in { options.services.gollum = { - enable = mkEnableOption (lib.mdDoc "Gollum service"); + enable = mkEnableOption (lib.mdDoc "Gollum, a git-powered wiki service"); address = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/graphical-desktop.nix b/nixos/modules/services/misc/graphical-desktop.nix new file mode 100644 index 0000000000000..a88c02e610bf4 --- /dev/null +++ b/nixos/modules/services/misc/graphical-desktop.nix @@ -0,0 +1,54 @@ +{ + config, + lib, + pkgs, + ... +}: +let + xcfg = config.services.xserver; + dmcfg = config.services.displayManager; +in +{ + config = lib.mkIf (xcfg.enable || dmcfg.enable) { + # The default max inotify watches is 8192. + # Nowadays most apps require a good number of inotify watches, + # the value below is used by default on several other distros. + boot.kernel.sysctl = { + "fs.inotify.max_user_instances" = lib.mkDefault 524288; + "fs.inotify.max_user_watches" = lib.mkDefault 524288; + }; + + environment = { + # localectl looks into 00-keyboard.conf + etc."X11/xorg.conf.d/00-keyboard.conf".text = '' + Section "InputClass" + Identifier "Keyboard catchall" + MatchIsKeyboard "on" + Option "XkbModel" "${xcfg.xkb.model}" + Option "XkbLayout" "${xcfg.xkb.layout}" + Option "XkbOptions" "${xcfg.xkb.options}" + Option "XkbVariant" "${xcfg.xkb.variant}" + EndSection + ''; + systemPackages = with pkgs; [ + nixos-icons # needed for gnome and pantheon about dialog, nixos-manual and maybe more + xdg-utils + ]; + }; + + fonts.enableDefaultPackages = lib.mkDefault true; + + hardware.opengl.enable = lib.mkDefault true; + + programs.gnupg.agent.pinentryPackage = lib.mkOverride 1100 pkgs.pinentry-gnome3; + + systemd.defaultUnit = lib.mkIf (xcfg.autorun || dmcfg.enable) "graphical.target"; + + xdg = { + autostart.enable = true; + menus.enable = true; + mime.enable = true; + icons.enable = true; + }; + }; +} diff --git a/nixos/modules/services/misc/greenclip.nix b/nixos/modules/services/misc/greenclip.nix index ecfb864ab2b78..554769b63331f 100644 --- a/nixos/modules/services/misc/greenclip.nix +++ b/nixos/modules/services/misc/greenclip.nix @@ -7,7 +7,7 @@ let in { options.services.greenclip = { - enable = mkEnableOption (lib.mdDoc "Greenclip daemon"); + enable = mkEnableOption (lib.mdDoc "Greenclip, a clipboard manager"); package = mkPackageOption pkgs [ "haskellPackages" "greenclip" ] { }; }; diff --git a/nixos/modules/services/misc/homepage-dashboard.nix b/nixos/modules/services/misc/homepage-dashboard.nix index 02f1378cb0d59..e1b0264230ba5 100644 --- a/nixos/modules/services/misc/homepage-dashboard.nix +++ b/nixos/modules/services/misc/homepage-dashboard.nix @@ -12,7 +12,7 @@ in { options = { services.homepage-dashboard = { - enable = lib.mkEnableOption (lib.mdDoc "Homepage Dashboard"); + enable = lib.mkEnableOption (lib.mdDoc "Homepage Dashboard, a highly customizable application dashboard"); package = lib.mkPackageOption pkgs "homepage-dashboard" { }; diff --git a/nixos/modules/services/misc/jackett.nix b/nixos/modules/services/misc/jackett.nix index c0bb0a575f01d..ad9288e45dd29 100644 --- a/nixos/modules/services/misc/jackett.nix +++ b/nixos/modules/services/misc/jackett.nix @@ -9,7 +9,7 @@ in { options = { services.jackett = { - enable = mkEnableOption (lib.mdDoc "Jackett"); + enable = mkEnableOption (lib.mdDoc "Jackett, API support for your favorite torrent trackers"); dataDir = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/languagetool.nix b/nixos/modules/services/misc/languagetool.nix index 9adf792373b5a..902e55320b46d 100644 --- a/nixos/modules/services/misc/languagetool.nix +++ b/nixos/modules/services/misc/languagetool.nix @@ -7,7 +7,7 @@ let settingsFormat = pkgs.formats.javaProperties {}; in { options.services.languagetool = { - enable = mkEnableOption (mdDoc "the LanguageTool server"); + enable = mkEnableOption (mdDoc "the LanguageTool server, a multilingual spelling, style, and grammar checker that helps correct or paraphrase texts"); port = mkOption { type = types.port; diff --git a/nixos/modules/services/misc/leaps.nix b/nixos/modules/services/misc/leaps.nix index 5522223ecc97c..b021937f8715c 100644 --- a/nixos/modules/services/misc/leaps.nix +++ b/nixos/modules/services/misc/leaps.nix @@ -9,7 +9,7 @@ in { options = { services.leaps = { - enable = mkEnableOption (lib.mdDoc "leaps"); + enable = mkEnableOption (lib.mdDoc "leaps, a pair programming service"); port = mkOption { type = types.port; default = 8080; diff --git a/nixos/modules/services/misc/lidarr.nix b/nixos/modules/services/misc/lidarr.nix index 8ceb567e88010..42627344dcd95 100644 --- a/nixos/modules/services/misc/lidarr.nix +++ b/nixos/modules/services/misc/lidarr.nix @@ -8,7 +8,7 @@ in { options = { services.lidarr = { - enable = mkEnableOption (lib.mdDoc "Lidarr"); + enable = mkEnableOption (lib.mdDoc "Lidarr, a Usenet/BitTorrent music downloader"); dataDir = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/lifecycled.nix b/nixos/modules/services/misc/lifecycled.nix index fb5cabb4f038b..fa36ec693a844 100644 --- a/nixos/modules/services/misc/lifecycled.nix +++ b/nixos/modules/services/misc/lifecycled.nix @@ -25,7 +25,7 @@ in options = { services.lifecycled = { - enable = mkEnableOption (lib.mdDoc "lifecycled"); + enable = mkEnableOption (lib.mdDoc "lifecycled, a daemon for responding to AWS AutoScaling Lifecycle Hooks"); queueCleaner = { enable = mkEnableOption (lib.mdDoc "lifecycled-queue-cleaner"); diff --git a/nixos/modules/services/misc/logkeys.nix b/nixos/modules/services/misc/logkeys.nix index 75d073a0c94bf..85f453b0d9da1 100644 --- a/nixos/modules/services/misc/logkeys.nix +++ b/nixos/modules/services/misc/logkeys.nix @@ -6,7 +6,7 @@ let cfg = config.services.logkeys; in { options.services.logkeys = { - enable = mkEnableOption (lib.mdDoc "logkeys service"); + enable = mkEnableOption (lib.mdDoc "logkeys, a keylogger service"); device = mkOption { description = lib.mdDoc "Use the given device as keyboard input event device instead of /dev/input/eventX default."; diff --git a/nixos/modules/services/misc/mbpfan.nix b/nixos/modules/services/misc/mbpfan.nix index ef56ea49d1a95..69f6331169f7d 100644 --- a/nixos/modules/services/misc/mbpfan.nix +++ b/nixos/modules/services/misc/mbpfan.nix @@ -4,14 +4,13 @@ with lib; let cfg = config.services.mbpfan; verbose = optionalString cfg.verbose "v"; - settingsFormat = pkgs.formats.ini {}; - settingsFile = settingsFormat.generate "mbpfan.ini" cfg.settings; + format = pkgs.formats.ini {}; + cfgfile = format.generate "mbpfan.ini" cfg.settings; in { options.services.mbpfan = { enable = mkEnableOption (lib.mdDoc "mbpfan, fan controller daemon for Apple Macs and MacBooks"); - - package = mkPackageOption pkgs "mbpfan" { }; + package = mkPackageOption pkgs "mbpfan" {}; verbose = mkOption { type = types.bool; @@ -29,7 +28,7 @@ in { default = {}; description = lib.mdDoc "INI configuration for Mbpfan."; type = types.submodule { - freeformType = settingsFormat.type; + freeformType = format.type; options.general.low_temp = mkOption { type = types.int; @@ -70,12 +69,12 @@ in { config = mkIf cfg.enable { boot.kernelModules = [ "coretemp" "applesmc" ]; environment.systemPackages = [ cfg.package ]; - environment.etc."mbpfan.conf".source = settingsFile; + environment.etc."mbpfan.conf".source = cfgfile; systemd.services.mbpfan = { description = "A fan manager daemon for MacBook Pro"; wantedBy = [ "sysinit.target" ]; - after = [ "syslog.target" "sysinit.target" ]; + after = [ "sysinit.target" ]; restartTriggers = [ config.environment.etc."mbpfan.conf".source ]; serviceConfig = { diff --git a/nixos/modules/services/misc/nitter.nix b/nixos/modules/services/misc/nitter.nix index d2cf7c0de2b77..0f2f62153b00e 100644 --- a/nixos/modules/services/misc/nitter.nix +++ b/nixos/modules/services/misc/nitter.nix @@ -52,7 +52,7 @@ in options = { services.nitter = { - enable = mkEnableOption (lib.mdDoc "Nitter"); + enable = mkEnableOption (lib.mdDoc "Nitter, an alternative Twitter front-end"); package = mkPackageOption pkgs "nitter" { }; diff --git a/nixos/modules/services/misc/nix-optimise.nix b/nixos/modules/services/misc/nix-optimise.nix index 0398229a13da9..514855abaee46 100644 --- a/nixos/modules/services/misc/nix-optimise.nix +++ b/nixos/modules/services/misc/nix-optimise.nix @@ -42,9 +42,11 @@ in startAt = lib.optionals cfg.automatic cfg.dates; }; - timers.nix-optimise.timerConfig = { - Persistent = true; - RandomizedDelaySec = 1800; + timers.nix-optimise = lib.mkIf cfg.automatic { + timerConfig = { + Persistent = true; + RandomizedDelaySec = 1800; + }; }; }; }; diff --git a/nixos/modules/services/misc/nzbget.nix b/nixos/modules/services/misc/nzbget.nix index d02fda62fa4fa..122b3dd249af4 100644 --- a/nixos/modules/services/misc/nzbget.nix +++ b/nixos/modules/services/misc/nzbget.nix @@ -25,7 +25,7 @@ in options = { services.nzbget = { - enable = mkEnableOption (lib.mdDoc "NZBGet"); + enable = mkEnableOption (lib.mdDoc "NZBGet, for downloading files from news servers"); user = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/nzbhydra2.nix b/nixos/modules/services/misc/nzbhydra2.nix index 536a4e4b00758..2c1a5eae076d2 100644 --- a/nixos/modules/services/misc/nzbhydra2.nix +++ b/nixos/modules/services/misc/nzbhydra2.nix @@ -7,7 +7,7 @@ let cfg = config.services.nzbhydra2; in { options = { services.nzbhydra2 = { - enable = mkEnableOption (lib.mdDoc "NZBHydra2"); + enable = mkEnableOption (lib.mdDoc "NZBHydra2, Usenet meta search"); dataDir = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/ollama.nix b/nixos/modules/services/misc/ollama.nix index 7a5661510e251..30c2b26d8322e 100644 --- a/nixos/modules/services/misc/ollama.nix +++ b/nixos/modules/services/misc/ollama.nix @@ -15,6 +15,22 @@ in services.ollama = { enable = lib.mkEnableOption "ollama server for local large language models"; package = lib.mkPackageOption pkgs "ollama" { }; + home = lib.mkOption { + type = types.str; + default = "%S/ollama"; + example = "/home/foo"; + description = '' + The home directory that the ollama service is started in. + ''; + }; + models = lib.mkOption { + type = types.str; + default = "%S/ollama/models"; + example = "/path/to/ollama/models"; + description = '' + The directory that the ollama service will read models from and download new models to. + ''; + }; listenAddress = lib.mkOption { type = types.str; default = "127.0.0.1:11434"; @@ -58,8 +74,8 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; environment = cfg.environmentVariables // { - HOME = "%S/ollama"; - OLLAMA_MODELS = "%S/ollama/models"; + HOME = cfg.home; + OLLAMA_MODELS = cfg.models; OLLAMA_HOST = cfg.listenAddress; }; serviceConfig = { diff --git a/nixos/modules/services/misc/ombi.nix b/nixos/modules/services/misc/ombi.nix index 8bf6a9b116ec2..2e452f7d88eac 100644 --- a/nixos/modules/services/misc/ombi.nix +++ b/nixos/modules/services/misc/ombi.nix @@ -8,7 +8,9 @@ in { options = { services.ombi = { enable = mkEnableOption (lib.mdDoc '' - Ombi. + Ombi, a web application that automatically gives your shared Plex or + Emby users the ability to request content by themselves! + Optionally see <https://docs.ombi.app/info/reverse-proxy> on how to set up a reverse proxy ''); diff --git a/nixos/modules/services/misc/owncast.nix b/nixos/modules/services/misc/owncast.nix index 01fe34cf50fec..cbb6ba29e3227 100644 --- a/nixos/modules/services/misc/owncast.nix +++ b/nixos/modules/services/misc/owncast.nix @@ -5,7 +5,7 @@ in { options.services.owncast = { - enable = mkEnableOption (lib.mdDoc "owncast"); + enable = mkEnableOption (lib.mdDoc "owncast, a video live streaming solution"); dataDir = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/paperless.nix b/nixos/modules/services/misc/paperless.nix index 9301d1f687254..9a81fdde62af8 100644 --- a/nixos/modules/services/misc/paperless.nix +++ b/nixos/modules/services/misc/paperless.nix @@ -220,15 +220,16 @@ in config = mkIf cfg.enable { services.redis.servers.paperless.enable = mkIf enableRedis true; - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" - "d '${cfg.mediaDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" - (if cfg.consumptionDirIsPublic then - "d '${cfg.consumptionDir}' 777 - - - -" - else - "d '${cfg.consumptionDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" - ) - ]; + systemd.tmpfiles.settings."10-paperless" = let + defaultRule = { + inherit (cfg) user; + inherit (config.users.users.${cfg.user}) group; + }; + in { + "${cfg.dataDir}".d = defaultRule; + "${cfg.mediaDir}".d = defaultRule; + "${cfg.consumptionDir}".d = if cfg.consumptionDirIsPublic then { mode = "777"; } else defaultRule; + }; systemd.services.paperless-scheduler = { description = "Paperless Celery Beat"; @@ -238,6 +239,7 @@ in User = cfg.user; ExecStart = "${pkg}/bin/celery --app paperless beat --loglevel INFO"; Restart = "on-failure"; + LoadCredential = lib.optionalString (cfg.passwordFile != null) "PAPERLESS_ADMIN_PASSWORD:${cfg.passwordFile}"; }; environment = env; @@ -270,7 +272,7 @@ in '' + optionalString (cfg.passwordFile != null) '' export PAPERLESS_ADMIN_USER="''${PAPERLESS_ADMIN_USER:-admin}" - export PAPERLESS_ADMIN_PASSWORD=$(cat "${cfg.dataDir}/superuser-password") + export PAPERLESS_ADMIN_PASSWORD=$(cat $CREDENTIALS_DIRECTORY/PAPERLESS_ADMIN_PASSWORD) superuserState="$PAPERLESS_ADMIN_USER:$PAPERLESS_ADMIN_PASSWORD" superuserStateFile="${cfg.dataDir}/superuser-state" @@ -298,19 +300,6 @@ in environment = env; }; - # Reading the user-provided password file requires root access - systemd.services.paperless-copy-password = mkIf (cfg.passwordFile != null) { - requiredBy = [ "paperless-scheduler.service" ]; - before = [ "paperless-scheduler.service" ]; - serviceConfig = { - ExecStart = '' - ${pkgs.coreutils}/bin/install --mode 600 --owner '${cfg.user}' --compare \ - '${cfg.passwordFile}' '${cfg.dataDir}/superuser-password' - ''; - Type = "oneshot"; - }; - }; - systemd.services.paperless-consumer = { description = "Paperless document consumer"; # Bind to `paperless-scheduler` so that the consumer never runs diff --git a/nixos/modules/services/misc/pinnwand.nix b/nixos/modules/services/misc/pinnwand.nix index 5fca9f4125a83..466d045a7b16b 100644 --- a/nixos/modules/services/misc/pinnwand.nix +++ b/nixos/modules/services/misc/pinnwand.nix @@ -10,7 +10,7 @@ let in { options.services.pinnwand = { - enable = mkEnableOption (lib.mdDoc "Pinnwand"); + enable = mkEnableOption (lib.mdDoc "Pinnwand, a pastebin"); port = mkOption { type = types.port; diff --git a/nixos/modules/services/misc/plikd.nix b/nixos/modules/services/misc/plikd.nix index 9b0825bf40c98..bb5d3c1a36ca5 100644 --- a/nixos/modules/services/misc/plikd.nix +++ b/nixos/modules/services/misc/plikd.nix @@ -11,7 +11,7 @@ in { options = { services.plikd = { - enable = mkEnableOption (lib.mdDoc "the plikd server"); + enable = mkEnableOption (lib.mdDoc "plikd, a temporary file upload system"); openFirewall = mkOption { type = types.bool; diff --git a/nixos/modules/services/misc/prowlarr.nix b/nixos/modules/services/misc/prowlarr.nix index 84d365003992c..952f95485bd08 100644 --- a/nixos/modules/services/misc/prowlarr.nix +++ b/nixos/modules/services/misc/prowlarr.nix @@ -9,7 +9,7 @@ in { options = { services.prowlarr = { - enable = mkEnableOption (lib.mdDoc "Prowlarr"); + enable = mkEnableOption (lib.mdDoc "Prowlarr, an indexer manager/proxy for Torrent trackers and Usenet indexers"); package = mkPackageOption pkgs "prowlarr" { }; diff --git a/nixos/modules/services/misc/radarr.nix b/nixos/modules/services/misc/radarr.nix index a5f264331ed36..eaf49673d3c7e 100644 --- a/nixos/modules/services/misc/radarr.nix +++ b/nixos/modules/services/misc/radarr.nix @@ -9,7 +9,7 @@ in { options = { services.radarr = { - enable = mkEnableOption (lib.mdDoc "Radarr"); + enable = mkEnableOption (lib.mdDoc "Radarr, a UsetNet/BitTorrent movie downloader"); package = mkPackageOption pkgs "radarr" { }; diff --git a/nixos/modules/services/misc/readarr.nix b/nixos/modules/services/misc/readarr.nix index 73868b4baa953..486e2b4155b56 100644 --- a/nixos/modules/services/misc/readarr.nix +++ b/nixos/modules/services/misc/readarr.nix @@ -8,7 +8,7 @@ in { options = { services.readarr = { - enable = mkEnableOption (lib.mdDoc "Readarr"); + enable = mkEnableOption (lib.mdDoc "Readarr, a Usenet/BitTorrent ebook downloader"); dataDir = mkOption { type = types.str; diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix index 8ebc46b42dcc8..f99fe7a845be4 100644 --- a/nixos/modules/services/misc/redmine.nix +++ b/nixos/modules/services/misc/redmine.nix @@ -56,7 +56,7 @@ in # interface options = { services.redmine = { - enable = mkEnableOption (lib.mdDoc "Redmine"); + enable = mkEnableOption (lib.mdDoc "Redmine, a project management web application"); package = mkPackageOption pkgs "redmine" { example = "redmine.override { ruby = pkgs.ruby_3_2; }"; diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix index 68a8318942506..08833e4135419 100644 --- a/nixos/modules/services/misc/rippled.nix +++ b/nixos/modules/services/misc/rippled.nix @@ -207,7 +207,7 @@ in options = { services.rippled = { - enable = mkEnableOption (lib.mdDoc "rippled"); + enable = mkEnableOption (lib.mdDoc "rippled, a decentralized cryptocurrency blockchain daemon implementing the XRP Ledger protocol in C++"); package = mkPackageOption pkgs "rippled" { }; diff --git a/nixos/modules/services/misc/signald.nix b/nixos/modules/services/misc/signald.nix index 32ba154506ce3..44b82a931cd84 100644 --- a/nixos/modules/services/misc/signald.nix +++ b/nixos/modules/services/misc/signald.nix @@ -8,7 +8,7 @@ let in { options.services.signald = { - enable = mkEnableOption (lib.mdDoc "the signald service"); + enable = mkEnableOption (lib.mdDoc "signald, the unofficial daemon for interacting with Signal"); user = mkOption { type = types.str; diff --git a/nixos/modules/services/monitoring/nezha-agent.nix b/nixos/modules/services/monitoring/nezha-agent.nix new file mode 100644 index 0000000000000..ef6878798f377 --- /dev/null +++ b/nixos/modules/services/monitoring/nezha-agent.nix @@ -0,0 +1,103 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.nezha-agent; +in +{ + meta = { + maintainers = with lib.maintainers; [ moraxyc ]; + }; + options = { + services.nezha-agent = { + enable = lib.mkEnableOption (lib.mdDoc "Agent of Nezha Monitoring"); + + package = lib.mkPackageOption pkgs "nezha-agent" { }; + debug = lib.mkEnableOption (lib.mdDoc "verbose log"); + tls = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Enable SSL/TLS encryption. + ''; + }; + disableCommandExecute = lib.mkOption { + type = lib.types.bool; + default = true; + description = lib.mdDoc '' + Disable executing the command from dashboard. + ''; + }; + skipConnection = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Do not monitor the number of connections. + ''; + }; + skipProcess = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Do not monitor the number of processes. + ''; + }; + reportDelay = lib.mkOption { + type = lib.types.enum [ 1 2 3 4 ]; + default = 1; + description = lib.mdDoc '' + The interval between system status reportings. + The value must be an integer from 1 to 4 + ''; + }; + passwordFile = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + description = lib.mdDoc '' + Path to the file contained the password from dashboard. + ''; + }; + server = lib.mkOption { + type = lib.types.str; + description = lib.mdDoc '' + Address to the dashboard + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.packages = [ cfg.package ]; + + systemd.services.nezha-agent = { + serviceConfig = { + ProtectSystem = "full"; + PrivateDevices = "yes"; + PrivateTmp = "yes"; + NoNewPrivileges = true; + }; + path = [ cfg.package ]; + startLimitIntervalSec = 10; + startLimitBurst = 3; + script = lib.concatStringsSep " " ( + [ + "${cfg.package}/bin/agent" + "--disable-auto-update" + "--disable-force-update" + "--password $(cat ${cfg.passwordFile})" + ] + ++ lib.optional cfg.debug "--debug" + ++ lib.optional cfg.disableCommandExecute "--disable-command-execute" + ++ lib.optional (cfg.reportDelay != null) "--report-delay ${toString cfg.reportDelay}" + ++ lib.optional (cfg.server != null) "--server ${cfg.server}" + ++ lib.optional cfg.skipConnection "--skip-conn" + ++ lib.optional cfg.skipProcess "--skip-procs" + ++ lib.optional cfg.tls "--tls" + ); + wantedBy = [ "multi-user.target" ]; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 640c6c339cf62..0331a07b5109d 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -55,6 +55,7 @@ let "modemmanager" "mongodb" "mysqld" + "nats" "nextcloud" "nginx" "nginxlog" diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nats.nix b/nixos/modules/services/monitoring/prometheus/exporters/nats.nix new file mode 100644 index 0000000000000..83e60426f5ed2 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/nats.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, options, ... }: + +with lib; + +let + + cfg = config.services.prometheus.exporters.nats; + +in +{ + port = 7777; + + extraOpts = { + url = mkOption { + type = types.str; + default = "http://127.0.0.1:8222"; + description = '' + NATS monitor endpoint to query. + ''; + }; + }; + + serviceOpts = { + serviceConfig = { + ExecStart = '' + ${pkgs.prometheus-nats-exporter}/bin/prometheus-nats-exporter \ + -addr ${cfg.listenAddress} \ + -port ${toString cfg.port} \ + ${concatStringsSep " \\\n " cfg.extraFlags} \ + ${cfg.url} + ''; + }; + }; +} diff --git a/nixos/modules/services/monitoring/thanos.nix b/nixos/modules/services/monitoring/thanos.nix index 02502816ef5d7..f9ec271c6ef55 100644 --- a/nixos/modules/services/monitoring/thanos.nix +++ b/nixos/modules/services/monitoring/thanos.nix @@ -353,6 +353,10 @@ let See <https://tools.ietf.org/html/rfc4366#section-3.1> ''; + grpc-compression = mkParam types.str '' + Compression algorithm to use for gRPC requests to other clients. + ''; + web.route-prefix = mkParam types.str '' Prefix for API and UI endpoints. @@ -642,6 +646,10 @@ let receive = params.common cfg.receive // params.objstore cfg.receive // { + receive.grpc-compression = mkParam types.str '' + Compression algorithm to use for gRPC requests to other receivers. + ''; + remote-write.address = mkParamDef types.str "0.0.0.0:19291" '' Address to listen on for remote write requests. ''; diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix index da8633d5066f7..0a4fa4c524a6c 100644 --- a/nixos/modules/services/networking/bind.nix +++ b/nixos/modules/services/networking/bind.nix @@ -121,7 +121,7 @@ in package = mkPackageOption pkgs "bind" { }; cacheNetworks = mkOption { - default = [ "127.0.0.0/24" ]; + default = [ "127.0.0.0/24" "::1/128" ]; type = types.listOf types.str; description = lib.mdDoc '' What networks are allowed to use us as a resolver. Note diff --git a/nixos/modules/services/networking/cloudflared.nix b/nixos/modules/services/networking/cloudflared.nix index b9556bfa60d06..76db339a1831c 100644 --- a/nixos/modules/services/networking/cloudflared.nix +++ b/nixos/modules/services/networking/cloudflared.nix @@ -11,7 +11,7 @@ let default = null; example = "30s"; description = lib.mdDoc '' - Timeout for establishing a new TCP connection to your origin server. This excludes the time taken to establish TLS, which is controlled by [https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/#tlstimeout](tlsTimeout). + Timeout for establishing a new TCP connection to your origin server. This excludes the time taken to establish TLS, which is controlled by [tlsTimeout](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/#tlstimeout). ''; }; diff --git a/nixos/modules/services/networking/i2p.nix b/nixos/modules/services/networking/i2p.nix index c5c7a955cbd4f..5c6c08831a43d 100644 --- a/nixos/modules/services/networking/i2p.nix +++ b/nixos/modules/services/networking/i2p.nix @@ -5,7 +5,8 @@ with lib; let cfg = config.services.i2p; homeDir = "/var/lib/i2p"; -in { +in +{ ###### interface options.services.i2p.enable = mkEnableOption (lib.mdDoc "I2P router"); @@ -27,7 +28,7 @@ in { User = "i2p"; WorkingDirectory = homeDir; Restart = "on-abort"; - ExecStart = "${pkgs.i2p}/bin/i2prouter-plain"; + ExecStart = "${pkgs.i2p}/bin/i2prouter"; }; }; }; diff --git a/nixos/modules/services/networking/kea.nix b/nixos/modules/services/networking/kea.nix index 656ddd41fd12b..5fd6427c90f86 100644 --- a/nixos/modules/services/networking/kea.nix +++ b/nixos/modules/services/networking/kea.nix @@ -9,7 +9,6 @@ with lib; let cfg = config.services.kea; - xor = x: y: (!x && y) || (x && !y); format = pkgs.formats.json {}; chooseNotNull = x: y: if x != null then x else y; diff --git a/nixos/modules/services/networking/mihomo.nix b/nixos/modules/services/networking/mihomo.nix index ae700603b5290..312530caeaade 100644 --- a/nixos/modules/services/networking/mihomo.nix +++ b/nixos/modules/services/networking/mihomo.nix @@ -12,7 +12,7 @@ let in { options.services.mihomo = { - enable = lib.mkEnableOption "Mihomo, A rule-based proxy in Go."; + enable = lib.mkEnableOption "Mihomo, A rule-based proxy in Go"; package = lib.mkPackageOption pkgs "mihomo" { }; @@ -28,14 +28,14 @@ in description = '' Local web interface to use. - You can also use the following website, just in case: + You can also use the following website: - metacubexd: - https://d.metacubex.one - https://metacubex.github.io/metacubexd - https://metacubexd.pages.dev - yacd: - https://yacd.haishan.me - - clash-dashboard (buggy): + - clash-dashboard: - https://clash.razord.top ''; }; @@ -49,7 +49,7 @@ in tunMode = lib.mkEnableOption '' necessary permission for Mihomo's systemd service for TUN mode to function properly. - Keep in mind, that you still need to enable TUN mode manually in Mihomo's configuration. + Keep in mind, that you still need to enable TUN mode manually in Mihomo's configuration ''; }; diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix index 00dbd6bbe386d..d6b2f652c8887 100644 --- a/nixos/modules/services/networking/radicale.nix +++ b/nixos/modules/services/networking/radicale.nix @@ -200,5 +200,5 @@ in { }; }; - meta.maintainers = with lib.maintainers; [ infinisil dotlambda ]; + meta.maintainers = with lib.maintainers; [ dotlambda ]; } diff --git a/nixos/modules/services/networking/soju.nix b/nixos/modules/services/networking/soju.nix index d69ec08ca13a0..810957be65f57 100644 --- a/nixos/modules/services/networking/soju.nix +++ b/nixos/modules/services/networking/soju.nix @@ -5,7 +5,10 @@ with lib; let cfg = config.services.soju; stateDir = "/var/lib/soju"; - listenCfg = concatMapStringsSep "\n" (l: "listen ${l}") cfg.listen; + runtimeDir = "/run/soju"; + listen = cfg.listen + ++ optional cfg.adminSocket.enable "unix+admin://${runtimeDir}/admin"; + listenCfg = concatMapStringsSep "\n" (l: "listen ${l}") listen; tlsCfg = optionalString (cfg.tlsCertificate != null) "tls ${cfg.tlsCertificate} ${cfg.tlsCertificateKey}"; logCfg = optionalString cfg.enableMessageLogging @@ -22,6 +25,10 @@ let ${cfg.extraConfig} ''; + + sojuctl = pkgs.writeShellScriptBin "sojuctl" '' + exec ${cfg.package}/bin/sojuctl --config ${configFile} "$@" + ''; in { ###### interface @@ -29,6 +36,8 @@ in options.services.soju = { enable = mkEnableOption (lib.mdDoc "soju"); + package = mkPackageOption pkgs "soju" { }; + listen = mkOption { type = types.listOf types.str; default = [ ":6697" ]; @@ -66,6 +75,14 @@ in description = lib.mdDoc "Whether to enable message logging."; }; + adminSocket.enable = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + Listen for admin connections from sojuctl at /run/soju/admin. + ''; + }; + httpOrigins = mkOption { type = types.listOf types.str; default = []; @@ -107,6 +124,8 @@ in } ]; + environment.systemPackages = [ sojuctl ]; + systemd.services.soju = { description = "soju IRC bouncer"; wantedBy = [ "multi-user.target" ]; @@ -115,8 +134,9 @@ in serviceConfig = { DynamicUser = true; Restart = "always"; - ExecStart = "${pkgs.soju}/bin/soju -config ${configFile}"; + ExecStart = "${cfg.package}/bin/soju -config ${configFile}"; StateDirectory = "soju"; + RuntimeDirectory = "soju"; }; }; }; diff --git a/nixos/modules/services/networking/technitium-dns-server.nix b/nixos/modules/services/networking/technitium-dns-server.nix new file mode 100644 index 0000000000000..0c8499e072d4f --- /dev/null +++ b/nixos/modules/services/networking/technitium-dns-server.nix @@ -0,0 +1,109 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.technitium-dns-server; + stateDir = "/var/lib/technitium-dns-server"; + inherit (lib) + mkEnableOption + mkPackageOption + mkOption + mkIf + types + ; +in +{ + options.services.technitium-dns-server = { + enable = mkEnableOption "Technitium DNS Server"; + + package = mkPackageOption pkgs "technitium-dns-server" { }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open ports in the firewall. + Standard ports are 53 (UDP and TCP, for DNS), 5380 and 53443 (TCP, HTTP and HTTPS for web interface). + Specify different or additional ports in options firewallUDPPorts and firewallTCPPorts if necessary. + ''; + }; + + firewallUDPPorts = mkOption { + type = with types; listOf int; + default = [ 53 ]; + description = '' + List of UDP ports to open in firewall. + ''; + }; + + firewallTCPPorts = mkOption { + type = with types; listOf int; + default = [ + 53 + 5380 # web interface HTTP + 53443 # web interface HTTPS + ]; + description = '' + List of TCP ports to open in firewall. + You might want to open ports 443 and 853 if you intend to use DNS over HTTPS or DNS over TLS. + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.technitium-dns-server = { + description = "Technitium DNS Server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/technitium-dns-server ${stateDir}"; + + DynamicUser = true; + + StateDirectory = "technitium-dns-server"; + WorkingDirectory = stateDir; + BindPaths = stateDir; + + Restart = "always"; + RestartSec = 10; + TimeoutStopSec = 10; + KillSignal = "SIGINT"; + + # Harden the service + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateTmp = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_NETLINK"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + }; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedUDPPorts = cfg.firewallUDPPorts; + allowedTCPPorts = cfg.firewallTCPPorts; + }; + }; + + meta.maintainers = with lib.maintainers; [ fabianrig ]; +} diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix index eb769f53901cf..5e20c83652988 100644 --- a/nixos/modules/services/networking/tinc.nix +++ b/nixos/modules/services/networking/tinc.nix @@ -348,7 +348,7 @@ in (flip mapAttrsToList cfg.networks (network: data: flip mapAttrs' data.hosts (host: text: nameValuePair ("tinc/${network}/hosts/${host}") - ({ mode = "0644"; user = "tinc.${network}"; inherit text; }) + ({ mode = "0644"; user = "tinc-${network}"; inherit text; }) ) // { "tinc/${network}/tinc.conf" = { mode = "0444"; @@ -375,13 +375,13 @@ in Restart = "always"; RestartSec = "3"; ExecReload = mkIf (versionAtLeast version "1.1pre") "${data.package}/bin/tinc -n ${network} reload"; - ExecStart = "${data.package}/bin/tincd -D -U tinc.${network} -n ${network} ${optionalString (data.chroot) "-R"} --pidfile /run/tinc.${network}.pid -d ${toString data.debugLevel}"; + ExecStart = "${data.package}/bin/tincd -D -U tinc-${network} -n ${network} ${optionalString (data.chroot) "-R"} --pidfile /run/tinc.${network}.pid -d ${toString data.debugLevel}"; }; preStart = '' mkdir -p /etc/tinc/${network}/hosts - chown tinc.${network} /etc/tinc/${network}/hosts + chown tinc-${network} /etc/tinc/${network}/hosts mkdir -p /etc/tinc/${network}/invitations - chown tinc.${network} /etc/tinc/${network}/invitations + chown tinc-${network} /etc/tinc/${network}/invitations # Determine how we should generate our keys if type tinc >/dev/null 2>&1; then @@ -420,14 +420,14 @@ in in [ cli-wrappers ]; users.users = flip mapAttrs' cfg.networks (network: _: - nameValuePair ("tinc.${network}") ({ + nameValuePair ("tinc-${network}") ({ description = "Tinc daemon user for ${network}"; isSystemUser = true; - group = "tinc.${network}"; + group = "tinc-${network}"; }) ); users.groups = flip mapAttrs' cfg.networks (network: _: - nameValuePair "tinc.${network}" {} + nameValuePair "tinc-${network}" {} ); }); diff --git a/nixos/modules/services/security/yubikey-agent.nix b/nixos/modules/services/security/yubikey-agent.nix index 3d5f84af2cf48..f7ee952e7f61e 100644 --- a/nixos/modules/services/security/yubikey-agent.nix +++ b/nixos/modules/services/security/yubikey-agent.nix @@ -23,7 +23,7 @@ in SSH_AUTH_SOCK to point at yubikey-agent. Note that yubikey-agent will use whatever pinentry is - specified in programs.gnupg.agent.pinentryFlavor. + specified in programs.gnupg.agent.pinentryPackage. ''; }; diff --git a/nixos/modules/services/system/cloud-init.nix b/nixos/modules/services/system/cloud-init.nix index 00ae77be4271c..689e0000fdd54 100644 --- a/nixos/modules/services/system/cloud-init.nix +++ b/nixos/modules/services/system/cloud-init.nix @@ -17,6 +17,7 @@ let ++ optional cfg.ext4.enable e2fsprogs ++ optional cfg.xfs.enable xfsprogs ; + hasFs = fsName: lib.any (fs: fs.fsType == fsName) (lib.attrValues config.fileSystems); settingsFormat = pkgs.formats.yaml { }; cfgfile = settingsFormat.generate "cloud.cfg" cfg.settings; in @@ -44,7 +45,8 @@ in btrfs.enable = mkOption { type = types.bool; - default = false; + default = hasFs "btrfs"; + defaultText = literalExpression ''hasFs "btrfs"''; description = mdDoc '' Allow the cloud-init service to operate `btrfs` filesystem. ''; @@ -52,7 +54,8 @@ in ext4.enable = mkOption { type = types.bool; - default = true; + default = hasFs "ext4"; + defaultText = literalExpression ''hasFs "ext4"''; description = mdDoc '' Allow the cloud-init service to operate `ext4` filesystem. ''; @@ -60,7 +63,8 @@ in xfs.enable = mkOption { type = types.bool; - default = false; + default = hasFs "xfs"; + defaultText = literalExpression ''hasFs "xfs"''; description = mdDoc '' Allow the cloud-init service to operate `xfs` filesystem. ''; @@ -204,7 +208,7 @@ in description = "Apply the settings specified in cloud-config"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; - after = [ "network-online.target" "syslog.target" "cloud-config.target" ]; + after = [ "network-online.target" "cloud-config.target" ]; path = path; serviceConfig = { @@ -220,7 +224,7 @@ in description = "Execute cloud user/final scripts"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; - after = [ "network-online.target" "syslog.target" "cloud-config.service" "rc-local.service" ]; + after = [ "network-online.target" "cloud-config.service" "rc-local.service" ]; requires = [ "cloud-config.target" ]; path = path; serviceConfig = { diff --git a/nixos/modules/services/system/nix-daemon.nix b/nixos/modules/services/system/nix-daemon.nix index ce255cd8d0a46..550ef6b1e18c2 100644 --- a/nixos/modules/services/system/nix-daemon.nix +++ b/nixos/modules/services/system/nix-daemon.nix @@ -247,7 +247,7 @@ in users.users = nixbldUsers; - services.xserver.displayManager.hiddenUsers = attrNames nixbldUsers; + services.displayManager.hiddenUsers = attrNames nixbldUsers; # Legacy configuration conversion. nix.settings = mkMerge [ diff --git a/nixos/modules/services/web-apps/castopod.nix b/nixos/modules/services/web-apps/castopod.nix index 0ccba217be4dd..0b905bb50761e 100644 --- a/nixos/modules/services/web-apps/castopod.nix +++ b/nixos/modules/services/web-apps/castopod.nix @@ -21,7 +21,7 @@ in options.services = { castopod = { - enable = lib.mkEnableOption (lib.mdDoc "Castopod"); + enable = lib.mkEnableOption (lib.mdDoc "Castopod, a hosting platform for podcasters"); package = lib.mkOption { type = lib.types.package; default = pkgs.castopod; diff --git a/nixos/modules/services/web-apps/healthchecks.nix b/nixos/modules/services/web-apps/healthchecks.nix index 1d439f162313b..04b40e6eb8b08 100644 --- a/nixos/modules/services/web-apps/healthchecks.nix +++ b/nixos/modules/services/web-apps/healthchecks.nix @@ -213,8 +213,7 @@ in preStart = '' ${pkg}/opt/healthchecks/manage.py collectstatic --no-input ${pkg}/opt/healthchecks/manage.py remove_stale_contenttypes --no-input - ${pkg}/opt/healthchecks/manage.py compress - ''; + '' + lib.optionalString (cfg.settings.DEBUG != "True") "${pkg}/opt/healthchecks/manage.py compress"; serviceConfig = commonConfig // { Restart = "always"; diff --git a/nixos/modules/services/web-apps/hledger-web.nix b/nixos/modules/services/web-apps/hledger-web.nix index be8ecc645e59c..2e888d081a9f9 100644 --- a/nixos/modules/services/web-apps/hledger-web.nix +++ b/nixos/modules/services/web-apps/hledger-web.nix @@ -26,28 +26,17 @@ in { ''; }; - capabilities = { - view = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc '' - Enable the view capability. - ''; - }; - add = mkOption { - type = types.bool; - default = false; - description = lib.mdDoc '' - Enable the add capability. - ''; - }; - manage = mkOption { - type = types.bool; - default = false; - description = lib.mdDoc '' - Enable the manage capability. - ''; - }; + allow = mkOption { + type = types.enum [ "view" "add" "edit" "sandstorm" ]; + default = "view"; + description = lib.mdDoc '' + User's access level for changing data. + + * view: view only permission. + * add: view and add permissions. + * edit: view, add, and edit permissions. + * sandstorm: permissions from the `X-Sandstorm-Permissions` request header. + ''; }; stateDir = mkOption { @@ -89,6 +78,11 @@ in { }; + imports = [ + (mkRemovedOptionModule [ "services" "hledger-web" "capabilities" ] + "This option has been replaced by new option `services.hledger-web.allow`.") + ]; + config = mkIf cfg.enable { users.users.hledger = { @@ -102,16 +96,11 @@ in { users.groups.hledger = {}; systemd.services.hledger-web = let - capabilityString = with cfg.capabilities; concatStringsSep "," ( - (optional view "view") - ++ (optional add "add") - ++ (optional manage "manage") - ); serverArgs = with cfg; escapeShellArgs ([ "--serve" "--host=${host}" "--port=${toString port}" - "--capabilities=${capabilityString}" + "--allow=${allow}" (optionalString (cfg.baseUrl != null) "--base-url=${cfg.baseUrl}") (optionalString (cfg.serveApi) "--serve-api") ] ++ (map (f: "--file=${stateDir}/${f}") cfg.journalFiles) diff --git a/nixos/modules/services/web-apps/kavita.nix b/nixos/modules/services/web-apps/kavita.nix index c90697bcfa8b2..81b8edc5e0066 100644 --- a/nixos/modules/services/web-apps/kavita.nix +++ b/nixos/modules/services/web-apps/kavita.nix @@ -34,8 +34,8 @@ in tokenKeyFile = lib.mkOption { type = lib.types.path; description = lib.mdDoc '' - A file containing the TokenKey, a secret with at 128+ bits. - It can be generated with `head -c 32 /dev/urandom | base64`. + A file containing the TokenKey, a secret with at 512+ bits. + It can be generated with `head -c 64 /dev/urandom | base64 --wrap=0`. ''; }; diff --git a/nixos/modules/services/web-apps/movim.nix b/nixos/modules/services/web-apps/movim.nix new file mode 100644 index 0000000000000..bb88a185b4618 --- /dev/null +++ b/nixos/modules/services/web-apps/movim.nix @@ -0,0 +1,711 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) + filterAttrsRecursive + generators + literalExpression + mkDefault + mkIf + mkOption + mkEnableOption + mkPackageOption + mkMerge + pipe + types + ; + + cfg = config.services.movim; + + defaultPHPCfg = { + "output_buffering" = 0; + "error_reporting" = "E_ALL & ~E_DEPRECATED & ~E_STRICT"; + "opcache.enable_cli" = 1; + "opcache.interned_strings_buffer" = 8; + "opcache.max_accelerated_files" = 6144; + "opcache.memory_consumption" = 128; + "opcache.revalidate_freq" = 2; + "opcache.fast_shutdown" = 1; + }; + + phpCfg = generators.toKeyValue + { mkKeyValue = generators.mkKeyValueDefault { } " = "; } + (defaultPHPCfg // cfg.phpCfg); + + podConfigFlags = + let + bevalue = a: lib.escapeShellArg (generators.mkValueStringDefault { } a); + in + lib.concatStringsSep " " + (lib.attrsets.foldlAttrs + (acc: k: v: acc ++ lib.optional (v != null) "--${k}=${bevalue v}") + [ ] + cfg.podConfig); + + package = + let + p = cfg.package.override + ({ + inherit phpCfg; + withPgsql = cfg.database.type == "pgsql"; + withMysql = cfg.database.type == "mysql"; + inherit (cfg) minifyStaticFiles; + } // lib.optionalAttrs (lib.isAttrs cfg.minifyStaticFiles) (with cfg.minifyStaticFiles; { + esbuild = esbuild.package; + lightningcss = lightningcss.package; + scour = scour.package; + })); + in + p.overrideAttrs (finalAttrs: prevAttrs: + let + appDir = "$out/share/php/${finalAttrs.pname}"; + + stateDirectories = '' + # Symlinking in our state directories + rm -rf $out/.env $out/cache ${appDir}/public/cache + ln -s ${cfg.dataDir}/.env ${appDir}/.env + ln -s ${cfg.dataDir}/public/cache ${appDir}/public/cache + ln -s ${cfg.logDir} ${appDir}/log + ln -s ${cfg.runtimeDir}/cache ${appDir}/cache + ''; + + exposeComposer = '' + # Expose PHP Composer for scripts + mkdir -p $out/bin + echo "#!${lib.getExe pkgs.dash}" > $out/bin/movim-composer + echo "${finalAttrs.php.packages.composer}/bin/composer --working-dir="${appDir}" \"\$@\"" >> $out/bin/movim-composer + chmod +x $out/bin/movim-composer + ''; + + podConfigInputDisableReplace = lib.optionalString (podConfigFlags != "") + (lib.concatStringsSep "\n" + (lib.attrsets.foldlAttrs + (acc: k: v: + acc ++ lib.optional (v != null) + # Disable all Admin panel options that were set in the + # `cfg.podConfig` to prevent confusing situtions where the + # values are rewritten on server reboot + '' + substituteInPlace ${appDir}/app/widgets/AdminMain/adminmain.tpl \ + --replace-warn 'name="${k}"' 'name="${k}" disabled' + '') + [ ] + cfg.podConfig)); + + precompressStaticFilesJobs = + let + inherit (cfg.precompressStaticFiles) brotli gzip; + + findTextFileNames = lib.concatStringsSep " -o " + (builtins.map (n: ''-iname "*.${n}"'') + [ "css" "ini" "js" "json" "manifest" "mjs" "svg" "webmanifest" ]); + in + lib.concatStringsSep "\n" [ + (lib.optionalString brotli.enable '' + echo -n "Precompressing static files with Brotli …" + find ${appDir}/public -type f ${findTextFileNames} \ + | ${lib.getExe pkgs.parallel} ${lib.escapeShellArgs [ + "--will-cite" + "-j $NIX_BUILD_CORES" + "${lib.getExe brotli.package} --keep --quality=${builtins.toString brotli.compressionLevel} --output={}.br {}" + ]} + echo " done." + '') + (lib.optionalString gzip.enable '' + echo -n "Precompressing static files with Gzip …" + find ${appDir}/public -type f ${findTextFileNames} \ + | ${lib.getExe pkgs.parallel} ${lib.escapeShellArgs [ + "--will-cite" + "-j $NIX_BUILD_CORES" + "${lib.getExe gzip.package} -c -${builtins.toString gzip.compressionLevel} {} > {}.gz" + ]} + echo " done." + '') + ]; + in + { + postInstall = lib.concatStringsSep "\n\n" [ + prevAttrs.postInstall + stateDirectories + exposeComposer + podConfigInputDisableReplace + precompressStaticFilesJobs + ]; + }); + + configFile = pipe cfg.settings [ + (filterAttrsRecursive (_: v: v != null)) + (generators.toKeyValue { }) + (pkgs.writeText "movim-env") + ]; + + pool = "movim"; + fpm = config.services.phpfpm.pools.${pool}; + phpExecutionUnit = "phpfpm-${pool}"; + + dbService = { + "postgresql" = "postgresql.service"; + "mysql" = "mysql.service"; + }.${cfg.database.type}; +in +{ + options.services = { + movim = { + enable = mkEnableOption "a Movim instance"; + package = mkPackageOption pkgs "movim" { }; + phpPackage = mkPackageOption pkgs "php" { }; + + phpCfg = mkOption { + type = with types; attrsOf (oneOf [ int str bool ]); + defaultText = literalExpression (generators.toPretty { } defaultPHPCfg); + default = { }; + description = "Extra PHP INI options such as `memory_limit`, `max_execution_time`, etc."; + }; + + user = mkOption { + type = types.nonEmptyStr; + default = "movim"; + description = "User running Movim service"; + }; + + group = mkOption { + type = types.nonEmptyStr; + default = "movim"; + description = "Group running Movim service"; + }; + + dataDir = mkOption { + type = types.nonEmptyStr; + default = "/var/lib/movim"; + description = "State directory of the `movim` user which holds the application’s state & data."; + }; + + logDir = mkOption { + type = types.nonEmptyStr; + default = "/var/log/movim"; + description = "Log directory of the `movim` user which holds the application’s logs."; + }; + + runtimeDir = mkOption { + type = types.nonEmptyStr; + default = "/run/movim"; + description = "Runtime directory of the `movim` user which holds the application’s caches & temporary files."; + }; + + domain = mkOption { + type = types.nonEmptyStr; + description = "Fully-qualified domain name (FQDN) for the Movim instance."; + }; + + port = mkOption { + type = types.port; + default = 8080; + description = "Movim daemon port."; + }; + + debug = mkOption { + type = types.bool; + default = false; + description = "Debugging logs."; + }; + + verbose = mkOption { + type = types.bool; + default = false; + description = "Verbose logs."; + }; + + minifyStaticFiles = mkOption { + type = with types; either bool (submodule { + options = { + script = mkOption { + type = types.submodule { + options = { + enable = mkEnableOption "Script minification"; + package = mkPackageOption pkgs "esbuild" { }; + target = mkOption { + type = with types; nullOr nonEmptyStr; + default = null; + }; + }; + }; + }; + style = mkOption { + type = types.submodule { + options = { + enable = mkEnableOption "Script minification"; + package = mkPackageOption pkgs "lightningcss" { }; + target = mkOption { + type = with types; nullOr nonEmptyStr; + default = null; + }; + }; + }; + }; + svg = mkOption { + type = types.submodule { + options = { + enable = mkEnableOption "SVG minification"; + package = mkPackageOption pkgs "scour" { }; + }; + }; + }; + }; + }); + default = true; + description = "Do minification on public static files"; + }; + + precompressStaticFiles = mkOption { + type = with types; submodule { + options = { + brotli = { + enable = mkEnableOption "Brotli precompression"; + package = mkPackageOption pkgs "brotli" { }; + compressionLevel = mkOption { + type = types.ints.between 0 11; + default = 11; + description = "Brotli compression level"; + }; + }; + gzip = { + enable = mkEnableOption "Gzip precompression"; + package = mkPackageOption pkgs "gzip" { }; + compressionLevel = mkOption { + type = types.ints.between 1 9; + default = 9; + description = "Gzip compression level"; + }; + }; + }; + }; + default = { + brotli.enable = true; + gzip.enable = false; + }; + description = "Aggressively precompress static files"; + }; + + podConfig = mkOption { + type = types.submodule { + options = { + info = mkOption { + type = with types; nullOr str; + default = null; + description = "Content of the info box on the login page"; + }; + + description = mkOption { + type = with types; nullOr str; + default = null; + description = "General description of the instance"; + }; + + timezone = mkOption { + type = with types; nullOr str; + default = null; + description = "The server timezone"; + }; + + restrictsuggestions = mkOption { + type = with types; nullOr bool; + default = null; + description = "Only suggest chatrooms, Communities and other contents that are available on the user XMPP server and related services"; + }; + + chatonly = mkOption { + type = with types; nullOr bool; + default = null; + description = "Disable all the social feature (Communities, Blog…) and keep only the chat ones"; + }; + + disableregistration = mkOption { + type = with types; nullOr bool; + default = null; + description = "Remove the XMPP registration flow and buttons from the interface"; + }; + + loglevel = mkOption { + type = with types; nullOr (ints.between 0 3); + default = null; + description = "The server loglevel"; + }; + + locale = mkOption { + type = with types; nullOr str; + default = null; + description = "The server main locale"; + }; + + xmppdomain = mkOption { + type = with types; nullOr str; + default = null; + description = "The default XMPP server domain"; + }; + + xmppdescription = mkOption { + type = with types; nullOr str; + default = null; + description = "The default XMPP server description"; + }; + + xmppwhitelist = mkOption { + type = with types; nullOr str; + default = null; + description = "The allowlisted XMPP servers"; + }; + }; + }; + default = { }; + description = '' + Pod configuration (values from `php daemon.php config --help`). + Note that these values will now be disabled in the admin panel. + ''; + }; + + settings = mkOption { + type = with types; attrsOf (nullOr (oneOf [ int str bool ])); + default = { }; + description = ".env settings for Movim. Secrets should use `secretFile` option instead. `null`s will be culled."; + }; + + secretFile = mkOption { + type = with types; nullOr path; + default = null; + description = "The secret file to be sourced for the .env settings."; + }; + + database = { + type = mkOption { + type = types.enum [ "mysql" "postgresql" ]; + example = "mysql"; + default = "postgresql"; + description = "Database engine to use."; + }; + + name = mkOption { + type = types.str; + default = "movim"; + description = "Database name."; + }; + + user = mkOption { + type = types.str; + default = "movim"; + description = "Database username."; + }; + + createLocally = mkOption { + type = types.bool; + default = true; + description = "local database using UNIX socket authentication"; + }; + }; + + nginx = mkOption { + type = with types; nullOr (submodule + (import ../web-servers/nginx/vhost-options.nix { + inherit config lib; + })); + default = null; + example = lib.literalExpression /* nginx */ '' + { + serverAliases = [ + "pics.''${config.networking.domain}" + ]; + enableACME = true; + forceHttps = true; + } + ''; + description = '' + With this option, you can customize an nginx virtual host which already has sensible defaults for Movim. + Set to `{ }` if you do not need any customization to the virtual host. + If enabled, then by default, the {option}`serverName` is `''${domain}`, + If this is set to null (the default), no nginx virtualHost will be configured. + ''; + }; + + poolConfig = mkOption { + type = with types; attrsOf (oneOf [ int str bool ]); + default = { }; + description = "Options for Movim’s PHP-FPM pool."; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + users = { + users = { + movim = mkIf (cfg.user == "movim") { + isSystemUser = true; + group = cfg.group; + }; + "${config.services.nginx.user}".extraGroups = [ cfg.group ]; + }; + groups = { + ${cfg.group} = { }; + }; + }; + + services = { + movim = { + settings = mkMerge [ + { + DAEMON_URL = "//${cfg.domain}"; + DAEMON_PORT = cfg.port; + DAEMON_INTERFACE = "127.0.0.1"; + DAEMON_DEBUG = cfg.debug; + DAEMON_VERBOSE = cfg.verbose; + } + (mkIf cfg.database.createLocally { + DB_DRIVER = { + "postgresql" = "pgsql"; + "mysql" = "mysql"; + }.${cfg.database.type}; + DB_HOST = "localhost"; + DB_PORT = config.services.${cfg.database.type}.settings.port; + DB_DATABASE = cfg.database.name; + DB_USERNAME = cfg.database.user; + DB_PASSWORD = ""; + }) + ]; + + poolConfig = lib.mapAttrs' (n: v: lib.nameValuePair n (lib.mkDefault v)) { + "pm" = "dynamic"; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 8; + "pm.max_requests" = 500; + }; + }; + + nginx = mkIf (cfg.nginx != null) { + enable = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + recommendedBrotliSettings = true; + recommendedProxySettings = true; + # TODO: recommended cache options already in Nginx⁇ + appendHttpConfig = /* nginx */ '' + fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=nginx_cache:100m inactive=60m; + fastcgi_cache_key "$scheme$request_method$host$request_uri"; + ''; + virtualHosts."${cfg.domain}" = mkMerge [ + cfg.nginx + { + root = lib.mkForce "${package}/share/php/movim/public"; + locations = { + "/favicon.ico" = { + priority = 100; + extraConfig = /* nginx */ '' + access_log off; + log_not_found off; + ''; + }; + "/robots.txt" = { + priority = 100; + extraConfig = /* nginx */ '' + access_log off; + log_not_found off; + ''; + }; + "~ /\\.(?!well-known).*" = { + priority = 210; + extraConfig = /* nginx */ '' + deny all; + ''; + }; + # Ask nginx to cache every URL starting with "/picture" + "/picture" = { + priority = 400; + tryFiles = "$uri $uri/ /index.php$is_args$args"; + extraConfig = /* nginx */ '' + set $no_cache 0; # Enable cache only there + ''; + }; + "/" = { + priority = 490; + tryFiles = "$uri $uri/ /index.php$is_args$args"; + extraConfig = /* nginx */ '' + # https://github.com/movim/movim/issues/314 + add_header Content-Security-Policy "default-src 'self'; img-src 'self' aesgcm: https:; media-src 'self' aesgcm: https:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"; + set $no_cache 1; + ''; + }; + "~ \\.php$" = { + priority = 500; + tryFiles = "$uri =404"; + extraConfig = /* nginx */ '' + include ${config.services.nginx.package}/conf/fastcgi.conf; + add_header X-Cache $upstream_cache_status; + fastcgi_ignore_headers "Cache-Control" "Expires" "Set-Cookie"; + fastcgi_cache nginx_cache; + fastcgi_cache_valid any 7d; + fastcgi_cache_bypass $no_cache; + fastcgi_no_cache $no_cache; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_index index.php; + fastcgi_pass unix:${fpm.socket}; + ''; + }; + "/ws/" = { + priority = 900; + proxyPass = "http://${cfg.settings.DAEMON_INTERFACE}:${builtins.toString cfg.port}/"; + proxyWebsockets = true; + recommendedProxySettings = true; + extraConfig = /* nginx */ '' + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + ''; + }; + }; + extraConfig = /* ngnix */ '' + index index.php; + ''; + } + ]; + }; + + mysql = mkIf (cfg.database.createLocally && cfg.database.type == "mysql") { + enable = mkDefault true; + package = mkDefault pkgs.mariadb; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [{ + name = cfg.user; + ensureDBOwnership = true; + }]; + }; + + postgresql = mkIf (cfg.database.createLocally && cfg.database.type == "postgresql") { + enable = mkDefault true; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [{ + name = cfg.user; + ensureDBOwnership = true; + }]; + authentication = '' + host ${cfg.database.name} ${cfg.database.user} localhost trust + ''; + }; + + phpfpm.pools.${pool} = + let + socketOwner = + if (cfg.nginx != null) + then config.services.nginx.user + else cfg.user; + in + { + phpPackage = package.php; + user = cfg.user; + group = cfg.group; + + phpOptions = '' + error_log = 'stderr' + log_errors = on + ''; + + settings = { + "listen.owner" = socketOwner; + "listen.group" = cfg.group; + "listen.mode" = "0660"; + "catch_workers_output" = true; + } // cfg.poolConfig; + }; + }; + + systemd = { + services.movim-data-setup = { + description = "Movim setup: .env file, databases init, cache reload"; + wantedBy = [ "multi-user.target" ]; + requiredBy = [ "${phpExecutionUnit}.service" ]; + before = [ "${phpExecutionUnit}.service" ]; + after = lib.optional cfg.database.createLocally dbService; + requires = lib.optional cfg.database.createLocally dbService; + + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.group; + UMask = "077"; + } // lib.optionalAttrs (cfg.secretFile != null) { + LoadCredential = "env-secrets:${cfg.secretFile}"; + }; + + script = '' + # Env vars + rm -f ${cfg.dataDir}/.env + cp --no-preserve=all ${configFile} ${cfg.dataDir}/.env + echo -e '\n' >> ${cfg.dataDir}/.env + if [[ -f "$CREDENTIALS_DIRECTORY/env-secrets" ]]; then + cat "$CREDENTIALS_DIRECTORY/env-secrets" >> ${cfg.dataDir}/.env + echo -e '\n' >> ${cfg.dataDir}/.env + fi + + # Caches, logs + mkdir -p ${cfg.dataDir}/public/cache ${cfg.logDir} ${cfg.runtimeDir}/cache + chmod -R ug+rw ${cfg.dataDir}/public/cache + chmod -R ug+rw ${cfg.logDir} + chmod -R ug+rwx ${cfg.runtimeDir}/cache + + # Migrations + MOVIM_VERSION="${package.version}" + if [[ ! -f "${cfg.dataDir}/.migration-version" ]] || [[ "$MOVIM_VERSION" != "$(<${cfg.dataDir}/.migration-version)" ]]; then + ${package}/bin/movim-composer movim:migrate && echo $MOVIM_VERSION > ${cfg.dataDir}/.migration-version + fi + '' + + lib.optionalString (podConfigFlags != "") ( + let + flags = lib.concatStringsSep " " + ([ "--no-interaction" ] + ++ lib.optional cfg.debug "-vvv" + ++ lib.optional (!cfg.debug && cfg.verbose) "-v"); + in + '' + ${lib.getExe package} config ${podConfigFlags} + '' + ); + }; + + services.movim = { + description = "Movim daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "movim-data-setup.service" ]; + requires = [ "movim-data-setup.service" ] + ++ lib.optional cfg.database.createLocally dbService; + environment = { + PUBLIC_URL = "//${cfg.domain}"; + WS_PORT = builtins.toString cfg.port; + }; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + WorkingDirectory = "${package}/share/php/movim"; + ExecStart = "${lib.getExe package} start"; + }; + }; + + services.${phpExecutionUnit} = { + after = [ "movim-data-setup.service" ]; + requires = [ "movim-data-setup.service" ] + ++ lib.optional cfg.database.createLocally dbService; + }; + + tmpfiles.settings."10-movim" = with cfg; { + "${dataDir}".d = { inherit user group; mode = "0710"; }; + "${dataDir}/public".d = { inherit user group; mode = "0750"; }; + "${dataDir}/public/cache".d = { inherit user group; mode = "0750"; }; + "${runtimeDir}".d = { inherit user group; mode = "0700"; }; + "${runtimeDir}/cache".d = { inherit user group; mode = "0700"; }; + "${logDir}".d = { inherit user group; mode = "0700"; }; + }; + }; + }; +} diff --git a/nixos/modules/services/web-apps/outline.nix b/nixos/modules/services/web-apps/outline.nix index 09dd6f83f39ac..891d78d4045b4 100644 --- a/nixos/modules/services/web-apps/outline.nix +++ b/nixos/modules/services/web-apps/outline.nix @@ -784,7 +784,7 @@ in # onboarding files: WorkingDirectory = "${cfg.package}/share/outline"; # In case this directory is not in /var/lib/outline, it needs to be made writable explicitly - ReadWritePaths = [ cfg.storage.localRootDir ]; + ReadWritePaths = lib.mkIf (cfg.storage.storageType == "local") [ cfg.storage.localRootDir ]; }; }; }; diff --git a/nixos/modules/services/web-apps/silverbullet.nix b/nixos/modules/services/web-apps/silverbullet.nix new file mode 100644 index 0000000000000..a0c6ee34d262f --- /dev/null +++ b/nixos/modules/services/web-apps/silverbullet.nix @@ -0,0 +1,123 @@ +{ config +, pkgs +, lib +, ... +}: +let + cfg = config.services.silverbullet; + defaultUser = "silverbullet"; + defaultGroup = defaultUser; + defaultSpaceDir = "/var/lib/silverbullet"; +in +{ + options = { + services.silverbullet = { + enable = lib.mkEnableOption (lib.mdDoc "Silverbullet, an open-source, self-hosted, offline-capable Personal Knowledge Management (PKM) web application."); + + package = lib.mkPackageOptionMD pkgs "silverbullet" { }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc "Open port in the firewall."; + }; + + listenPort = lib.mkOption { + type = lib.types.int; + default = 3000; + description = lib.mdDoc "Port to listen on."; + }; + + listenAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + description = lib.mdDoc "Address or hostname to listen on. Defaults to 127.0.0.1."; + }; + + spaceDir = lib.mkOption { + type = lib.types.path; + default = defaultSpaceDir; + example = "/home/yourUser/silverbullet"; + description = lib.mdDoc '' + Folder to store Silverbullet's space/workspace. + By default it is located at `${defaultSpaceDir}`. + ''; + }; + + user = lib.mkOption { + type = lib.types.str; + default = defaultUser; + example = "yourUser"; + description = lib.mdDoc '' + The user to run Silverbullet as. + By default, a user named `${defaultUser}` will be created whose space + directory is [spaceDir](#opt-services.silverbullet.spaceDir). + ''; + }; + + group = lib.mkOption { + type = lib.types.str; + default = defaultGroup; + example = "yourGroup"; + description = lib.mdDoc '' + The group to run Silverbullet under. + By default, a group named `${defaultGroup}` will be created. + ''; + }; + + envFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + default = null; + example = "/etc/silverbullet.env"; + description = lib.mdDoc '' + File containing extra environment variables. For example: + + ``` + SB_USER=user:password + SB_AUTH_TOKEN=abcdefg12345 + ``` + ''; + }; + + extraArgs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = [ "--db /path/to/silverbullet.db" ]; + description = lib.mdDoc "Extra arguments passed to silverbullet."; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.silverbullet = { + description = "Silverbullet service"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + preStart = lib.mkIf (!lib.hasPrefix "/var/lib/" cfg.spaceDir) "mkdir -p '${cfg.spaceDir}'"; + serviceConfig = { + Type = "simple"; + User = "${cfg.user}"; + Group = "${cfg.group}"; + EnvironmentFile = lib.mkIf (cfg.envFile != null) "${cfg.envFile}"; + StateDirectory = lib.mkIf (lib.hasPrefix "/var/lib/" cfg.spaceDir) (lib.last (lib.splitString "/" cfg.spaceDir)); + ExecStart = "${lib.getExe cfg.package} --port ${toString cfg.listenPort} --hostname '${cfg.listenAddress}' '${cfg.spaceDir}' " + lib.concatStringsSep " " cfg.extraArgs; + Restart = "on-failure"; + }; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.listenPort ]; + }; + + users.users.${defaultUser} = lib.mkIf (cfg.user == defaultUser) { + isSystemUser = true; + group = cfg.group; + description = "Silverbullet daemon user"; + }; + + users.groups.${defaultGroup} = lib.mkIf (cfg.group == defaultGroup) { }; + }; + + meta.maintainers = with lib.maintainers; [ aorith ]; +} diff --git a/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixos/modules/services/x11/desktop-managers/budgie.nix index 466ef5c565b7e..d6e6bb2fa14e8 100644 --- a/nixos/modules/services/x11/desktop-managers/budgie.nix +++ b/nixos/modules/services/x11/desktop-managers/budgie.nix @@ -43,6 +43,8 @@ let budgie-control-center = pkgs.budgie.budgie-control-center.override { enableSshSocket = config.services.openssh.startWhenNeeded; }; + + notExcluded = pkg: (!(lib.elem pkg config.environment.budgie.excludePackages)); in { meta.maintainers = lib.teams.budgie.members; @@ -91,7 +93,7 @@ in { }; config = mkIf cfg.enable { - services.xserver.displayManager.sessionPackages = with pkgs; [ + services.displayManager.sessionPackages = with pkgs; [ budgie.budgie-desktop ]; @@ -160,7 +162,7 @@ in { ++ cfg.sessionPath; # Both budgie-desktop-view and nemo defaults to this emulator. - programs.gnome-terminal.enable = mkDefault true; + programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.gnome.gnome-terminal); # Fonts. fonts.packages = [ diff --git a/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixos/modules/services/x11/desktop-managers/cinnamon.nix index f5a6c05865c47..6983b51376fd4 100644 --- a/nixos/modules/services/x11/desktop-managers/cinnamon.nix +++ b/nixos/modules/services/x11/desktop-managers/cinnamon.nix @@ -60,7 +60,7 @@ in config = mkMerge [ (mkIf cfg.enable { - services.xserver.displayManager.sessionPackages = [ pkgs.cinnamon.cinnamon-common ]; + services.displayManager.sessionPackages = [ pkgs.cinnamon.cinnamon-common ]; services.xserver.displayManager.lightdm.greeters.slick = { enable = mkDefault true; @@ -95,7 +95,7 @@ in ''; # Default services - services.blueman.enable = mkDefault true; + services.blueman.enable = mkDefault (notExcluded pkgs.blueman); hardware.bluetooth.enable = mkDefault true; hardware.pulseaudio.enable = mkDefault true; security.polkit.enable = true; @@ -228,10 +228,10 @@ in }) (mkIf serviceCfg.apps.enable { - programs.geary.enable = mkDefault true; - programs.gnome-disks.enable = mkDefault true; - programs.gnome-terminal.enable = mkDefault true; - programs.file-roller.enable = mkDefault true; + programs.geary.enable = mkDefault (notExcluded pkgs.gnome.geary); + programs.gnome-disks.enable = mkDefault (notExcluded pkgs.gnome.gnome-disk-utility); + programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.gnome.gnome-terminal); + programs.file-roller.enable = mkDefault (notExcluded pkgs.gnome.file-roller); environment.systemPackages = with pkgs // pkgs.gnome // pkgs.cinnamon; utils.removePackagesByName [ # cinnamon team apps diff --git a/nixos/modules/services/x11/desktop-managers/deepin.nix b/nixos/modules/services/x11/desktop-managers/deepin.nix index 902e3a9317dd1..61f6fece58708 100644 --- a/nixos/modules/services/x11/desktop-managers/deepin.nix +++ b/nixos/modules/services/x11/desktop-managers/deepin.nix @@ -38,8 +38,8 @@ in config = mkIf cfg.enable { - services.xserver.displayManager.sessionPackages = [ pkgs.deepin.dde-session ]; - services.xserver.displayManager.defaultSession = mkDefault "dde-x11"; + services.displayManager.sessionPackages = [ pkgs.deepin.dde-session ]; + services.displayManager.defaultSession = mkDefault "dde-x11"; # Update the DBus activation environment after launching the desktop manager. services.xserver.displayManager.sessionCommands = '' diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix index 33d0a7b526436..896d8dcbff40f 100644 --- a/nixos/modules/services/x11/desktop-managers/default.nix +++ b/nixos/modules/services/x11/desktop-managers/default.nix @@ -87,7 +87,7 @@ in default = null; example = "none"; description = lib.mdDoc '' - **Deprecated**, please use [](#opt-services.xserver.displayManager.defaultSession) instead. + **Deprecated**, please use [](#opt-services.displayManager.defaultSession) instead. Default desktop manager loaded if none have been chosen. ''; diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix index 28dd408c923c8..d241c63436faa 100644 --- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix +++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix @@ -54,7 +54,7 @@ in "/share/locale" ]; - services.xserver.displayManager.sessionPackages = [ pkgs.enlightenment.enlightenment ]; + services.displayManager.sessionPackages = [ pkgs.enlightenment.enlightenment ]; services.xserver.displayManager.sessionCommands = '' if test "$XDG_CURRENT_DESKTOP" = "Enlightenment"; then diff --git a/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixos/modules/services/x11/desktop-managers/gnome.nix index 2cf9bc2eac37e..cc959bcf7bd58 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome.nix @@ -261,7 +261,7 @@ in services.gnome.core-shell.enable = true; services.gnome.core-utilities.enable = mkDefault true; - services.xserver.displayManager.sessionPackages = [ pkgs.gnome.gnome-session.sessions ]; + services.displayManager.sessionPackages = [ pkgs.gnome.gnome-session.sessions ]; environment.extraInit = '' ${concatMapStrings (p: '' @@ -285,7 +285,7 @@ in }) (mkIf flashbackEnabled { - services.xserver.displayManager.sessionPackages = + services.displayManager.sessionPackages = let wmNames = map (wm: wm.wmName) flashbackWms; namesAreUnique = lib.unique wmNames == wmNames; diff --git a/nixos/modules/services/x11/desktop-managers/lumina.nix b/nixos/modules/services/x11/desktop-managers/lumina.nix index 7b694106bf7ee..9df9fe42a1ff6 100644 --- a/nixos/modules/services/x11/desktop-managers/lumina.nix +++ b/nixos/modules/services/x11/desktop-managers/lumina.nix @@ -27,7 +27,7 @@ in config = mkIf cfg.enable { - services.xserver.displayManager.sessionPackages = [ + services.displayManager.sessionPackages = [ pkgs.lumina.lumina ]; diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix index 957eac7848e7f..e475442b9ef47 100644 --- a/nixos/modules/services/x11/desktop-managers/mate.nix +++ b/nixos/modules/services/x11/desktop-managers/mate.nix @@ -49,7 +49,7 @@ in config = mkMerge [ (mkIf (cfg.enable || cfg.enableWaylandSession) { - services.xserver.displayManager.sessionPackages = [ + services.displayManager.sessionPackages = [ pkgs.mate.mate-session-manager ]; @@ -103,7 +103,7 @@ in environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${pkgs.mate.mate-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas"; environment.systemPackages = [ pkgs.mate.mate-wayland-session ]; - services.xserver.displayManager.sessionPackages = [ pkgs.mate.mate-wayland-session ]; + services.displayManager.sessionPackages = [ pkgs.mate.mate-wayland-session ]; }) ]; } diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix index 2cfdc69b86e06..2115f8f0ab235 100644 --- a/nixos/modules/services/x11/desktop-managers/pantheon.nix +++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix @@ -12,6 +12,7 @@ let extraGSettingsOverrides = cfg.extraGSettingsOverrides; }; + notExcluded = pkg: (!(lib.elem pkg config.environment.pantheon.excludePackages)); in { @@ -96,7 +97,7 @@ in pkgs.pantheon.pantheon-agent-geoclue2 ] config.environment.pantheon.excludePackages; - services.xserver.displayManager.sessionPackages = [ pkgs.pantheon.elementary-session-settings ]; + services.displayManager.sessionPackages = [ pkgs.pantheon.elementary-session-settings ]; # Ensure lightdm is used when Pantheon is enabled # Without it screen locking will be nonfunctional because of the use of lightlocker @@ -109,7 +110,7 @@ in # Without this, elementary LightDM greeter will pre-select non-existent `default` session # https://github.com/elementary/greeter/issues/368 - services.xserver.displayManager.defaultSession = mkDefault "pantheon"; + services.displayManager.defaultSession = mkDefault "pantheon"; services.xserver.displayManager.sessionCommands = '' if test "$XDG_CURRENT_DESKTOP" = "Pantheon"; then @@ -190,22 +191,6 @@ in "org.gnome.SettingsDaemon.XSettings.service" ]; - # https://github.com/elementary/gala/issues/1826#issuecomment-1890461298 - systemd.user.services."io.elementary.gala.daemon@" = { - unitConfig = { - Description = "Gala Daemon"; - BindsTo = "io.elementary.gala@.service"; - After = "io.elementary.gala@.service"; - }; - - serviceConfig = { - Type = "dbus"; - BusName = "org.pantheon.gala.daemon"; - ExecStart = "${pkgs.pantheon.gala}/bin/gala-daemon"; - Slice = "session.slice"; - }; - }; - # Global environment environment.systemPackages = (with pkgs.pantheon; [ elementary-session-settings @@ -304,8 +289,8 @@ in }) (mkIf serviceCfg.apps.enable { - programs.evince.enable = mkDefault true; - programs.file-roller.enable = mkDefault true; + programs.evince.enable = mkDefault (notExcluded pkgs.gnome.evince); + programs.file-roller.enable = mkDefault (notExcluded pkgs.gnome.file-roller); environment.systemPackages = utils.removePackagesByName ([ pkgs.gnome.gnome-font-viewer diff --git a/nixos/modules/services/x11/desktop-managers/phosh.nix b/nixos/modules/services/x11/desktop-managers/phosh.nix index 75e02130addc5..41107788db0a5 100644 --- a/nixos/modules/services/x11/desktop-managers/phosh.nix +++ b/nixos/modules/services/x11/desktop-managers/phosh.nix @@ -220,7 +220,7 @@ in services.gnome.core-shell.enable = true; services.gnome.core-os-services.enable = true; - services.xserver.displayManager.sessionPackages = [ cfg.package ]; + services.displayManager.sessionPackages = [ cfg.package ]; environment.etc."phosh/phoc.ini".source = if builtins.isPath cfg.phocConfig then cfg.phocConfig diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix index f516a29fb5db3..bb6e5873deff9 100644 --- a/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -357,7 +357,7 @@ in pkgs.media-player-info ]; - services.xserver.displayManager.sddm = { + services.displayManager.sddm = { theme = mkDefault "breeze"; }; @@ -403,16 +403,16 @@ in system.nixos-generate-config.desktopConfiguration = [ '' # Enable the Plasma 5 Desktop Environment. - services.xserver.displayManager.sddm.enable = true; + services.displayManager.sddm.enable = true; services.xserver.desktopManager.plasma5.enable = true; '' ]; - services.xserver.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-workspace ]; + services.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-workspace ]; # Default to be `plasma` (X11) instead of `plasmawayland`, since plasma wayland currently has # many tiny bugs. # See: https://github.com/NixOS/nixpkgs/issues/143272 - services.xserver.displayManager.defaultSession = mkDefault "plasma"; + services.displayManager.defaultSession = mkDefault "plasma"; environment.systemPackages = with pkgs.plasma5Packages; @@ -538,7 +538,7 @@ in }; }; - services.xserver.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-mobile ]; + services.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-mobile ]; }) # Plasma Bigscreen @@ -559,7 +559,7 @@ in kdeconnect-kde ]; - services.xserver.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-bigscreen ]; + services.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-bigscreen ]; # required for plasma-remotecontrollers to work correctly hardware.uinput.enable = true; diff --git a/nixos/modules/services/x11/desktop-managers/surf-display.nix b/nixos/modules/services/x11/desktop-managers/surf-display.nix index 38ebb9d02b4ac..e5f2c76f4ac25 100644 --- a/nixos/modules/services/x11/desktop-managers/surf-display.nix +++ b/nixos/modules/services/x11/desktop-managers/surf-display.nix @@ -119,7 +119,7 @@ in { }; config = mkIf cfg.enable { - services.xserver.displayManager.sessionPackages = [ + services.displayManager.sessionPackages = [ pkgs.surf-display ]; diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix index c22048c6692e9..129bafefabe99 100644 --- a/nixos/modules/services/x11/display-managers/default.nix +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -14,7 +14,6 @@ with lib; let cfg = config.services.xserver; - opt = options.services.xserver; xorg = pkgs.xorg; fontconfig = config.fonts.fontconfig; @@ -70,14 +69,14 @@ let source ~/.xprofile fi - ${optionalString cfg.displayManager.job.logToJournal '' + ${optionalString config.services.displayManager.logToJournal '' if [ -z "$_DID_SYSTEMD_CAT" ]; then export _DID_SYSTEMD_CAT=1 exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$@" fi ''} - ${optionalString cfg.displayManager.job.logToFile '' + ${optionalString config.services.displayManager.logToFile '' exec &> >(tee ~/.xsession-errors) ''} @@ -130,41 +129,6 @@ let exit 1 fi ''; - - installedSessions = pkgs.runCommand "desktops" - { # trivial derivation - preferLocalBuild = true; - allowSubstitutes = false; - } - '' - mkdir -p "$out/share/"{xsessions,wayland-sessions} - - ${concatMapStrings (pkg: '' - for n in ${concatStringsSep " " pkg.providedSessions}; do - if ! test -f ${pkg}/share/wayland-sessions/$n.desktop -o \ - -f ${pkg}/share/xsessions/$n.desktop; then - echo "Couldn't find provided session name, $n.desktop, in session package ${pkg.name}:" - echo " ${pkg}" - return 1 - fi - done - - if test -d ${pkg}/share/xsessions; then - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${pkg}/share/xsessions $out/share/xsessions - fi - if test -d ${pkg}/share/wayland-sessions; then - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${pkg}/share/wayland-sessions $out/share/wayland-sessions - fi - '') cfg.displayManager.sessionPackages} - ''; - - dmDefault = cfg.desktopManager.default; - # fallback default for cases when only default wm is set - dmFallbackDefault = if dmDefault != null then dmDefault else "none"; - wmDefault = cfg.windowManager.default; - - defaultSessionFromLegacyOptions = dmFallbackDefault + optionalString (wmDefault != null && wmDefault != "none") "+${wmDefault}"; - in { @@ -215,35 +179,6 @@ in ''; }; - hiddenUsers = mkOption { - type = types.listOf types.str; - default = [ "nobody" ]; - description = lib.mdDoc '' - A list of users which will not be shown in the display manager. - ''; - }; - - sessionPackages = mkOption { - type = with types; listOf (package // { - description = "package with provided sessions"; - check = p: assertMsg - (package.check p && p ? providedSessions - && p.providedSessions != [] && all isString p.providedSessions) - '' - Package, '${p.name}', did not specify any session names, as strings, in - 'passthru.providedSessions'. This is required when used as a session package. - - The session names can be looked up in: - ${p}/share/xsessions - ${p}/share/wayland-sessions - ''; - }); - default = []; - description = lib.mdDoc '' - A list of packages containing x11 or wayland session files to be passed to the display manager. - ''; - }; - session = mkOption { default = []; type = types.listOf types.attrs; @@ -274,51 +209,6 @@ in ''; }; - sessionData = mkOption { - description = lib.mdDoc "Data exported for display managers’ convenience"; - internal = true; - default = {}; - apply = val: { - wrapper = xsessionWrapper; - desktops = installedSessions; - sessionNames = concatMap (p: p.providedSessions) cfg.displayManager.sessionPackages; - # We do not want to force users to set defaultSession when they have only single DE. - autologinSession = - if cfg.displayManager.defaultSession != null then - cfg.displayManager.defaultSession - else if cfg.displayManager.sessionData.sessionNames != [] then - head cfg.displayManager.sessionData.sessionNames - else - null; - }; - }; - - defaultSession = mkOption { - type = with types; nullOr str // { - description = "session name"; - check = d: - assertMsg (d != null -> (str.check d && elem d cfg.displayManager.sessionData.sessionNames)) '' - Default graphical session, '${d}', not found. - Valid names for 'services.xserver.displayManager.defaultSession' are: - ${concatStringsSep "\n " cfg.displayManager.sessionData.sessionNames} - ''; - }; - default = - if dmDefault != null || wmDefault != null then - defaultSessionFromLegacyOptions - else - null; - defaultText = literalMD '' - Taken from display manager settings or window manager settings, if either is set. - ''; - example = "gnome"; - description = lib.mdDoc '' - Graphical session to pre-select in the session chooser (only effective for GDM, LightDM and SDDM). - - On GDM, LightDM and SDDM, it will also be used as a session for auto-login. - ''; - }; - importedVariables = mkOption { type = types.listOf (types.strMatching "[a-zA-Z_][a-zA-Z0-9_]*"); visible = false; @@ -327,106 +217,19 @@ in ''; }; - job = { - - preStart = mkOption { - type = types.lines; - default = ""; - example = "rm -f /var/log/my-display-manager.log"; - description = lib.mdDoc "Script executed before the display manager is started."; - }; - - execCmd = mkOption { - type = types.str; - example = literalExpression ''"''${pkgs.lightdm}/bin/lightdm"''; - description = lib.mdDoc "Command to start the display manager."; - }; - - environment = mkOption { - type = types.attrsOf types.unspecified; - default = {}; - description = lib.mdDoc "Additional environment variables needed by the display manager."; - }; - - logToFile = mkOption { - type = types.bool; - default = false; - description = lib.mdDoc '' - Whether the display manager redirects the output of the - session script to {file}`~/.xsession-errors`. - ''; - }; - - logToJournal = mkOption { - type = types.bool; - default = true; - description = lib.mdDoc '' - Whether the display manager redirects the output of the - session script to the systemd journal. - ''; - }; - - }; - - # Configuration for automatic login. Common for all DM. - autoLogin = mkOption { - type = types.submodule ({ config, options, ... }: { - options = { - enable = mkOption { - type = types.bool; - default = config.user != null; - defaultText = literalExpression "config.${options.user} != null"; - description = lib.mdDoc '' - Automatically log in as {option}`autoLogin.user`. - ''; - }; - - user = mkOption { - type = types.nullOr types.str; - default = null; - description = lib.mdDoc '' - User to be used for the automatic login. - ''; - }; - }; - }); - - default = {}; - description = lib.mdDoc '' - Auto login configuration attrset. - ''; - }; - }; }; config = { assertions = [ - { assertion = cfg.displayManager.autoLogin.enable -> cfg.displayManager.autoLogin.user != null; - message = '' - services.xserver.displayManager.autoLogin.enable requires services.xserver.displayManager.autoLogin.user to be set - ''; - } { assertion = cfg.desktopManager.default != null || cfg.windowManager.default != null -> cfg.displayManager.defaultSession == defaultSessionFromLegacyOptions; - message = "You cannot use both services.xserver.displayManager.defaultSession option and legacy options (services.xserver.desktopManager.default and services.xserver.windowManager.default)."; + message = "You cannot use both services.displayManager.defaultSession option and legacy options (services.xserver.desktopManager.default and services.xserver.windowManager.default)."; } ]; - warnings = - mkIf (dmDefault != null || wmDefault != null) [ - '' - The following options are deprecated: - ${concatStringsSep "\n " (map ({c, t}: t) (filter ({c, t}: c != null) [ - { c = dmDefault; t = "- services.xserver.desktopManager.default"; } - { c = wmDefault; t = "- services.xserver.windowManager.default"; } - ]))} - Please use - services.xserver.displayManager.defaultSession = "${defaultSessionFromLegacyOptions}"; - instead. - '' - ]; + services.displayManager.sessionData.wrapper = xsessionWrapper; services.xserver.displayManager.xserverBin = "${xorg.xorgserver.out}/bin/X"; @@ -449,7 +252,7 @@ in # Create desktop files and scripts for starting sessions for WMs/DMs # that do not have upstream session files (those defined using services.{display,desktop,window}Manager.session options). - services.xserver.displayManager.sessionPackages = + services.displayManager.sessionPackages = let dms = filter (s: s.manage == "desktop") cfg.displayManager.session; wms = filter (s: s.manage == "window") cfg.displayManager.session; @@ -511,20 +314,14 @@ in ) (cartesianProductOfSets { dm = dms; wm = wms; }) ); - - # Make xsessions and wayland sessions available in XDG_DATA_DIRS - # as some programs have behavior that depends on them being present - environment.sessionVariables.XDG_DATA_DIRS = lib.mkIf (cfg.displayManager.sessionPackages != [ ]) [ - "${cfg.displayManager.sessionData.desktops}/share" - ]; }; imports = [ (mkRemovedOptionModule [ "services" "xserver" "displayManager" "desktopManagerHandlesLidAndPower" ] "The option is no longer necessary because all display managers have already delegated lid management to systemd.") - (mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logsXsession" ] [ "services" "xserver" "displayManager" "job" "logToFile" ]) - (mkRenamedOptionModule [ "services" "xserver" "displayManager" "logToJournal" ] [ "services" "xserver" "displayManager" "job" "logToJournal" ]) - (mkRenamedOptionModule [ "services" "xserver" "displayManager" "extraSessionFilesPackages" ] [ "services" "xserver" "displayManager" "sessionPackages" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "job" "logsXsession" ] [ "services" "displayManager" "logToFile" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "logToJournal" ] [ "services" "displayManager" "logToJournal" ]) + (mkRenamedOptionModule [ "services" "xserver" "displayManager" "extraSessionFilesPackages" ] [ "services" "displayManager" "sessionPackages" ]) ]; } diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 400e5601dc59a..6bdfe9ea6f8cd 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -32,7 +32,7 @@ let load-module module-position-event-sounds ''; - defaultSessionName = config.services.xserver.displayManager.defaultSession; + defaultSessionName = config.services.displayManager.defaultSession; setSessionScript = pkgs.callPackage ./account-service-util.nix { }; in @@ -41,14 +41,12 @@ in imports = [ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "gdm" "autoLogin" "enable" ] [ "services" - "xserver" "displayManager" "autoLogin" "enable" ]) (mkRenamedOptionModule [ "services" "xserver" "displayManager" "gdm" "autoLogin" "user" ] [ "services" - "xserver" "displayManager" "autoLogin" "user" @@ -148,14 +146,14 @@ in services.xserver.display = null; services.xserver.verbose = null; - services.xserver.displayManager.job = + services.displayManager = { environment = { GDM_X_SERVER_EXTRA_ARGS = toString (filter (arg: arg != "-terminate") cfg.xserverArgs); XDG_DATA_DIRS = lib.makeSearchPath "share" [ gdm # for gnome-login.session - cfg.sessionData.desktops + config.services.displayManager.sessionData.desktops pkgs.gnome.gnome-control-center # for accessibility icon pkgs.gnome.adwaita-icon-theme pkgs.hicolor-icon-theme # empty icon theme as a base @@ -169,7 +167,7 @@ in execCmd = "exec ${gdm}/bin/gdm"; preStart = optionalString (defaultSessionName != null) '' # Set default session in session chooser to a specified values – basically ignore session history. - ${setSessionScript}/bin/set-session ${cfg.sessionData.autologinSession} + ${setSessionScript}/bin/set-session ${config.services.displayManager.sessionData.autologinSession} ''; }; @@ -265,14 +263,14 @@ in daemon = mkMerge [ { WaylandEnable = cfg.gdm.wayland; } # nested if else didn't work - (mkIf (cfg.autoLogin.enable && cfg.gdm.autoLogin.delay != 0 ) { + (mkIf (config.services.displayManager.autoLogin.enable && cfg.gdm.autoLogin.delay != 0 ) { TimedLoginEnable = true; - TimedLogin = cfg.autoLogin.user; + TimedLogin = config.services.displayManager.autoLogin.user; TimedLoginDelay = cfg.gdm.autoLogin.delay; }) - (mkIf (cfg.autoLogin.enable && cfg.gdm.autoLogin.delay == 0 ) { + (mkIf (config.services.displayManager.autoLogin.enable && cfg.gdm.autoLogin.delay == 0 ) { AutomaticLoginEnable = true; - AutomaticLogin = cfg.autoLogin.user; + AutomaticLogin = config.services.displayManager.autoLogin.user; }) ]; debug = mkIf cfg.gdm.debug { @@ -282,7 +280,7 @@ in environment.etc."gdm/custom.conf".source = configFile; - environment.etc."gdm/Xsession".source = config.services.xserver.displayManager.sessionData.wrapper; + environment.etc."gdm/Xsession".source = config.services.displayManager.sessionData.wrapper; # GDM LFS PAM modules, adapted somehow to NixOS security.pam.services = { diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix index f4195c4c2dc39..8702d0b97ed2e 100644 --- a/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix +++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix @@ -60,7 +60,7 @@ in Note that this greeter starts only the default X session. You can configure the default X session using - [](#opt-services.xserver.displayManager.defaultSession). + [](#opt-services.displayManager.defaultSession). ''; }; diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix index dede7680ecb3a..b2ea8e6d94f21 100644 --- a/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix +++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix @@ -22,7 +22,7 @@ in Note that this greeter starts only the default X session. You can configure the default X session using - [](#opt-services.xserver.displayManager.defaultSession). + [](#opt-services.displayManager.defaultSession). ''; }; @@ -81,7 +81,7 @@ in { assertion = dmcfg.defaultSession != null; message = '' - Please set: services.xserver.displayManager.defaultSession + Please set: services.displayManager.defaultSession ''; } ]; diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 548d3c5bc46a5..cb6365bace352 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -5,9 +5,9 @@ with lib; let xcfg = config.services.xserver; - dmcfg = xcfg.displayManager; + dmcfg = config.services.displayManager; xEnv = config.systemd.services.display-manager.environment; - cfg = dmcfg.lightdm; + cfg = xcfg.displayManager.lightdm; sessionData = dmcfg.sessionData; setSessionScript = pkgs.callPackage ./account-service-util.nix { }; @@ -26,7 +26,7 @@ let else additionalArgs="-logfile /var/log/X.$display.log" fi - exec ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} $additionalArgs "$@" + exec ${xcfg.displayManager.xserverBin} ${toString xcfg.displayManager.xserverArgs} $additionalArgs "$@" ''; usersConf = writeText "users.conf" @@ -58,10 +58,10 @@ let autologin-user-timeout = ${toString cfg.autoLogin.timeout} autologin-session = ${sessionData.autologinSession} ''} - ${optionalString (dmcfg.setupCommands != "") '' + ${optionalString (xcfg.displayManager.setupCommands != "") '' display-setup-script=${pkgs.writeScript "lightdm-display-setup" '' #!${pkgs.bash}/bin/bash - ${dmcfg.setupCommands} + ${xcfg.displayManager.setupCommands} ''} ''} ${cfg.extraSeatDefaults} @@ -86,14 +86,12 @@ in ./lightdm-greeters/mobile.nix (mkRenamedOptionModule [ "services" "xserver" "displayManager" "lightdm" "autoLogin" "enable" ] [ "services" - "xserver" "displayManager" "autoLogin" "enable" ]) (mkRenamedOptionModule [ "services" "xserver" "displayManager" "lightdm" "autoLogin" "user" ] [ "services" - "xserver" "displayManager" "autoLogin" "user" @@ -187,7 +185,7 @@ in } { assertion = dmcfg.autoLogin.enable -> sessionData.autologinSession != null; message = '' - LightDM auto-login requires that services.xserver.displayManager.defaultSession is set. + LightDM auto-login requires that services.displayManager.defaultSession is set. ''; } { assertion = !cfg.greeter.enable -> (dmcfg.autoLogin.enable && cfg.autoLogin.timeout == 0); @@ -203,12 +201,12 @@ in # Set default session in session chooser to a specified values – basically ignore session history. # Auto-login is already covered by a config value. - services.xserver.displayManager.job.preStart = optionalString (!dmcfg.autoLogin.enable && dmcfg.defaultSession != null) '' + services.displayManager.preStart = optionalString (!dmcfg.autoLogin.enable && dmcfg.defaultSession != null) '' ${setSessionScript}/bin/set-session ${dmcfg.defaultSession} ''; # setSessionScript needs session-files in XDG_DATA_DIRS - services.xserver.displayManager.job.environment.XDG_DATA_DIRS = "${dmcfg.sessionData.desktops}/share/"; + services.displayManager.environment.XDG_DATA_DIRS = "${dmcfg.sessionData.desktops}/share/"; # setSessionScript wants AccountsService systemd.services.display-manager.wants = [ @@ -216,7 +214,7 @@ in ]; # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH - services.xserver.displayManager.job.execCmd = '' + services.displayManager.execCmd = '' export PATH=${lightdm}/sbin:$PATH exec ${lightdm}/sbin/lightdm ''; diff --git a/nixos/modules/services/x11/display-managers/xpra.nix b/nixos/modules/services/x11/display-managers/xpra.nix index 3e7c6b01b3e91..ce80e013e81e2 100644 --- a/nixos/modules/services/x11/display-managers/xpra.nix +++ b/nixos/modules/services/x11/display-managers/xpra.nix @@ -226,7 +226,7 @@ in VideoRam 192000 ''; - services.xserver.displayManager.job.execCmd = '' + services.displayManager.execCmd = '' ${optionalString (cfg.pulseaudio) "export PULSE_COOKIE=/run/pulse/.config/pulse/cookie"} exec ${pkgs.xpra}/bin/xpra ${if cfg.desktop == null then "start" else "start-desktop --start=${cfg.desktop}"} \ diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix index e180f2693e0c6..527c95bb14ac3 100644 --- a/nixos/modules/services/x11/window-managers/default.nix +++ b/nixos/modules/services/x11/window-managers/default.nix @@ -77,7 +77,7 @@ in default = null; example = "wmii"; description = lib.mdDoc '' - **Deprecated**, please use [](#opt-services.xserver.displayManager.defaultSession) instead. + **Deprecated**, please use [](#opt-services.displayManager.defaultSession) instead. Default window manager loaded if none have been chosen. ''; diff --git a/nixos/modules/services/x11/window-managers/ragnarwm.nix b/nixos/modules/services/x11/window-managers/ragnarwm.nix index 7242c8b1324c4..0f4c2660b1e07 100644 --- a/nixos/modules/services/x11/window-managers/ragnarwm.nix +++ b/nixos/modules/services/x11/window-managers/ragnarwm.nix @@ -18,7 +18,7 @@ in ###### implementation config = mkIf cfg.enable { - services.xserver.displayManager.sessionPackages = [ cfg.package ]; + services.displayManager.sessionPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ]; }; diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index c5b168e608a4d..b9d39aa2b2ef2 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -639,28 +639,18 @@ in ###### implementation config = mkIf cfg.enable { + services.displayManager.enable = true; services.xserver.displayManager.lightdm.enable = let dmConf = cfg.displayManager; default = !(dmConf.gdm.enable - || dmConf.sddm.enable + || config.services.displayManager.sddm.enable || dmConf.xpra.enable || dmConf.sx.enable || dmConf.startx.enable || config.services.greetd.enable); in mkIf (default) (mkDefault true); - # so that the service won't be enabled when only startx is used - systemd.services.display-manager.enable = - let dmConf = cfg.displayManager; - noDmUsed = !(dmConf.gdm.enable - || dmConf.sddm.enable - || dmConf.xpra.enable - || dmConf.lightdm.enable); - in mkIf (noDmUsed) (mkDefault false); - - hardware.opengl.enable = mkDefault true; - services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ]; # FIXME: somehow check for unknown driver names. @@ -694,19 +684,6 @@ in # -xkbdir command line option does not seems to be passed to xkbcomp. "X11/xkb".source = "${cfg.xkb.dir}"; }) - # localectl looks into 00-keyboard.conf - //{ - "X11/xorg.conf.d/00-keyboard.conf".text = '' - Section "InputClass" - Identifier "Keyboard catchall" - MatchIsKeyboard "on" - Option "XkbModel" "${cfg.xkb.model}" - Option "XkbLayout" "${cfg.xkb.layout}" - Option "XkbOptions" "${cfg.xkb.options}" - Option "XkbVariant" "${cfg.xkb.variant}" - EndSection - ''; - } # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5 // (let cfgPath = "X11/xorg.conf.d/10-evdev.conf"; in { @@ -726,31 +703,12 @@ in xorg.xprop xorg.xauth pkgs.xterm - pkgs.xdg-utils xorg.xf86inputevdev.out # get evdev.4 man page - pkgs.nixos-icons # needed for gnome and pantheon about dialog, nixos-manual and maybe more ] config.services.xserver.excludePackages ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; environment.pathsToLink = [ "/share/X11" ]; - xdg = { - autostart.enable = true; - menus.enable = true; - mime.enable = true; - icons.enable = true; - }; - - # The default max inotify watches is 8192. - # Nowadays most apps require a good number of inotify watches, - # the value below is used by default on several other distros. - boot.kernel.sysctl."fs.inotify.max_user_instances" = mkDefault 524288; - boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288; - - programs.gnupg.agent.pinentryPackage = lib.mkOverride 1100 pkgs.pinentry-gnome3; - - systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; - systemd.services.display-manager = { description = "Display Manager"; @@ -761,17 +719,17 @@ in environment = optionalAttrs config.hardware.opengl.setLdLibraryPath { LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.addOpenGLRunpath.driverLink ]; } - // cfg.displayManager.job.environment; + // config.services.displayManager.environment; preStart = '' - ${cfg.displayManager.job.preStart} + ${config.services.displayManager.preStart} rm -f /tmp/.X0-lock ''; # TODO: move declaring the systemd service to its own mkIf - script = mkIf (config.systemd.services.display-manager.enable == true) "${cfg.displayManager.job.execCmd}"; + script = mkIf (config.systemd.services.display-manager.enable == true) "${config.services.displayManager.execCmd}"; # Stop restarting if the display manager stops (crashes) 2 times # in one minute. Starting X typically takes 3-4s. @@ -910,7 +868,6 @@ in ${cfg.extraConfig} ''; - fonts.enableDefaultPackages = mkDefault true; fonts.packages = [ (if cfg.upscaleDefaultCursor then fontcursormisc_hidpi else pkgs.xorg.fontcursormisc) pkgs.xorg.fontmiscmisc |