about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/development/writing-nixos-tests.section.md2
-rw-r--r--nixos/doc/manual/installation/installing.chapter.md3
-rw-r--r--nixos/doc/manual/release-notes/rl-2405.section.md17
-rw-r--r--nixos/lib/make-iso9660-image.nix25
-rw-r--r--nixos/lib/make-iso9660-image.sh5
-rw-r--r--nixos/modules/config/no-x-libs.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix11
-rw-r--r--nixos/modules/programs/clash-verge.nix7
-rw-r--r--nixos/modules/programs/gnupg.nix42
-rw-r--r--nixos/modules/programs/wayland/sway.nix5
-rw-r--r--nixos/modules/services/backup/bacula.nix222
-rw-r--r--nixos/modules/services/continuous-integration/hydra/default.nix34
-rw-r--r--nixos/modules/services/databases/lldap.nix17
-rw-r--r--nixos/modules/services/desktop-managers/plasma6.nix (renamed from nixos/modules/services/x11/desktop-managers/plasma6.nix)18
-rw-r--r--nixos/modules/services/development/hoogle.nix15
-rw-r--r--nixos/modules/services/hardware/fwupd.nix4
-rw-r--r--nixos/modules/services/matrix/matrix-sliding-sync.nix3
-rw-r--r--nixos/modules/services/monitoring/scrutiny.nix9
-rw-r--r--nixos/modules/services/networking/murmur.nix2
-rw-r--r--nixos/modules/services/networking/nebula.nix34
-rw-r--r--nixos/modules/services/networking/networkmanager.nix3
-rw-r--r--nixos/modules/services/networking/unbound.nix9
-rw-r--r--nixos/modules/services/security/esdm.nix101
-rw-r--r--nixos/modules/services/security/yubikey-agent.nix14
-rw-r--r--nixos/modules/services/web-apps/gotosocial.nix2
-rw-r--r--nixos/modules/services/web-servers/stargazer.nix8
-rw-r--r--nixos/modules/services/x11/desktop-managers/deepin.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/lxqt.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix1
-rw-r--r--nixos/modules/services/x11/xserver.nix2
-rw-r--r--nixos/modules/system/boot/binfmt.nix1
-rw-r--r--nixos/modules/system/boot/systemd.nix2
-rw-r--r--nixos/modules/system/boot/uki.nix2
-rw-r--r--nixos/modules/virtualisation/amazon-ec2-amis.nix68
-rw-r--r--nixos/modules/virtualisation/incus.nix13
-rw-r--r--nixos/tests/all-tests.nix2
-rw-r--r--nixos/tests/incus/container.nix1
-rw-r--r--nixos/tests/incus/default.nix1
-rw-r--r--nixos/tests/incus/lxd-to-incus.nix1
-rw-r--r--nixos/tests/incus/openvswitch.nix65
-rw-r--r--nixos/tests/incus/preseed.nix1
-rw-r--r--nixos/tests/incus/socket-activated.nix1
-rw-r--r--nixos/tests/incus/ui.nix1
-rw-r--r--nixos/tests/incus/virtual-machine.nix1
-rw-r--r--nixos/tests/miriway.nix4
-rw-r--r--nixos/tests/nebula.nix6
-rw-r--r--nixos/tests/ollama.nix56
-rw-r--r--nixos/tests/pass-secret-service.nix1
-rw-r--r--nixos/tests/pgvecto-rs.nix76
-rw-r--r--nixos/tests/privoxy.nix13
-rw-r--r--nixos/tests/web-apps/gotosocial.nix2
53 files changed, 734 insertions, 207 deletions
diff --git a/nixos/doc/manual/development/writing-nixos-tests.section.md b/nixos/doc/manual/development/writing-nixos-tests.section.md
index 84b247fd2042..50886376c240 100644
--- a/nixos/doc/manual/development/writing-nixos-tests.section.md
+++ b/nixos/doc/manual/development/writing-nixos-tests.section.md
@@ -261,7 +261,7 @@ added using the parameter `extraPythonPackages`. For example, you could add
 
   testScript = ''
     import numpy as np
-    assert str(np.zeros(4) == "array([0., 0., 0., 0.])")
+    assert str(np.zeros(4)) == "[0. 0. 0. 0.]"
   '';
 }
 ```
diff --git a/nixos/doc/manual/installation/installing.chapter.md b/nixos/doc/manual/installation/installing.chapter.md
index 815bcc071cd9..c7deb07352f1 100644
--- a/nixos/doc/manual/installation/installing.chapter.md
+++ b/nixos/doc/manual/installation/installing.chapter.md
@@ -272,6 +272,9 @@ update /etc/fstab.
     # parted /dev/sda -- mkpart ESP fat32 1MB 512MB
     # parted /dev/sda -- set 3 esp on
     ```
