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/backup/znapzend.nix10
-rw-r--r--nixos/modules/services/databases/postgresql.nix33
-rw-r--r--nixos/modules/services/databases/redis.nix11
-rw-r--r--nixos/modules/services/desktop-managers/plasma6.nix2
-rw-r--r--nixos/modules/services/desktops/pipewire/wireplumber.nix183
-rw-r--r--nixos/modules/services/display-managers/sddm.nix4
-rw-r--r--nixos/modules/services/editors/emacs.md41
-rw-r--r--nixos/modules/services/hardware/libinput.nix (renamed from nixos/modules/services/x11/hardware/libinput.nix)12
-rw-r--r--nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/cdi-generate.nix60
-rw-r--r--nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/default.nix40
-rw-r--r--nixos/modules/services/hardware/nvidia-container-toolkit/cdi-generate.nix35
-rw-r--r--nixos/modules/services/hardware/nvidia-container-toolkit/default.nix127
-rw-r--r--nixos/modules/services/home-automation/ebusd.nix24
-rw-r--r--nixos/modules/services/home-automation/evcc.nix1
-rw-r--r--nixos/modules/services/home-automation/wyoming/faster-whisper.nix2
-rw-r--r--nixos/modules/services/logging/logrotate.nix2
-rw-r--r--nixos/modules/services/mail/mailman.nix11
-rw-r--r--nixos/modules/services/mail/roundcube.nix7
-rw-r--r--nixos/modules/services/matrix/appservice-irc.nix3
-rw-r--r--nixos/modules/services/matrix/conduit.nix2
-rw-r--r--nixos/modules/services/misc/gitea.nix2
-rw-r--r--nixos/modules/services/misc/greenclip.nix5
-rw-r--r--nixos/modules/services/monitoring/parsedmarc.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/bind.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/bird.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/collectd.nix10
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/domain.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/flow.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/idrac.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix11
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/json.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/kea.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/keylight.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/knot.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/lnd.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/mail.nix14
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/minio.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix12
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/nats.nix5
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/nginx.nix11
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/node.nix10
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/nut.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/openldap.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/pihole.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/ping.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/postfix.nix10
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/postgres.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/process.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/pve.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/redis.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/restic.nix13
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix11
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/script.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/shelly.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/snmp.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/sql.nix8
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/statsd.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/systemd.nix7
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/tor.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/unbound.nix11
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/unifi.nix9
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/varnish.nix10
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix10
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/zfs.nix7
-rw-r--r--nixos/modules/services/monitoring/rustdesk-server.nix6
-rw-r--r--nixos/modules/services/monitoring/vmagent.nix114
-rw-r--r--nixos/modules/services/networking/adguardhome.nix122
-rw-r--r--nixos/modules/services/networking/clatd.nix82
-rw-r--r--nixos/modules/services/networking/deconz.nix2
-rw-r--r--nixos/modules/services/networking/firewall-nftables.nix18
-rw-r--r--nixos/modules/services/networking/inadyn.nix250
-rw-r--r--nixos/modules/services/networking/jotta-cli.md27
-rw-r--r--nixos/modules/services/networking/jotta-cli.nix43
-rw-r--r--nixos/modules/services/networking/knot.nix2
-rw-r--r--nixos/modules/services/networking/netbird/coturn.nix6
-rw-r--r--nixos/modules/services/networking/pixiecore.nix2
-rw-r--r--nixos/modules/services/networking/pppd.nix2
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix8
-rw-r--r--nixos/modules/services/networking/sunshine.nix163
-rw-r--r--nixos/modules/services/networking/tailscale.nix2
-rw-r--r--nixos/modules/services/networking/trust-dns.nix6
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix13
-rw-r--r--nixos/modules/services/search/manticore.nix131
-rw-r--r--nixos/modules/services/security/oauth2-proxy-nginx.nix130
-rw-r--r--nixos/modules/services/security/oauth2-proxy.nix (renamed from nixos/modules/services/security/oauth2_proxy.nix)255
-rw-r--r--nixos/modules/services/security/oauth2_proxy_nginx.nix91
-rw-r--r--nixos/modules/services/security/vault.nix4
-rw-r--r--nixos/modules/services/security/vaultwarden/default.nix16
-rw-r--r--nixos/modules/services/system/dbus.nix2
-rw-r--r--nixos/modules/services/system/earlyoom.nix39
-rw-r--r--nixos/modules/services/web-apps/akkoma.nix6
-rw-r--r--nixos/modules/services/web-apps/castopod.nix2
-rw-r--r--nixos/modules/services/web-apps/coder.nix3
-rw-r--r--nixos/modules/services/web-apps/gotosocial.nix2
-rw-r--r--nixos/modules/services/web-apps/limesurvey.nix16
-rw-r--r--nixos/modules/services/web-apps/mediawiki.nix4
-rw-r--r--nixos/modules/services/web-apps/movim.nix22
-rw-r--r--nixos/modules/services/web-apps/nextcloud.md28
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix9
-rw-r--r--nixos/modules/services/web-apps/pretalx.nix8
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix5
-rw-r--r--nixos/modules/services/x11/desktop-managers/budgie.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/cinnamon.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/deepin.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/enlightenment.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/lxqt.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix2
-rw-r--r--nixos/modules/services/x11/hardware/cmt.nix4
-rw-r--r--nixos/modules/services/x11/hardware/synaptics.nix6
137 files changed, 1963 insertions, 769 deletions
diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix
index 71e5977c44640..7f2c89edbf374 100644
--- a/nixos/modules/services/backup/znapzend.nix
+++ b/nixos/modules/services/backup/znapzend.nix
@@ -315,6 +315,14 @@ in
         '';
       };
 
+      mailErrorSummaryTo = mkOption {
+        type = singleLineStr;
+        default = "";
+        description = ''
+          Email address to send a summary to if "send task(s) failed".
+        '';
+      };
+
       noDestroy = mkOption {
         type = bool;
         default = false;
@@ -455,6 +463,8 @@ in
               "--loglevel=${cfg.logLevel}"
               (optionalString cfg.noDestroy "--nodestroy")
               (optionalString cfg.autoCreation "--autoCreation")
+              (optionalString (cfg.mailErrorSummaryTo != "")
+                "--mailErrorSummaryTo=${cfg.mailErrorSummaryTo}")
               (optionalString (enabledFeatures != [])
                 "--features=${concatStringsSep "," enabledFeatures}")
             ]; in "${pkgs.znapzend}/bin/znapzend ${args}";
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 8a386b4848b91..35d3ba0aa2094 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -1,8 +1,31 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit (lib)
+    attrValues
+    concatMapStrings
+    concatStringsSep
+    const
+    elem
+    filterAttrs
+    isString
+    literalExpression
+    mapAttrs
+    mapAttrsToList
+    mkAfter
+    mkBefore
+    mkDefault
+    mkEnableOption
+    mkIf
+    mkMerge
+    mkOption
+    mkPackageOption
+    mkRemovedOptionModule
+    mkRenamedOptionModule
+    optionalString
+    types
+    versionAtLeast
+    ;
 
   cfg = config.services.postgresql;
 
@@ -24,7 +47,7 @@ let
     if true == value then "yes"
     else if false == value then "no"
     else if isString value then "'${lib.replaceStrings ["'"] ["''"] value}'"
-    else toString value;
+    else builtins.toString value;
 
   # The main PostgreSQL configuration file.
   configFile = pkgs.writeTextDir "postgresql.conf" (concatStringsSep "\n" (mapAttrsToList (n: v: "${n} = ${toStr v}") (filterAttrs (const (x: x != null)) cfg.settings)));
