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/from_md/release-notes/rl-2111.section.xml29
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2205.section.xml18
-rw-r--r--nixos/doc/manual/release-notes/rl-2111.section.md14
-rw-r--r--nixos/doc/manual/release-notes/rl-2205.section.md9
-rwxr-xr-xnixos/lib/test-driver/test-driver.py1
-rw-r--r--nixos/modules/config/fonts/fontdir.nix1
-rw-r--r--nixos/modules/config/gtk/gtk-icon-cache.nix1
-rw-r--r--nixos/modules/config/i18n.nix6
-rw-r--r--nixos/modules/misc/meta.nix2
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/programs/bcc.nix6
-rw-r--r--nixos/modules/security/pam.nix8
-rw-r--r--nixos/modules/services/audio/icecast.nix1
-rw-r--r--nixos/modules/services/audio/navidrome.nix2
-rw-r--r--nixos/modules/services/audio/ympd.nix1
-rw-r--r--nixos/modules/services/backup/bacula.nix3
-rw-r--r--nixos/modules/services/backup/borgbackup.nix1
-rw-r--r--nixos/modules/services/cluster/kubernetes/kubelet.nix1
-rw-r--r--nixos/modules/services/cluster/kubernetes/pki.nix1
-rw-r--r--nixos/modules/services/cluster/kubernetes/proxy.nix1
-rw-r--r--nixos/modules/services/computing/slurm/slurm.nix1
-rw-r--r--nixos/modules/services/continuous-integration/github-runner.nix1
-rw-r--r--nixos/modules/services/continuous-integration/hydra/default.nix1
-rw-r--r--nixos/modules/services/games/factorio.nix4
-rw-r--r--nixos/modules/services/logging/journalwatch.nix1
-rw-r--r--nixos/modules/services/logging/klogd.nix1
-rw-r--r--nixos/modules/services/mail/opendkim.nix1
-rw-r--r--nixos/modules/services/misc/etcd.nix1
-rw-r--r--nixos/modules/services/misc/gitea.nix2
-rw-r--r--nixos/modules/services/misc/gitlab.nix2
-rw-r--r--nixos/modules/services/misc/matrix-appservice-discord.nix3
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix6
-rw-r--r--nixos/modules/services/misc/mautrix-telegram.nix3
-rw-r--r--nixos/modules/services/misc/moonraker.nix1
-rw-r--r--nixos/modules/services/misc/mx-puppet-discord.nix9
-rw-r--r--nixos/modules/services/misc/sourcehut/default.nix3
-rw-r--r--nixos/modules/services/misc/xmrig.nix1
-rw-r--r--nixos/modules/services/monitoring/collectd.nix5
-rw-r--r--nixos/modules/services/monitoring/graphite.nix1
-rw-r--r--nixos/modules/services/monitoring/nagios.nix1
-rw-r--r--nixos/modules/services/monitoring/parsedmarc.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/postfix.nix3
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix64
-rw-r--r--nixos/modules/services/monitoring/smartd.nix3
-rw-r--r--nixos/modules/services/network-filesystems/drbd.nix12
-rw-r--r--nixos/modules/services/network-filesystems/ipfs.nix5
-rw-r--r--nixos/modules/services/networking/bind.nix1
-rw-r--r--nixos/modules/services/networking/consul.nix4
-rw-r--r--nixos/modules/services/networking/coturn.nix1
-rw-r--r--nixos/modules/services/networking/ddclient.nix6
-rw-r--r--nixos/modules/services/networking/dnscrypt-wrapper.nix1
-rw-r--r--nixos/modules/services/networking/flannel.nix3
-rw-r--r--nixos/modules/services/networking/knot.nix49
-rw-r--r--nixos/modules/services/networking/lxd-image-server.nix3
-rw-r--r--nixos/modules/services/networking/ncdns.nix1
-rw-r--r--nixos/modules/services/networking/nix-serve.nix14
-rw-r--r--nixos/modules/services/networking/nsd.nix1
-rw-r--r--nixos/modules/services/networking/ntp/chrony.nix1
-rw-r--r--nixos/modules/services/networking/ntp/ntpd.nix1
-rw-r--r--nixos/modules/services/networking/ntp/openntpd.nix1
-rw-r--r--nixos/modules/services/networking/resilio.nix1
-rw-r--r--nixos/modules/services/networking/seafile.nix1
-rw-r--r--nixos/modules/services/networking/shairport-sync.nix31
-rw-r--r--nixos/modules/services/networking/skydns.nix1
-rw-r--r--nixos/modules/services/networking/smokeping.nix6
-rw-r--r--nixos/modules/services/networking/soju.nix1
-rw-r--r--nixos/modules/services/security/oauth2_proxy_nginx.nix1
-rw-r--r--nixos/modules/services/security/step-ca.nix4
-rw-r--r--nixos/modules/services/security/torsocks.nix1
-rw-r--r--nixos/modules/services/video/epgstation/default.nix2
-rw-r--r--nixos/modules/services/video/mirakurun.nix2
-rw-r--r--nixos/modules/services/video/rtsp-simple-server.nix80
-rw-r--r--nixos/modules/services/web-apps/ihatemoney/default.nix1
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix8
-rw-r--r--nixos/modules/services/web-apps/nextcloud.xml2
-rw-r--r--nixos/modules/services/web-apps/openwebrx.nix1
-rw-r--r--nixos/modules/services/web-apps/peertube.nix1
-rw-r--r--nixos/modules/services/web-servers/uwsgi.nix2
-rw-r--r--nixos/modules/services/web-servers/varnish/default.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix5
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix233
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix2
-rw-r--r--nixos/modules/system/activation/activation-script.nix2
-rw-r--r--nixos/modules/system/activation/top-level.nix1
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix1
-rw-r--r--nixos/modules/system/boot/resolved.nix1
-rw-r--r--nixos/modules/system/boot/timesyncd.nix2
-rw-r--r--nixos/modules/tasks/snapraid.nix4
-rw-r--r--nixos/modules/virtualisation/amazon-ec2-amis.nix40
-rw-r--r--nixos/modules/virtualisation/amazon-options.nix3
-rw-r--r--nixos/modules/virtualisation/oci-containers.nix2
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixos/modules/virtualisation/waydroid.nix9
-rw-r--r--nixos/tests/all-tests.nix7
-rw-r--r--nixos/tests/bpf.nix25
-rw-r--r--nixos/tests/custom-ca.nix9
-rw-r--r--nixos/tests/docker-tools.nix25
-rw-r--r--nixos/tests/drbd.nix87
-rw-r--r--nixos/tests/knot.nix6
-rw-r--r--nixos/tests/nextcloud/default.nix10
-rw-r--r--nixos/tests/nix-serve-ssh.nix (renamed from nixos/tests/nix-ssh-serve.nix)2
-rw-r--r--nixos/tests/prometheus-exporters.nix22
-rw-r--r--nixos/tests/step-ca.nix76
-rw-r--r--nixos/tests/vault-postgresql.nix2
105 files changed, 931 insertions, 125 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
index fb98b6a4b01c0..6b706e4aeaa16 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
@@ -1,9 +1,5 @@
 <section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-release-21.11">
   <title>Release 21.11 (“Porcupine”, 2021/11/30)</title>
-  <para>
-    In addition to numerous new and upgraded packages, this release has
-    the following highlights:
-  </para>
   <itemizedlist spacing="compact">
     <listitem>
       <para>
@@ -14,6 +10,10 @@
   </itemizedlist>
   <section xml:id="sec-release-21.11-highlights">
     <title>Highlights</title>
+    <para>
+      In addition to numerous new and upgraded packages, this release
+      has the following highlights:
+    </para>
     <itemizedlist>
       <listitem>
         <para>
@@ -255,14 +255,14 @@
         <para>
           <link xlink:href="https://www.isc.org/kea/">Kea</link>, ISCs
           2nd generation DHCP and DDNS server suite. Available at
-          <link xlink:href="options.html#opt-services.kea">services.kea</link>.
+          <link xlink:href="options.html#opt-services.kea.dhcp4">services.kea</link>.
         </para>
       </listitem>
       <listitem>
         <para>
           <link xlink:href="https://owncast.online/">owncast</link>,
           self-hosted video live streaming solution. Available at
-          <link xlink:href="options.html#opt-services.owncast">services.owncast</link>.
+          <link xlink:href="options.html#opt-services.owncast.enable">services.owncast</link>.
         </para>
       </listitem>
       <listitem>
@@ -270,7 +270,7 @@
           <link xlink:href="https://joinpeertube.org/">PeerTube</link>,
           developed by Framasoft, is the free and decentralized
           alternative to video platforms. Available at
-          <link xlink:href="options.html#opt-services.peertube">services.peertube</link>.
+          <link xlink:href="options.html#opt-services.peertube.enable">services.peertube</link>.
         </para>
       </listitem>
       <listitem>
@@ -524,6 +524,15 @@
           <link linkend="opt-services.ananicy.enable">services.ananicy</link>.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/prometheus-community/smartctl_exporter">smartctl_exporter</link>,
+          a Prometheus exporter for
+          <link xlink:href="https://en.wikipedia.org/wiki/S.M.A.R.T.">S.M.A.R.T.</link>
+          data. Available as
+          <link xlink:href="options.html#opt-services.prometheus.exporters.smartctl.enable">services.prometheus.exporters.smartctl</link>.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
   <section xml:id="sec-release-21.11-incompatibilities">
@@ -2023,6 +2032,12 @@ Superuser created successfully.
           hydrus manual</link>.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          More jdk and jre versions are now exposed via
+          <literal>java-packages.compiler</literal>.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
 </section>
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index 4752cad6c7b09..c84a3e3b01938 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -57,6 +57,24 @@
           new versions will release.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          The <literal>wafHook</literal> hook now honors
+          <literal>NIX_BUILD_CORES</literal> when
+          <literal>enableParallelBuilding</literal> is not set
+          explicitly. Packages can restore the old behaviour by setting
+          <literal>enableParallelBuilding=false</literal>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <literal>pkgs.claws-mail-gtk2</literal>, representing Claws
+          Mail’s older release version three, was removed in order to
+          get rid of Python 2. Please switch to
+          <literal>claws-mail</literal>, which is Claws Mail’s latest
+          release based on GTK+3 and Python 3.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
   <section xml:id="sec-release-22.05-notable-changes">
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md
index 5abfa6beb1061..48adc4ad33cba 100644
--- a/nixos/doc/manual/release-notes/rl-2111.section.md
+++ b/nixos/doc/manual/release-notes/rl-2111.section.md
@@ -1,11 +1,11 @@
 # Release 21.11 (“Porcupine”, 2021/11/30) {#sec-release-21.11}
 
-In addition to numerous new and upgraded packages, this release has the following highlights:
-
 - Support is planned until the end of June 2022, handing over to 22.05.
 
 ## Highlights {#sec-release-21.11-highlights}
 