+    ::: {.note}
+    In case you decided to not create a swap partition, replace `3` by `2`. To be sure of the id number of ESP, run `parted --list`.
+    :::
 
 Once complete, you can follow with
 [](#sec-installation-manual-partitioning-formatting).
diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md
index 665e8590fc42..22689868cf02 100644
--- a/nixos/doc/manual/release-notes/rl-2405.section.md
+++ b/nixos/doc/manual/release-notes/rl-2405.section.md
@@ -42,6 +42,12 @@ In addition to numerous new and upgraded packages, this release has the followin
 - A new option `system.etc.overlay.enable` was added. If enabled, `/etc` is
   mounted via an overlayfs instead of being created by a custom perl script.
 
+- NixOS AMIs are now uploaded regularly to a new AWS Account.
+  Instructions on how to use them can be found on <https://nixos.github.io/amis>.
+  We are working on integration the data into the NixOS homepage.
+  The list in `nixos/modules/virtualisation/amazon-ec2-amis.nix` will stop
+  being updated and will be removed in the future.
+
 - It is now possible to have a completely perlless system (i.e. a system
   without perl). Previously, the NixOS activation depended on two perl scripts
   which can now be replaced via an opt-in mechanism. To make your system
@@ -121,6 +127,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
 
 - The `power.ups` module now generates `upsd.conf`, `upsd.users` and `upsmon.conf` automatically from a set of new configuration options. This breaks compatibility with existing `power.ups` setups where these files were created manually. Back up these files before upgrading NixOS.
 
+- `unrar` was updated to v7. See [changelog](https://www.rarlab.com/unrar7notes.htm) for more information.
+
 - `k3s` was updated to [v1.29](https://github.com/k3s-io/k3s/releases/tag/v1.29.1%2Bk3s2). See [changelog and upgrade notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.29.md#urgent-upgrade-notes) for more information.
 
 - `k9s` was updated to v0.31. There have been various breaking changes in the config file format,
@@ -129,6 +137,12 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
   [v0.31](https://github.com/derailed/k9s/releases/tag/v0.31.0) for details. It is recommended
   to back up your current configuration and let k9s recreate the new base configuration.
 
+- NixOS AMIs are now uploaded regularly to a new AWS Account.
+  Instructions on how to use them can be found on <https://nixos.github.io/amis>.
+  We are working on integration the data into the NixOS homepage.
+  The list in `nixos/modules/virtualisation/amazon-ec2-amis.nix` will stop
+  being updated and will be removed in the future.
+
 - The option `services.postgresql.ensureUsers._.ensurePermissions` has been removed as it's
   not declarative and is broken with newer postgresql versions. Consider using
   [](#opt-services.postgresql.ensureUsers._.ensureDBOwnership)
@@ -375,6 +389,9 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
 
 - [Nginx virtual hosts](#opt-services.nginx.virtualHosts) using `forceSSL` or
   `globalRedirect` can now have redirect codes other than 301 through
+
+- `bacula` now allows to configure `TLS` for encrypted communication.
+
   `redirectCode`.
 
 - `libjxl` 0.9.0 [dropped support for the butteraugli API](https://github.com/libjxl/libjxl/pull/2576). You will no longer be able to set `enableButteraugli` on `libaom`.
diff --git a/nixos/lib/make-iso9660-image.nix b/nixos/lib/make-iso9660-image.nix
index 2f7dcf519a16..ec520f570682 100644
--- a/nixos/lib/make-iso9660-image.nix
+++ b/nixos/lib/make-iso9660-image.nix
@@ -1,4 +1,4 @@
-{ stdenv, closureInfo, xorriso, syslinux, libossp_uuid
+{ lib, stdenv, callPackage, closureInfo, xorriso, syslinux, libossp_uuid, squashfsTools
 
 , # The file name of the resulting ISO image.
   isoName ? "cd.iso"
@@ -16,6 +16,17 @@
   # symlink to `object' that will be added to the CD.
   storeContents ? []
 
+, # In addition to `contents', the closure of the store paths listed
+  # in `squashfsContents' is compressed as squashfs and the result is
+  # placed in /nix-store.squashfs on the CD.
+  # FIXME: This is a performance optimization to avoid Hydra copying
+  # the squashfs between builders and should be removed when Hydra
+  # is smarter about scheduling.
+  squashfsContents ? []
+
+, # Compression settings for squashfs
+  squashfsCompression ? "xz -Xdict-size 100%"
+
 , # Whether this should be an El-Torito bootable CD.
   bootable ? false
 
@@ -45,12 +56,20 @@ assert bootable -> bootImage != "";
 assert efiBootable -> efiBootImage != "";
 assert usbBootable -> isohybridMbrImage != "";
 
+let
+  needSquashfs = squashfsContents != [];
+  makeSquashfsDrv = callPackage ./make-squashfs.nix {
+    storeContents = squashfsContents;
+    comp = squashfsCompression;
+  };
+in
 stdenv.mkDerivation {
   name = isoName;
   __structuredAttrs = true;
 
   buildCommandPath = ./make-iso9660-image.sh;
-  nativeBuildInputs = [ xorriso syslinux zstd libossp_uuid ];
+  nativeBuildInputs = [ xorriso syslinux zstd libossp_uuid ]
+    ++ lib.optionals needSquashfs makeSquashfsDrv.nativeBuildInputs;
 
   inherit isoName bootable bootImage compressImage volumeID efiBootImage efiBootable isohybridMbrImage usbBootable;
 
@@ -60,6 +79,8 @@ stdenv.mkDerivation {
   objects = map (x: x.object) storeContents;
   symlinks = map (x: x.symlink) storeContents;
 
+  squashfsCommand = lib.optionalString needSquashfs makeSquashfsDrv.buildCommand;
+
   # For obtaining the closure of `storeContents'.
   closureInfo = closureInfo { rootPaths = map (x: x.object) storeContents; };
 }
diff --git a/nixos/lib/make-iso9660-image.sh b/nixos/lib/make-iso9660-image.sh
index 34febe9cfe0e..5881195e461f 100644
--- a/nixos/lib/make-iso9660-image.sh
+++ b/nixos/lib/make-iso9660-image.sh
@@ -68,6 +68,11 @@ for i in $(< $closureInfo/store-paths); do
     addPath "${i:1}" "$i"
 done
 
+# If needed, build a squashfs and add that
+if [[ -n "$squashfsCommand" ]]; then
+    (out="nix-store.squashfs" eval "$squashfsCommand")
+    addPath "nix-store.squashfs" "nix-store.squashfs"
+fi
 
 # Also include a manifest of the closures in a format suitable for
 # nix-store --load-db.
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix
index 870b3fe77cca..fea6e0c4110b 100644
--- a/nixos/modules/config/no-x-libs.nix
+++ b/nixos/modules/config/no-x-libs.nix
@@ -66,7 +66,7 @@ with lib;
       networkmanager-sstp = super.networkmanager-vpnc.override { withGnome = false; };
       networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
       pango = super.pango.override { x11Support = false; };
-      pinentry = super.pinentry.override { enabledFlavors = [ "curses" "tty" "emacs" ]; withLibsecret = false; };
+      pinentry-curses = super.pinentry-curses.override { withLibsecret = false; };
       pipewire = super.pipewire.override { vulkanSupport = false; x11Support = false; };
       pythonPackagesExtensions = super.pythonPackagesExtensions ++ [
         (python-final: python-prev: {
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 6adb94e09aff..f5b6af3a6b7f 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -811,12 +811,6 @@ in
       optional config.isoImage.includeSystemBuildDependencies
         config.system.build.toplevel.drvPath;
 
-    # Create the squashfs image that contains the Nix store.
-    system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
-      storeContents = config.isoImage.storeContents;
-      comp = config.isoImage.squashfsCompression;
-    };
-
     # Individual files to be included on the CD, outside of the Nix
     # store on the CD.
     isoImage.contents =
@@ -827,9 +821,6 @@ in
         { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
           target = "/boot/" + config.system.boot.loader.initrdFile;
         }
-        { source = config.system.build.squashfsStore;
-          target = "/nix-store.squashfs";
-        }
         { source = pkgs.writeText "version" config.system.nixos.label;
           target = "/version.txt";
         }
@@ -878,6 +869,8 @@ in
       bootable = config.isoImage.makeBiosBootable;
       bootImage = "/isolinux/isolinux.bin";
       syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null;
+      squashfsContents = config.isoImage.storeContents;
+      squashfsCompression = config.isoImage.squashfsCompression;
     } // optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) {
       usbBootable = true;
       isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
diff --git a/nixos/modules/programs/clash-verge.nix b/nixos/modules/programs/clash-verge.nix
index 57a1c0377edb..e1afafa7cadc 100644
--- a/nixos/modules/programs/clash-verge.nix
+++ b/nixos/modules/programs/clash-verge.nix
@@ -3,6 +3,7 @@
 {
   options.programs.clash-verge = {
     enable = lib.mkEnableOption (lib.mdDoc "Clash Verge");
+    package = lib.mkPackageOption pkgs "clash-verge" {};
     autoStart = lib.mkEnableOption (lib.mdDoc "Clash Verge auto launch");
     tunMode = lib.mkEnableOption (lib.mdDoc "Clash Verge TUN mode");
   };
@@ -14,10 +15,10 @@
     lib.mkIf cfg.enable {
 
       environment.systemPackages = [
-        pkgs.clash-verge
+        cfg.package
         (lib.mkIf cfg.autoStart (pkgs.makeAutostartItem {
           name = "clash-verge";
-          package = pkgs.clash-verge;
+          package = cfg.package;
         }))
       ];
 
@@ -25,7 +26,7 @@
         owner = "root";
         group = "root";
         capabilities = "cap_net_bind_service,cap_net_admin=+ep";
-        source = "${lib.getExe pkgs.clash-verge}";
+        source = "${lib.getExe cfg.package}";
       };
     };
 
diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix
index 179d2de87cc5..66be1f247fbd 100644
--- a/nixos/modules/programs/gnupg.nix
+++ b/nixos/modules/programs/gnupg.nix
@@ -1,8 +1,7 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit (lib) mkRemovedOptionModule mkOption mkPackageOption types mkIf optionalString;
 
   cfg = config.programs.gnupg;
 
@@ -26,8 +25,10 @@ let
       "curses";
 
 in
-
 {
+  imports = [
+    (mkRemovedOptionModule [ "programs" "gnupg" "agent" "pinentryFlavor" ] "Use programs.gnupg.agent.pinentryPackage instead")
+  ];
 
   options.programs.gnupg = {
     package = mkPackageOption pkgs "gnupg" { };
@@ -66,17 +67,17 @@ in
       '';
     };
 
-    agent.pinentryFlavor = mkOption {
-      type = types.nullOr (types.enum pkgs.pinentry.flavors);
-      example = "gnome3";
-      default = defaultPinentryFlavor;
-      defaultText = literalMD ''matching the configured desktop environment'';
+    agent.pinentryPackage = mkOption {
+      type = types.nullOr types.package;
+      example = lib.literalMD "pkgs.pinentry-gnome3";
+      default = pkgs.pinentry-curses;
+      defaultText = lib.literalMD "matching the configured desktop environment or `pkgs.pinentry-curses`";
       description = lib.mdDoc ''
-        Which pinentry interface to use. If not null, the path to the
-        pinentry binary will be set in /etc/gnupg/gpg-agent.conf.
-        If not set at all, it'll pick an appropriate flavor depending on the
-        system configuration (qt flavor for lxqt and plasma5, gtk2 for xfce
-        4.12, gnome3 on all other systems with X enabled, ncurses otherwise).
+        Which pinentry package to use. The path to the mainProgram as defined in
+        the package's meta attriutes will be set in /etc/gnupg/gpg-agent.conf.
+        If not set by the user, it'll pick an appropriate flavor depending on the
+        system configuration (qt flavor for lxqt and plasma5, gtk2 for xfce,
+        gnome3 on all other systems with X enabled, curses otherwise).
       '';
     };
 
@@ -102,9 +103,8 @@ in
   };
 
   config = mkIf cfg.agent.enable {
-    programs.gnupg.agent.settings = {
-      pinentry-program = lib.mkIf (cfg.agent.pinentryFlavor != null)
-        "${pkgs.pinentry.${cfg.agent.pinentryFlavor}}/bin/pinentry";
+    programs.gnupg.agent.settings = mkIf (cfg.agent.pinentryPackage != null) {
+      pinentry-program = lib.getExe cfg.agent.pinentryPackage;
     };
 
     environment.etc."gnupg/gpg-agent.conf".source =
@@ -207,9 +207,9 @@ in
       wantedBy = [ "sockets.target" ];
     };
 
-    services.dbus.packages = mkIf (cfg.agent.pinentryFlavor == "gnome3") [ pkgs.gcr ];
+    services.dbus.packages = mkIf (lib.elem "gnome3" (cfg.agent.pinentryPackage.flavors or [])) [ pkgs.gcr ];
 
-    environment.systemPackages = with pkgs; [ cfg.package ];
+    environment.systemPackages = [ cfg.package ];
 
     environment.interactiveShellInit = ''
       # Bind gpg-agent to this TTY if gpg commands are used.
@@ -230,12 +230,10 @@ in
     '';
 
     assertions = [
-      { assertion = cfg.agent.enableSSHSupport -> !config.programs.ssh.startAgent;
+      {
+        assertion = cfg.agent.enableSSHSupport -> !config.programs.ssh.startAgent;
         message = "You can't use ssh-agent and GnuPG agent with SSH support enabled at the same time!";
       }
     ];
   };
-
-  # uses attributes of the linked package
-  meta.buildDocsInSandbox = false;
 }
diff --git a/nixos/modules/programs/wayland/sway.nix b/nixos/modules/programs/wayland/sway.nix
index ca2503ae5da7..2bd297af5254 100644
--- a/nixos/modules/programs/wayland/sway.nix
+++ b/nixos/modules/programs/wayland/sway.nix
@@ -152,6 +152,7 @@ in {
             '';
           }
         ];
+
         environment = {
           systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
           # Needed for the default wallpaper:
@@ -166,8 +167,12 @@ in {
             "sway/config".source = mkOptionDefault "${cfg.package}/etc/sway/config";
           };
         };
+
+        programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;
+
         # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
         xdg.portal.config.sway.default = mkDefault [ "wlr" "gtk" ];
+
         # To make a Sway session available if a display manager like SDDM is enabled:
         services.xserver.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ]; }
       (import ./wayland-session.nix { inherit lib pkgs; })
diff --git a/nixos/modules/services/backup/bacula.nix b/nixos/modules/services/backup/bacula.nix
index 5a75a46e5259..39975adf5909 100644
--- a/nixos/modules/services/backup/bacula.nix
+++ b/nixos/modules/services/backup/bacula.nix
@@ -4,11 +4,36 @@
 # TODO: test configuration when building nixexpr (use -t parameter)
 # TODO: support sqlite3 (it's deprecate?) and mysql
 
-with lib;
 
 let
+  inherit (lib)
+    concatStringsSep
+    literalExpression
+    mapAttrsToList
+    mdDoc
+    mkIf
+    mkOption
+    optional
+    optionalString
+    types
+    ;
   libDir = "/var/lib/bacula";
 
+  yes_no = bool: if bool then "yes" else "no";
+  tls_conf = tls_cfg: optionalString tls_cfg.enable (
+    concatStringsSep
+      "\n"
+      (
+      ["TLS Enable = yes;"]
+      ++ optional (tls_cfg.require != null) "TLS Require = ${yes_no tls_cfg.require};"
+      ++ optional (tls_cfg.certificate != null) ''TLS Certificate = "${tls_cfg.certificate}";''
+      ++ [''TLS Key = "${tls_cfg.key}";'']
+      ++ optional (tls_cfg.verifyPeer != null) "TLS Verify Peer = ${yes_no tls_cfg.verifyPeer};"
+      ++ optional (tls_cfg.allowedCN != [ ]) "TLS Allowed CN = ${concatStringsSep " " (tls_cfg.allowedCN)};"
+      ++ optional (tls_cfg.caCertificateFile != null) ''TLS CA Certificate File = "${tls_cfg.caCertificateFile}";''
+      )
+  );
+
   fd_cfg = config.services.bacula-fd;
   fd_conf = pkgs.writeText "bacula-fd.conf"
     ''
@@ -18,6 +43,7 @@ let
         WorkingDirectory = ${libDir};
         Pid Directory = /run;
         ${fd_cfg.extraClientConfig}
+        ${tls_conf fd_cfg.tls}
       }
 
       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
@@ -25,6 +51,7 @@ let
         Name = "${name}";
         Password = ${value.password};
         Monitor = ${value.monitor};
+        ${tls_conf value.tls}
       }
       '') fd_cfg.director)}
 
@@ -44,6 +71,7 @@ let
         WorkingDirectory = ${libDir};
         Pid Directory = /run;
         ${sd_cfg.extraStorageConfig}
+        ${tls_conf sd_cfg.tls}
       }
 
       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
@@ -70,6 +98,7 @@ let
         Name = "${name}";
         Password = ${value.password};
         Monitor = ${value.monitor};
+        ${tls_conf value.tls}
       }
       '') sd_cfg.director)}
 
@@ -90,6 +119,7 @@ let
       Working Directory = ${libDir};
       Pid Directory = /run/;
       QueryFile = ${pkgs.bacula}/etc/query.sql;
+      ${tls_conf dir_cfg.tls}
       ${dir_cfg.extraDirectorConfig}
     }
 
