about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules')
-rw-r--r--nixpkgs/nixos/modules/config/ldso.nix6
-rw-r--r--nixpkgs/nixos/modules/config/no-x-libs.nix1
-rw-r--r--nixpkgs/nixos/modules/config/users-groups.nix22
-rw-r--r--nixpkgs/nixos/modules/config/vte.nix4
-rw-r--r--nixpkgs/nixos/modules/config/xdg/portal.nix28
-rw-r--r--nixpkgs/nixos/modules/module-list.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/chromium.nix2
-rw-r--r--nixpkgs/nixos/modules/programs/quark-goldleaf.nix18
-rw-r--r--nixpkgs/nixos/modules/programs/yazi.nix4
-rw-r--r--nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix3
-rw-r--r--nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix3
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix2
-rw-r--r--nixpkgs/nixos/modules/services/databases/mysql.nix15
-rw-r--r--nixpkgs/nixos/modules/services/databases/pgbouncer.nix19
-rw-r--r--nixpkgs/nixos/modules/services/display-managers/greetd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/games/teeworlds.nix310
-rw-r--r--nixpkgs/nixos/modules/services/hardware/asusd.nix10
-rw-r--r--nixpkgs/nixos/modules/services/hardware/bolt.nix19
-rw-r--r--nixpkgs/nixos/modules/services/hardware/brltty.nix1
-rw-r--r--nixpkgs/nixos/modules/services/hardware/undervolt.nix9
-rw-r--r--nixpkgs/nixos/modules/services/mail/stalwart-mail.nix13
-rw-r--r--nixpkgs/nixos/modules/services/misc/sourcehut/default.nix22
-rw-r--r--nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix13
-rw-r--r--nixpkgs/nixos/modules/services/networking/go-camo.nix73
-rw-r--r--nixpkgs/nixos/modules/services/networking/hostapd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/knot.nix109
-rw-r--r--nixpkgs/nixos/modules/services/networking/libreswan.nix7
-rw-r--r--nixpkgs/nixos/modules/services/security/opensnitch.nix102
-rw-r--r--nixpkgs/nixos/modules/services/system/automatic-timezoned.nix2
-rw-r--r--nixpkgs/nixos/modules/services/torrent/transmission.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mastodon.nix46
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/photoprism.nix19
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/garage.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/ttyd.nix92
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix10
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel.nix7
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix5
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd/oomd.nix6
-rw-r--r--nixpkgs/nixos/modules/system/etc/build-composefs-dump.py3
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker.nix14
-rw-r--r--nixpkgs/nixos/modules/virtualisation/incus.nix12
42 files changed, 818 insertions, 225 deletions
diff --git a/nixpkgs/nixos/modules/config/ldso.nix b/nixpkgs/nixos/modules/config/ldso.nix
index 72ae3958d886..bd6f0dc5a83b 100644
--- a/nixpkgs/nixos/modules/config/ldso.nix
+++ b/nixpkgs/nixos/modules/config/ldso.nix
@@ -6,9 +6,9 @@ let
   libDir = pkgs.stdenv.hostPlatform.libDir;
   ldsoBasename = builtins.unsafeDiscardStringContext (last (splitString "/" pkgs.stdenv.cc.bintools.dynamicLinker));
 
-  pkgs32 = pkgs.pkgsi686Linux;
-  libDir32 = pkgs32.stdenv.hostPlatform.libDir;
-  ldsoBasename32 = builtins.unsafeDiscardStringContext (last (splitString "/" pkgs32.stdenv.cc.bintools.dynamicLinker));
+  # Hard-code to avoid creating another instance of nixpkgs. Also avoids eval errors in some cases.
+  libDir32 = "lib"; # pkgs.pkgsi686Linux.stdenv.hostPlatform.libDir
+  ldsoBasename32 = "ld-linux.so.2"; # last (splitString "/" pkgs.pkgsi686Linux.stdenv.cc.bintools.dynamicLinker)
 in {
   options = {
     environment.ldso = mkOption {
diff --git a/nixpkgs/nixos/modules/config/no-x-libs.nix b/nixpkgs/nixos/modules/config/no-x-libs.nix
index 2f763290e32d..32b17f6059ef 100644
--- a/nixpkgs/nixos/modules/config/no-x-libs.nix
+++ b/nixpkgs/nixos/modules/config/no-x-libs.nix
@@ -83,6 +83,7 @@ with lib;
       # translateManpages -> perlPackages.po4a -> texlive-combined-basic -> texlive-core-big -> libX11
       util-linux = super.util-linux.override { translateManpages = false; };
       vim-full = super.vim-full.override { guiSupport = false; };
+      vte = super.vte.override { gtkVersion = null; };
       zbar = super.zbar.override { enableVideo = false; withXorg = false; };
     }));
   };
diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix
index 967ad0846d75..dd34771c0b42 100644
--- a/nixpkgs/nixos/modules/config/users-groups.nix
+++ b/nixpkgs/nixos/modules/config/users-groups.nix
@@ -649,7 +649,6 @@ in {
         home = "/root";
         shell = mkDefault cfg.defaultUserShell;
         group = "root";
-        initialHashedPassword = mkDefault "!";
       };
       nobody = {
         uid = ids.uids.nobody;
@@ -897,7 +896,26 @@ in {
     ));
 
     warnings =
-      builtins.filter (x: x != null) (
+      flip concatMap (attrValues cfg.users) (user: let
+        unambiguousPasswordConfiguration = 1 >= length (filter (x: x != null) ([
+          user.hashedPassword
+          user.hashedPasswordFile
+          user.password
+        ] ++ optionals cfg.mutableUsers [
+          # For immutable users, initialHashedPassword is set to hashedPassword,
+          # so using these options would always trigger the assertion.
+          user.initialHashedPassword
+          user.initialPassword
+        ]));
+      in optional (!unambiguousPasswordConfiguration) ''
+        The user '${user.name}' has multiple of the options
+        `hashedPassword`, `password`, `hashedPasswordFile`, `initialPassword`
+        & `initialHashedPassword` set to a non-null value.
+        The options silently discard others by the order of precedence
+        given above which can lead to surprising results. To resolve this warning,
+        set at most one of the options above to a non-`null` value.
+      '')
+      ++ builtins.filter (x: x != null) (
         flip mapAttrsToList cfg.users (_: user:
         # This regex matches a subset of the Modular Crypto Format (MCF)[1]
         # informal standard. Since this depends largely on the OS or the
diff --git a/nixpkgs/nixos/modules/config/vte.nix b/nixpkgs/nixos/modules/config/vte.nix
index a969607f6e0b..48f85246560a 100644
--- a/nixpkgs/nixos/modules/config/vte.nix
+++ b/nixpkgs/nixos/modules/config/vte.nix
@@ -1,5 +1,3 @@
-# VTE
-
 { config, pkgs, lib, ... }:
 
 with lib;
@@ -9,7 +7,7 @@ let
   vteInitSnippet = ''
     # Show current working directory in VTE terminals window title.
     # Supports both bash and zsh, requires interactive shell.
-    . ${pkgs.vte}/etc/profile.d/vte.sh
+    . ${pkgs.vte.override { gtkVersion = null; }}/etc/profile.d/vte.sh
   '';
 
 in
diff --git a/nixpkgs/nixos/modules/config/xdg/portal.nix b/nixpkgs/nixos/modules/config/xdg/portal.nix
index 07d4fa76c2e8..5aa23377f9ff 100644
--- a/nixpkgs/nixos/modules/config/xdg/portal.nix
+++ b/nixpkgs/nixos/modules/config/xdg/portal.nix
@@ -119,19 +119,6 @@ in
     let
       cfg = config.xdg.portal;
       packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
-      configPackages = cfg.configPackages;
-
-      joinedPortals = pkgs.buildEnv {
-        name = "xdg-portals";
-        paths = packages;
-        pathsToLink = [ "/share/xdg-desktop-portal/portals" "/share/applications" ];
-      };
-
-      joinedPortalConfigs = pkgs.buildEnv {
-        name = "xdg-portal-configs";
-        paths = configPackages;
-        pathsToLink = [ "/share/xdg-desktop-portal" ];
-      };
     in
     mkIf cfg.enable {
       warnings = lib.optional (cfg.configPackages == [ ] && cfg.config == { }) ''
@@ -158,17 +145,18 @@ in
       systemd.packages = packages;
 
       environment = {
-        # fixes screen sharing on plasmawayland on non-chromium apps by linking
-        # share/applications/*.desktop files
-        # see https://github.com/NixOS/nixpkgs/issues/145174
-        systemPackages = [ joinedPortals ];
-        pathsToLink = [ "/share/applications" ];
+        systemPackages = packages ++ cfg.configPackages;
+        pathsToLink = [
+          # Portal definitions and upstream desktop environment portal configurations.
+          "/share/xdg-desktop-portal"
+          # .desktop files to register fallback icon and app name.
+          "/share/applications"
+        ];
 
         sessionVariables = {
           GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
           NIXOS_XDG_OPEN_USE_PORTAL = mkIf cfg.xdgOpenUsePortal "1";
-          XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals";
-          NIXOS_XDG_DESKTOP_PORTAL_CONFIG_DIR = mkIf (cfg.configPackages != [ ]) "${joinedPortalConfigs}/share/xdg-desktop-portal";
+          NIX_XDG_DESKTOP_PORTAL_DIR = "/run/current-system/sw/share/xdg-desktop-portal/portals";
         };
 
         etc = lib.concatMapAttrs
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index e81754414ea4..a64efec046a4 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -241,6 +241,7 @@
   ./programs/proxychains.nix
   ./programs/qdmr.nix
   ./programs/qt5ct.nix
+  ./programs/quark-goldleaf.nix
   ./programs/regreet.nix
   ./programs/rog-control-center.nix
   ./programs/rust-motd.nix
@@ -963,6 +964,7 @@
   ./services/networking/gns3-server.nix
   ./services/networking/gnunet.nix
   ./services/networking/go-autoconfig.nix
+  ./services/networking/go-camo.nix
   ./services/networking/go-neb.nix
   ./services/networking/go-shadowsocks2.nix
   ./services/networking/gobgpd.nix
diff --git a/nixpkgs/nixos/modules/programs/chromium.nix b/nixpkgs/nixos/modules/programs/chromium.nix
index 287d93c82cad..45a9e9e2a689 100644
--- a/nixpkgs/nixos/modules/programs/chromium.nix
+++ b/nixpkgs/nixos/modules/programs/chromium.nix
@@ -23,7 +23,7 @@ in
 
       enablePlasmaBrowserIntegration = mkEnableOption (lib.mdDoc "Native Messaging Host for Plasma Browser Integration");
 
-      plasmaBrowserIntegrationPackage = mkPackageOption pkgs "plasma5Packages.plasma-browser-integration" { };
+      plasmaBrowserIntegrationPackage = mkPackageOption pkgs [ "plasma5Packages" "plasma-browser-integration" ] { };
 
       extensions = mkOption {
         type = with types; nullOr (listOf str);
diff --git a/nixpkgs/nixos/modules/programs/quark-goldleaf.nix b/nixpkgs/nixos/modules/programs/quark-goldleaf.nix
new file mode 100644
index 000000000000..71aadc8c594e
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/quark-goldleaf.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+let
+  cfg = config.programs.quark-goldleaf;
+in
+{
+  options = {
+    programs.quark-goldleaf = {
+      enable = lib.mkEnableOption "quark-goldleaf with udev rules applied";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.quark-goldleaf ];
+    services.udev.packages = [ pkgs.quark-goldleaf ];
+  };
+
+  meta.maintainers = pkgs.quark-goldleaf.meta.maintainers;
+}
diff --git a/nixpkgs/nixos/modules/programs/yazi.nix b/nixpkgs/nixos/modules/programs/yazi.nix
index 273a7eeed05f..338eddb60d80 100644
--- a/nixpkgs/nixos/modules/programs/yazi.nix
+++ b/nixpkgs/nixos/modules/programs/yazi.nix
@@ -22,7 +22,7 @@ in
             description = lib.mdDoc ''
               Configuration included in `${name}.toml`.
 
-              See https://github.com/sxyazi/yazi/blob/v${cfg.package.version}/config/docs/${name}.md for documentation.
+              See https://yazi-rs.github.io/docs/configuration/${name}/ for documentation.
             '';
           }))
           names);
@@ -47,7 +47,5 @@ in
   };
   meta = {
     maintainers = with lib.maintainers; [ linsui ];
-    # The version of the package is used in the doc.
-    buildDocsInSandbox = false;
   };
 }
