about summary refs log tree commit diff
path: root/nixos/modules/services
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/admin/pgadmin.nix2
-rw-r--r--nixos/modules/services/backup/borgbackup.nix3
-rw-r--r--nixos/modules/services/cluster/patroni/default.nix36
-rw-r--r--nixos/modules/services/continuous-integration/gitlab-runner.nix15
-rw-r--r--nixos/modules/services/continuous-integration/woodpecker/agents.nix2
-rw-r--r--nixos/modules/services/continuous-integration/woodpecker/server.nix2
-rw-r--r--nixos/modules/services/databases/monetdb.nix2
-rw-r--r--nixos/modules/services/desktop-managers/lomiri.nix13
-rw-r--r--nixos/modules/services/desktop-managers/plasma6.nix4
-rw-r--r--nixos/modules/services/desktops/espanso.nix1
-rw-r--r--nixos/modules/services/desktops/gnome/gnome-keyring.nix23
-rw-r--r--nixos/modules/services/desktops/gnome/gnome-user-share.nix4
-rw-r--r--nixos/modules/services/desktops/gnome/rygel.nix8
-rw-r--r--nixos/modules/services/desktops/gnome/sushi.nix4
-rw-r--r--nixos/modules/services/desktops/playerctld.nix32
-rw-r--r--nixos/modules/services/games/armagetronad.nix2
-rw-r--r--nixos/modules/services/games/teeworlds.nix2
-rw-r--r--nixos/modules/services/hardware/auto-epp.nix2
-rw-r--r--nixos/modules/services/home-automation/ebusd.nix2
-rw-r--r--nixos/modules/services/home-automation/matter-server.nix2
-rw-r--r--nixos/modules/services/mail/roundcube.nix12
-rw-r--r--nixos/modules/services/mail/stalwart-mail.nix21
-rw-r--r--nixos/modules/services/misc/dictd.nix3
-rw-r--r--nixos/modules/services/misc/gitlab.nix7
-rw-r--r--nixos/modules/services/misc/jellyseerr.nix7
-rw-r--r--nixos/modules/services/misc/ollama.nix3
-rw-r--r--nixos/modules/services/misc/renovate.nix1
-rw-r--r--nixos/modules/services/misc/rkvm.nix2
-rw-r--r--nixos/modules/services/misc/snapper.nix26
-rw-r--r--nixos/modules/services/misc/sonarr.nix8
-rw-r--r--nixos/modules/services/misc/zoneminder.nix14
-rw-r--r--nixos/modules/services/monitoring/grafana.nix2
-rw-r--r--nixos/modules/services/monitoring/nezha-agent.nix15
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/fastly.nix41
-rw-r--r--nixos/modules/services/monitoring/smartd.nix27
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix6
-rw-r--r--nixos/modules/services/networking/blocky.nix4
-rw-r--r--nixos/modules/services/networking/cgit.nix82
-rw-r--r--nixos/modules/services/networking/cloudflare-dyndns.nix13
-rw-r--r--nixos/modules/services/networking/cloudflared.nix10
-rw-r--r--nixos/modules/services/networking/firefox-syncserver.nix2
-rw-r--r--nixos/modules/services/networking/gns3-server.nix8
-rw-r--r--nixos/modules/services/networking/mihomo.nix12
-rw-r--r--nixos/modules/services/networking/mosquitto.nix2
-rw-r--r--nixos/modules/services/networking/networkd-dispatcher.nix4
-rw-r--r--nixos/modules/services/networking/networkmanager.nix2
-rw-r--r--nixos/modules/services/networking/oink.nix1
-rw-r--r--nixos/modules/services/networking/prosody.nix70
-rw-r--r--nixos/modules/services/networking/resilio.nix2
-rw-r--r--nixos/modules/services/networking/scion/scion-control.nix10
-rw-r--r--nixos/modules/services/networking/scion/scion-daemon.nix8
-rw-r--r--nixos/modules/services/networking/scion/scion-dispatcher.nix2
-rw-r--r--nixos/modules/services/networking/scion/scion-router.nix2
-rw-r--r--nixos/modules/services/networking/smokeping.nix8
-rw-r--r--nixos/modules/services/networking/syncthing.nix9
-rw-r--r--nixos/modules/services/networking/xrdp.nix4
-rw-r--r--nixos/modules/services/search/hound.nix84
-rw-r--r--nixos/modules/services/security/sks.nix2
-rw-r--r--nixos/modules/services/security/yubikey-agent.nix2
-rw-r--r--nixos/modules/services/system/cloud-init.nix11
-rw-r--r--nixos/modules/services/torrent/rtorrent.nix2
-rw-r--r--nixos/modules/services/ttys/kmscon.nix14
-rw-r--r--nixos/modules/services/web-apps/code-server.nix2
-rw-r--r--nixos/modules/services/web-apps/eintopf.nix92
-rw-r--r--nixos/modules/services/web-apps/freshrss.nix46
-rw-r--r--nixos/modules/services/web-apps/healthchecks.nix18
-rw-r--r--nixos/modules/services/web-apps/invidious.nix2
-rw-r--r--nixos/modules/services/web-apps/keycloak.nix6
-rw-r--r--nixos/modules/services/web-apps/limesurvey.nix78
-rw-r--r--nixos/modules/services/web-apps/nextcloud.md23
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix6
-rw-r--r--nixos/modules/services/web-apps/peering-manager.nix25
-rw-r--r--nixos/modules/services/web-apps/pixelfed.nix2
-rw-r--r--nixos/modules/services/web-apps/pretalx.nix2
-rw-r--r--nixos/modules/services/web-apps/shiori.nix80
-rw-r--r--nixos/modules/services/web-apps/silverbullet.nix2
-rw-r--r--nixos/modules/services/web-apps/slskd.nix2
-rw-r--r--nixos/modules/services/web-apps/suwayomi-server.nix2
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix20
-rw-r--r--nixos/modules/services/web-servers/fcgiwrap.nix130
-rw-r--r--nixos/modules/services/x11/desktop-managers/budgie.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/cinnamon.nix14
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome.md2
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome.nix44
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix10
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix5
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix14
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix12
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/slick.nix12
-rw-r--r--nixos/modules/services/x11/window-managers/herbstluftwm.nix5
91 files changed, 983 insertions, 409 deletions
diff --git a/nixos/modules/services/admin/pgadmin.nix b/nixos/modules/services/admin/pgadmin.nix
index b3dd3c78874c2..9c430bd05e712 100644
--- a/nixos/modules/services/admin/pgadmin.nix
+++ b/nixos/modules/services/admin/pgadmin.nix
@@ -35,7 +35,7 @@ in
       default = 5050;
     };
 