@@ -108,13 +138,99 @@ let
     ${dir_cfg.extraConfig}
     '';
 
-  directorOptions = {...}:
+  linkOption = name: destination: "[${name}](#opt-${builtins.replaceStrings [ "<" ">"] ["_" "_"] destination})";
+  tlsLink = destination: submodulePath: linkOption "${submodulePath}.${destination}" "${submodulePath}.${destination}";
+
+  tlsOptions = submodulePath: {...}:
+  {
+    options = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = mdDoc ''
+          Specifies if TLS should be enabled.
+          If this set to `false` TLS will be completely disabled, even if ${tlsLink "tls.require" submodulePath} is true.
+        '';
+      };
+      require = mkOption {
+        type = types.nullOr types.bool;
+        default = null;
+        description = mdDoc ''
+          Require TLS or TLS-PSK encryption.
+          This directive is ignored unless one of ${tlsLink "tls.enable" submodulePath} is true or TLS PSK Enable is set to `yes`.
+          If TLS is not required while TLS or TLS-PSK are enabled, then the Bacula component
+          will connect with other components either with or without TLS or TLS-PSK
+
+          If ${tlsLink "tls.enable" submodulePath} or TLS-PSK is enabled and TLS is required, then the Bacula
+          component will refuse any connection request that does not use TLS.
+        '';
+      };
+      certificate = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = mdDoc ''
+          The full path to the PEM encoded TLS certificate.
+          It will be used as either a client or server certificate,
+          depending on the connection direction.
+          This directive is required in a server context, but it may
+          not be specified in a client context if ${tlsLink "tls.verifyPeer" submodulePath} is
+          `false` in the corresponding server context.
+        '';
+      };
+      key = mkOption {
+        type = types.path;
+        description = mdDoc ''
+          The path of a PEM encoded TLS private key.
+          It must correspond to the TLS certificate.
+        '';
+      };
+      verifyPeer = mkOption {
+        type = types.nullOr types.bool;
+        default = null;
+        description = mdDoc ''
+          Verify peer certificate.
+          Instructs server to request and verify the client's X.509 certificate.
+          Any client certificate signed by a known-CA will be accepted.
+          Additionally, the client's X509 certificate Common Name must meet the value of the Address directive.
+          If ${tlsLink "tls.allowedCN" submodulePath} is used,
+          the client's x509 certificate Common Name must also correspond to
+          one of the CN specified in the ${tlsLink "tls.allowedCN" submodulePath} directive.
+          This directive is valid only for a server and not in client context.
+
+          Standard from Bacula is `true`.
+        '';
+      };
+      allowedCN = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        description = mdDoc ''
+          Common name attribute of allowed peer certificates.
+          This directive is valid for a server and in a client context.
+          If this directive is specified, the peer certificate will be verified against this list.
+          In the case this directive is configured on a server side, the allowed
+          CN list will not be checked if ${tlsLink "tls.verifyPeer" submodulePath} is false.
+        '';
+      };
+      caCertificateFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = mdDoc ''
+          The path specifying a PEM encoded TLS CA certificate(s).
+          Multiple certificates are permitted in the file.
+          One of TLS CA Certificate File or TLS CA Certificate Dir are required in a server context, unless
+          ${tlsLink "tls.verifyPeer" submodulePath} is false, and are always required in a client context.
+        '';
+      };
+    };
+  };
+
+  directorOptions = submodulePath:{...}:
   {
     options = {
       password = mkOption {
         type = types.str;
         # TODO: required?
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Specifies the password that must be supplied for the default Bacula
           Console to be authorized. The same password must appear in the
           Director resource of the Console configuration file. For added
@@ -135,7 +251,7 @@ let
         type = types.enum [ "no" "yes" ];
         default = "no";
         example = "yes";
-        description = lib.mdDoc ''
+        description = mdDoc ''
           If Monitor is set to `no`, this director will have
           full access to this Storage daemon. If Monitor is set to
           `yes`, this director will only be able to fetch the
@@ -146,6 +262,13 @@ let
           security problems.
         '';
       };
+
+      tls = mkOption {
+        type = types.submodule (tlsOptions "${submodulePath}.director.<name>");
+        description = mdDoc ''
+          TLS Options for the Director in this Configuration.
+        '';
+      };
     };
   };
 