+In addition to numerous new and upgraded packages, this release has the following highlights:
+
 - Nix has been updated to version 2.4, reference its [release notes](https://discourse.nixos.org/t/nix-2-4-released/15822) for more information on what has changed. The previous version of Nix, 2.3.16, remains available for the time being in the `nix_2_3` package.
 
 - `iptables` now uses `nf_tables` backend.
@@ -68,11 +68,11 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - [Jibri](https://github.com/jitsi/jibri), a service for recording or streaming a Jitsi Meet conference. Available as [services.jibri](options.html#opt-services.jibri.enable).
 
-- [Kea](https://www.isc.org/kea/), ISCs 2nd generation DHCP and DDNS server suite. Available at [services.kea](options.html#opt-services.kea).
+- [Kea](https://www.isc.org/kea/), ISCs 2nd generation DHCP and DDNS server suite. Available at [services.kea](options.html#opt-services.kea.dhcp4).
 
-- [owncast](https://owncast.online/), self-hosted video live streaming solution. Available at [services.owncast](options.html#opt-services.owncast).
+- [owncast](https://owncast.online/), self-hosted video live streaming solution. Available at [services.owncast](options.html#opt-services.owncast.enable).
 
-- [PeerTube](https://joinpeertube.org/), developed by Framasoft, is the free and decentralized alternative to video platforms. Available at [services.peertube](options.html#opt-services.peertube).
+- [PeerTube](https://joinpeertube.org/), developed by Framasoft, is the free and decentralized alternative to video platforms. Available at [services.peertube](options.html#opt-services.peertube.enable).
 
 - [sourcehut](https://sr.ht), a collection of tools useful for software development. Available as [services.sourcehut](options.html#opt-services.sourcehut.enable).
 
@@ -147,6 +147,8 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - Auto nice daemons [ananicy](https://github.com/Nefelim4ag/Ananicy) and [ananicy-cpp](https://gitlab.com/ananicy-cpp/ananicy-cpp/). Available as [services.ananicy](#opt-services.ananicy.enable).
 
+- [smartctl_exporter](https://github.com/prometheus-community/smartctl_exporter), a Prometheus exporter for [S.M.A.R.T.](https://en.wikipedia.org/wiki/S.M.A.R.T.) data. Available as [services.prometheus.exporters.smartctl](options.html#opt-services.prometheus.exporters.smartctl.enable).
+
 ## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
 
 - The NixOS VM test framework, `pkgs.nixosTest`/`make-test-python.nix`, now requires detaching commands such as `succeed("foo &")` and `succeed("foo | xclip -i")` to close stdout.
@@ -549,3 +551,5 @@ In addition to numerous new and upgraded packages, this release has the followin
 - RetroArch has been upgraded from version `1.8.5` to `1.9.13.2`. Since the previous release was quite old, if you're having issues after the upgrade, please delete your `$XDG_CONFIG_HOME/retroarch/retroarch.cfg` file.
 
 - hydrus has been upgraded from version `438` to `463`. Since upgrading between releases this old is advised against, be sure to have a backup of your data before upgrading. For details, see [the hydrus manual](https://hydrusnetwork.github.io/hydrus/help/getting_started_installing.html#big_updates).
+
+- More jdk and jre versions are now exposed via `java-packages.compiler`.
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index b0526a1fb3b49..45ed69cf1b031 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -10,7 +10,7 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 ## Backward Incompatibilities {#sec-release-22.05-incompatibilities}
 
-* `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`.
+- `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`.
   This *only* makes a difference if you are cross-compiling and will
   ensure that `pkgs.ghc` always runs on the host platform and compiles
   for the target platform (similar to `pkgs.gcc` for example).
@@ -22,9 +22,14 @@ In addition to numerous new and upgraded packages, this release has the followin
   instead to ensure cross compilation keeps working (or switch to
   `haskellPackages.callPackage`).
 
-* `pkgs.emacsPackages.orgPackages` is removed because org elpa is deprecated.
+- `pkgs.emacsPackages.orgPackages` is removed because org elpa is deprecated.
   The packages in the top level of `pkgs.emacsPackages`, such as org and
   org-contrib, refer to the ones in `pkgs.emacsPackages.elpaPackages` and
   `pkgs.emacsPackages.nongnuPackages` where the new versions will release.
 
+- The `wafHook` hook now honors `NIX_BUILD_CORES` when `enableParallelBuilding` is not set explicitly. Packages can restore the old behaviour by setting `enableParallelBuilding=false`.
+
+- `pkgs.claws-mail-gtk2`, representing Claws Mail's older release version three, was removed in order to get rid of Python 2.
+  Please switch to `claws-mail`, which is Claws Mail's latest release based on GTK+3 and Python 3.
+
 ## Other Notable Changes {#sec-release-22.05-notable-changes}
diff --git a/nixos/lib/test-driver/test-driver.py b/nixos/lib/test-driver/test-driver.py
index 2cdf4fc2732ea..90c9e9be45cde 100755
--- a/nixos/lib/test-driver/test-driver.py
+++ b/nixos/lib/test-driver/test-driver.py
@@ -916,6 +916,7 @@ class Machine:
     def send_key(self, key: str) -> None:
         key = CHAR_TO_KEY.get(key, key)
         self.send_monitor_command("sendkey {}".format(key))
+        time.sleep(0.01)
 
     def start(self) -> None:
         if self.booted:
diff --git a/nixos/modules/config/fonts/fontdir.nix b/nixos/modules/config/fonts/fontdir.nix
index db4b6c638ab4d..560918302ca66 100644
--- a/nixos/modules/config/fonts/fontdir.nix
+++ b/nixos/modules/config/fonts/fontdir.nix
@@ -39,6 +39,7 @@ in
       decompressFonts = mkOption {
         type = types.bool;
         default = config.programs.xwayland.enable;
+        defaultText = literalExpression "config.programs.xwayland.enable";
         description = ''
           Whether to decompress fonts in
           <filename>/run/current-system/sw/share/X11/fonts</filename>.
diff --git a/nixos/modules/config/gtk/gtk-icon-cache.nix b/nixos/modules/config/gtk/gtk-icon-cache.nix
index 7441f4de40eb8..ff9aa7c6a0477 100644
--- a/nixos/modules/config/gtk/gtk-icon-cache.nix
+++ b/nixos/modules/config/gtk/gtk-icon-cache.nix
@@ -6,6 +6,7 @@ with lib;
     gtk.iconCache.enable = mkOption {
       type = types.bool;
       default = config.services.xserver.enable;
+      defaultText = literalExpression "config.services.xserver.enable";
       description = ''
         Whether to build icon theme caches for GTK applications.
       '';
diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix
index 545d4a3dca61e..5b8d5b214496b 100644
--- a/nixos/modules/config/i18n.nix
+++ b/nixos/modules/config/i18n.nix
@@ -14,6 +14,12 @@ with lib;
           allLocales = any (x: x == "all") config.i18n.supportedLocales;
           locales = config.i18n.supportedLocales;
         };
+        defaultText = literalExpression ''
+          pkgs.buildPackages.glibcLocales.override {
+            allLocales = any (x: x == "all") config.i18n.supportedLocales;
+            locales = config.i18n.supportedLocales;
+          }
+        '';
         example = literalExpression "pkgs.glibcLocales";
         description = ''
           Customized pkg.glibcLocales package.
diff --git a/nixos/modules/misc/meta.nix b/nixos/modules/misc/meta.nix
index 1410e33342a6b..3dd97cbec235e 100644
--- a/nixos/modules/misc/meta.nix
+++ b/nixos/modules/misc/meta.nix
@@ -37,7 +37,7 @@ in
         type = listOfMaintainers;
         internal = true;
         default = [];
-        example = [ lib.maintainers.all ];
+        example = literalExpression ''[ lib.maintainers.all ]'';
         description = ''
           List of maintainers of each module.  This option should be defined at
           most once per module.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 1d51fca02fbf1..f36e7dd67eaee 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -898,6 +898,7 @@
   ./services/networking/unbound.nix
   ./services/networking/unifi.nix
   ./services/video/unifi-video.nix
+  ./services/video/rtsp-simple-server.nix
   ./services/networking/v2ray.nix
   ./services/networking/vsftpd.nix
   ./services/networking/wasabibackend.nix
diff --git a/nixos/modules/programs/bcc.nix b/nixos/modules/programs/bcc.nix
index d76249bb5cab4..e475c6ceaa6cc 100644
--- a/nixos/modules/programs/bcc.nix
+++ b/nixos/modules/programs/bcc.nix
@@ -1,9 +1,9 @@
-{ config, lib, ... }:
+{ config, pkgs, lib, ... }:
 {
   options.programs.bcc.enable = lib.mkEnableOption "bcc";
 
   config = lib.mkIf config.programs.bcc.enable {
-    environment.systemPackages = [ config.boot.kernelPackages.bcc ];
-    boot.extraModulePackages = [ config.boot.kernelPackages.bcc ];
+    environment.systemPackages = [ pkgs.bcc ];
+    boot.extraModulePackages = [ pkgs.bcc ];
   };
 }
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index b03bf290fd231..8ed7a721a3ef8 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -38,6 +38,7 @@ let
 
       p11Auth = mkOption {
         default = config.security.pam.p11.enable;
+        defaultText = literalExpression "config.security.pam.p11.enable";
         type = types.bool;
         description = ''
           If set, keys listed in
@@ -49,6 +50,7 @@ let
 
       u2fAuth = mkOption {
         default = config.security.pam.u2f.enable;
+        defaultText = literalExpression "config.security.pam.u2f.enable";
         type = types.bool;
         description = ''
           If set, users listed in
@@ -61,6 +63,7 @@ let
 
       yubicoAuth = mkOption {
         default = config.security.pam.yubico.enable;
+        defaultText = literalExpression "config.security.pam.yubico.enable";
         type = types.bool;
         description = ''
           If set, users listed in
@@ -83,6 +86,7 @@ let
 
       usbAuth = mkOption {
         default = config.security.pam.usb.enable;
+        defaultText = literalExpression "config.security.pam.usb.enable";
         type = types.bool;
         description = ''
           If set, users listed in
@@ -93,6 +97,7 @@ let
 
       otpwAuth = mkOption {
         default = config.security.pam.enableOTPW;
+        defaultText = literalExpression "config.security.pam.enableOTPW";
         type = types.bool;
         description = ''
           If set, the OTPW system will be used (if
@@ -126,6 +131,7 @@ let
 
       fprintAuth = mkOption {
         default = config.services.fprintd.enable;
+        defaultText = literalExpression "config.services.fprintd.enable";
         type = types.bool;
         description = ''
           If set, fingerprint reader will be used (if exists and
@@ -135,6 +141,7 @@ let
 
       oathAuth = mkOption {
         default = config.security.pam.oath.enable;
+        defaultText = literalExpression "config.security.pam.oath.enable";
         type = types.bool;
         description = ''
           If set, the OATH Toolkit will be used.
@@ -249,6 +256,7 @@ let
 
       pamMount = mkOption {
         default = config.security.pam.mount.enable;
+        defaultText = literalExpression "config.security.pam.mount.enable";
         type = types.bool;
         description = ''
           Enable PAM mount (pam_mount) system to mount fileystems on user login.
diff --git a/nixos/modules/services/audio/icecast.nix b/nixos/modules/services/audio/icecast.nix
index 6ca20a7a10866..5ee5bd745f96e 100644
--- a/nixos/modules/services/audio/icecast.nix
+++ b/nixos/modules/services/audio/icecast.nix
@@ -50,6 +50,7 @@ in {
         type = types.nullOr types.str;
         description = "DNS name or IP address that will be used for the stream directory lookups or possibily the playlist generation if a Host header is not provided.";
         default = config.networking.domain;
+        defaultText = literalExpression "config.networking.domain";
       };
 
       admin = {
diff --git a/nixos/modules/services/audio/navidrome.nix b/nixos/modules/services/audio/navidrome.nix
index c2fe429f9844e..3660e05310be1 100644
--- a/nixos/modules/services/audio/navidrome.nix
+++ b/nixos/modules/services/audio/navidrome.nix
@@ -9,7 +9,7 @@ in {
   options = {
     services.navidrome = {
 
-      enable = mkEnableOption pkgs.navidrome.meta.description;
+      enable = mkEnableOption "Navidrome music server";
 
       settings = mkOption rec {
         type = settingsFormat.type;
diff --git a/nixos/modules/services/audio/ympd.nix b/nixos/modules/services/audio/ympd.nix
index 36c5527027ffa..84b72d1425132 100644
--- a/nixos/modules/services/audio/ympd.nix
+++ b/nixos/modules/services/audio/ympd.nix
@@ -31,6 +31,7 @@ in {
         port = mkOption {
           type = types.int;
           default = config.services.mpd.network.port;
+          defaultText = literalExpression "config.services.mpd.network.port";
           description = "The port where MPD is listening.";
           example = 6600;
         };
diff --git a/nixos/modules/services/backup/bacula.nix b/nixos/modules/services/backup/bacula.nix
index cc8b77cbfbe8e..5989020423463 100644
--- a/nixos/modules/services/backup/bacula.nix
+++ b/nixos/modules/services/backup/bacula.nix
@@ -302,6 +302,7 @@ in {
 
       name = mkOption {
         default = "${config.networking.hostName}-fd";
+        defaultText = literalExpression ''"''${config.networking.hostName}-fd"'';
         type = types.str;
         description = ''
           The client name that must be used by the Director when connecting.
@@ -364,6 +365,7 @@ in {
 
       name = mkOption {
         default = "${config.networking.hostName}-sd";
+        defaultText = literalExpression ''"''${config.networking.hostName}-sd"'';
         type = types.str;
         description = ''
           Specifies the Name of the Storage daemon.
@@ -439,6 +441,7 @@ in {
 
       name = mkOption {
         default = "${config.networking.hostName}-dir";
+        defaultText = literalExpression ''"''${config.networking.hostName}-dir"'';
         type = types.str;
         description = ''
           The director name used by the system administrator. This directive is
diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix
index b2147c1bbfc93..220c571b927e5 100644
--- a/nixos/modules/services/backup/borgbackup.nix
+++ b/nixos/modules/services/backup/borgbackup.nix
@@ -152,7 +152,6 @@ let
       serviceConfig = {
         # The service's only task is to ensure that the specified path exists
         Type = "oneshot";
-        WorkingDirectory = cfg.path;
       };
       wantedBy = [ "multi-user.target" ];
     };
diff --git a/nixos/modules/services/cluster/kubernetes/kubelet.nix b/nixos/modules/services/cluster/kubernetes/kubelet.nix
index eb0cb1f3dbc0c..2806f73375bca 100644
--- a/nixos/modules/services/cluster/kubernetes/kubelet.nix
+++ b/nixos/modules/services/cluster/kubernetes/kubelet.nix
@@ -168,6 +168,7 @@ in
     hostname = mkOption {
       description = "Kubernetes kubelet hostname override.";
       default = config.networking.hostName;
+      defaultText = literalExpression "config.networking.hostName";
       type = str;
     };
 
diff --git a/nixos/modules/services/cluster/kubernetes/pki.nix b/nixos/modules/services/cluster/kubernetes/pki.nix
index faf951d815741..76ab03cd520ba 100644
--- a/nixos/modules/services/cluster/kubernetes/pki.nix
+++ b/nixos/modules/services/cluster/kubernetes/pki.nix
@@ -98,6 +98,7 @@ in
         the public and private keys respectively.
       '';
       default = "${config.services.cfssl.dataDir}/ca";
+      defaultText = literalExpression ''"''${config.services.cfssl.dataDir}/ca"'';
       type = str;
     };
 
diff --git a/nixos/modules/services/cluster/kubernetes/proxy.nix b/nixos/modules/services/cluster/kubernetes/proxy.nix
index a92043d52597c..a09efcef94eaf 100644
--- a/nixos/modules/services/cluster/kubernetes/proxy.nix
+++ b/nixos/modules/services/cluster/kubernetes/proxy.nix
@@ -37,6 +37,7 @@ in
     hostname = mkOption {
       description = "Kubernetes proxy hostname override.";
       default = config.networking.hostName;
+      defaultText = literalExpression "config.networking.hostName";
       type = str;
     };
 
diff --git a/nixos/modules/services/computing/slurm/slurm.nix b/nixos/modules/services/computing/slurm/slurm.nix
index 0c96f32313297..d2f3feffc970c 100644
--- a/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixos/modules/services/computing/slurm/slurm.nix
@@ -80,6 +80,7 @@ in
         dbdHost = mkOption {
           type = types.str;
           default = config.networking.hostName;
+          defaultText = literalExpression "config.networking.hostName";
           description = ''
             Hostname of the machine where <literal>slurmdbd</literal>
             is running (i.e. name returned by <literal>hostname -s</literal>).
diff --git a/nixos/modules/services/continuous-integration/github-runner.nix b/nixos/modules/services/continuous-integration/github-runner.nix
index 943c1e4598df5..59370f43fe750 100644
--- a/nixos/modules/services/continuous-integration/github-runner.nix
+++ b/nixos/modules/services/continuous-integration/github-runner.nix
@@ -58,6 +58,7 @@ in
       '';
       example = "nixos";
       default = config.networking.hostName;
+      defaultText = literalExpression "config.networking.hostName";
     };
 
     runnerGroup = mkOption {
diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix
index d6cde77c0a3f5..ccb7cc21734eb 100644
--- a/nixos/modules/services/continuous-integration/hydra/default.nix
+++ b/nixos/modules/services/continuous-integration/hydra/default.nix
@@ -203,6 +203,7 @@ in
       buildMachinesFiles = mkOption {
         type = types.listOf types.path;
         default = optional (config.nix.buildMachines != []) "/etc/nix/machines";
+        defaultText = literalExpression ''optional (config.nix.buildMachines != []) "/etc/nix/machines"'';
         example = [ "/etc/nix/machines" "/var/lib/hydra/provisioner/machines" ];
         description = "List of files containing build machines.";
       };
diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix
index 0e8860a02819c..96fcd6d2c8b30 100644
--- a/nixos/modules/services/games/factorio.nix
+++ b/nixos/modules/services/games/factorio.nix
@@ -75,8 +75,8 @@ in
         description = ''
           The name of the savegame that will be used by the server.
 
-          When not present in ${stateDir}/saves, a new map with default
-          settings will be generated before starting the service.
+          When not present in /var/lib/''${config.services.factorio.stateDirName}/saves,
+          a new map with default settings will be generated before starting the service.
         '';
       };
       # TODO Add more individual settings as nixos-options?
diff --git a/nixos/modules/services/logging/journalwatch.nix b/nixos/modules/services/logging/journalwatch.nix
index 576c646c0f58b..fb86904d1ea29 100644
--- a/nixos/modules/services/logging/journalwatch.nix
+++ b/nixos/modules/services/logging/journalwatch.nix
@@ -74,6 +74,7 @@ in {
       mailFrom = mkOption {
         type = types.str;
         default = "journalwatch@${config.networking.hostName}";
+        defaultText = literalExpression ''"journalwatch@''${config.networking.hostName}"'';
         description = ''
           Mail address to send journalwatch reports from.
         '';
diff --git a/nixos/modules/services/logging/klogd.nix b/nixos/modules/services/logging/klogd.nix
index 2d1f515da9209..8d371c161eb18 100644
--- a/nixos/modules/services/logging/klogd.nix
+++ b/nixos/modules/services/logging/klogd.nix
@@ -10,6 +10,7 @@ with lib;
     services.klogd.enable = mkOption {
       type = types.bool;
       default = versionOlder (getVersion config.boot.kernelPackages.kernel) "3.5";
+      defaultText = literalExpression ''versionOlder (getVersion config.boot.kernelPackages.kernel) "3.5"'';
       description = ''
         Whether to enable klogd, the kernel log message processing
         daemon.  Since systemd handles logging of kernel messages on
diff --git a/nixos/modules/services/mail/opendkim.nix b/nixos/modules/services/mail/opendkim.nix
index beff57613afc5..f1ffc5d3aeef2 100644
--- a/nixos/modules/services/mail/opendkim.nix
+++ b/nixos/modules/services/mail/opendkim.nix
@@ -55,6 +55,7 @@ in {
       domains = mkOption {
         type = types.str;
         default = "csl:${config.networking.hostName}";
+        defaultText = literalExpression ''"csl:''${config.networking.hostName}"'';
         example = "csl:example.com,mydomain.net";
         description = ''
           Local domains set (see <literal>opendkim(8)</literal> for more information on datasets).
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index c4ea091a03802..26ad1ad5536aa 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -17,6 +17,7 @@ in {
     name = mkOption {
       description = "Etcd unique node name.";
       default = config.networking.hostName;
+      defaultText = literalExpression "config.networking.hostName";
       type = types.str;
     };
 
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index c0f7661c5698b..022a73c2b596a 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -299,7 +299,7 @@ in
               ENABLED = true;
               MAILER_TYPE = "sendmail";
               FROM = "do-not-reply@example.org";
-              SENDMAIL_PATH = "${pkgs.system-sendmail}/bin/sendmail";
+              SENDMAIL_PATH = "''${pkgs.system-sendmail}/bin/sendmail";
             };
             other = {
               SHOW_FOOTER_VERSION = false;
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index b2abe70627d0d..01a7ea42d9db4 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -475,6 +475,7 @@ in {
       host = mkOption {
         type = types.str;
         default = config.networking.hostName;
+        defaultText = literalExpression "config.networking.hostName";
         description = "GitLab host name. Used e.g. for copy-paste URLs.";
       };
 
@@ -534,6 +535,7 @@ in {
         host = mkOption {
           type = types.str;
           default = config.services.gitlab.host;
+          defaultText = literalExpression "config.services.gitlab.host";
           description = "GitLab container registry host name.";
         };
         port = mkOption {
diff --git a/nixos/modules/services/misc/matrix-appservice-discord.nix b/nixos/modules/services/misc/matrix-appservice-discord.nix
index c448614eca328..947471e56b46d 100644
--- a/nixos/modules/services/misc/matrix-appservice-discord.nix
+++ b/nixos/modules/services/misc/matrix-appservice-discord.nix
@@ -98,6 +98,9 @@ in {
       serviceDependencies = mkOption {
         type = with types; listOf str;
         default = optional config.services.matrix-synapse.enable "matrix-synapse.service";
+        defaultText = literalExpression ''
+          optional config.services.matrix-synapse.enable "matrix-synapse.service"
+        '';
         description = ''
           List of Systemd services to require and wait for when starting the application service,
           such as the Matrix homeserver if it's running on the same host.
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index 950c72c6e589b..0f96f6b1ee225 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -227,6 +227,7 @@ in {
         type = types.str;
         example = "example.com";
         default = config.networking.hostName;
+        defaultText = literalExpression "config.networking.hostName";
         description = ''
           The domain name of the server, with optional explicit port.
           This is used by remote servers to look up the server address.
@@ -379,6 +380,11 @@ in {
         default = if versionAtLeast config.system.stateVersion "18.03"
           then "psycopg2"
           else "sqlite3";
+        defaultText = literalExpression ''
+          if versionAtLeast config.system.stateVersion "18.03"
+            then "psycopg2"
+            else "sqlite3"
+        '';
         description = ''
           The database engine name. Can be sqlite or psycopg2.
         '';
diff --git a/nixos/modules/services/misc/mautrix-telegram.nix b/nixos/modules/services/misc/mautrix-telegram.nix
index 59d0b6824090c..3b070b873b048 100644
--- a/nixos/modules/services/misc/mautrix-telegram.nix
+++ b/nixos/modules/services/misc/mautrix-telegram.nix
@@ -108,6 +108,9 @@ in {
       serviceDependencies = mkOption {
         type = with types; listOf str;
         default = optional config.services.matrix-synapse.enable "matrix-synapse.service";
+        defaultText = literalExpression ''
+          optional config.services.matrix-synapse.enable "matrix-synapse.service"
+        '';
         description = ''
           List of Systemd services to require and wait for when starting the application service.
         '';
diff --git a/nixos/modules/services/misc/moonraker.nix b/nixos/modules/services/misc/moonraker.nix
index de8668a0c066e..e08d2f84212dc 100644
--- a/nixos/modules/services/misc/moonraker.nix
+++ b/nixos/modules/services/misc/moonraker.nix
@@ -18,6 +18,7 @@ in {
       klipperSocket = mkOption {
         type = types.path;
         default = config.services.klipper.apiSocket;
+        defaultText = literalExpression "config.services.klipper.apiSocket";
         description = "Path to Klipper's API socket.";
       };
 
diff --git a/nixos/modules/services/misc/mx-puppet-discord.nix b/nixos/modules/services/misc/mx-puppet-discord.nix
index c34803f97223f..b6f5e04511ae3 100644
--- a/nixos/modules/services/misc/mx-puppet-discord.nix
+++ b/nixos/modules/services/misc/mx-puppet-discord.nix
@@ -39,7 +39,7 @@ in {
 
           #defaults to sqlite but can be configured to use postgresql with
           #connstring
-          database.filename = "${dataDir}/mx-puppet-discord/database.db";
+          database.filename = "${dataDir}/database.db";
           logging = {
             console = "info";
             lineDateFormat = "MMM-D HH:mm:ss.SSS";
@@ -67,6 +67,9 @@ in {
       serviceDependencies = mkOption {
         type = with types; listOf str;
         default = optional config.services.matrix-synapse.enable "matrix-synapse.service";
+        defaultText = literalExpression ''
+          optional config.services.matrix-synapse.enable "matrix-synapse.service"
+        '';
         description = ''
           List of Systemd services to require and wait for when starting the application service.
         '';
@@ -110,7 +113,9 @@ in {
         UMask = 0027;
 
         ExecStart = ''
-          ${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -c ${settingsFile}
+          ${pkgs.mx-puppet-discord}/bin/mx-puppet-discord \
+            -c ${settingsFile} \
+            -f ${registrationFile}
         '';
       };
     };
diff --git a/nixos/modules/services/misc/sourcehut/default.nix b/nixos/modules/services/misc/sourcehut/default.nix
index 9c812d6b043c4..c84a75b0ca029 100644
--- a/nixos/modules/services/misc/sourcehut/default.nix
+++ b/nixos/modules/services/misc/sourcehut/default.nix
@@ -71,6 +71,9 @@ in
     originBase = mkOption {
       type = types.str;
       default = with config.networking; hostName + lib.optionalString (domain != null) ".${domain}";
+      defaultText = literalExpression ''
+        with config.networking; hostName + optionalString (domain != null) ".''${domain}"
+      '';
       description = ''
         Host name used by reverse-proxy and for default settings. Will host services at git."''${originBase}". For example: git.sr.ht
       '';
diff --git a/nixos/modules/services/misc/xmrig.nix b/nixos/modules/services/misc/xmrig.nix
index cf01bb119e894..c5c3803920c8d 100644
--- a/nixos/modules/services/misc/xmrig.nix
+++ b/nixos/modules/services/misc/xmrig.nix
@@ -18,6 +18,7 @@ with lib;
       package = mkOption {
         type = types.package;
         default = pkgs.xmrig;
+        defaultText = literalExpression "pkgs.xmrig";
         example = literalExpression "pkgs.xmrig-mo";
         description = "XMRig package to use.";
       };
diff --git a/nixos/modules/services/monitoring/collectd.nix b/nixos/modules/services/monitoring/collectd.nix
index 6af04d22f0f70..660d108587dee 100644
--- a/nixos/modules/services/monitoring/collectd.nix
+++ b/nixos/modules/services/monitoring/collectd.nix
@@ -132,7 +132,12 @@ in {
     users.users = optionalAttrs (cfg.user == "collectd") {
       collectd = {
         isSystemUser = true;
+        group = "collectd";
       };
     };
+
+    users.groups = optionalAttrs (cfg.user == "collectd") {
+      collectd = {};
+    };
   };
 }
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index 4690a252c9259..0dbb33530c928 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -324,6 +324,7 @@ in {
 
       mongoUrl = mkOption {
         default = "mongodb://${config.services.mongodb.bind_ip}:27017/seyren";
+        defaultText = literalExpression ''"mongodb://''${config.services.mongodb.bind_ip}:27017/seyren"'';
         description = "Mongodb connection string.";
         type = types.str;
       };
diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix
index 83020d52fc82b..2c7f0ed196688 100644
--- a/nixos/modules/services/monitoring/nagios.nix
+++ b/nixos/modules/services/monitoring/nagios.nix
@@ -131,6 +131,7 @@ in
       validateConfig = mkOption {
         type = types.bool;
         default = pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform;
+        defaultText = literalExpression "pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform";
         description = "if true, the syntax of the nagios configuration file is checked at build time";
       };
 
diff --git a/nixos/modules/services/monitoring/parsedmarc.nix b/nixos/modules/services/monitoring/parsedmarc.nix
index eeee04b4400ca..8571e1f01ed69 100644
--- a/nixos/modules/services/monitoring/parsedmarc.nix
+++ b/nixos/modules/services/monitoring/parsedmarc.nix
@@ -93,6 +93,7 @@ in
         dashboard = lib.mkOption {
           type = lib.types.bool;
           default = config.services.grafana.enable;
+          defaultText = lib.literalExpression "config.services.grafana.enable";
           description = ''
             Whether the official parsedmarc grafana dashboard should
             be provisioned to the local grafana instance.
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix
index 62e90232e114c..d29d50706ef60 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -61,6 +61,7 @@ let
     "rtl_433"
     "script"
     "snmp"
+    "smartctl"
     "smokeping"
     "sql"
     "surfboard"
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
index f57589a59c7bc..4d3c1fa267e5f 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
@@ -76,6 +76,9 @@ in
   serviceOpts = {
     serviceConfig = {
       DynamicUser = false;
+      # By default, each prometheus exporter only gets AF_INET & AF_INET6,
+      # but AF_UNIX is needed to read from the `showq`-socket.
+      RestrictAddressFamilies = [ "AF_UNIX" ];
       ExecStart = ''
         ${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
           --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix b/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix
new file mode 100644
index 0000000000000..b6416b93e69c4
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/exporters/smartctl.nix
@@ -0,0 +1,64 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+  cfg = config.services.prometheus.exporters.smartctl;
+  format = pkgs.formats.yaml {};
+  configFile = format.generate "smartctl-exporter.yml" {
+    smartctl_exporter = {
+      bind_to = "${cfg.listenAddress}:${toString cfg.port}";
+      url_path = "/metrics";
+      smartctl_location = "${pkgs.smartmontools}/bin/smartctl";
+      collect_not_more_than_period = cfg.maxInterval;
+      devices = cfg.devices;
+    };
+  };
+in {
+  port = 9633;
+
+  extraOpts = {
+    devices = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = literalExpression ''
+        [ "/dev/sda", "/dev/nvme0n1" ];
+      '';
+      description = ''
+        Paths to disks that will be monitored.
+      '';
+    };
+    maxInterval = mkOption {
+      type = types.str;
+      default = "60s";
+      example = "2m";
+      description = ''
+        Interval that limits how often a disk can be queried.
+      '';
+    };
+  };
+
+  serviceOpts = {
+    serviceConfig = {
+      AmbientCapabilities = [
+        "CAP_SYS_ADMIN"
+      ];
+      CapabilityBoundingSet = [
+        "CAP_SYS_ADMIN"
+      ];
+      DevicePolicy = "closed";
+      DeviceAllow = lib.mkForce cfg.devices;
+      ExecStart = ''
+        ${pkgs.prometheus-smartctl-exporter}/bin/smartctl_exporter -config ${configFile}
+      '';
+      PrivateDevices = lib.mkForce false;
+      ProtectProc = "invisible";
+      ProcSubset = "pid";
+      SupplementaryGroups = [ "disk" ];
+      SystemCallFilter = [
+        "@system-service"
+        "~@privileged @resources"
+      ];
+    };
+  };
+}
diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix
index 3ea254371142b..73021b1b4d38f 100644
--- a/nixos/modules/services/monitoring/smartd.nix
+++ b/nixos/modules/services/monitoring/smartd.nix
@@ -125,6 +125,7 @@ in
         mail = {
           enable = mkOption {
             default = config.services.mail.sendmailSetuidWrapper != null;
+            defaultText = literalExpression "config.services.mail.sendmailSetuidWrapper != null";
             type = types.bool;
             description = "Whenever to send e-mail notifications.";
           };
@@ -169,12 +170,14 @@ in
         x11 = {
           enable = mkOption {
             default = config.services.xserver.enable;
+            defaultText = literalExpression "config.services.xserver.enable";
             type = types.bool;
             description = "Whenever to send X11 xmessage notifications.";
           };
 
           display = mkOption {
             default = ":${toString config.services.xserver.display}";
+            defaultText = literalExpression ''":''${toString config.services.xserver.display}"'';
             type = types.str;
             description = "DISPLAY to send X11 notifications to.";
           };
diff --git a/nixos/modules/services/network-filesystems/drbd.nix b/nixos/modules/services/network-filesystems/drbd.nix
index 916e7eaaaa949..c730e0b34e90b 100644
--- a/nixos/modules/services/network-filesystems/drbd.nix
+++ b/nixos/modules/services/network-filesystems/drbd.nix
@@ -47,19 +47,17 @@ let cfg = config.services.drbd; in
         options drbd usermode_helper=/run/current-system/sw/bin/drbdadm
       '';
 
-    environment.etc.drbd.conf =
+    environment.etc."drbd.conf" =
       { source = pkgs.writeText "drbd.conf" cfg.config; };
 
     systemd.services.drbd = {
       after = [ "systemd-udev.settle.service" "network.target" ];
       wants = [ "systemd-udev.settle.service" ];
       wantedBy = [ "multi-user.target" ];
-      script = ''
-        ${pkgs.drbd}/sbin/drbdadm up all
-      '';
-      serviceConfig.ExecStop = ''
-        ${pkgs.drbd}/sbin/drbdadm down all
-      '';
+      serviceConfig = {
+        ExecStart = "${pkgs.drbd}/sbin/drbdadm up all";
+        ExecStop = "${pkgs.drbd}/sbin/drbdadm down all";
+      };
     };
   };
 }
diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix
index 36b72ca48b2c3..5482b2aaf88cc 100644
--- a/nixos/modules/services/network-filesystems/ipfs.nix
+++ b/nixos/modules/services/network-filesystems/ipfs.nix
@@ -79,6 +79,11 @@ in
           if versionAtLeast config.system.stateVersion "17.09"
           then "/var/lib/ipfs"
           else "/var/lib/ipfs/.ipfs";
+        defaultText = literalExpression ''
+          if versionAtLeast config.system.stateVersion "17.09"
+          then "/var/lib/ipfs"
+          else "/var/lib/ipfs/.ipfs"
+        '';
         description = "The data dir for IPFS";
       };
 
diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix
index f2b2e4c4d5d4f..e44f8d4cf3026 100644
--- a/nixos/modules/services/networking/bind.nix
+++ b/nixos/modules/services/networking/bind.nix
@@ -144,6 +144,7 @@ in
 
       forwarders = mkOption {
         default = config.networking.nameservers;
+        defaultText = literalExpression "config.networking.nameservers";
         type = types.listOf types.str;
         description = "
           List of servers we should forward requests to.
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index 792b2e7f5dfeb..ca9c422e6d7cb 100644
--- a/nixos/modules/services/networking/consul.nix
+++ b/nixos/modules/services/networking/consul.nix
@@ -8,7 +8,9 @@ let
 
   configOptions = {
     data_dir = dataDir;
-    ui = cfg.webUi;
+    ui_config = {
+      enabled = cfg.webUi;
+    };
   } // cfg.extraConfig;
 
   configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ]
diff --git a/nixos/modules/services/networking/coturn.nix b/nixos/modules/services/networking/coturn.nix
index 610754e9bd39d..ce563c31136f6 100644
--- a/nixos/modules/services/networking/coturn.nix
+++ b/nixos/modules/services/networking/coturn.nix
@@ -193,6 +193,7 @@ in {
       realm = mkOption {
         type = types.str;
         default = config.networking.hostName;
+        defaultText = literalExpression "config.networking.hostName";
         example = "example.com";
         description = ''
           The default realm to be used for the users when no explicit
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index fd9c216b06029..021b28d5c34f2 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -29,10 +29,10 @@ let
   configFile = if (cfg.configFile != null) then cfg.configFile else configFile';
 
   preStart = ''
-    install ${configFile} /run/${RuntimeDirectory}/ddclient.conf
+    install --mode=0400 ${configFile} /run/${RuntimeDirectory}/ddclient.conf
     ${lib.optionalString (cfg.configFile == null) (if (cfg.passwordFile != null) then ''
-      password=$(head -n 1 ${cfg.passwordFile})
-      sed -i "s/^password=$/password=$password/" /run/${RuntimeDirectory}/ddclient.conf
+      password=$(printf "%q" "$(head -n 1 "${cfg.passwordFile}")")
+      sed -i "s|^password=$|password=$password|" /run/${RuntimeDirectory}/ddclient.conf
     '' else ''
       sed -i '/^password=$/d' /run/${RuntimeDirectory}/ddclient.conf
     '')}
diff --git a/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixos/modules/services/networking/dnscrypt-wrapper.nix
index 400d6e67044e2..c2add170e9cc7 100644
--- a/nixos/modules/services/networking/dnscrypt-wrapper.nix
+++ b/nixos/modules/services/networking/dnscrypt-wrapper.nix
@@ -145,6 +145,7 @@ in {
     providerName = mkOption {
       type = types.str;
       default = "2.dnscrypt-cert.${config.networking.hostName}";
+      defaultText = literalExpression ''"2.dnscrypt-cert.''${config.networking.hostName}"'';
       example = "2.dnscrypt-cert.myresolver";
       description = ''
         The name that will be given to this DNSCrypt resolver.
diff --git a/nixos/modules/services/networking/flannel.nix b/nixos/modules/services/networking/flannel.nix
index b15339870ee2d..ac84b3d35a3d8 100644
--- a/nixos/modules/services/networking/flannel.nix
+++ b/nixos/modules/services/networking/flannel.nix
@@ -93,6 +93,9 @@ in {
       '';
       type = types.nullOr types.str;
       default = with config.networking; (hostName + optionalString (domain != null) ".${domain}");
+      defaultText = literalExpression ''
+        with config.networking; (hostName + optionalString (domain != null) ".''${domain}")
+      '';
       example = "node1.example.com";
     };
 
diff --git a/nixos/modules/services/networking/knot.nix b/nixos/modules/services/networking/knot.nix
index 67eadbd767024..a58a03997b3b8 100644
--- a/nixos/modules/services/networking/knot.nix
+++ b/nixos/modules/services/networking/knot.nix
@@ -80,13 +80,13 @@ in {
   };
 
   config = mkIf config.services.knot.enable {
+    users.groups.knot = {};
     users.users.knot = {
       isSystemUser = true;
       group = "knot";
       description = "Knot daemon user";
     };
 
-    users.groups.knot.gid = null;
     systemd.services.knot = {
       unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/";
       description = cfg.package.meta.description;
@@ -98,17 +98,52 @@ in {
         Type = "notify";
         ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
         ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
-        CapabilityBoundingSet = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
-        AmbientCapabilities = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
-        NoNewPrivileges = true;
         User = "knot";
+        Group = "knot";
+
+        AmbientCapabilities = [
+          "CAP_NET_BIND_SERVICE"
+        ];
+        CapabilityBoundingSet = [
+          "CAP_NET_BIND_SERVICE"
+        ];
+        DeviceAllow = "";
+        DevicePolicy = "closed";
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        PrivateUsers = false; # breaks capability passing
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "strict";
+        RemoveIPC = true;
+        Restart = "on-abort";
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+          "AF_UNIX"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime =true;
+        RestrictSUIDSGID = true;
         RuntimeDirectory = "knot";
         StateDirectory = "knot";
         StateDirectoryMode = "0700";
-        PrivateDevices = true;
-        RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
         SystemCallArchitectures = "native";
-        Restart = "on-abort";
+        SystemCallFilter = [
+          "@system-service"
+          "~@privileged"
+        ];
+        UMask = "0077";
       };
     };
 
diff --git a/nixos/modules/services/networking/lxd-image-server.nix b/nixos/modules/services/networking/lxd-image-server.nix
index 5ec6cacffa497..b119ba8acf634 100644
--- a/nixos/modules/services/networking/lxd-image-server.nix
+++ b/nixos/modules/services/networking/lxd-image-server.nix
@@ -55,9 +55,8 @@ in
         path = "/var/log/lxd-image-server/lxd-image-server.log";
         frequency = "daily";
         keep = 21;
-        user = "lxd-image-server";
-        group = cfg.group;
         extraConfig = ''
+          create 755 lxd-image-server ${cfg.group}
           missingok
           compress
           delaycompress
diff --git a/nixos/modules/services/networking/ncdns.nix b/nixos/modules/services/networking/ncdns.nix
index af17fc0814b2e..82c285d051607 100644
--- a/nixos/modules/services/networking/ncdns.nix
+++ b/nixos/modules/services/networking/ncdns.nix
@@ -76,6 +76,7 @@ in
       identity.hostname = mkOption {
         type = types.str;
         default = config.networking.hostName;
+        defaultText = literalExpression "config.networking.hostName";
         example = "example.com";
         description = ''
           The hostname of this ncdns instance, which defaults to the machine
diff --git a/nixos/modules/services/networking/nix-serve.nix b/nixos/modules/services/networking/nix-serve.nix
index 7fc145f2303d7..390f0ddaee83c 100644
--- a/nixos/modules/services/networking/nix-serve.nix
+++ b/nixos/modules/services/networking/nix-serve.nix
@@ -37,8 +37,6 @@ in
           nix-store --generate-binary-cache-key key-name secret-key-file public-key-file
           ```
 
-          Make sure user `nix-serve` has read access to the private key file.
-
           For more details see <citerefentry><refentrytitle>nix-store</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
         '';
       };
@@ -61,16 +59,22 @@ in
 
       path = [ config.nix.package.out pkgs.bzip2.bin ];
       environment.NIX_REMOTE = "daemon";
-      environment.NIX_SECRET_KEY_FILE = cfg.secretKeyFile;
+
+      script = ''
+        ${lib.optionalString (cfg.secretKeyFile != null) ''
+          export NIX_SECRET_KEY_FILE="$CREDENTIALS_DIRECTORY/NIX_SECRET_KEY_FILE"
+        ''}
+        exec ${pkgs.nix-serve}/bin/nix-serve --listen ${cfg.bindAddress}:${toString cfg.port} ${cfg.extraParams}
+      '';
 
       serviceConfig = {
         Restart = "always";
         RestartSec = "5s";
-        ExecStart = "${pkgs.nix-serve}/bin/nix-serve " +
-          "--listen ${cfg.bindAddress}:${toString cfg.port} ${cfg.extraParams}";
         User = "nix-serve";
         Group = "nix-serve";
         DynamicUser = true;
+        LoadCredential = lib.optionalString (cfg.secretKeyFile != null)
+          "NIX_SECRET_KEY_FILE:${cfg.secretKeyFile}";
       };
     };
   };
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index 893995165b9e4..cf6c9661dc1b0 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -603,6 +603,7 @@ in
     reuseport = mkOption {
       type = types.bool;
       default = pkgs.stdenv.isLinux;
+      defaultText = literalExpression "pkgs.stdenv.isLinux";
       description = ''
         Whether to enable SO_REUSEPORT on all used sockets. This lets multiple
         processes bind to the same port. This speeds up operation especially
diff --git a/nixos/modules/services/networking/ntp/chrony.nix b/nixos/modules/services/networking/ntp/chrony.nix
index d414936a2c2be..34728455a2120 100644
--- a/nixos/modules/services/networking/ntp/chrony.nix
+++ b/nixos/modules/services/networking/ntp/chrony.nix
@@ -52,6 +52,7 @@ in
 
       servers = mkOption {
         default = config.networking.timeServers;
+        defaultText = literalExpression "config.networking.timeServers";
         type = types.listOf types.str;
         description = ''
           The set of NTP servers from which to synchronise.
diff --git a/nixos/modules/services/networking/ntp/ntpd.nix b/nixos/modules/services/networking/ntp/ntpd.nix
index ce4802ce02450..12be0d045a857 100644
--- a/nixos/modules/services/networking/ntp/ntpd.nix
+++ b/nixos/modules/services/networking/ntp/ntpd.nix
@@ -77,6 +77,7 @@ in
 
       servers = mkOption {
         default = config.networking.timeServers;
+        defaultText = literalExpression "config.networking.timeServers";
         type = types.listOf types.str;
         description = ''
           The set of NTP servers from which to synchronise.
diff --git a/nixos/modules/services/networking/ntp/openntpd.nix b/nixos/modules/services/networking/ntp/openntpd.nix
index 9f3892e3b538e..e86b71291f960 100644
--- a/nixos/modules/services/networking/ntp/openntpd.nix
+++ b/nixos/modules/services/networking/ntp/openntpd.nix
@@ -23,6 +23,7 @@ in
 
     servers = mkOption {
       default = config.services.ntp.servers;
+      defaultText = literalExpression "config.services.ntp.servers";
       type = types.listOf types.str;
       inherit (options.services.ntp.servers) description;
     };
diff --git a/nixos/modules/services/networking/resilio.nix b/nixos/modules/services/networking/resilio.nix
index 4701b0e8143d2..891278506417d 100644
--- a/nixos/modules/services/networking/resilio.nix
+++ b/nixos/modules/services/networking/resilio.nix
@@ -58,6 +58,7 @@ in
         type = types.str;
         example = "Voltron";
         default = config.networking.hostName;
+        defaultText = literalExpression "config.networking.hostName";
         description = ''
           Name of the Resilio Sync device.
         '';
diff --git a/nixos/modules/services/networking/seafile.nix b/nixos/modules/services/networking/seafile.nix
index 856797b6b0209..d7fb22edebed7 100644
--- a/nixos/modules/services/networking/seafile.nix
+++ b/nixos/modules/services/networking/seafile.nix
@@ -124,6 +124,7 @@ in {
       type = types.package;
       description = "Which package to use for the seafile server.";
       default = pkgs.seafile-server;
+      defaultText = literalExpression "pkgs.seafile-server";
     };
 
     seahubExtraConf = mkOption {
diff --git a/nixos/modules/services/networking/shairport-sync.nix b/nixos/modules/services/networking/shairport-sync.nix
index ac526c0e9f6f4..eb61663e4d922 100644
--- a/nixos/modules/services/networking/shairport-sync.nix
+++ b/nixos/modules/services/networking/shairport-sync.nix
@@ -36,6 +36,14 @@ in
         '';
       };
 
+      openFirewall = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to automatically open ports in the firewall.
+        '';
+      };
+
       user = mkOption {
         type = types.str;
         default = "shairport";
@@ -45,6 +53,15 @@ in
         '';
       };
 
+      group = mkOption {
+        type = types.str;
+        default = "shairport";
+        description = ''
+          Group account name under which to run shairport-sync. The account
+          will be created.
+        '';
+      };
+
     };
 
   };
@@ -58,13 +75,22 @@ in
     services.avahi.publish.enable = true;
     services.avahi.publish.userServices = true;
 
-    users.users.${cfg.user} =
-      { description = "Shairport user";
+    users = {
+      users.${cfg.user} = {
+        description = "Shairport user";
         isSystemUser = true;
         createHome = true;
         home = "/var/lib/shairport-sync";
+        group = cfg.group;
         extraGroups = [ "audio" ] ++ optional config.hardware.pulseaudio.enable "pulse";
       };
+      groups.${cfg.group} = {};
+    };
+
+    networking.firewall = mkIf cfg.openFirewall {
+      allowedTCPPorts = [ 5000 ];
+      allowedUDPPortRanges = [ { from = 6001; to = 6011; } ];
+    };
 
     systemd.services.shairport-sync =
       {
@@ -73,6 +99,7 @@ in
         wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           User = cfg.user;
+          Group = cfg.group;
           ExecStart = "${pkgs.shairport-sync}/bin/shairport-sync ${cfg.arguments}";
           RuntimeDirectory = "shairport-sync";
         };
diff --git a/nixos/modules/services/networking/skydns.nix b/nixos/modules/services/networking/skydns.nix
index c4e959b57bbed..dea60a3862a38 100644
--- a/nixos/modules/services/networking/skydns.nix
+++ b/nixos/modules/services/networking/skydns.nix
@@ -49,6 +49,7 @@ in {
 
     nameservers = mkOption {
       default = map (n: n + ":53") config.networking.nameservers;
+      defaultText = literalExpression ''map (n: n + ":53") config.networking.nameservers'';
       type = types.listOf types.str;
       description = "Skydns list of nameservers to forward DNS requests to when not authoritative for a domain.";
       example = ["8.8.8.8:53" "8.8.4.4:53"];
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index c075cbbceac9a..bd71b158dbe32 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -241,6 +241,12 @@ in
           + FPing
           binary = ${config.security.wrapperDir}/fping
         '';
+        defaultText = literalExpression ''
+          '''
+            + FPing
+            binary = ''${config.security.wrapperDir}/fping
+          '''
+        '';
         description = "Probe configuration";
       };
       sendmail = mkOption {
diff --git a/nixos/modules/services/networking/soju.nix b/nixos/modules/services/networking/soju.nix
index 68a33e9dccba5..cb0acf4765ff1 100644
--- a/nixos/modules/services/networking/soju.nix
+++ b/nixos/modules/services/networking/soju.nix
@@ -43,6 +43,7 @@ in
     hostName = mkOption {
       type = types.str;
       default = config.networking.hostName;
+      defaultText = literalExpression "config.networking.hostName";
       description = "Server hostname.";
     };
 
diff --git a/nixos/modules/services/security/oauth2_proxy_nginx.nix b/nixos/modules/services/security/oauth2_proxy_nginx.nix
index d82ddb894ea55..5853c5a123c6b 100644
--- a/nixos/modules/services/security/oauth2_proxy_nginx.nix
+++ b/nixos/modules/services/security/oauth2_proxy_nginx.nix
@@ -8,6 +8,7 @@ in
     proxy = mkOption {
       type = types.str;
       default = config.services.oauth2_proxy.httpAddress;
+      defaultText = literalExpression "config.services.oauth2_proxy.httpAddress";
       description = ''
         The address of the reverse proxy endpoint for oauth2_proxy
       '';
diff --git a/nixos/modules/services/security/step-ca.nix b/nixos/modules/services/security/step-ca.nix
index db7f81acd2a39..27b2ceed1a430 100644
--- a/nixos/modules/services/security/step-ca.nix
+++ b/nixos/modules/services/security/step-ca.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, nixosTests, ... }:
 let
   cfg = config.services.step-ca;
   settingsFormat = (pkgs.formats.json { });
@@ -82,6 +82,8 @@ in
       });
     in
     {
+      passthru.tests.step-ca = nixosTests.step-ca;
+
       assertions =
         [
           {
diff --git a/nixos/modules/services/security/torsocks.nix b/nixos/modules/services/security/torsocks.nix
index 47ac95c4626e0..fdd6ac32cc662 100644
--- a/nixos/modules/services/security/torsocks.nix
+++ b/nixos/modules/services/security/torsocks.nix
@@ -37,6 +37,7 @@ in
       enable = mkOption {
         type        = types.bool;
         default     = config.services.tor.enable && config.services.tor.client.enable;
+        defaultText = literalExpression "config.services.tor.enable && config.services.tor.client.enable";
         description = ''
           Whether to build <literal>/etc/tor/torsocks.conf</literal>
           containing the specified global torsocks configuration.
diff --git a/nixos/modules/services/video/epgstation/default.nix b/nixos/modules/services/video/epgstation/default.nix
index 36f7b937d5acd..56bd9d9eeecab 100644
--- a/nixos/modules/services/video/epgstation/default.nix
+++ b/nixos/modules/services/video/epgstation/default.nix
@@ -48,7 +48,7 @@ let
 in
 {
   options.services.epgstation = {
-    enable = mkEnableOption pkgs.epgstation.meta.description;
+    enable = mkEnableOption "EPGStation: DTV Software in Japan";
 
     usePreconfiguredStreaming = mkOption {
       type = types.bool;
diff --git a/nixos/modules/services/video/mirakurun.nix b/nixos/modules/services/video/mirakurun.nix
index 16efb56cfd610..35303b2332c67 100644
--- a/nixos/modules/services/video/mirakurun.nix
+++ b/nixos/modules/services/video/mirakurun.nix
@@ -24,7 +24,7 @@ in
   {
     options = {
       services.mirakurun = {
-        enable = mkEnableOption mirakurun.meta.description;
+        enable = mkEnableOption "the Mirakurun DVR Tuner Server";
 
         port = mkOption {
           type = with types; nullOr port;
diff --git a/nixos/modules/services/video/rtsp-simple-server.nix b/nixos/modules/services/video/rtsp-simple-server.nix
new file mode 100644
index 0000000000000..644b1945a1ecb
--- /dev/null
+++ b/nixos/modules/services/video/rtsp-simple-server.nix
@@ -0,0 +1,80 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.rtsp-simple-server;
+  package = pkgs.rtsp-simple-server;
+  format = pkgs.formats.yaml {};
+in
+{
+  options = {
+    services.rtsp-simple-server = {
+      enable = mkEnableOption "RTSP Simple Server";
+
+      settings = mkOption {
+        description = ''
+          Settings for rtsp-simple-server.
+          Read more at <link xlink:href="https://github.com/aler9/rtsp-simple-server/blob/main/rtsp-simple-server.yml"/>
+        '';
+        type = format.type;
+
+        default = {
+          logLevel = "info";
+          logDestinations = [
+            "stdout"
+          ];
+          # we set this so when the user uses it, it just works (see LogsDirectory below). but it's not used by default.
+          logFile = "/var/log/rtsp-simple-server/rtsp-simple-server.log";
+        };
+
+        example = {
+          paths = {
+            cam = {
+              runOnInit = "ffmpeg -f v4l2 -i /dev/video0 -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH";
+              runOnInitRestart = true;
+            };
+          };
+        };
+      };
+
+      env = mkOption {
+        type = with types; attrsOf anything;
+        description = "Extra environment variables for RTSP Simple Server";
+        default = {};
+        example = {
+          RTSP_CONFKEY = "mykey";
+        };
+      };
+    };
+  };
+
+  config = mkIf (cfg.enable) {
+    # NOTE: rtsp-simple-server watches this file and automatically reloads if it changes
+    environment.etc."rtsp-simple-server.yaml".source = format.generate "rtsp-simple-server.yaml" cfg.settings;
+
+    systemd.services.rtsp-simple-server = {
+      environment = cfg.env;
+
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      path = with pkgs; [
+        ffmpeg
+      ];
+
+      serviceConfig = {
+        DynamicUser = true;
+        User = "rtsp-simple-server";
+        Group = "rtsp-simple-server";
+
+        LogsDirectory = "rtsp-simple-server";
+
+        # user likely may want to stream cameras, can't hurt to add video group
+        SupplementaryGroups = "video";
+
+        ExecStart = "${package}/bin/rtsp-simple-server /etc/rtsp-simple-server.yaml";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/ihatemoney/default.nix b/nixos/modules/services/web-apps/ihatemoney/default.nix
index 238241854c1ce..ad314c885ba8d 100644
--- a/nixos/modules/services/web-apps/ihatemoney/default.nix
+++ b/nixos/modules/services/web-apps/ihatemoney/default.nix
@@ -79,6 +79,7 @@ in
         email = mkOption {
           type = types.str;
           default = "ihatemoney@${config.networking.hostName}";
+          defaultText = literalExpression ''"ihatemoney@''${config.networking.hostName}"'';
           description = "The email of the sender of ihatemoney emails";
         };
       };
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 04ec7888950d5..b1a536e519db4 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -153,7 +153,7 @@ in {
     package = mkOption {
       type = types.package;
       description = "Which package to use for the Nextcloud instance.";
-      relatedPackages = [ "nextcloud21" "nextcloud22" ];
+      relatedPackages = [ "nextcloud21" "nextcloud22" "nextcloud23" ];
     };
     phpPackage = mkOption {
       type = types.package;
@@ -508,7 +508,7 @@ in {
 
   config = mkIf cfg.enable (mkMerge [
     { warnings = let
-        latest = 22;
+        latest = 23;
         upgradeWarning = major: nixos:
           ''
             A legacy Nextcloud install (from before NixOS ${nixos}) may be installed.
@@ -543,6 +543,7 @@ in {
         '')
         ++ (optional (versionOlder cfg.package.version "21") (upgradeWarning 20 "21.05"))
         ++ (optional (versionOlder cfg.package.version "22") (upgradeWarning 21 "21.11"))
+        ++ (optional (versionOlder cfg.package.version "23") (upgradeWarning 22 "22.05"))
         ++ (optional isUnsupportedMariadb ''
             You seem to be using MariaDB at an unsupported version (i.e. at least 10.6)!
             Please note that this isn't supported officially by Nextcloud. You can either
@@ -573,7 +574,8 @@ in {
           # nextcloud20 throws an eval-error because it's dropped).
           else if versionOlder stateVersion "21.03" then nextcloud20
           else if versionOlder stateVersion "21.11" then nextcloud21
-          else nextcloud22
+          else if versionOlder stateVersion "22.05" then nextcloud22
+          else nextcloud23
         );
 
       services.nextcloud.datadir = mkOptionDefault config.services.nextcloud.home;
diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml
index 9d9cb8dfb3f28..8f55086a2bd1f 100644
--- a/nixos/modules/services/web-apps/nextcloud.xml
+++ b/nixos/modules/services/web-apps/nextcloud.xml
@@ -11,7 +11,7 @@
   desktop client is packaged at <literal>pkgs.nextcloud-client</literal>.
  </para>
  <para>
-  The current default by NixOS is <package>nextcloud22</package> which is also the latest
+  The current default by NixOS is <package>nextcloud23</package> which is also the latest
   major version available.
  </para>
  <section xml:id="module-services-nextcloud-basic-usage">
diff --git a/nixos/modules/services/web-apps/openwebrx.nix b/nixos/modules/services/web-apps/openwebrx.nix
index 51005cd1e4972..9e90c01e0bbb0 100644
--- a/nixos/modules/services/web-apps/openwebrx.nix
+++ b/nixos/modules/services/web-apps/openwebrx.nix
@@ -9,6 +9,7 @@ in
     package = mkOption {
       type = types.package;
       default = pkgs.openwebrx;
+      defaultText = literalExpression "pkgs.openwebrx";
       description = "OpenWebRX package to use for the service";
     };
   };
diff --git a/nixos/modules/services/web-apps/peertube.nix b/nixos/modules/services/web-apps/peertube.nix
index 362a3358b7930..932ddcfef198a 100644
--- a/nixos/modules/services/web-apps/peertube.nix
+++ b/nixos/modules/services/web-apps/peertube.nix
@@ -234,6 +234,7 @@ in {
     package = lib.mkOption {
       type = lib.types.package;
       default = pkgs.peertube;
+      defaultText = lib.literalExpression "pkgs.peertube";
       description = "Peertube package to use.";
     };
   };
diff --git a/nixos/modules/services/web-servers/uwsgi.nix b/nixos/modules/services/web-servers/uwsgi.nix
index ac435951310eb..a1cad17336d8d 100644
--- a/nixos/modules/services/web-servers/uwsgi.nix
+++ b/nixos/modules/services/web-servers/uwsgi.nix
@@ -121,7 +121,7 @@ in {
               moin = {
                 type = "normal";
                 pythonPackages = self: with self; [ moinmoin ];
-                socket = "${config.services.uwsgi.runDir}/uwsgi.sock";
+                socket = "''${config.services.uwsgi.runDir}/uwsgi.sock";
               };
             };
           }
diff --git a/nixos/modules/services/web-servers/varnish/default.nix b/nixos/modules/services/web-servers/varnish/default.nix
index 0ebf58eb9f616..fe817313a993b 100644
--- a/nixos/modules/services/web-servers/varnish/default.nix
+++ b/nixos/modules/services/web-servers/varnish/default.nix
@@ -42,6 +42,7 @@ in
       stateDir = mkOption {
         type = types.path;
         default = "/var/spool/varnish/${config.networking.hostName}";
+        defaultText = literalExpression ''"/var/spool/varnish/''${config.networking.hostName}"'';
         description = "
           Directory holding all state for Varnish to run.
         ";
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 5a41f96497f2b..3296b72204856 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -296,9 +296,10 @@ in
     })
 
     (mkIf serviceCfg.contractor.enable {
-      environment.systemPackages = with  pkgs.pantheon; [
+      environment.systemPackages = with pkgs.pantheon; [
         contractor
-        extra-elementary-contracts
+        file-roller-contract
+        gnome-bluetooth-contract
       ];
 
       environment.pathsToLink = [
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 8a1793484e23e..9bacdaa9be984 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -4,6 +4,28 @@ let
   xcfg = config.services.xserver;
   cfg = xcfg.desktopManager.plasma5;
 
+  # Use only for **internal** options.
+  # This is not exactly user-friendly.
+  kdeConfigurationType = with types;
+    let
+      valueTypes = (oneOf [
+        bool
+        float
+        int
+        str
+      ]) // {
+        description = "KDE Configuration value";
+        emptyValue.value = "";
+      };
+      set = (nullOr (lazyAttrsOf valueTypes)) // {
+        description = "KDE Configuration set";
+        emptyValue.value = {};
+      };
+    in (lazyAttrsOf set) // {
+        description = "KDE Configuration file";
+        emptyValue.value = {};
+      };
+
   libsForQt5 = pkgs.plasma5Packages;
   inherit (libsForQt5) kdeGear kdeFrameworks plasma5;
   inherit (pkgs) writeText;
@@ -169,6 +191,37 @@ in
       type = types.bool;
       default = false;
     };
+
+    # Internally allows configuring kdeglobals globally
+    kdeglobals = mkOption {
+      internal = true;
+      default = {};
+      type = kdeConfigurationType;
+    };
+
+    # Internally allows configuring kwin globally
+    kwinrc = mkOption {
+      internal = true;
+      default = {};
+      type = kdeConfigurationType;
+    };
+
+    mobile.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable support for running the Plasma Mobile shell.
+      '';
+    };
+
+    mobile.installRecommendedSoftware = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Installs software recommended for use with Plasma Mobile, but which
+        is not strictly required for Plasma Mobile to run.
+      '';
+    };
   };
 
   imports = [
@@ -177,22 +230,8 @@ in
   ];
 
   config = mkMerge [
-    (mkIf cfg.enable {
-
-      # Seed our configuration into nixos-generate-config
-      system.nixos-generate-config.desktopConfiguration = [
-        ''
-          # Enable the Plasma 5 Desktop Environment.
-          services.xserver.displayManager.sddm.enable = true;
-          services.xserver.desktopManager.plasma5.enable = true;
-        ''
-      ];
-
-      services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-workspace ];
-      # Default to be `plasma` (X11) instead of `plasmawayland`, since plasma wayland currently has
-      # many tiny bugs.
-      # See: https://github.com/NixOS/nixpkgs/issues/143272
-      services.xserver.displayManager.defaultSession = mkDefault "plasma";
+    # Common Plasma dependencies
+    (mkIf (cfg.enable || cfg.mobile.enable) {
 
       security.wrappers = {
         kcheckpass = {
@@ -278,37 +317,24 @@ in
           kdeplasma-addons
           kgamma5
           khotkeys
-          kinfocenter
-          kmenuedit
           kscreen
           kscreenlocker
-          ksystemstats
           kwayland
           kwin
           kwrited
           libkscreen
           libksysguard
           milou
-          plasma-systemmonitor
           plasma-browser-integration
           plasma-integration
           polkit-kde-agent
-          spectacle
-          systemsettings
 
           plasma-desktop
           plasma-workspace
           plasma-workspace-wallpapers
 
-          dolphin
-          dolphin-plugins
-          ffmpegthumbs
-          kdegraphics-thumbnailers
-          khelpcenter
-          kio-extras
           konsole
           oxygen
-          print-manager
 
           breeze-icons
           pkgs.hicolor-icon-theme
@@ -319,10 +345,6 @@ in
           qtvirtualkeyboard
 
           pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
-
-          elisa
-          gwenview
-          okular
         ]
 
         # Phonon audio backend
@@ -396,7 +418,67 @@ in
           serviceConfig.Type = "oneshot";
           script = activationScript;
         };
+      };
+
+      xdg.portal.enable = true;
+      xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ];
+
+      # Update the start menu for each user that is currently logged in
+      system.userActivationScripts.plasmaSetup = activationScript;
+      services.xserver.displayManager.setupCommands = startplasma;
+
+      nixpkgs.config.firefox.enablePlasmaBrowserIntegration = true;
+
+      environment.etc = {
+        "xdg/kwinrc".text     = lib.generators.toINI {} cfg.kwinrc;
+        "xdg/kdeglobals".text = lib.generators.toINI {} cfg.kdeglobals;
+      };
+    })
+
+    # Plasma Desktop
+    (mkIf cfg.enable {
+
+      # Seed our configuration into nixos-generate-config
+      system.nixos-generate-config.desktopConfiguration = [
+        ''
+          # Enable the Plasma 5 Desktop Environment.
+          services.xserver.displayManager.sddm.enable = true;
+          services.xserver.desktopManager.plasma5.enable = true;
+        ''
+      ];
 
+      services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-workspace ];
+      # Default to be `plasma` (X11) instead of `plasmawayland`, since plasma wayland currently has
+      # many tiny bugs.
+      # See: https://github.com/NixOS/nixpkgs/issues/143272
+      services.xserver.displayManager.defaultSession = mkDefault "plasma";
+
+      environment.systemPackages =
+        with libsForQt5;
+        with plasma5; with kdeGear; with kdeFrameworks;
+        [
+          ksystemstats
+          kinfocenter
+          kmenuedit
+          plasma-systemmonitor
+          spectacle
+          systemsettings
+
+          dolphin
+          dolphin-plugins
+          ffmpegthumbs
+          kdegraphics-thumbnailers
+          khelpcenter
+          kio-extras
+          print-manager
+
+          elisa
+          gwenview
+          okular
+        ]
+      ;
+
+      systemd.user.services = {
         plasma-run-with-systemd = {
           description = "Run KDE Plasma via systemd";
           wantedBy = [ "basic.target" ];
@@ -409,15 +491,88 @@ in
           '';
         };
       };
+    })
 
-      xdg.portal.enable = true;
-      xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ];
+    # Plasma Mobile
+    (mkIf cfg.mobile.enable {
+      assertions = [
+        {
+          # The user interface breaks without NetworkManager
+          assertion = config.networking.networkmanager.enable;
+          message = "Plasma Mobile requires NetworkManager.";
+        }
+        {
+          # The user interface breaks without bluetooth
+          assertion = config.hardware.bluetooth.enable;
+          message = "Plasma Mobile requires Bluetooth.";
+        }
+        {
+          # The user interface breaks without pulse
+          assertion = config.hardware.pulseaudio.enable;
+          message = "Plasma Mobile requires pulseaudio.";
+        }
+      ];
 
-      # Update the start menu for each user that is currently logged in
-      system.userActivationScripts.plasmaSetup = activationScript;
-      services.xserver.displayManager.setupCommands = startplasma;
+      environment.systemPackages =
+        with libsForQt5;
+        with plasma5; with kdeApplications; with kdeFrameworks;
+        [
+          # Basic packages without which Plasma Mobile fails to work properly.
+          plasma-phone-components
+          plasma-nano
+          pkgs.maliit-framework
+          pkgs.maliit-keyboard
+        ]
+        ++ lib.optionals (cfg.mobile.installRecommendedSoftware) (with libsForQt5.plasmaMobileGear;[
+          # Additional software made for Plasma Mobile.
+          alligator
+          angelfish
+          audiotube
+          calindori
+          kalk
+          kasts
+          kclock
+          keysmith
+          koko
+          krecorder
+          ktrip
+          kweather
+          plasma-dialer
+          plasma-phonebook
+          plasma-settings
+          spacebar
+        ])
+      ;
+
+      # The following services are needed or the UI is broken.
+      hardware.bluetooth.enable = true;
+      hardware.pulseaudio.enable = true;
+      networking.networkmanager.enable = true;
+
+      # Recommendations can be found here:
+      #  - https://invent.kde.org/plasma-mobile/plasma-phone-settings/-/tree/master/etc/xdg
+      # This configuration is the minimum required for Plasma Mobile to *work*.
+      services.xserver.desktopManager.plasma5 = {
+        kdeglobals = {
+          KDE = {
+            # This forces a numeric PIN for the lockscreen, which is the
+            # recommendation from upstream.
+            LookAndFeelPackage = lib.mkDefault "org.kde.plasma.phone";
+          };
+        };
+        kwinrc = {
+          Windows = {
+            # Forces windows to be maximized
+            Placement = lib.mkDefault "Maximizing";
+          };
+          "org.kde.kdecoration2" = {
+            # No decorations (title bar)
+            NoPlugin = lib.mkDefault "true";
+          };
+        };
+      };
 
-      nixpkgs.config.firefox.enablePlasmaBrowserIntegration = true;
+      services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-phone-components ];
     })
   ];
 }
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 9a7532b476415..84b75c83aeab4 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -312,7 +312,7 @@ in
     };
 
     systemd.tmpfiles.rules = [
-      "d /run/lightdm 0711 lightdm lightdm 0"
+      "d /run/lightdm 0711 lightdm lightdm -"
       "d /var/cache/lightdm 0711 root lightdm -"
       "d /var/lib/lightdm 1770 lightdm lightdm -"
       "d /var/lib/lightdm-data 1775 lightdm lightdm -"
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index 8dbfe393f109b..4a32387db8da5 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -150,7 +150,7 @@ in
       example = literalExpression ''
         { plasmaSetup = {
             text = '''
-              ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5"
+              ''${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5"
             ''';
             deps = [];
           };
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index b04577aeb83e4..58377ea64438e 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -201,6 +201,7 @@ in
     system.boot.loader.kernelFile = mkOption {
       internal = true;
       default = pkgs.stdenv.hostPlatform.linux-kernel.target;
+      defaultText = literalExpression "pkgs.stdenv.hostPlatform.linux-kernel.target";
       type = types.str;
       description = ''
         Name of the kernel file to be passed to the bootloader.
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index fa8500dd42bdc..8db271f871352 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -99,6 +99,7 @@ in
 
       enable = mkOption {
         default = !config.boot.isContainer;
+        defaultText = literalExpression "!config.boot.isContainer";
         type = types.bool;
         description = ''
           Whether to enable the GNU GRUB boot loader.
diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix
index a6fc07da0abbf..21d3fab2f35df 100644
--- a/nixos/modules/system/boot/resolved.nix
+++ b/nixos/modules/system/boot/resolved.nix
@@ -32,6 +32,7 @@ in
 
     services.resolved.domains = mkOption {
       default = config.networking.search;
+      defaultText = literalExpression "config.networking.search";
       example = [ "example.com" ];
       type = types.listOf types.str;
       description = ''
diff --git a/nixos/modules/system/boot/timesyncd.nix b/nixos/modules/system/boot/timesyncd.nix
index 692315dbe99c4..5f35a15476965 100644
--- a/nixos/modules/system/boot/timesyncd.nix
+++ b/nixos/modules/system/boot/timesyncd.nix
@@ -9,6 +9,7 @@ with lib;
     services.timesyncd = {
       enable = mkOption {
         default = !config.boot.isContainer;
+        defaultText = literalExpression "!config.boot.isContainer";
         type = types.bool;
         description = ''
           Enables the systemd NTP client daemon.
@@ -16,6 +17,7 @@ with lib;
       };
       servers = mkOption {
         default = config.networking.timeServers;
+        defaultText = literalExpression "config.networking.timeServers";
         type = types.listOf types.str;
         description = ''
           The set of NTP servers from which to synchronise.
diff --git a/nixos/modules/tasks/snapraid.nix b/nixos/modules/tasks/snapraid.nix
index 4529009930fcb..ff956f3067096 100644
--- a/nixos/modules/tasks/snapraid.nix
+++ b/nixos/modules/tasks/snapraid.nix
@@ -193,7 +193,6 @@ in
             LockPersonality = true;
             MemoryDenyWriteExecute = true;
             NoNewPrivileges = true;
-            PrivateDevices = true;
             PrivateTmp = true;
             ProtectClock = true;
             ProtectControlGroups = true;
@@ -208,7 +207,8 @@ in
             SystemCallArchitectures = "native";
             SystemCallFilter = "@system-service";
             SystemCallErrorNumber = "EPERM";
-            CapabilityBoundingSet = "CAP_DAC_OVERRIDE";
+            CapabilityBoundingSet = "CAP_DAC_OVERRIDE" ++
+              lib.optionalString cfg.touchBeforeSync " CAP_FOWNER";
 
             ProtectSystem = "strict";
             ProtectHome = "read-only";
diff --git a/nixos/modules/virtualisation/amazon-ec2-amis.nix b/nixos/modules/virtualisation/amazon-ec2-amis.nix
index b3459ba3d650f..91b5237e3371d 100644
--- a/nixos/modules/virtualisation/amazon-ec2-amis.nix
+++ b/nixos/modules/virtualisation/amazon-ec2-amis.nix
@@ -402,5 +402,43 @@ let self = {
   "21.05".ap-east-1.x86_64-linux.hvm-ebs = "ami-06dc98082bc55c1fc";
   "21.05".sa-east-1.x86_64-linux.hvm-ebs = "ami-04737dd49b98936c6";
 
-  latest = self."21.05";
+  # 21.11.333823.96b4157790f-x86_64-linux
+  "21.11".eu-west-1.x86_64-linux.hvm-ebs = "ami-01d0304a712f2f3f0";
+  "21.11".eu-west-2.x86_64-linux.hvm-ebs = "ami-00e828bfc1e5d09ac";
+  "21.11".eu-west-3.x86_64-linux.hvm-ebs = "ami-0e1ea64430d8103f2";
+  "21.11".eu-central-1.x86_64-linux.hvm-ebs = "ami-0fcf28c07e86142c5";
+  "21.11".eu-north-1.x86_64-linux.hvm-ebs = "ami-0ee83a3c6590fd6b1";
+  "21.11".us-east-1.x86_64-linux.hvm-ebs = "ami-099756bfda4540da0";
+  "21.11".us-east-2.x86_64-linux.hvm-ebs = "ami-0b20a80b82052d23f";
+  "21.11".us-west-1.x86_64-linux.hvm-ebs = "ami-088ea590004b01752";
+  "21.11".us-west-2.x86_64-linux.hvm-ebs = "ami-0025b9d4831b911a7";
+  "21.11".ca-central-1.x86_64-linux.hvm-ebs = "ami-0e67089f898e74443";
+  "21.11".ap-southeast-1.x86_64-linux.hvm-ebs = "ami-0dc8d718279d3402d";
+  "21.11".ap-southeast-2.x86_64-linux.hvm-ebs = "ami-0155e842329970187";
+  "21.11".ap-northeast-1.x86_64-linux.hvm-ebs = "ami-07c95eda953bf5435";
+  "21.11".ap-northeast-2.x86_64-linux.hvm-ebs = "ami-04167df3cd952b3bd";
+  "21.11".ap-south-1.x86_64-linux.hvm-ebs = "ami-0680e05531b3db677";
+  "21.11".ap-east-1.x86_64-linux.hvm-ebs = "ami-0835a3e481dc240f9";
+  "21.11".sa-east-1.x86_64-linux.hvm-ebs = "ami-0f7c354c421348e51";
+
+  # 21.11.333823.96b4157790f-aarch64-linux
+  "21.11".eu-west-1.aarch64-linux.hvm-ebs = "ami-048f3eea6a12c4b3b";
+  "21.11".eu-west-2.aarch64-linux.hvm-ebs = "ami-0e6f18f2009806add";
+  "21.11".eu-west-3.aarch64-linux.hvm-ebs = "ami-0a28d593f5e938d80";
+  "21.11".eu-central-1.aarch64-linux.hvm-ebs = "ami-0b9c95d926ab9474c";
+  "21.11".eu-north-1.aarch64-linux.hvm-ebs = "ami-0f2d400b4a2368a1a";
+  "21.11".us-east-1.aarch64-linux.hvm-ebs = "ami-05afb75585567d386";
+  "21.11".us-east-2.aarch64-linux.hvm-ebs = "ami-07f360673c2fccf8d";
+  "21.11".us-west-1.aarch64-linux.hvm-ebs = "ami-0a6892c61d85774db";
+  "21.11".us-west-2.aarch64-linux.hvm-ebs = "ami-04eaf20283432e852";
+  "21.11".ca-central-1.aarch64-linux.hvm-ebs = "ami-036b69828502e7fdf";
+  "21.11".ap-southeast-1.aarch64-linux.hvm-ebs = "ami-0d52e51e68b6954ef";
+  "21.11".ap-southeast-2.aarch64-linux.hvm-ebs = "ami-000a3019e003f4fb9";
+  "21.11".ap-northeast-1.aarch64-linux.hvm-ebs = "ami-09b0c7928780e25b6";
+  "21.11".ap-northeast-2.aarch64-linux.hvm-ebs = "ami-05f80f3c83083ff62";
+  "21.11".ap-south-1.aarch64-linux.hvm-ebs = "ami-05b2a3ff8489c3f59";
+  "21.11".ap-east-1.aarch64-linux.hvm-ebs = "ami-0aa3b50a4f2822a00";
+  "21.11".sa-east-1.aarch64-linux.hvm-ebs = "ami-00f68eff453d3fe69";
+
+  latest = self."21.11";
 }; in self
diff --git a/nixos/modules/virtualisation/amazon-options.nix b/nixos/modules/virtualisation/amazon-options.nix
index 698edcd835a6d..0465571ca9262 100644
--- a/nixos/modules/virtualisation/amazon-options.nix
+++ b/nixos/modules/virtualisation/amazon-options.nix
@@ -1,6 +1,6 @@
 { config, lib, pkgs, ... }:
 let
-  inherit (lib) types;
+  inherit (lib) literalExpression types;
 in {
   options = {
     ec2 = {
@@ -50,6 +50,7 @@ in {
       };
       efi = lib.mkOption {
         default = pkgs.stdenv.hostPlatform.isAarch64;
+        defaultText = literalExpression "pkgs.stdenv.hostPlatform.isAarch64";
         internal = true;
         description = ''
           Whether the EC2 instance is using EFI.
diff --git a/nixos/modules/virtualisation/oci-containers.nix b/nixos/modules/virtualisation/oci-containers.nix
index 24573bba48000..5af9baff8bc1b 100644
--- a/nixos/modules/virtualisation/oci-containers.nix
+++ b/nixos/modules/virtualisation/oci-containers.nix
@@ -28,7 +28,7 @@ let
             You still need to set the <literal>image</literal> attribute, as it
             will be used as the image name for docker to start a container.
           '';
-          example = literalExpression "pkgs.dockerTools.buildDockerImage {...};";
+          example = literalExpression "pkgs.dockerTools.buildImage {...};";
         };
 
         login = {
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 91356ac1d9845..c7c3d7474645a 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -329,6 +329,7 @@ in
       mkOption {
         type = types.str;
         default = "./${config.system.name}.qcow2";
+        defaultText = literalExpression ''"./''${config.system.name}.qcow2"'';
         description =
           ''
             Path to the disk image containing the root filesystem.
@@ -678,6 +679,7 @@ in
       mkOption {
         type = types.str;
         default = "./${config.system.name}-efi-vars.fd";
+        defaultText = literalExpression ''"./''${config.system.name}-efi-vars.fd"'';
         description =
           ''
             Path to nvram image containing UEFI variables.  The will be created
diff --git a/nixos/modules/virtualisation/waydroid.nix b/nixos/modules/virtualisation/waydroid.nix
index 854ab056dbb84..4fc798ff39f89 100644
--- a/nixos/modules/virtualisation/waydroid.nix
+++ b/nixos/modules/virtualisation/waydroid.nix
@@ -18,7 +18,8 @@ let
     /dev/hwbinder = hidl
   '';
 
-in {
+in
+{
 
   options.virtualisation.waydroid = {
     enable = mkEnableOption "Waydroid";
@@ -36,6 +37,12 @@ in {
       (isEnabled "ASHMEM")
     ];
 
+    /* NOTE: we always enable this flag even if CONFIG_PSI_DEFAULT_DISABLED is not on
+      as reading the kernel config is not always possible and on kernels where it's
+      already on it will be no-op
+    */
+    boot.kernelParams = [ "psi=1" ];
+
     environment.etc."gbinder.d/waydroid.conf".source = waydroidGbinderConf;
 
     environment.systemPackages = with pkgs; [ waydroid ];
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index e2b9c868bc85d..8ac3f6043d084 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -44,6 +44,7 @@ in
   boot-stage1 = handleTest ./boot-stage1.nix {};
   borgbackup = handleTest ./borgbackup.nix {};
   botamusique = handleTest ./botamusique.nix {};
+  bpf = handleTestOn ["x86_64-linux" "aarch64-linux"] ./bpf.nix {};
   btrbk = handleTest ./btrbk.nix {};
   buildbot = handleTest ./buildbot.nix {};
   buildkite-agents = handleTest ./buildkite-agents.nix {};
@@ -111,6 +112,7 @@ in
   dokuwiki = handleTest ./dokuwiki.nix {};
   domination = handleTest ./domination.nix {};
   dovecot = handleTest ./dovecot.nix {};
+  drbd = handleTest ./drbd.nix {};
   ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
   ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
   ecryptfs = handleTest ./ecryptfs.nix {};
@@ -315,8 +317,8 @@ in
   nginx-sso = handleTest ./nginx-sso.nix {};
   nginx-variants = handleTest ./nginx-variants.nix {};
   nitter = handleTest ./nitter.nix {};
-  nix-serve = handleTest ./nix-ssh-serve.nix {};
-  nix-ssh-serve = handleTest ./nix-ssh-serve.nix {};
+  nix-serve = handleTest ./nix-serve.nix {};
+  nix-serve-ssh = handleTest ./nix-serve-ssh.nix {};
   nixops = handleTest ./nixops/default.nix {};
   nixos-generate-config = handleTest ./nixos-generate-config.nix {};
   node-red = handleTest ./node-red.nix {};
@@ -432,6 +434,7 @@ in
   sslh = handleTest ./sslh.nix {};
   sssd = handleTestOn ["x86_64-linux"] ./sssd.nix {};
   sssd-ldap = handleTestOn ["x86_64-linux"] ./sssd-ldap.nix {};
+  step-ca = handleTestOn ["x86_64-linux"] ./step-ca.nix {};
   strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
   sudo = handleTest ./sudo.nix {};
   sway = handleTest ./sway.nix {};
diff --git a/nixos/tests/bpf.nix b/nixos/tests/bpf.nix
new file mode 100644
index 0000000000000..233c7dab1ee22
--- /dev/null
+++ b/nixos/tests/bpf.nix
@@ -0,0 +1,25 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "bpf";
+  meta.maintainers = with pkgs.lib.maintainers; [ martinetd ];
+
+  machine = { pkgs, ... }: {
+    programs.bcc.enable = true;
+    environment.systemPackages = with pkgs; [ bpftrace ];
+  };
+
+  testScript = ''
+    ## bcc
+    # syscount -d 1 stops 1s after probe started so is good for that
+    print(machine.succeed("syscount -d 1"))
+
+    ## bpftrace
+    # list probes
+    machine.succeed("bpftrace -l")
+    # simple BEGIN probe (user probe on bpftrace itself)
+    print(machine.succeed("bpftrace -e 'BEGIN { print(\"ok\"); exit(); }'"))
+    # tracepoint
+    print(machine.succeed("bpftrace -e 'tracepoint:syscalls:sys_enter_* { print(probe); exit(); }'"))
+    # kprobe
+    print(machine.succeed("bpftrace -e 'kprobe:schedule { print(probe); exit() }'"))
+  '';
+})
diff --git a/nixos/tests/custom-ca.nix b/nixos/tests/custom-ca.nix
index 0ab49f3b34306..a55449a397a7c 100644
--- a/nixos/tests/custom-ca.nix
+++ b/nixos/tests/custom-ca.nix
@@ -82,6 +82,9 @@ in
       # chromium-based browsers refuse to run as root
       test-support.displayManager.auto.user = "alice";
 
+      # browsers may hang with the default memory
+      virtualisation.memorySize = 600;
+
       networking.hosts."127.0.0.1" = [ "good.example.com" "bad.example.com" ];
       security.pki.certificateFiles = [ "${example-good-cert}/ca.crt" ];
 
@@ -160,7 +163,7 @@ in
         browser = command.split()[0]
         with subtest("Good certificate is trusted in " + browser):
             execute_as(
-                "alice", f"env P11_KIT_DEBUG=trust {command} https://good.example.com & >&2"
+                "alice", f"{command} https://good.example.com >&2 &"
             )
             wait_for_window_as("alice", browser)
             machine.wait_for_text("It works!")
@@ -168,9 +171,9 @@ in
             execute_as("alice", "xdotool key ctrl+w")  # close tab
 
         with subtest("Unknown CA is untrusted in " + browser):
-            execute_as("alice", f"{command} https://bad.example.com & >&2")
+            execute_as("alice", f"{command} https://bad.example.com >&2 &")
             machine.wait_for_text(error)
             machine.screenshot("bad" + browser)
-            machine.succeed("pkill " + browser)
+            machine.succeed("pkill -f " + browser)
   '';
 })
diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix
index 7110187e8d764..19ebed3ebd0bd 100644
--- a/nixos/tests/docker-tools.nix
+++ b/nixos/tests/docker-tools.nix
@@ -276,15 +276,22 @@ import ./make-test-python.nix ({ pkgs, ... }: {
         # Ensure the image has the correct number of layers
         assert len(set_of_layers("layered-bulk-layer")) == 4
 
-    with subtest("Ensure correct behavior when no store is needed"):
+    with subtest("Ensure only minimal paths are added to the store"):
+        # TODO: make an example that has no store paths, for example by making
+        #       busybox non-self-referential.
+
         # This check tests that buildLayeredImage can build images that don't need a store.
         docker.succeed(
             "docker load --input='${pkgs.dockerTools.examples.no-store-paths}'"
         )
 
-        # This check may be loosened to allow an *empty* store rather than *no* store.
-        docker.succeed("docker run --rm no-store-paths ls /")
-        docker.fail("docker run --rm no-store-paths ls /nix/store")
+        docker.succeed("docker run --rm no-store-paths ls / >/dev/console")
+
+        # If busybox isn't self-referential, we need this line
+        #   docker.fail("docker run --rm no-store-paths ls /nix/store >/dev/console")
+        # However, it currently is self-referential, so we check that it is the
+        # only store path.
+        docker.succeed("diff <(docker run --rm no-store-paths ls /nix/store) <(basename ${pkgs.pkgsStatic.busybox}) >/dev/console")
 
     with subtest("Ensure buildLayeredImage does not change store path contents."):
         docker.succeed(
@@ -379,11 +386,21 @@ import ./make-test-python.nix ({ pkgs, ... }: {
             "docker run --rm ${examples.layeredImageWithFakeRootCommands.imageName} sh -c 'stat -c '%u' /home/jane | grep -E ^1000$'"
         )
 
+    with subtest("The image contains store paths referenced by the fakeRootCommands output"):
+        docker.succeed(
+            "docker run --rm ${examples.layeredImageWithFakeRootCommands.imageName} /hello/bin/layeredImageWithFakeRootCommands-hello"
+        )
+
     with subtest("exportImage produces a valid tarball"):
         docker.succeed(
             "tar -tf ${examples.exportBash} | grep '\./bin/bash' > /dev/null"
         )
 
+    with subtest("layered image fakeRootCommands with fakechroot works"):
+        docker.succeed("${examples.imageViaFakeChroot} | docker load")
+        docker.succeed("docker run --rm image-via-fake-chroot | grep -i hello")
+        docker.succeed("docker image rm image-via-fake-chroot:latest")
+
     with subtest("Ensure bare paths in contents are loaded correctly"):
         docker.succeed(
             "docker load --input='${examples.build-image-with-path}'",
diff --git a/nixos/tests/drbd.nix b/nixos/tests/drbd.nix
new file mode 100644
index 0000000000000..bede7206d706c
--- /dev/null
+++ b/nixos/tests/drbd.nix
@@ -0,0 +1,87 @@
+import ./make-test-python.nix (
+  { pkgs, lib, ... }:
+  let
+    drbdPort = 7789;
+
+    drbdConfig =
+      { nodes, ... }:
+      {
+        virtualisation.emptyDiskImages = [ 1 ];
+        networking.firewall.allowedTCPPorts = [ drbdPort ];
+
+        services.drbd = {
+          enable = true;
+          config = ''
+            global {
+              usage-count yes;
+            }
+
+            common {
+              net {
+                protocol C;
+                ping-int 1;
+              }
+            }
+
+            resource r0 {
+              volume 0 {
+                device    /dev/drbd0;
+                disk      /dev/vdb;
+                meta-disk internal;
+              }
+
+              on drbd1 {
+                address ${nodes.drbd1.config.networking.primaryIPAddress}:${toString drbdPort};
+              }
+
+              on drbd2 {
+                address ${nodes.drbd2.config.networking.primaryIPAddress}:${toString drbdPort};
+              }
+            }
+          '';
+        };
+      };
+  in
+  {
+    name = "drbd";
+    meta = with pkgs.lib.maintainers; {
+      maintainers = [ ryantm astro ];
+    };
+
+    nodes.drbd1 = drbdConfig;
+    nodes.drbd2 = drbdConfig;
+
+    testScript = { nodes }: ''
+      drbd1.start()
+      drbd2.start()
+
+      drbd1.wait_for_unit("network.target")
+      drbd2.wait_for_unit("network.target")
+
+      drbd1.succeed(
+          "drbdadm create-md r0",
+          "drbdadm up r0",
+          "drbdadm primary r0 --force",
+      )
+
+      drbd2.succeed("drbdadm create-md r0", "drbdadm up r0")
+
+      drbd1.succeed(
+          "mkfs.ext4 /dev/drbd0",
+          "mkdir -p /mnt/drbd",
+          "mount /dev/drbd0 /mnt/drbd",
+          "touch /mnt/drbd/hello",
+          "umount /mnt/drbd",
+          "drbdadm secondary r0",
+      )
+      drbd1.sleep(1)
+
+      drbd2.succeed(
+          "drbdadm primary r0",
+          "mkdir -p /mnt/drbd",
+          "mount /dev/drbd0 /mnt/drbd",
+          "ls /mnt/drbd/hello",
+      )
+    '';
+  }
+)
diff --git a/nixos/tests/knot.nix b/nixos/tests/knot.nix
index 22279292f77f9..203fd03fac26f 100644
--- a/nixos/tests/knot.nix
+++ b/nixos/tests/knot.nix
@@ -45,6 +45,10 @@ in {
   nodes = {
     master = { lib, ... }: {
       imports = [ common ];
+
+      # trigger sched_setaffinity syscall
+      virtualisation.cores = 2;
+
       networking.interfaces.eth1 = {
         ipv4.addresses = lib.mkForce [
           { address = "192.168.0.1"; prefixLength = 24; }
@@ -206,5 +210,7 @@ in {
 
             test(host, "RRSIG", "www.example.com", r"RR set signature is")
             test(host, "DNSKEY", "example.com", r"DNSSEC key is")
+
+    master.log(master.succeed("systemd-analyze security knot.service | grep -v '✓'"))
   '';
 })
diff --git a/nixos/tests/nextcloud/default.nix b/nixos/tests/nextcloud/default.nix
index bd7a7aacdc91a..34d3c345354c7 100644
--- a/nixos/tests/nextcloud/default.nix
+++ b/nixos/tests/nextcloud/default.nix
@@ -1,6 +1,6 @@
-{ system ? builtins.currentSystem,
-  config ? {},
-  pkgs ? import ../../.. { inherit system config; }
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../../.. { inherit system config; }
 }:
 
 with pkgs.lib;
@@ -17,5 +17,5 @@ foldl
       nextcloudVersion = ver;
     };
   })
-  {}
-  [ 21 22 ]
+{ }
+  [ 21 22 23 ]
diff --git a/nixos/tests/nix-ssh-serve.nix b/nixos/tests/nix-serve-ssh.nix
index 03f83542c7c11..1eb8d5b395b1f 100644
--- a/nixos/tests/nix-ssh-serve.nix
+++ b/nixos/tests/nix-serve-ssh.nix
@@ -35,7 +35,7 @@ in
 
        client.fail("diff /root/other-store$(cat mach-id-path) /etc/machine-id")
        # Currently due to shared store this is a noop :(
-       client.succeed("nix copy --to ssh-ng://nix-ssh@server $(cat mach-id-path)")
+       client.succeed("nix copy --experimental-features 'nix-command' --to ssh-ng://nix-ssh@server $(cat mach-id-path)")
        client.succeed(
            "nix-store --realise $(cat mach-id-path) --store /root/other-store --substituters ssh-ng://nix-ssh@server"
        )
diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix
index d069854328a2c..62deb38649514 100644
--- a/nixos/tests/prometheus-exporters.nix
+++ b/nixos/tests/prometheus-exporters.nix
@@ -861,6 +861,9 @@ let
         wait_for_unit("prometheus-postfix-exporter.service")
         wait_for_file("/var/lib/postfix/queue/public/showq")
         wait_for_open_port(9154)
+        wait_until_succeeds(
+            "curl -sSf http://localhost:9154/metrics | grep 'postfix_up{path=\"/var/lib/postfix/queue/public/showq\"} 1'"
+        )
         succeed(
             "curl -sSf http://localhost:9154/metrics | grep 'postfix_smtpd_connects_total 0'"
         )
@@ -1015,6 +1018,25 @@ let
       '';
     };
 
+    smartctl = {
+      exporterConfig = {
+        enable = true;
+        devices = [
+          "/dev/vda"
+        ];
+      };
+      exporterTest = ''
+        wait_for_unit("prometheus-smartctl-exporter.service")
+        wait_for_open_port("9633")
+        wait_until_succeeds(
+          "curl -sSf 'localhost:9633/metrics'"
+        )
+        wait_until_succeeds(
+            'journalctl -eu prometheus-smartctl-exporter.service -o cat | grep "/dev/vda: Unable to detect device type"'
+        )
+      '';
+    };
+
     smokeping = {
       exporterConfig = {
         enable = true;
diff --git a/nixos/tests/step-ca.nix b/nixos/tests/step-ca.nix
new file mode 100644
index 0000000000000..b22bcb060f2bf
--- /dev/null
+++ b/nixos/tests/step-ca.nix
@@ -0,0 +1,76 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+  let
+    test-certificates = pkgs.runCommandLocal "test-certificates" { } ''
+      mkdir -p $out
+      echo insecure-root-password > $out/root-password-file
+      echo insecure-intermediate-password > $out/intermediate-password-file
+      ${pkgs.step-cli}/bin/step certificate create "Example Root CA" $out/root_ca.crt $out/root_ca.key --password-file=$out/root-password-file --profile root-ca
+      ${pkgs.step-cli}/bin/step certificate create "Example Intermediate CA 1" $out/intermediate_ca.crt $out/intermediate_ca.key --password-file=$out/intermediate-password-file --ca-password-file=$out/root-password-file --profile intermediate-ca --ca $out/root_ca.crt --ca-key $out/root_ca.key
+    '';
+  in
+  {
+    nodes =
+      {
+        caserver =
+          { config, pkgs, ... }: {
+            services.step-ca = {
+              enable = true;
+              address = "0.0.0.0";
+              port = 8443;
+              openFirewall = true;
+              intermediatePasswordFile = "${test-certificates}/intermediate-password-file";
+              settings = {
+                dnsNames = [ "caserver" ];
+                root = "${test-certificates}/root_ca.crt";
+                crt = "${test-certificates}/intermediate_ca.crt";
+                key = "${test-certificates}/intermediate_ca.key";
+                db = {
+                  type = "badger";
+                  dataSource = "/var/lib/step-ca/db";
+                };
+                authority = {
+                  provisioners = [
+                    {
+                      type = "ACME";
+                      name = "acme";
+                    }
+                  ];
+                };
+              };
+            };
+          };
+
+        caclient =
+          { config, pkgs, ... }: {
+            security.acme.server = "https://caserver:8443/acme/acme/directory";
+            security.acme.email = "root@example.org";
+            security.acme.acceptTerms = true;
+
+            security.pki.certificateFiles = [ "${test-certificates}/root_ca.crt" ];
+
+            networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+            services.nginx = {
+              enable = true;
+              virtualHosts = {
+                "caclient" = {
+                  forceSSL = true;
+                  enableACME = true;
+                };
+              };
+            };
+          };
+
+        catester = { config, pkgs, ... }: {
+          security.pki.certificateFiles = [ "${test-certificates}/root_ca.crt" ];
+        };
+      };
+
+    testScript =
+      ''
+        catester.start()
+        caserver.wait_for_unit("step-ca.service")
+        caclient.wait_for_unit("acme-finished-caclient.target")
+        catester.succeed("curl https://caclient/ | grep \"Welcome to nginx!\"")
+      '';
+  })
diff --git a/nixos/tests/vault-postgresql.nix b/nixos/tests/vault-postgresql.nix
index 071cfd106ffbc..2847af13cbf05 100644
--- a/nixos/tests/vault-postgresql.nix
+++ b/nixos/tests/vault-postgresql.nix
@@ -64,6 +64,6 @@ import ./make-test-python.nix ({ pkgs, ... }:
       machine.wait_for_unit("vault.service")
       machine.wait_for_open_port(8200)
       machine.succeed("vault operator init")
-      machine.succeed("vault status | grep Sealed | grep true")
+      machine.succeed("vault status || test $? -eq 2")
     '';
 })