@@ -439,7 +462,7 @@ in
   config = mkIf cfg.enable {
 
     assertions = map ({ name, ensureDBOwnership, ... }: {
-      assertion = ensureDBOwnership -> builtins.elem name cfg.ensureDatabases;
+      assertion = ensureDBOwnership -> elem name cfg.ensureDatabases;
       message = ''
         For each database user defined with `services.postgresql.ensureUsers` and
         `ensureDBOwnership = true;`, a database with the same name must be defined
@@ -537,7 +560,7 @@ in
         # Wait for PostgreSQL to be ready to accept connections.
         postStart =
           ''
-            PSQL="psql --port=${toString cfg.settings.port}"
+            PSQL="psql --port=${builtins.toString cfg.settings.port}"
 
             while ! $PSQL -d postgres -c "" 2> /dev/null; do
                 if ! kill -0 "$MAINPID"; then exit 1; fi
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index 1da2fa9f11604..ad88a4f589a20 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -57,9 +57,9 @@ in {
       package = mkPackageOption pkgs "redis" { };
 
       vmOverCommit = mkEnableOption ''
-        setting of vm.overcommit_memory to 1
+        set `vm.overcommit_memory` sysctl to 1
         (Suggested for Background Saving: <https://redis.io/docs/get-started/faq/>)
-      '';
+      '' // { default = true; };
 
       servers = mkOption {
         type = with types; attrsOf (submodule ({ config, name, ... }: {
@@ -312,10 +312,9 @@ in {
       '';
     }) enabledServers);
 
-    boot.kernel.sysctl = mkMerge [
-      { "vm.nr_hugepages" = "0"; }
-      ( mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; } )
-    ];
+    boot.kernel.sysctl = mkIf cfg.vmOverCommit {
+      "vm.overcommit_memory" = "1";
+    };
 
     networking.firewall.allowedTCPPorts = concatMap (conf:
       optional conf.openFirewall conf.port
diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix
index 856d36b8a3030..08507b4d370a7 100644
--- a/nixos/modules/services/desktop-managers/plasma6.nix
+++ b/nixos/modules/services/desktop-managers/plasma6.nix
@@ -238,7 +238,7 @@ in {
     services.system-config-printer.enable = mkIf config.services.printing.enable (mkDefault true);
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
-    services.xserver.libinput.enable = mkDefault true;
+    services.libinput.enable = mkDefault true;
 
     # Extra UDEV rules used by Solid
     services.udev.packages = [
diff --git a/nixos/modules/services/desktops/pipewire/wireplumber.nix b/nixos/modules/services/desktops/pipewire/wireplumber.nix
index 6ab62eb03c25f..c924801bcd8ba 100644
--- a/nixos/modules/services/desktops/pipewire/wireplumber.nix
+++ b/nixos/modules/services/desktops/pipewire/wireplumber.nix
@@ -1,18 +1,40 @@
 { config, lib, pkgs, ... }:
 
 let
-  inherit (builtins) attrNames concatMap length;
+  inherit (builtins) concatMap;
   inherit (lib) maintainers;
-  inherit (lib.attrsets) attrByPath filterAttrs;
+  inherit (lib.attrsets) attrByPath mapAttrsToList;
   inherit (lib.lists) flatten optional;
   inherit (lib.modules) mkIf;
   inherit (lib.options) literalExpression mkOption;
-  inherit (lib.strings) hasPrefix;
-  inherit (lib.types) bool listOf package;
+  inherit (lib.strings) concatStringsSep makeSearchPath;
+  inherit (lib.types) bool listOf attrsOf package lines;
+  inherit (lib.path) subpath;
 
   pwCfg = config.services.pipewire;
   cfg = pwCfg.wireplumber;
   pwUsedForAudio = pwCfg.audio.enable;
+
+  json = pkgs.formats.json { };
+
+  configSectionsToConfFile = path: value:
+    pkgs.writeTextDir
+      path
+      (concatStringsSep "\n" (
+        mapAttrsToList
+          (section: content: "${section} = " + (builtins.toJSON content))
+          value
+      ));
+
+  mapConfigToFiles = config:
+    mapAttrsToList
+      (name: value: configSectionsToConfFile "share/wireplumber/wireplumber.conf.d/${name}.conf" value)
+      config;
+
+  mapScriptsToFiles = scripts:
+    mapAttrsToList
+      (relativePath: value: pkgs.writeTextDir (subpath.join ["share/wireplumber/scripts" relativePath]) value)
+      scripts;
 in
 {
   meta.maintainers = [ maintainers.k900 ];
@@ -33,6 +55,114 @@ in
         description = "The WirePlumber derivation to use.";
       };
 
+      extraConfig = mkOption {
+        # Two layer attrset is necessary before using JSON, because of the whole
+        # config file not being a JSON object, but a concatenation of JSON objects
+        # in sections.
+        type = attrsOf (attrsOf json.type);
+        default = { };
+        example = literalExpression ''{
+          "log-level-debug" = {
+            "context.properties" = {
+              # Output Debug log messages as opposed to only the default level (Notice)
+              "log.level" = "D";
+            };
+          };
+          "wh-1000xm3-ldac-hq" = {
+            "monitor.bluez.rules" = [
+              {
+                matches = [
+                  {
+                    # Match any bluetooth device with ids equal to that of a WH-1000XM3
+                    "device.name" = "~bluez_card.*";
+                    "device.product.id" = "0x0cd3";
+                    "device.vendor.id" = "usb:054c";
+                  }
+                ];
+                actions = {
+                  update-props = {
+                    # Set quality to high quality instead of the default of auto
+                    "bluez5.a2dp.ldac.quality" = "hq";
+                  };
+                };
+              }
+            ];
+          };
+        }'';
+        description = ''
+          Additional configuration for the WirePlumber daemon when run in
+          single-instance mode (the default in nixpkgs and currently the only
+          supported way to run WirePlumber configured via `extraConfig`).
+
+          See also:
+          - [The configuration file][docs-the-conf-file]
+          - [Modifying configuration][docs-modifying-config]
+          - [Locations of files][docs-file-locations]
+          - and the [configuration section][docs-config-section] of the docs in general
+
+          Note that WirePlumber (and PipeWire) use dotted attribute names like
+          `device.product.id`. These are not nested, but flat objects for WirePlumber/PipeWire,
+          so to write these in nix expressions, remember to quote them like `"device.product.id"`.
+          Have a look at the example for this.
+
+          [docs-the-conf-file]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/conf_file.html
+          [docs-modifying-config]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/modifying_configuration.html
+          [docs-file-locations]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/locations.html
+          [docs-config-section]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration.html
+        '';
+      };
+
+      extraScripts = mkOption {
+        type = attrsOf lines;
+        default = { };
+        example = {
+          "test/hello-world.lua" = ''
+            print("Hello, world!")
+          '';
+        };
+        description = ''
+          Additional scripts for WirePlumber to be used by configuration files.
+
+          Every item in this attrset becomes a separate lua file with the path
+          relative to the `scripts` directory specified in the name of the item.
+          The scripts get passed to the WirePlumber service via the `XDG_DATA_DIRS`
+          variable. Scripts specified here are preferred over those shipped with
+          WirePlumber if they occupy the same relative path.
+
+          For a script to be loaded, it needs to be specified as part of a component,
+          and that component needs to be required by an active profile (e.g. `main`).
+          Components can be defined in config files either via `extraConfig` or `configPackages`.
+
+          For the hello-world example, you'd have to add the following `extraConfig`:
+          ```nix
+            services.pipewire.wireplumber.extraConfig."99-hello-world" = {
+              "wireplumber.components" = [
+                {
+                  name = "test/hello-world.lua";
+                  type = "script/lua";
+                  provides = "custom.hello-world";
+                }
+              ];
+
+              "wireplumber.profiles" = {
+                main = {
+                  "custom.hello-world" = "required";
+                };
+              };
+            };
+          ```
+
+          See also:
+          - [Location of scripts][docs-file-locations-scripts]
+          - [Components & Profiles][docs-components-profiles]
+          - [Migration - Loading custom scripts][docs-migration-loading-custom-scripts]
+
+          [docs-file-locations-scripts]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/locations.html#location-of-scripts
+          [docs-components-profiles]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/components_and_profiles.html
+          [docs-migration-loading-custom-scripts]: https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/migration.html#loading-custom-scripts
+        '';
+      };
+
       configPackages = mkOption {
         type = listOf package;
         default = [ ];
@@ -57,7 +187,7 @@ in
 
       extraLv2Packages = mkOption {
         type = listOf package;
-        default = [];
+        default = [ ];
         example = literalExpression "[ pkgs.lsp-plugins ]";
         description = ''
           List of packages that provide LV2 plugins in `lib/lv2` that should
@@ -96,9 +226,22 @@ in
         }
       '';
 
+      extraConfigPkg = pkgs.buildEnv {
+        name = "wireplumber-extra-config";
+        paths = mapConfigToFiles cfg.extraConfig;
+        pathsToLink = [ "/share/wireplumber/wireplumber.conf.d" ];
+      };
+
+      extraScriptsPkg = pkgs.buildEnv {
+        name = "wireplumber-extra-scrips";
+        paths = mapScriptsToFiles cfg.extraScripts;
+        pathsToLink = [ "/share/wireplumber/scripts" ];
+      };
+
       configPackages = cfg.configPackages
-          ++ optional (!pwUsedForAudio) pwNotForAudioConfigPkg
-          ++ optional pwCfg.systemWide systemwideConfigPkg;
+        ++ [ extraConfigPkg extraScriptsPkg ]
+        ++ optional (!pwUsedForAudio) pwNotForAudioConfigPkg
+        ++ optional pwCfg.systemWide systemwideConfigPkg;
 
       configs = pkgs.buildEnv {
         name = "wireplumber-configs";
@@ -110,7 +253,7 @@ in
         (
           concatMap
             (p:
-              attrByPath ["passthru" "requiredLv2Packages"] [] p
+              attrByPath [ "passthru" "requiredLv2Packages" ] [ ] p
             )
             configPackages
         );
@@ -127,24 +270,10 @@ in
           assertion = !config.hardware.bluetooth.hsphfpd.enable;
           message = "Using WirePlumber conflicts with hsphfpd, as it provides the same functionality. `hardware.bluetooth.hsphfpd.enable` needs be set to false";
         }
-        {
-          assertion = length
-            (attrNames
-              (
-                filterAttrs
-                  (name: value:
-                    hasPrefix "wireplumber/" name || name == "wireplumber"
-                  )
-                  config.environment.etc
-              )) == 1;
-          message = "Using `environment.etc.\"wireplumber<...>\"` directly is no longer supported in 24.05. Use `services.pipewire.wireplumber.configPackages` instead.";
-        }
       ];
 
       environment.systemPackages = [ cfg.package ];
 
-      environment.etc.wireplumber.source = "${configs}/share/wireplumber";
-
       systemd.packages = [ cfg.package ];
 
       systemd.services.wireplumber.enable = pwCfg.systemWide;
@@ -156,10 +285,16 @@ in
       systemd.services.wireplumber.environment = mkIf pwCfg.systemWide {
         # Force WirePlumber to use system dbus.
         DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/dbus/system_bus_socket";
+
+        # Make WirePlumber find our config/script files and lv2 plugins required by those
+        # (but also the configs/scripts shipped with WirePlumber)
+        XDG_DATA_DIRS = makeSearchPath "share" [ configs cfg.package ];
         LV2_PATH = "${lv2Plugins}/lib/lv2";
       };
 
-      systemd.user.services.wireplumber.environment.LV2_PATH =
-        mkIf (!pwCfg.systemWide) "${lv2Plugins}/lib/lv2";
+      systemd.user.services.wireplumber.environment = mkIf (!pwCfg.systemWide) {
+        XDG_DATA_DIRS = makeSearchPath "share" [ configs cfg.package ];
+        LV2_PATH = "${lv2Plugins}/lib/lv2";
+      };
     };
 }
diff --git a/nixos/modules/services/display-managers/sddm.nix b/nixos/modules/services/display-managers/sddm.nix
index aaf1f0dcfc65d..a6bfa213fe380 100644
--- a/nixos/modules/services/display-managers/sddm.nix
+++ b/nixos/modules/services/display-managers/sddm.nix
@@ -111,8 +111,8 @@ let
       let
         westonIni = (pkgs.formats.ini { }).generate "weston.ini" {
           libinput = {
-            enable-tap = xcfg.libinput.mouse.tapping;
-            left-handed = xcfg.libinput.mouse.leftHanded;
+            enable-tap = config.services.libinput.mouse.tapping;
+            left-handed = config.services.libinput.mouse.leftHanded;
           };
           keyboard = {
             keymap_model = xcfg.xkb.model;
diff --git a/nixos/modules/services/editors/emacs.md b/nixos/modules/services/editors/emacs.md
index 885f927422bdc..da10286751554 100644
--- a/nixos/modules/services/editors/emacs.md
+++ b/nixos/modules/services/editors/emacs.md
@@ -366,44 +366,3 @@ convenient if you regularly edit Nix files.
 You can use `woman` to get completion of all available
 man pages. For example, type `M-x woman <RET> nixos-rebuild <RET>.`
 
-### Editing DocBook 5 XML Documents {#sec-emacs-docbook-xml}
-
-Emacs includes
-[nXML](https://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Introduction.html),
-a major-mode for validating and editing XML documents. When editing DocBook
-5.0 documents, such as [this one](#book-nixos-manual),
-nXML needs to be configured with the relevant schema, which is not
-included.
-
-To install the DocBook 5.0 schemas, either add
-{var}`pkgs.docbook5` to [](#opt-environment.systemPackages)
-([NixOS](#sec-declarative-package-mgmt)), or run
-`nix-env -f '<nixpkgs>' -iA docbook5`
-([Nix](#sec-ad-hoc-packages)).
-
-Then customize the variable {var}`rng-schema-locating-files` to
-include {file}`~/.emacs.d/schemas.xml` and put the following
-text into that file:
-::: {.example #ex-emacs-docbook-xml}
-### nXML Schema Configuration (`~/.emacs.d/schemas.xml`)
-
-```xml
-<?xml version="1.0"?>
-<!--
-  To let emacs find this file, evaluate:
-  (add-to-list 'rng-schema-locating-files "~/.emacs.d/schemas.xml")
--->
-<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
-  <!--
-    Use this variation if pkgs.docbook5 is added to environment.systemPackages
-  -->
-  <namespace ns="http://docbook.org/ns/docbook"
-             uri="/run/current-system/sw/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
-  <!--
-    Use this variation if installing schema with "nix-env -iA pkgs.docbook5".
-  <namespace ns="http://docbook.org/ns/docbook"
-             uri="../.nix-profile/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
-  -->
-</locatingRules>
-```
-:::
diff --git a/nixos/modules/services/x11/hardware/libinput.nix b/nixos/modules/services/hardware/libinput.nix
index 54ff7d85a0331..b8aa59035d338 100644
--- a/nixos/modules/services/x11/hardware/libinput.nix
+++ b/nixos/modules/services/hardware/libinput.nix
@@ -2,7 +2,7 @@
 
 with lib;
 
-let cfg = config.services.xserver.libinput;
+let cfg = config.services.libinput;
 
     xorgBool = v: if v then "on" else "off";
 
@@ -223,7 +223,7 @@ let cfg = config.services.xserver.libinput;
 in {
 
   imports =
-    (map (option: mkRenamedOptionModule ([ "services" "xserver" "libinput" option ]) [ "services" "xserver" "libinput" "touchpad" option ]) [
+    (map (option: mkRenamedOptionModule ([ "services" "xserver" "libinput" option ]) [ "services" "libinput" "touchpad" option ]) [
       "accelProfile"
       "accelSpeed"
       "buttonMapping"
@@ -242,11 +242,15 @@ in {
       "transformationMatrix"
       "disableWhileTyping"
       "additionalOptions"
-    ]);
+    ]) ++ [
+      (mkRenamedOptionModule [ "services" "xserver" "libinput" "enable" ]   [ "services" "libinput" "enable" ])
+      (mkRenamedOptionModule [ "services" "xserver" "libinput" "mouse" ]    [ "services" "libinput" "mouse" ])
+      (mkRenamedOptionModule [ "services" "xserver" "libinput" "touchpad" ] [ "services" "libinput" "touchpad" ])
+    ];
 
   options = {
 
-    services.xserver.libinput = {
+    services.libinput = {
       enable = mkEnableOption "libinput" // {
         default = config.services.xserver.enable;
         defaultText = lib.literalExpression "config.services.xserver.enable";
diff --git a/nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/cdi-generate.nix b/nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/cdi-generate.nix
deleted file mode 100644
index 1aaa2d07b9bde..0000000000000
--- a/nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/cdi-generate.nix
+++ /dev/null
@@ -1,60 +0,0 @@
-{
-  addDriverRunpath,
-  glibc,
-  jq,
-  lib,
-  nvidia-container-toolkit,
-  nvidia-driver,
-  runtimeShell,
-  writeScriptBin,
-}:
-let
-  mountOptions = { options = ["ro" "nosuid" "nodev" "bind"]; };
-  mounts = [
-    # FIXME: Making /usr mounts optional
-    { hostPath = lib.getExe' nvidia-driver "nvidia-cuda-mps-control";
-      containerPath = "/usr/bin/nvidia-cuda-mps-control"; }
-    { hostPath = lib.getExe' nvidia-driver "nvidia-cuda-mps-server";
-      containerPath = "/usr/bin/nvidia-cuda-mps-server"; }
-    { hostPath = lib.getExe' nvidia-driver "nvidia-debugdump";
-      containerPath = "/usr/bin/nvidia-debugdump"; }
-    { hostPath = lib.getExe' nvidia-driver "nvidia-powerd";
-      containerPath = "/usr/bin/nvidia-powerd"; }
-    { hostPath = lib.getExe' nvidia-driver "nvidia-smi";
-      containerPath = "/usr/bin/nvidia-smi"; }
-    { hostPath = lib.getExe' nvidia-container-toolkit "nvidia-ctk";
-      containerPath = "/usr/bin/nvidia-ctk"; }
-    { hostPath = "${lib.getLib glibc}/lib";
-      containerPath = "${lib.getLib glibc}/lib"; }
-
-    # FIXME: use closureinfo
-    {
-      hostPath = addDriverRunpath.driverLink;
-      containerPath = addDriverRunpath.driverLink;
-    }
-    { hostPath = "${lib.getLib glibc}/lib";
-      containerPath = "${lib.getLib glibc}/lib"; }
-    { hostPath = "${lib.getLib glibc}/lib64";
-      containerPath = "${lib.getLib glibc}/lib64"; }
-  ];
-  jqAddMountExpression = ".containerEdits.mounts[.containerEdits.mounts | length] |= . +";
-  mountsToJq = lib.concatMap
-    (mount:
-      ["${lib.getExe jq} '${jqAddMountExpression} ${builtins.toJSON (mount // mountOptions)}'"])
-    mounts;
-in
-writeScriptBin "nvidia-cdi-generator"
-''
-#! ${runtimeShell}
-
-function cdiGenerate {
-  ${lib.getExe' nvidia-container-toolkit "nvidia-ctk"} cdi generate \
-    --format json \
-    --ldconfig-path ${lib.getExe' glibc "ldconfig"} \
-    --library-search-path ${lib.getLib nvidia-driver}/lib \
-    --nvidia-ctk-path ${lib.getExe' nvidia-container-toolkit "nvidia-ctk"}
-}
-
-cdiGenerate | \
-  ${lib.concatStringsSep " | " mountsToJq} > $RUNTIME_DIRECTORY/nvidia-container-toolkit.json
-''
diff --git a/nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/default.nix b/nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/default.nix
deleted file mode 100644
index 5aa3c72ee0a06..0000000000000
--- a/nixos/modules/services/hardware/nvidia-container-toolkit-cdi-generator/default.nix
+++ /dev/null
@@ -1,40 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-{
-
-  options = {
-
-    hardware.nvidia-container-toolkit-cdi-generator.enable = lib.mkOption {
-      default = false;
-      internal = true;
-      visible = false;
-      type = lib.types.bool;
-      description = ''
-        Enable dynamic CDI configuration for NVidia devices by running
-        nvidia-container-toolkit on boot.
-      '';
-    };
-
-  };
-
-  config = {
-
-    systemd.services.nvidia-container-toolkit-cdi-generator = lib.mkIf config.hardware.nvidia-container-toolkit-cdi-generator.enable {
-      description = "Container Device Interface (CDI) for Nvidia generator";
-      wantedBy = [ "multi-user.target" ];
-      after = [ "systemd-udev-settle.service" ];
-      serviceConfig = {
-        RuntimeDirectory = "cdi";
-        RemainAfterExit = true;
-        ExecStart =
-          let
-            script = pkgs.callPackage ./cdi-generate.nix { nvidia-driver = config.hardware.nvidia.package; };
-          in
-          lib.getExe script;
-        Type = "oneshot";
-      };
-    };
-
-  };
-
-}
diff --git a/nixos/modules/services/hardware/nvidia-container-toolkit/cdi-generate.nix b/nixos/modules/services/hardware/nvidia-container-toolkit/cdi-generate.nix
new file mode 100644
index 0000000000000..ca769cc44e5c9
--- /dev/null
+++ b/nixos/modules/services/hardware/nvidia-container-toolkit/cdi-generate.nix
@@ -0,0 +1,35 @@
+{
+  glibc,
+  jq,
+  lib,
+  mounts,
+  nvidia-container-toolkit,
+  nvidia-driver,
+  runtimeShell,
+  writeScriptBin,
+}: let
+  mkMount = {hostPath, containerPath, mountOptions}: {
+    inherit hostPath containerPath;
+    options = mountOptions;
+  };
+  jqAddMountExpression = ".containerEdits.mounts[.containerEdits.mounts | length] |= . +";
+  allJqMounts = lib.concatMap
+    (mount:
+      ["${lib.getExe jq} '${jqAddMountExpression} ${builtins.toJSON (mkMount mount)}'"])
+    mounts;
+in
+writeScriptBin "nvidia-cdi-generator"
+''
+#! ${runtimeShell}
+
+function cdiGenerate {
+  ${lib.getExe' nvidia-container-toolkit "nvidia-ctk"} cdi generate \
+    --format json \
+    --ldconfig-path ${lib.getExe' glibc "ldconfig"} \
+    --library-search-path ${lib.getLib nvidia-driver}/lib \
+    --nvidia-ctk-path ${lib.getExe' nvidia-container-toolkit "nvidia-ctk"}
+}
+
+cdiGenerate | \
+  ${lib.concatStringsSep " | " allJqMounts} > $RUNTIME_DIRECTORY/nvidia-container-toolkit.json
+''
diff --git a/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix b/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix
new file mode 100644
index 0000000000000..6c6bc667e6498
--- /dev/null
+++ b/nixos/modules/services/hardware/nvidia-container-toolkit/default.nix
@@ -0,0 +1,127 @@
+{ config, lib, pkgs, ... }:
+
+{
+  imports = [
+    (lib.mkRenamedOptionModule
+      [ "virtualisation" "containers" "cdi" "dynamic" "nvidia" "enable" ]
+      [ "hardware" "nvidia-container-toolkit" "enable" ])
+  ];
+
+  options = let
+    mountType = {
+      options = {
+        hostPath = lib.mkOption {
+          type = lib.types.str;
+          description = "Host path.";
+        };
+        containerPath = lib.mkOption {
+          type = lib.types.str;
+          description = "Container path.";
+        };
+        mountOptions = lib.mkOption {
+          default = [ "ro" "nosuid" "nodev" "bind" ];
+          type = lib.types.listOf lib.types.str;
+          description = "Mount options.";
+        };
+      };
+    };
+  in {
+
+    hardware.nvidia-container-toolkit = {
+      enable = lib.mkOption {
+        default = false;
+        type = lib.types.bool;
+        description = ''
+          Enable dynamic CDI configuration for NVidia devices by running
+          nvidia-container-toolkit on boot.
+        '';
+      };
+
+      mounts = lib.mkOption {
+        type = lib.types.listOf (lib.types.submodule mountType);
+        default = [];
+        description = "Mounts to be added to every container under the Nvidia CDI profile.";
+      };
+
+      mount-nvidia-executables = lib.mkOption {
+        default = true;
+        type = lib.types.bool;
+        description = ''
+          Mount executables nvidia-smi, nvidia-cuda-mps-control, nvidia-cuda-mps-server,
+          nvidia-debugdump, nvidia-powerd and nvidia-ctk on containers.
+        '';
+      };
+
+      mount-nvidia-docker-1-directories = lib.mkOption {
+        default = true;
+        type = lib.types.bool;
+        description = ''
+          Mount nvidia-docker-1 directories on containers: /usr/local/nvidia/lib and
+          /usr/local/nvidia/lib64.
+        '';
+      };
+    };
+
+  };
+
+  config = {
+
+    virtualisation.docker.daemon.settings = lib.mkIf
+      (config.hardware.nvidia-container-toolkit.enable &&
+       (lib.versionAtLeast config.virtualisation.docker.package.version "25")) {
+      features.cdi = true;
+    };
+
+    hardware.nvidia-container-toolkit.mounts = let
+      nvidia-driver = config.hardware.nvidia.package;
+    in (lib.mkMerge [
+      [{ hostPath = pkgs.addDriverRunpath.driverLink;
+         containerPath = pkgs.addDriverRunpath.driverLink; }
+       { hostPath = "${lib.getLib pkgs.glibc}/lib";
+         containerPath = "${lib.getLib pkgs.glibc}/lib"; }
+       { hostPath = "${lib.getLib pkgs.glibc}/lib64";
+         containerPath = "${lib.getLib pkgs.glibc}/lib64"; }]
+      (lib.mkIf config.hardware.nvidia-container-toolkit.mount-nvidia-executables
+        [{ hostPath = lib.getExe' nvidia-driver "nvidia-cuda-mps-control";
+           containerPath = "/usr/bin/nvidia-cuda-mps-control"; }
+         { hostPath = lib.getExe' nvidia-driver "nvidia-cuda-mps-server";
+           containerPath = "/usr/bin/nvidia-cuda-mps-server"; }
+         { hostPath = lib.getExe' nvidia-driver "nvidia-debugdump";
+           containerPath = "/usr/bin/nvidia-debugdump"; }
+         { hostPath = lib.getExe' nvidia-driver "nvidia-powerd";
+           containerPath = "/usr/bin/nvidia-powerd"; }
+         { hostPath = lib.getExe' nvidia-driver "nvidia-smi";
+           containerPath = "/usr/bin/nvidia-smi"; }])
+      # nvidia-docker 1.0 uses /usr/local/nvidia/lib{,64}
+      #   e.g.
+      #     - https://gitlab.com/nvidia/container-images/cuda/-/blob/e3ff10eab3a1424fe394899df0e0f8ca5a410f0f/dist/12.3.1/ubi9/base/Dockerfile#L44
+      #     - https://github.com/NVIDIA/nvidia-docker/blob/01d2c9436620d7dde4672e414698afe6da4a282f/src/nvidia/volumes.go#L104-L173
+      (lib.mkIf config.hardware.nvidia-container-toolkit.mount-nvidia-docker-1-directories
+        [{ hostPath = "${lib.getLib nvidia-driver}/lib";
+           containerPath = "/usr/local/nvidia/lib"; }
+         { hostPath = "${lib.getLib nvidia-driver}/lib";
+           containerPath = "/usr/local/nvidia/lib64"; }])
+    ]);
+
+    systemd.services.nvidia-container-toolkit-cdi-generator = lib.mkIf config.hardware.nvidia-container-toolkit.enable {
+      description = "Container Device Interface (CDI) for Nvidia generator";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "systemd-udev-settle.service" ];
+      serviceConfig = {
+        RuntimeDirectory = "cdi";
+        RemainAfterExit = true;
+        ExecStart =
+          let
+            script = pkgs.callPackage ./cdi-generate.nix {
+              inherit (config.hardware.nvidia-container-toolkit) mounts;
+              nvidia-driver = config.hardware.nvidia.package;
+            };
+          in
+          lib.getExe script;
+        Type = "oneshot";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/home-automation/ebusd.nix b/nixos/modules/services/home-automation/ebusd.nix
index aaf2ca1d775d5..d388022d7b50b 100644
--- a/nixos/modules/services/home-automation/ebusd.nix
+++ b/nixos/modules/services/home-automation/ebusd.nix
@@ -97,50 +97,50 @@ in
 
     logs = {
       main = mkOption {
-        type = types.enum [ "error" "notice" "info" "debug"];
+        type = types.enum [ "none" "error" "notice" "info" "debug"];
         default = "info";
         description = ''
-          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (error|notice|info|debug) [all:notice].
+          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (none|error|notice|info|debug) [all:notice].
         '';
       };
 
       network = mkOption {
-        type = types.enum [ "error" "notice" "info" "debug"];
+        type = types.enum [ "none" "error" "notice" "info" "debug"];
         default = "info";
         description = ''
-          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (error|notice|info|debug) [all:notice].
+          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (none|error|notice|info|debug) [all:notice].
         '';
       };
 
       bus = mkOption {
-        type = types.enum [ "error" "notice" "info" "debug"];
+        type = types.enum [ "none" "error" "notice" "info" "debug"];
         default = "info";
         description = ''
-          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (error|notice|info|debug) [all:notice].
+          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (none|error|notice|info|debug) [all:notice].
         '';
       };
 
       update = mkOption {
-        type = types.enum [ "error" "notice" "info" "debug"];
+        type = types.enum [ "none" "error" "notice" "info" "debug"];
         default = "info";
         description = ''
-          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (error|notice|info|debug) [all:notice].
+          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (none|error|notice|info|debug) [all:notice].
         '';
       };
 
       other = mkOption {
-        type = types.enum [ "error" "notice" "info" "debug"];
+        type = types.enum [ "none" "error" "notice" "info" "debug"];
         default = "info";
         description = ''
-          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (error|notice|info|debug) [all:notice].
+          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (none|error|notice|info|debug) [all:notice].
         '';
       };
 
       all = mkOption {
-        type = types.enum [ "error" "notice" "info" "debug"];
+        type = types.enum [ "none" "error" "notice" "info" "debug"];
         default = "info";
         description = ''
-          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (error|notice|info|debug) [all:notice].
+          Only write log for matching AREAs (main|network|bus|update|other|all) below or equal to LEVEL (none|error|notice|info|debug) [all:notice].
         '';
       };
     };
diff --git a/nixos/modules/services/home-automation/evcc.nix b/nixos/modules/services/home-automation/evcc.nix
index cf4043c946fa5..a952437b1b56e 100644
--- a/nixos/modules/services/home-automation/evcc.nix
+++ b/nixos/modules/services/home-automation/evcc.nix
@@ -63,6 +63,7 @@ in
         DynamicUser = true;
         LockPersonality = true;
         MemoryDenyWriteExecute = true;
+        Restart = "on-failure";
         RestrictAddressFamilies = [
           "AF_INET"
           "AF_INET6"
diff --git a/nixos/modules/services/home-automation/wyoming/faster-whisper.nix b/nixos/modules/services/home-automation/wyoming/faster-whisper.nix
index cbff3ab3e617c..d0fca6a41c7b6 100644
--- a/nixos/modules/services/home-automation/wyoming/faster-whisper.nix
+++ b/nixos/modules/services/home-automation/wyoming/faster-whisper.nix
@@ -119,6 +119,8 @@ in
         wantedBy = [
           "multi-user.target"
         ];
+        # https://github.com/rhasspy/wyoming-faster-whisper/issues/27
+        environment."HF_HUB_CACHE" = "/tmp";
         serviceConfig = {
           DynamicUser = true;
           User = "wyoming-faster-whisper";
diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix
index 3e29828eba2f2..9344277fc1e02 100644
--- a/nixos/modules/services/logging/logrotate.nix
+++ b/nixos/modules/services/logging/logrotate.nix
@@ -224,7 +224,7 @@ in
           and users are replaced by dummy users), so tests are complemented by a
           logrotate-checkconf service that is enabled by default.
           This extra check can be disabled by disabling it at the systemd level with the
-          {option}`services.systemd.services.logrotate-checkconf.enable` option.
+          {option}`systemd.services.logrotate-checkconf.enable` option.
 
           Conversely there are still things that might make this check fail incorrectly
           (e.g. a file path where we don't have access to intermediate directories):
diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix
index 7e7ca7e4060ec..180c9800d7345 100644
--- a/nixos/modules/services/mail/mailman.nix
+++ b/nixos/modules/services/mail/mailman.nix
@@ -534,14 +534,11 @@ in {
               hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
               secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
 
-              mailmanWebCfgTmp=$(mktemp)
-              jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
+              install -m 0440 -o root -g mailman \
+                <(jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
                   --arg archiver_key "$hyperkittyApiKey" \
-                  --arg secret_key "$secretKey" \
-                  >"$mailmanWebCfgTmp"
-              chown root:mailman "$mailmanWebCfgTmp"
-              chmod 440 "$mailmanWebCfgTmp"
-              mv -n "$mailmanWebCfgTmp" "$mailmanWebCfg"
+                  --arg secret_key "$secretKey") \
+                "$mailmanWebCfg"
           fi
 
           hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY "$mailmanWebCfg")"
diff --git a/nixos/modules/services/mail/roundcube.nix b/nixos/modules/services/mail/roundcube.nix
index 4499532ace897..78f627d33e2df 100644
--- a/nixos/modules/services/mail/roundcube.nix
+++ b/nixos/modules/services/mail/roundcube.nix
@@ -7,7 +7,7 @@ let
   fpm = config.services.phpfpm.pools.roundcube;
   localDB = cfg.database.host == "localhost";
   user = cfg.database.username;
-  phpWithPspell = pkgs.php81.withExtensions ({ enabled, all }: [ all.pspell ] ++ enabled);
+  phpWithPspell = pkgs.php83.withExtensions ({ enabled, all }: [ all.pspell ] ++ enabled);
 in
 {
   options.services.roundcube = {
@@ -247,14 +247,15 @@ in
       (mkIf (cfg.database.host == "localhost") {
         requires = [ "postgresql.service" ];
         after = [ "postgresql.service" ];
-        path = [ config.services.postgresql.package ];
       })
       {
         wants = [ "network-online.target" ];
         after = [ "network-online.target" ];
         wantedBy = [ "multi-user.target" ];
+
+        path = [ config.services.postgresql.package ];
         script = let
-          psql = "${lib.optionalString (!localDB) "PGPASSFILE=${cfg.database.passwordFile}"} ${pkgs.postgresql}/bin/psql ${lib.optionalString (!localDB) "-h ${cfg.database.host} -U ${cfg.database.username} "} ${cfg.database.dbname}";
+          psql = "${lib.optionalString (!localDB) "PGPASSFILE=${cfg.database.passwordFile}"} psql ${lib.optionalString (!localDB) "-h ${cfg.database.host} -U ${cfg.database.username} "} ${cfg.database.dbname}";
         in
         ''
           version="$(${psql} -t <<< "select value from system where name = 'roundcube-version';" || true)"
diff --git a/nixos/modules/services/matrix/appservice-irc.nix b/nixos/modules/services/matrix/appservice-irc.nix
index 90790169142aa..f4539a90f2e60 100644
--- a/nixos/modules/services/matrix/appservice-irc.nix
+++ b/nixos/modules/services/matrix/appservice-irc.nix
@@ -214,8 +214,9 @@ in {
         RestrictRealtime = true;
         PrivateMounts = true;
         SystemCallFilter = [
-          "@system-service @pkey @chown"
+          "@system-service @pkey"
           "~@privileged @resources"
+          "@chown"
         ];
         SystemCallArchitectures = "native";
         # AF_UNIX is required to connect to a postgres socket.
diff --git a/nixos/modules/services/matrix/conduit.nix b/nixos/modules/services/matrix/conduit.nix
index e6685af562c0a..9b8a4f45c268f 100644
--- a/nixos/modules/services/matrix/conduit.nix
+++ b/nixos/modules/services/matrix/conduit.nix
@@ -102,7 +102,7 @@ in
         default = {};
         description = ''
             Generates the conduit.toml configuration file. Refer to
-            <https://gitlab.com/famedly/conduit/-/blob/master/conduit-example.toml>
+            <https://docs.conduit.rs/configuration.html>
             for details on supported values.
             Note that database_path can not be edited because the service's reliance on systemd StateDir.
         '';
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index e76ba0efd4283..a8526688b074f 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -722,5 +722,5 @@ in
       timerConfig.OnCalendar = cfg.dump.interval;
     };
   };
-  meta.maintainers = with lib.maintainers; [ srhb ma27 thehedgeh0g ];
+  meta.maintainers = with lib.maintainers; [ srhb ma27 pyrox0 ];
 }
diff --git a/nixos/modules/services/misc/greenclip.nix b/nixos/modules/services/misc/greenclip.nix
index 9d1483a5a047a..d92cd1854877f 100644
--- a/nixos/modules/services/misc/greenclip.nix
+++ b/nixos/modules/services/misc/greenclip.nix
@@ -18,7 +18,10 @@ in {
       description = "greenclip daemon";
       wantedBy = [ "graphical-session.target" ];
       after    = [ "graphical-session.target" ];
-      serviceConfig.ExecStart = "${cfg.package}/bin/greenclip daemon";
+      serviceConfig = {
+        ExecStart = "${cfg.package}/bin/greenclip daemon";
+        Restart = "always";
+      };
     };
 
     environment.systemPackages = [ cfg.package ];
diff --git a/nixos/modules/services/monitoring/parsedmarc.nix b/nixos/modules/services/monitoring/parsedmarc.nix
index 9191a4a697e0b..a14ade59c29eb 100644
--- a/nixos/modules/services/monitoring/parsedmarc.nix
+++ b/nixos/modules/services/monitoring/parsedmarc.nix
@@ -301,7 +301,7 @@ in
               description = ''
                 The addresses to send outgoing mail to.
               '';
-              apply = x: if x == [] then null else lib.concatStringsSep "," x;
+              apply = x: if x == [] || x == null then null else lib.concatStringsSep "," x;
             };
           };
 
@@ -438,7 +438,7 @@ in
             ];
         dashboards.settings.providers = lib.mkIf cfg.provision.grafana.dashboard [{
           name = "parsedmarc";
-          options.path = "${pkgs.python3Packages.parsedmarc.dashboard}";
+          options.path = "${pkgs.parsedmarc.dashboard}";
         }];
       };
     };
@@ -446,7 +446,7 @@ in
     services.parsedmarc.settings = lib.mkMerge [
       (lib.mkIf cfg.provision.elasticsearch {
         elasticsearch = {
-          hosts = [ "localhost:9200" ];
+          hosts = [ "http://localhost:9200" ];
           ssl = false;
         };
       })
@@ -530,7 +530,7 @@ in
             MemoryDenyWriteExecute = true;
             LockPersonality = true;
             SystemCallArchitectures = "native";
-            ExecStart = "${pkgs.python3Packages.parsedmarc}/bin/parsedmarc -c /run/parsedmarc/parsedmarc.ini";
+            ExecStart = "${lib.getExe pkgs.parsedmarc} -c /run/parsedmarc/parsedmarc.ini";
           };
         };
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix b/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix
index 33a28ba132b8b..f188fe1f68fb8 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.apcupsd;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9162;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix b/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix
index 306726f47e395..e98982c0dd312 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/artifactory.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.artifactory;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9531;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bind.nix b/nixos/modules/services/monitoring/prometheus/exporters/bind.nix
index 0f3a13900a274..1c7dcf8b1ef03 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/bind.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/bind.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.bind;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9119;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bird.nix b/nixos/modules/services/monitoring/prometheus/exporters/bird.nix
index a020cd3d54b42..5d91eeed106d4 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/bird.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/bird.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.bird;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    singleton
+    ;
 in
 {
   port = 9324;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix b/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix
index b2bea158b07fc..e44140b1f51a0 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/bitcoin.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.bitcoin;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9332;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix b/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
index 80d0cfcc5e451..33a1fdc528053 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
@@ -1,10 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   logPrefix = "services.prometheus.exporter.blackbox";
   cfg = config.services.prometheus.exporters.blackbox;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    escapeShellArg
+    ;
 
   # This ensures that we can deal with string paths, path types and
   # store-path strings with context.
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix b/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix
index ff1ee6a517b9c..0af1e33b2c445 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/buildkite-agent.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.buildkite-agent;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    optionalString
+    literalExpression
+    ;
 in
 {
   port = 9876;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix b/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
index 339eb8c3f5f46..6f4c936fd4093 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
@@ -1,9 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.collectd;
+  inherit (lib)
+    mkOption
+    mkEnableOption
+    types
+    optionalString
+    concatStringsSep
+    escapeShellArg
+    ;
 in
 {
   port = 9103;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix b/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix
index 0f240cb30bb1d..3674fab1e4f83 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.dmarc;
+  inherit (lib) mkOption types optionalString;
 
   json = builtins.toJSON {
     inherit (cfg) folders port;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
index f7ff2665f3d89..ba438ea74a3b6 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.dnsmasq;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    escapeShellArg
+    ;
 in
 {
   port = 9153;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/domain.nix b/nixos/modules/services/monitoring/prometheus/exporters/domain.nix
index b2c8e6664c0f6..c271a040d288f 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/domain.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/domain.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.domain;
+  inherit (lib) concatStringsSep;
 in
 {
   port = 9222;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix b/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
index ca02f73729161..f11e91fd761a9 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.dovecot;
+  inherit (lib)
+    mkOption
+    types
+    escapeShellArg
+    concatStringsSep
+    ;
 in
 {
   port = 9166;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/flow.nix b/nixos/modules/services/monitoring/prometheus/exporters/flow.nix
index a9e2446d01568..7719215952a53 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/flow.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/flow.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.flow;
+  inherit (lib)
+    mkOption
+    types
+    literalExpression
+    concatStringsSep
+    optionalString
+    ;
 in {
   port = 9590;
   extraOpts = {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix b/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix
index fe1d1834570ac..29470147c13f2 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/fritzbox.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.fritzbox;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9133;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix b/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix
index 3d1123e18a32d..54696187feb15 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/idrac.nix
@@ -1,8 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
 let
   cfg = config.services.prometheus.exporters.idrac;
+  inherit (lib) mkOption types;
 
   configFile = if cfg.configurationPath != null
                then cfg.configurationPath
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix b/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix
index c1e2a458f97b3..92d02a3f14635 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/imap-mailstat.nix
@@ -1,7 +1,5 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.imap-mailstat;
   valueToString = value:
@@ -13,6 +11,15 @@ let
         else "XXX ${toString value}"
       )
     );
+  inherit (lib)
+    mkOption
+    types
+    concatStrings
+    concatStringsSep
+    attrValues
+    mapAttrs
+    optionalString
+    ;
   createConfigFile = accounts:
     # unfortunately on toTOML yet
     # https://github.com/NixOS/nix/issues/3929
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix
index 9ac0c35bf816f..3a5680439d4c2 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.influxdb;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9122;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix b/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix
index a51c09d5086c0..51db6059081fb 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/ipmi.nix
@@ -1,10 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   logPrefix = "services.prometheus.exporter.ipmi";
   cfg = config.services.prometheus.exporters.ipmi;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    optionals
+    escapeShellArg
+    ;
 in {
   port = 9290;
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix b/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix
index f6c2d9172f4c4..6a6c003c19776 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/jitsi.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.jitsi;
+  inherit (lib)
+    mkOption
+    types
+    escapeShellArg
+    concatStringsSep
+    ;
 in
 {
   port = 9700;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/json.nix b/nixos/modules/services/monitoring/prometheus/exporters/json.nix
index 1e4632f9310eb..1c8db0ea3e0b1 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/json.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/json.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.json;
+  inherit (lib)
+    mkOption
+    types
+    escapeShellArg
+    concatStringsSep
+    mkRemovedOptionModule
+    ;
 in
 {
   port = 7979;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix b/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix
index 75b8bb650478a..3519cce6e821b 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/junos-czerwonk.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.junos-czerwonk;
+  inherit (lib)
+    mkOption
+    types
+    escapeShellArg
+    mkIf
+    concatStringsSep
+    ;
 
   configFile = if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configurationFile);
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/kea.nix b/nixos/modules/services/monitoring/prometheus/exporters/kea.nix
index 88dc284a8cc63..d0f2eb6b8a3c0 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/kea.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/kea.nix
@@ -5,10 +5,14 @@
 , ...
 }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.kea;
+  inherit (lib)
+    mkOption
+    types
+    mkRenamedOptionModule
+    literalExpression
+    ;
 in {
   imports = [
     (mkRenamedOptionModule [ "controlSocketPaths" ] [ "targets" ])
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix b/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix
index afdb664a0de5e..44169cce6745e 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.keylight;
+  inherit (lib) concatStringsSep;
 in
 {
   port = 9288;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/knot.nix b/nixos/modules/services/monitoring/prometheus/exporters/knot.nix
index 79d952dfb1641..ed902fc27c152 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/knot.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/knot.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.knot;
+  inherit (lib)
+    mkOption
+    types
+    literalExpression
+    concatStringsSep
+    ;
 in {
   port = 9433;
   extraOpts = {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix b/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix
index cc8db6e1b4e43..edface276f541 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.lnd;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9092;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
index 7ace5c1968fb1..f6dd6f7eb994a 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
@@ -1,9 +1,19 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.mail;
+  inherit (lib)
+    mkOption
+    types
+    mapAttrs'
+    nameValuePair
+    toLower
+    filterAttrs
+    escapeShellArg
+    literalExpression
+    mkIf
+    concatStringsSep
+    ;
 
   configFile = if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile);
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix b/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
index 9e0a98f0ba64f..cd438f13edd25 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.mikrotik;
+  inherit (lib)
+    mkOption
+    types
+    literalExpression
+    concatStringsSep
+    escapeShellArg
+    ;
 in
 {
   port = 9436;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/minio.nix b/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
index e1edd364c8fcb..8faff5908b8a9 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.minio;
+  inherit (lib)
+    mkOption
+    types
+    optionalString
+    concatStringsSep
+    escapeShellArg
+    ;
 in
 {
   port = 9290;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix b/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix
index 37a2daebd9739..37ff49b27000f 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.modemmanager;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9539;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix b/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix
index 10d533a2bbdad..288434e93abb0 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/mongodb.nix
@@ -1,9 +1,17 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.mongodb;
+  inherit (lib)
+    mkOption
+    types
+    optionalString
+    getExe
+    length
+    concatStringsSep
+    concatMapStringsSep
+    escapeShellArgs
+    ;
 in
 {
   port = 9216;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nats.nix b/nixos/modules/services/monitoring/prometheus/exporters/nats.nix
index 83e60426f5ed2..224ce474d5377 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/nats.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/nats.nix
@@ -1,11 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
-
   cfg = config.services.prometheus.exporters.nats;
-
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 7777;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix b/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
index f22c5e2e5cff1..d221bac8421ac 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.nextcloud;
+  inherit (lib)
+    mkOption
+    types
+    escapeShellArg
+    concatStringsSep
+    ;
 in
 {
   port = 9205;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
index d4939c7063a39..091ad2291d2a6 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
@@ -1,9 +1,16 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.nginx;
+  inherit (lib)
+    mkOption
+    types
+    mkMerge
+    mkRemovedOptionModule
+    mkRenamedOptionModule
+    mkIf
+    concatStringsSep
+    ;
 in
 {
   port = 9113;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix b/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix
index ebb13a8c3ee3b..2b4fd12895a39 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/nginxlog.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.nginxlog;
+  inherit (lib) mkOption types;
 in {
   port = 9117;
   extraOpts = {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/node.nix b/nixos/modules/services/monitoring/prometheus/exporters/node.nix
index 8615bd04951cc..9d6b51ad140d0 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/node.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/node.nix
@@ -1,9 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.node;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    concatMapStringsSep
+    any
+    optionals
+    ;
   collectorIsEnabled = final: any (collector: (final == collector)) cfg.enabledCollectors;
   collectorIsDisabled = final: any (collector: (final == collector)) cfg.disabledCollectors;
 in
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nut.nix b/nixos/modules/services/monitoring/prometheus/exporters/nut.nix
index e88059cea4396..157bdadddfc99 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/nut.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/nut.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.nut;
+  inherit (lib)
+    mkOption
+    types
+    optionalString
+    concatStringsSep
+    ;
 in
 {
   port = 9199;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/openldap.nix b/nixos/modules/services/monitoring/prometheus/exporters/openldap.nix
index 9c1b39bb3a349..bb65bd2709330 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/openldap.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/openldap.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.openldap;
+  inherit (lib) mkOption types concatStringsSep;
 in {
   port = 9330;
   extraOpts = {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix b/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix
index 725a5679e271f..71b602638632e 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/pgbouncer.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.pgbouncer;
+  inherit (lib)
+    mkOption
+    types
+    optionals
+    escapeShellArg
+    concatStringsSep
+    ;
 in
 {
   port = 9127;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix b/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix
index 926626b5e7979..30b260dc3792a 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/pihole.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.pihole;
+  inherit (lib)
+    mkOption
+    types
+    mkRemovedOptionModule
+    optionalString
+    ;
 in
 {
   imports = [
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/ping.nix b/nixos/modules/services/monitoring/prometheus/exporters/ping.nix
index a47db4c16f427..9122a6be66e66 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/ping.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/ping.nix
@@ -1,9 +1,9 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
 
 let
   cfg = config.services.prometheus.exporters.ping;
+  inherit (lib) mkOption types concatStringsSep;
 
   settingsFormat = pkgs.formats.yaml {};
   configFile = settingsFormat.generate "config.yml" cfg.settings;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
index 188a5f9a1a14a..7aa3622f16d62 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
@@ -1,9 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.postfix;
+  inherit (lib)
+    mkOption
+    types
+    mkIf
+    escapeShellArg
+    concatStringsSep
+    optional
+    ;
 in
 {
   port = 9154;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix b/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix
index 7ed71ff9e10e9..bf392382660ab 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/postgres.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.postgres;
+  inherit (lib)
+    mkOption
+    types
+    mkIf
+    mkForce
+    concatStringsSep
+    ;
 in
 {
   port = 9187;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/process.nix b/nixos/modules/services/monitoring/prometheus/exporters/process.nix
index b041a957b6387..8e5eceee067ce 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/process.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/process.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.process;
+  inherit (lib)
+    mkOption
+    types
+    literalExpression
+    concatStringsSep
+    ;
   configFile = pkgs.writeText "process-exporter.yaml" (builtins.toJSON cfg.settings);
 in
 {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/pve.nix b/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
index 96db49d9591f7..8928577b69532 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/pve.nix
@@ -1,8 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
 let
   cfg = config.services.prometheus.exporters.pve;
+  inherit (lib)
+    mkOption
+    types
+    mkPackageOption
+    optionalString
+    optionalAttrs
+    ;
 
   # pve exporter requires a config file so create an empty one if configFile is not provided
   emptyConfigFile = pkgs.writeTextFile {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix b/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix
index 66a8423f8ff5c..d788ce363d614 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/py-air-control.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.py-air-control;
+  inherit (lib) mkOption types;
 
   workingDir = "/var/lib/${cfg.stateDir}";
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/redis.nix b/nixos/modules/services/monitoring/prometheus/exporters/redis.nix
index ee7d87e8e6150..672e3dfe7b059 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/redis.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/redis.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.redis;
+  inherit (lib) concatStringsSep;
 in
 {
   port = 9121;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/restic.nix b/nixos/modules/services/monitoring/prometheus/exporters/restic.nix
index aaf3c189a4d20..ef44803ba053d 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/restic.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/restic.nix
@@ -1,9 +1,18 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.restic;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    mkIf
+    mapAttrs'
+    splitString
+    toUpper
+    optionalAttrs
+    nameValuePair
+    ;
 in
 {
   port = 9753;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix b/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix
index ee8047fb4599d..8993aee5d2482 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/rspamd.nix
@@ -1,9 +1,16 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.rspamd;
+  inherit (lib)
+    mkOption
+    types
+    replaceStrings
+    mkRemovedOptionModule
+    recursiveUpdate
+    concatStringsSep
+    literalExpression
+    ;
 
   mkFile = conf:
     pkgs.writeText "rspamd-exporter-config.yml" (builtins.toJSON conf);
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/script.nix b/nixos/modules/services/monitoring/prometheus/exporters/script.nix
index 5fe8512f554e7..0967ce236a62e 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/script.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/script.nix
@@ -1,9 +1,13 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.script;
+  inherit (lib)
+    mkOption
+    types
+    literalExpression
+    concatStringsSep
+    ;
   configFile = pkgs.writeText "script-exporter.yaml" (builtins.toJSON cfg.settings);
 in
 {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix b/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix
index 5b3cf10b650b0..be3e483c6ee19 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/shelly.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.shelly;
+  inherit (lib) mkOption types;
 in
 {
   port = 9784;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix b/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix
index 84658c48c7239..8aadd87abbedb 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.smartctl;
+  inherit (lib) mkOption types literalExpression;
   args = lib.escapeShellArgs ([
     "--web.listen-address=${cfg.listenAddress}:${toString cfg.port}"
     "--smartctl.path=${pkgs.smartmontools}/bin/smartctl"
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix b/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix
index 79ed5129dda4d..c3baed1503764 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.smokeping;
+  inherit (lib) mkOption types concatStringsSep;
   goDuration = types.mkOptionType {
     name = "goDuration";
     description = "Go duration (https://golang.org/pkg/time/#ParseDuration)";
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
index 19ab31d735f86..dc10a9a2f92ea 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
@@ -1,10 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   logPrefix = "services.prometheus.exporters.snmp";
   cfg = config.services.prometheus.exporters.snmp;
+  inherit (lib)
+    mkOption
+    types
+    literalExpression
+    escapeShellArg
+    concatStringsSep
+    ;
 
   # This ensures that we can deal with string paths, path types and
   # store-path strings with context.
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/sql.nix b/nixos/modules/services/monitoring/prometheus/exporters/sql.nix
index 4c4d8f880364a..59715f5d33e24 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/sql.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/sql.nix
@@ -1,7 +1,13 @@
 { config, lib, pkgs, options, ... }:
-with lib;
 let
   cfg = config.services.prometheus.exporters.sql;
+  inherit (lib)
+    mkOption
+    types
+    mapAttrs
+    mapAttrsToList
+    concatStringsSep
+    ;
   cfgOptions = {
     options = with types; {
       jobs = mkOption {
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix b/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix
index 94df86167e8ce..b1bc65c9a492f 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/statsd.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.statsd;
+  inherit (lib) concatStringsSep;
 in
 {
   port = 9102;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix b/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix
index 0e16d27b9d042..d848e263a3b64 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/surfboard.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.surfboard;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9239;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/systemd.nix b/nixos/modules/services/monitoring/prometheus/exporters/systemd.nix
index 2edd1de83e1bf..52bad81ed7d51 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/systemd.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/systemd.nix
@@ -1,9 +1,8 @@
 { config, pkgs, lib, ... }:
 
-with lib;
-
-let cfg = config.services.prometheus.exporters.systemd;
-
+let
+  cfg = config.services.prometheus.exporters.systemd;
+  inherit (lib) concatStringsSep;
 in {
   port = 9558;
 
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/tor.nix b/nixos/modules/services/monitoring/prometheus/exporters/tor.nix
index 48406def98944..d39112d0c283c 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/tor.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/tor.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.tor;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9130;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix b/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix
index 0452f630c2e2f..df6011e2434b1 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix
@@ -5,10 +5,17 @@
 , ...
 }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.unbound;
+  inherit (lib)
+    mkOption
+    types
+    mkRemovedOptionModule
+    optionalAttrs
+    optionalString
+    mkMerge
+    mkIf
+    ;
 in
 {
   imports = [
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix b/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
index 82309febf63b8..07d177251f40d 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.unifi;
+  inherit (lib)
+    mkOption
+    types
+    escapeShellArg
+    optionalString
+    concatStringsSep
+    ;
 in
 {
   port = 9130;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix b/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix
index 0ea824fbf1140..7b9ba4c5d1edb 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/unpoller.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.unpoller;
+  inherit (lib) mkEnableOption generators;
 
   configFile = pkgs.writeText "prometheus-unpoller-exporter.json" (generators.toJSON {} {
     poller = { inherit (cfg.log) debug quiet; };
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix b/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix
index 1582554c12531..4fda15c9ee4ea 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/v2ray.nix
@@ -1,9 +1,8 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.v2ray;
+  inherit (lib) mkOption types concatStringsSep;
 in
 {
   port = 9299;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
index 811792674b96c..e94c513ae84f1 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
@@ -1,9 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.varnish;
+  inherit (lib)
+    mkOption
+    types
+    mkDefault
+    optional
+    escapeShellArg
+    concatStringsSep
+    ;
 in
 {
   port = 9131;
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix b/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
index 27c0c191c6e34..7a48c836425ff 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
@@ -1,9 +1,15 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
-
 let
   cfg = config.services.prometheus.exporters.wireguard;
+  inherit (lib)
+    mkOption
+    types
+    mkRenamedOptionModule
+    mkEnableOption
+    optionalString
+    escapeShellArg
+    ;
 in {
   port = 9586;
   imports = [
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix b/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix
index ce9cd624dc278..a685b94b827f4 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/zfs.nix
@@ -1,9 +1,14 @@
 { config, lib, pkgs, options, ... }:
 
-with lib;
 
 let
   cfg = config.services.prometheus.exporters.zfs;
+  inherit (lib)
+    mkOption
+    types
+    concatStringsSep
+    concatMapStringsSep
+    ;
 in
 {
   port = 9134;
diff --git a/nixos/modules/services/monitoring/rustdesk-server.nix b/nixos/modules/services/monitoring/rustdesk-server.nix
index fcfd57167dd8f..21e6128c7226a 100644
--- a/nixos/modules/services/monitoring/rustdesk-server.nix
+++ b/nixos/modules/services/monitoring/rustdesk-server.nix
@@ -53,15 +53,14 @@ in {
         Slice = "system-rustdesk.slice";
         User  = "rustdesk";
         Group = "rustdesk";
+        DynamicUser = "yes";
         Environment = [];
         WorkingDirectory = "/var/lib/rustdesk";
         StateDirectory   = "rustdesk";
         StateDirectoryMode = "0750";
         LockPersonality = true;
-        NoNewPrivileges = true;
         PrivateDevices = true;
         PrivateMounts = true;
-        PrivateTmp = true;
         PrivateUsers = true;
         ProtectClock = true;
         ProtectControlGroups = true;
@@ -71,10 +70,7 @@ in {
         ProtectKernelModules = true;
         ProtectKernelTunables = true;
         ProtectProc = "invisible";
-        ProtectSystem = "strict";
-        RemoveIPC = true;
         RestrictNamespaces = true;
-        RestrictSUIDSGID = true;
       };
     };
   in lib.mkIf cfg.enable {
diff --git a/nixos/modules/services/monitoring/vmagent.nix b/nixos/modules/services/monitoring/vmagent.nix
index cdcf1571154e9..4838e0709d09e 100644
--- a/nixos/modules/services/monitoring/vmagent.nix
+++ b/nixos/modules/services/monitoring/vmagent.nix
@@ -1,63 +1,62 @@
 { config, pkgs, lib, ... }:
-with lib;
+
 let
   cfg = config.services.vmagent;
   settingsFormat = pkgs.formats.json { };
 in {
-  options.services.vmagent = {
-    enable = mkEnableOption "vmagent";
-
-    user = mkOption {
-      default = "vmagent";
-      type = types.str;
-      description = ''
-        User account under which vmagent runs.
-      '';
-    };
+  imports = [
+    (lib.mkRemovedOptionModule [ "services" "vmagent" "dataDir" ] "dataDir has been deprecated in favor of systemd provided CacheDirectory")
+    (lib.mkRemovedOptionModule [ "services" "vmagent" "user" ] "user has been deprecated in favor of systemd DynamicUser")
+    (lib.mkRemovedOptionModule [ "services" "vmagent" "group" ] "group has been deprecated in favor of systemd DynamicUser")
+    (lib.mkRenamedOptionModule [ "services" "vmagent" "remoteWriteUrl" ] [ "services" "vmagent" "remoteWrite" "url" ])
+  ];
 
-    group = mkOption {
-      type = types.str;
-      default = "vmagent";
-      description = ''
-        Group under which vmagent runs.
-      '';
-    };
-
-    package = mkPackageOption pkgs "vmagent" { };
+  options.services.vmagent = {
+    enable = lib.mkEnableOption "vmagent";
 
-    dataDir = mkOption {
-      type = types.str;
-      default = "/var/lib/vmagent";
-      description = ''
-        The directory where vmagent stores its data files.
-      '';
-    };
+    package = lib.mkPackageOption pkgs "vmagent" { };
 
-    remoteWriteUrl = mkOption {
-      default = "http://localhost:8428/api/v1/write";
-      type = types.str;
-      description = ''
-        The storage endpoint such as VictoriaMetrics
-      '';
+    remoteWrite = {
+      url = lib.mkOption {
+        default = null;
+        type = lib.types.nullOr lib.types.str;
+        description = ''
+          Endpoint for prometheus compatible remote_write
+        '';
+      };
+      basicAuthUsername = lib.mkOption {
+        default = null;
+        type = lib.types.nullOr lib.types.str;
+        description = ''
+          Basic Auth username used to connect to remote_write endpoint
+        '';
+      };
+      basicAuthPasswordFile = lib.mkOption {
+        default = null;
+        type = lib.types.nullOr lib.types.str;
+        description = ''
+          File that contains the Basic Auth password used to connect to remote_write endpoint
+        '';
+      };
     };
 
-    prometheusConfig = mkOption {
+    prometheusConfig = lib.mkOption {
       type = lib.types.submodule { freeformType = settingsFormat.type; };
       description = ''
         Config for prometheus style metrics
       '';
     };
 
-    openFirewall = mkOption {
-      type = types.bool;
+    openFirewall = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Whether to open the firewall for the default ports.
       '';
     };
 
-    extraArgs = mkOption {
-      type = types.listOf types.str;
+    extraArgs = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
       default = [];
       description = ''
         Extra args to pass to `vmagent`. See the docs:
@@ -67,37 +66,36 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
-    users.groups = mkIf (cfg.group == "vmagent") { vmagent = { }; };
-
-    users.users = mkIf (cfg.user == "vmagent") {
-      vmagent = {
-        group = cfg.group;
-        description = "vmagent daemon user";
-        home = cfg.dataDir;
-        isSystemUser = true;
-      };
-    };
-
-    networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 8429 ];
+  config = lib.mkIf cfg.enable {
+    networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ 8429 ];
 
     systemd.services.vmagent = let
       prometheusConfig = settingsFormat.generate "prometheusConfig.yaml" cfg.prometheusConfig;
+      startCommandLine = lib.concatStringsSep " " ([
+        "${cfg.package}/bin/vmagent"
+        "-promscrape.config=${prometheusConfig}"
+      ] ++ cfg.extraArgs
+        ++ lib.optionals (cfg.remoteWrite.url != null) [
+        "-remoteWrite.url=${cfg.remoteWrite.url}"
+        "-remoteWrite.tmpDataPath=%C/vmagent/remote_write_tmp"
+      ] ++ lib.optional (cfg.remoteWrite.basicAuthUsername != null) "-remoteWrite.basicAuth.username=${cfg.remoteWrite.basicAuthUsername}"
+        ++ lib.optional (cfg.remoteWrite.basicAuthPasswordFile != null) "-remoteWrite.basicAuth.passwordFile=\${CREDENTIALS_DIRECTORY}/remote_write_basic_auth_password");
     in {
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
       description = "vmagent system service";
       serviceConfig = {
-        User = cfg.user;
-        Group = cfg.group;
+        DynamicUser = true;
+        User = "vmagent";
+        Group = "vmagent";
         Type = "simple";
         Restart = "on-failure";
-        WorkingDirectory = cfg.dataDir;
-        ExecStart = "${cfg.package}/bin/vmagent -remoteWrite.url=${cfg.remoteWriteUrl} -promscrape.config=${prometheusConfig} ${escapeShellArgs cfg.extraArgs}";
+        CacheDirectory = "vmagent";
+        ExecStart = startCommandLine;
+        LoadCredential = lib.optional (cfg.remoteWrite.basicAuthPasswordFile != null) [
+          "remote_write_basic_auth_password:${cfg.remoteWrite.basicAuthPasswordFile}"
+        ];
       };
     };
-
-    systemd.tmpfiles.rules =
-      [ "d '${cfg.dataDir}' 0755 ${cfg.user} ${cfg.group} -" ];
   };
 }
diff --git a/nixos/modules/services/networking/adguardhome.nix b/nixos/modules/services/networking/adguardhome.nix
index 6958bcccf54cf..df9927351edc3 100644
--- a/nixos/modules/services/networking/adguardhome.nix
+++ b/nixos/modules/services/networking/adguardhome.nix
@@ -4,6 +4,7 @@ with lib;
 
 let
   cfg = config.services.adguardhome;
+  settingsFormat = pkgs.formats.yaml { };
 
   args = concatStringsSep " " ([
     "--no-check-update"
@@ -12,27 +13,33 @@ let
     "--config /var/lib/AdGuardHome/AdGuardHome.yaml"
   ] ++ cfg.extraArgs);
 
-  configFile = pkgs.writeTextFile {
-    name = "AdGuardHome.yaml";
-    text = builtins.toJSON cfg.settings;
-    checkPhase = "${pkgs.adguardhome}/bin/adguardhome -c $out --check-config";
-  };
-  defaultBindPort = 3000;
-
-in
-{
-
-  imports =
-    let cfgPath = [ "services" "adguardhome" ];
-    in
-    [
-      (mkRenamedOptionModuleWith { sinceRelease = 2211; from = cfgPath ++ [ "host" ]; to = cfgPath ++ [ "settings" "bind_host" ]; })
-      (mkRenamedOptionModuleWith { sinceRelease = 2211; from = cfgPath ++ [ "port" ]; to = cfgPath ++ [ "settings" "bind_port" ]; })
-    ];
-
+  settings = if (cfg.settings != null) then
+    cfg.settings // (if cfg.settings.schema_version < 23 then {
+      bind_host = cfg.host;
+      bind_port = cfg.port;
+    } else {
+      http.address = "${cfg.host}:${toString cfg.port}";
+    })
+  else
+    null;
+
+  configFile =
+    (settingsFormat.generate "AdGuardHome.yaml" settings).overrideAttrs (_: {
+      checkPhase = "${cfg.package}/bin/adguardhome -c $out --check-config";
+    });
+in {
   options.services.adguardhome = with types; {
     enable = mkEnableOption "AdGuard Home network-wide ad blocker";
 
+    package = mkOption {
+      type = package;
+      default = pkgs.adguardhome;
+      defaultText = literalExpression "pkgs.adguardhome";
+      description = ''
+        The package that runs adguardhome.
+      '';
+    };
+
     openFirewall = mkOption {
       default = false;
       type = bool;
@@ -43,8 +50,8 @@ in
     };
 
     allowDHCP = mkOption {
-      default = cfg.settings.dhcp.enabled or false;
-      defaultText = literalExpression ''config.services.adguardhome.settings.dhcp.enabled or false'';
+      default = settings.dhcp.enabled or false;
+      defaultText = literalExpression "config.services.adguardhome.settings.dhcp.enabled or false";
       type = bool;
       description = ''
         Allows AdGuard Home to open raw sockets (`CAP_NET_RAW`), which is
@@ -65,32 +72,34 @@ in
       '';
     };
 
+    host = mkOption {
+      default = "0.0.0.0";
+      type = str;
+      description = ''
+        Host address to bind HTTP server to.
+      '';
+    };
+
+    port = mkOption {
+      default = 3000;
+      type = port;
+      description = ''
+        Port to serve HTTP pages on.
+      '';
+    };
+
     settings = mkOption {
       default = null;
       type = nullOr (submodule {
-        freeformType = (pkgs.formats.yaml { }).type;
+        freeformType = settingsFormat.type;
         options = {
           schema_version = mkOption {
-            default = pkgs.adguardhome.schema_version;
-            defaultText = literalExpression "pkgs.adguardhome.schema_version";
+            default = cfg.package.schema_version;
+            defaultText = literalExpression "cfg.package.schema_version";
             type = int;
             description = ''
               Schema version for the configuration.
-              Defaults to the `schema_version` supplied by `pkgs.adguardhome`.
-            '';
-          };
-          bind_host = mkOption {
-            default = "0.0.0.0";
-            type = str;
-            description = ''
-              Host address to bind HTTP server to.
-            '';
-          };
-          bind_port = mkOption {
-            default = defaultBindPort;
-            type = port;
-            description = ''
-              Port to serve HTTP pages on.
+              Defaults to the `schema_version` supplied by `cfg.package`.
             '';
           };
         };
@@ -107,7 +116,7 @@ in
 
         Set this to `null` (default) for a non-declarative configuration without any
         Nix-supplied values.
-        Declarative configurations are supplied with a default `schema_version`, `bind_host`, and `bind_port`.
+        Declarative configurations are supplied with a default `schema_version`, and `http.address`.
         :::
       '';
     };
@@ -124,17 +133,25 @@ in
   config = mkIf cfg.enable {
     assertions = [
       {
-        assertion = cfg.settings != null -> cfg.mutableSettings
-          || (hasAttrByPath [ "dns" "bind_host" ] cfg.settings)
-          || (hasAttrByPath [ "dns" "bind_hosts" ] cfg.settings);
-        message =
-          "AdGuard setting dns.bind_host or dns.bind_hosts needs to be configured for a minimal working configuration";
+        assertion = cfg.settings != null
+          -> !(hasAttrByPath [ "bind_host" ] cfg.settings);
+        message = "AdGuard option `settings.bind_host' has been superseded by `services.adguardhome.host'";
+      }
+      {
+        assertion = cfg.settings != null
+          -> !(hasAttrByPath [ "bind_port" ] cfg.settings);
+        message = "AdGuard option `settings.bind_host' has been superseded by `services.adguardhome.port'";
+      }
+      {
+        assertion = settings != null -> cfg.mutableSettings
+          || hasAttrByPath [ "dns" "bootstrap_dns" ] settings;
+        message = "AdGuard setting dns.bootstrap_dns needs to be configured for a minimal working configuration";
       }
       {
-        assertion = cfg.settings != null -> cfg.mutableSettings
-          || hasAttrByPath [ "dns" "bootstrap_dns" ] cfg.settings;
-        message =
-          "AdGuard setting dns.bootstrap_dns needs to be configured for a minimal working configuration";
+        assertion = settings != null -> cfg.mutableSettings
+          || hasAttrByPath [ "dns" "bootstrap_dns" ] settings
+          && isList settings.dns.bootstrap_dns;
+        message = "AdGuard setting dns.bootstrap_dns needs to be a list";
       }
     ];
 
@@ -147,7 +164,7 @@ in
         StartLimitBurst = 10;
       };
 
-      preStart = optionalString (cfg.settings != null) ''
+      preStart = optionalString (settings != null) ''
         if    [ -e "$STATE_DIRECTORY/AdGuardHome.yaml" ] \
            && [ "${toString cfg.mutableSettings}" = "1" ]; then
           # Writing directly to AdGuardHome.yaml results in empty file
@@ -161,8 +178,9 @@ in
 
       serviceConfig = {
         DynamicUser = true;
-        ExecStart = "${pkgs.adguardhome}/bin/adguardhome ${args}";
-        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ] ++ optionals cfg.allowDHCP [ "CAP_NET_RAW" ];
+        ExecStart = "${cfg.package}/bin/adguardhome ${args}";
+        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]
+          ++ optionals cfg.allowDHCP [ "CAP_NET_RAW" ];
         Restart = "always";
         RestartSec = 10;
         RuntimeDirectory = "AdGuardHome";
@@ -170,6 +188,6 @@ in
       };
     };
 
-    networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.bind_port or defaultBindPort ];
+    networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
   };
 }
diff --git a/nixos/modules/services/networking/clatd.nix b/nixos/modules/services/networking/clatd.nix
new file mode 100644
index 0000000000000..76e0c130ca466
--- /dev/null
+++ b/nixos/modules/services/networking/clatd.nix
@@ -0,0 +1,82 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.clatd;
+
+  settingsFormat = pkgs.formats.keyValue {};
+
+  configFile = settingsFormat.generate "clatd.conf" cfg.settings;
+in
+{
+  options = {
+    services.clatd = {
+      enable = mkEnableOption "clatd";
+
+      package = mkPackageOption pkgs "clatd" { };
+
+      settings = mkOption {
+        type = types.submodule ({ name, ... }: {
+          freeformType = settingsFormat.type;
+        });
+        default = { };
+        example = literalExpression ''
+          {
+            plat-prefix = "64:ff9b::/96";
+          }
+        '';
+        description = ''
+          Configuration of clatd. See [clatd Documentation](https://github.com/toreanderson/clatd/blob/master/README.pod#configuration).
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.clatd = {
+      description = "464XLAT CLAT daemon";
+      documentation = [ "man:clatd(8)" ];
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-online.target" ];
+      wants = [ "network-online.target" ];
+      startLimitIntervalSec = 0;
+
+      serviceConfig = {
+        ExecStart = "${cfg.package}/bin/clatd -c ${configFile}";
+        startLimitIntervalSec = 0;
+
+        # Hardening
+        CapabilityBoundingSet = [
+          "CAP_NET_ADMIN"
+        ];
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateTmp = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectProc = "invisible";
+        ProtectSystem = true;
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+          "AF_NETLINK"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [
+          "@network-io"
+          "@system-service"
+          "~@privileged"
+          "~@resources"
+        ];
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/deconz.nix b/nixos/modules/services/networking/deconz.nix
index eaa7759d0407c..88b0ee612d871 100644
--- a/nixos/modules/services/networking/deconz.nix
+++ b/nixos/modules/services/networking/deconz.nix
@@ -95,7 +95,7 @@ in
       '';
       postStart = ''
         # Delay signalling service readiness until it's actually up.
-        while ! "${lib.getExe pkgs.curl}" -sSfl -o /dev/null "http://${cfg.listenAddress}:${toString cfg.httpPort}"; do
+        while ! "${lib.getExe pkgs.curl}" -sSfL -o /dev/null "http://${cfg.listenAddress}:${toString cfg.httpPort}"; do
             echo "Waiting for TCP port ${toString cfg.httpPort} to be open..."
             sleep 1
         done
diff --git a/nixos/modules/services/networking/firewall-nftables.nix b/nixos/modules/services/networking/firewall-nftables.nix
index de336113843ef..a5ee7efc3c324 100644
--- a/nixos/modules/services/networking/firewall-nftables.nix
+++ b/nixos/modules/services/networking/firewall-nftables.nix
@@ -45,6 +45,18 @@ in
           This option only works with the nftables based firewall.
         '';
       };
+
+      extraReversePathFilterRules = mkOption {
+        type = types.lines;
+        default = "";
+        example = "fib daddr . mark . iif type local accept";
+        description = ''
+          Additional nftables rules to be appended to the rpfilter-allow
+          chain.
+
+          This option only works with the nftables based firewall.
+        '';
+      };
     };
 
   };
@@ -79,6 +91,8 @@ in
             meta nfproto ipv4 udp sport . udp dport { 67 . 68, 68 . 67 } accept comment "DHCPv4 client/server"
             fib saddr . mark ${optionalString (cfg.checkReversePath != "loose") ". iif"} oif exists accept
 
+            jump rpfilter-allow
+
             ${optionalString cfg.logReversePathDrops ''
               log level info prefix "rpfilter drop: "
             ''}
@@ -86,6 +100,10 @@ in
           }
         ''}
 
+        chain rpfilter-allow {
+          ${cfg.extraReversePathFilterRules}
+        }
+
         chain input {
           type filter hook input priority filter; policy drop;
 
diff --git a/nixos/modules/services/networking/inadyn.nix b/nixos/modules/services/networking/inadyn.nix
new file mode 100644
index 0000000000000..baa4302096c2c
--- /dev/null
+++ b/nixos/modules/services/networking/inadyn.nix
@@ -0,0 +1,250 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.inadyn;
+
+  # check if a value of an attrset is not null or an empty collection
+  nonEmptyValue = _: v: v != null && v != [ ] && v != { };
+
+  renderOption = k: v:
+    if builtins.elem k [ "provider" "custom" ] then
+      lib.concatStringsSep "\n"
+        (mapAttrsToList
+          (name: config: ''
+            ${k} ${name} {
+                ${lib.concatStringsSep "\n    " (mapAttrsToList renderOption (filterAttrs nonEmptyValue config))}
+            }'')
+          v)
+    else if k == "include" then
+      "${k}(\"${v}\")"
+    else if k == "hostname" && builtins.isList v then
+      "${k} = { ${builtins.concatStringsSep ", " (map (s: "\"${s}\"") v)} }"
+    else if builtins.isBool v then
+      "${k} = ${boolToString v}"
+    else if builtins.isString v then
+      "${k} = \"${v}\""
+    else
+      "${k} = ${toString v}";
+
+  configFile' = pkgs.writeText "inadyn.conf"
+    ''
+      # This file was generated by nix
+      # do not edit
+
+      ${(lib.concatStringsSep "\n" (mapAttrsToList renderOption (filterAttrs nonEmptyValue cfg.settings)))}
+    '';
+
+  configFile = if (cfg.configFile != null) then cfg.configFile else configFile';
+in
+{
+  options.services.inadyn = with types;
+    let
+      providerOptions =
+        {
+          include = mkOption {
+            default = null;
+            description = "File to include additional settings for this provider from.";
+            type = nullOr path;
+          };
+          ssl = mkOption {
+            default = true;
+            description = "Whether to use HTTPS for this DDNS provider.";
+            type = bool;
+          };
+          username = mkOption {
+            default = null;
+            description = "Username for this DDNS provider.";
+            type = nullOr str;
+          };
+          password = mkOption {
+            default = null;
+            description = ''
+              Password for this DDNS provider.
+
+              WARNING: This will be world-readable in the nix store.
+              To store credentials securely, use the `include` or `configFile` options.
+            '';
+            type = nullOr str;
+          };
+          hostname = mkOption {
+            default = "*";
+            example = "your.cool-domain.com";
+            description = "Hostname alias(es).";
+            type = either str (listOf str);
+          };
+        };
+    in
+    {
+      enable = mkEnableOption (''
+        synchronise your machine's IP address with a dynamic DNS provider using inadyn
+      '');
+      user = mkOption {
+        default = "inadyn";
+        type = types.str;
+        description = ''
+          User account under which inadyn runs.
+
+          ::: {.note}
+          If left as the default value this user will automatically be created
+          on system activation, otherwise you are responsible for
+          ensuring the user exists before the inadyn service starts.
+          :::
+        '';
+      };
+      group = mkOption {
+        default = "inadyn";
+        type = types.str;
+        description = ''
+          Group account under which inadyn runs.
+
+          ::: {.note}
+          If left as the default value this user will automatically be created
+          on system activation, otherwise you are responsible for
+          ensuring the user exists before the inadyn service starts.
+          :::
+        '';
+      };
+      interval = mkOption {
+        default = "*-*-* *:*:00";
+        description = ''
+          How often to check the current IP.
+          Uses the format described in {manpage}`systemd.time(7)`";
+        '';
+        type = str;
+      };
+      logLevel = lib.mkOption {
+        type = lib.types.enum [ "none" "err" "warning" "info" "notice" "debug" ];
+        default = "notice";
+        description = "Set inadyn's log level.";
+      };
+      settings = mkOption {
+        default = { };
+        description = "See `inadyn.conf (5)`";
+        type = submodule {
+          freeformType = attrs;
+          options = {
+            allow-ipv6 = mkOption {
+              default = config.networking.enableIPv6;
+              defaultText = "`config.networking.enableIPv6`";
+              description = "Whether to get IPv6 addresses from interfaces.";
+              type = bool;
+            };
+            forced-update = mkOption {
+              default = 2592000;
+              description = "Duration (in seconds) after which an update is forced.";
+              type = ints.positive;
+            };
+            provider = mkOption {
+              default = { };
+              description = ''
+                Settings for DDNS providers built-in to inadyn.
+
+                For a list of built-in providers, see `inadyn.conf (5)`.
+              '';
+              type = attrsOf (submodule {
+                freeformType = attrs;
+                options = providerOptions;
+              });
+            };
+            custom = mkOption {
+              default = { };
+              description = ''
+                Settings for custom DNS providers.
+              '';
+              type = attrsOf (submodule {
+                freeformType = attrs;
+                options = providerOptions // {
+                  ddns-server = mkOption {
+                    description = "DDNS server name.";
+                    type = str;
+                  };
+                  ddns-path = mkOption {
+                    description = ''
+                      DDNS server path.
+
+                      See `inadnyn.conf (5)` for a list for format specifiers that can be used.
+                    '';
+                    example = "/update?user=%u&password=%p&domain=%h&myip=%i";
+                    type = str;
+                  };
+                };
+              });
+            };
+          };
+        };
+      };
+      configFile = mkOption {
+        default = null;
+        description = ''
+          Configuration file for inadyn.
+
+          Setting this will override all other configuration options.
+
+          Passed to the inadyn service using LoadCredential.
+        '';
+        type = nullOr path;
+      };
+    };
+
+  config = lib.mkIf cfg.enable {
+    systemd = {
+      services.inadyn = {
+        description = "Update nameservers using inadyn";
+        documentation = [
+          "man:inadyn"
+          "man:inadyn.conf"
+          "file:${pkgs.inadyn}/share/doc/inadyn/README.md"
+        ];
+        requires = [ "network-online.target" ];
+        wantedBy = [ "multi-user.target" ];
+        startAt = cfg.interval;
+        serviceConfig = {
+          Type = "oneshot";
+          ExecStart = ''${lib.getExe pkgs.inadyn} -f ${configFile} --cache-dir ''${CACHE_DIRECTORY}/inadyn -1 --foreground -l ${cfg.logLevel}'';
+          LoadCredential = "config:${configFile}";
+          CacheDirectory = "inadyn";
+
+          User = cfg.user;
+          Group = cfg.group;
+          UMask = "0177";
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK";
+          NoNewPrivileges = true;
+          PrivateDevices = true;
+          PrivateTmp = true;
+          PrivateUsers = true;
+          ProtectSystem = "strict";
+          ProtectProc = "invisible";
+          ProtectHome = true;
+          ProtectClock = true;
+          ProtectControlGroups = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          RestrictNamespaces = true;
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          SystemCallArchitectures = "native";
+          SystemCallErrorNumber = "EPERM";
+          SystemCallFilter = "@system-service";
+          CapabilityBoundingSet = "";
+        };
+      };
+
+      timers.inadyn.timerConfig.Persistent = true;
+    };
+
+    users.users.inadyn = mkIf (cfg.user == "inadyn") {
+      group = cfg.group;
+      isSystemUser = true;
+    };
+
+    users.groups = mkIf (cfg.group == "inadyn") {
+      inadyn = { };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/jotta-cli.md b/nixos/modules/services/networking/jotta-cli.md
new file mode 100644
index 0000000000000..fee002a4e6046
--- /dev/null
+++ b/nixos/modules/services/networking/jotta-cli.md
@@ -0,0 +1,27 @@
+# Jottacloud Command-line Tool {#module-services-jotta-cli}
+
+The [Jottacloud Command-line Tool](https://docs.jottacloud.com/en/articles/1436834-jottacloud-command-line-tool) is a headless [Jottacloud](https://jottacloud.com) client.
+
+## Quick Start {#module-services-jotta-cli-quick-start}
+
+```nix
+{
+  user.services.jotta-cli.enable = true;
+}
+```
+
+This adds `jotta-cli` to `environment.systemPackages` and starts a user service that runs `jottad` with the default options.
+
+## Example Configuration {#module-services-jotta-cli-example-configuration}
+
+```nix
+user.services.jotta-cli = {
+  enable = true;
+  options = [ "slow" ];
+  package = pkgs.jotta-cli;
+};
+```
+
+This uses `jotta-cli` and `jottad` from the `pkgs.jotta-cli` package and starts `jottad` in low memory mode.
+
+`jottad` is also added to `environment.systemPackages`, so `jottad --help` can be used to explore options.
diff --git a/nixos/modules/services/networking/jotta-cli.nix b/nixos/modules/services/networking/jotta-cli.nix
new file mode 100644
index 0000000000000..c7e6dad5453ca
--- /dev/null
+++ b/nixos/modules/services/networking/jotta-cli.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.user.services.jotta-cli;
+in {
+  options = {
+    user.services.jotta-cli = {
+
+      enable = mkEnableOption "Jottacloud Command-line Tool";
+
+      options = mkOption {
+        default = [ "stdoutlog" "datadir" "%h/.jottad/" ];
+        example = [ ];
+        type = with types; listOf str;
+        description = "Command-line options passed to jottad.";
+      };
+
+      package = lib.mkPackageOption pkgs "jotta-cli" { };
+    };
+  };
+  config = mkIf cfg.enable {
+    systemd.user.services.jottad = {
+
+      description = "Jottacloud Command-line Tool daemon";
+
+      serviceConfig = {
+        Type = "notify";
+        EnvironmentFile = "-%h/.config/jotta-cli/jotta-cli.env";
+        ExecStart = "${lib.getExe' cfg.package "jottad"} ${concatStringsSep " " cfg.options}";
+        Restart = "on-failure";
+      };
+
+      wantedBy = [ "default.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "network-online.target" ];
+    };
+    environment.systemPackages = [ pkgs.jotta-cli ];
+  };
+
+  meta.maintainers = with lib.maintainers; [ evenbrenden ];
+  meta.doc = ./jotta-cli.md;
+}
diff --git a/nixos/modules/services/networking/knot.nix b/nixos/modules/services/networking/knot.nix
index 89d3ea5e9626a..145b4ad1dd3f1 100644
--- a/nixos/modules/services/networking/knot.nix
+++ b/nixos/modules/services/networking/knot.nix
@@ -226,7 +226,7 @@ in {
       };
 
       settings = mkOption {
-        type = types.submodule { freeformType = types.attrs; };
+        type = (pkgs.formats.yaml {}).type;
         default = {};
         description = ''
           Extra configuration as nix values.
diff --git a/nixos/modules/services/networking/netbird/coturn.nix b/nixos/modules/services/networking/netbird/coturn.nix
index dd032abb2d75e..746d70a07250d 100644
--- a/nixos/modules/services/networking/netbird/coturn.nix
+++ b/nixos/modules/services/networking/netbird/coturn.nix
@@ -148,10 +148,10 @@ in
         allowedUDPPorts = cfg.openPorts;
         allowedTCPPorts = cfg.openPorts;
 
-        allowedUDPPortRanges = [
+        allowedUDPPortRanges = with config.services.coturn; [
           {
-            from = cfg.minPort;
-            to = cfg.maxPort;
+            from = min-port;
+            to = max-port;
           }
         ];
       };
diff --git a/nixos/modules/services/networking/pixiecore.nix b/nixos/modules/services/networking/pixiecore.nix
index e61d32e136095..cfdb8014136ed 100644
--- a/nixos/modules/services/networking/pixiecore.nix
+++ b/nixos/modules/services/networking/pixiecore.nix
@@ -6,7 +6,7 @@ let
   cfg = config.services.pixiecore;
 in
 {
-  meta.maintainers = with maintainers; [ bbigras danderson ];
+  meta.maintainers = with maintainers; [ bbigras ];
 
   options = {
     services.pixiecore = {
diff --git a/nixos/modules/services/networking/pppd.nix b/nixos/modules/services/networking/pppd.nix
index d937456efddd4..8310b119b5f67 100644
--- a/nixos/modules/services/networking/pppd.nix
+++ b/nixos/modules/services/networking/pppd.nix
@@ -7,7 +7,7 @@ let
 in
 {
   meta = {
-    maintainers = with maintainers; [ danderson ];
+    maintainers = with maintainers; [ ];
   };
 
   options = {
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 5f2f6cb07af79..c62bccd462d33 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -346,6 +346,7 @@ in
                 violates the privacy of users and is not recommended.
               '';
             };
+            UsePAM = mkEnableOption "PAM authentication" // { default = true; };
             UseDns = mkOption {
               type = types.bool;
               # apply if cfg.useDns then "yes" else "no"
@@ -489,6 +490,8 @@ in
                 {manpage}`sshd_config(5)` for details.
               '';
             };
+            # Disabled by default, since pam_motd handles this.
+            PrintMotd = mkEnableOption "printing /etc/motd when a user logs in interactively";
           };
         });
       };
@@ -622,7 +625,7 @@ in
 
     networking.firewall.allowedTCPPorts = optionals cfg.openFirewall cfg.ports;
 
-    security.pam.services.sshd =
+    security.pam.services.sshd = lib.mkIf cfg.settings.UsePAM
       { startSession = true;
         showMotd = true;
         unixAuth = cfg.settings.PasswordAuthentication;
@@ -638,8 +641,6 @@ in
 
     services.openssh.extraConfig = mkOrder 0
       ''
-        UsePAM yes
-
         Banner ${if cfg.banner == null then "none" else pkgs.writeText "ssh_banner" cfg.banner}
 
         AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
@@ -657,7 +658,6 @@ in
         ${optionalString cfg.allowSFTP ''
           Subsystem sftp ${cfg.sftpServerExecutable} ${concatStringsSep " " cfg.sftpFlags}
         ''}
-        PrintMotd no # handled by pam_motd
         AuthorizedKeysFile ${toString cfg.authorizedKeysFiles}
         ${optionalString (cfg.authorizedKeysCommand != "none") ''
           AuthorizedKeysCommand ${cfg.authorizedKeysCommand}
diff --git a/nixos/modules/services/networking/sunshine.nix b/nixos/modules/services/networking/sunshine.nix
new file mode 100644
index 0000000000000..0749eaee95d8a
--- /dev/null
+++ b/nixos/modules/services/networking/sunshine.nix
@@ -0,0 +1,163 @@
+{ config, lib, pkgs, utils, ... }:
+let
+  inherit (lib) mkEnableOption mkPackageOption mkOption mkIf mkDefault types optionals getExe;
+  inherit (utils) escapeSystemdExecArgs;
+  cfg = config.services.sunshine;
+
+  # ports used are offset from a single base port, see https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/advanced_usage.html#port
+  generatePorts = port: offsets: map (offset: port + offset) offsets;
+  defaultPort = 47989;
+
+  appsFormat = pkgs.formats.json { };
+  settingsFormat = pkgs.formats.keyValue { };
+
+  appsFile = appsFormat.generate "apps.json" cfg.applications;
+  configFile = settingsFormat.generate "sunshine.conf" cfg.settings;
+in
+{
+  options.services.sunshine = with types; {
+    enable = mkEnableOption "Sunshine, a self-hosted game stream host for Moonlight";
+    package = mkPackageOption pkgs "sunshine" { };
+    openFirewall = mkOption {
+      type = bool;
+      default = false;
+      description = ''
+        Whether to automatically open ports in the firewall.
+      '';
+    };
+    capSysAdmin = mkOption {
+      type = bool;
+      default = false;
+      description = ''
+        Whether to give the Sunshine binary CAP_SYS_ADMIN, required for DRM/KMS screen capture.
+      '';
+    };
+    autoStart = mkOption {
+      type = bool;
+      default = true;
+      description = ''
+        Whether sunshine should be started automatically.
+      '';
+    };
+    settings = mkOption {
+      default = { };
+      description = ''
+        Settings to be rendered into the configuration file. If this is set, no configuration is possible from the web UI.
+
+        See https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/advanced_usage.html#configuration for syntax.
+      '';
+      example = ''
+        {
+          sunshine_name = "nixos";
+        }
+      '';
+      type = submodule (settings: {
+        freeformType = settingsFormat.type;
+        options.port = mkOption {
+          type = port;
+          default = defaultPort;
+          description = ''
+            Base port -- others used are offset from this one, see https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/advanced_usage.html#port for details.
+          '';
+        };
+      });
+    };
+    applications = mkOption {
+      default = { };
+      description = ''
+        Configuration for applications to be exposed to Moonlight. If this is set, no configuration is possible from the web UI, and must be by the `settings` option.
+      '';
+      example = ''
+        {
+          env = {
+            PATH = "$(PATH):$(HOME)/.local/bin";
+          };
+          apps = [
+            {
+              name = "1440p Desktop";
+              prep-cmd = [
+                {
+                  do = "''${pkgs.kdePackages.libkscreen}/bin/kscreen-doctor output.DP-4.mode.2560x1440@144";
+                  undo = "''${pkgs.kdePackages.libkscreen}/bin/kscreen-doctor output.DP-4.mode.3440x1440@144";
+                }
+              ];
+              exclude-global-prep-cmd = "false";
+              auto-detach = "true";
+            }
+          ];
+        }
+      '';
+      type = submodule {
+        options = {
+          env = mkOption {
+            default = { };
+            description = ''
+              Environment variables to be set for the applications.
+            '';
+            type = attrsOf str;
+          };
+          apps = mkOption {
+            default = [ ];
+            description = ''
+              Applications to be exposed to Moonlight.
+            '';
+            type = listOf attrs;
+          };
+        };
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.sunshine.settings.file_apps = mkIf (cfg.applications.apps != [ ]) "${appsFile}";
+
+    environment.systemPackages = [
+      cfg.package
+    ];
+
+    networking.firewall = mkIf cfg.openFirewall {
+      allowedTCPPorts = generatePorts cfg.settings.port [ (-5) 0 1 21 ];
+      allowedUDPPorts = generatePorts cfg.settings.port [ 9 10 11 13 21 ];
+    };
+
+    boot.kernelModules = [ "uinput" ];
+
+    services.udev.packages = [ cfg.package ];
+
+    services.avahi = {
+      enable = mkDefault true;
+      publish = {
+        enable = mkDefault true;
+        userServices = mkDefault true;
+      };
+    };
+
+    security.wrappers.sunshine = mkIf cfg.capSysAdmin {
+      owner = "root";
+      group = "root";
+      capabilities = "cap_sys_admin+p";
+      source = getExe cfg.package;
+    };
+
+    systemd.user.services.sunshine = {
+      description = "Self-hosted game stream host for Moonlight";
+
+      wantedBy = mkIf cfg.autoStart [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      wants = [ "graphical-session.target" ];
+      after = [ "graphical-session.target" ];
+
+      startLimitIntervalSec = 500;
+      startLimitBurst = 5;
+
+      serviceConfig = {
+        # only add configFile if an application or a setting other than the default port is set to allow configuration from web UI
+        ExecStart = escapeSystemdExecArgs ([
+          (if cfg.capSysAdmin then "${config.security.wrapperDir}/sunshine" else "${getExe cfg.package}")
+        ] ++ optionals (cfg.applications.apps != [ ] || (builtins.length (builtins.attrNames cfg.settings) > 1 || cfg.settings.port != defaultPort)) [ "${configFile}" ]);
+        Restart = "on-failure";
+        RestartSec = "5s";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/tailscale.nix b/nixos/modules/services/networking/tailscale.nix
index 2a77c0c7a23e7..a79e47d8491b8 100644
--- a/nixos/modules/services/networking/tailscale.nix
+++ b/nixos/modules/services/networking/tailscale.nix
@@ -6,7 +6,7 @@ let
   cfg = config.services.tailscale;
   isNetworkd = config.networking.useNetworkd;
 in {
-  meta.maintainers = with maintainers; [ danderson mbaillie twitchyliquid64 mfrw ];
+  meta.maintainers = with maintainers; [ mbaillie mfrw ];
 
   options.services.tailscale = {
     enable = mkEnableOption "Tailscale client daemon";
diff --git a/nixos/modules/services/networking/trust-dns.nix b/nixos/modules/services/networking/trust-dns.nix
index e6f8cc15819f6..039b7de263504 100644
--- a/nixos/modules/services/networking/trust-dns.nix
+++ b/nixos/modules/services/networking/trust-dns.nix
@@ -51,7 +51,7 @@ in
       package = mkPackageOption pkgs "trust-dns" {
         extraDescription = ''
           ::: {.note}
-          The package must provide `meta.mainProgram` which names the server binayr; any other utilities (client, resolver) are not needed.
+          The package must provide `meta.mainProgram` which names the server binary; any other utilities (client, resolver) are not needed.
           :::
         '';
       };
@@ -86,7 +86,7 @@ in
               type = types.listOf types.str;
               default = [ "0.0.0.0" ];
               description = ''
-              List of ipv4 addresses on which to listen for DNS queries.
+                List of ipv4 addresses on which to listen for DNS queries.
               '';
             };
             listen_addrs_ipv6 = mkOption {
@@ -114,7 +114,7 @@ in
             };
             zones = mkOption {
               description = "List of zones to serve.";
-              default = {};
+              default = [];
               type = types.listOf (types.coercedTo types.str (zone: { inherit zone; }) zoneType);
             };
           };
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index c9dd1d1b0f01f..435cd530c18d4 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -124,11 +124,20 @@ let
           fi
         ''}
 
+        # ensure wpa_supplicant.conf exists, or the daemon will fail to start
+        ${optionalString cfg.allowAuxiliaryImperativeNetworks ''
+          touch /etc/wpa_supplicant.conf
+        ''}
+
         # substitute environment variables
         if [ -f "${configFile}" ]; then
           ${pkgs.gawk}/bin/awk '{
-            for(varname in ENVIRON)
-              gsub("@"varname"@", ENVIRON[varname])
+            for(varname in ENVIRON) {
+              find = "@"varname"@"
+              repl = ENVIRON[varname]
+              if (i = index($0, find))
+                $0 = substr($0, 1, i-1) repl substr($0, i+length(find))
+            }
             print
           }' "${configFile}" > "${finalConfig}"
         else
diff --git a/nixos/modules/services/search/manticore.nix b/nixos/modules/services/search/manticore.nix
new file mode 100644
index 0000000000000..a8fcd9d0b3820
--- /dev/null
+++ b/nixos/modules/services/search/manticore.nix
@@ -0,0 +1,131 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.manticore;
+  format = pkgs.formats.json { };
+
+  toSphinx = {
+    mkKeyValue    ? mkKeyValueDefault {} "=",
+    listsAsDuplicateKeys ? true
+  }: attrsOfAttrs:
+    let
+        # map function to string for each key val
+        mapAttrsToStringsSep = sep: mapFn: attrs:
+          concatStringsSep sep
+            (mapAttrsToList mapFn attrs);
+        mkSection = sectName: sectValues: ''
+          ${sectName} {
+        '' + lib.generators.toKeyValue { inherit mkKeyValue listsAsDuplicateKeys; } sectValues + ''}'';
+    in
+      # map input to ini sections
+      mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
+
+  configFile = pkgs.writeText "manticore.conf" (
+    toSphinx {
+        mkKeyValue = k: v: "  ${k} = ${v}";
+    } cfg.settings
+  );
+
+in {
+
+  options = {
+    services.manticore = {
+
+      enable = mkEnableOption "Manticoresearch";
+
+      settings = mkOption {
+        default = {
+          searchd = {
+            listen = [
+              "127.0.0.1:9312"
+              "127.0.0.1:9306:mysql"
+              "127.0.0.1:9308:http"
+            ];
+            log = "/var/log/manticore/searchd.log";
+            query_log = "/var/log/manticore/query.log";
+            pid_file = "/run/manticore/searchd.pid";
+            data_dir = "/var/lib/manticore";
+          };
+        };
+        description = ''
+          Configuration for Manticoresearch. See
+          <https://manual.manticoresearch.com/Server%20settings>
+          for more information.
+        '';
+        type = types.submodule {
+          freeformType = format.type;
+        };
+        example = literalExpression ''
+          {
+            searchd = {
+                listen = [
+                  "127.0.0.1:9312"
+                  "127.0.0.1:9306:mysql"
+                  "127.0.0.1:9308:http"
+                ];
+                log = "/var/log/manticore/searchd.log";
+                query_log = "/var/log/manticore/query.log";
+                pid_file = "/run/manticore/searchd.pid";
+                data_dir = "/var/lib/manticore";
+            };
+          }
+        '';
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd = {
+      packages = [ pkgs.manticoresearch ];
+      services.manticore = {
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
+        serviceConfig = {
+          ExecStart = [
+            ""
+            "${pkgs.manticoresearch}/bin/searchd --config ${configFile}"
+          ];
+          ExecStop = [
+            ""
+            "${pkgs.manticoresearch}/bin/searchd --config ${configFile} --stopwait"
+          ];
+          ExecStartPre = [ "" ];
+          DynamicUser = true;
+          LogsDirectory = "manticore";
+          RuntimeDirectory = "manticore";
+          StateDirectory = "manticore";
+          ReadWritePaths = "";
+          CapabilityBoundingSet = "";
+          RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+          RestrictNamespaces = true;
+          PrivateDevices = true;
+          PrivateUsers = true;
+          ProtectClock = true;
+          ProtectControlGroups = true;
+          ProtectHome = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          SystemCallArchitectures = "native";
+          SystemCallFilter = [ "@system-service" "~@privileged" ];
+          RestrictRealtime = true;
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          UMask = "0066";
+          ProtectHostname = true;
+        } // lib.optionalAttrs (cfg.settings.searchd.pid_file != null) {
+          PIDFile = cfg.settings.searchd.pid_file;
+        };
+      };
+    };
+
+  };
+
+  meta.maintainers = with lib.maintainers; [ onny ];
+
+}
diff --git a/nixos/modules/services/security/oauth2-proxy-nginx.nix b/nixos/modules/services/security/oauth2-proxy-nginx.nix
new file mode 100644
index 0000000000000..c05bd304752d1
--- /dev/null
+++ b/nixos/modules/services/security/oauth2-proxy-nginx.nix
@@ -0,0 +1,130 @@
+{ config, lib, ... }:
+let
+  cfg = config.services.oauth2-proxy.nginx;
+in
+{
+  options.services.oauth2-proxy.nginx = {
+    proxy = lib.mkOption {
+      type = lib.types.str;
+      default = config.services.oauth2-proxy.httpAddress;
+      defaultText = lib.literalExpression "config.services.oauth2-proxy.httpAddress";
+      description = ''
+        The address of the reverse proxy endpoint for oauth2-proxy
+      '';
+    };
+
+    domain = lib.mkOption {
+      type = lib.types.str;
+      description = ''
+        The domain under which the oauth2-proxy will be accesible and the path of cookies are set to.
+        This setting must be set to ensure back-redirects are working properly
+        if oauth2-proxy is configured with {option}`services.oauth2-proxy.cookie.domain`
+        or multiple {option}`services.oauth2-proxy.nginx.virtualHosts` that are not on the same domain.
+      '';
+    };
+
+    virtualHosts = lib.mkOption {
+      type = let
+        vhostSubmodule = lib.types.submodule {
+          options = {
+            allowed_groups = lib.mkOption {
+              type = lib.types.nullOr (lib.types.listOf lib.types.str);
+              description = "List of groups to allow access to this vhost, or null to allow all.";
+              default = null;
+            };
+            allowed_emails = lib.mkOption {
+              type = lib.types.nullOr (lib.types.listOf lib.types.str);
+              description = "List of emails to allow access to this vhost, or null to allow all.";
+              default = null;
+            };
+            allowed_email_domains = lib.mkOption {
+              type = lib.types.nullOr (lib.types.listOf lib.types.str);
+              description = "List of email domains to allow access to this vhost, or null to allow all.";
+              default = null;
+            };
+          };
+        };
+        oldType = lib.types.listOf lib.types.str;
+        convertFunc = x:
+          lib.warn "services.oauth2-proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty {} x}"
+          lib.genAttrs x (_: {});
+        newType = lib.types.attrsOf vhostSubmodule;
+      in lib.types.coercedTo oldType convertFunc newType;
+      default = {};
+      example = {
+        "protected.foo.com" = {
+          allowed_groups = ["admins"];
+          allowed_emails = ["boss@foo.com"];
+        };
+      };
+      description = ''
+        Nginx virtual hosts to put behind the oauth2 proxy.
+        You can exclude specific locations by setting `auth_request off;` in the locations extraConfig setting.
+      '';
+    };
+  };
+
+  config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != [] && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
+    enable = true;
+  };
+
+  config.services.nginx = lib.mkIf (cfg.virtualHosts != [] && config.services.oauth2-proxy.enable) (lib.mkMerge ([
+    {
+      virtualHosts.${cfg.domain}.locations."/oauth2/" = {
+        proxyPass = cfg.proxy;
+        extraConfig = ''
+          proxy_set_header X-Scheme                $scheme;
+          proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
+        '';
+      };
+    }
+  ] ++ lib.optional (cfg.virtualHosts != []) {
+    recommendedProxySettings = true; # needed because duplicate headers
+  } ++ (lib.mapAttrsToList (vhost: conf: {
+    virtualHosts.${vhost} = {
+      locations = {
+        "/oauth2/auth" = let
+          maybeQueryArg = name: value:
+            if value == null then null
+            else "${name}=${lib.concatStringsSep "," (builtins.map lib.escapeURL value)}";
+          allArgs = lib.mapAttrsToList maybeQueryArg conf;
+          cleanArgs = builtins.filter (x: x != null) allArgs;
+          cleanArgsStr = lib.concatStringsSep "&" cleanArgs;
+        in {
+          # nginx doesn't support passing query string arguments to auth_request,
+          # so pass them here instead
+          proxyPass = "${cfg.proxy}/oauth2/auth?${cleanArgsStr}";
+          extraConfig = ''
+            auth_request off;
+            proxy_set_header X-Scheme         $scheme;
+            # nginx auth_request includes headers but not body
+            proxy_set_header Content-Length   "";
+            proxy_pass_request_body           off;
+          '';
+        };
+        "@redirectToAuth2ProxyLogin" = {
+          return = "307 https://${cfg.domain}/oauth2/start?rd=$scheme://$host$request_uri";
+          extraConfig = ''
+            auth_request off;
+          '';
+        };
+      };
+
+      extraConfig = ''
+        auth_request /oauth2/auth;
+        error_page 401 = @redirectToAuth2ProxyLogin;
+
+        # pass information via X-User and X-Email headers to backend,
+        # requires running with --set-xauthrequest flag
+        auth_request_set $user   $upstream_http_x_auth_request_user;
+        auth_request_set $email  $upstream_http_x_auth_request_email;
+        proxy_set_header X-User  $user;
+        proxy_set_header X-Email $email;
+
+        # if you enabled --cookie-refresh, this is needed for it to work with auth_request
+        auth_request_set $auth_cookie $upstream_http_set_cookie;
+        add_header Set-Cookie $auth_cookie;
+      '';
+    };
+  }) cfg.virtualHosts)));
+}
diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2-proxy.nix
index abf1ce9ba0200..075e64b743b1e 100644
--- a/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixos/modules/services/security/oauth2-proxy.nix
@@ -1,15 +1,12 @@
-# NixOS module for oauth2_proxy.
-
 { config, lib, pkgs, ... }:
 
-with lib;
 let
-  cfg = config.services.oauth2_proxy;
+  cfg = config.services.oauth2-proxy;
 
-  # oauth2_proxy provides many options that are only relevant if you are using
+  # oauth2-proxy provides many options that are only relevant if you are using
   # a certain provider. This set maps from provider name to a function that
   # takes the configuration and returns a string that can be inserted into the
-  # command-line to launch oauth2_proxy.
+  # command-line to launch oauth2-proxy.
   providerSpecificOptions = {
     azure = cfg: {
       azure-tenant = cfg.azure.tenant;
@@ -47,6 +44,7 @@ let
     reverse-proxy = reverseProxy;
     proxy-prefix = proxyPrefix;
     profile-url = profileURL;
+    oidc-issuer-url = oidcIssuerUrl;
     redeem-url = redeemURL;
     redirect-url = redirectURL;
     request-logging = requestLogging;
@@ -72,28 +70,28 @@ let
   } // (getProviderOptions cfg cfg.provider) // cfg.extraConfig;
 
   mapConfig = key: attr:
-  optionalString (attr != null && attr != []) (
-    if isDerivation attr then mapConfig key (toString attr) else
-    if (builtins.typeOf attr) == "set" then concatStringsSep " "
-      (mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
-    if (builtins.typeOf attr) == "list" then concatMapStringsSep " " (mapConfig key) attr else
-    if (builtins.typeOf attr) == "bool" then "--${key}=${boolToString attr}" else
+  lib.optionalString (attr != null && attr != []) (
+    if lib.isDerivation attr then mapConfig key (toString attr) else
+    if (builtins.typeOf attr) == "set" then lib.concatStringsSep " "
+      (lib.mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
+    if (builtins.typeOf attr) == "list" then lib.concatMapStringsSep " " (mapConfig key) attr else
+    if (builtins.typeOf attr) == "bool" then "--${key}=${lib.boolToString attr}" else
     if (builtins.typeOf attr) == "string" then "--${key}='${attr}'" else
     "--${key}=${toString attr}");
 
-  configString = concatStringsSep " " (mapAttrsToList mapConfig allConfig);
+  configString = lib.concatStringsSep " " (lib.mapAttrsToList mapConfig allConfig);
 in
 {
-  options.services.oauth2_proxy = {
-    enable = mkEnableOption "oauth2_proxy";
+  options.services.oauth2-proxy = {
+    enable = lib.mkEnableOption "oauth2-proxy";
 
-    package = mkPackageOption pkgs "oauth2-proxy" { };
+    package = lib.mkPackageOption pkgs "oauth2-proxy" { };
 
     ##############################################
     # PROVIDER configuration
     # Taken from: https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/providers.go
-    provider = mkOption {
-      type = types.enum [
+    provider = lib.mkOption {
+      type = lib.types.enum [
         "adfs"
         "azure"
         "bitbucket"
@@ -115,31 +113,40 @@ in
       '';
     };
 
-    approvalPrompt = mkOption {
-      type = types.enum ["force" "auto"];
+    approvalPrompt = lib.mkOption {
+      type = lib.types.enum ["force" "auto"];
       default = "force";
       description = ''
         OAuth approval_prompt.
       '';
     };
 
-    clientID = mkOption {
-      type = types.nullOr types.str;
+    clientID = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       description = ''
         The OAuth Client ID.
       '';
       example = "123456.apps.googleusercontent.com";
     };
 
-    clientSecret = mkOption {
-      type = types.nullOr types.str;
+    oidcIssuerUrl = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
+      default = null;
+      description = ''
+        The OAuth issuer URL.
+      '';
+      example = "https://login.microsoftonline.com/{TENANT_ID}/v2.0";
+    };
+
+    clientSecret = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       description = ''
         The OAuth Client Secret.
       '';
     };
 
-    skipAuthRegexes = mkOption {
-     type = types.listOf types.str;
+    skipAuthRegexes = lib.mkOption {
+     type = lib.types.listOf lib.types.str;
      default = [];
      description = ''
        Skip authentication for requests matching any of these regular
@@ -149,8 +156,8 @@ in
 
     # XXX: Not clear whether these two options are mutually exclusive or not.
     email = {
-      domains = mkOption {
-        type = types.listOf types.str;
+      domains = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [];
         description = ''
           Authenticate emails with the specified domains. Use
@@ -158,8 +165,8 @@ in
         '';
       };
 
-      addresses = mkOption {
-        type = types.nullOr types.lines;
+      addresses = lib.mkOption {
+        type = lib.types.nullOr lib.types.lines;
         default = null;
         description = ''
           Line-separated email addresses that are allowed to authenticate.
@@ -167,8 +174,8 @@ in
       };
     };
 
-    loginURL = mkOption {
-      type = types.nullOr types.str;
+    loginURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Authentication endpoint.
@@ -180,8 +187,8 @@ in
       example = "https://provider.example.com/oauth/authorize";
     };
 
-    redeemURL = mkOption {
-      type = types.nullOr types.str;
+    redeemURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Token redemption endpoint.
@@ -193,8 +200,8 @@ in
       example = "https://provider.example.com/oauth/token";
     };
 
-    validateURL = mkOption {
-      type = types.nullOr types.str;
+    validateURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Access token validation endpoint.
@@ -206,10 +213,10 @@ in
       example = "https://provider.example.com/user/emails";
     };
 
-    redirectURL = mkOption {
+    redirectURL = lib.mkOption {
       # XXX: jml suspects this is always necessary, but the command-line
       # doesn't require it so making it optional.
-      type = types.nullOr types.str;
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         The OAuth2 redirect URL.
@@ -218,16 +225,16 @@ in
     };
 
     azure = {
-      tenant = mkOption {
-        type = types.str;
+      tenant = lib.mkOption {
+        type = lib.types.str;
         default = "common";
         description = ''
           Go to a tenant-specific or common (tenant-independent) endpoint.
         '';
       };
 
-      resource = mkOption {
-        type = types.str;
+      resource = lib.mkOption {
+        type = lib.types.str;
         description = ''
           The resource that is protected.
         '';
@@ -235,8 +242,8 @@ in
     };
 
     google = {
-      adminEmail = mkOption {
-        type = types.str;
+      adminEmail = lib.mkOption {
+        type = lib.types.str;
         description = ''
           The Google Admin to impersonate for API calls.
 
@@ -248,16 +255,16 @@ in
         '';
       };
 
-      groups = mkOption {
-        type = types.listOf types.str;
+      groups = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [];
         description = ''
           Restrict logins to members of these Google groups.
         '';
       };
 
-      serviceAccountJSON = mkOption {
-        type = types.path;
+      serviceAccountJSON = lib.mkOption {
+        type = lib.types.path;
         description = ''
           The path to the service account JSON credentials.
         '';
@@ -265,16 +272,16 @@ in
     };
 
     github = {
-      org = mkOption {
-        type = types.nullOr types.str;
+      org = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Restrict logins to members of this organisation.
         '';
       };
 
-      team = mkOption {
-        type = types.nullOr types.str;
+      team = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Restrict logins to members of this team.
@@ -285,8 +292,8 @@ in
 
     ####################################################
     # UPSTREAM Configuration
-    upstream = mkOption {
-      type = with types; coercedTo str (x: [x]) (listOf str);
+    upstream = lib.mkOption {
+      type = with lib.types; coercedTo str (x: [x]) (listOf str);
       default = [];
       description = ''
         The http url(s) of the upstream endpoint or `file://`
@@ -294,40 +301,40 @@ in
       '';
     };
 
-    passAccessToken = mkOption {
-      type = types.bool;
+    passAccessToken = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Pass OAuth access_token to upstream via X-Forwarded-Access-Token header.
       '';
     };
 
-    passBasicAuth = mkOption {
-      type = types.bool;
+    passBasicAuth = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream.
       '';
     };
 
-    basicAuthPassword = mkOption {
-      type = types.nullOr types.str;
+    basicAuthPassword = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         The password to set when passing the HTTP Basic Auth header.
       '';
     };
 
-    passHostHeader = mkOption {
-      type = types.bool;
+    passHostHeader = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Pass the request Host Header to upstream.
       '';
     };
 
-    signatureKey = mkOption {
-      type = types.nullOr types.str;
+    signatureKey = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         GAP-Signature request signature key.
@@ -336,8 +343,8 @@ in
     };
 
     cookie = {
-      domain = mkOption {
-        type = types.nullOr types.str;
+      domain = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Optional cookie domains to force cookies to (ie: `.yourcompany.com`).
@@ -347,33 +354,33 @@ in
         example = ".yourcompany.com";
       };
 
-      expire = mkOption {
-        type = types.str;
+      expire = lib.mkOption {
+        type = lib.types.str;
         default = "168h0m0s";
         description = ''
           Expire timeframe for cookie.
         '';
       };
 
-      httpOnly = mkOption {
-        type = types.bool;
+      httpOnly = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Set HttpOnly cookie flag.
         '';
       };
 
-      name = mkOption {
-        type = types.str;
+      name = lib.mkOption {
+        type = lib.types.str;
         default = "_oauth2_proxy";
         description = ''
           The name of the cookie that the oauth_proxy creates.
         '';
       };
 
-      refresh = mkOption {
+      refresh = lib.mkOption {
         # XXX: Unclear what the behavior is when this is not specified.
-        type = types.nullOr types.str;
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Refresh the cookie after this duration; 0 to disable.
@@ -381,15 +388,15 @@ in
         example = "168h0m0s";
       };
 
-      secret = mkOption {
-        type = types.nullOr types.str;
+      secret = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         description = ''
           The seed string for secure cookies.
         '';
       };
 
-      secure = mkOption {
-        type = types.bool;
+      secure = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Set secure (HTTPS) cookie flag.
@@ -400,8 +407,8 @@ in
     ####################################################
     # OAUTH2 PROXY configuration
 
-    httpAddress = mkOption {
-      type = types.str;
+    httpAddress = lib.mkOption {
+      type = lib.types.str;
       default = "http://127.0.0.1:4180";
       description = ''
         HTTPS listening address.  This module does not expose the port by
@@ -411,8 +418,8 @@ in
     };
 
     htpasswd = {
-      file = mkOption {
-        type = types.nullOr types.path;
+      file = lib.mkOption {
+        type = lib.types.nullOr lib.types.path;
         default = null;
         description = ''
           Additionally authenticate against a htpasswd file. Entries must be
@@ -420,8 +427,8 @@ in
         '';
       };
 
-      displayForm = mkOption {
-        type = types.bool;
+      displayForm = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Display username / password login form if an htpasswd file is provided.
@@ -429,16 +436,16 @@ in
       };
     };
 
-    customTemplatesDir = mkOption {
-      type = types.nullOr types.path;
+    customTemplatesDir = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
       default = null;
       description = ''
         Path to custom HTML templates.
       '';
     };
 
-    reverseProxy = mkOption {
-      type = types.bool;
+    reverseProxy = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         In case when running behind a reverse proxy, controls whether headers
@@ -448,8 +455,8 @@ in
       '';
     };
 
-    proxyPrefix = mkOption {
-      type = types.str;
+    proxyPrefix = lib.mkOption {
+      type = lib.types.str;
       default = "/oauth2";
       description = ''
         The url root path that this proxy should be nested under.
@@ -457,30 +464,30 @@ in
     };
 
     tls = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to serve over TLS.
         '';
       };
 
-      certificate = mkOption {
-        type = types.path;
+      certificate = lib.mkOption {
+        type = lib.types.path;
         description = ''
           Path to certificate file.
         '';
       };
 
-      key = mkOption {
-        type = types.path;
+      key = lib.mkOption {
+        type = lib.types.path;
         description = ''
           Path to private key file.
         '';
       };
 
-      httpsAddress = mkOption {
-        type = types.str;
+      httpsAddress = lib.mkOption {
+        type = lib.types.str;
         default = ":443";
         description = ''
           `addr:port` to listen on for HTTPS clients.
@@ -492,8 +499,8 @@ in
       };
     };
 
-    requestLogging = mkOption {
-      type = types.bool;
+    requestLogging = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Log requests to stdout.
@@ -504,42 +511,42 @@ in
     # UNKNOWN
 
     # XXX: Is this mandatory? Is it part of another group? Is it part of the provider specification?
-    scope = mkOption {
+    scope = lib.mkOption {
       # XXX: jml suspects this is always necessary, but the command-line
       # doesn't require it so making it optional.
-      type = types.nullOr types.str;
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         OAuth scope specification.
       '';
     };
 
-    profileURL = mkOption {
-      type = types.nullOr types.str;
+    profileURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Profile access endpoint.
       '';
     };
 
-    setXauthrequest = mkOption {
-      type = types.nullOr types.bool;
+    setXauthrequest = lib.mkOption {
+      type = lib.types.nullOr lib.types.bool;
       default = false;
       description = ''
         Set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode). Setting this to 'null' means using the upstream default (false).
       '';
     };
 
-    extraConfig = mkOption {
+    extraConfig = lib.mkOption {
       default = {};
-      type = types.attrsOf types.anything;
+      type = lib.types.attrsOf lib.types.anything;
       description = ''
         Extra config to pass to oauth2-proxy.
       '';
     };
 
-    keyFile = mkOption {
-      type = types.nullOr types.path;
+    keyFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
       default = null;
       description = ''
         oauth2-proxy allows passing sensitive configuration via environment variables.
@@ -547,28 +554,30 @@ in
         OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
         and specify the path here.
       '';
-      example = "/run/keys/oauth2_proxy";
+      example = "/run/keys/oauth2-proxy";
     };
-
   };
 
-  config = mkIf cfg.enable {
+  imports = [
+    (lib.mkRenamedOptionModule [ "services" "oauth2_proxy" ] [ "services" "oauth2-proxy" ])
+  ];
 
-    services.oauth2_proxy = mkIf (cfg.keyFile != null) {
-      clientID = mkDefault null;
-      clientSecret = mkDefault null;
-      cookie.secret = mkDefault null;
+  config = lib.mkIf cfg.enable {
+    services.oauth2-proxy = lib.mkIf (cfg.keyFile != null) {
+      clientID = lib.mkDefault null;
+      clientSecret = lib.mkDefault null;
+      cookie.secret = lib.mkDefault null;
     };
 
-    users.users.oauth2_proxy = {
+    users.users.oauth2-proxy = {
       description = "OAuth2 Proxy";
       isSystemUser = true;
-      group = "oauth2_proxy";
+      group = "oauth2-proxy";
     };
 
-    users.groups.oauth2_proxy = {};
+    users.groups.oauth2-proxy = {};
 
-    systemd.services.oauth2_proxy = {
+    systemd.services.oauth2-proxy = {
       description = "OAuth2 Proxy";
       path = [ cfg.package ];
       wantedBy = [ "multi-user.target" ];
@@ -576,10 +585,10 @@ in
       after = [ "network-online.target" ];
 
       serviceConfig = {
-        User = "oauth2_proxy";
+        User = "oauth2-proxy";
         Restart = "always";
         ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
-        EnvironmentFile = mkIf (cfg.keyFile != null) cfg.keyFile;
+        EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
       };
     };
 
diff --git a/nixos/modules/services/security/oauth2_proxy_nginx.nix b/nixos/modules/services/security/oauth2_proxy_nginx.nix
deleted file mode 100644
index 87ea61276837c..0000000000000
--- a/nixos/modules/services/security/oauth2_proxy_nginx.nix
+++ /dev/null
@@ -1,91 +0,0 @@
-{ config, lib, ... }:
-with lib;
-let
-  cfg = config.services.oauth2_proxy.nginx;
-in
-{
-  options.services.oauth2_proxy.nginx = {
-    proxy = mkOption {
-      type = types.str;
-      default = config.services.oauth2_proxy.httpAddress;
-      defaultText = literalExpression "config.services.oauth2_proxy.httpAddress";
-      description = ''
-        The address of the reverse proxy endpoint for oauth2_proxy
-      '';
-    };
-
-    domain = mkOption {
-      type = types.str;
-      description = ''
-        The domain under which the oauth2_proxy will be accesible and the path of cookies are set to.
-        This setting must be set to ensure back-redirects are working properly
-        if oauth2-proxy is configured with {option}`services.oauth2_proxy.cookie.domain`
-        or multiple {option}`services.oauth2_proxy.nginx.virtualHosts` that are not on the same domain.
-      '';
-    };
-
-    virtualHosts = mkOption {
-      type = types.listOf types.str;
-      default = [];
-      description = ''
-        A list of nginx virtual hosts to put behind the oauth2 proxy.
-        You can exclude specific locations by setting `auth_request off;` in the locations extraConfig setting.
-      '';
-    };
-  };
-
-  config.services.oauth2_proxy = mkIf (cfg.virtualHosts != [] && (hasPrefix "127.0.0.1:" cfg.proxy)) {
-    enable = true;
-  };
-
-  config.services.nginx = mkIf (cfg.virtualHosts != [] && config.services.oauth2_proxy.enable) (mkMerge ([
-    {
-      virtualHosts.${cfg.domain}.locations."/oauth2/" = {
-        proxyPass = cfg.proxy;
-        extraConfig = ''
-          proxy_set_header X-Scheme                $scheme;
-          proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
-        '';
-      };
-    }
-  ] ++ optional (cfg.virtualHosts != []) {
-    recommendedProxySettings = true; # needed because duplicate headers
-  } ++ (map (vhost: {
-    virtualHosts.${vhost} = {
-      locations = {
-        "/oauth2/auth" = {
-          proxyPass = cfg.proxy;
-          extraConfig = ''
-            auth_request off;
-            proxy_set_header X-Scheme         $scheme;
-            # nginx auth_request includes headers but not body
-            proxy_set_header Content-Length   "";
-            proxy_pass_request_body           off;
-          '';
-        };
-        "@redirectToAuth2ProxyLogin" = {
-          return = "307 https://${cfg.domain}/oauth2/start?rd=$scheme://$host$request_uri";
-          extraConfig = ''
-            auth_request off;
-          '';
-        };
-      };
-
-      extraConfig = ''
-        auth_request /oauth2/auth;
-        error_page 401 = @redirectToAuth2ProxyLogin;
-
-        # pass information via X-User and X-Email headers to backend,
-        # requires running with --set-xauthrequest flag
-        auth_request_set $user   $upstream_http_x_auth_request_user;
-        auth_request_set $email  $upstream_http_x_auth_request_email;
-        proxy_set_header X-User  $user;
-        proxy_set_header X-Email $email;
-
-        # if you enabled --cookie-refresh, this is needed for it to work with auth_request
-        auth_request_set $auth_cookie $upstream_http_set_cookie;
-        add_header Set-Cookie $auth_cookie;
-      '';
-    };
-  }) cfg.virtualHosts)));
-}
diff --git a/nixos/modules/services/security/vault.nix b/nixos/modules/services/security/vault.nix
index ab86da47b2e1c..650f9bda99c33 100644
--- a/nixos/modules/services/security/vault.nix
+++ b/nixos/modules/services/security/vault.nix
@@ -56,8 +56,8 @@ in
       };
 
       devRootTokenID = mkOption {
-        type = types.str;
-        default = false;
+        type = types.nullOr types.str;
+        default = null;
         description = ''
           Initial root token. This only applies when {option}`services.vault.dev` is true
         '';
diff --git a/nixos/modules/services/security/vaultwarden/default.nix b/nixos/modules/services/security/vaultwarden/default.nix
index b2920931f9a9e..33957be437b30 100644
--- a/nixos/modules/services/security/vaultwarden/default.nix
+++ b/nixos/modules/services/security/vaultwarden/default.nix
@@ -131,21 +131,13 @@ in {
         Additional environment file as defined in {manpage}`systemd.exec(5)`.
 
         Secrets like {env}`ADMIN_TOKEN` and {env}`SMTP_PASSWORD`
-        may be passed to the service without adding them to the world-readable Nix store.
+        should be passed to the service without adding them to the world-readable Nix store.
 
-        Note that this file needs to be available on the host on which
-        `vaultwarden` is running.
+        Note that this file needs to be available on the host on which `vaultwarden` is running.
 
-        As a concrete example, to make the Admin UI available
-        (from which new users can be invited initially),
+        As a concrete example, to make the Admin UI available (from which new users can be invited initially),
         the secret {env}`ADMIN_TOKEN` needs to be defined as described
-        [here](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page).
-        Setting `environmentFile` to `/var/lib/vaultwarden.env`
-        and ensuring permissions with e.g.
-        `chown vaultwarden:vaultwarden /var/lib/vaultwarden.env`
-        (the `vaultwarden` user will only exist after activating with
-        `enable = true;` before this), we can set the contents of the file to have
-        contents such as:
+        [here](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page):
 
         ```
         # Admin secret token, see
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index a9fc88e320c6b..8dba0aca64337 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -39,7 +39,7 @@ in
 
       implementation = mkOption {
         type = types.enum [ "dbus" "broker" ];
-        default = "broker";
+        default = "dbus";
         description = ''
           The implementation to use for the message bus defined by the D-Bus specification.
           Can be either the classic dbus daemon or dbus-broker, which aims to provide high
diff --git a/nixos/modules/services/system/earlyoom.nix b/nixos/modules/services/system/earlyoom.nix
index bcdf7d6512d5a..7e012dee02cbf 100644
--- a/nixos/modules/services/system/earlyoom.nix
+++ b/nixos/modules/services/system/earlyoom.nix
@@ -4,15 +4,29 @@ let
   cfg = config.services.earlyoom;
 
   inherit (lib)
-    mkDefault mkEnableOption mkIf mkOption types
-    mkRemovedOptionModule literalExpression
-    escapeShellArg concatStringsSep optional optionalString;
-
+    concatStringsSep
+    escapeShellArg
+    literalExpression
+    mkDefault
+    mkEnableOption
+    mkIf
+    mkOption
+    mkPackageOption
+    mkRemovedOptionModule
+    optionalString
+    optionals
+    types;
 in
 {
+  meta = {
+    maintainers = with lib.maintainers; [ AndersonTorres ];
+  };
+
   options.services.earlyoom = {
     enable = mkEnableOption "early out of memory killing";
 
+    package = mkPackageOption pkgs "earlyoom" { };
+
     freeMemThreshold = mkOption {
       type = types.ints.between 1 100;
       default = 10;
@@ -138,22 +152,21 @@ in
     systemd.services.earlyoom = {
       description = "Early OOM Daemon for Linux";
       wantedBy = [ "multi-user.target" ];
-      path = optional cfg.enableNotifications pkgs.dbus;
+      path = optionals cfg.enableNotifications [ pkgs.dbus ];
       serviceConfig = {
         StandardError = "journal";
         ExecStart = concatStringsSep " " ([
-          "${pkgs.earlyoom}/bin/earlyoom"
+          "${lib.getExe cfg.package}"
           ("-m ${toString cfg.freeMemThreshold}"
-            + optionalString (cfg.freeMemKillThreshold != null) ",${toString cfg.freeMemKillThreshold}")
+           + optionalString (cfg.freeMemKillThreshold != null) ",${toString cfg.freeMemKillThreshold}")
           ("-s ${toString cfg.freeSwapThreshold}"
-            + optionalString (cfg.freeSwapKillThreshold != null) ",${toString cfg.freeSwapKillThreshold}")
+           + optionalString (cfg.freeSwapKillThreshold != null) ",${toString cfg.freeSwapKillThreshold}")
           "-r ${toString cfg.reportInterval}"
         ]
-        ++ optional cfg.enableDebugInfo "-d"
-        ++ optional cfg.enableNotifications "-n"
-        ++ optional (cfg.killHook != null) "-N ${escapeShellArg cfg.killHook}"
-        ++ cfg.extraArgs
-        );
+        ++ optionals cfg.enableDebugInfo [ "-d" ]
+        ++ optionals cfg.enableNotifications [ "-n" ]
+        ++ optionals (cfg.killHook != null) [ "-N ${escapeShellArg cfg.killHook}" ]
+        ++ cfg.extraArgs);
       };
     };
   };
diff --git a/nixos/modules/services/web-apps/akkoma.nix b/nixos/modules/services/web-apps/akkoma.nix
index eca498549df36..7c9bf6c465164 100644
--- a/nixos/modules/services/web-apps/akkoma.nix
+++ b/nixos/modules/services/web-apps/akkoma.nix
@@ -817,11 +817,11 @@ in {
                 base_url = mkOption {
                     type = types.nullOr types.nonEmptyStr;
                     default = if lib.versionOlder config.system.stateVersion "24.05"
-                              then "${httpConf.scheme}://${httpConf.host}:${builtins.toString httpConf.port}/media/"
+                              then "${httpConf.scheme}://${httpConf.host}:${builtins.toString httpConf.port}"
                               else null;
                     defaultText = literalExpression ''
                       if lib.versionOlder config.system.stateVersion "24.05"
-                      then "$\{httpConf.scheme}://$\{httpConf.host}:$\{builtins.toString httpConf.port}/media/"
+                      then "$\{httpConf.scheme}://$\{httpConf.host}:$\{builtins.toString httpConf.port}"
                       else null;
                     '';
                     description = ''
@@ -957,7 +957,7 @@ in {
     assertions = optionals (cfg.config.":pleroma".":media_proxy".enabled && cfg.config.":pleroma".":media_proxy".base_url == null) [''
       `services.akkoma.config.":pleroma".":media_proxy".base_url` must be set when the media proxy is enabled.
     ''];
-    warnings = optionals (with config.security; (!sudo.enable) && (!sudo-rs.enable)) [''
+    warnings = optionals (with config.security; cfg.installWrapper && (!sudo.enable) && (!sudo-rs.enable)) [''
       The pleroma_ctl wrapper enabled by the installWrapper option relies on
       sudo, which appears to have been disabled through security.sudo.enable.
     ''];
diff --git a/nixos/modules/services/web-apps/castopod.nix b/nixos/modules/services/web-apps/castopod.nix
index 69ee670276a76..d3750c3dd3938 100644
--- a/nixos/modules/services/web-apps/castopod.nix
+++ b/nixos/modules/services/web-apps/castopod.nix
@@ -17,7 +17,7 @@ let
 in
 {
   meta.doc = ./castopod.md;
-  meta.maintainers = with lib.maintainers; [ alexoundos misuzu ];
+  meta.maintainers = with lib.maintainers; [ alexoundos ];
 
   options.services = {
     castopod = {
diff --git a/nixos/modules/services/web-apps/coder.nix b/nixos/modules/services/web-apps/coder.nix
index 318a7c8fc1357..5450adbe118da 100644
--- a/nixos/modules/services/web-apps/coder.nix
+++ b/nixos/modules/services/web-apps/coder.nix
@@ -169,7 +169,7 @@ in {
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      environment = config.environment.extra // {
+      environment = cfg.environment.extra // {
         CODER_ACCESS_URL = cfg.accessUrl;
         CODER_WILDCARD_ACCESS_URL = cfg.wildcardAccessUrl;
         CODER_PG_CONNECTION_URL = "user=${cfg.database.username} ${optionalString (cfg.database.password != null) "password=${cfg.database.password}"} database=${cfg.database.database} host=${cfg.database.host} ${optionalString (cfg.database.sslmode != null) "sslmode=${cfg.database.sslmode}"}";
@@ -223,4 +223,5 @@ in {
       };
     };
   };
+  meta.maintainers = pkgs.coder.meta.maintainers;
 }
diff --git a/nixos/modules/services/web-apps/gotosocial.nix b/nixos/modules/services/web-apps/gotosocial.nix
index 8e0e1ad765212..aee1edf66a6a7 100644
--- a/nixos/modules/services/web-apps/gotosocial.nix
+++ b/nixos/modules/services/web-apps/gotosocial.nix
@@ -27,7 +27,7 @@ let
 in
 {
   meta.doc = ./gotosocial.md;
-  meta.maintainers = with lib.maintainers; [ misuzu blakesmith ];
+  meta.maintainers = with lib.maintainers; [ blakesmith ];
 
   options.services.gotosocial = {
     enable = lib.mkEnableOption "ActivityPub social network server";
diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix
index 0d0361584c3a0..cdd60f572b990 100644
--- a/nixos/modules/services/web-apps/limesurvey.nix
+++ b/nixos/modules/services/web-apps/limesurvey.nix
@@ -2,7 +2,7 @@
 
 let
 
-  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption;
+  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption mkPackageOption;
   inherit (lib) literalExpression mapAttrs optional optionalString types;
 
   cfg = config.services.limesurvey;
@@ -12,8 +12,6 @@ let
   group = config.services.httpd.group;
   stateDir = "/var/lib/limesurvey";
 
-  pkg = pkgs.limesurvey;
-
   configType = with types; oneOf [ (attrsOf configType) str int bool ] // {
     description = "limesurvey config type (str, int, bool or attribute set thereof)";
   };
@@ -34,6 +32,8 @@ in
   options.services.limesurvey = {
     enable = mkEnableOption "Limesurvey web application";
 
+    package = mkPackageOption pkgs "limesurvey" { };
+
     encryptionKey = mkOption {
       type = types.str;
       default = "E17687FC77CEE247F0E22BB3ECF27FDE8BEC310A892347EC13013ABA11AA7EB5";
@@ -240,7 +240,7 @@ in
       adminAddr = mkDefault cfg.virtualHost.adminAddr;
       extraModules = [ "proxy_fcgi" ];
       virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost {
-        documentRoot = mkForce "${pkg}/share/limesurvey";
+        documentRoot = mkForce "${cfg.package}/share/limesurvey";
         extraConfig = ''
           Alias "/tmp" "${stateDir}/tmp"
           <Directory "${stateDir}">
@@ -256,7 +256,7 @@ in
             Options -Indexes
           </Directory>
 
-          <Directory "${pkg}/share/limesurvey">
+          <Directory "${cfg.package}/share/limesurvey">
             <FilesMatch "\.php$">
               <If "-f %{REQUEST_FILENAME}">
                 SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/"
@@ -277,7 +277,7 @@ in
       "d ${stateDir}/tmp/assets 0750 ${user} ${group} - -"
       "d ${stateDir}/tmp/runtime 0750 ${user} ${group} - -"
       "d ${stateDir}/tmp/upload 0750 ${user} ${group} - -"
-      "C ${stateDir}/upload 0750 ${user} ${group} - ${pkg}/share/limesurvey/upload"
+      "C ${stateDir}/upload 0750 ${user} ${group} - ${cfg.package}/share/limesurvey/upload"
     ];
 
     systemd.services.limesurvey-init = {
@@ -288,8 +288,8 @@ in
       environment.LIMESURVEY_CONFIG = limesurveyConfig;
       script = ''
         # update or install the database as required
-        ${pkgs.php81}/bin/php ${pkg}/share/limesurvey/application/commands/console.php updatedb || \
-        ${pkgs.php81}/bin/php ${pkg}/share/limesurvey/application/commands/console.php install admin password admin admin@example.com verbose
+        ${pkgs.php81}/bin/php ${cfg.package}/share/limesurvey/application/commands/console.php updatedb || \
+        ${pkgs.php81}/bin/php ${cfg.package}/share/limesurvey/application/commands/console.php install admin password admin admin@example.com verbose
       '';
       serviceConfig = {
         User = user;
diff --git a/nixos/modules/services/web-apps/mediawiki.nix b/nixos/modules/services/web-apps/mediawiki.nix
index 7246fd93a2314..b11626ec2dc3b 100644
--- a/nixos/modules/services/web-apps/mediawiki.nix
+++ b/nixos/modules/services/web-apps/mediawiki.nix
@@ -246,7 +246,9 @@ in
 
       passwordFile = mkOption {
         type = types.path;
-        description = "A file containing the initial password for the admin user.";
+        description = ''
+          A file containing the initial password for the administrator account "admin".
+        '';
         example = "/run/keys/mediawiki-password";
       };
 
diff --git a/nixos/modules/services/web-apps/movim.nix b/nixos/modules/services/web-apps/movim.nix
index bb88a185b4618..29bed0e067fa4 100644
--- a/nixos/modules/services/web-apps/movim.nix
+++ b/nixos/modules/services/web-apps/movim.nix
@@ -103,22 +103,20 @@ let
           lib.concatStringsSep "\n" [
             (lib.optionalString brotli.enable ''
               echo -n "Precompressing static files with Brotli …"
-              find ${appDir}/public -type f ${findTextFileNames} \
-                | ${lib.getExe pkgs.parallel} ${lib.escapeShellArgs [
-                    "--will-cite"
-                    "-j $NIX_BUILD_CORES"
-                    "${lib.getExe brotli.package} --keep --quality=${builtins.toString brotli.compressionLevel} --output={}.br {}"
-                   ]}
+              find ${appDir}/public -type f ${findTextFileNames} -print0 \
+                | xargs -0 -n 1 -P $NIX_BUILD_CORES ${pkgs.writeShellScript "movim_precompress_broti" ''
+                    file="$1"
+                    ${lib.getExe brotli.package} --keep --quality=${builtins.toString brotli.compressionLevel} --output=$file.br $file
+                  ''}
               echo " done."
             '')
             (lib.optionalString gzip.enable ''
               echo -n "Precompressing static files with Gzip …"
-              find ${appDir}/public -type f ${findTextFileNames} \
-                | ${lib.getExe pkgs.parallel} ${lib.escapeShellArgs [
-                    "--will-cite"
-                    "-j $NIX_BUILD_CORES"
-                    "${lib.getExe gzip.package} -c -${builtins.toString gzip.compressionLevel} {} > {}.gz"
-                   ]}
+              find ${appDir}/public -type f ${findTextFileNames} -print0 \
+                | xargs -0 -n 1 -P $NIX_BUILD_CORES ${pkgs.writeShellScript "movim_precompress_broti" ''
+                    file="$1"
+                    ${lib.getExe gzip.package} -c -${builtins.toString gzip.compressionLevel} $file > $file.gz
+                  ''}
               echo " done."
             '')
           ];
diff --git a/nixos/modules/services/web-apps/nextcloud.md b/nixos/modules/services/web-apps/nextcloud.md
index 06a8712b0b8ae..ec860d307b381 100644
--- a/nixos/modules/services/web-apps/nextcloud.md
+++ b/nixos/modules/services/web-apps/nextcloud.md
@@ -5,7 +5,7 @@ self-hostable cloud platform. The server setup can be automated using
 [services.nextcloud](#opt-services.nextcloud.enable). A
 desktop client is packaged at `pkgs.nextcloud-client`.
 
-The current default by NixOS is `nextcloud28` which is also the latest
+The current default by NixOS is `nextcloud29` which is also the latest
 major version available.
 
 ## Basic usage {#module-services-nextcloud-basic-usage}
@@ -184,6 +184,32 @@ Alternatively, extra apps can also be declared with the [](#opt-services.nextclo
 When using this setting, apps can no longer be managed statefully because this can lead to Nextcloud updating apps
 that are managed by Nix. If you want automatic updates it is recommended that you use web interface to install apps.
 
+## Known warnings {#module-services-nextcloud-known-warnings}
+
+### Failed to get an iterator for log entries: Logreader application only supports "file" log_type {#module-services-nextcloud-warning-logreader}
+
+This is because
+
+* our module writes logs into the journal (`journalctl -t Nextcloud`)
+* the Logreader application that allows reading logs in the admin panel is enabled
+  by default and requires logs written to a file.
+
+The logreader application doesn't work, as it was the case before. The only change is that
+it complains loudly now. So nothing actionable here by default. Alternatively you can
+
+* disable the logreader application to shut up the "error".
+
+  We can't really do that by default since whether apps are enabled/disabled is part
+  of the application's state and tracked inside the database.
+
+* set [](#opt-services.nextcloud.settings.log_type) to "file" to be able to view logs
+  from the admin panel.
+
+### Your web server is not properly set up to resolve `.well-known` URLs, failed on: `/.well-known/caldav` {#module-services-nextcloud-warning-wellknown-caldav}
+
+This warning appearing seems to be an upstream issue and is being sorted out
+in [nextcloud/server#45033](https://github.com/nextcloud/server/issues/45033).
+
 ## Maintainer information {#module-services-nextcloud-maintainer-info}
 
 As stated in the previous paragraph, we must provide a clean upgrade-path for Nextcloud
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index f179a9854eb91..21f76938f20c5 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -819,7 +819,8 @@ in {
         ++ (optional (versionOlder cfg.package.version "25") (upgradeWarning 24 "22.11"))
         ++ (optional (versionOlder cfg.package.version "26") (upgradeWarning 25 "23.05"))
         ++ (optional (versionOlder cfg.package.version "27") (upgradeWarning 26 "23.11"))
-        ++ (optional (versionOlder cfg.package.version "28") (upgradeWarning 27 "24.05"));
+        ++ (optional (versionOlder cfg.package.version "28") (upgradeWarning 27 "24.05"))
+        ++ (optional (versionOlder cfg.package.version "29") (upgradeWarning 28 "24.11"));
 
       services.nextcloud.package = with pkgs;
         mkDefault (
@@ -832,10 +833,12 @@ in {
           else if versionOlder stateVersion "23.05" then nextcloud25
           else if versionOlder stateVersion "23.11" then nextcloud26
           else if versionOlder stateVersion "24.05" then nextcloud27
-          else nextcloud28
+          else nextcloud29
         );
 
-      services.nextcloud.phpPackage = pkgs.php82;
+      services.nextcloud.phpPackage =
+        if versionOlder cfg.package.version "29" then pkgs.php82
+        else pkgs.php83;
 
       services.nextcloud.phpOptions = mkMerge [
         (mapAttrs (const mkOptionDefault) defaultPHPSettings)
diff --git a/nixos/modules/services/web-apps/pretalx.nix b/nixos/modules/services/web-apps/pretalx.nix
index e80eedf9f8590..b062a8b7eeeac 100644
--- a/nixos/modules/services/web-apps/pretalx.nix
+++ b/nixos/modules/services/web-apps/pretalx.nix
@@ -286,16 +286,16 @@ in
         virtualHosts.${cfg.nginx.domain} = {
           # https://docs.pretalx.org/administrator/installation.html#step-7-ssl
           extraConfig = ''
-            more_set_headers Referrer-Policy same-origin;
-            more_set_headers X-Content-Type-Options nosniff;
+            more_set_headers "Referrer-Policy: same-origin";
+            more_set_headers "X-Content-Type-Options: nosniff";
           '';
           locations = {
             "/".proxyPass = "http://pretalx";
             "/media/" = {
-              alias = "${cfg.settings.filesystem.data}/data/media/";
+              alias = "${cfg.settings.filesystem.data}/media/";
               extraConfig = ''
                 access_log off;
-                more_set_headers Content-Disposition 'attachment; filename="$1"';
+                more_set_headers 'Content-Disposition: attachment; filename="$1"';
                 expires 7d;
               '';
             };
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 40470f535bf61..08fab09e1e559 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -352,7 +352,8 @@ let
 
         # The acme-challenge location doesn't need to be added if we are not using any automated
         # certificate provisioning and can also be omitted when we use a certificate obtained via a DNS-01 challenge
-        acmeLocation = optionalString (vhost.enableACME || (vhost.useACMEHost != null && config.security.acme.certs.${vhost.useACMEHost}.dnsProvider == null))
+        acmeName = if vhost.useACMEHost != null then vhost.useACMEHost else vhostName;
+        acmeLocation = optionalString ((vhost.enableACME || vhost.useACMEHost != null) && config.security.acme.certs.${acmeName}.dnsProvider == null)
           # Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx)
           # We use ^~ here, so that we don't check any regexes (which could
           # otherwise easily override this intended match accidentally).
@@ -829,7 +830,7 @@ in
       sslCiphers = mkOption {
         type = types.nullOr types.str;
         # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
-        default = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
+        default = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305";
         description = "Ciphers to choose from when negotiating TLS handshakes.";
       };
 
diff --git a/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixos/modules/services/x11/desktop-managers/budgie.nix
index 75ee82f1f948a..b4e7390293351 100644
--- a/nixos/modules/services/x11/desktop-managers/budgie.nix
+++ b/nixos/modules/services/x11/desktop-managers/budgie.nix
@@ -214,7 +214,7 @@ in {
 
     services.geoclue2.enable = mkDefault true; # for BCC's Privacy > Location Services panel.
     services.upower.enable = config.powerManagement.enable; # for Budgie's Status Indicator and BCC's Power panel.
-    services.xserver.libinput.enable = mkDefault true; # for BCC's Mouse panel.
+    services.libinput.enable = mkDefault true; # for BCC's Mouse panel.
     services.colord.enable = mkDefault true; # for BCC's Color panel.
     services.gnome.at-spi2-core.enable = mkDefault true; # for BCC's A11y panel.
     services.accounts-daemon.enable = mkDefault true; # for BCC's Users panel.
diff --git a/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixos/modules/services/x11/desktop-managers/cinnamon.nix
index 8c29b41c8cf80..482527d1e8ad5 100644
--- a/nixos/modules/services/x11/desktop-managers/cinnamon.nix
+++ b/nixos/modules/services/x11/desktop-managers/cinnamon.nix
@@ -116,7 +116,7 @@ in
       services.touchegg.enable = mkDefault true;
       services.udisks2.enable = true;
       services.upower.enable = mkDefault config.powerManagement.enable;
-      services.xserver.libinput.enable = mkDefault true;
+      services.libinput.enable = mkDefault true;
       services.xserver.updateDbusEnvironment = true;
       networking.networkmanager.enable = mkDefault true;
 
diff --git a/nixos/modules/services/x11/desktop-managers/deepin.nix b/nixos/modules/services/x11/desktop-managers/deepin.nix
index 680ce7b9a93e6..30bd14adb4192 100644
--- a/nixos/modules/services/x11/desktop-managers/deepin.nix
+++ b/nixos/modules/services/x11/desktop-managers/deepin.nix
@@ -61,7 +61,7 @@ in
       services.gnome.gnome-keyring.enable = mkDefault true;
       services.bamf.enable = mkDefault true;
 
-      services.xserver.libinput.enable = mkDefault true;
+      services.libinput.enable = mkDefault true;
       services.udisks2.enable = true;
       services.upower.enable = mkDefault config.powerManagement.enable;
       networking.networkmanager.enable = mkDefault true;
diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
index 09f90e1cd4df8..0a341ba133d39 100644
--- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix
+++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
@@ -96,7 +96,7 @@ in
 
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
-    services.xserver.libinput.enable = mkDefault true;
+    services.libinput.enable = mkDefault true;
 
     services.dbus.packages = [ e.efl ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixos/modules/services/x11/desktop-managers/gnome.nix
index 95c79cf96108c..a0cf56e7a920d 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome.nix
@@ -339,7 +339,7 @@ in
       # services.packagekit.enable = mkDefault true;
       services.udisks2.enable = true;
       services.upower.enable = config.powerManagement.enable;
-      services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
+      services.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
 
       # Explicitly enabled since GNOME will be severely broken without these.
       xdg.mime.enable = true;
diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix
index 1937bdcbd3e73..ac86c385bcc8d 100644
--- a/nixos/modules/services/x11/desktop-managers/lxqt.nix
+++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix
@@ -69,7 +69,7 @@ in
 
     services.upower.enable = config.powerManagement.enable;
 
-    services.xserver.libinput.enable = mkDefault true;
+    services.libinput.enable = mkDefault true;
 
     xdg.portal.lxqt.enable = mkDefault true;
 
diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix
index 520d40d67908c..beae07b70dbfe 100644
--- a/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -88,7 +88,7 @@ in
       services.udev.packages = [ pkgs.mate.mate-settings-daemon ];
       services.gvfs.enable = true;
       services.upower.enable = config.powerManagement.enable;
-      services.xserver.libinput.enable = mkDefault true;
+      services.libinput.enable = mkDefault true;
 
       security.pam.services.mate-screensaver.unixAuth = true;
 
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 57ccbaccb0c68..008bc65eb6a4f 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -159,7 +159,7 @@ in
       services.gsignond.plugins = with pkgs.gsignondPlugins; [ lastfm mail oauth ];
       services.udisks2.enable = true;
       services.upower.enable = config.powerManagement.enable;
-      services.xserver.libinput.enable = mkDefault true;
+      services.libinput.enable = mkDefault true;
       services.xserver.updateDbusEnvironment = true;
       services.zeitgeist.enable = mkDefault true;
       services.geoclue2.enable = mkDefault true;
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 56fcd70dc9516..7d80b9b2641c3 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -348,7 +348,7 @@ in
       services.system-config-printer.enable = mkIf config.services.printing.enable (mkDefault true);
       services.udisks2.enable = true;
       services.upower.enable = config.powerManagement.enable;
-      services.xserver.libinput.enable = mkDefault true;
+      services.libinput.enable = mkDefault true;
 
       # Extra UDEV rules used by Solid
       services.udev.packages = [
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index c55d0021b6a7c..85d0d199de3f2 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -164,7 +164,7 @@ in
     services.gvfs.enable = true;
     services.tumbler.enable = true;
     services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
-    services.xserver.libinput.enable = mkDefault true; # used in xfce4-settings-manager
+    services.libinput.enable = mkDefault true; # used in xfce4-settings-manager
 
     # Enable default programs
     programs.dconf.enable = true;
diff --git a/nixos/modules/services/x11/hardware/cmt.nix b/nixos/modules/services/x11/hardware/cmt.nix
index 55d3d840ee092..53906c5c716f4 100644
--- a/nixos/modules/services/x11/hardware/cmt.nix
+++ b/nixos/modules/services/x11/hardware/cmt.nix
@@ -46,10 +46,10 @@ in {
 
     assertions = [
       {
-        assertion = !config.services.xserver.libinput.enable;
+        assertion = !config.services.libinput.enable;
         message = ''
           cmt and libinput are incompatible, meaning you cannot enable them both.
-          To use cmt you need to disable libinput with `services.xserver.libinput.enable = false`
+          To use cmt you need to disable libinput with `services.libinput.enable = false`
           If you haven't enabled it in configuration.nix, it's enabled by default on a
           different xserver module.
         '';
diff --git a/nixos/modules/services/x11/hardware/synaptics.nix b/nixos/modules/services/x11/hardware/synaptics.nix
index 4dfa917d8fb4a..c43fdac6b1ec6 100644
--- a/nixos/modules/services/x11/hardware/synaptics.nix
+++ b/nixos/modules/services/x11/hardware/synaptics.nix
@@ -30,7 +30,7 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = "Whether to enable touchpad support. Deprecated: Consider services.xserver.libinput.enable.";
+        description = "Whether to enable touchpad support. Deprecated: Consider services.libinput.enable.";
       };
 
       dev = mkOption {
@@ -207,8 +207,8 @@ in {
 
     assertions = [
       {
-        assertion = !config.services.xserver.libinput.enable;
-        message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver).";
+        assertion = !config.services.libinput.enable;
+        message = "Synaptics and libinput are incompatible, you cannot enable both.";
       }
     ];