diff --git a/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix b/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix
index 3fb916c76971..a920b6cb1268 100644
--- a/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixpkgs/nixos/modules/services/cluster/kubernetes/default.nix
@@ -285,7 +285,7 @@ in {
       systemd.tmpfiles.rules = [
         "d /opt/cni/bin 0755 root root -"
         "d /run/kubernetes 0755 kubernetes kubernetes -"
-        "d /var/lib/kubernetes 0755 kubernetes kubernetes -"
+        "d ${cfg.dataDir} 0755 kubernetes kubernetes -"
       ];
 
       users.users.kubernetes = {
@@ -294,6 +294,7 @@ in {
         group = "kubernetes";
         home = cfg.dataDir;
         createHome = true;
+        homeMode = "755";
       };
       users.groups.kubernetes.gid = config.ids.gids.kubernetes;
 
diff --git a/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix b/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix
index 9a01238c2391..a4b5cb8eda86 100644
--- a/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix
+++ b/nixpkgs/nixos/modules/services/cluster/kubernetes/pki.nix
@@ -192,7 +192,8 @@ in
         mkdir -p "$(dirname "${certmgrAPITokenPath}")"
         if [ -f "${cfsslAPITokenPath}" ]; then
           ln -fs "${cfsslAPITokenPath}" "${certmgrAPITokenPath}"
-        else
+        elif [ ! -f "${certmgrAPITokenPath}" ]; then
+          # Don't remove the token if it already exists
           install -m 600 /dev/null "${certmgrAPITokenPath}"
         fi
       ''
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix b/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix
index 54bbe69703f9..b1d44e67658b 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/hydra/default.nix
@@ -39,7 +39,7 @@ let
 
   hydra-package =
   let
-    makeWrapperArgs = concatStringsSep " " (mapAttrsToList (key: value: "--set \"${key}\" \"${value}\"") hydraEnv);
+    makeWrapperArgs = concatStringsSep " " (mapAttrsToList (key: value: "--set-default \"${key}\" \"${value}\"") hydraEnv);
   in pkgs.buildEnv rec {
     name = "hydra-env";
     nativeBuildInputs = [ pkgs.makeWrapper ];
diff --git a/nixpkgs/nixos/modules/services/databases/mysql.nix b/nixpkgs/nixos/modules/services/databases/mysql.nix
index 128bb0862175..a6d71cca88de 100644
--- a/nixpkgs/nixos/modules/services/databases/mysql.nix
+++ b/nixpkgs/nixos/modules/services/databases/mysql.nix
@@ -7,6 +7,9 @@ let
   cfg = config.services.mysql;
 
   isMariaDB = lib.getName cfg.package == lib.getName pkgs.mariadb;
+  isOracle = lib.getName cfg.package == lib.getName pkgs.mysql80;
+  # Oracle MySQL has supported "notify" service type since 8.0
+  hasNotify = isMariaDB || (isOracle && versionAtLeast cfg.package.version "8.0");
 
   mysqldOptions =
     "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}";
@@ -377,19 +380,11 @@ in
         # The super user account to use on *first* run of MySQL server
         superUser = if isMariaDB then cfg.user else "root";
       in ''
-        ${optionalString (!isMariaDB) ''
+        ${optionalString (!hasNotify) ''
           # Wait until the MySQL server is available for use
-          count=0
           while [ ! -e /run/mysqld/mysqld.sock ]
           do
-              if [ $count -eq 30 ]
-              then
-                  echo "Tried 30 times, giving up..."
-                  exit 1
-              fi
-
               echo "MySQL daemon not yet started. Waiting for 1 second..."
-              count=$((count++))
               sleep 1
           done
         ''}
@@ -477,7 +472,7 @@ in
 
       serviceConfig = mkMerge [
         {
-          Type = if isMariaDB then "notify" else "simple";
+          Type = if hasNotify then "notify" else "simple";
           Restart = "on-abort";
           RestartSec = "5s";
 
diff --git a/nixpkgs/nixos/modules/services/databases/pgbouncer.nix b/nixpkgs/nixos/modules/services/databases/pgbouncer.nix
index 65b287e84442..157d49c13161 100644
--- a/nixpkgs/nixos/modules/services/databases/pgbouncer.nix
+++ b/nixpkgs/nixos/modules/services/databases/pgbouncer.nix
@@ -66,9 +66,6 @@ let
       ${optionalString (cfg.adminUsers != null) "admin_users = ${cfg.adminUsers}"}
       ${optionalString (cfg.statsUsers != null) "stats_users = ${cfg.statsUsers}"}
 
-      # linux
-      pidfile = /run/pgbouncer/pgbouncer.pid
-
       # extra
       ${cfg.extraConfig}
     '';
@@ -96,10 +93,9 @@ in {
 
     logFile = mkOption {
       type = types.nullOr types.str;
-      default = "pgbouncer.log";
+      default = null;
       description = lib.mdDoc ''
-        Specifies the log file.
-        Either this or syslog has to be specified.
+        Specifies a log file in addition to journald.
       '';
     };
 
@@ -601,22 +597,21 @@ in {
 
     systemd.services.pgbouncer = {
       description = "PgBouncer - PostgreSQL connection pooler";
-      wants    = [ "postgresql.service" ];
-      after    = [ "postgresql.service" ];
+      wants    = [ "network-online.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service";
+      after    = [ "network-online.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service";
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
-        Type = "forking";
+        Type = "notify";
         User = cfg.user;
         Group = cfg.group;
-        ExecStart = "${pkgs.pgbouncer}/bin/pgbouncer -d ${confFile}";
+        ExecStart = "${lib.getExe pkgs.pgbouncer} ${confFile}";
         ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
         RuntimeDirectory = "pgbouncer";
-        PIDFile = "/run/pgbouncer/pgbouncer.pid";
         LimitNOFILE = cfg.openFilesLimit;
       };
     };
 
-    networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.port;
+    networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.listenPort;
 
   };
 
diff --git a/nixpkgs/nixos/modules/services/display-managers/greetd.nix b/nixpkgs/nixos/modules/services/display-managers/greetd.nix
index 2212f97a9ffe..c2d345152de9 100644
--- a/nixpkgs/nixos/modules/services/display-managers/greetd.nix
+++ b/nixpkgs/nixos/modules/services/display-managers/greetd.nix
@@ -78,7 +78,7 @@ in
       serviceConfig = {
         ExecStart = "${pkgs.greetd.greetd}/bin/greetd --config ${settingsFormat.generate "greetd.toml" cfg.settings}";
 
-        Restart = mkIf cfg.restart "always";
+        Restart = mkIf cfg.restart "on-success";
 
         # Defaults from greetd upstream configuration
         IgnoreSIGPIPE = false;
diff --git a/nixpkgs/nixos/modules/services/games/teeworlds.nix b/nixpkgs/nixos/modules/services/games/teeworlds.nix
index bd0df1ffca57..04b611fb3cb1 100644
--- a/nixpkgs/nixos/modules/services/games/teeworlds.nix
+++ b/nixpkgs/nixos/modules/services/games/teeworlds.nix
@@ -6,13 +6,86 @@ let
   cfg = config.services.teeworlds;
   register = cfg.register;
 
+  bool = b: if b != null && b then "1" else "0";
+  optionalSetting = s: setting: optionalString (s != null) "${setting} ${s}";
+  lookup = attrs: key: default: if attrs ? key then attrs."${key}" else default;
+
+  inactivePenaltyOptions = {
+    "spectator" = "1";
+    "spectator/kick" = "2";
+    "kick" = "3";
+  };
+  skillLevelOptions = {
+    "casual" = "0";
+    "normal" = "1";
+    "competitive" = "2";
+  };
+  tournamentModeOptions = {
+    "disable" = "0";
+    "enable"  = "1";
+    "restrictSpectators" = "2";
+  };
+
   teeworldsConf = pkgs.writeText "teeworlds.cfg" ''
     sv_port ${toString cfg.port}
-    sv_register ${if cfg.register then "1" else "0"}
-    ${optionalString (cfg.name != null) "sv_name ${cfg.name}"}
-    ${optionalString (cfg.motd != null) "sv_motd ${cfg.motd}"}
-    ${optionalString (cfg.password != null) "password ${cfg.password}"}
-    ${optionalString (cfg.rconPassword != null) "sv_rcon_password ${cfg.rconPassword}"}
+    sv_register ${bool cfg.register}
+    sv_name ${cfg.name}
+    ${optionalSetting cfg.motd "sv_motd"}
+    ${optionalSetting cfg.password "password"}
+    ${optionalSetting cfg.rconPassword "sv_rcon_password"}
+
+    ${optionalSetting cfg.server.bindAddr "bindaddr"}
+    ${optionalSetting cfg.server.hostName "sv_hostname"}
+    sv_high_bandwidth ${bool cfg.server.enableHighBandwidth}
+    sv_inactivekick ${lookup inactivePenaltyOptions cfg.server.inactivePenalty "spectator/kick"}
+    sv_inactivekick_spec ${bool cfg.server.kickInactiveSpectators}
+    sv_inactivekick_time ${toString cfg.server.inactiveTime}
+    sv_max_clients ${toString cfg.server.maxClients}
+    sv_max_clients_per_ip ${toString cfg.server.maxClientsPerIP}
+    sv_skill_level ${lookup skillLevelOptions cfg.server.skillLevel "normal"}
+    sv_spamprotection ${bool cfg.server.enableSpamProtection}
+
+    sv_gametype ${cfg.game.gameType}
+    sv_map ${cfg.game.map}
+    sv_match_swap ${bool cfg.game.swapTeams}
+    sv_player_ready_mode ${bool cfg.game.enableReadyMode}
+    sv_player_slots ${toString cfg.game.playerSlots}
+    sv_powerups ${bool cfg.game.enablePowerups}
+    sv_scorelimit ${toString cfg.game.scoreLimit}
+    sv_strict_spectate_mode ${bool cfg.game.restrictSpectators}
+    sv_teamdamage ${bool cfg.game.enableTeamDamage}
+    sv_timelimit ${toString cfg.game.timeLimit}
+    sv_tournament_mode ${lookup tournamentModeOptions cfg.server.tournamentMode "disable"}
+    sv_vote_kick ${bool cfg.game.enableVoteKick}
+    sv_vote_kick_bantime ${toString cfg.game.voteKickBanTime}
+    sv_vote_kick_min ${toString cfg.game.voteKickMinimumPlayers}
+
+    ${optionalSetting cfg.server.bindAddr "bindaddr"}
+    ${optionalSetting cfg.server.hostName "sv_hostname"}
+    sv_high_bandwidth ${bool cfg.server.enableHighBandwidth}
+    sv_inactivekick ${lookup inactivePenaltyOptions cfg.server.inactivePenalty "spectator/kick"}
+    sv_inactivekick_spec ${bool cfg.server.kickInactiveSpectators}
+    sv_inactivekick_time ${toString cfg.server.inactiveTime}
+    sv_max_clients ${toString cfg.server.maxClients}
+    sv_max_clients_per_ip ${toString cfg.server.maxClientsPerIP}
+    sv_skill_level ${lookup skillLevelOptions cfg.server.skillLevel "normal"}
+    sv_spamprotection ${bool cfg.server.enableSpamProtection}
+
+    sv_gametype ${cfg.game.gameType}
+    sv_map ${cfg.game.map}
+    sv_match_swap ${bool cfg.game.swapTeams}
+    sv_player_ready_mode ${bool cfg.game.enableReadyMode}
+    sv_player_slots ${toString cfg.game.playerSlots}
+    sv_powerups ${bool cfg.game.enablePowerups}
+    sv_scorelimit ${toString cfg.game.scoreLimit}
+    sv_strict_spectate_mode ${bool cfg.game.restrictSpectators}
+    sv_teamdamage ${bool cfg.game.enableTeamDamage}
+    sv_timelimit ${toString cfg.game.timeLimit}
+    sv_tournament_mode ${lookup tournamentModeOptions cfg.server.tournamentMode "disable"}
+    sv_vote_kick ${bool cfg.game.enableVoteKick}
+    sv_vote_kick_bantime ${toString cfg.game.voteKickBanTime}
+    sv_vote_kick_min ${toString cfg.game.voteKickMinimumPlayers}
+
     ${concatStringsSep "\n" cfg.extraOptions}
   '';
 
@@ -22,17 +95,19 @@ in
     services.teeworlds = {
       enable = mkEnableOption (lib.mdDoc "Teeworlds Server");
 
+      package = mkPackageOptionMD pkgs "teeworlds-server" { };
+
       openPorts = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc "Whether to open firewall ports for Teeworlds";
+        description = lib.mdDoc "Whether to open firewall ports for Teeworlds.";
       };
 
       name = mkOption {
-        type = types.nullOr types.str;
-        default = null;
+        type = types.str;
+        default = "unnamed server";
         description = lib.mdDoc ''
-          Name of the server. Defaults to 'unnamed server'.
+          Name of the server.
         '';
       };
 
@@ -41,7 +116,7 @@ in
         example = true;
         default = false;
         description = lib.mdDoc ''
-          Whether the server registers as public server in the global server list. This is disabled by default because of privacy.
+          Whether the server registers as a public server in the global server list. This is disabled by default for privacy reasons.
         '';
       };
 
@@ -49,7 +124,7 @@ in
         type = types.nullOr types.str;
         default = null;
         description = lib.mdDoc ''
-          Set the server message of the day text.
+          The server's message of the day text.
         '';
       };
 
@@ -85,6 +160,217 @@ in
         '';
         example = [ "sv_map dm1" "sv_gametype dm" ];
       };
+
+      server = {
+        bindAddr = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          description = lib.mdDoc ''
+            The address the server will bind to.
+          '';
+        };
+
+        enableHighBandwidth = mkOption {
+          type = types.bool;
+          default = false;
+          description = lib.mdDoc ''
+            Whether to enable high bandwidth mode on LAN servers. This will double the amount of bandwidth required for running the server.
+          '';
+        };
+
+        hostName = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          description = lib.mdDoc ''
+            Hostname for the server.
+          '';
+        };
+
+        inactivePenalty = mkOption {
+          type = types.enum [ "spectator" "spectator/kick" "kick" ];
+          example = "spectator";
+          default = "spectator/kick";
+          description = lib.mdDoc ''
+            Specify what to do when a client goes inactive (see [](#opt-services.teeworlds.server.inactiveTime)).
+
+            - `spectator`: send the client into spectator mode
+
+            - `spectator/kick`: send the client into a free spectator slot, otherwise kick the client
+
+            - `kick`: kick the client
+          '';
+        };
+
+        kickInactiveSpectators = mkOption {
+          type = types.bool;
+          default = false;
+          description = lib.mdDoc ''
+            Whether to kick inactive spectators.
+          '';
+        };
+
+        inactiveTime = mkOption {
+          type = types.ints.unsigned;
+          default = 3;
+          description = lib.mdDoc ''
+            The amount of minutes a client has to idle before it is considered inactive.
+          '';
+        };
+
+        maxClients = mkOption {
+          type = types.ints.unsigned;
+          default = 12;
+          description = lib.mdDoc ''
+            The maximum amount of clients that can be connected to the server at the same time.
+          '';
+        };
+
+        maxClientsPerIP = mkOption {
+          type = types.ints.unsigned;
+          default = 12;
+          description = lib.mdDoc ''
+            The maximum amount of clients with the same IP address that can be connected to the server at the same time.
+          '';
+        };
+
+        skillLevel = mkOption {
+          type = types.enum [ "casual" "normal" "competitive" ];
+          default = "normal";
+          description = lib.mdDoc ''
+            The skill level shown in the server browser.
+          '';
+        };
+
+        enableSpamProtection = mkOption {
+          type = types.bool;
+          default = true;
+          description = lib.mdDoc ''
+            Whether to enable chat spam protection.
+          '';
+        };
+      };
+
+      game = {
+        gameType = mkOption {
+          type = types.str;
+          example = "ctf";
+          default = "dm";
+          description = lib.mdDoc ''
+            The game type to use on the server.
+
+            The default gametypes are `dm`, `tdm`, `ctf`, `lms`, and `lts`.
+          '';
+        };
+
+        map = mkOption {
+          type = types.str;
+          example = "ctf5";
+          default = "dm1";
+          description = lib.mdDoc ''
+            The map to use on the server.
+          '';
+        };
+
+        swapTeams = mkOption {
+          type = types.bool;
+          default = true;
+          description = lib.mdDoc ''
+            Whether to swap teams each round.
+          '';
+        };
+
+        enableReadyMode = mkOption {
+          type = types.bool;
+          default = false;
+          description = lib.mdDoc ''
+            Whether to enable "ready mode"; where players can pause/unpause the game
+            and start the game in warmup, using their ready state.
+          '';
+        };
+
+        playerSlots = mkOption {
+          type = types.ints.unsigned;
+          default = 8;
+          description = lib.mdDoc ''
+            The amount of slots to reserve for players (as opposed to spectators).
+          '';
+        };
+
+        enablePowerups = mkOption {
+          type = types.bool;
+          default = true;
+          description = lib.mdDoc ''
+            Whether to allow powerups such as the ninja.
+          '';
+        };
+
+        scoreLimit = mkOption {
+          type = types.ints.unsigned;
+          example = 400;
+          default = 20;
+          description = lib.mdDoc ''
+            The score limit needed to win a round.
+          '';
+        };
+
+        restrictSpectators = mkOption {
+          type = types.bool;
+          default = false;
+          description = lib.mdDoc ''
+            Whether to restrict access to information such as health, ammo and armour in spectator mode.
+          '';
+        };
+
+        enableTeamDamage = mkOption {
+          type = types.bool;
+          default = false;
+          description = lib.mdDoc ''
+            Whether to enable team damage; whether to allow team mates to inflict damage on one another.
+          '';
+        };
+
+        timeLimit = mkOption {
+          type = types.ints.unsigned;
+          default = 0;
+          description = lib.mdDoc ''
+            Time limit of the game. In cases of equal points, there will be sudden death.
+            Setting this to 0 disables a time limit.
+          '';
+        };
+
+        tournamentMode = mkOption {
+          type = types.enum [ "disable" "enable" "restrictSpectators" ];
+          default = "disable";
+          description = lib.mdDoc ''
+            Whether to enable tournament mode. In tournament mode, players join as spectators.
+            If this is set to `restrictSpectators`, tournament mode is enabled but spectator chat is restricted.
+          '';
+        };
+
+        enableVoteKick = mkOption {
+          type = types.bool;
+          default = true;
+          description = lib.mdDoc ''
+            Whether to enable voting to kick players.
+          '';
+        };
+
+        voteKickBanTime = mkOption {
+          type = types.ints.unsigned;
+          default = 5;
+          description = lib.mdDoc ''
+            The amount of minutes that a player is banned for if they get kicked by a vote.
+          '';
+        };
+
+        voteKickMinimumPlayers = mkOption {
+          type = types.ints.unsigned;
+          default = 5;
+          description = lib.mdDoc ''
+            The minimum amount of players required to start a kick vote.
+          '';
+        };
+      };
     };
   };
 
@@ -100,7 +386,7 @@ in
 
       serviceConfig = {
         DynamicUser = true;
-        ExecStart = "${pkgs.teeworlds-server}/bin/teeworlds_srv -f ${teeworldsConf}";
+        ExecStart = "${cfg.package}/bin/teeworlds_srv -f ${teeworldsConf}";
 
         # Hardening
         CapabilityBoundingSet = false;
diff --git a/nixpkgs/nixos/modules/services/hardware/asusd.nix b/nixpkgs/nixos/modules/services/hardware/asusd.nix
index ebbdea26c051..ff9a751e5be8 100644
--- a/nixpkgs/nixos/modules/services/hardware/asusd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/asusd.nix
@@ -8,6 +8,8 @@ in
     services.asusd = {
       enable = lib.mkEnableOption (lib.mdDoc "the asusd service for ASUS ROG laptops");
 
+      package = lib.mkPackageOption pkgs "asusctl" { };
+
       enableUserService = lib.mkOption {
         type = lib.types.bool;
         default = false;
@@ -73,7 +75,7 @@ in
   };
 
   config = lib.mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.asusctl ];
+    environment.systemPackages = [ cfg.package ];
 
     environment.etc =
       let
@@ -92,9 +94,9 @@ in
       };
 
     services.dbus.enable = true;
-    systemd.packages = [ pkgs.asusctl ];
-    services.dbus.packages = [ pkgs.asusctl ];
-    services.udev.packages = [ pkgs.asusctl ];
+    systemd.packages = [ cfg.package ];
+    services.dbus.packages = [ cfg.package ];
+    services.udev.packages = [ cfg.package ];
     services.supergfxd.enable = lib.mkDefault true;
 
     systemd.user.services.asusd-user.enable = cfg.enableUserService;
diff --git a/nixpkgs/nixos/modules/services/hardware/bolt.nix b/nixpkgs/nixos/modules/services/hardware/bolt.nix
index 6990a9ea63b3..3bdf67cc1758 100644
--- a/nixpkgs/nixos/modules/services/hardware/bolt.nix
+++ b/nixpkgs/nixos/modules/services/hardware/bolt.nix
@@ -1,14 +1,13 @@
-# Thunderbolt 3 device manager
-
 { config, lib, pkgs, ...}:
 
 with lib;
 
+let
+  cfg = config.services.hardware.bolt;
+in
 {
   options = {
-
     services.hardware.bolt = {
-
       enable = mkOption {
         type = types.bool;
         default = false;
@@ -20,15 +19,13 @@ with lib;
         '';
       };
 
+      package = mkPackageOption pkgs "bolt" { };
     };
-
   };
 
-  config = mkIf config.services.hardware.bolt.enable {
-
-    environment.systemPackages = [ pkgs.bolt ];
-    services.udev.packages = [ pkgs.bolt ];
-    systemd.packages = [ pkgs.bolt ];
-
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+    services.udev.packages = [ cfg.package ];
+    systemd.packages = [ cfg.package ];
   };
 }
diff --git a/nixpkgs/nixos/modules/services/hardware/brltty.nix b/nixpkgs/nixos/modules/services/hardware/brltty.nix
index 3133804f485f..f96760e92c57 100644
--- a/nixpkgs/nixos/modules/services/hardware/brltty.nix
+++ b/nixpkgs/nixos/modules/services/hardware/brltty.nix
@@ -34,6 +34,7 @@ in {
     users.users.brltty = {
       description = "BRLTTY daemon user";
       group = "brltty";
+      isSystemUser = true;
     };
     users.groups = {
       brltty = { };
diff --git a/nixpkgs/nixos/modules/services/hardware/undervolt.nix b/nixpkgs/nixos/modules/services/hardware/undervolt.nix
index 67d8171587bb..c4d4c6791a21 100644
--- a/nixpkgs/nixos/modules/services/hardware/undervolt.nix
+++ b/nixpkgs/nixos/modules/services/hardware/undervolt.nix
@@ -12,6 +12,7 @@ let
     inherit (cfg)
       verbose
       temp
+      turbo
       ;
     # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
     #
@@ -105,6 +106,14 @@ in
       '';
     };
 
+    turbo = mkOption {
+      type = types.nullOr types.int;
+      default = null;
+      description = lib.mdDoc ''
+        Changes the Intel Turbo feature status (1 is disabled and 0 is enabled).
+      '';
+    };
+
     p1.limit = mkOption {
       type = with types; nullOr int;
       default = null;
diff --git a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
index f576a426b318..8ab3497f7a17 100644
--- a/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
+++ b/nixpkgs/nixos/modules/services/mail/stalwart-mail.nix
@@ -32,10 +32,15 @@ in {
       global.tracing.level = mkDefault "info";
       queue.path = mkDefault "${dataDir}/queue";
       report.path = mkDefault "${dataDir}/reports";
+      store.db.type = mkDefault "sqlite";
       store.db.path = mkDefault "${dataDir}/data/index.sqlite3";
-      store.blob.type = mkDefault "local";
-      store.blob.local.path = mkDefault "${dataDir}/data/blobs";
+      store.blob.type = mkDefault "fs";
+      store.blob.path = mkDefault "${dataDir}/data/blobs";
+      storage.data = mkDefault "db";
+      storage.fts = mkDefault "db";
+      storage.blob = mkDefault "blob";
       resolver.type = mkDefault "system";
+      resolver.public-suffix = mkDefault ["https://publicsuffix.org/list/public_suffix_list.dat"];
     };
 
     systemd.services.stalwart-mail = {
@@ -57,8 +62,8 @@ in {
         KillSignal = "SIGINT";
         Restart = "on-failure";
         RestartSec = 5;
-        StandardOutput = "syslog";
-        StandardError = "syslog";
+        StandardOutput = "journal";
+        StandardError = "journal";
         SyslogIdentifier = "stalwart-mail";
 
         DynamicUser = true;
diff --git a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix
index 80a6162b2168..557d6d7e7168 100644
--- a/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix
+++ b/nixpkgs/nixos/modules/services/misc/sourcehut/default.nix
@@ -790,13 +790,21 @@ in
         '';
       };
       systemd.tmpfiles.settings."10-sourcehut-gitsrht" = mkIf cfg.git.enable (
-        builtins.listToAttrs (map (name: {
-          name = "/var/log/sourcehut/gitsrht-${name}";
-          value.f = {
-            inherit (cfg.git) user group;
-            mode = "0644";
-          };
-        }) [ "keys" "shell" "update-hook" ])
+        mkMerge [
+          (builtins.listToAttrs (map (name: {
+            name = "/var/log/sourcehut/gitsrht-${name}";
+            value.f = {
+              inherit (cfg.git) user group;
+              mode = "0644";
+            };
+          }) [ "keys" "shell" "update-hook" ]))
+          {
+            ${cfg.settings."git.sr.ht".repos}.d = {
+              inherit (cfg.git) user group;
+              mode = "0644";
+            };
+          }
+        ]
       );
       systemd.services.sshd = {
         preStart = mkIf cfg.hg.enable ''
diff --git a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix
index 6c51a9bb8555..a8300ecd5233 100644
--- a/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix
+++ b/nixpkgs/nixos/modules/services/misc/tandoor-recipes.nix
@@ -17,14 +17,11 @@ let
     lib.mapAttrs (_: toString) cfg.extraConfig
   );
 
-  manage =
-    let
-      setupEnv = lib.concatStringsSep "\n" (mapAttrsToList (name: val: "export ${name}=\"${val}\"") env);
-    in
-    pkgs.writeShellScript "manage" ''
-      ${setupEnv}
-      exec ${pkg}/bin/tandoor-recipes "$@"
-    '';
+  manage = pkgs.writeShellScript "manage" ''
+    set -o allexport # Export the following env vars
+    ${lib.toShellVars env}
+    exec ${pkg}/bin/tandoor-recipes "$@"
+  '';
 in
 {
   meta.maintainers = with maintainers; [ ambroisie ];
diff --git a/nixpkgs/nixos/modules/services/networking/go-camo.nix b/nixpkgs/nixos/modules/services/networking/go-camo.nix
new file mode 100644
index 000000000000..cb3b6eade464
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/go-camo.nix
@@ -0,0 +1,73 @@
+{ lib, pkgs, config, ... }:
+
+let
+  cfg = config.services.go-camo;
+  inherit (lib) mkOption mkEnableOption mkIf mkMerge types optionalString;
+in
+{
+  options.services.go-camo = {
+    enable = mkEnableOption "go-camo service";
+    listen = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = "Address:Port to bind to for HTTP (default: 0.0.0.0:8080).";
+      apply = v: optionalString (v != null) "--listen=${v}";
+    };
+    sslListen = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = "Address:Port to bind to for HTTPS.";
+      apply = v: optionalString (v != null) "--ssl-listen=${v}";
+    };
+    sslKey = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = "Path to TLS private key.";
+      apply = v: optionalString (v != null) "--ssl-key=${v}";
+    };
+    sslCert = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = "Path to TLS certificate.";
+      apply = v: optionalString (v != null) "--ssl-cert=${v}";
+    };
+    keyFile = mkOption {
+      type = types.path;
+      default = null;
+      description = ''
+        A file containing the HMAC key to use for signing URLs.
+        The file can contain any string. Can be generated using "openssl rand -base64 18 > the_file".
+      '';
+    };
+    extraOptions = mkOption {
+      type = with types; listOf str;
+      default = [];
+      description = "Extra options passed to the go-camo command.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.go-camo = {
+      description = "go-camo service";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      environment = {
+        GOCAMO_HMAC_FILE = "%d/hmac";
+      };
+      script = ''
+        export GOCAMO_HMAC=$(cat "$GOCAMO_HMAC_FILE")
+        exec ${lib.escapeShellArgs(lib.lists.remove "" ([ "${pkgs.go-camo}/bin/go-camo" cfg.listen cfg.sslListen cfg.sslKey cfg.sslCert ] ++ cfg.extraOptions))}
+      '';
+      serviceConfig = {
+        NoNewPrivileges = true;
+        ProtectSystem = "strict";
+        DynamicUser = true;
+        User = "gocamo";
+        Group = "gocamo";
+        LoadCredential = [
+          "hmac:${cfg.keyFile}"
+        ];
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/hostapd.nix b/nixpkgs/nixos/modules/services/networking/hostapd.nix
index 00482e59acf3..40542155ed63 100644
--- a/nixpkgs/nixos/modules/services/networking/hostapd.nix
+++ b/nixpkgs/nixos/modules/services/networking/hostapd.nix
@@ -909,7 +909,7 @@ in {
                 in {
                   settings = {
                     ssid = bssCfg.ssid;
-                    utf8_ssid = bssCfg.ssid;
+                    utf8_ssid = bssCfg.utf8Ssid;
 
                     logger_syslog = mkDefault (-1);
                     logger_syslog_level = bssCfg.logLevel;
diff --git a/nixpkgs/nixos/modules/services/networking/knot.nix b/nixpkgs/nixos/modules/services/networking/knot.nix
index 94c32586736a..6488a159b3b7 100644
--- a/nixpkgs/nixos/modules/services/networking/knot.nix
+++ b/nixpkgs/nixos/modules/services/networking/knot.nix
@@ -1,8 +1,36 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, utils, ... }:
 
-with lib;
 
 let
+  inherit (lib)
+    attrNames
+    concatMapStrings
+    concatMapStringsSep
+    concatStrings
+    concatStringsSep
+    elem
+    filter
+    flip
+    hasAttr
+    hasPrefix
+    isAttrs
+    isBool
+    isDerivation
+    isList
+    mapAttrsToList
+    mkChangedOptionModule
+    mkEnableOption
+    mkIf
+    mkOption
+    mkPackageOption
+    optionals
+    types
+  ;
+
+  inherit (utils)
+    escapeSystemdExecArgs
+  ;
+
   cfg = config.services.knot;
 
   yamlConfig = let
@@ -113,8 +141,7 @@ let
   mkConfigFile = configString: pkgs.writeTextFile {
     name = "knot.conf";
     text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + configString;
-    # TODO: maybe we could do some checks even when private keys complicate this?
-    checkPhase = lib.optionalString (cfg.keyFiles == []) ''
+    checkPhase = lib.optionalString cfg.checkConfig ''
       ${cfg.package}/bin/knotc --config=$out conf-check
     '';
   };
@@ -142,12 +169,45 @@ let
 in {
   options = {
     services.knot = {
-      enable = mkEnableOption (lib.mdDoc "Knot authoritative-only DNS server");
+      enable = mkEnableOption "Knot authoritative-only DNS server";
+
+      enableXDP = mkOption {
+        type = types.bool;
+        default = lib.hasAttrByPath [ "xdp" "listen" ] cfg.settings;
+        defaultText = ''
+          Enabled when the `xdp.listen` setting is configured through `settings`.
+        '';
+        example = true;
+        description = ''
+          Extends the systemd unit with permissions to allow for the use of
+          the eXpress Data Path (XDP).
+
+          ::: {.note}
+            Make sure to read up on functional [limitations](https://www.knot-dns.cz/docs/latest/singlehtml/index.html#mode-xdp-limitations)
+            when running in XDP mode.
+          :::
+        '';
+      };
+
+      checkConfig = mkOption {
+        type = types.bool;
+        # TODO: maybe we could do some checks even when private keys complicate this?
+        # conf-check fails hard on missing IPs/devices with XDP
+        default = cfg.keyFiles == [] && !cfg.enableXDP;
+        defaultText = ''
+          Disabled when the config uses `keyFiles` or `enableXDP`.
+        '';
+        example = false;
+        description = ''
+          Toggles the configuration test at build time. It runs in a
+          sandbox, and therefore cannot be used in all scenarios.
+        '';
+      };
 
       extraArgs = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = lib.mdDoc ''
+        description = ''
           List of additional command line parameters for knotd
         '';
       };
@@ -155,7 +215,7 @@ in {
       keyFiles = mkOption {
         type = types.listOf types.path;
         default = [];
-        description = lib.mdDoc ''
+        description = ''
           A list of files containing additional configuration
           to be included using the include directive. This option
           allows to include configuration like TSIG keys without
@@ -168,7 +228,7 @@ in {
       settings = mkOption {
         type = types.attrs;
         default = {};
-        description = lib.mdDoc ''
+        description = ''
           Extra configuration as nix values.
         '';
       };
@@ -176,7 +236,7 @@ in {
       settingsFile = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = lib.mdDoc ''
+        description = ''
           As alternative to ``settings``, you can provide whole configuration
           directly in the almost-YAML format of Knot DNS.
           You might want to utilize ``pkgs.writeText "knot.conf" "longConfigString"`` for this.
@@ -210,19 +270,35 @@ in {
       wants = [ "network.target" ];
       after = ["network.target" ];
 
-      serviceConfig = {
+      serviceConfig = let
+        # https://www.knot-dns.cz/docs/3.3/singlehtml/index.html#pre-requisites
+        xdpCapabilities = lib.optionals (cfg.enableXDP) [
+          "CAP_NET_ADMIN"
+          "CAP_NET_RAW"
+          "CAP_SYS_ADMIN"
+          "CAP_IPC_LOCK"
+        ] ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "5.11") [
+          "CAP_SYS_RESOURCE"
+        ];
+      in {
         Type = "notify";
-        ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
-        ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
+        ExecStart = escapeSystemdExecArgs ([
+          (lib.getExe cfg.package)
+          "--config=${configFile}"
+          "--socket=${socketFile}"
+        ] ++ cfg.extraArgs);
+        ExecReload = escapeSystemdExecArgs [
+          "${knot-cli-wrappers}/bin/knotc" "reload"
+        ];
         User = "knot";
         Group = "knot";
 
         AmbientCapabilities = [
           "CAP_NET_BIND_SERVICE"
-        ];
+        ] ++ xdpCapabilities;
         CapabilityBoundingSet = [
           "CAP_NET_BIND_SERVICE"
-        ];
+        ] ++ xdpCapabilities;
         DeviceAllow = "";
         DevicePolicy = "closed";
         LockPersonality = true;
@@ -247,6 +323,9 @@ in {
           "AF_INET"
           "AF_INET6"
           "AF_UNIX"
+        ] ++ optionals (cfg.enableXDP) [
+          "AF_NETLINK"
+          "AF_XDP"
         ];
         RestrictNamespaces = true;
         RestrictRealtime =true;
@@ -258,6 +337,8 @@ in {
         SystemCallFilter = [
           "@system-service"
           "~@privileged"
+        ] ++ optionals (cfg.enableXDP) [
+          "bpf"
         ];
         UMask = "0077";
       };
diff --git a/nixpkgs/nixos/modules/services/networking/libreswan.nix b/nixpkgs/nixos/modules/services/networking/libreswan.nix
index db4d2f7f0ba0..a44cac93d5f6 100644
--- a/nixpkgs/nixos/modules/services/networking/libreswan.nix
+++ b/nixpkgs/nixos/modules/services/networking/libreswan.nix
@@ -133,9 +133,6 @@ in
       "ipsec.d/01-nixos.conf".source = configFile;
     } // policyFiles;
 
-    # Create NSS database directory
-    systemd.tmpfiles.rules = [ "d /var/lib/ipsec/nss 755 root root -" ];
-
     systemd.services.ipsec = {
       description = "Internet Key Exchange (IKE) Protocol Daemon for IPsec";
       wantedBy = [ "multi-user.target" ];
@@ -153,6 +150,10 @@ in
         echo 0 | tee /proc/sys/net/ipv4/conf/*/send_redirects
         echo 0 | tee /proc/sys/net/ipv{4,6}/conf/*/accept_redirects
       '';
+      serviceConfig = {
+        StateDirectory = "ipsec/nss";
+        StateDirectoryMode = 0700;
+      };
     };
 
   };
diff --git a/nixpkgs/nixos/modules/services/security/opensnitch.nix b/nixpkgs/nixos/modules/services/security/opensnitch.nix
index 97ac3a72804c..42cf8159f3ea 100644
--- a/nixpkgs/nixos/modules/services/security/opensnitch.nix
+++ b/nixpkgs/nixos/modules/services/security/opensnitch.nix
@@ -36,7 +36,8 @@ in {
 
         description = mdDoc ''
           Declarative configuration of firewall rules.
-          All rules will be stored in `/var/lib/opensnitch/rules`.
+          All rules will be stored in `/var/lib/opensnitch/rules` by default.
+          Rules path can be configured with `settings.Rules.Path`.
           See [upstream documentation](https://github.com/evilsocket/opensnitch/wiki/Rules)
           for available options.
         '';
@@ -79,15 +80,6 @@ in {
               '';
             };
 
-            DefaultDuration = mkOption {
-              type = types.enum [
-                "once" "always" "until restart" "30s" "5m" "15m" "30m" "1h"
-              ];
-              description = mdDoc ''
-                Default duration of firewall rule.
-              '';
-            };
-
             InterceptUnknown = mkOption {
               type = types.bool;
               description = mdDoc ''
@@ -134,6 +126,30 @@ in {
               };
 
             };
+
+            Ebpf.ModulesPath = mkOption {
+              type = types.path;
+              default = if cfg.settings.ProcMonitorMethod == "ebpf" then "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd" else null;
+              defaultText = literalExpression ''
+                if cfg.settings.ProcMonitorMethod == "ebpf" then
+                  "\\$\\{config.boot.kernelPackages.opensnitch-ebpf\\}/etc/opensnitchd"
+                else null;
+              '';
+              description = mdDoc ''
+                Configure eBPF modules path. Used when
+                `settings.ProcMonitorMethod` is set to `ebpf`.
+              '';
+            };
+
+            Rules.Path = mkOption {
+              type = types.path;
+              default = "/var/lib/opensnitch/rules";
+              description = mdDoc ''
+                Path to the directory where firewall rules can be found and will
+                get stored by the NixOS module.
+              '';
+            };
+
           };
         };
         description = mdDoc ''
@@ -151,40 +167,42 @@ in {
 
     systemd = {
       packages = [ pkgs.opensnitch ];
-      services.opensnitchd.wantedBy = [ "multi-user.target" ];
+      services.opensnitchd = {
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          ExecStart = [
+            ""
+            "${pkgs.opensnitch}/bin/opensnitchd --config-file ${format.generate "default-config.json" cfg.settings}"
+          ];
+        };
+        preStart = mkIf (cfg.rules != {}) (let
+          rules = flip mapAttrsToList predefinedRules (file: content: {
+          inherit (content) file;
+          local = "${cfg.settings.Rules.Path}/${file}.json";
+        });
+        in ''
+          # Remove all firewall rules from rules path (configured with
+          # cfg.settings.Rules.Path) that are symlinks to a store-path, but aren't
+          # declared in `cfg.rules` (i.e. all networks that were "removed" from
+          # `cfg.rules`).
+          find ${cfg.settings.Rules.Path} -type l -lname '${builtins.storeDir}/*' ${optionalString (rules != {}) ''
+            -not \( ${concatMapStringsSep " -o " ({ local, ... }:
+              "-name '${baseNameOf local}*'")
+            rules} \) \
+          ''} -delete
+          ${concatMapStrings ({ file, local }: ''
+            ln -sf '${file}' "${local}"
+          '') rules}
+        '');
+      };
+      tmpfiles.rules = [
+        "d ${cfg.settings.Rules.Path} 0750 root root - -"
+        "L+ /etc/opensnitchd/system-fw.json - - - - ${pkgs.opensnitch}/etc/opensnitchd/system-fw.json"
+      ];
     };
 
-    systemd.services.opensnitchd.preStart = mkIf (cfg.rules != {}) (let
-      rules = flip mapAttrsToList predefinedRules (file: content: {
-        inherit (content) file;
-        local = "/var/lib/opensnitch/rules/${file}.json";
-      });
-    in ''
-      # Remove all firewall rules from `/var/lib/opensnitch/rules` that are symlinks to a store-path,
-      # but aren't declared in `cfg.rules` (i.e. all networks that were "removed" from
-      # `cfg.rules`).
-      find /var/lib/opensnitch/rules -type l -lname '${builtins.storeDir}/*' ${optionalString (rules != {}) ''
-        -not \( ${concatMapStringsSep " -o " ({ local, ... }:
-          "-name '${baseNameOf local}*'")
-        rules} \) \
-      ''} -delete
-      ${concatMapStrings ({ file, local }: ''
-        ln -sf '${file}' "${local}"
-      '') rules}
-
-      if [ ! -f /etc/opensnitchd/system-fw.json ]; then
-        cp "${pkgs.opensnitch}/etc/opensnitchd/system-fw.json" "/etc/opensnitchd/system-fw.json"
-      fi
-    '');
-
-    environment.etc = mkMerge [ ({
-      "opensnitchd/default-config.json".source = format.generate "default-config.json" cfg.settings;
-    }) (mkIf (cfg.settings.ProcMonitorMethod == "ebpf") {
-      "opensnitchd/opensnitch.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch.o";
-      "opensnitchd/opensnitch-dns.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch-dns.o";
-      "opensnitchd/opensnitch-procs.o".source = "${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd/opensnitch-procs.o";
-    })];
-
   };
+
+  meta.maintainers = with lib.maintainers; [ onny ];
 }
 
diff --git a/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix b/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix
index 8934ed3a7ef2..7d3cd004a7ba 100644
--- a/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix
+++ b/nixpkgs/nixos/modules/services/system/automatic-timezoned.nix
@@ -50,7 +50,7 @@ in
         serviceConfig = {
           Type = "exec";
           User = "automatic-timezoned";
-          ExecStart = "${cfg.package}/bin/automatic-timezoned --zoneinfo-path=${pkgs.tzdata}/share/zoneinfo/zone1970.tab";
+          ExecStart = "${cfg.package}/bin/automatic-timezoned";
         };
         wantedBy = [ "default.target" ];
       };
diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix
index 5dd02eb33163..a9fb123b981e 100644
--- a/nixpkgs/nixos/modules/services/torrent/transmission.nix
+++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix
@@ -74,7 +74,7 @@ in
             description = lib.mdDoc "";
           };
           options.message-level = mkOption {
-            type = types.ints.between 0 3;
+            type = types.ints.between 0 6;
             default = 2;
             description = lib.mdDoc "Set verbosity of transmission messages.";
           };
diff --git a/nixpkgs/nixos/modules/services/web-apps/mastodon.nix b/nixpkgs/nixos/modules/services/web-apps/mastodon.nix
index 8d09d1b97828..7fc710c6fcec 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mastodon.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mastodon.nix
@@ -4,7 +4,8 @@ let
   cfg = config.services.mastodon;
   opt = options.services.mastodon;
 
-  # We only want to create a database if we're actually going to connect to it.
+  # We only want to create a Redis and PostgreSQL databases if we're actually going to connect to it local.
+  redisActuallyCreateLocally = cfg.redis.createLocally && (cfg.redis.host == "127.0.0.1" || cfg.redis.enableUnixSocket);
   databaseActuallyCreateLocally = cfg.database.createLocally && cfg.database.host == "/run/postgresql";
 
   env = {
@@ -33,6 +34,7 @@ let
 
     TRUSTED_PROXY_IP = cfg.trustedProxy;
   }
+  // lib.optionalAttrs (cfg.redis.createLocally && cfg.redis.enableUnixSocket) { REDIS_URL = "unix://${config.services.redis.servers.mastodon.unixSocket}"; }
   // lib.optionalAttrs (cfg.database.host != "/run/postgresql" && cfg.database.port != null) { DB_PORT = toString cfg.database.port; }
   // lib.optionalAttrs cfg.smtp.authenticate { SMTP_LOGIN  = cfg.smtp.user; }
   // lib.optionalAttrs (cfg.elasticsearch.host != null) { ES_HOST = cfg.elasticsearch.host; }
@@ -116,9 +118,11 @@ let
       threads = toString (if processCfg.threads == null then cfg.sidekiqThreads else processCfg.threads);
     in {
       after = [ "network.target" "mastodon-init-dirs.service" ]
+        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
         ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
         ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
       requires = [ "mastodon-init-dirs.service" ]
+        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
         ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
         ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
       description = "Mastodon sidekiq${jobClassLabel}";
@@ -146,9 +150,11 @@ let
         name = "mastodon-streaming-${toString i}";
         value = {
           after = [ "network.target" "mastodon-init-dirs.service" ]
+            ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
             ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
             ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
           requires = [ "mastodon-init-dirs.service" ]
+            ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
             ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
             ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
           wantedBy = [ "mastodon.target" "mastodon-streaming.target" ];
@@ -404,6 +410,19 @@ in {
           type = lib.types.port;
           default = 31637;
         };
+
+        passwordFile = lib.mkOption {
+          description = lib.mdDoc "A file containing the password for Redis database.";
+          type = lib.types.nullOr lib.types.path;
+          default = null;
+          example = "/run/keys/mastodon-redis-password";
+        };
+
+        enableUnixSocket = lib.mkOption {
+          description = lib.mdDoc "Use Unix socket";
+          type = lib.types.bool;
+          default = true;
+        };
       };
 
       database = {
@@ -613,6 +632,13 @@ in {
   config = lib.mkIf cfg.enable (lib.mkMerge [{
     assertions = [
       {
+        assertion = redisActuallyCreateLocally -> (!cfg.redis.enableUnixSocket || cfg.redis.passwordFile == null);
+        message = ''
+          <option>services.mastodon.redis.enableUnixSocket</option> needs to be disabled if
+            <option>services.mastodon.redis.passwordFile</option> is used.
+        '';
+      }
+      {
         assertion = databaseActuallyCreateLocally -> (cfg.user == cfg.database.user && cfg.database.user == cfg.database.name);
         message = ''
           For local automatic database provisioning (services.mastodon.database.createLocally == true) with peer
@@ -689,6 +715,8 @@ in {
         OTP_SECRET="$(cat ${cfg.otpSecretFile})"
         VAPID_PRIVATE_KEY="$(cat ${cfg.vapidPrivateKeyFile})"
         VAPID_PUBLIC_KEY="$(cat ${cfg.vapidPublicKeyFile})"
+      '' + lib.optionalString (cfg.redis.passwordFile != null)''
+        REDIS_PASSWORD="$(cat ${cfg.redis.passwordFile})"
       '' + lib.optionalString (cfg.database.passwordFile != null) ''
         DB_PASS="$(cat ${cfg.database.passwordFile})"
       '' + lib.optionalString cfg.smtp.authenticate ''
@@ -751,9 +779,11 @@ in {
 
     systemd.services.mastodon-web = {
       after = [ "network.target" "mastodon-init-dirs.service" ]
+        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
         ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
         ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
       requires = [ "mastodon-init-dirs.service" ]
+        ++ lib.optional redisActuallyCreateLocally "redis-mastodon.service"
         ++ lib.optional databaseActuallyCreateLocally "postgresql.service"
         ++ lib.optional cfg.automaticMigrations "mastodon-init-db.service";
       wantedBy = [ "mastodon.target" ];
@@ -834,11 +864,14 @@ in {
       enable = true;
       hostname = lib.mkDefault "${cfg.localDomain}";
     };
-    services.redis.servers.mastodon = lib.mkIf (cfg.redis.createLocally && cfg.redis.host == "127.0.0.1") {
-      enable = true;
-      port = cfg.redis.port;
-      bind = "127.0.0.1";
-    };
+    services.redis.servers.mastodon = lib.mkIf redisActuallyCreateLocally (lib.mkMerge [
+      {
+        enable = true;
+      }
+      (lib.mkIf (!cfg.redis.enableUnixSocket) {
+        port = cfg.redis.port;
+      })
+    ]);
     services.postgresql = lib.mkIf databaseActuallyCreateLocally {
       enable = true;
       ensureUsers = [
@@ -859,6 +892,7 @@ in {
         };
       })
       (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package pkgs.imagemagick ])
+      (lib.mkIf (cfg.redis.createLocally && cfg.redis.enableUnixSocket) {${config.services.mastodon.user}.extraGroups = [ "redis-mastodon" ];})
     ];
 
     users.groups.${cfg.group}.members = lib.optional cfg.configureNginx config.services.nginx.user;
diff --git a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
index d3773cc9cf78..ccf995fccf3e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/photoprism.nix
@@ -12,17 +12,14 @@ let
     lib.mapAttrs (_: toString) cfg.settings
   );
 
-  manage =
-    let
-      setupEnv = lib.concatStringsSep "\n" (lib.mapAttrsToList (name: val: "export ${name}=${lib.escapeShellArg val}") env);
-    in
-    pkgs.writeShellScript "manage" ''
-      ${setupEnv}
-      eval "$(${config.systemd.package}/bin/systemctl show -pUID,MainPID photoprism.service | ${pkgs.gnused}/bin/sed "s/UID/ServiceUID/")"
-      exec ${pkgs.util-linux}/bin/nsenter \
-        -t $MainPID -m -S $ServiceUID -G $ServiceUID --wdns=${cfg.storagePath} \
-        ${cfg.package}/bin/photoprism "$@"
-    '';
+  manage = pkgs.writeShellScript "manage" ''
+    set -o allexport # Export the following env vars
+    ${lib.toShellVars env}
+    eval "$(${config.systemd.package}/bin/systemctl show -pUID,MainPID photoprism.service | ${pkgs.gnused}/bin/sed "s/UID/ServiceUID/")"
+    exec ${pkgs.util-linux}/bin/nsenter \
+      -t $MainPID -m -S $ServiceUID -G $ServiceUID --wdns=${cfg.storagePath} \
+      ${cfg.package}/bin/photoprism "$@"
+  '';
 in
 {
   meta.maintainers = with lib.maintainers; [ stunkymonkey ];
diff --git a/nixpkgs/nixos/modules/services/web-servers/garage.nix b/nixpkgs/nixos/modules/services/web-servers/garage.nix
index 47b4c6ab416e..48dd5b34757c 100644
--- a/nixpkgs/nixos/modules/services/web-servers/garage.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/garage.nix
@@ -30,7 +30,7 @@ in
     };
 
     logLevel = mkOption {
-      type = types.enum ([ "info" "debug" "trace" ]);
+      type = types.enum ([ "error" "warn" "info" "debug" "trace" ]);
       default = "info";
       example = "debug";
       description = lib.mdDoc "Garage log level, see <https://garagehq.deuxfleurs.fr/documentation/quick-start/#launching-the-garage-server> for examples.";
diff --git a/nixpkgs/nixos/modules/services/web-servers/ttyd.nix b/nixpkgs/nixos/modules/services/web-servers/ttyd.nix
index e545869ca432..14361df2bb66 100644
--- a/nixpkgs/nixos/modules/services/web-servers/ttyd.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/ttyd.nix
@@ -1,11 +1,17 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
 
   cfg = config.services.ttyd;
 
+  inherit (lib)
+    optionals
+    types
+    concatLists
+    mapAttrsToList
+    mkOption
+    ;
+
   # Command line arguments for the ttyd daemon
   args = [ "--port" (toString cfg.port) ]
          ++ optionals (cfg.socket != null) [ "--interface" cfg.socket ]
@@ -14,6 +20,7 @@ let
          ++ (concatLists (mapAttrsToList (_k: _v: [ "--client-option" "${_k}=${_v}" ]) cfg.clientOptions))
          ++ [ "--terminal-type" cfg.terminalType ]
          ++ optionals cfg.checkOrigin [ "--check-origin" ]
+         ++ optionals cfg.writeable [ "--writable" ] # the typo is correct
          ++ [ "--max-clients" (toString cfg.maxClients) ]
          ++ optionals (cfg.indexFile != null) [ "--index" cfg.indexFile ]
          ++ optionals cfg.enableIPv6 [ "--ipv6" ]
@@ -30,40 +37,40 @@ in
 
   options = {
     services.ttyd = {
-      enable = mkEnableOption (lib.mdDoc "ttyd daemon");
+      enable = lib.mkEnableOption ("ttyd daemon");
 
       port = mkOption {
         type = types.port;
         default = 7681;
-        description = lib.mdDoc "Port to listen on (use 0 for random port)";
+        description = "Port to listen on (use 0 for random port)";
       };
 
       socket = mkOption {
         type = types.nullOr types.path;
         default = null;
         example = "/var/run/ttyd.sock";
-        description = lib.mdDoc "UNIX domain socket path to bind.";
+        description = "UNIX domain socket path to bind.";
       };
 
       interface = mkOption {
         type = types.nullOr types.str;
         default = null;
         example = "eth0";
-        description = lib.mdDoc "Network interface to bind.";
+        description = "Network interface to bind.";
       };
 
       username = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = lib.mdDoc "Username for basic authentication.";
+        description = "Username for basic http authentication.";
       };
 
       passwordFile = mkOption {
         type = types.nullOr types.path;
         default = null;
         apply = value: if value == null then null else toString value;
-        description = lib.mdDoc ''
-          File containing the password to use for basic authentication.
+        description = ''
+          File containing the password to use for basic http authentication.
           For insecurely putting the password in the globally readable store use
           `pkgs.writeText "ttydpw" "MyPassword"`.
         '';
@@ -72,19 +79,46 @@ in
       signal = mkOption {
         type = types.ints.u8;
         default = 1;
-        description = lib.mdDoc "Signal to send to the command on session close.";
+        description = "Signal to send to the command on session close.";
+      };
+
+      entrypoint = mkOption {
+        type = types.listOf types.str;
+        default = [ "${pkgs.shadow}/bin/login" ];
+        defaultText = lib.literalExpression ''
+          [ "''${pkgs.shadow}/bin/login" ]
+        '';
+        example = lib.literalExpression ''
+          [ (lib.getExe pkgs.htop) ]
+        '';
+        description = "Which command ttyd runs.";
+        apply = lib.escapeShellArgs;
+      };
+
+      user = mkOption {
+        type = types.str;
+        # `login` needs to be run as root
+        default = "root";
+        description = "Which unix user ttyd should run as.";
+      };
+
+      writeable = mkOption {
+        type = types.nullOr types.bool;
+        default = null; # null causes an eval error, forcing the user to consider attack surface
+        example = true;
+        description = "Allow clients to write to the TTY.";
       };
 
       clientOptions = mkOption {
         type = types.attrsOf types.str;
         default = {};
-        example = literalExpression ''
+        example = lib.literalExpression ''
           {
             fontSize = "16";
             fontFamily = "Fira Code";
           }
         '';
-        description = lib.mdDoc ''
+        description = ''
           Attribute set of client options for xtermjs.
           <https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/>
         '';
@@ -93,50 +127,50 @@ in
       terminalType = mkOption {
         type = types.str;
         default = "xterm-256color";
-        description = lib.mdDoc "Terminal type to report.";
+        description = "Terminal type to report.";
       };
 
       checkOrigin = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc "Whether to allow a websocket connection from a different origin.";
+        description = "Whether to allow a websocket connection from a different origin.";
       };
 
       maxClients = mkOption {
         type = types.int;
         default = 0;
-        description = lib.mdDoc "Maximum clients to support (0, no limit)";
+        description = "Maximum clients to support (0, no limit)";
       };
 
       indexFile = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = lib.mdDoc "Custom index.html path";
+        description = "Custom index.html path";
       };
 
       enableIPv6 = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc "Whether or not to enable IPv6 support.";
+        description = "Whether or not to enable IPv6 support.";
       };
 
       enableSSL = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc "Whether or not to enable SSL (https) support.";
+        description = "Whether or not to enable SSL (https) support.";
       };
 
       certFile = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = lib.mdDoc "SSL certificate file path.";
+        description = "SSL certificate file path.";
       };
 
       keyFile = mkOption {
         type = types.nullOr types.path;
         default = null;
         apply = value: if value == null then null else toString value;
-        description = lib.mdDoc ''
+        description = ''
           SSL key file path.
           For insecurely putting the keyFile in the globally readable store use
           `pkgs.writeText "ttydKeyFile" "SSLKEY"`.
@@ -146,25 +180,27 @@ in
       caFile = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = lib.mdDoc "SSL CA file path for client certificate verification.";
+        description = "SSL CA file path for client certificate verification.";
       };
 
       logLevel = mkOption {
         type = types.int;
         default = 7;
-        description = lib.mdDoc "Set log level.";
+        description = "Set log level.";
       };
     };
   };
 
   ###### implementation
 
-  config = mkIf cfg.enable {
+  config = lib.mkIf cfg.enable {
 
     assertions =
       [ { assertion = cfg.enableSSL
             -> cfg.certFile != null && cfg.keyFile != null && cfg.caFile != null;
           message = "SSL is enabled for ttyd, but no certFile, keyFile or caFile has been specified."; }
+        { assertion = cfg.writeable != null;
+          message = "services.ttyd.writeable must be set"; }
         { assertion = ! (cfg.interface != null && cfg.socket != null);
           message = "Cannot set both interface and socket for ttyd."; }
         { assertion = (cfg.username != null) == (cfg.passwordFile != null);
@@ -177,21 +213,19 @@ in
       wantedBy = [ "multi-user.target" ];
 
       serviceConfig = {
-        # Runs login which needs to be run as root
-        # login: Cannot possibly work without effective root
-        User = "root";
+        User = cfg.user;
         LoadCredential = lib.optionalString (cfg.passwordFile != null) "TTYD_PASSWORD_FILE:${cfg.passwordFile}";
       };
 
       script = if cfg.passwordFile != null then ''
         PASSWORD=$(cat "$CREDENTIALS_DIRECTORY/TTYD_PASSWORD_FILE")
         ${pkgs.ttyd}/bin/ttyd ${lib.escapeShellArgs args} \
-          --credential ${escapeShellArg cfg.username}:"$PASSWORD" \
-          ${pkgs.shadow}/bin/login
+          --credential ${lib.escapeShellArg cfg.username}:"$PASSWORD" \
+          ${cfg.entrypoint}
       ''
       else ''
         ${pkgs.ttyd}/bin/ttyd ${lib.escapeShellArgs args} \
-          ${pkgs.shadow}/bin/login
+          ${cfg.entrypoint}
       '';
     };
   };
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
index 463c45675cee..fe39097a22e8 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/budgie.nix
@@ -39,6 +39,10 @@ let
     '';
     destination = "/share/gnome-background-properties/nixos.xml";
   };
+
+  budgie-control-center = pkgs.budgie.budgie-control-center.override {
+    enableSshSocket = config.services.openssh.startWhenNeeded;
+  };
 in {
   options = {
     services.xserver.desktopManager.budgie = {
@@ -114,7 +118,7 @@ in {
       [
         # Budgie Desktop.
         budgie.budgie-backgrounds
-        budgie.budgie-control-center
+        budgie-control-center
         (budgie.budgie-desktop-with-plugins.override { plugins = cfg.extraPlugins; })
         budgie.budgie-desktop-view
         budgie.budgie-screensaver
@@ -233,8 +237,8 @@ in {
     services.gvfs.enable = mkDefault true;
 
     # Register packages for DBus.
-    services.dbus.packages = with pkgs; [
-      budgie.budgie-control-center
+    services.dbus.packages = [
+      budgie-control-center
     ];
 
     # Register packages for udev.
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix
index 48741aa41d85..e3cb5cc3be2b 100644
--- a/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix
@@ -17,7 +17,7 @@ in
       { name = "icewm";
         start =
           ''
-            ${pkgs.icewm}/bin/icewm &
+            ${pkgs.icewm}/bin/icewm-session &
             waitPID=$!
           '';
       };
diff --git a/nixpkgs/nixos/modules/system/boot/kernel.nix b/nixpkgs/nixos/modules/system/boot/kernel.nix
index a46331ccd431..b0ac857feb4b 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel.nix
+++ b/nixpkgs/nixos/modules/system/boot/kernel.nix
@@ -81,6 +81,13 @@ in
             extraStructuredConfig.FOO = lib.kernel.yes;
             features.foo = true;
           }
+          {
+            name = "foo-ml-mbox";
+            patch = (fetchurl {
+              url = "https://lore.kernel.org/lkml/19700205182810.58382-1-email@domain/t.mbox.gz";
+              hash = "sha256-...";
+            });
+          }
         ]
       '';
       description = lib.mdDoc ''
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index e990aeea7a14..8f3f3612805f 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -621,6 +621,11 @@ in
             path the secret should have inside the initrd, the value
             is the path it should be copied from (or null for the same
             path inside and out).
+
+            Note that `nixos-rebuild switch` will generate the initrd
+            also for past generations, so if secrets are moved or deleted
+            you will also have to garbage collect the generations that
+            use those secrets.
           '';
         example = literalExpression
           ''
diff --git a/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix b/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix
index 000b18c01609..edc25784367a 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd/oomd.nix
@@ -49,15 +49,15 @@ in {
 
     systemd.slices."-".sliceConfig = lib.mkIf cfg.enableRootSlice {
       ManagedOOMMemoryPressure = "kill";
-      ManagedOOMMemoryPressureLimit = "80%";
+      ManagedOOMMemoryPressureLimit = lib.mkDefault "80%";
     };
     systemd.slices."system".sliceConfig = lib.mkIf cfg.enableSystemSlice {
       ManagedOOMMemoryPressure = "kill";
-      ManagedOOMMemoryPressureLimit = "80%";
+      ManagedOOMMemoryPressureLimit = lib.mkDefault "80%";
     };
     systemd.slices."user-".sliceConfig = lib.mkIf cfg.enableUserSlices {
       ManagedOOMMemoryPressure = "kill";
-      ManagedOOMMemoryPressureLimit = "80%";
+      ManagedOOMMemoryPressureLimit = lib.mkDefault "80%";
     };
     systemd.user.units."slice" = lib.mkIf cfg.enableUserSlices {
       text = ''
diff --git a/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py b/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py
index bf4ec791ecf7..bba454dd888d 100644
--- a/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py
+++ b/nixpkgs/nixos/modules/system/etc/build-composefs-dump.py
@@ -199,7 +199,8 @@ def main() -> None:
                         size=os.stat(source).st_size,
                         filetype=FileType.file,
                         mode=mode,
-                        payload=target,
+                        # payload needs to be relative path in this case
+                        payload=target.lstrip("/"),
                     )
             paths[target] = composefs_path
             add_leading_directories(target, attrs, paths)
diff --git a/nixpkgs/nixos/modules/virtualisation/docker.nix b/nixpkgs/nixos/modules/virtualisation/docker.nix
index b0d61ee06091..d4d34d13a94d 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker.nix
@@ -93,8 +93,18 @@ in
         default = null;
         description =
           lib.mdDoc ''
-            This option determines which Docker storage driver to use. By default
-            it let's docker automatically choose preferred storage driver.
+            This option determines which Docker
+            [storage driver](https://docs.docker.com/storage/storagedriver/select-storage-driver/)
+            to use.
+            By default it lets docker automatically choose the preferred storage
+            driver.
+            However, it is recommended to specify a storage driver explicitly, as
+            docker's default varies over versions.
+
+            ::: {.warning}
+            Changing the storage driver will cause any existing containers
+            and images to become inaccessible.
+            :::
           '';
       };
 
diff --git a/nixpkgs/nixos/modules/virtualisation/incus.nix b/nixpkgs/nixos/modules/virtualisation/incus.nix
index bbe5b48b95bb..3bbe0ba45851 100644
--- a/nixpkgs/nixos/modules/virtualisation/incus.nix
+++ b/nixpkgs/nixos/modules/virtualisation/incus.nix
@@ -97,6 +97,12 @@ in
           considered failed and systemd will attempt to restart it.
         '';
       };
+
+      ui = {
+        enable = lib.mkEnableOption (lib.mdDoc "(experimental) Incus UI");
+
+        package = lib.mkPackageOption pkgs [ "incus" "ui" ] { };
+      };
     };
   };
 
@@ -165,10 +171,12 @@ in
         "${config.boot.zfs.package}/lib/udev"
       ];
 
-      environment = {
+      environment = lib.mkMerge [ {
         # Override Path to the LXC template configuration directory
         INCUS_LXC_TEMPLATE_CONFIG = "${pkgs.lxcfs}/share/lxc/config";
-      };
+      } (lib.mkIf (cfg.ui.enable) {
+        "INCUS_UI" = cfg.ui.package;
+      }) ];
 
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/incusd --group incus-admin";