@@ -154,7 +277,7 @@ let
     options = {
       changerDevice = mkOption {
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           The specified name-string must be the generic SCSI device name of the
           autochanger that corresponds to the normal read/write Archive Device
           specified in the Device resource. This generic SCSI device name
@@ -173,7 +296,7 @@ let
 
       changerCommand = mkOption {
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           The name-string specifies an external program to be called that will
           automatically change volumes as required by Bacula. Normally, this
           directive will be specified only in the AutoChanger resource, which
@@ -195,14 +318,14 @@ let
       };
 
       devices = mkOption {
-        description = lib.mdDoc "";
+        description = mdDoc "";
         type = types.listOf types.str;
       };
 
       extraAutochangerConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Autochanger directive.
         '';
         example = ''
@@ -219,7 +342,7 @@ let
       archiveDevice = mkOption {
         # TODO: required?
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           The specified name-string gives the system file name of the storage
           device managed by this storage daemon. This will usually be the
           device file name of a removable storage device (tape drive), for
@@ -236,7 +359,7 @@ let
       mediaType = mkOption {
         # TODO: required?
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           The specified name-string names the type of media supported by this
           device, for example, `DLT7000`. Media type names are
           arbitrary in that you set them to anything you want, but they must be
@@ -274,7 +397,7 @@ let
       extraDeviceConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Device directive.
         '';
         example = ''
@@ -295,7 +418,7 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Whether to enable the Bacula File Daemon.
         '';
       };
@@ -304,7 +427,7 @@ in {
         default = "${config.networking.hostName}-fd";
         defaultText = literalExpression ''"''${config.networking.hostName}-fd"'';
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           The client name that must be used by the Director when connecting.
           Generally, it is a good idea to use a name related to the machine so
           that error messages can be easily identified if you have multiple
@@ -315,7 +438,7 @@ in {
       port = mkOption {
         default = 9102;
         type = types.port;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           This specifies the port number on which the Client listens for
           Director connections. It must agree with the FDPort specified in
           the Client resource of the Director's configuration file.
@@ -324,16 +447,26 @@ in {
 
       director = mkOption {
         default = {};
-        description = lib.mdDoc ''
+        description = mdDoc ''
           This option defines director resources in Bacula File Daemon.
         '';
-        type = with types; attrsOf (submodule directorOptions);
+        type = types.attrsOf (types.submodule (directorOptions "services.bacula-fd"));
       };
 
+
+      tls = mkOption {
+        type = types.submodule (tlsOptions "services.bacula-fd");
+        default = { };
+        description = mdDoc ''
+          TLS Options for the File Daemon.
+          Important notice: The backup won't be encrypted.
+        '';
+       };
+
       extraClientConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Client directive.
         '';
         example = ''
@@ -345,7 +478,7 @@ in {
       extraMessagesConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Messages directive.
         '';
         example = ''
@@ -358,7 +491,7 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Whether to enable Bacula Storage Daemon.
         '';
       };
@@ -367,7 +500,7 @@ in {
         default = "${config.networking.hostName}-sd";
         defaultText = literalExpression ''"''${config.networking.hostName}-sd"'';
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Specifies the Name of the Storage daemon.
         '';
       };
@@ -375,7 +508,7 @@ in {
       port = mkOption {
         default = 9103;
         type = types.port;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Specifies port number on which the Storage daemon listens for
           Director connections.
         '';
@@ -383,32 +516,32 @@ in {
 
       director = mkOption {
         default = {};
-        description = lib.mdDoc ''
+        description = mdDoc ''
           This option defines Director resources in Bacula Storage Daemon.
         '';
-        type = with types; attrsOf (submodule directorOptions);
+        type = types.attrsOf (types.submodule (directorOptions "services.bacula-sd"));
       };
 
       device = mkOption {
         default = {};
-        description = lib.mdDoc ''
+        description = mdDoc ''
           This option defines Device resources in Bacula Storage Daemon.
         '';
-        type = with types; attrsOf (submodule deviceOptions);
+        type = types.attrsOf (types.submodule deviceOptions);
       };
 
       autochanger = mkOption {
         default = {};
-        description = lib.mdDoc ''
+        description = mdDoc ''
           This option defines Autochanger resources in Bacula Storage Daemon.
         '';
-        type = with types; attrsOf (submodule autochangerOptions);
+        type = types.attrsOf (types.submodule autochangerOptions);
       };
 
       extraStorageConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Storage directive.
         '';
         example = ''
@@ -420,13 +553,21 @@ in {
       extraMessagesConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Messages directive.
         '';
         example = ''
           console = all
         '';
       };
+      tls = mkOption {
+        type = types.submodule (tlsOptions "services.bacula-sd");
+        default = { };
+        description = mdDoc ''
+          TLS Options for the Storage Daemon.
+          Important notice: The backup won't be encrypted.
+        '';
+       };
 
     };
 
@@ -434,7 +575,7 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Whether to enable Bacula Director Daemon.
         '';
       };
@@ -443,7 +584,7 @@ in {
         default = "${config.networking.hostName}-dir";
         defaultText = literalExpression ''"''${config.networking.hostName}-dir"'';
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           The director name used by the system administrator. This directive is
           required.
         '';
@@ -452,7 +593,7 @@ in {
       port = mkOption {
         default = 9101;
         type = types.port;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Specify the port (a positive integer) on which the Director daemon
           will listen for Bacula Console connections. This same port number
           must be specified in the Director resource of the Console
@@ -465,7 +606,7 @@ in {
       password = mkOption {
         # TODO: required?
         type = types.str;
-        description = lib.mdDoc ''
+        description = mdDoc ''
            Specifies the password that must be supplied for a Director.
         '';
       };
@@ -473,7 +614,7 @@ in {
       extraMessagesConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Messages directive.
         '';
         example = ''
@@ -484,7 +625,7 @@ in {
       extraDirectorConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration to be passed in Director directive.
         '';
         example = ''
@@ -496,13 +637,22 @@ in {
       extraConfig = mkOption {
         default = "";
         type = types.lines;
-        description = lib.mdDoc ''
+        description = mdDoc ''
           Extra configuration for Bacula Director Daemon.
         '';
         example = ''
           TODO
         '';
       };
+
+      tls = mkOption {
+        type = types.submodule (tlsOptions "services.bacula-dir");
+        default = { };
+        description = mdDoc ''
+          TLS Options for the Director.
+          Important notice: The backup won't be encrypted.
+        '';
+       };
     };
   };
 
diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix
index b1d44e67658b..10e1f0532c84 100644
--- a/nixos/modules/services/continuous-integration/hydra/default.nix
+++ b/nixos/modules/services/continuous-integration/hydra/default.nix
@@ -178,6 +178,24 @@ in
         description = lib.mdDoc "Whether to run the server in debug mode.";
       };
 
+      maxServers = mkOption {
+        type = types.int;
+        default = 25;
+        description = lib.mdDoc "Maximum number of starman workers to spawn.";
+      };
+
+      minSpareServers = mkOption {
+        type = types.int;
+        default = 4;
+        description = lib.mdDoc "Minimum number of spare starman workers to keep.";
+      };
+
+      maxSpareServers = mkOption {
+        type = types.int;
+        default = 5;
+        description = lib.mdDoc "Maximum number of spare starman workers to keep.";
+      };
+
       extraConfig = mkOption {
         type = types.lines;
         description = lib.mdDoc "Extra lines for the Hydra configuration.";
@@ -224,6 +242,16 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = cfg.maxServers != 0 && cfg.maxSpareServers != 0 && cfg.minSpareServers != 0;
+        message = "services.hydra.{minSpareServers,maxSpareServers,minSpareServers} cannot be 0";
+      }
+      {
+        assertion = cfg.minSpareServers < cfg.maxSpareServers;
+        message = "services.hydra.minSpareServers cannot be bigger than servives.hydra.maxSpareServers";
+      }
+    ];
 
     users.groups.hydra = {
       gid = config.ids.gids.hydra;
@@ -258,7 +286,7 @@ in
         using_frontend_proxy = 1
         base_uri = ${cfg.hydraURL}
         notification_sender = ${cfg.notificationSender}
-        max_servers = 25
+        max_servers = ${toString cfg.maxServers}
         ${optionalString (cfg.logo != null) ''
           hydra_logo = ${cfg.logo}
         ''}
@@ -359,8 +387,8 @@ in
         serviceConfig =
           { ExecStart =
               "@${hydra-package}/bin/hydra-server hydra-server -f -h '${cfg.listenHost}' "
-              + "-p ${toString cfg.port} --max_spare_servers 5 --max_servers 25 "
-              + "--max_requests 100 ${optionalString cfg.debugServer "-d"}";
+              + "-p ${toString cfg.port} --min_spare_servers ${toString cfg.minSpareServers} --max_spare_servers ${toString cfg.maxSpareServers} "
+              + "--max_servers ${toString cfg.maxServers} --max_requests 100 ${optionalString cfg.debugServer "-d"}";
             User = "hydra-www";
             PermissionsStartOnly = true;
             Restart = "always";
diff --git a/nixos/modules/services/databases/lldap.nix b/nixos/modules/services/databases/lldap.nix
index e821da8e58aa..033de7af886f 100644
--- a/nixos/modules/services/databases/lldap.nix
+++ b/nixos/modules/services/databases/lldap.nix
@@ -107,10 +107,25 @@ in
       wants = [ "network-online.target" ];
       after = [ "network-online.target" ];
       wantedBy = [ "multi-user.target" ];
+      # lldap defaults to a hardcoded `jwt_secret` value if none is provided, which is bad, because
+      # an attacker could create a valid admin jwt access token fairly trivially.
+      # Because there are 3 different ways `jwt_secret` can be provided, we check if any one of them is present,
+      # and if not, bootstrap a secret in `/var/lib/lldap/jwt_secret_file` and give that to lldap.
+      script = lib.optionalString (!cfg.settings ? jwt_secret) ''
+        if [[ -z "$LLDAP_JWT_SECRET_FILE" ]] && [[ -z "$LLDAP_JWT_SECRET" ]]; then
+          if [[ ! -e "./jwt_secret_file" ]]; then
+            ${lib.getExe pkgs.openssl} rand -base64 -out ./jwt_secret_file 32
+          fi
+          export LLDAP_JWT_SECRET_FILE="./jwt_secret_file"
+        fi
+      '' + ''
+         ${lib.getExe cfg.package} run --config-file ${format.generate "lldap_config.toml" cfg.settings}
+      '';
       serviceConfig = {
-        ExecStart = "${lib.getExe cfg.package} run --config-file ${format.generate "lldap_config.toml" cfg.settings}";
         StateDirectory = "lldap";
+        StateDirectoryMode = "0750";
         WorkingDirectory = "%S/lldap";
+        UMask = "0027";
         User = "lldap";
         Group = "lldap";
         DynamicUser = true;
diff --git a/nixos/modules/services/x11/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix
index 1237261e0af7..1710d28954d6 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma6.nix
+++ b/nixos/modules/services/desktop-managers/plasma6.nix
@@ -5,8 +5,7 @@
   utils,
   ...
 }: let
-  xcfg = config.services.xserver;
-  cfg = xcfg.desktopManager.plasma6;
+  cfg = config.services.desktopManager.plasma6;
 
   inherit (pkgs) kdePackages;
   inherit (lib) literalExpression mkDefault mkIf mkOption mkPackageOptionMD types;
@@ -17,7 +16,7 @@
   '';
 in {
   options = {
-    services.xserver.desktopManager.plasma6 = {
+    services.desktopManager.plasma6 = {
       enable = mkOption {
         type = types.bool;
         default = false;
@@ -44,6 +43,12 @@ in {
     };
   };
 
+  imports = [
+    (lib.mkRenamedOptionModule [ "services" "xserver" "desktopManager" "plasma6" "enable" ] [ "services" "desktopManager" "plasma6" "enable" ])
+    (lib.mkRenamedOptionModule [ "services" "xserver" "desktopManager" "plasma6" "enableQt5Integration" ] [ "services" "desktopManager" "plasma6" "enableQt5Integration" ])
+    (lib.mkRenamedOptionModule [ "services" "xserver" "desktopManager" "plasma6" "notoPackage" ] [ "services" "desktopManager" "plasma6" "notoPackage" ])
+  ];
+
   config = mkIf cfg.enable {
     assertions = [
       {
@@ -161,7 +166,7 @@ in {
     in
       requiredPackages
       ++ utils.removePackagesByName optionalPackages config.environment.plasma6.excludePackages
-      ++ lib.optionals config.services.xserver.desktopManager.plasma6.enableQt5Integration [
+      ++ lib.optionals config.services.desktopManager.plasma6.enableQt5Integration [
         breeze.qt5
         plasma-integration.qt5
         pkgs.plasma5Packages.kwayland-integration
@@ -175,7 +180,7 @@ in {
       ++ lib.optional config.powerManagement.enable powerdevil
       ++ lib.optional config.services.colord.enable colord-kde
       ++ lib.optional config.services.hardware.bolt.enable plasma-thunderbolt
-      ++ lib.optionals config.services.samba.enable [kdenetwork-filesharing pkgs.samba]
+      ++ lib.optional config.services.samba.enable kdenetwork-filesharing
       ++ lib.optional config.services.xserver.wacom.enable wacomtablet
       ++ lib.optional config.services.flatpak.enable flatpak-kcm;
 
@@ -185,7 +190,7 @@ in {
       "/libexec" # for drkonqi
     ];
 
-    environment.etc."X11/xkb".source = xcfg.xkb.dir;
+    environment.etc."X11/xkb".source = config.services.xserver.xkb.dir;
 
     # Add ~/.config/kdedefaults to XDG_CONFIG_DIRS for shells, since Plasma sets that.
     # FIXME: maybe we should append to XDG_CONFIG_DIRS in /etc/set-environment instead?
@@ -210,6 +215,7 @@ in {
       serif = ["Noto Serif"];
     };
 
+    programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt;
     programs.ssh.askPassword = mkDefault "${kdePackages.ksshaskpass.out}/bin/ksshaskpass";
 
     # Enable helpful DBus services.
diff --git a/nixos/modules/services/development/hoogle.nix b/nixos/modules/services/development/hoogle.nix
index 88dd01fd8aab..c90bb7f01902 100644
--- a/nixos/modules/services/development/hoogle.nix
+++ b/nixos/modules/services/development/hoogle.nix
@@ -56,6 +56,16 @@ in {
       description = lib.mdDoc "Set the host to bind on.";
       default = "127.0.0.1";
     };
+
+    extraOptions = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "--no-security-headers" ];
+      description = lib.mdDoc ''
+        Additional command-line arguments to pass to
+        {command}`hoogle server`
+      '';
+    };
   };
 
   config = mkIf cfg.enable {
@@ -66,7 +76,10 @@ in {
 
       serviceConfig = {
         Restart = "always";
-        ExecStart = ''${hoogleEnv}/bin/hoogle server --local --port ${toString cfg.port} --home ${cfg.home} --host ${cfg.host}'';
+        ExecStart = ''
+          ${hoogleEnv}/bin/hoogle server --local --port ${toString cfg.port} --home ${cfg.home} --host ${cfg.host} \
+            ${concatStringsSep " " cfg.extraOptions}
+        '';
 
         DynamicUser = true;
 
diff --git a/nixos/modules/services/hardware/fwupd.nix b/nixos/modules/services/hardware/fwupd.nix
index 8a9e38d0547b..c4837ff80ec7 100644
--- a/nixos/modules/services/hardware/fwupd.nix
+++ b/nixos/modules/services/hardware/fwupd.nix
@@ -14,11 +14,11 @@ let
 
   customEtc = {
     "fwupd/fwupd.conf" = {
-      source = format.generate "fwupd.conf" {
+      source = format.generate "fwupd.conf" ({
         fwupd = cfg.daemonSettings;
       } // lib.optionalAttrs (lib.length (lib.attrNames cfg.uefiCapsuleSettings) != 0) {
         uefi_capsule = cfg.uefiCapsuleSettings;
-      };
+      });
       # fwupd tries to chmod the file if it doesn't have the right permissions
       mode = "0640";
     };
diff --git a/nixos/modules/services/matrix/matrix-sliding-sync.nix b/nixos/modules/services/matrix/matrix-sliding-sync.nix
index 8b22cd7dba80..d62e41bebd64 100644
--- a/nixos/modules/services/matrix/matrix-sliding-sync.nix
+++ b/nixos/modules/services/matrix/matrix-sliding-sync.nix
@@ -37,7 +37,7 @@ in
             type = lib.types.str;
             default = "127.0.0.1:8009";
             example = "[::]:8008";
-            description = lib.mdDoc "The interface and port to listen on.";
+            description = lib.mdDoc "The interface and port or path (for unix socket) to listen on.";
           };
 
           SYNCV3_LOG_LEVEL = lib.mkOption {
@@ -98,6 +98,7 @@ in
         ExecStart = lib.getExe cfg.package;
         StateDirectory = "matrix-sliding-sync";
         WorkingDirectory = "%S/matrix-sliding-sync";
+        RuntimeDirectory = "matrix-sliding-sync";
         Restart = "on-failure";
         RestartSec = "1s";
       };
diff --git a/nixos/modules/services/monitoring/scrutiny.nix b/nixos/modules/services/monitoring/scrutiny.nix
index aef924ef840c..2862cdd80128 100644
--- a/nixos/modules/services/monitoring/scrutiny.nix
+++ b/nixos/modules/services/monitoring/scrutiny.nix
@@ -201,17 +201,12 @@ in
             Type = "oneshot";
             ExecStart = "${getExe cfg.collector.package} run --config ${settingsFormat.generate "scrutiny-collector.yaml" cfg.collector.settings}";
           };
+          startAt = cfg.collector.schedule;
         };
       };
 
       timers = mkIf cfg.collector.enable {
-        scrutiny-collector = {
-          timerConfig = {
-            OnCalendar = cfg.collector.schedule;
-            Persistent = true;
-            Unit = "scrutiny-collector.service";
-          };
-        };
+        scrutiny-collector.timerConfig.Persistent = true;
       };
     };
   };
diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix
index 5805f332a66f..1fb5063e5ad8 100644
--- a/nixos/modules/services/networking/murmur.nix
+++ b/nixos/modules/services/networking/murmur.nix
@@ -33,7 +33,7 @@ let
     sendversion=${boolToString cfg.sendVersion}
 
     ${optionalString (cfg.registerName != "") "registerName=${cfg.registerName}"}
-    ${optionalString (cfg.registerPassword == "") "registerPassword=${cfg.registerPassword}"}
+    ${optionalString (cfg.registerPassword != "") "registerPassword=${cfg.registerPassword}"}
     ${optionalString (cfg.registerUrl != "") "registerUrl=${cfg.registerUrl}"}
     ${optionalString (cfg.registerHostname != "") "registerHostname=${cfg.registerHostname}"}
 
diff --git a/nixos/modules/services/networking/nebula.nix b/nixos/modules/services/networking/nebula.nix
index e13876172dac..2f9e41ae9c80 100644
--- a/nixos/modules/services/networking/nebula.nix
+++ b/nixos/modules/services/networking/nebula.nix
@@ -10,6 +10,15 @@ let
   format = pkgs.formats.yaml {};
 
   nameToId = netName: "nebula-${netName}";
+
+  resolveFinalPort = netCfg:
+    if netCfg.listen.port == null then
+      if (netCfg.isLighthouse || netCfg.isRelay) then
+        4242
+      else
+        0
+    else
+      netCfg.listen.port;
 in
 {
   # Interface
@@ -95,8 +104,15 @@ in
             };
 
             listen.port = mkOption {
-              type = types.port;
-              default = 4242;
+              type = types.nullOr types.port;
+              default = null;
+              defaultText = lib.literalExpression ''
+                if (config.services.nebula.networks.''${name}.isLighthouse ||
+                    config.services.nebula.networks.''${name}.isRelay) then
+                  4242
+                else
+                  0;
+              '';
               description = lib.mdDoc "Port number to listen on.";
             };
 
@@ -174,7 +190,7 @@ in
           };
           listen = {
             host = netCfg.listen.host;
-            port = netCfg.listen.port;
+            port = resolveFinalPort netCfg;
           };
           tun = {
             disabled = netCfg.tun.disable;
@@ -185,7 +201,15 @@ in
             outbound = netCfg.firewall.outbound;
           };
         } netCfg.settings;
-        configFile = format.generate "nebula-config-${netName}.yml" settings;
+        configFile = format.generate "nebula-config-${netName}.yml" (
+          warnIf
+            ((settings.lighthouse.am_lighthouse || settings.relay.am_relay) && settings.listen.port == 0)
+            ''
+              Nebula network '${netName}' is configured as a lighthouse or relay, and its port is ${builtins.toString settings.listen.port}.
+              You will likely experience connectivity issues: https://nebula.defined.net/docs/config/listen/#listenport
+            ''
+            settings
+          );
         in
         {
           # Create the systemd service for Nebula.
@@ -229,7 +253,7 @@ in
 
     # Open the chosen ports for UDP.
     networking.firewall.allowedUDPPorts =
-      unique (mapAttrsToList (netName: netCfg: netCfg.listen.port) enabledNetworks);
+      unique (filter (port: port > 0) (mapAttrsToList (netName: netCfg: resolveFinalPort netCfg) enabledNetworks));
 
     # Create the service users and groups.
     users.users = mkMerge (mapAttrsToList (netName: netCfg:
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index c96439cf2641..63804a3b1c54 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -291,7 +291,7 @@ in
       };
 
       dns = mkOption {
-        type = types.enum [ "default" "dnsmasq" "unbound" "systemd-resolved" "none" ];
+        type = types.enum [ "default" "dnsmasq" "systemd-resolved" "none" ];
         default = "default";
         description = lib.mdDoc ''
           Set the DNS (`resolv.conf`) processing mode.
@@ -436,6 +436,7 @@ in
             And if you edit a declarative profile NetworkManager will move it to the persistent storage and treat it like a ad-hoc one,
             but there will be two profiles as soon as the systemd unit from this option runs again which can be confusing since NetworkManager tools will start displaying two profiles with the same name and probably a bit different settings depending on what you edited.
             A profile won't be deleted even if it's removed from the config until the system reboots because that's when NetworkManager clears it's temp directory.
+            If `networking.resolvconf.enable` is true, attributes affecting the name resolution (such as `ignore-auto-dns`) may not end up changing `/etc/resolv.conf` as expected when other name services (for example `networking.dhcpcd`) are enabled. Run `resolvconf -l` in the terminal to see what each service produces.
           '';
         };
         environmentFiles = mkOption {
diff --git a/nixos/modules/services/networking/unbound.nix b/nixos/modules/services/networking/unbound.nix
index 8438e472e11e..242fcd500bb0 100644
--- a/nixos/modules/services/networking/unbound.nix
+++ b/nixos/modules/services/networking/unbound.nix
@@ -76,12 +76,13 @@ in {
 
       checkconf = mkOption {
         type = types.bool;
-        default = !cfg.settings ? include;
-        defaultText = "!config.services.unbound.settings ? include";
+        default = !cfg.settings ? include && !cfg.settings ? remote-control;
+        defaultText = "!services.unbound.settings ? include && !services.unbound.settings ? remote-control";
         description = lib.mdDoc ''
           Wether to check the resulting config file with unbound checkconf for syntax errors.
 
-          If settings.include is used, then this options is disabled, as the import can likely not be resolved at build time.
+          If settings.include is used, this options is disabled, as the import can likely not be accessed at build time.
+          If settings.remote-control is used, this option is disabled, too as the control-key-file, server-cert-file and server-key-file cannot be accessed at build time.
         '';
       };
 
@@ -229,8 +230,6 @@ in {
       resolvconf = {
         useLocalResolver = mkDefault true;
       };
-
-      networkmanager.dns = "unbound";
     };
 
     environment.etc."unbound/unbound.conf".source = confFile;
diff --git a/nixos/modules/services/security/esdm.nix b/nixos/modules/services/security/esdm.nix
index 134b4be1a94c..c34fba1b3c75 100644
--- a/nixos/modules/services/security/esdm.nix
+++ b/nixos/modules/services/security/esdm.nix
@@ -4,49 +4,33 @@ let
   cfg = config.services.esdm;
 in
 {
+  imports = [
+    # removed option 'services.esdm.cuseRandomEnable'
+    (lib.mkRemovedOptionModule [ "services" "esdm" "cuseRandomEnable" ] ''
+      Use services.esdm.enableLinuxCompatServices instead.
+    '')
+    # removed option 'services.esdm.cuseUrandomEnable'
+    (lib.mkRemovedOptionModule [ "services" "esdm" "cuseUrandomEnable" ] ''
+      Use services.esdm.enableLinuxCompatServices instead.
+    '')
+    # removed option 'services.esdm.procEnable'
+    (lib.mkRemovedOptionModule [ "services" "esdm" "procEnable" ] ''
+      Use services.esdm.enableLinuxCompatServices instead.
+    '')
+    # removed option 'services.esdm.verbose'
+    (lib.mkRemovedOptionModule [ "services" "esdm" "verbose" ] ''
+      There is no replacement.
+    '')
+  ];
+
   options.services.esdm = {
     enable = lib.mkEnableOption (lib.mdDoc "ESDM service configuration");
     package = lib.mkPackageOption pkgs "esdm" { };
-    serverEnable = lib.mkOption {
-      type = lib.types.bool;
-      default = true;
-      description = lib.mdDoc ''
-        Enable option for ESDM server service. If serverEnable == false, then the esdm-server
-        will not start. Also the subsequent services esdm-cuse-random, esdm-cuse-urandom
-        and esdm-proc will not start as these have the entry Want=esdm-server.service.
-      '';
-    };
-    cuseRandomEnable = lib.mkOption {
-      type = lib.types.bool;
-      default = true;
-      description = lib.mdDoc ''
-        Enable option for ESDM cuse-random service. Determines if the esdm-cuse-random.service
-        is started.
-      '';
-    };
-    cuseUrandomEnable = lib.mkOption {
-      type = lib.types.bool;
-      default = true;
-      description = lib.mdDoc ''
-        Enable option for ESDM cuse-urandom service. Determines if the esdm-cuse-urandom.service
-        is started.
-      '';
-    };
-    procEnable = lib.mkOption {
+    enableLinuxCompatServices = lib.mkOption {
       type = lib.types.bool;
       default = true;
       description = lib.mdDoc ''
-        Enable option for ESDM proc service. Determines if the esdm-proc.service
-        is started.
-      '';
-    };
-    verbose = lib.mkOption {
-      type = lib.types.bool;
-      default = false;
-      description = lib.mdDoc ''
-        Enable verbose ExecStart for ESDM. If verbose == true, then the corresponding "ExecStart"
-        values of the 4 aforementioned services are overwritten with the option
-        for the highest verbosity.
+        Enable /dev/random, /dev/urandom and /proc/sys/kernel/random/* userspace wrapper.
       '';
     };
   };
@@ -55,46 +39,13 @@ in
     lib.mkMerge [
       ({
         systemd.packages = [ cfg.package ];
-      })
-      # It is necessary to set those options for these services to be started by systemd in NixOS
-      (lib.mkIf cfg.serverEnable {
         systemd.services."esdm-server".wantedBy = [ "basic.target" ];
-        systemd.services."esdm-server".serviceConfig = lib.mkIf cfg.verbose {
-          ExecStart = [
-            " " # unset previous value defined in 'esdm-server.service'
-            "${cfg.package}/bin/esdm-server -f -vvvvvv"
-          ];
-        };
-      })
-
-      (lib.mkIf cfg.cuseRandomEnable {
-        systemd.services."esdm-cuse-random".wantedBy = [ "basic.target" ];
-        systemd.services."esdm-cuse-random".serviceConfig = lib.mkIf cfg.verbose {
-          ExecStart = [
-            " " # unset previous value defined in 'esdm-cuse-random.service'
-            "${cfg.package}/bin/esdm-cuse-random -f -v 6"
-          ];
-        };
       })
-
-      (lib.mkIf cfg.cuseUrandomEnable {
-        systemd.services."esdm-cuse-urandom".wantedBy = [ "basic.target" ];
-        systemd.services."esdm-cuse-urandom".serviceConfig = lib.mkIf cfg.verbose {
-          ExecStart = [
-            " " # unset previous value defined in 'esdm-cuse-urandom.service'
-            "${config.services.esdm.package}/bin/esdm-cuse-urandom -f -v 6"
-          ];
-        };
-      })
-
-      (lib.mkIf cfg.procEnable {
-        systemd.services."esdm-proc".wantedBy = [ "basic.target" ];
-        systemd.services."esdm-proc".serviceConfig = lib.mkIf cfg.verbose {
-          ExecStart = [
-            " " # unset previous value defined in 'esdm-proc.service'
-            "${cfg.package}/bin/esdm-proc --relabel -f -o allow_other /proc/sys/kernel/random -v 6"
-          ];
-        };
+      # It is necessary to set those options for these services to be started by systemd in NixOS
+      (lib.mkIf cfg.enableLinuxCompatServices {
+        systemd.targets."esdm-linux-compat".wantedBy = [ "basic.target" ];
+        systemd.services."esdm-server-suspend".wantedBy = [ "sleep.target" "suspend.target" "hibernate.target" ];
+        systemd.services."esdm-server-resume".wantedBy = [ "sleep.target" "suspend.target" "hibernate.target" ];
       })
     ]);
 
diff --git a/nixos/modules/services/security/yubikey-agent.nix b/nixos/modules/services/security/yubikey-agent.nix
index a9f15e4405f2..3d5f84af2cf4 100644
--- a/nixos/modules/services/security/yubikey-agent.nix
+++ b/nixos/modules/services/security/yubikey-agent.nix
@@ -6,9 +6,6 @@ with lib;
 
 let
   cfg = config.services.yubikey-agent;
-
-  # reuse the pinentryFlavor option from the gnupg module
-  pinentryFlavor = config.programs.gnupg.agent.pinentryFlavor;
 in
 {
   ###### interface
@@ -40,14 +37,9 @@ in
 
     # This overrides the systemd user unit shipped with the
     # yubikey-agent package
-    systemd.user.services.yubikey-agent = mkIf (pinentryFlavor != null) {
-      path = [ pkgs.pinentry.${pinentryFlavor} ];
-      wantedBy = [
-        (if pinentryFlavor == "tty" || pinentryFlavor == "curses" then
-          "default.target"
-        else
-          "graphical-session.target")
-      ];
+    systemd.user.services.yubikey-agent = mkIf (config.programs.gnupg.agent.pinentryPackage != null) {
+      path = [ config.programs.gnupg.agent.pinentryPackage ];
+      wantedBy = [ "default.target" ];
     };
 
     # Yubikey-agent expects pcsd to be running in order to function.
diff --git a/nixos/modules/services/web-apps/gotosocial.nix b/nixos/modules/services/web-apps/gotosocial.nix
index 45464f646da8..657509c11005 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 ];
+  meta.maintainers = with lib.maintainers; [ misuzu blakesmith ];
 
   options.services.gotosocial = {
     enable = lib.mkEnableOption (lib.mdDoc "ActivityPub social network server");
diff --git a/nixos/modules/services/web-servers/stargazer.nix b/nixos/modules/services/web-servers/stargazer.nix
index 18f57363137c..4eca33326040 100644
--- a/nixos/modules/services/web-servers/stargazer.nix
+++ b/nixos/modules/services/web-servers/stargazer.nix
@@ -129,6 +129,12 @@ in
       example = lib.literalExpression "\"1y\"";
     };
 
+    debugMode = lib.mkOption {
+      type = lib.types.bool;
+      default = false;
+      description = lib.mdDoc "Run Stargazer in debug mode.";
+    };
+
     routes = lib.mkOption {
       type = lib.types.listOf
         (lib.types.submodule {
@@ -195,7 +201,7 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
-        ExecStart = "${pkgs.stargazer}/bin/stargazer ${configFile}";
+        ExecStart = "${pkgs.stargazer}/bin/stargazer ${configFile} ${lib.optionalString cfg.debugMode "-D"}";
         Restart = "always";
         # User and group
         User = cfg.user;
diff --git a/nixos/modules/services/x11/desktop-managers/deepin.nix b/nixos/modules/services/x11/desktop-managers/deepin.nix
index 0824d6e30a8a..e6f221201013 100644
--- a/nixos/modules/services/x11/desktop-managers/deepin.nix
+++ b/nixos/modules/services/x11/desktop-managers/deepin.nix
@@ -66,6 +66,7 @@ in
       services.upower.enable = mkDefault config.powerManagement.enable;
       networking.networkmanager.enable = mkDefault true;
       programs.dconf.enable = mkDefault true;
+      programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt;
 
       fonts.packages = with pkgs; [ noto-fonts ];
       xdg.mime.enable = true;
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index ecb8d1e91bde..33d0a7b52643 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -18,7 +18,7 @@ in
   # determines the default: later modules (if enabled) are preferred.
   # E.g., if Plasma 5 is enabled, it supersedes xterm.
   imports = [
-    ./none.nix ./xterm.nix ./phosh.nix ./xfce.nix ./plasma5.nix ./plasma6.nix ./lumina.nix
+    ./none.nix ./xterm.nix ./phosh.nix ./xfce.nix ./plasma5.nix ../../desktop-managers/plasma6.nix ./lumina.nix
     ./lxqt.nix ./enlightenment.nix ./gnome.nix ./retroarch.nix ./kodi.nix
     ./mate.nix ./pantheon.nix ./surf-display.nix ./cde.nix
     ./cinnamon.nix ./budgie.nix ./deepin.nix
diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix
index 50ad72dc7388..d3bdc4326a90 100644
--- a/nixos/modules/services/x11/desktop-managers/lxqt.nix
+++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix
@@ -62,6 +62,8 @@ in
     # Link some extra directories in /run/current-system/software/share
     environment.pathsToLink = [ "/share" ];
 
+    programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt;
+
     # virtual file systems support for PCManFM-QT
     services.gvfs.enable = true;
 
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 7645b3070369..c884b4487e24 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -336,6 +336,7 @@ in
         serif = [ "Noto Serif" ];
       };
 
+      programs.gnupg.agent.pinentryPackage = pkgs.pinentry-qt;
       programs.ssh.askPassword = mkDefault "${pkgs.plasma5Packages.ksshaskpass.out}/bin/ksshaskpass";
 
       # Enable helpful DBus services.
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index e28486bcc12d..6bc964f4c6ed 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -131,6 +131,7 @@ in
         xfdesktop
       ] ++ optional cfg.enableScreensaver xfce4-screensaver) excludePackages;
 
+    programs.gnupg.agent.pinentryPackage = pkgs.pinentry-gtk2;
     programs.xfconf.enable = true;
     programs.thunar.enable = true;
 
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 38fb1074fcdf..3d7474e18263 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -749,6 +749,8 @@ in
     boot.kernel.sysctl."fs.inotify.max_user_instances" = mkDefault 524288;
     boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288;
 
+    programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;
+
     systemd.defaultUnit = mkIf cfg.autorun "graphical.target";
 
     systemd.services.display-manager =
diff --git a/nixos/modules/system/boot/binfmt.nix b/nixos/modules/system/boot/binfmt.nix
index 08e3dce70844..2242c9da62d0 100644
--- a/nixos/modules/system/boot/binfmt.nix
+++ b/nixos/modules/system/boot/binfmt.nix
@@ -331,6 +331,7 @@ in {
           "proc-sys-fs-binfmt_misc.mount"
           "systemd-binfmt.service"
         ];
+        services.systemd-binfmt.after = [ "systemd-tmpfiles-setup.service" ];
         services.systemd-binfmt.restartTriggers = [ (builtins.toJSON config.boot.binfmt.registrations) ];
       })
     ];
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 49090423e078..a8885aee78f2 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -97,7 +97,7 @@ let
 
       # Maintaining state across reboots.
       "systemd-random-seed.service"
-      "systemd-boot-random-seed.service"
+      ] ++ (optional cfg.package.withBootloader "systemd-boot-random-seed.service") ++ [
       "systemd-backlight@.service"
       "systemd-rfkill.service"
       "systemd-rfkill.socket"
diff --git a/nixos/modules/system/boot/uki.nix b/nixos/modules/system/boot/uki.nix
index ce00ac8e6397..0965b887c12e 100644
--- a/nixos/modules/system/boot/uki.nix
+++ b/nixos/modules/system/boot/uki.nix
@@ -75,6 +75,8 @@ in
         OSRelease = lib.mkOptionDefault "@${config.system.build.etc}/etc/os-release";
         # This is needed for cross compiling.
         EFIArch = lib.mkOptionDefault efiArch;
+      } // lib.optionalAttrs (config.hardware.deviceTree.enable && config.hardware.deviceTree.name != null) {
+        DeviceTree = lib.mkOptionDefault "${config.hardware.deviceTree.package}/${config.hardware.deviceTree.name}";
       };
     };
 
diff --git a/nixos/modules/virtualisation/amazon-ec2-amis.nix b/nixos/modules/virtualisation/amazon-ec2-amis.nix
index ff88f02e5d33..97636f4dcb2a 100644
--- a/nixos/modules/virtualisation/amazon-ec2-amis.nix
+++ b/nixos/modules/virtualisation/amazon-ec2-amis.nix
@@ -1,3 +1,6 @@
+# NOTE: this file will stop being updated.
+# please use https://nixos.github.io/amis/  and https://nixos.github.io/amis/images.json
+# instead.
 let self = {
   "14.04".ap-northeast-1.x86_64-linux.hvm-ebs = "ami-71c6f470";
   "14.04".ap-northeast-1.x86_64-linux.pv-ebs = "ami-4dcbf84c";
@@ -584,5 +587,68 @@ let self = {
   "23.05".us-west-1.aarch64-linux.hvm-ebs = "ami-0e75c8f3deb1f842b";
   "23.05".us-west-2.aarch64-linux.hvm-ebs = "ami-0d0979d889078d036";
 
-  latest = self."23.05";
+
+  # 23.11.4976.79baff8812a0
+
+  "23.11".eu-north-1.x86_64-linux.hvm-ebs = "ami-00e64007071666b9e";
+  "23.11".ap-south-2.x86_64-linux.hvm-ebs = "ami-0bbb8e5663f912455";
+  "23.11".ap-south-1.x86_64-linux.hvm-ebs = "ami-057ec482a7bc9cb87";
+  "23.11".eu-south-1.x86_64-linux.hvm-ebs = "ami-083f9740e86ab36b9";
+  "23.11".eu-south-2.x86_64-linux.hvm-ebs = "ami-0686a9ef630e6eeef";
+  "23.11".me-central-1.x86_64-linux.hvm-ebs = "ami-0475d5925ff0390f8";
+  "23.11".il-central-1.x86_64-linux.hvm-ebs = "ami-0997e21a353de1226";
+  "23.11".ca-central-1.x86_64-linux.hvm-ebs = "ami-0f9fc310496ea54ec";
+  "23.11".eu-central-1.x86_64-linux.hvm-ebs = "ami-0923e79b6f9b198fa";
+  "23.11".eu-central-2.x86_64-linux.hvm-ebs = "ami-0b02e6421cde609ff";
+  "23.11".us-west-1.x86_64-linux.hvm-ebs = "ami-0e94c086e49480566";
+  "23.11".us-west-2.x86_64-linux.hvm-ebs = "ami-0a2f8942a90eb233a";
+  "23.11".af-south-1.x86_64-linux.hvm-ebs = "ami-0c9ff564e4a503c56";
+  "23.11".eu-west-3.x86_64-linux.hvm-ebs = "ami-0955d4d89c446d5ff";
+  "23.11".eu-west-2.x86_64-linux.hvm-ebs = "ami-0c5834d32e6dce6c8";
+  "23.11".eu-west-1.x86_64-linux.hvm-ebs = "ami-0e7d1823ac80520e6";
+  "23.11".ap-northeast-3.x86_64-linux.hvm-ebs = "ami-06b3692ef87ef308a";
+  "23.11".ap-northeast-2.x86_64-linux.hvm-ebs = "ami-0fb1e23007bdc6083";
+  "23.11".me-south-1.x86_64-linux.hvm-ebs = "ami-0a4beeb2fc744c149";
+  "23.11".ap-northeast-1.x86_64-linux.hvm-ebs = "ami-0f60ab2288ac784c3";
+  "23.11".sa-east-1.x86_64-linux.hvm-ebs = "ami-058779e1d5c1cc6ae";
+  "23.11".ap-east-1.x86_64-linux.hvm-ebs = "ami-039879f1b367e167f";
+  "23.11".ca-west-1.x86_64-linux.hvm-ebs = "ami-07dc9bc5645a981f1";
+  "23.11".ap-southeast-1.x86_64-linux.hvm-ebs = "ami-0ee92af1fc4c4e5f3";
+  "23.11".ap-southeast-2.x86_64-linux.hvm-ebs = "ami-0814092ef52275887";
+  "23.11".ap-southeast-3.x86_64-linux.hvm-ebs = "ami-0d20b4b6529b6214c";
+  "23.11".ap-southeast-4.x86_64-linux.hvm-ebs = "ami-0aa7b8aa04e5ec741";
+  "23.11".us-east-1.x86_64-linux.hvm-ebs = "ami-0c2e37dc938ed9405";
+  "23.11".us-east-2.x86_64-linux.hvm-ebs = "ami-05c218c4a08c58296";
+
+  "23.11".eu-north-1.aarch64-linux.hvm-ebs = "ami-05e68ac90786e5ac0";
+  "23.11".ap-south-2.aarch64-linux.hvm-ebs = "ami-0a53356d3176a82af";
+  "23.11".ap-south-1.aarch64-linux.hvm-ebs = "ami-0cc335be202b53954";
+  "23.11".eu-south-1.aarch64-linux.hvm-ebs = "ami-05d387849385390c0";
+  "23.11".eu-south-2.aarch64-linux.hvm-ebs = "ami-0193deb9aa4b398bb";
+  "23.11".me-central-1.aarch64-linux.hvm-ebs = "ami-05bd96550451e131d";
+  "23.11".il-central-1.aarch64-linux.hvm-ebs = "ami-0264204c502a16f49";
+  "23.11".ca-central-1.aarch64-linux.hvm-ebs = "ami-08345537f80791b3c";
+  "23.11".eu-central-1.aarch64-linux.hvm-ebs = "ami-03b257130b2b01000";
+  "23.11".eu-central-2.aarch64-linux.hvm-ebs = "ami-0b4412d8a4d3fb7ae";
+  "23.11".us-west-1.aarch64-linux.hvm-ebs = "ami-0a2d70cd7a3b03e24";
+  "23.11".us-west-2.aarch64-linux.hvm-ebs = "ami-01b8e062c74311de0";
+  "23.11".af-south-1.aarch64-linux.hvm-ebs = "ami-011c296fee301596b";
+  "23.11".eu-west-3.aarch64-linux.hvm-ebs = "ami-024531ee8546d7ec7";
+  "23.11".eu-west-2.aarch64-linux.hvm-ebs = "ami-0a5dda5cf7e00b39b";
+  "23.11".eu-west-1.aarch64-linux.hvm-ebs = "ami-013f7a51b602dec7d";
+  "23.11".ap-northeast-3.aarch64-linux.hvm-ebs = "ami-0220fc0e06979c6ff";
+  "23.11".ap-northeast-2.aarch64-linux.hvm-ebs = "ami-0978048539bbad573";
+  "23.11".me-south-1.aarch64-linux.hvm-ebs = "ami-02057e1a9c901b506";
+  "23.11".ap-northeast-1.aarch64-linux.hvm-ebs = "ami-05616e07e227f9982";
+  "23.11".sa-east-1.aarch64-linux.hvm-ebs = "ami-0bf5255283cec803b";
+  "23.11".ap-east-1.aarch64-linux.hvm-ebs = "ami-00432470e52956e49";
+  "23.11".ca-west-1.aarch64-linux.hvm-ebs = "ami-0675649785473e1ac";
+  "23.11".ap-southeast-1.aarch64-linux.hvm-ebs = "ami-006494f0fa381ba53";
+  "23.11".ap-southeast-2.aarch64-linux.hvm-ebs = "ami-0d8c15d68266d6881";
+  "23.11".ap-southeast-3.aarch64-linux.hvm-ebs = "ami-0db38da4ed78d2a10";
+  "23.11".ap-southeast-4.aarch64-linux.hvm-ebs = "ami-098b3b942486b5e71";
+  "23.11".us-east-1.aarch64-linux.hvm-ebs = "ami-02d1d66bda50b9036";
+  "23.11".us-east-2.aarch64-linux.hvm-ebs = "ami-0aa62457617706386";
+
+  latest = self."23.11";
 }; in self
diff --git a/nixos/modules/virtualisation/incus.nix b/nixos/modules/virtualisation/incus.nix
index a561c5682ae5..da7873c7bec8 100644
--- a/nixos/modules/virtualisation/incus.nix
+++ b/nixos/modules/virtualisation/incus.nix
@@ -164,19 +164,24 @@ in
         "network-online.target"
         "lxcfs.service"
         "incus.socket"
-      ];
+      ]
+        ++ lib.optional config.virtualisation.vswitch.enable "ovs-vswitchd.service";
+
       requires = [
         "lxcfs.service"
         "incus.socket"
-      ];
+      ]
+        ++ lib.optional config.virtualisation.vswitch.enable "ovs-vswitchd.service";
+
       wants = [
         "network-online.target"
       ];
 
-      path = lib.mkIf config.boot.zfs.enabled [
+      path = lib.optionals config.boot.zfs.enabled [
         config.boot.zfs.package
         "${config.boot.zfs.package}/lib/udev"
-      ];
+      ]
+        ++ lib.optional config.virtualisation.vswitch.enable config.virtualisation.vswitch.package;
 
       environment = lib.mkMerge [ {
         # Override Path to the LXC template configuration directory
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 7376cd40b910..ac64b85dd486 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -640,6 +640,7 @@ in {
   nzbget = handleTest ./nzbget.nix {};
   nzbhydra2 = handleTest ./nzbhydra2.nix {};
   oh-my-zsh = handleTest ./oh-my-zsh.nix {};
+  ollama = handleTest ./ollama.nix {};
   ombi = handleTest ./ombi.nix {};
   openarena = handleTest ./openarena.nix {};
   openldap = handleTest ./openldap.nix {};
@@ -686,6 +687,7 @@ in {
   pgbouncer = handleTest ./pgbouncer.nix {};
   pgjwt = handleTest ./pgjwt.nix {};
   pgmanage = handleTest ./pgmanage.nix {};
+  pgvecto-rs = handleTest ./pgvecto-rs.nix {};
   phosh = handleTest ./phosh.nix {};
   photoprism = handleTest ./photoprism.nix {};
   php = handleTest ./php {};
diff --git a/nixos/tests/incus/container.nix b/nixos/tests/incus/container.nix
index eb00429e53fe..9260f70da98c 100644
--- a/nixos/tests/incus/container.nix
+++ b/nixos/tests/incus/container.nix
@@ -29,6 +29,7 @@ in
 
       incus.enable = true;
     };
+    networking.nftables.enable = true;
   };
 
   testScript = ''
diff --git a/nixos/tests/incus/default.nix b/nixos/tests/incus/default.nix
index ff36fe9d6730..474a621c5ce9 100644
--- a/nixos/tests/incus/default.nix
+++ b/nixos/tests/incus/default.nix
@@ -11,6 +11,7 @@
     boot.initrd.systemd.enable = true;
   }; };
   lxd-to-incus = import ./lxd-to-incus.nix { inherit system pkgs; };
+  openvswitch = import ./openvswitch.nix { inherit system pkgs; };
   preseed = import ./preseed.nix { inherit system pkgs; };
   socket-activated = import ./socket-activated.nix { inherit system pkgs; };
   ui = import ./ui.nix {inherit system pkgs;};
diff --git a/nixos/tests/incus/lxd-to-incus.nix b/nixos/tests/incus/lxd-to-incus.nix
index c0fc98c224df..262f63c0f26f 100644
--- a/nixos/tests/incus/lxd-to-incus.nix
+++ b/nixos/tests/incus/lxd-to-incus.nix
@@ -67,6 +67,7 @@ import ../make-test-python.nix (
 
           incus.enable = true;
         };
+        networking.nftables.enable = true;
       };
 
     testScript = ''
diff --git a/nixos/tests/incus/openvswitch.nix b/nixos/tests/incus/openvswitch.nix
new file mode 100644
index 000000000000..5d4aef031ad0
--- /dev/null
+++ b/nixos/tests/incus/openvswitch.nix
@@ -0,0 +1,65 @@
+import ../make-test-python.nix ({ pkgs, lib, ... } :
+
+{
+  name = "incus-openvswitch";
+
+  meta = {
+    maintainers = lib.teams.lxc.members;
+  };
+
+  nodes.machine = { lib, ... }: {
+    virtualisation = {
+      incus.enable = true;
+      vswitch.enable = true;
+      incus.preseed = {
+        networks = [
+          {
+            name = "nixostestbr0";
+            type = "bridge";
+            config = {
+              "bridge.driver" = "openvswitch";
+              "ipv4.address" = "10.0.100.1/24";
+              "ipv4.nat" = "true";
+            };
+          }
+        ];
+        profiles = [
+          {
+            name = "nixostest_default";
+            devices = {
+              eth0 = {
+                name = "eth0";
+                network = "nixostestbr0";
+                type = "nic";
+              };
+              root = {
+                path = "/";
+                pool = "default";
+                size = "35GiB";
+                type = "disk";
+              };
+            };
+          }
+        ];
+        storage_pools = [
+          {
+            name = "nixostest_pool";
+            driver = "dir";
+          }
+        ];
+      };
+    };
+    networking.nftables.enable = true;
+  };
+
+  testScript = ''
+    machine.wait_for_unit("incus.service")
+    machine.wait_for_unit("incus-preseed.service")
+
+    with subtest("Verify openvswitch bridge"):
+      machine.succeed("incus network info nixostestbr0")
+
+    with subtest("Verify openvswitch bridge"):
+      machine.succeed("ovs-vsctl br-exists nixostestbr0")
+  '';
+})
diff --git a/nixos/tests/incus/preseed.nix b/nixos/tests/incus/preseed.nix
index a488d71f3c92..f2d928115f3e 100644
--- a/nixos/tests/incus/preseed.nix
+++ b/nixos/tests/incus/preseed.nix
@@ -48,6 +48,7 @@ import ../make-test-python.nix ({ pkgs, lib, ... } :
         ];
       };
     };
+    networking.nftables.enable = true;
   };
 
   testScript = ''
diff --git a/nixos/tests/incus/socket-activated.nix b/nixos/tests/incus/socket-activated.nix
index fca536b7054f..59caf1090fbd 100644
--- a/nixos/tests/incus/socket-activated.nix
+++ b/nixos/tests/incus/socket-activated.nix
@@ -12,6 +12,7 @@ import ../make-test-python.nix ({ pkgs, lib, ... } :
       incus.enable = true;
       incus.socketActivation = true;
     };
+    networking.nftables.enable = true;
   };
 
   testScript = ''
diff --git a/nixos/tests/incus/ui.nix b/nixos/tests/incus/ui.nix
index 24ce1217d8df..837eb14844ce 100644
--- a/nixos/tests/incus/ui.nix
+++ b/nixos/tests/incus/ui.nix
@@ -10,6 +10,7 @@ import ../make-test-python.nix ({ pkgs, lib, ... }: {
       incus.enable = true;
       incus.ui.enable = true;
     };
+    networking.nftables.enable = true;
 
     environment.systemPackages =
       let
diff --git a/nixos/tests/incus/virtual-machine.nix b/nixos/tests/incus/virtual-machine.nix
index c76e4f448f2f..ab378c7b9490 100644
--- a/nixos/tests/incus/virtual-machine.nix
+++ b/nixos/tests/incus/virtual-machine.nix
@@ -32,6 +32,7 @@ in
 
       incus.enable = true;
     };
+    networking.nftables.enable = true;
   };
 
   testScript = ''
diff --git a/nixos/tests/miriway.nix b/nixos/tests/miriway.nix
index a0987d9fc41b..24e6ec6367cd 100644
--- a/nixos/tests/miriway.nix
+++ b/nixos/tests/miriway.nix
@@ -100,7 +100,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
     # Test Wayland
     # We let Miriway start the first terminal, as we might get stuck if it's not ready to process the first keybind
     # machine.send_key("ctrl-alt-t")
-    machine.wait_for_text("alice@machine")
+    machine.wait_for_text(r"(alice|machine)")
     machine.send_chars("test-wayland\n")
     machine.wait_for_file("/tmp/test-wayland-exit-ok")
     machine.copy_from_vm("/tmp/test-wayland.out")
@@ -112,7 +112,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
 
     # Test XWayland
     machine.send_key("ctrl-alt-a")
-    machine.wait_for_text("alice@machine")
+    machine.wait_for_text(r"(alice|machine)")
     machine.send_chars("test-x11\n")
     machine.wait_for_file("/tmp/test-x11-exit-ok")
     machine.copy_from_vm("/tmp/test-x11.out")
diff --git a/nixos/tests/nebula.nix b/nixos/tests/nebula.nix
index 89b91d89fcb3..6c468153d5b2 100644
--- a/nixos/tests/nebula.nix
+++ b/nixos/tests/nebula.nix
@@ -10,6 +10,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: let
       environment.systemPackages = [ pkgs.nebula ];
       users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ];
       services.openssh.enable = true;
+      networking.firewall.enable = true; # Implicitly true, but let's make sure.
       networking.interfaces.eth1.useDHCP = false;
 
       services.nebula.networks.smoke = {
@@ -17,7 +18,10 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: let
         ca = "/etc/nebula/ca.crt";
         cert = "/etc/nebula/${name}.crt";
         key = "/etc/nebula/${name}.key";
-        listen = { host = "0.0.0.0"; port = 4242; };
+        listen = {
+          host = "0.0.0.0";
+          port = if (config.services.nebula.networks.smoke.isLighthouse || config.services.nebula.networks.smoke.isRelay) then 4242 else 0;
+        };
       };
     }
     extraConfig
diff --git a/nixos/tests/ollama.nix b/nixos/tests/ollama.nix
new file mode 100644
index 000000000000..4b21f445cdbd
--- /dev/null
+++ b/nixos/tests/ollama.nix
@@ -0,0 +1,56 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }:
+let
+  mainPort = "11434";
+  altPort = "11435";
+
+  curlRequest = port: request:
+    "curl http://127.0.0.1:${port}/api/generate -d '${builtins.toJSON request}'";
+
+  prompt = {
+    model = "tinydolphin";
+    prompt = "lorem ipsum";
+    options = {
+      seed = 69;
+      temperature = 0;
+    };
+  };
+in
+{
+  name = "ollama";
+  meta = with lib.maintainers; {
+    maintainers = [ abysssol ];
+  };
+
+  nodes = {
+    cpu = { ... }: {
+      services.ollama.enable = true;
+    };
+
+    rocm = { ... }: {
+      services.ollama.enable = true;
+      services.ollama.acceleration = "rocm";
+    };
+
+    cuda = { ... }: {
+      services.ollama.enable = true;
+      services.ollama.acceleration = "cuda";
+    };
+
+    altAddress = { ... }: {
+      services.ollama.enable = true;
+      services.ollama.listenAddress = "127.0.0.1:${altPort}";
+    };
+  };
+
+  testScript = ''
+    vms = [ cpu, rocm, cuda, altAddress ];
+
+    start_all()
+    for vm in vms:
+        vm.wait_for_unit("multi-user.target")
+
+    stdout = cpu.succeed("""${curlRequest mainPort prompt}""", timeout=100)
+
+    stdout = altAddress.succeed("""${curlRequest altPort prompt}""", timeout=100)
+  '';
+})
diff --git a/nixos/tests/pass-secret-service.nix b/nixos/tests/pass-secret-service.nix
index e0dddf0ad29e..cdbdaa52dbc0 100644
--- a/nixos/tests/pass-secret-service.nix
+++ b/nixos/tests/pass-secret-service.nix
@@ -26,7 +26,6 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
 
       programs.gnupg = {
         agent.enable = true;
-        agent.pinentryFlavor = "tty";
         dirmngr.enable = true;
       };
     };
diff --git a/nixos/tests/pgvecto-rs.nix b/nixos/tests/pgvecto-rs.nix
new file mode 100644
index 000000000000..cd871dab6a0f
--- /dev/null
+++ b/nixos/tests/pgvecto-rs.nix
@@ -0,0 +1,76 @@
+# mostly copied from ./timescaledb.nix which was copied from ./postgresql.nix
+# as it seemed unapproriate to test additional extensions for postgresql there.
+
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+with pkgs.lib;
+
+let
+  postgresql-versions = import ../../pkgs/servers/sql/postgresql pkgs;
+  # Test cases from https://docs.pgvecto.rs/use-cases/hybrid-search.html
+  test-sql = pkgs.writeText "postgresql-test" ''
+    CREATE EXTENSION vectors;
+
+    CREATE TABLE items (
+      id bigserial PRIMARY KEY,
+      content text NOT NULL,
+      embedding vectors.vector(3) NOT NULL -- 3 dimensions
+    );
+
+    INSERT INTO items (content, embedding) VALUES
+      ('a fat cat sat on a mat and ate a fat rat', '[1, 2, 3]'),
+      ('a fat dog sat on a mat and ate a fat rat', '[4, 5, 6]'),
+      ('a thin cat sat on a mat and ate a thin rat', '[7, 8, 9]'),
+      ('a thin dog sat on a mat and ate a thin rat', '[10, 11, 12]');
+  '';
+  make-postgresql-test = postgresql-name: postgresql-package: makeTest {
+    name = postgresql-name;
+    meta = with pkgs.lib.maintainers; {
+      maintainers = [ diogotcorreia ];
+    };
+
+    nodes.machine = { ... }:
+      {
+        services.postgresql = {
+          enable = true;
+          package = postgresql-package;
+          extraPlugins = ps: with ps; [
+            pgvecto-rs
+          ];
+          settings.shared_preload_libraries = "vectors";
+        };
+      };
+
+    testScript = ''
+      def check_count(statement, lines):
+          return 'test $(sudo -u postgres psql postgres -tAc "{}"|wc -l) -eq {}'.format(
+              statement, lines
+          )
+
+
+      machine.start()
+      machine.wait_for_unit("postgresql")
+
+      with subtest("Postgresql with extension vectors is available just after unit start"):
+          machine.succeed(check_count("SELECT * FROM pg_available_extensions WHERE name = 'vectors' AND default_version = '${postgresql-package.pkgs.pgvecto-rs.version}';", 1))
+
+      machine.succeed("sudo -u postgres psql -f ${test-sql}")
+
+      machine.succeed(check_count("SELECT content, embedding FROM items WHERE to_tsvector('english', content) @@ 'cat & rat'::tsquery;", 2))
+
+      machine.shutdown()
+    '';
+
+  };
+  applicablePostgresqlVersions = filterAttrs (_: value: versionAtLeast value.version "12") postgresql-versions;
+in
+mapAttrs'
+  (name: package: {
+    inherit name;
+    value = make-postgresql-test name package;
+  })
+  applicablePostgresqlVersions
diff --git a/nixos/tests/privoxy.nix b/nixos/tests/privoxy.nix
index 2d95c4522a01..2a18d332c877 100644
--- a/nixos/tests/privoxy.nix
+++ b/nixos/tests/privoxy.nix
@@ -77,6 +77,11 @@ in
     networking.proxy.httpsProxy = "http://localhost:8118";
   };
 
+  nodes.machine_socks4  = { ... }: { services.privoxy = { enable = true; settings.forward-socks4  = "/ 127.0.0.1:9050 ."; }; };
+  nodes.machine_socks4a = { ... }: { services.privoxy = { enable = true; settings.forward-socks4a = "/ 127.0.0.1:9050 ."; }; };
+  nodes.machine_socks5  = { ... }: { services.privoxy = { enable = true; settings.forward-socks5  = "/ 127.0.0.1:9050 ."; }; };
+  nodes.machine_socks5t = { ... }: { services.privoxy = { enable = true; settings.forward-socks5t = "/ 127.0.0.1:9050 ."; }; };
+
   testScript =
     ''
       with subtest("Privoxy is running"):
@@ -109,5 +114,13 @@ in
           machine.systemctl("start systemd-tmpfiles-clean")
           # ...and count again
           machine.succeed("test $(ls /run/privoxy/certs | wc -l) -eq 0")
+
+      with subtest("Privoxy supports socks upstream proxies"):
+          for m in [machine_socks4, machine_socks4a, machine_socks5, machine_socks5t]:
+              m.wait_for_unit("privoxy")
+              m.wait_for_open_port(8118)
+              # We expect a 503 error because the dummy upstream proxy is not reachable.
+              # In issue #265654, instead privoxy segfaulted causing curl to exit with "Empty reply from server".
+              m.succeed("http_proxy=http://localhost:8118 curl -v http://does-not-exist/ 2>&1 | grep 'HTTP/1.1 503'")
     '';
 })
diff --git a/nixos/tests/web-apps/gotosocial.nix b/nixos/tests/web-apps/gotosocial.nix
index 6d279ab63a79..8c4e76b14e3b 100644
--- a/nixos/tests/web-apps/gotosocial.nix
+++ b/nixos/tests/web-apps/gotosocial.nix
@@ -1,7 +1,7 @@
 { lib, ... }:
 {
   name = "gotosocial";
-  meta.maintainers = with lib.maintainers; [ misuzu ];
+  meta.maintainers = with lib.maintainers; [ misuzu blakesmith ];
 
   nodes.machine = { pkgs, ... }: {
     environment.systemPackages = [ pkgs.jq ];