-    package = mkPackageOptionMD pkgs "pgadmin4" { };
+    package = mkPackageOption pkgs "pgadmin4" { };
 
     initialEmail = mkOption {
       description = "Initial email for the pgAdmin account";
diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix
index a3c0715c9e607..abb7925e0935f 100644
--- a/nixos/modules/services/backup/borgbackup.nix
+++ b/nixos/modules/services/backup/borgbackup.nix
@@ -104,6 +104,9 @@ let
             --what="sleep" \
             --why="Scheduled backup" \
         '' + backupScript;
+      unitConfig = optionalAttrs (isLocalPath cfg.repo) {
+        RequiresMountsFor = [ cfg.repo ];
+      };
       serviceConfig = {
         User = cfg.user;
         Group = cfg.group;
diff --git a/nixos/modules/services/cluster/patroni/default.nix b/nixos/modules/services/cluster/patroni/default.nix
index d1a165603fdaa..3b563bb89fffb 100644
--- a/nixos/modules/services/cluster/patroni/default.nix
+++ b/nixos/modules/services/cluster/patroni/default.nix
@@ -10,6 +10,15 @@ let
   configFile = format.generate configFileName cfg.settings;
 in
 {
+  imports = [
+    (lib.mkRemovedOptionModule [ "services" "patroni" "raft" ] ''
+      Raft has been deprecated by upstream.
+    '')
+    (lib.mkRemovedOptionModule [ "services" "patroni" "raftPort" ] ''
+      Raft has been deprecated by upstream.
+    '')
+  ];
+
   options.services.patroni = {
 
     enable = mkEnableOption "Patroni";
@@ -68,7 +77,7 @@ in
       type = types.path;
       default = "/var/lib/patroni";
       description = ''
-        Folder where Patroni data will be written, used by Raft as well if enabled.
+        Folder where Patroni data will be written, this is where the pgpass password file will be written.
       '';
     };
 
@@ -120,22 +129,6 @@ in
       '';
     };
 
-    raft = mkOption {
-      type = types.bool;
-      default = false;
-      description = ''
-        This will configure Patroni to use its own RAFT implementation instead of using a dedicated DCS.
-      '';
-    };
-
-    raftPort = mkOption {
-      type = types.port;
-      default = 5010;
-      description = ''
-        The port on which RAFT listens.
-      '';
-    };
-
     softwareWatchdog = mkOption {
       type = types.bool;
       default = false;
@@ -178,12 +171,6 @@ in
         connect_address = "${cfg.nodeIp}:${toString cfg.restApiPort}";
       };
 
-      raft = mkIf cfg.raft {
-        data_dir = "${cfg.dataDir}/raft";
-        self_addr = "${cfg.nodeIp}:5010";
-        partner_addrs = map (ip: ip + ":5010") cfg.otherNodesIps;
-      };
-
       postgresql = {
         listen = "${cfg.nodeIp}:${toString cfg.postgresqlPort}";
         connect_address = "${cfg.nodeIp}:${toString cfg.postgresqlPort}";
@@ -235,7 +222,7 @@ in
             KillMode = "process";
           }
           (mkIf (cfg.postgresqlDataDir == "/var/lib/postgresql/${cfg.postgresqlPackage.psqlSchema}" && cfg.dataDir == "/var/lib/patroni") {
-            StateDirectory = "patroni patroni/raft postgresql postgresql/${cfg.postgresqlPackage.psqlSchema}";
+            StateDirectory = "patroni postgresql postgresql/${cfg.postgresqlPackage.psqlSchema}";
             StateDirectoryMode = "0750";
           })
         ];
@@ -251,7 +238,6 @@ in
     environment.systemPackages = [
       pkgs.patroni
       cfg.postgresqlPackage
-      (mkIf cfg.raft pkgs.python310Packages.pysyncobj)
     ];
 
     environment.etc."${configFileName}".source = configFile;
diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix
index 1771ca0b980b9..c603aff38038a 100644
--- a/nixos/modules/services/continuous-integration/gitlab-runner.nix
+++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -137,8 +137,10 @@ let
             "--builds-dir ${service.buildsDir}"
             ++ optional (service.cloneUrl != null)
             "--clone-url ${service.cloneUrl}"
-            ++ optional (service.preCloneScript != null)
-            "--pre-clone-script ${service.preCloneScript}"
+            ++ optional (service.preGetSourcesScript != null)
+            "--pre-get-sources-script ${service.preGetSourcesScript}"
+            ++ optional (service.postGetSourcesScript != null)
+            "--post-get-sources-script ${service.postGetSourcesScript}"
             ++ optional (service.preBuildScript != null)
             "--pre-build-script ${service.preBuildScript}"
             ++ optional (service.postBuildScript != null)
@@ -495,13 +497,20 @@ in {
               Whitelist allowed services.
             '';
           };
-          preCloneScript = mkOption {
+          preGetSourcesScript = mkOption {
             type = types.nullOr types.path;
             default = null;
             description = ''
               Runner-specific command script executed before code is pulled.
             '';
           };
+          postGetSourcesScript = mkOption {
+            type = types.nullOr types.path;
+            default = null;
+            description = ''
+              Runner-specific command script executed after code is pulled.
+            '';
+          };
           preBuildScript = mkOption {
             type = types.nullOr types.path;
             default = null;
diff --git a/nixos/modules/services/continuous-integration/woodpecker/agents.nix b/nixos/modules/services/continuous-integration/woodpecker/agents.nix
index ce5926a246bbe..b88bc6a0ccac0 100644
--- a/nixos/modules/services/continuous-integration/woodpecker/agents.nix
+++ b/nixos/modules/services/continuous-integration/woodpecker/agents.nix
@@ -109,7 +109,7 @@ let
   };
 in
 {
-  meta.maintainers = with lib.maintainers; [ janik ambroisie ];
+  meta.maintainers = with lib.maintainers; [ ambroisie ];
 
   options = {
     services.woodpecker-agents = {
diff --git a/nixos/modules/services/continuous-integration/woodpecker/server.nix b/nixos/modules/services/continuous-integration/woodpecker/server.nix
index 54d8da8a59e5e..6e3cfb0b0114c 100644
--- a/nixos/modules/services/continuous-integration/woodpecker/server.nix
+++ b/nixos/modules/services/continuous-integration/woodpecker/server.nix
@@ -8,7 +8,7 @@ let
   cfg = config.services.woodpecker-server;
 in
 {
-  meta.maintainers = with lib.maintainers; [ janik ambroisie ];
+  meta.maintainers = with lib.maintainers; [ ambroisie ];
 
 
   options = {
diff --git a/nixos/modules/services/databases/monetdb.nix b/nixos/modules/services/databases/monetdb.nix
index 5025eb30369b4..ee24cf2b0fc20 100644
--- a/nixos/modules/services/databases/monetdb.nix
+++ b/nixos/modules/services/databases/monetdb.nix
@@ -6,7 +6,7 @@ let
   cfg = config.services.monetdb;
 
 in {
-  meta.maintainers = with maintainers; [ StillerHarpo primeos ];
+  meta.maintainers = with maintainers; [ StillerHarpo ];
 
   ###### interface
   options = {
diff --git a/nixos/modules/services/desktop-managers/lomiri.nix b/nixos/modules/services/desktop-managers/lomiri.nix
index 0b871aa38183e..fba7177307e91 100644
--- a/nixos/modules/services/desktop-managers/lomiri.nix
+++ b/nixos/modules/services/desktop-managers/lomiri.nix
@@ -23,6 +23,7 @@ in {
         lomiri
         lomiri-download-manager
         lomiri-filemanager-app
+        lomiri-polkit-agent
         lomiri-schemas # exposes some required dbus interfaces
         lomiri-session # wrappers to properly launch the session
         lomiri-sounds
@@ -145,6 +146,18 @@ in {
           ExecStart = "${pkgs.lomiri.lomiri-url-dispatcher}/libexec/lomiri-url-dispatcher/lomiri-update-directory /run/current-system/sw/share/lomiri-url-dispatcher/urls/";
         };
       };
+
+      "lomiri-polkit-agent" = rec {
+        description = "Lomiri Polkit agent";
+        wantedBy = [ "lomiri.service" "lomiri-full-greeter.service" "lomiri-full-shell.service" "lomiri-greeter.service" "lomiri-shell.service" ];
+        after = [ "graphical-session.target" ];
+        partOf = wantedBy;
+        serviceConfig = {
+          Type = "simple";
+          Restart = "always";
+          ExecStart = "${pkgs.lomiri.lomiri-polkit-agent}/libexec/lomiri-polkit-agent/policykit-agent";
+        };
+      };
     };
 
     systemd.services = {
diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix
index 796e24286f9e4..01a5bfa1dee27 100644
--- a/nixos/modules/services/desktop-managers/plasma6.nix
+++ b/nixos/modules/services/desktop-managers/plasma6.nix
@@ -8,7 +8,7 @@
   cfg = config.services.desktopManager.plasma6;
 
   inherit (pkgs) kdePackages;
-  inherit (lib) literalExpression mkDefault mkIf mkOption mkPackageOptionMD types;
+  inherit (lib) literalExpression mkDefault mkIf mkOption mkPackageOption types;
 
   activationScript = ''
     # will be rebuilt automatically
@@ -29,7 +29,7 @@ in {
         description = "Enable Qt 5 integration (theming, etc). Disable for a pure Qt 6 system.";
       };
 
-      notoPackage = mkPackageOptionMD pkgs "Noto fonts - used for UI by default" {
+      notoPackage = mkPackageOption pkgs "Noto fonts - used for UI by default" {
         default = ["noto-fonts"];
         example = "noto-fonts-lgc-plus";
       };
diff --git a/nixos/modules/services/desktops/espanso.nix b/nixos/modules/services/desktops/espanso.nix
index a6b8a078247b1..a2c4b77b90464 100644
--- a/nixos/modules/services/desktops/espanso.nix
+++ b/nixos/modules/services/desktops/espanso.nix
@@ -8,6 +8,7 @@ in {
   options = {
     services.espanso = {
       enable = mkEnableOption "Espanso";
+      wayland = mkEnableOption "use the Wayland compatible espanso package";
       package = mkPackageOption pkgs "espanso" {
         example = "pkgs.espanso-wayland";
       };
diff --git a/nixos/modules/services/desktops/gnome/gnome-keyring.nix b/nixos/modules/services/desktops/gnome/gnome-keyring.nix
index 02b198fd81cb9..550c6ba8eff54 100644
--- a/nixos/modules/services/desktops/gnome/gnome-keyring.nix
+++ b/nixos/modules/services/desktops/gnome/gnome-keyring.nix
@@ -26,33 +26,22 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.gnome.gnome-keyring ];
+    environment.systemPackages = [ pkgs.gnome-keyring ];
 
     services.dbus.packages = [
-      pkgs.gnome.gnome-keyring
+      pkgs.gnome-keyring
       pkgs.gcr
     ];
 
-    xdg.portal.extraPortals = [ pkgs.gnome.gnome-keyring ];
-
-    security.pam.services = lib.mkMerge [
-      {
-        login.enableGnomeKeyring = true;
-      }
-      (lib.mkIf config.services.xserver.displayManager.gdm.enable {
-        gdm-password.enableGnomeKeyring = true;
-        gdm-autologin.enableGnomeKeyring = true;
-      })
-      (lib.mkIf (config.services.xserver.displayManager.gdm.enable && config.services.fprintd.enable) {
-        gdm-fingerprint.enableGnomeKeyring = true;
-      })
-    ];
+    xdg.portal.extraPortals = [ pkgs.gnome-keyring ];
+
+    security.pam.services.login.enableGnomeKeyring = true;
 
     security.wrappers.gnome-keyring-daemon = {
       owner = "root";
       group = "root";
       capabilities = "cap_ipc_lock=ep";
-      source = "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon";
+      source = "${pkgs.gnome-keyring}/bin/gnome-keyring-daemon";
     };
   };
 }
diff --git a/nixos/modules/services/desktops/gnome/gnome-user-share.nix b/nixos/modules/services/desktops/gnome/gnome-user-share.nix
index 2c6d94b7bdfc6..518beb80419a9 100644
--- a/nixos/modules/services/desktops/gnome/gnome-user-share.nix
+++ b/nixos/modules/services/desktops/gnome/gnome-user-share.nix
@@ -26,11 +26,11 @@
   config = lib.mkIf config.services.gnome.gnome-user-share.enable {
 
     environment.systemPackages = [
-      pkgs.gnome.gnome-user-share
+      pkgs.gnome-user-share
     ];
 
     systemd.packages = [
-      pkgs.gnome.gnome-user-share
+      pkgs.gnome-user-share
     ];
 
   };
diff --git a/nixos/modules/services/desktops/gnome/rygel.nix b/nixos/modules/services/desktops/gnome/rygel.nix
index c980b239d521e..7ce7e079b6af6 100644
--- a/nixos/modules/services/desktops/gnome/rygel.nix
+++ b/nixos/modules/services/desktops/gnome/rygel.nix
@@ -23,12 +23,12 @@
 
   ###### implementation
   config = lib.mkIf config.services.gnome.rygel.enable {
-    environment.systemPackages = [ pkgs.gnome.rygel ];
+    environment.systemPackages = [ pkgs.rygel ];
 
-    services.dbus.packages = [ pkgs.gnome.rygel ];
+    services.dbus.packages = [ pkgs.rygel ];
 
-    systemd.packages = [ pkgs.gnome.rygel ];
+    systemd.packages = [ pkgs.rygel ];
 
-    environment.etc."rygel.conf".source = "${pkgs.gnome.rygel}/etc/rygel.conf";
+    environment.etc."rygel.conf".source = "${pkgs.rygel}/etc/rygel.conf";
   };
 }
diff --git a/nixos/modules/services/desktops/gnome/sushi.nix b/nixos/modules/services/desktops/gnome/sushi.nix
index 946030e4bb229..7f7360488eb41 100644
--- a/nixos/modules/services/desktops/gnome/sushi.nix
+++ b/nixos/modules/services/desktops/gnome/sushi.nix
@@ -31,9 +31,9 @@
 
   config = lib.mkIf config.services.gnome.sushi.enable {
 
-    environment.systemPackages = [ pkgs.gnome.sushi ];
+    environment.systemPackages = [ pkgs.sushi ];
 
-    services.dbus.packages = [ pkgs.gnome.sushi ];
+    services.dbus.packages = [ pkgs.sushi ];
 
   };
 
diff --git a/nixos/modules/services/desktops/playerctld.nix b/nixos/modules/services/desktops/playerctld.nix
new file mode 100644
index 0000000000000..ef4866d75715d
--- /dev/null
+++ b/nixos/modules/services/desktops/playerctld.nix
@@ -0,0 +1,32 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  cfg = config.services.playerctld;
+in
+{
+  options.services.playerctld = {
+    enable = lib.mkEnableOption "the playerctld daemon";
+
+    package = lib.mkPackageOption pkgs "playerctl" { };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+    systemd.user.services.playerctld = {
+      description = "Playerctld daemon to track media player activity";
+      wantedBy = [ "default.target" ];
+
+      serviceConfig = {
+        Type = "exec";
+        ExecStart = "${cfg.package}/bin/playerctld";
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ aacebedo ];
+}
diff --git a/nixos/modules/services/games/armagetronad.nix b/nixos/modules/services/games/armagetronad.nix
index 71c8528a9f6ea..dfeadb19026f7 100644
--- a/nixos/modules/services/games/armagetronad.nix
+++ b/nixos/modules/services/games/armagetronad.nix
@@ -36,7 +36,7 @@ in
           options = {
             enable = mkEnableOption "armagetronad";
 
-            package = lib.mkPackageOptionMD pkgs "armagetronad-dedicated" {
+            package = lib.mkPackageOption pkgs "armagetronad-dedicated" {
               example = ''
                 pkgs.armagetronad."0.2.9-sty+ct+ap".dedicated
               '';
diff --git a/nixos/modules/services/games/teeworlds.nix b/nixos/modules/services/games/teeworlds.nix
index 1958fd4141788..b9ed49937a7f7 100644
--- a/nixos/modules/services/games/teeworlds.nix
+++ b/nixos/modules/services/games/teeworlds.nix
@@ -95,7 +95,7 @@ in
     services.teeworlds = {
       enable = mkEnableOption "Teeworlds Server";
 
-      package = mkPackageOptionMD pkgs "teeworlds-server" { };
+      package = mkPackageOption pkgs "teeworlds-server" { };
 
       openPorts = mkOption {
         type = types.bool;
diff --git a/nixos/modules/services/hardware/auto-epp.nix b/nixos/modules/services/hardware/auto-epp.nix
index b568dec26f4c9..1d939a98142e0 100644
--- a/nixos/modules/services/hardware/auto-epp.nix
+++ b/nixos/modules/services/hardware/auto-epp.nix
@@ -10,7 +10,7 @@ in {
     services.auto-epp = {
       enable = lib.mkEnableOption "auto-epp for amd active pstate";
 
-      package = lib.mkPackageOptionMD pkgs "auto-epp" {};
+      package = lib.mkPackageOption pkgs "auto-epp" {};
 
       settings = mkOption {
         type = types.submodule {
diff --git a/nixos/modules/services/home-automation/ebusd.nix b/nixos/modules/services/home-automation/ebusd.nix
index f5c5479e8eaff..97d1e2796adab 100644
--- a/nixos/modules/services/home-automation/ebusd.nix
+++ b/nixos/modules/services/home-automation/ebusd.nix
@@ -11,7 +11,7 @@ in
   options.services.ebusd = {
     enable = mkEnableOption "ebusd, a daemon for communication with eBUS heating systems";
 
-    package = mkPackageOptionMD pkgs "ebusd" { };
+    package = mkPackageOption pkgs "ebusd" { };
 
     device = mkOption {
       type = types.str;
diff --git a/nixos/modules/services/home-automation/matter-server.nix b/nixos/modules/services/home-automation/matter-server.nix
index 7bf1cfe54d17b..08a68db71386e 100644
--- a/nixos/modules/services/home-automation/matter-server.nix
+++ b/nixos/modules/services/home-automation/matter-server.nix
@@ -19,7 +19,7 @@ in
   options.services.matter-server = with types; {
     enable = mkEnableOption "Matter-server";
 
-    package = mkPackageOptionMD pkgs "python-matter-server" { };
+    package = mkPackageOption pkgs "python-matter-server" { };
 
     port = mkOption {
       type = types.port;
diff --git a/nixos/modules/services/mail/roundcube.nix b/nixos/modules/services/mail/roundcube.nix
index 78f627d33e2df..2914877bdccde 100644
--- a/nixos/modules/services/mail/roundcube.nix
+++ b/nixos/modules/services/mail/roundcube.nix
@@ -93,13 +93,17 @@ in
     maxAttachmentSize = mkOption {
       type = types.int;
       default = 18;
+      apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.37)}M";
       description = ''
         The maximum attachment size in MB.
-
-        Note: Since roundcube only uses 70% of max upload values configured in php
-        30% is added automatically to [](#opt-services.roundcube.maxAttachmentSize).
+        [upstream issue comment]: https://github.com/roundcube/roundcubemail/issues/7979#issuecomment-808879209
+        ::: {.note}
+        Since there is some overhead in base64 encoding applied to attachments, + 37% will be added
+        to the value set in this option in order to offset the overhead. For example, setting
+        `maxAttachmentSize` to `100` would result in `137M` being the real value in the configuration.
+        See [upstream issue comment] for more details on the motivations behind this.
+        :::
       '';
-      apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.3)}M";
     };
 
     configureNginx = lib.mkOption {
diff --git a/nixos/modules/services/mail/stalwart-mail.nix b/nixos/modules/services/mail/stalwart-mail.nix
index 776243a68af53..1025788f0d84d 100644
--- a/nixos/modules/services/mail/stalwart-mail.nix
+++ b/nixos/modules/services/mail/stalwart-mail.nix
@@ -9,12 +9,28 @@ let
   dataDir = "/var/lib/stalwart-mail";
   useLegacyStorage = versionOlder config.system.stateVersion "24.11";
 
+  parsePorts = listeners: let
+    parseAddresses = listeners: lib.flatten(lib.mapAttrsToList (name: value: value.bind) listeners);
+    splitAddress = addr: strings.splitString ":" addr;
+    extractPort = addr: strings.toInt(builtins.foldl' (a: b: b) "" (splitAddress addr));
+  in
+    builtins.map(address: extractPort address) (parseAddresses listeners);
+
 in {
   options.services.stalwart-mail = {
     enable = mkEnableOption "the Stalwart all-in-one email server";
 
     package = mkPackageOption pkgs "stalwart-mail" { };
 
+    openFirewall = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to open TCP firewall ports, which are specified in
+        {option}`services.stalwart-mail.settings.listener` on all interfaces.
+      '';
+    };
+
     settings = mkOption {
       inherit (configFormat) type;
       default = { };
@@ -138,6 +154,11 @@ in {
 
     # Make admin commands available in the shell
     environment.systemPackages = [ cfg.package ];
+
+    networking.firewall = mkIf (cfg.openFirewall
+      && (builtins.hasAttr "listener" cfg.settings.server)) {
+      allowedTCPPorts = parsePorts cfg.settings.server.listener;
+    };
   };
 
   meta = {
diff --git a/nixos/modules/services/misc/dictd.nix b/nixos/modules/services/misc/dictd.nix
index 8cb51bb0b7a7f..6660d5e977ffb 100644
--- a/nixos/modules/services/misc/dictd.nix
+++ b/nixos/modules/services/misc/dictd.nix
@@ -62,6 +62,9 @@ in
       description = "DICT.org Dictionary Server";
       wantedBy = [ "multi-user.target" ];
       environment = { LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; };
+      # Work around the fact that dictd doesn't handle SIGTERM; it terminates
+      # with code 143 instead of exiting with code 0.
+      serviceConfig.SuccessExitStatus = [ 143 ];
       serviceConfig.Type = "forking";
       script = "${pkgs.dict}/sbin/dictd -s -c ${dictdb}/share/dictd/dictd.conf --locale en_US.UTF-8";
     };
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index 7b96a182f0d94..492c669f180a9 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -12,7 +12,7 @@ let
   postgresqlPackage = if config.services.postgresql.enable then
                         config.services.postgresql.package
                       else
-                        pkgs.postgresql_13;
+                        pkgs.postgresql_14;
 
   gitlabSocket = "${cfg.statePath}/tmp/sockets/gitlab.socket";
   gitalySocket = "${cfg.statePath}/tmp/sockets/gitaly.socket";
@@ -1119,8 +1119,8 @@ in {
         message = "services.gitlab.secrets.jwsFile must be set!";
       }
       {
-        assertion = versionAtLeast postgresqlPackage.version "13.6.0";
-        message = "PostgreSQL >=13.6 is required to run GitLab 16. Follow the instructions in the manual section for upgrading PostgreSQL here: https://nixos.org/manual/nixos/stable/index.html#module-services-postgres-upgrading";
+        assertion = versionAtLeast postgresqlPackage.version "14.9";
+        message = "PostgreSQL >= 14.9 is required to run GitLab 17. Follow the instructions in the manual section for upgrading PostgreSQL here: https://nixos.org/manual/nixos/stable/index.html#module-services-postgres-upgrading";
       }
     ];
 
@@ -1282,6 +1282,7 @@ in {
       "d ${gitlabConfig.production.shared.path}/registry 0750 ${cfg.user} ${cfg.group} -"
       "d ${gitlabConfig.production.shared.path}/terraform_state 0750 ${cfg.user} ${cfg.group} -"
       "d ${gitlabConfig.production.shared.path}/ci_secure_files 0750 ${cfg.user} ${cfg.group} -"
+      "d ${gitlabConfig.production.shared.path}/external-diffs 0750 ${cfg.user} ${cfg.group} -"
       "L+ /run/gitlab/config - - - - ${cfg.statePath}/config"
       "L+ /run/gitlab/log - - - - ${cfg.statePath}/log"
       "L+ /run/gitlab/tmp - - - - ${cfg.statePath}/tmp"
diff --git a/nixos/modules/services/misc/jellyseerr.nix b/nixos/modules/services/misc/jellyseerr.nix
index 7599a1af33840..9aab517e0493b 100644
--- a/nixos/modules/services/misc/jellyseerr.nix
+++ b/nixos/modules/services/misc/jellyseerr.nix
@@ -9,6 +9,7 @@ in
 
   options.services.jellyseerr = {
     enable = mkEnableOption ''Jellyseerr, a requests manager for Jellyfin'';
+    package = mkPackageOption pkgs "jellyseerr" { };
 
     openFirewall = mkOption {
       type = types.bool;
@@ -32,10 +33,10 @@ in
       serviceConfig = {
         Type = "exec";
         StateDirectory = "jellyseerr";
-        WorkingDirectory = "${pkgs.jellyseerr}/libexec/jellyseerr/deps/jellyseerr";
+        WorkingDirectory = "${cfg.package}/libexec/jellyseerr/deps/jellyseerr";
         DynamicUser = true;
-        ExecStart = "${pkgs.jellyseerr}/bin/jellyseerr";
-        BindPaths = [ "/var/lib/jellyseerr/:${pkgs.jellyseerr}/libexec/jellyseerr/deps/jellyseerr/config/" ];
+        ExecStart = lib.getExe cfg.package;
+        BindPaths = [ "/var/lib/jellyseerr/:${cfg.package}/libexec/jellyseerr/deps/jellyseerr/config/" ];
         Restart = "on-failure";
         ProtectHome = true;
         ProtectSystem = "strict";
diff --git a/nixos/modules/services/misc/ollama.nix b/nixos/modules/services/misc/ollama.nix
index c460514783efc..a0a32f1702bf3 100644
--- a/nixos/modules/services/misc/ollama.nix
+++ b/nixos/modules/services/misc/ollama.nix
@@ -5,9 +5,6 @@ let
   cfg = config.services.ollama;
   ollamaPackage = cfg.package.override {
     inherit (cfg) acceleration;
-    linuxPackages = config.boot.kernelPackages // {
-      nvidia_x11 = config.hardware.nvidia.package;
-    };
   };
 in
 {
diff --git a/nixos/modules/services/misc/renovate.nix b/nixos/modules/services/misc/renovate.nix
index 25a719c91cbd8..9062b7424b681 100644
--- a/nixos/modules/services/misc/renovate.nix
+++ b/nixos/modules/services/misc/renovate.nix
@@ -128,6 +128,7 @@ in
         RestrictAddressFamilies = [
           "AF_INET"
           "AF_INET6"
+          "AF_UNIX"
         ];
         RestrictNamespaces = true;
         RestrictRealtime = true;
diff --git a/nixos/modules/services/misc/rkvm.nix b/nixos/modules/services/misc/rkvm.nix
index 9d41669e00f61..b149c3d3979f5 100644
--- a/nixos/modules/services/misc/rkvm.nix
+++ b/nixos/modules/services/misc/rkvm.nix
@@ -7,7 +7,7 @@ let
   toml = pkgs.formats.toml { };
 in
 {
-  meta.maintainers = with maintainers; [ ckie ];
+  meta.maintainers = with maintainers; [ ];
 
   options.services.rkvm = {
     enable = mkOption {
diff --git a/nixos/modules/services/misc/snapper.nix b/nixos/modules/services/misc/snapper.nix
index 1b16ef7958ad2..fc57683de3280 100644
--- a/nixos/modules/services/misc/snapper.nix
+++ b/nixos/modules/services/misc/snapper.nix
@@ -96,48 +96,48 @@ let
     };
 
     TIMELINE_LIMIT_HOURLY = mkOption {
-      type = types.str;
-      default = "10";
+      type = types.int;
+      default = 10;
       description = ''
         Limits for timeline cleanup.
       '';
     };
 
     TIMELINE_LIMIT_DAILY = mkOption {
-      type = types.str;
-      default = "10";
+      type = types.int;
+      default = 10;
       description = ''
         Limits for timeline cleanup.
       '';
     };
 
     TIMELINE_LIMIT_WEEKLY = mkOption {
-      type = types.str;
-      default = "0";
+      type = types.int;
+      default = 0;
       description = ''
         Limits for timeline cleanup.
       '';
     };
 
     TIMELINE_LIMIT_MONTHLY = mkOption {
-      type = types.str;
-      default = "10";
+      type = types.int;
+      default = 10;
       description = ''
         Limits for timeline cleanup.
       '';
     };
 
     TIMELINE_LIMIT_QUARTERLY = mkOption {
-      type = types.str;
-      default = "0";
+      type = types.int;
+      default = 0;
       description = ''
         Limits for timeline cleanup.
       '';
     };
 
     TIMELINE_LIMIT_YEARLY = mkOption {
-      type = types.str;
-      default = "10";
+      type = types.int;
+      default = 10;
       description = ''
         Limits for timeline cleanup.
       '';
@@ -353,4 +353,6 @@ in
       ) (attrNames cfg.configs);
     }
   );
+
+  meta.maintainers = with lib.maintainers; [ Djabx ];
 }
diff --git a/nixos/modules/services/misc/sonarr.nix b/nixos/modules/services/misc/sonarr.nix
index 228a2d48f5a9c..60e73198d60de 100644
--- a/nixos/modules/services/misc/sonarr.nix
+++ b/nixos/modules/services/misc/sonarr.nix
@@ -1,4 +1,4 @@
-{ config, pkgs, lib, ... }:
+{ config, pkgs, lib, utils, ... }:
 
 with lib;
 
@@ -54,7 +54,11 @@ in
         Type = "simple";
         User = cfg.user;
         Group = cfg.group;
-        ExecStart = "${cfg.package}/bin/NzbDrone -nobrowser -data='${cfg.dataDir}'";
+        ExecStart = utils.escapeSystemdExecArgs [
+          (lib.getExe cfg.package)
+          "-nobrowser"
+          "-data=${cfg.dataDir}"
+        ];
         Restart = "on-failure";
       };
     };
diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix
index d09cd87febfff..8db63d5386332 100644
--- a/nixos/modules/services/misc/zoneminder.nix
+++ b/nixos/modules/services/misc/zoneminder.nix
@@ -202,10 +202,10 @@ in {
     ];
 
     services = {
-      fcgiwrap = lib.mkIf useNginx {
-        enable = true;
-        preforkProcesses = cfg.cameras;
-        inherit user group;
+      fcgiwrap.zoneminder = lib.mkIf useNginx {
+        process.prefork = cfg.cameras;
+        process.user = user;
+        process.group = group;
       };
 
       mysql = lib.mkIf cfg.database.createLocally {
@@ -225,9 +225,7 @@ in {
             default = true;
             root = "${pkg}/share/zoneminder/www";
             listen = [ { addr = "0.0.0.0"; inherit (cfg) port; } ];
-            extraConfig = let
-              fcgi = config.services.fcgiwrap;
-            in ''
+            extraConfig = ''
               index index.php;
 
               location / {
@@ -257,7 +255,7 @@ in {
                   fastcgi_param HTTP_PROXY "";
                   fastcgi_intercept_errors on;
 
-                  fastcgi_pass ${fcgi.socketType}:${fcgi.socketAddress};
+                  fastcgi_pass unix:${config.services.fcgiwrap.zoneminder.socket.address};
                 }
 
                 location /cache/ {
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index 32919950adc1e..eae2658b7ffb8 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -105,7 +105,7 @@ let
       };
       url = mkOption {
         type = types.str;
-        default = "localhost";
+        default = "";
         description = "Url of the datasource.";
       };
       editable = mkOption {
diff --git a/nixos/modules/services/monitoring/nezha-agent.nix b/nixos/modules/services/monitoring/nezha-agent.nix
index 8312a425d28fc..7ebbc7f2f3297 100644
--- a/nixos/modules/services/monitoring/nezha-agent.nix
+++ b/nixos/modules/services/monitoring/nezha-agent.nix
@@ -24,6 +24,13 @@ in
           Enable SSL/TLS encryption.
         '';
       };
+      gpu = lib.mkOption {
+        type = lib.types.bool;
+        default = true;
+        description = ''
+          Enable GPU monitoring.
+        '';
+      };
       disableCommandExecute = lib.mkOption {
         type = lib.types.bool;
         default = true;
@@ -46,7 +53,12 @@ in
         '';
       };
       reportDelay = lib.mkOption {
-        type = lib.types.enum [ 1 2 3 4 ];
+        type = lib.types.enum [
+          1
+          2
+          3
+          4
+        ];
         default = 1;
         description = ''
           The interval between system status reportings.
@@ -96,6 +108,7 @@ in
         ++ lib.optional cfg.skipConnection "--skip-conn"
         ++ lib.optional cfg.skipProcess "--skip-procs"
         ++ lib.optional cfg.tls "--tls"
+        ++ lib.optional cfg.gpu "--gpu"
       );
       wantedBy = [ "multi-user.target" ];
     };
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix b/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix
index 097ea39594788..e470ebe2eb592 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/fastly.nix
@@ -1,17 +1,20 @@
-{ config
-, lib
-, pkgs
-, options
-, ...
+{
+  config,
+  lib,
+  pkgs,
+  utils,
+  ...
 }:
 
 let
   inherit (lib)
-    escapeShellArgs
+    getExe
     mkOption
     optionals
     types
-  ;
+    ;
+
+  inherit (utils) escapeSystemdExecArgs;
 
   cfg = config.services.prometheus.exporters.fastly;
 in
@@ -39,17 +42,19 @@ in
   serviceOpts = {
     serviceConfig = {
       LoadCredential = "fastly-api-token:${cfg.tokenPath}";
+      Environment = [ "FASTLY_API_TOKEN=%d/fastly-api-token" ];
+      ExecStart = escapeSystemdExecArgs (
+        [
+          (getExe pkgs.prometheus-fastly-exporter)
+          "-listen"
+          "${cfg.listenAddress}:${toString cfg.port}"
+        ]
+        ++ optionals (cfg.configFile != null) [
+          "--config-file"
+          cfg.configFile
+        ]
+        ++ cfg.extraFlags
+      );
     };
-    script = let
-      call = escapeShellArgs ([
-        "${pkgs.prometheus-fastly-exporter}/bin/fastly-exporter"
-        "-listen" "${cfg.listenAddress}:${toString cfg.port}"
-      ] ++ optionals (cfg.configFile != null) [
-        "--config-file" cfg.configFile
-      ] ++ cfg.extraFlags);
-    in ''
-      export FASTLY_API_TOKEN="$(cat $CREDENTIALS_DIRECTORY/fastly-api-token)"
-      ${call}
-    '';
   };
 }
diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix
index 2c05eaad25ace..6fd3b5707ab67 100644
--- a/nixos/modules/services/monitoring/smartd.nix
+++ b/nixos/modules/services/monitoring/smartd.nix
@@ -10,6 +10,7 @@ let
   opt = options.services.smartd;
 
   nm = cfg.notifications.mail;
+  ns = cfg.notifications.systembus-notify;
   nw = cfg.notifications.wall;
   nx = cfg.notifications.x11;
 
@@ -28,6 +29,12 @@ let
       ${pkgs.smartmontools}/sbin/smartctl -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE"
       } | ${nm.mailer} -i "${nm.recipient}"
     ''}
+    ${optionalString ns.enable ''
+      ${pkgs.dbus}/bin/dbus-send --system \
+        / net.nuetzlich.SystemNotifications.Notify \
+        "string:Problem detected with disk: $SMARTD_DEVICESTRING" \
+        "string:Warning message from smartd is: $SMARTD_MESSAGE"
+    ''}
     ${optionalString nw.enable ''
       {
       ${pkgs.coreutils}/bin/cat << EOF
@@ -159,6 +166,24 @@ in
           };
         };
 
+        systembus-notify = {
+          enable = mkOption {
+            default = false;
+            type = types.bool;
+            description = ''
+              Whenever to send systembus-notify notifications.
+
+              WARNING: enabling this option (while convenient) should *not* be done on a
+              machine where you do not trust the other users as it allows any other
+              local user to DoS your session by spamming notifications.
+
+              To actually see the notifications in your GUI session, you need to have
+              `systembus-notify` running as your user, which this
+              option handles by enabling {option}`services.systembus-notify`.
+            '';
+          };
+        };
+
         wall = {
           enable = mkOption {
             default = true;
@@ -247,6 +272,8 @@ in
       serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}";
     };
 
+    services.systembus-notify.enable = mkDefault ns.enable;
+
   };
 
 }
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index c70d0cf7beac3..a887f964ca428 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -55,6 +55,7 @@ let
         PIDFile = "/run/${appName}.pid";
         Type = "notify";
         NotifyAccess = "all"; #may not do anything...
+        Slice = "system-samba.slice";
       };
       unitConfig.RequiresMountsFor = "/var/lib/samba";
 
@@ -216,6 +217,11 @@ in
             wants = [ "network-online.target" ];
             wantedBy = [ "multi-user.target" ];
           };
+
+          slices.system-samba = {
+            description = "Samba slice";
+          };
+
           # Refer to https://github.com/samba-team/samba/tree/master/packaging/systemd
           # for correct use with systemd
           services = {
diff --git a/nixos/modules/services/networking/blocky.nix b/nixos/modules/services/networking/blocky.nix
index b98c8b7bdb730..4bc6ffa3f46ab 100644
--- a/nixos/modules/services/networking/blocky.nix
+++ b/nixos/modules/services/networking/blocky.nix
@@ -12,6 +12,8 @@ in
   options.services.blocky = {
     enable = mkEnableOption "blocky, a fast and lightweight DNS proxy as ad-blocker for local network with many features";
 
+    package = mkPackageOption pkgs "blocky" { };
+
     settings = mkOption {
       type = format.type;
       default = { };
@@ -30,7 +32,7 @@ in
 
       serviceConfig = {
         DynamicUser = true;
-        ExecStart = "${pkgs.blocky}/bin/blocky --config ${configFile}";
+        ExecStart = "${getExe cfg.package} --config ${configFile}";
         Restart = "on-failure";
 
         AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
diff --git a/nixos/modules/services/networking/cgit.nix b/nixos/modules/services/networking/cgit.nix
index 0ccbef756812e..de8128ed5a59c 100644
--- a/nixos/modules/services/networking/cgit.nix
+++ b/nixos/modules/services/networking/cgit.nix
@@ -25,14 +25,14 @@ let
 
   regexLocation = cfg: regexEscape (stripLocation cfg);
 
-  mkFastcgiPass = cfg: ''
+  mkFastcgiPass = name: cfg: ''
     ${if cfg.nginx.location == "/" then ''
       fastcgi_param PATH_INFO $uri;
     '' else ''
       fastcgi_split_path_info ^(${regexLocation cfg})(/.+)$;
       fastcgi_param PATH_INFO $fastcgi_path_info;
     ''
-    }fastcgi_pass unix:${config.services.fcgiwrap.socketAddress};
+    }fastcgi_pass unix:${config.services.fcgiwrap."cgit-${name}".socket.address};
   '';
 
   cgitrcLine = name: value: "${name}=${
@@ -72,25 +72,11 @@ let
     ${cfg.extraConfig}
   '';
 
-  mkCgitReposDir = cfg:
-    if cfg.scanPath != null then
-      cfg.scanPath
-    else
-      pkgs.runCommand "cgit-repos" {
-        preferLocalBuild = true;
-        allowSubstitutes = false;
-      } ''
-        mkdir -p "$out"
-        ${
-          concatStrings (
-            mapAttrsToList
-              (name: value: ''
-                ln -s ${escapeShellArg value.path} "$out"/${escapeShellArg name}
-              '')
-              cfg.repos
-          )
-        }
-      '';
+  fcgiwrapUnitName = name: "fcgiwrap-cgit-${name}";
+  fcgiwrapRuntimeDir = name: "/run/${fcgiwrapUnitName name}";
+  gitProjectRoot = name: cfg: if cfg.scanPath != null
+    then cfg.scanPath
+    else "${fcgiwrapRuntimeDir name}/repos";
 
 in
 {
@@ -154,6 +140,18 @@ in
             type = types.lines;
             default = "";
           };
+
+          user = mkOption {
+            description = "User to run the cgit service as.";
+            type = types.str;
+            default = "cgit";
+          };
+
+          group = mkOption {
+            description = "Group to run the cgit service as.";
+            type = types.str;
+            default = "cgit";
+          };
         };
       }));
     };
@@ -165,18 +163,46 @@ in
       message = "Exactly one of services.cgit.${vhost}.scanPath or services.cgit.${vhost}.repos must be set.";
     }) cfgs;
 
-    services.fcgiwrap.enable = true;
+    users = mkMerge (flip mapAttrsToList cfgs (_: cfg: {
+      users.${cfg.user} = {
+        isSystemUser = true;
+        inherit (cfg) group;
+      };
+      groups.${cfg.group} = { };
+    }));
+
+    services.fcgiwrap = flip mapAttrs' cfgs (name: cfg:
+      nameValuePair "cgit-${name}" {
+        process = { inherit (cfg) user group; };
+        socket = { inherit (config.services.nginx) user group; };
+      }
+    );
+
+    systemd.services = flip mapAttrs' cfgs (name: cfg:
+      nameValuePair (fcgiwrapUnitName name)
+      (mkIf (cfg.repos != { }) {
+        serviceConfig.RuntimeDirectory = fcgiwrapUnitName name;
+        preStart = ''
+          GIT_PROJECT_ROOT=${escapeShellArg (gitProjectRoot name cfg)}
+          mkdir -p "$GIT_PROJECT_ROOT"
+          cd "$GIT_PROJECT_ROOT"
+          ${concatLines (flip mapAttrsToList cfg.repos (name: repo: ''
+            ln -s ${escapeShellArg repo.path} ${escapeShellArg name}
+          ''))}
+        '';
+      }
+    ));
 
     services.nginx.enable = true;
 
-    services.nginx.virtualHosts = mkMerge (mapAttrsToList (_: cfg: {
+    services.nginx.virtualHosts = mkMerge (mapAttrsToList (name: cfg: {
       ${cfg.nginx.virtualHost} = {
         locations = (
           genAttrs'
             [ "cgit.css" "cgit.png" "favicon.ico" "robots.txt" ]
-            (name: nameValuePair "= ${stripLocation cfg}/${name}" {
+            (fileName: nameValuePair "= ${stripLocation cfg}/${fileName}" {
               extraConfig = ''
-                alias ${cfg.package}/cgit/${name};
+                alias ${cfg.package}/cgit/${fileName};
               '';
             })
         ) // {
@@ -184,10 +210,10 @@ in
             fastcgiParams = rec {
               SCRIPT_FILENAME = "${pkgs.git}/libexec/git-core/git-http-backend";
               GIT_HTTP_EXPORT_ALL = "1";
-              GIT_PROJECT_ROOT = mkCgitReposDir cfg;
+              GIT_PROJECT_ROOT = gitProjectRoot name cfg;
               HOME = GIT_PROJECT_ROOT;
             };
-            extraConfig = mkFastcgiPass cfg;
+            extraConfig = mkFastcgiPass name cfg;
           };
           "${stripLocation cfg}/" = {
             fastcgiParams = {
@@ -196,7 +222,7 @@ in
               HTTP_HOST = "$server_name";
               CGIT_CONFIG = mkCgitrc cfg;
             };
-            extraConfig = mkFastcgiPass cfg;
+            extraConfig = mkFastcgiPass name cfg;
           };
         };
       };
diff --git a/nixos/modules/services/networking/cloudflare-dyndns.nix b/nixos/modules/services/networking/cloudflare-dyndns.nix
index ab5b1a08539a5..a15de2ddd861b 100644
--- a/nixos/modules/services/networking/cloudflare-dyndns.nix
+++ b/nixos/modules/services/networking/cloudflare-dyndns.nix
@@ -28,6 +28,16 @@ in
         '';
       };
 
+      frequency = mkOption {
+        type = types.nullOr types.str;
+        default = "*:0/5";
+        description = ''
+          Run cloudflare-dyndns with the given frequency (see
+          {manpage}`systemd.time(7)` for the format).
+          If null, do not run automatically.
+        '';
+      };
+
       proxied = mkOption {
         type = types.bool;
         default = false;
@@ -67,7 +77,6 @@ in
       description = "CloudFlare Dynamic DNS Client";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      startAt = "*:0/5";
 
       environment = {
         CLOUDFLARE_DOMAINS = toString cfg.domains;
@@ -88,6 +97,8 @@ in
           in
           "${pkgs.cloudflare-dyndns}/bin/cloudflare-dyndns ${toString args}";
       };
+    } // optionalAttrs (cfg.frequency != null) {
+      startAt = cfg.frequency;
     };
   };
 }
diff --git a/nixos/modules/services/networking/cloudflared.nix b/nixos/modules/services/networking/cloudflared.nix
index 60f6b7c466892..c0d1012ffb80d 100644
--- a/nixos/modules/services/networking/cloudflared.nix
+++ b/nixos/modules/services/networking/cloudflared.nix
@@ -131,7 +131,7 @@ let
         `cloudflared` starts a proxy server to translate HTTP traffic into TCP when proxying, for example, SSH or RDP. This configures what type of proxy will be started. Valid options are:
 
         - `""` for the regular proxy
-        - `"socks"` for a SOCKS5 proxy. Refer to the [https://developers.cloudflare.com/cloudflare-one/tutorials/kubectl/](tutorial on connecting through Cloudflare Access using kubectl) for more information.
+        - `"socks"` for a SOCKS5 proxy. Refer to the [tutorial on connecting through Cloudflare Access using kubectl](https://developers.cloudflare.com/cloudflare-one/tutorials/kubectl/) for more information.
       '';
     };
   };
@@ -167,7 +167,7 @@ in
             description = ''
               Credential file.
 
-              See [https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-terms/#credentials-file](Credentials file).
+              See [Credentials file](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-terms/#credentials-file).
             '';
           };
 
@@ -178,7 +178,7 @@ in
               description = ''
                 Enable warp routing.
 
-                See [https://developers.cloudflare.com/cloudflare-one/tutorials/warp-to-tunnel/](Connect from WARP to a private network on Cloudflare using Cloudflare Tunnel).
+                See [Connect from WARP to a private network on Cloudflare using Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/tutorials/warp-to-tunnel/).
               '';
             };
           };
@@ -204,7 +204,7 @@ in
                   description = ''
                     Service to pass the traffic.
 
-                    See [https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/#supported-protocols](Supported protocols).
+                    See [Supported protocols](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/#supported-protocols).
                   '';
                   example = "http://localhost:80, tcp://localhost:8000, unix:/home/production/echo.sock, hello_world or http_status:404";
                 };
@@ -226,7 +226,7 @@ in
             description = ''
               Ingress rules.
 
-              See [https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/](Ingress rules).
+              See [Ingress rules](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/configuration/local-management/ingress/).
             '';
             example = {
               "*.domain.com" = "http://localhost:80";
diff --git a/nixos/modules/services/networking/firefox-syncserver.nix b/nixos/modules/services/networking/firefox-syncserver.nix
index a9fcd883beb07..674a424fb0a42 100644
--- a/nixos/modules/services/networking/firefox-syncserver.nix
+++ b/nixos/modules/services/networking/firefox-syncserver.nix
@@ -316,7 +316,7 @@ in
   };
 
   meta = {
-    maintainers = with lib.maintainers; [ pennae ];
+    maintainers = with lib.maintainers; [ ];
     doc = ./firefox-syncserver.md;
   };
 }
diff --git a/nixos/modules/services/networking/gns3-server.nix b/nixos/modules/services/networking/gns3-server.nix
index b2f25b158bbbc..ec6a53dddc709 100644
--- a/nixos/modules/services/networking/gns3-server.nix
+++ b/nixos/modules/services/networking/gns3-server.nix
@@ -16,7 +16,7 @@ in {
     services.gns3-server = {
       enable = lib.mkEnableOption "GNS3 Server daemon";
 
-      package = lib.mkPackageOptionMD pkgs "gns3-server" { };
+      package = lib.mkPackageOption pkgs "gns3-server" { };
 
       auth = {
         enable = lib.mkEnableOption "password based HTTP authentication to access the GNS3 Server";
@@ -88,17 +88,17 @@ in {
 
       dynamips = {
         enable = lib.mkEnableOption ''Dynamips support'';
-        package = lib.mkPackageOptionMD pkgs "dynamips" { };
+        package = lib.mkPackageOption pkgs "dynamips" { };
       };
 
       ubridge = {
         enable = lib.mkEnableOption ''uBridge support'';
-        package = lib.mkPackageOptionMD pkgs "ubridge" { };
+        package = lib.mkPackageOption pkgs "ubridge" { };
       };
 
       vpcs = {
         enable = lib.mkEnableOption ''VPCS support'';
-        package = lib.mkPackageOptionMD pkgs "vpcs" { };
+        package = lib.mkPackageOption pkgs "vpcs" { };
       };
     };
   };
diff --git a/nixos/modules/services/networking/mihomo.nix b/nixos/modules/services/networking/mihomo.nix
index d4bb10496279d..a425952b54ced 100644
--- a/nixos/modules/services/networking/mihomo.nix
+++ b/nixos/modules/services/networking/mihomo.nix
@@ -2,10 +2,11 @@
 # cfg.configFile contains secrets such as proxy servers' credential!
 # we dont want plaintext secrets in world-readable `/nix/store`.
 
-{ lib
-, config
-, pkgs
-, ...
+{
+  lib,
+  config,
+  pkgs,
+  ...
 }:
 let
   cfg = config.services.mihomo;
@@ -17,7 +18,6 @@ in
     package = lib.mkPackageOption pkgs "mihomo" { };
 
     configFile = lib.mkOption {
-      default = null;
       type = lib.types.nullOr lib.types.path;
       description = "Configuration file to use.";
     };
@@ -67,7 +67,7 @@ in
           ExecStart = lib.concatStringsSep " " [
             (lib.getExe cfg.package)
             "-d /var/lib/private/mihomo"
-            (lib.optionalString (cfg.configFile != null) "-f \${CREDENTIALS_DIRECTORY}/config.yaml")
+            "-f \${CREDENTIALS_DIRECTORY}/config.yaml"
             (lib.optionalString (cfg.webui != null) "-ext-ui ${cfg.webui}")
             (lib.optionalString (cfg.extraOpts != null) cfg.extraOpts)
           ];
diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix
index 9825af47777e5..7baaf93a1bcfa 100644
--- a/nixos/modules/services/networking/mosquitto.nix
+++ b/nixos/modules/services/networking/mosquitto.nix
@@ -721,7 +721,7 @@ in
   };
 
   meta = {
-    maintainers = with lib.maintainers; [ pennae ];
+    maintainers = with lib.maintainers; [ ];
     doc = ./mosquitto.md;
   };
 }
diff --git a/nixos/modules/services/networking/networkd-dispatcher.nix b/nixos/modules/services/networking/networkd-dispatcher.nix
index 427835870e59f..cced406934c1a 100644
--- a/nixos/modules/services/networking/networkd-dispatcher.nix
+++ b/nixos/modules/services/networking/networkd-dispatcher.nix
@@ -13,7 +13,7 @@ in {
 
       enable = mkEnableOption ''
         Networkd-dispatcher service for systemd-networkd connection status
-        change. See [https://gitlab.com/craftyguy/networkd-dispatcher](upstream instructions)
+        change. See [upstream instructions](https://gitlab.com/craftyguy/networkd-dispatcher)
         for usage
       '';
 
@@ -35,7 +35,7 @@ in {
         '';
         description = ''
           Declarative configuration of networkd-dispatcher rules. See
-          [https://gitlab.com/craftyguy/networkd-dispatcher](upstream instructions)
+          [upstream instructions](https://gitlab.com/craftyguy/networkd-dispatcher)
           for an introduction and example scripts.
         '';
         type = types.attrsOf (types.submodule {
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index b7143cf520f96..fda8245ba97d1 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -127,7 +127,7 @@ in
 {
 
   meta = {
-    maintainers = teams.freedesktop.members ++ [ lib.maintainers.janik ];
+    maintainers = teams.freedesktop.members;
   };
 
   ###### interface
diff --git a/nixos/modules/services/networking/oink.nix b/nixos/modules/services/networking/oink.nix
index cd0fdf172331d..3497ca9220a80 100644
--- a/nixos/modules/services/networking/oink.nix
+++ b/nixos/modules/services/networking/oink.nix
@@ -77,6 +77,7 @@ in
   config = mkIf cfg.enable {
     systemd.services.oink = {
       description = "Dynamic DNS client for Porkbun";
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       script = "${cfg.package}/bin/oink -c ${oinkConfig}";
     };
diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix
index 0de07a9b870c6..9e54dfc17dfe7 100644
--- a/nixos/modules/services/networking/prosody.nix
+++ b/nixos/modules/services/networking/prosody.nix
@@ -266,6 +266,13 @@ let
     else if builtins.isList x then "{ ${lib.concatMapStringsSep ", " toLua x} }"
     else throw "Invalid Lua value";
 
+  settingsToLua = prefix: settings: generators.toKeyValue {
+    listsAsDuplicateKeys = false;
+    mkKeyValue = k: generators.mkKeyValueDefault {
+      mkValueString = toLua;
+    } " = " (prefix + k);
+  } (filterAttrs (k: v: v != null) settings);
+
   createSSLOptsStr = o: ''
     ssl = {
       cafile = "/etc/ssl/certs/ca-bundle.crt";
@@ -418,15 +425,26 @@ let
       httpUploadPath = mkOption {
         type = types.str;
         description = ''
-          Directory where the uploaded files will be stored. By
-          default, uploaded files are put in a sub-directory of the
-          default Prosody storage path (usually /var/lib/prosody).
+          Directory where the uploaded files will be stored when the http_upload module is used.
+          By default, uploaded files are put in a sub-directory of the default Prosody storage path (usually /var/lib/prosody).
         '';
         default = "/var/lib/prosody";
       };
     };
   };
 
+  httpFileShareOpts = { ... }: {
+    freeformType = with types;
+      let atom = oneOf [ int bool str (listOf atom) ]; in
+      attrsOf (nullOr atom) // {
+        description = "int, bool, string or list of them";
+      };
+    options.domain = mkOption {
+      type = with types; nullOr str;
+      description = "Domain name for a http_file_share service.";
+    };
+  };
+
   vHostOpts = { ... }: {
 
     options = {
@@ -650,7 +668,7 @@ in
 
       uploadHttp = mkOption {
         description = ''
-          Configures the Prosody builtin HTTP server to handle user uploads.
+          Configures the old Prosody builtin HTTP server to handle user uploads.
         '';
         type = types.nullOr (types.submodule uploadHttpOpts);
         default = null;
@@ -659,6 +677,17 @@ in
         };
       };
 
+      httpFileShare = mkOption {
+        description = ''
+          Configures the http_file_share module to handle user uploads.
+        '';
+        type = types.nullOr (types.submodule httpFileShareOpts);
+        default = null;
+        example = {
+          domain = "uploads.my-xmpp-example-host.org";
+        };
+      };
+
       muc = mkOption {
         type = types.listOf (types.submodule mucOpts);
         default = [ ];
@@ -716,6 +745,17 @@ in
         description = "Additional prosody configuration";
       };
 
+      log = mkOption {
+        type = types.lines;
+        default = ''"*syslog"'';
+        description = "Logging configuration. See [](https://prosody.im/doc/logging) for more details";
+        example = ''
+          {
+            { min = "warn"; to = "*syslog"; };
+          }
+        '';
+      };
+
     };
   };
 
@@ -740,11 +780,10 @@ in
             You need to setup at least a MUC domain to comply with
             XEP-0423.
           '' + genericErrMsg;}
-        { assertion = cfg.uploadHttp != null || !cfg.xmppComplianceSuite;
+        { assertion = cfg.uploadHttp != null || cfg.httpFileShare != null || !cfg.xmppComplianceSuite;
           message = ''
-            You need to setup the uploadHttp module through
-            config.services.prosody.uploadHttp to comply with
-            XEP-0423.
+            You need to setup the http_upload or http_file_share modules through config.services.prosody.uploadHttp
+            or config.services.prosody.httpFileShare to comply with XEP-0423.
           '' + genericErrMsg;}
       ];
     in errors;
@@ -753,8 +792,11 @@ in
 
     environment.etc."prosody/prosody.cfg.lua".text =
       let
-        httpDiscoItems = optionals (cfg.uploadHttp != null)
-            [{ url = cfg.uploadHttp.domain; description = "HTTP upload endpoint";}];
+        httpDiscoItems = optional (cfg.uploadHttp != null) {
+          url = cfg.uploadHttp.domain; description = "HTTP upload endpoint";
+        } ++ optional (cfg.httpFileShare != null) {
+          url = cfg.httpFileShare.domain; description = "HTTP file share endpoint";
+        };
         mucDiscoItems = builtins.foldl'
             (acc: muc: [{ url = muc.domain; description = "${muc.domain} MUC endpoint";}] ++ acc)
             []
@@ -764,7 +806,7 @@ in
 
       pidfile = "/run/prosody/prosody.pid"
 
-      log = "*syslog"
+      log = ${cfg.log}
 
       data_path = "${cfg.dataDir}"
       plugin_paths = {
@@ -833,7 +875,6 @@ in
         '') cfg.muc}
 
       ${ lib.optionalString (cfg.uploadHttp != null) ''
-        -- TODO: think about migrating this to mod-http_file_share instead.
         Component ${toLua cfg.uploadHttp.domain} "http_upload"
             http_upload_file_size_limit = ${cfg.uploadHttp.uploadFileSizeLimit}
             http_upload_expire_after = ${cfg.uploadHttp.uploadExpireAfter}
@@ -841,6 +882,11 @@ in
             http_upload_path = ${toLua cfg.uploadHttp.httpUploadPath}
       ''}
 
+      ${lib.optionalString (cfg.httpFileShare != null) ''
+        Component ${toLua cfg.httpFileShare.domain} "http_file_share"
+        ${settingsToLua "  http_file_share_" (cfg.httpFileShare // { domain = null; })}
+      ''}
+
       ${ lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
         VirtualHost "${v.domain}"
           enabled = ${boolToString v.enabled};
diff --git a/nixos/modules/services/networking/resilio.nix b/nixos/modules/services/networking/resilio.nix
index 395796d39db8e..c788069fbaa55 100644
--- a/nixos/modules/services/networking/resilio.nix
+++ b/nixos/modules/services/networking/resilio.nix
@@ -291,5 +291,5 @@ in
     };
   };
 
-  meta.maintainers = with maintainers; [ jwoudenberg ];
+  meta.maintainers = with maintainers; [ ];
 }
diff --git a/nixos/modules/services/networking/scion/scion-control.nix b/nixos/modules/services/networking/scion/scion-control.nix
index b86f1ef26b358..95d78a87ac859 100644
--- a/nixos/modules/services/networking/scion/scion-control.nix
+++ b/nixos/modules/services/networking/scion/scion-control.nix
@@ -12,13 +12,13 @@ let
       reconnect_to_dispatcher = true;
     };
     beacon_db = {
-      connection = "/var/lib/scion-control/control.beacon.db";
+      connection = "/run/scion-control/control.beacon.db";
     };
     path_db = {
-      connection = "/var/lib/scion-control/control.path.db";
+      connection = "/run/scion-control/control.path.db";
     };
     trust_db = {
-      connection = "/var/lib/scion-control/control.trust.db";
+      connection = "/run/scion-control/control.trust.db";
     };
     log.console = {
       level = "info";
@@ -35,7 +35,7 @@ in
       example = literalExpression ''
         {
           path_db = {
-            connection = "/var/lib/scion-control/control.path.db";
+            connection = "/run/scion-control/control.path.db";
           };
           log.console = {
             level = "info";
@@ -62,7 +62,7 @@ in
         DynamicUser = true;
         Restart = "on-failure";
         BindPaths = [ "/dev/shm:/run/shm" ];
-        StateDirectory = "scion-control";
+        RuntimeDirectory = "scion-control";
       };
     };
   };
diff --git a/nixos/modules/services/networking/scion/scion-daemon.nix b/nixos/modules/services/networking/scion/scion-daemon.nix
index a9c0c80f101f8..8528bec1d52eb 100644
--- a/nixos/modules/services/networking/scion/scion-daemon.nix
+++ b/nixos/modules/services/networking/scion/scion-daemon.nix
@@ -12,10 +12,10 @@ let
       reconnect_to_dispatcher = true;
     };
     path_db = {
-      connection = "/var/lib/scion-daemon/sd.path.db";
+      connection = "/run/scion-daemon/sd.path.db";
     };
     trust_db = {
-      connection = "/var/lib/scion-daemon/sd.trust.db";
+      connection = "/run/scion-daemon/sd.trust.db";
     };
     log.console = {
       level = "info";
@@ -32,7 +32,7 @@ in
       example = literalExpression ''
         {
           path_db = {
-            connection = "/var/lib/scion-daemon/sd.path.db";
+            connection = "/run/scion-daemon/sd.path.db";
           };
           log.console = {
             level = "info";
@@ -57,7 +57,7 @@ in
         ExecStart = "${pkgs.scion}/bin/scion-daemon --config ${configFile}";
         Restart = "on-failure";
         DynamicUser = true;
-        StateDirectory = "scion-daemon";
+        RuntimeDirectory = "scion-daemon";
       };
     };
   };
diff --git a/nixos/modules/services/networking/scion/scion-dispatcher.nix b/nixos/modules/services/networking/scion/scion-dispatcher.nix
index 9118ebefa18f3..7c9f5e6a385ee 100644
--- a/nixos/modules/services/networking/scion/scion-dispatcher.nix
+++ b/nixos/modules/services/networking/scion/scion-dispatcher.nix
@@ -66,7 +66,7 @@ in
         ExecStartPre = "${pkgs.coreutils}/bin/rm -rf /run/shm/dispatcher";
         ExecStart = "${pkgs.scion}/bin/scion-dispatcher --config ${configFile}";
         Restart = "on-failure";
-        StateDirectory = "scion-dispatcher";
+        RuntimeDirectory = "scion-dispatcher";
       };
     };
   };
diff --git a/nixos/modules/services/networking/scion/scion-router.nix b/nixos/modules/services/networking/scion/scion-router.nix
index 3579005a429ed..2cac44ab767ef 100644
--- a/nixos/modules/services/networking/scion/scion-router.nix
+++ b/nixos/modules/services/networking/scion/scion-router.nix
@@ -42,7 +42,7 @@ in
         ExecStart = "${pkgs.scion}/bin/scion-router --config ${configFile}";
         Restart = "on-failure";
         DynamicUser = true;
-        StateDirectory = "scion-router";
+        RuntimeDirectory = "scion-router";
       };
     };
   };
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index 3fb3eac45cc82..a07cde847cf69 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -337,7 +337,11 @@ in
     };
 
     # use nginx to serve the smokeping web service
-    services.fcgiwrap.enable = mkIf cfg.webService true;
+    services.fcgiwrap.smokeping = mkIf cfg.webService {
+      process.user = cfg.user;
+      process.group = cfg.user;
+      socket = { inherit (config.services.nginx) user group; };
+    };
     services.nginx = mkIf cfg.webService {
       enable = true;
       virtualHosts."smokeping" = {
@@ -349,7 +353,7 @@ in
         locations."/smokeping.fcgi" = {
           extraConfig = ''
             include ${config.services.nginx.package}/conf/fastcgi_params;
-            fastcgi_pass unix:${config.services.fcgiwrap.socketAddress};
+            fastcgi_pass unix:${config.services.fcgiwrap.smokeping.socket.address};
             fastcgi_param SCRIPT_FILENAME ${smokepingHome}/smokeping.fcgi;
             fastcgi_param DOCUMENT_ROOT ${smokepingHome};
           '';
diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix
index 45503ef89aaa1..94ff838b50e04 100644
--- a/nixos/modules/services/networking/syncthing.nix
+++ b/nixos/modules/services/networking/syncthing.nix
@@ -368,6 +368,15 @@ in {
                     '';
                   };
 
+                  type = mkOption {
+                    type = types.enum [ "sendreceive" "sendonly" "receiveonly" "receiveencrypted" ];
+                    default = "sendreceive";
+                    description = ''
+                      Controls how the folder is handled by Syncthing.
+                      See <https://docs.syncthing.net/users/config.html#config-option-folder.type>.
+                    '';
+                  };
+
                   devices = mkOption {
                     type = types.listOf types.str;
                     default = [];
diff --git a/nixos/modules/services/networking/xrdp.nix b/nixos/modules/services/networking/xrdp.nix
index 884325d13159b..d571c6e4d88d7 100644
--- a/nixos/modules/services/networking/xrdp.nix
+++ b/nixos/modules/services/networking/xrdp.nix
@@ -51,11 +51,11 @@ in
 
       enable = mkEnableOption "xrdp, the Remote Desktop Protocol server";
 
-      package = mkPackageOptionMD pkgs "xrdp" { };
+      package = mkPackageOption pkgs "xrdp" { };
 
       audio = {
         enable = mkEnableOption "audio support for xrdp sessions. So far it only works with PulseAudio sessions on the server side. No PipeWire support yet";
-        package = mkPackageOptionMD pkgs "pulseaudio-module-xrdp" {};
+        package = mkPackageOption pkgs "pulseaudio-module-xrdp" {};
       };
 
       port = mkOption {
diff --git a/nixos/modules/services/search/hound.nix b/nixos/modules/services/search/hound.nix
index e3f9c8da3752a..7aca1adc19b08 100644
--- a/nixos/modules/services/search/hound.nix
+++ b/nixos/modules/services/search/hound.nix
@@ -1,71 +1,66 @@
 { config, lib, pkgs, ... }:
-with lib;
 let
   cfg = config.services.hound;
+  settingsFormat = pkgs.formats.json { };
 in {
   imports = [
     (lib.mkRemovedOptionModule [ "services" "hound" "extraGroups" ] "Use users.users.hound.extraGroups instead")
+    (lib.mkChangedOptionModule [ "services" "hound" "config" ] [ "services" "hound" "settings" ] (config: builtins.fromJSON config.services.hound.config))
   ];
 
-  meta.maintainers = with maintainers; [ SuperSandro2000 ];
+  meta.maintainers = with lib.maintainers; [ SuperSandro2000 ];
 
   options = {
     services.hound = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to enable the hound code search daemon.
-        '';
-      };
+      enable = lib.mkEnableOption "hound";
 
-      package = mkPackageOptionMD pkgs "hound" { };
+      package = lib.mkPackageOption pkgs "hound" { };
 
-      user = mkOption {
+      user = lib.mkOption {
         default = "hound";
-        type = types.str;
+        type = lib.types.str;
         description = ''
           User the hound daemon should execute under.
         '';
       };
 
-      group = mkOption {
+      group = lib.mkOption {
         default = "hound";
-        type = types.str;
+        type = lib.types.str;
         description = ''
           Group the hound daemon should execute under.
         '';
       };
 
-      home = mkOption {
+      home = lib.mkOption {
         default = "/var/lib/hound";
-        type = types.path;
+        type = lib.types.path;
         description = ''
           The path to use as hound's $HOME.
           If the default user "hound" is configured then this is the home of the "hound" user.
         '';
       };
 
-      config = mkOption {
-        type = types.str;
-        description = ''
-          The full configuration of the Hound daemon. Note the dbpath
-          should be an absolute path to a writable location on disk.
-        '';
-        example = literalExpression ''
+      settings = lib.mkOption {
+        type = settingsFormat.type;
+        example = lib.literalExpression ''
           {
-            "max-concurrent-indexers" : 2,
-            "repos" : {
-                "nixpkgs": {
-                  "url" : "https://www.github.com/NixOS/nixpkgs.git"
-                }
-            }
+            max-concurrent-indexers = 2;
+            repos.nixpkgs.url = "https://www.github.com/NixOS/nixpkgs.git";
           }
         '';
+        description = ''
+          The full configuration of the Hound daemon.
+          See the upstream documentation <https://github.com/hound-search/hound/blob/main/docs/config-options.md> for details.
+
+          :::{.note}
+          The `dbpath` should be an absolute path to a writable directory.
+          :::.com/hound-search/hound/blob/main/docs/config-options.md>.
+        '';
       };
 
-      listen = mkOption {
-        type = types.str;
+      listen = lib.mkOption {
+        type = lib.types.str;
         default = "0.0.0.0:6080";
         example = ":6080";
         description = ''
@@ -75,7 +70,7 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
     users.groups = lib.mkIf (cfg.group == "hound") {
       hound = { };
     };
@@ -89,16 +84,19 @@ in {
       };
     };
 
-    systemd.services.hound = let
-      configFile = pkgs.writeTextFile {
-        name = "hound.json";
-        text = cfg.config;
-        checkPhase = ''
-          # check if the supplied text is valid json
-          ${lib.getExe pkgs.jq} . $target > /dev/null
-        '';
-      };
-    in {
+    environment.etc."hound/config.json".source = pkgs.writeTextFile {
+      name = "hound-config";
+      text = builtins.toJSON cfg.settings;
+      checkPhase = ''
+        ${cfg.package}/bin/houndd -check-conf -conf $out
+      '';
+    };
+
+    services.hound.settings = {
+      dbpath = "${config.services.hound.home}/data";
+    };
+
+    systemd.services.hound = {
       description = "Hound Code Search";
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
@@ -107,7 +105,7 @@ in {
         Group = cfg.group;
         WorkingDirectory = cfg.home;
         ExecStartPre = "${pkgs.git}/bin/git config --global --replace-all http.sslCAinfo /etc/ssl/certs/ca-certificates.crt";
-        ExecStart = "${cfg.package}/bin/houndd -addr ${cfg.listen} -conf ${configFile}";
+        ExecStart = "${cfg.package}/bin/houndd -addr ${cfg.listen} -conf /etc/hound/config.json";
       };
     };
   };
diff --git a/nixos/modules/services/security/sks.nix b/nixos/modules/services/security/sks.nix
index 520da45c94e2f..20d2dadbb7e22 100644
--- a/nixos/modules/services/security/sks.nix
+++ b/nixos/modules/services/security/sks.nix
@@ -10,7 +10,7 @@ let
   '';
 
 in {
-  meta.maintainers = with maintainers; [ primeos calbrecht jcumming ];
+  meta.maintainers = with maintainers; [ calbrecht jcumming ];
 
   options = {
 
diff --git a/nixos/modules/services/security/yubikey-agent.nix b/nixos/modules/services/security/yubikey-agent.nix
index 991f6a5595451..6a4dc7014970a 100644
--- a/nixos/modules/services/security/yubikey-agent.nix
+++ b/nixos/modules/services/security/yubikey-agent.nix
@@ -10,7 +10,7 @@ in
 {
   ###### interface
 
-  meta.maintainers = with maintainers; [ philandstuff rawkode jwoudenberg ];
+  meta.maintainers = with maintainers; [ philandstuff rawkode ];
 
   options = {
 
diff --git a/nixos/modules/services/system/cloud-init.nix b/nixos/modules/services/system/cloud-init.nix
index 5d7258cac7780..7148d62b90842 100644
--- a/nixos/modules/services/system/cloud-init.nix
+++ b/nixos/modules/services/system/cloud-init.nix
@@ -16,6 +16,7 @@ let
   ++ optional cfg.btrfs.enable btrfs-progs
   ++ optional cfg.ext4.enable e2fsprogs
   ++ optional cfg.xfs.enable xfsprogs
+  ++ cfg.extraPackages
   ;
   hasFs = fsName: lib.any (fs: fs.fsType == fsName) (lib.attrValues config.fileSystems);
   settingsFormat = pkgs.formats.yaml { };
@@ -79,6 +80,14 @@ in
         '';
       };
 
+      extraPackages = mkOption {
+        type = types.listOf types.package;
+        default = [ ];
+        description = ''
+          List of additional packages to be available within cloud-init jobs.
+        '';
+      };
+
       settings = mkOption {
         description = ''
           Structured cloud-init configuration.
@@ -163,7 +172,7 @@ in
         { text = cfg.config; }
     ;
 
-    systemd.network.enable = cfg.network.enable;
+    systemd.network.enable = mkIf cfg.network.enable true;
 
     systemd.services.cloud-init-local = {
       description = "Initial cloud-init job (pre-networking)";
diff --git a/nixos/modules/services/torrent/rtorrent.nix b/nixos/modules/services/torrent/rtorrent.nix
index e0ce33d13462e..609b06b5e7066 100644
--- a/nixos/modules/services/torrent/rtorrent.nix
+++ b/nixos/modules/services/torrent/rtorrent.nix
@@ -182,7 +182,7 @@ in {
 
       # XMLRPC
       scgi_local = (cfg.rpcsock)
-      schedule = scgi_group,0,0,"execute.nothrow=chown,\":rtorrent\",(cfg.rpcsock)"
+      schedule = scgi_group,0,0,"execute.nothrow=chown,\":${cfg.group}\",(cfg.rpcsock)"
       schedule = scgi_permission,0,0,"execute.nothrow=chmod,\"g+w,o=\",(cfg.rpcsock)"
     '';
 
diff --git a/nixos/modules/services/ttys/kmscon.nix b/nixos/modules/services/ttys/kmscon.nix
index 4803d577b94b1..6b05886756fe2 100644
--- a/nixos/modules/services/ttys/kmscon.nix
+++ b/nixos/modules/services/ttys/kmscon.nix
@@ -41,6 +41,12 @@ in {
           }; in nullOr (nonEmptyListOf fontType);
       };
 
+      useXkbConfig = mkOption {
+        description = "Configure keymap from xserver keyboard settings.";
+        type = types.bool;
+        default = false;
+      };
+
       extraConfig = mkOption {
         description = "Extra contents of the kmscon.conf file.";
         type = types.lines;
@@ -91,9 +97,15 @@ in {
 
     services.kmscon.extraConfig =
       let
+        xkb = optionals cfg.useXkbConfig
+          (lib.mapAttrsToList (n: v: "xkb-${n}=${v}") (
+            lib.filterAttrs
+              (n: v: builtins.elem n ["layout" "model" "options" "variant"] && v != "")
+              config.services.xserver.xkb
+          ));
         render = optionals cfg.hwRender [ "drm" "hwaccel" ];
         fonts = optional (cfg.fonts != null) "font-name=${lib.concatMapStringsSep ", " (f: f.name) cfg.fonts}";
-      in lib.concatStringsSep "\n" (render ++ fonts);
+      in lib.concatStringsSep "\n" (xkb ++ render ++ fonts);
 
     hardware.graphics.enable = mkIf cfg.hwRender true;
 
diff --git a/nixos/modules/services/web-apps/code-server.nix b/nixos/modules/services/web-apps/code-server.nix
index abb5be50d353e..f94a1a8b53fa4 100644
--- a/nixos/modules/services/web-apps/code-server.nix
+++ b/nixos/modules/services/web-apps/code-server.nix
@@ -9,7 +9,7 @@ in {
     services.code-server = {
       enable = lib.mkEnableOption "code-server";
 
-      package = lib.mkPackageOptionMD pkgs "code-server" {
+      package = lib.mkPackageOption pkgs "code-server" {
         example = ''
           pkgs.vscode-with-extensions.override {
             vscode = pkgs.code-server;
diff --git a/nixos/modules/services/web-apps/eintopf.nix b/nixos/modules/services/web-apps/eintopf.nix
new file mode 100644
index 0000000000000..a2b304445597e
--- /dev/null
+++ b/nixos/modules/services/web-apps/eintopf.nix
@@ -0,0 +1,92 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.eintopf;
+
+in {
+  options.services.eintopf = {
+
+    enable = mkEnableOption "Eintopf community event calendar web app";
+
+    settings = mkOption {
+      type = types.attrsOf types.str;
+      default = { };
+      description = ''
+        Settings to configure web service. See
+        <https://codeberg.org/Klasse-Methode/eintopf/src/branch/main/DEPLOYMENT.md>
+        for available options.
+      '';
+      example = literalExpression ''
+        {
+          EINTOPF_ADDR = ":1234";
+          EINTOPF_ADMIN_EMAIL = "admin@example.org";
+          EINTOPF_TIMEZONE = "Europe/Berlin";
+        }
+      '';
+    };
+
+    secrets = lib.mkOption {
+      type = with types; listOf path;
+      description = ''
+        A list of files containing the various secrets. Should be in the
+        format expected by systemd's `EnvironmentFile` directory.
+      '';
+      default = [ ];
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.eintopf = {
+      description = "Community event calendar web app";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-online.target" ];
+      wants = [ "network-online.target" ];
+      environment = cfg.settings;
+      serviceConfig = {
+        ExecStart = "${pkgs.eintopf}/bin/eintopf";
+        WorkingDirectory = "/var/lib/eintopf";
+        StateDirectory = "eintopf" ;
+        EnvironmentFile = [ cfg.secrets ];
+
+        # hardening
+        AmbientCapabilities = "";
+        CapabilityBoundingSet = "" ;
+        DevicePolicy = "closed";
+        DynamicUser = true;
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        PrivateUsers = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        RemoveIPC = true;
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [ "@system-service" "~@privileged" ];
+        UMask = "0077";
+      };
+    };
+
+  };
+
+  meta.maintainers = with lib.maintainers; [ onny ];
+
+}
diff --git a/nixos/modules/services/web-apps/freshrss.nix b/nixos/modules/services/web-apps/freshrss.nix
index 021101fecaa48..7a22e15231923 100644
--- a/nixos/modules/services/web-apps/freshrss.nix
+++ b/nixos/modules/services/web-apps/freshrss.nix
@@ -5,6 +5,15 @@ let
   cfg = config.services.freshrss;
 
   poolName = "freshrss";
+
+  extension-env = pkgs.buildEnv {
+    name = "freshrss-extensions";
+    paths = cfg.extensions;
+  };
+  env-vars = {
+    DATA_PATH = cfg.dataDir;
+    THIRDPARTY_EXTENSIONS_PATH = "${extension-env}/share/freshrss/";
+  };
 in
 {
   meta.maintainers = with maintainers; [ etu stunkymonkey mattchrist ];
@@ -14,6 +23,31 @@ in
 
     package = mkPackageOption pkgs "freshrss" { };
 
+    extensions = mkOption {
+      type = types.listOf types.package;
+      default = [ ];
+      defaultText = literalExpression "[]";
+      example = literalExpression ''
+        with freshrss-extensions; [
+          youtube
+        ] ++ [
+          (freshrss-extensions.buildFreshRssExtension {
+            FreshRssExtUniqueId = "ReadingTime";
+            pname = "reading-time";
+            version = "1.5";
+            src = pkgs.fetchFromGitLab {
+              domain = "framagit.org";
+              owner = "Lapineige";
+              repo = "FreshRSS_Extension-ReadingTime";
+              rev = "fb6e9e944ef6c5299fa56ffddbe04c41e5a34ebf";
+             hash = "sha256-C5cRfaphx4Qz2xg2z+v5qRji8WVSIpvzMbethTdSqsk=";
+           };
+          })
+        ]
+      '';
+      description = "Additional extensions to be used.";
+    };
+
     defaultUser = mkOption {
       type = types.str;
       default = "admin";
@@ -214,9 +248,7 @@ in
             "pm.max_spare_servers" = 5;
             "catch_workers_output" = true;
           };
-          phpEnv = {
-            DATA_PATH = "${cfg.dataDir}";
-          };
+          phpEnv = env-vars;
         };
       };
 
@@ -259,9 +291,7 @@ in
             RemainAfterExit = true;
           };
           restartIfChanged = true;
-          environment = {
-            DATA_PATH = cfg.dataDir;
-          };
+          environment = env-vars;
 
           script =
             let
@@ -293,9 +323,7 @@ in
         description = "FreshRSS feed updater";
         after = [ "freshrss-config.service" ];
         startAt = "*:0/5";
-        environment = {
-          DATA_PATH = cfg.dataDir;
-        };
+        environment = env-vars;
         serviceConfig = defaultServiceConfig // {
           ExecStart = "${cfg.package}/app/actualize_script.php";
         };
diff --git a/nixos/modules/services/web-apps/healthchecks.nix b/nixos/modules/services/web-apps/healthchecks.nix
index 5562b37e502c6..c7db999a62c21 100644
--- a/nixos/modules/services/web-apps/healthchecks.nix
+++ b/nixos/modules/services/web-apps/healthchecks.nix
@@ -11,7 +11,7 @@ let
   environment = {
     PYTHONPATH = pkg.pythonPath;
     STATIC_ROOT = cfg.dataDir + "/static";
-  } // cfg.settings;
+  } // lib.filterAttrs (_: v: !builtins.isNull v) cfg.settings;
 
   environmentFile = pkgs.writeText "healthchecks-environment" (lib.generators.toKeyValue { } environment);
 
@@ -21,6 +21,7 @@ let
       sudo='exec /run/wrappers/bin/sudo -u ${cfg.user} --preserve-env --preserve-env=PYTHONPATH'
     fi
     export $(cat ${environmentFile} | xargs)
+    ${lib.optionalString (cfg.settingsFile != null) "export $(cat ${cfg.settingsFile} | xargs)"}
     $sudo ${pkg}/opt/healthchecks/manage.py "$@"
   '';
 in
@@ -89,6 +90,12 @@ in
       '';
     };
 
+    settingsFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
+      default = null;
+      description = opt.settings.description;
+    };
+
     settings = lib.mkOption {
       description = ''
         Environment variables which are read by healthchecks `(local)_settings.py`.
@@ -109,6 +116,8 @@ in
           have support for a `_FILE` variant, run:
           - `nix-instantiate --eval --expr '(import <nixpkgs> {}).healthchecks.secrets'`
           - or `nix eval 'nixpkgs#healthchecks.secrets'` if the flake support has been enabled.
+
+        If the same variable is set in both `settings` and `settingsFile` the value from `settingsFile` has priority.
       '';
       type = types.submodule (settings: {
         freeformType = types.attrsOf types.str;
@@ -121,8 +130,9 @@ in
           };
 
           SECRET_KEY_FILE = mkOption {
-            type = types.path;
+            type = types.nullOr types.path;
             description = "Path to a file containing the secret key.";
+            default = null;
           };
 
           DEBUG = mkOption {
@@ -186,7 +196,9 @@ in
           WorkingDirectory = cfg.dataDir;
           User = cfg.user;
           Group = cfg.group;
-          EnvironmentFile = [ environmentFile ];
+          EnvironmentFile = [
+            environmentFile
+          ] ++ lib.optional (cfg.settingsFile != null) cfg.settingsFile;
           StateDirectory = mkIf (cfg.dataDir == "/var/lib/healthchecks") "healthchecks";
           StateDirectoryMode = mkIf (cfg.dataDir == "/var/lib/healthchecks") "0750";
         };
diff --git a/nixos/modules/services/web-apps/invidious.nix b/nixos/modules/services/web-apps/invidious.nix
index f0e860383a62c..7997ea1f36308 100644
--- a/nixos/modules/services/web-apps/invidious.nix
+++ b/nixos/modules/services/web-apps/invidious.nix
@@ -390,7 +390,7 @@ in
         '';
       };
 
-      package = lib.mkPackageOptionMD pkgs "http3-ytproxy" { };
+      package = lib.mkPackageOption pkgs "http3-ytproxy" { };
     };
   };
 
diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix
index 36bae2575974e..5d429675bafcf 100644
--- a/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixos/modules/services/web-apps/keycloak.nix
@@ -328,7 +328,7 @@ in
             };
 
             hostname = mkOption {
-              type = str;
+              type = nullOr str;
               example = "keycloak.example.com";
               description = ''
                 The hostname part of the public URL used as base for
@@ -478,6 +478,10 @@ in
             message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably";
           }
           {
+            assertion = cfg.settings.hostname != null || ! cfg.settings.hostname-strict or true;
+            message = "Setting the Keycloak hostname is required, see `services.keycloak.settings.hostname`";
+          }
+          {
             assertion = cfg.settings.hostname-url or null == null;
             message = ''
               The option `services.keycloak.settings.hostname-url' has been removed.
diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix
index cdd60f572b990..dbcd9eae2d29a 100644
--- a/nixos/modules/services/web-apps/limesurvey.nix
+++ b/nixos/modules/services/web-apps/limesurvey.nix
@@ -18,7 +18,15 @@ let
 
   limesurveyConfig = pkgs.writeText "config.php" ''
     <?php
-      return json_decode('${builtins.toJSON cfg.config}', true);
+      return \array_merge(
+        \json_decode('${builtins.toJSON cfg.config}', true),
+        [
+          'config' => [
+            'encryptionnonce' => \trim(\file_get_contents(\getenv('CREDENTIALS_DIRECTORY') . DIRECTORY_SEPARATOR . 'encryption_nonce')),
+            'encryptionsecretboxkey' => \trim(\file_get_contents(\getenv('CREDENTIALS_DIRECTORY') . DIRECTORY_SEPARATOR . 'encryption_key')),
+          ]
+        ]
+      );
     ?>
   '';
 
@@ -35,8 +43,9 @@ in
     package = mkPackageOption pkgs "limesurvey" { };
 
     encryptionKey = mkOption {
-      type = types.str;
-      default = "E17687FC77CEE247F0E22BB3ECF27FDE8BEC310A892347EC13013ABA11AA7EB5";
+      type = types.nullOr types.str;
+      default = null;
+      visible = false;
       description = ''
         This is a 32-byte key used to encrypt variables in the database.
         You _must_ change this from the default value.
@@ -44,14 +53,35 @@ in
     };
 
     encryptionNonce = mkOption {
-      type = types.str;
-      default = "1ACC8555619929DB91310BE848025A427B0F364A884FFA77";
+      type = types.nullOr types.str;
+      default = null;
+      visible = false;
       description = ''
         This is a 24-byte nonce used to encrypt variables in the database.
         You _must_ change this from the default value.
       '';
     };
 
+    encryptionKeyFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        32-byte key used to encrypt variables in the database.
+
+        Note: It should be string not a store path in order to prevent the password from being world readable
+      '';
+    };
+
+    encryptionNonceFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        24-byte used to encrypt variables in the database.
+
+        Note: It should be string not a store path in order to prevent the password from being world readable
+      '';
+    };
+
     database = {
       type = mkOption {
         type = types.enum [ "mysql" "pgsql" "odbc" "mssql" ];
@@ -183,6 +213,22 @@ in
       { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
         message = "a password cannot be specified if services.limesurvey.database.createLocally is set to true";
       }
+      { assertion = cfg.encryptionKey != null || cfg.encryptionKeyFile != null;
+        message = ''
+          You must set `services.limesurvey.encryptionKeyFile` to a file containing a 32-character uppercase hex string.
+
+          If this message appears when updating your system, please turn off encryption
+          in the LimeSurvey interface and create backups before filling the key.
+        '';
+      }
+      { assertion = cfg.encryptionNonce != null || cfg.encryptionNonceFile != null;
+        message = ''
+          You must set `services.limesurvey.encryptionNonceFile` to a file containing a 24-character uppercase hex string.
+
+          If this message appears when updating your system, please turn off encryption
+          in the LimeSurvey interface and create backups before filling the nonce.
+        '';
+      }
     ];
 
     services.limesurvey.config = mapAttrs (name: mkDefault) {
@@ -204,8 +250,6 @@ in
       config = {
         tempdir = "${stateDir}/tmp";
         uploaddir = "${stateDir}/upload";
-        encryptionnonce = cfg.encryptionNonce;
-        encryptionsecretboxkey = cfg.encryptionKey;
         force_ssl = mkIf (cfg.virtualHost.addSSL || cfg.virtualHost.forceSSL || cfg.virtualHost.onlySSL) "on";
         config.defaultlang = "en";
       };
@@ -229,11 +273,26 @@ in
       phpPackage = pkgs.php81;
       phpEnv.DBENGINE = "${cfg.database.dbEngine}";
       phpEnv.LIMESURVEY_CONFIG = "${limesurveyConfig}";
+      # App code cannot access credentials directly since the service starts
+      # with the root user so we copy the credentials to a place accessible to Limesurvey
+      phpEnv.CREDENTIALS_DIRECTORY = "${stateDir}/credentials";
       settings = {
         "listen.owner" = config.services.httpd.user;
         "listen.group" = config.services.httpd.group;
       } // cfg.poolConfig;
     };
+    systemd.services.phpfpm-limesurvey.serviceConfig = {
+      ExecStartPre = pkgs.writeShellScript "limesurvey-phpfpm-exec-pre" ''
+        cp -f "''${CREDENTIALS_DIRECTORY}"/encryption_key "${stateDir}/credentials/encryption_key"
+        chown ${user}:${group} "${stateDir}/credentials/encryption_key"
+        cp -f "''${CREDENTIALS_DIRECTORY}"/encryption_nonce "${stateDir}/credentials/encryption_nonce"
+        chown ${user}:${group} "${stateDir}/credentials/encryption_nonce"
+      '';
+      LoadCredential = [
+        "encryption_key:${if cfg.encryptionKeyFile != null then cfg.encryptionKeyFile else pkgs.writeText "key" cfg.encryptionKey}"
+        "encryption_nonce:${if cfg.encryptionNonceFile != null then cfg.encryptionNonceFile else pkgs.writeText "nonce" cfg.encryptionKey}"
+      ];
+    };
 
     services.httpd = {
       enable = true;
@@ -277,6 +336,7 @@ in
       "d ${stateDir}/tmp/assets 0750 ${user} ${group} - -"
       "d ${stateDir}/tmp/runtime 0750 ${user} ${group} - -"
       "d ${stateDir}/tmp/upload 0750 ${user} ${group} - -"
+      "d ${stateDir}/credentials 0700 ${user} ${group} - -"
       "C ${stateDir}/upload 0750 ${user} ${group} - ${cfg.package}/share/limesurvey/upload"
     ];
 
@@ -295,6 +355,10 @@ in
         User = user;
         Group = group;
         Type = "oneshot";
+        LoadCredential = [
+          "encryption_key:${if cfg.encryptionKeyFile != null then cfg.encryptionKeyFile else pkgs.writeText "key" cfg.encryptionKey}"
+          "encryption_nonce:${if cfg.encryptionNonceFile != null then cfg.encryptionNonceFile else pkgs.writeText "nonce" cfg.encryptionKey}"
+        ];
       };
     };
 
diff --git a/nixos/modules/services/web-apps/nextcloud.md b/nixos/modules/services/web-apps/nextcloud.md
index 0b615deae44be..c433be5350b53 100644
--- a/nixos/modules/services/web-apps/nextcloud.md
+++ b/nixos/modules/services/web-apps/nextcloud.md
@@ -121,6 +121,29 @@ Auto updates for Nextcloud apps can be enabled using
     This is not an end-to-end encryption, but can be used to encrypt files that will be persisted
     to external storage such as S3.
 
+  - **Issues with file permissions / unsafe path transitions**
+
+    {manpage}`systemd-tmpfiles(8)` makes sure that the paths for
+
+    * configuration (including declarative config)
+    * data
+    * app store
+    * home directory itself (usually `/var/lib/nextcloud`)
+
+    are properly set up. However, `systemd-tmpfiles` will refuse to do so
+    if it detects an unsafe path transition, i.e. creating files/directories
+    within a directory that is neither owned by `root` nor by `nextcloud`, the
+    owning user of the files/directories to be created.
+
+    Symptoms of that include
+
+    * `config/override.config.php` not being updated (and the config file
+      eventually being garbage-collected).
+    * failure to read from application data.
+
+    To work around that, please make sure that all directories in question
+    are owned by `nextcloud:nextcloud`.
+
 ## Using an alternative webserver as reverse-proxy (e.g. `httpd`) {#module-services-nextcloud-httpd}
 
 By default, `nginx` is used as reverse-proxy for `nextcloud`.
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index bfb3e73e65102..c8c4fe4b4d612 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -91,10 +91,10 @@ let
     cd ${webroot}
     sudo=exec
     if [[ "$USER" != nextcloud ]]; then
-      sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR --preserve-env=OC_PASS'
+      sudo='exec /run/wrappers/bin/sudo -u nextcloud'
     fi
-    export NEXTCLOUD_CONFIG_DIR="${datadir}/config"
-    $sudo \
+    $sudo ${pkgs.coreutils}/bin/env \
+      NEXTCLOUD_CONFIG_DIR="${datadir}/config" \
       ${phpCli} \
       occ "$@"
   '';
diff --git a/nixos/modules/services/web-apps/peering-manager.nix b/nixos/modules/services/web-apps/peering-manager.nix
index c85cb76e5ea11..acdc393745293 100644
--- a/nixos/modules/services/web-apps/peering-manager.nix
+++ b/nixos/modules/services/web-apps/peering-manager.nix
@@ -16,6 +16,8 @@ let
       ln -s ${configFile} $out/opt/peering-manager/peering_manager/configuration.py
     '' + lib.optionalString cfg.enableLdap ''
       ln -s ${cfg.ldapConfigPath} $out/opt/peering-manager/peering_manager/ldap_config.py
+    '' + lib.optionalString cfg.enableOidc ''
+      ln -s ${cfg.oidcConfigPath} $out/opt/peering-manager/peering_manager/oidc_config.py
     '';
   })).override {
     inherit (cfg) plugins;
@@ -139,6 +141,24 @@ in {
         See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6-ldap/#configuration) for possible options.
       '';
     };
+
+    enableOidc = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable OIDC-Authentication for Peering Manager.
+
+        This requires a configuration file being pass through `oidcConfigPath`.
+      '';
+    };
+
+    oidcConfigPath = mkOption {
+      type = types.path;
+      description = ''
+        Path to the Configuration-File for OIDC-Authentication, will be loaded as `oidc_config.py`.
+        See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6b-oidc/#configuration) for possible options.
+      '';
+    };
   };
 
   config = lib.mkIf cfg.enable {
@@ -173,7 +193,10 @@ in {
           PEERINGDB_API_KEY = file.readline()
       '';
 
-      plugins = lib.mkIf cfg.enableLdap (ps: [ ps.django-auth-ldap ]);
+      plugins = (ps:
+        (lib.optionals cfg.enableLdap [ ps.django-auth-ldap ]) ++
+        (lib.optionals cfg.enableOidc (with ps; [ mozilla-django-oidc pyopenssl josepy ]))
+      );
     };
 
     system.build.peeringManagerPkg = pkg;
diff --git a/nixos/modules/services/web-apps/pixelfed.nix b/nixos/modules/services/web-apps/pixelfed.nix
index cd0e8f62b65c8..46d671f8504b6 100644
--- a/nixos/modules/services/web-apps/pixelfed.nix
+++ b/nixos/modules/services/web-apps/pixelfed.nix
@@ -40,7 +40,7 @@ in {
     pixelfed = {
       enable = mkEnableOption "a Pixelfed instance";
       package = mkPackageOption pkgs "pixelfed" { };
-      phpPackage = mkPackageOption pkgs "php81" { };
+      phpPackage = mkPackageOption pkgs "php82" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixos/modules/services/web-apps/pretalx.nix b/nixos/modules/services/web-apps/pretalx.nix
index 1411d11982c87..2280d9165b40b 100644
--- a/nixos/modules/services/web-apps/pretalx.nix
+++ b/nixos/modules/services/web-apps/pretalx.nix
@@ -35,7 +35,7 @@ in
   options.services.pretalx = {
     enable = lib.mkEnableOption "pretalx";
 
-    package = lib.mkPackageOptionMD pkgs "pretalx" {};
+    package = lib.mkPackageOption pkgs "pretalx" {};
 
     group = lib.mkOption {
       type = lib.types.str;
diff --git a/nixos/modules/services/web-apps/shiori.nix b/nixos/modules/services/web-apps/shiori.nix
index 022bb5e438812..df3eeaef16183 100644
--- a/nixos/modules/services/web-apps/shiori.nix
+++ b/nixos/modules/services/web-apps/shiori.nix
@@ -1,17 +1,15 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-let
-  cfg = config.services.shiori;
+let cfg = config.services.shiori;
 in {
   options = {
     services.shiori = {
-      enable = mkEnableOption "Shiori simple bookmarks manager";
+      enable = lib.mkEnableOption "Shiori simple bookmarks manager";
 
-      package = mkPackageOption pkgs "shiori" { };
+      package = lib.mkPackageOption pkgs "shiori" { };
 
-      address = mkOption {
-        type = types.str;
+      address = lib.mkOption {
+        type = lib.types.str;
         default = "";
         description = ''
           The IP address on which Shiori will listen.
@@ -19,30 +17,55 @@ in {
         '';
       };
 
-      port = mkOption {
-        type = types.port;
+      port = lib.mkOption {
+        type = lib.types.port;
         default = 8080;
         description = "The port of the Shiori web application";
       };
 
-      webRoot = mkOption {
-        type = types.str;
+      webRoot = lib.mkOption {
+        type = lib.types.str;
         default = "/";
         example = "/shiori";
         description = "The root of the Shiori web application";
       };
+
+      environmentFile = lib.mkOption {
+        type = lib.types.nullOr lib.types.path;
+        default = null;
+        example = "/path/to/environmentFile";
+        description = ''
+          Path to file containing environment variables.
+          Useful for passing down secrets.
+          <https://github.com/go-shiori/shiori/blob/master/docs/Configuration.md#overall-configuration>
+        '';
+      };
+
+      databaseUrl = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
+        default = null;
+        example = "postgres:///shiori?host=/run/postgresql";
+        description = "The connection URL to connect to MySQL or PostgreSQL";
+      };
     };
   };
 
-  config = mkIf cfg.enable {
-    systemd.services.shiori = with cfg; {
+  config = lib.mkIf cfg.enable {
+    systemd.services.shiori = {
       description = "Shiori simple bookmarks manager";
       wantedBy = [ "multi-user.target" ];
-
-      environment.SHIORI_DIR = "/var/lib/shiori";
+      after = [ "postgresql.service" "mysql.service" ];
+      environment = {
+        SHIORI_DIR = "/var/lib/shiori";
+      } // lib.optionalAttrs (cfg.databaseUrl != null) {
+        SHIORI_DATABASE_URL = cfg.databaseUrl;
+      };
 
       serviceConfig = {
-        ExecStart = "${package}/bin/shiori serve --address '${address}' --port '${toString port}' --webroot '${webRoot}'";
+        ExecStart =
+          "${cfg.package}/bin/shiori server --address '${cfg.address}' --port '${
+            toString cfg.port
+          }' --webroot '${cfg.webRoot}'";
 
         DynamicUser = true;
         StateDirectory = "shiori";
@@ -50,15 +73,24 @@ in {
         RuntimeDirectory = "shiori";
 
         # Security options
-
+        EnvironmentFile =
+          lib.optional (cfg.environmentFile != null) cfg.environmentFile;
         BindReadOnlyPaths = [
           "/nix/store"
 
           # For SSL certificates, and the resolv.conf
           "/etc"
-        ];
+        ] ++ lib.optional (config.services.postgresql.enable &&
+                           cfg.databaseUrl != null &&
+                           lib.strings.hasPrefix "postgres://" cfg.databaseUrl)
+            "/run/postgresql"
+          ++ lib.optional (config.services.mysql.enable &&
+                           cfg.databaseUrl != null &&
+                           lib.strings.hasPrefix "mysql://" cfg.databaseUrl)
+            "/var/run/mysqld";
 
         CapabilityBoundingSet = "";
+        AmbientCapabilities = "CAP_NET_BIND_SERVICE";
 
         DeviceAllow = "";
 
@@ -78,7 +110,7 @@ in {
         ProtectKernelTunables = true;
 
         RestrictNamespaces = true;
-        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
         RestrictRealtime = true;
         RestrictSUIDSGID = true;
 
@@ -88,11 +120,17 @@ in {
         SystemCallErrorNumber = "EPERM";
         SystemCallFilter = [
           "@system-service"
-          "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid"
+          "~@cpu-emulation"
+          "~@debug"
+          "~@keyring"
+          "~@memlock"
+          "~@obsolete"
+          "~@privileged"
+          "~@setuid"
         ];
       };
     };
   };
 
-  meta.maintainers = with maintainers; [ minijackson ];
+  meta.maintainers = with lib.maintainers; [ minijackson CaptainJawZ ];
 }
diff --git a/nixos/modules/services/web-apps/silverbullet.nix b/nixos/modules/services/web-apps/silverbullet.nix
index 5d5f950a9a661..a6a830e674b49 100644
--- a/nixos/modules/services/web-apps/silverbullet.nix
+++ b/nixos/modules/services/web-apps/silverbullet.nix
@@ -14,7 +14,7 @@ in
     services.silverbullet = {
       enable = lib.mkEnableOption "Silverbullet, an open-source, self-hosted, offline-capable Personal Knowledge Management (PKM) web application";
 
-      package = lib.mkPackageOptionMD pkgs "silverbullet" { };
+      package = lib.mkPackageOption pkgs "silverbullet" { };
 
       openFirewall = lib.mkOption {
         type = lib.types.bool;
diff --git a/nixos/modules/services/web-apps/slskd.nix b/nixos/modules/services/web-apps/slskd.nix
index 6254fe294eeed..7d4bc66c73998 100644
--- a/nixos/modules/services/web-apps/slskd.nix
+++ b/nixos/modules/services/web-apps/slskd.nix
@@ -7,7 +7,7 @@ in {
   options.services.slskd = with lib; with types; {
     enable = mkEnableOption "slskd";
 
-    package = mkPackageOptionMD pkgs "slskd" { };
+    package = mkPackageOption pkgs "slskd" { };
 
     user = mkOption {
       type = types.str;
diff --git a/nixos/modules/services/web-apps/suwayomi-server.nix b/nixos/modules/services/web-apps/suwayomi-server.nix
index ba2352d0e693f..caa091685d2fb 100644
--- a/nixos/modules/services/web-apps/suwayomi-server.nix
+++ b/nixos/modules/services/web-apps/suwayomi-server.nix
@@ -11,7 +11,7 @@ in
     services.suwayomi-server = {
       enable = mkEnableOption "Suwayomi, a free and open source manga reader server that runs extensions built for Tachiyomi";
 
-      package = lib.mkPackageOptionMD pkgs "suwayomi-server" { };
+      package = lib.mkPackageOption pkgs "suwayomi-server" { };
 
       dataDir = mkOption {
         type = types.path;
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 4d49b29efff69..46cb099595794 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -435,7 +435,7 @@ in
         example = literalExpression ''
           [
             "proxy_connect"
-            { name = "jk"; path = "''${pkgs.tomcat_connectors}/modules/mod_jk.so"; }
+            { name = "jk"; path = "''${pkgs.apacheHttpdPackages.mod_jk}/modules/mod_jk.so"; }
           ]
         '';
         description = ''
@@ -538,25 +538,13 @@ in
         '';
       };
 
-      enableMellon = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Whether to enable the mod_auth_mellon module.";
-      };
+      enableMellon = mkEnableOption "the mod_auth_mellon module";
 
-      enablePHP = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Whether to enable the PHP module.";
-      };
+      enablePHP = mkEnableOption "the PHP module";
 
       phpPackage = mkPackageOption pkgs "php" { };
 
-      enablePerl = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Whether to enable the Perl module (mod_perl).";
-      };
+      enablePerl = mkEnableOption "the Perl module (mod_perl)";
 
       phpOptions = mkOption {
         type = types.lines;
diff --git a/nixos/modules/services/web-servers/fcgiwrap.nix b/nixos/modules/services/web-servers/fcgiwrap.nix
index 3250e9c05ed66..29ddd39942c60 100644
--- a/nixos/modules/services/web-servers/fcgiwrap.nix
+++ b/nixos/modules/services/web-servers/fcgiwrap.nix
@@ -3,70 +3,128 @@
 with lib;
 
 let
-  cfg = config.services.fcgiwrap;
+  forEachInstance = f: flip mapAttrs' config.services.fcgiwrap (name: cfg:
+    nameValuePair "fcgiwrap-${name}" (f cfg)
+  );
+
 in {
+  options.services.fcgiwrap = mkOption {
+    description = "Configuration for fcgiwrap instances.";
+    default = { };
+    type = types.attrsOf (types.submodule ({ config, ... }: { options = {
+      process.prefork = mkOption {
+        type = types.ints.positive;
+        default = 1;
+        description = "Number of processes to prefork.";
+      };
 
-  options = {
-    services.fcgiwrap = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Whether to enable fcgiwrap, a server for running CGI applications over FastCGI.";
+      process.user = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          User as which this instance of fcgiwrap will be run.
+          Set to `null` (the default) to use a dynamically allocated user.
+        '';
       };
 
-      preforkProcesses = mkOption {
-        type = types.int;
-        default = 1;
-        description = "Number of processes to prefork.";
+      process.group = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "Group as which this instance of fcgiwrap will be run.";
       };
 
-      socketType = mkOption {
+      socket.type = mkOption {
         type = types.enum [ "unix" "tcp" "tcp6" ];
         default = "unix";
         description = "Socket type: 'unix', 'tcp' or 'tcp6'.";
       };
 
-      socketAddress = mkOption {
+      socket.address = mkOption {
         type = types.str;
-        default = "/run/fcgiwrap.sock";
+        default = "/run/fcgiwrap-${config._module.args.name}.sock";
         example = "1.2.3.4:5678";
-        description = "Socket address. In case of a UNIX socket, this should be its filesystem path.";
+        description = ''
+          Socket address.
+          In case of a UNIX socket, this should be its filesystem path.
+        '';
       };
 
-      user = mkOption {
+      socket.user = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = "User permissions for the socket.";
+        description = ''
+          User to be set as owner of the UNIX socket.
+          Defaults to the process running user.
+        '';
       };
 
-      group = mkOption {
+      socket.group = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = "Group permissions for the socket.";
+        description = ''
+          Group to be set as owner of the UNIX socket.
+          Defaults to the process running group.
+        '';
       };
-    };
+
+      socket.mode = mkOption {
+        type = types.nullOr types.str;
+        default = if config.socket.type == "unix" then "0600" else null;
+        defaultText = literalExpression ''
+          if config.socket.type == "unix" then "0600" else null
+        '';
+        description = ''
+          Mode to be set on the UNIX socket.
+          Defaults to private to the socket's owner.
+        '';
+      };
+    }; }));
   };
 
-  config = mkIf cfg.enable {
-    systemd.services.fcgiwrap = {
+  config = {
+    assertions = concatLists (mapAttrsToList (name: cfg: [
+      {
+        assertion = cfg.socket.user != null -> cfg.socket.type == "unix";
+        message = "Socket owner can only be set for the UNIX socket type.";
+      }
+      {
+        assertion = cfg.socket.group != null -> cfg.socket.type == "unix";
+        message = "Socket owner can only be set for the UNIX socket type.";
+      }
+      {
+        assertion = cfg.socket.mode != null -> cfg.socket.type == "unix";
+        message = "Socket mode can only be set for the UNIX socket type.";
+      }
+    ]) config.services.fcgiwrap);
+
+    systemd.services = forEachInstance (cfg: {
       after = [ "nss-user-lookup.target" ];
-      wantedBy = optional (cfg.socketType != "unix") "multi-user.target";
+      wantedBy = optional (cfg.socket.type != "unix") "multi-user.target";
 
       serviceConfig = {
-        ExecStart = "${pkgs.fcgiwrap}/sbin/fcgiwrap -c ${builtins.toString cfg.preforkProcesses} ${
-          optionalString (cfg.socketType != "unix") "-s ${cfg.socketType}:${cfg.socketAddress}"
-        }";
-      } // (if cfg.user != null && cfg.group != null then {
-        User = cfg.user;
-        Group = cfg.group;
-      } else { } );
-    };
+        ExecStart = ''
+          ${pkgs.fcgiwrap}/sbin/fcgiwrap ${cli.toGNUCommandLineShell {} ({
+            c = cfg.process.prefork;
+          } // (optionalAttrs (cfg.socket.type != "unix") {
+            s = "${cfg.socket.type}:${cfg.socket.address}";
+          }))}
+        '';
+      } // (if cfg.process.user != null then {
+        User = cfg.process.user;
+        Group = cfg.process.group;
+      } else {
+        DynamicUser = true;
+      });
+    });
 
-    systemd.sockets = if (cfg.socketType == "unix") then {
-      fcgiwrap = {
-        wantedBy = [ "sockets.target" ];
-        socketConfig.ListenStream = cfg.socketAddress;
+    systemd.sockets = forEachInstance (cfg: mkIf (cfg.socket.type == "unix") {
+      wantedBy = [ "sockets.target" ];
+      socketConfig = {
+        ListenStream = cfg.socket.address;
+        SocketUser = cfg.socket.user;
+        SocketGroup = cfg.socket.group;
+        SocketMode = cfg.socket.mode;
       };
-    } else { };
+    });
   };
 }
diff --git a/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixos/modules/services/x11/desktop-managers/budgie.nix
index b4e7390293351..7f43a939970b8 100644
--- a/nixos/modules/services/x11/desktop-managers/budgie.nix
+++ b/nixos/modules/services/x11/desktop-managers/budgie.nix
@@ -61,7 +61,7 @@ in {
         '';
         type = types.listOf types.package;
         default = [];
-        example = literalExpression "[ pkgs.gnome.gpaste ]";
+        example = literalExpression "[ pkgs.gpaste ]";
       };
 
       extraGSettingsOverrides = mkOption {
@@ -132,7 +132,7 @@ in {
         gnome-menus
 
         # Required by Budgie Control Center.
-        gnome.zenity
+        zenity
 
         # Provides `gsettings`.
         glib
@@ -162,7 +162,7 @@ in {
       ++ cfg.sessionPath;
 
     # Both budgie-desktop-view and nemo defaults to this emulator.
-    programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.gnome.gnome-terminal);
+    programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.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 fa67441e7ac49..0dc21862d8348 100644
--- a/nixos/modules/services/x11/desktop-managers/cinnamon.nix
+++ b/nixos/modules/services/x11/desktop-managers/cinnamon.nix
@@ -27,7 +27,7 @@ in
       sessionPath = mkOption {
         default = [];
         type = types.listOf types.package;
-        example = literalExpression "[ pkgs.gnome.gpaste ]";
+        example = literalExpression "[ pkgs.gpaste ]";
         description = ''
           Additional list of packages to be added to the session search path.
           Useful for GSettings-conditional autostart.
@@ -163,8 +163,8 @@ in
         libgnomekbd
 
         # theme
-        gnome.adwaita-icon-theme
-        gnome.gnome-themes-extra
+        adwaita-icon-theme
+        gnome-themes-extra
         gtk3.out
 
         # other
@@ -229,11 +229,11 @@ in
     })
 
     (mkIf serviceCfg.apps.enable {
-      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);
+      programs.gnome-disks.enable = mkDefault (notExcluded pkgs.gnome-disk-utility);
+      programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.gnome-terminal);
+      programs.file-roller.enable = mkDefault (notExcluded pkgs.file-roller);
 
-      environment.systemPackages = with pkgs // pkgs.gnome // pkgs.cinnamon; utils.removePackagesByName [
+      environment.systemPackages = with pkgs // pkgs.cinnamon; utils.removePackagesByName [
         # cinnamon team apps
         bulky
         warpinator
diff --git a/nixos/modules/services/x11/desktop-managers/gnome.md b/nixos/modules/services/x11/desktop-managers/gnome.md
index 2b4bd06df04f2..9943f138dc60c 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome.md
+++ b/nixos/modules/services/x11/desktop-managers/gnome.md
@@ -114,7 +114,7 @@ in `dconf-editor`
 ## Shell Extensions {#sec-gnome-shell-extensions}
 
 Most Shell extensions are packaged under the `gnomeExtensions` attribute.
-Some packages that include Shell extensions, like `gnome.gpaste`, don’t have their extension decoupled under this attribute.
+Some packages that include Shell extensions, like `gpaste`, don’t have their extension decoupled under this attribute.
 
 You can install them like any other package:
 
diff --git a/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixos/modules/services/x11/desktop-managers/gnome.nix
index fe50d930b5af0..11d5fcbfee23d 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome.nix
@@ -89,7 +89,7 @@ in
       sessionPath = mkOption {
         default = [];
         type = types.listOf types.package;
-        example = literalExpression "[ pkgs.gnome.gpaste ]";
+        example = literalExpression "[ pkgs.gpaste ]";
         description = ''
           Additional list of packages to be added to the session search path.
           Useful for GNOME Shell extensions or GSettings-conditional autostart.
@@ -176,7 +176,7 @@ in
 
     environment.gnome.excludePackages = mkOption {
       default = [];
-      example = literalExpression "[ pkgs.gnome.totem ]";
+      example = literalExpression "[ pkgs.totem ]";
       type = types.listOf types.package;
       description = "Which packages gnome should exclude from the default environment";
     };
@@ -373,7 +373,7 @@ in
             gnome-shell
           ];
           optionalPackages = with pkgs.gnome; [
-            adwaita-icon-theme
+            pkgs.adwaita-icon-theme
             nixos-background-info
             gnome-backgrounds
             gnome-bluetooth
@@ -399,28 +399,28 @@ in
         with pkgs.gnome;
         utils.removePackagesByName
           ([
-            baobab
-            epiphany
+            pkgs.baobab
+            pkgs.epiphany
             pkgs.gnome-text-editor
-            gnome-calculator
-            gnome-calendar
+            pkgs.gnome-calculator
+            pkgs.gnome-calendar
             gnome-characters
             gnome-clocks
             pkgs.gnome-console
             gnome-contacts
-            gnome-font-viewer
+            pkgs.gnome-font-viewer
             gnome-logs
             gnome-maps
             gnome-music
-            gnome-system-monitor
+            pkgs.gnome-system-monitor
             gnome-weather
             pkgs.loupe
-            nautilus
+            pkgs.nautilus
             pkgs.gnome-connections
-            simple-scan
+            pkgs.simple-scan
             pkgs.snapshot
-            totem
-            yelp
+            pkgs.totem
+            pkgs.yelp
           ] ++ lib.optionals config.services.flatpak.enable [
             # Since PackageKit Nix support is not there yet,
             # only install gnome-software if flatpak is enabled.
@@ -432,12 +432,12 @@ in
       # Since some of these have a corresponding package, we only
       # enable that program module if the package hasn't been excluded
       # through `environment.gnome.excludePackages`
-      programs.evince.enable = notExcluded pkgs.gnome.evince;
-      programs.file-roller.enable = notExcluded pkgs.gnome.file-roller;
-      programs.geary.enable = notExcluded pkgs.gnome.geary;
-      programs.gnome-disks.enable = notExcluded pkgs.gnome.gnome-disk-utility;
-      programs.seahorse.enable = notExcluded pkgs.gnome.seahorse;
-      services.gnome.sushi.enable = notExcluded pkgs.gnome.sushi;
+      programs.evince.enable = notExcluded pkgs.evince;
+      programs.file-roller.enable = notExcluded pkgs.file-roller;
+      programs.geary.enable = notExcluded pkgs.geary;
+      programs.gnome-disks.enable = notExcluded pkgs.gnome-disk-utility;
+      programs.seahorse.enable = notExcluded pkgs.seahorse;
+      services.gnome.sushi.enable = notExcluded pkgs.sushi;
 
       # VTE shell integration for gnome-console
       programs.bash.vteIntegration = mkDefault true;
@@ -482,9 +482,9 @@ in
 
     # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/3.38.0/elements/core/meta-gnome-core-developer-tools.bst
     (lib.mkIf serviceCfg.core-developer-tools.enable {
-      environment.systemPackages = with pkgs.gnome; utils.removePackagesByName [
-        dconf-editor
-        devhelp
+      environment.systemPackages = utils.removePackagesByName [
+        pkgs.dconf-editor
+        pkgs.devhelp
         pkgs.gnome-builder
         # boxes would make sense in this option, however
         # it doesn't function well enough to be included
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 0e9a06706d4f6..01bf3aad202ad 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -44,7 +44,7 @@ in
       sessionPath = mkOption {
         default = [];
         type = types.listOf types.package;
-        example = literalExpression "[ pkgs.gnome.gpaste ]";
+        example = literalExpression "[ pkgs.gpaste ]";
         description = ''
           Additional list of packages to be added to the session search path.
           Useful for GSettings-conditional autostart.
@@ -207,7 +207,7 @@ in
         desktop-file-utils
         glib # for gsettings program
         gnome-menus
-        gnome.adwaita-icon-theme
+        adwaita-icon-theme
         gtk3.out # for gtk-launch program
         onboard
         orca # elementary/greeter#668
@@ -284,11 +284,11 @@ in
     })
 
     (mkIf serviceCfg.apps.enable {
-      programs.evince.enable = mkDefault (notExcluded pkgs.gnome.evince);
-      programs.file-roller.enable = mkDefault (notExcluded pkgs.gnome.file-roller);
+      programs.evince.enable = mkDefault (notExcluded pkgs.evince);
+      programs.file-roller.enable = mkDefault (notExcluded pkgs.file-roller);
 
       environment.systemPackages = utils.removePackagesByName ([
-        pkgs.gnome.gnome-font-viewer
+        pkgs.gnome-font-viewer
       ] ++ (with pkgs.pantheon; [
         elementary-calculator
         elementary-calendar
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 69a83ecb72065..98d3555ccbc5e 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -84,8 +84,8 @@ in
       glib # for gsettings
       gtk3.out # gtk-update-icon-cache
 
-      gnome.gnome-themes-extra
-      gnome.adwaita-icon-theme
+      gnome-themes-extra
+      adwaita-icon-theme
       hicolor-icon-theme
       tango-icon-theme
       xfce4-icon-theme
@@ -165,6 +165,7 @@ in
     services.tumbler.enable = true;
     services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
     services.libinput.enable = mkDefault true; # used in xfce4-settings-manager
+    services.colord.enable = mkDefault true;
 
     # Enable default programs
     programs.dconf.enable = true;
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index 51ab08e74f864..1a39b365db5f3 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -6,6 +6,7 @@ let
 
   cfg = config.services.xserver.displayManager;
   gdm = pkgs.gnome.gdm;
+  pamCfg = config.security.pam.services;
   settingsFormat = pkgs.formats.ini { };
   configFile = settingsFormat.generate "custom.conf" cfg.gdm.settings;
 
@@ -155,7 +156,7 @@ in
             gdm # for gnome-login.session
             config.services.displayManager.sessionData.desktops
             pkgs.gnome.gnome-control-center # for accessibility icon
-            pkgs.gnome.adwaita-icon-theme
+            pkgs.adwaita-icon-theme
             pkgs.hicolor-icon-theme # empty icon theme as a base
           ];
         } // optionalAttrs (xSessionWrapper != null) {
@@ -183,7 +184,7 @@ in
 
     # Otherwise GDM will not be able to start correctly and display Wayland sessions
     systemd.packages = with pkgs.gnome; [ gdm gnome-session gnome-shell ];
-    environment.systemPackages = [ pkgs.gnome.adwaita-icon-theme ];
+    environment.systemPackages = [ pkgs.adwaita-icon-theme ];
 
     # We dont use the upstream gdm service
     # it has to be disabled since the gdm package has it
@@ -321,15 +322,20 @@ in
         session   include       login
       '';
 
+      # This would block password prompt when included by gdm-password.
+      # GDM will instead run gdm-fingerprint in parallel.
       login.fprintAuth = mkIf config.services.fprintd.enable false;
+
       gdm-fingerprint.text = mkIf config.services.fprintd.enable ''
         auth       required                    pam_shells.so
         auth       requisite                   pam_nologin.so
         auth       requisite                   pam_faillock.so      preauth
         auth       required                    ${pkgs.fprintd}/lib/security/pam_fprintd.so
-        auth       optional                    pam_permit.so
         auth       required                    pam_env.so
-        auth       [success=ok default=1]      ${pkgs.gnome.gdm}/lib/security/pam_gdm.so
+        ${lib.optionalString pamCfg.login.enableGnomeKeyring ''
+          auth       [success=ok default=1]      ${pkgs.gnome.gdm}/lib/security/pam_gdm.so
+          auth       optional                    ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so
+        ''}
 
         account    include                     login
 
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix
index 930ee96b384d5..8975d6fb9f0f7 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix
@@ -34,8 +34,8 @@ in {
       theme = {
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.gnome-themes-extra;
-          defaultText = literalExpression "pkgs.gnome.gnome-themes-extra";
+          default = pkgs.gnome-themes-extra;
+          defaultText = literalExpression "pkgs.gnome-themes-extra";
           description = ''
             The package path that contains the theme given in the name option.
           '';
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
index 30940da103a96..0907aeb839ba3 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -47,8 +47,8 @@ in
 
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.gnome-themes-extra;
-          defaultText = literalExpression "pkgs.gnome.gnome-themes-extra";
+          default = pkgs.gnome-themes-extra;
+          defaultText = literalExpression "pkgs.gnome-themes-extra";
           description = ''
             The package path that contains the theme given in the name option.
           '';
@@ -68,8 +68,8 @@ in
 
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.adwaita-icon-theme;
-          defaultText = literalExpression "pkgs.gnome.adwaita-icon-theme";
+          default = pkgs.adwaita-icon-theme;
+          defaultText = literalExpression "pkgs.adwaita-icon-theme";
           description = ''
             The package path that contains the icon theme given in the name option.
           '';
@@ -89,8 +89,8 @@ in
 
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.adwaita-icon-theme;
-          defaultText = literalExpression "pkgs.gnome.adwaita-icon-theme";
+          default = pkgs.adwaita-icon-theme;
+          defaultText = literalExpression "pkgs.adwaita-icon-theme";
           description = ''
             The package path that contains the cursor theme given in the name option.
           '';
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/slick.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/slick.nix
index 299d3bae5f06f..d20b26491aee1 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/slick.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/slick.nix
@@ -33,8 +33,8 @@ in
       theme = {
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.gnome-themes-extra;
-          defaultText = literalExpression "pkgs.gnome.gnome-themes-extra";
+          default = pkgs.gnome-themes-extra;
+          defaultText = literalExpression "pkgs.gnome-themes-extra";
           description = ''
             The package path that contains the theme given in the name option.
           '';
@@ -52,8 +52,8 @@ in
       iconTheme = {
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.adwaita-icon-theme;
-          defaultText = literalExpression "pkgs.gnome.adwaita-icon-theme";
+          default = pkgs.adwaita-icon-theme;
+          defaultText = literalExpression "pkgs.adwaita-icon-theme";
           description = ''
             The package path that contains the icon theme given in the name option.
           '';
@@ -90,8 +90,8 @@ in
       cursorTheme = {
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome.adwaita-icon-theme;
-          defaultText = literalExpression "pkgs.gnome.adwaita-icon-theme";
+          default = pkgs.adwaita-icon-theme;
+          defaultText = literalExpression "pkgs.adwaita-icon-theme";
           description = ''
             The package path that contains the cursor theme given in the name option.
           '';
diff --git a/nixos/modules/services/x11/window-managers/herbstluftwm.nix b/nixos/modules/services/x11/window-managers/herbstluftwm.nix
index 7edaf4e980ec4..94c9f4aa91c8f 100644
--- a/nixos/modules/services/x11/window-managers/herbstluftwm.nix
+++ b/nixos/modules/services/x11/window-managers/herbstluftwm.nix
@@ -33,7 +33,10 @@ in
             (cfg.configFile != null)
             ''-c "${cfg.configFile}"''
             ;
-        in "${cfg.package}/bin/herbstluftwm ${configFileClause} &";
+        in ''
+          ${cfg.package}/bin/herbstluftwm ${configFileClause} &
+          waitPID=$!
+        '';
     };
     environment.systemPackages = [ cfg.package ];
   };