summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/development/option-declarations.section.md4
-rw-r--r--nixos/doc/manual/development/option-types.section.md4
-rw-r--r--nixos/doc/manual/development/writing-nixos-tests.section.md13
-rw-r--r--nixos/doc/manual/from_md/development/option-declarations.section.xml4
-rw-r--r--nixos/doc/manual/from_md/development/option-types.section.xml6
-rw-r--r--nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml13
-rw-r--r--nixos/doc/manual/from_md/installation/upgrading.chapter.xml16
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2205.section.xml677
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2211.section.xml114
-rw-r--r--nixos/doc/manual/installation/upgrading.chapter.md16
-rw-r--r--nixos/doc/manual/release-notes/release-notes.xml1
-rw-r--r--nixos/doc/manual/release-notes/rl-2205.section.md239
-rw-r--r--nixos/doc/manual/release-notes/rl-2211.section.md51
-rw-r--r--nixos/lib/eval-config.nix5
-rw-r--r--nixos/lib/test-driver/default.nix2
-rw-r--r--nixos/lib/test-driver/test_driver/machine.py2
-rw-r--r--nixos/lib/test-driver/test_driver/py.typed0
-rw-r--r--nixos/lib/test-script-prepend.py42
-rw-r--r--nixos/lib/testing-python.nix35
-rw-r--r--nixos/modules/config/update-users-groups.pl6
-rw-r--r--nixos/modules/config/users-groups.nix11
-rw-r--r--nixos/modules/hardware/new-lg4ff.nix29
-rw-r--r--nixos/modules/hardware/saleae-logic.nix25
-rw-r--r--nixos/modules/hardware/video/nvidia.nix31
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixos/modules/misc/nixpkgs.nix9
-rw-r--r--nixos/modules/misc/version.nix2
-rw-r--r--nixos/modules/module-list.nix6
-rw-r--r--nixos/modules/programs/atop.nix18
-rw-r--r--nixos/modules/programs/cfs-zen-tweaks.nix28
-rw-r--r--nixos/modules/programs/gnupg.nix2
-rw-r--r--nixos/modules/services/backup/btrbk.nix90
-rw-r--r--nixos/modules/services/backup/restic.nix174
-rw-r--r--nixos/modules/services/computing/slurm/slurm.nix10
-rw-r--r--nixos/modules/services/databases/openldap.nix11
-rw-r--r--nixos/modules/services/databases/postgresql.nix3
-rw-r--r--nixos/modules/services/games/asf.nix78
-rw-r--r--nixos/modules/services/mail/mailman.nix58
-rw-r--r--nixos/modules/services/mail/postfix.nix1
-rw-r--r--nixos/modules/services/misc/dendrite.nix19
-rw-r--r--nixos/modules/services/misc/gitlab.nix10
-rw-r--r--nixos/modules/services/misc/gollum.nix16
-rw-r--r--nixos/modules/services/misc/jellyfin.nix3
-rw-r--r--nixos/modules/services/misc/libreddit.nix44
-rw-r--r--nixos/modules/services/monitoring/grafana.nix80
-rw-r--r--nixos/modules/services/monitoring/mimir.nix4
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix2
-rw-r--r--nixos/modules/services/networking/bird-lg.nix269
-rw-r--r--nixos/modules/services/networking/mosquitto.nix10
-rw-r--r--nixos/modules/services/networking/openconnect.nix8
-rw-r--r--nixos/modules/services/networking/r53-ddns.nix72
-rw-r--r--nixos/modules/services/networking/zeronet.nix11
-rw-r--r--nixos/modules/services/system/localtime.nix32
-rw-r--r--nixos/modules/services/web-apps/hedgedoc.nix9
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix16
-rw-r--r--nixos/modules/services/web-apps/peertube.nix16
-rw-r--r--nixos/modules/services/web-apps/timetagger.nix80
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/phosh.nix8
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py33
-rw-r--r--nixos/modules/system/boot/plymouth.nix10
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh2
-rw-r--r--nixos/modules/system/boot/stage-1.nix44
-rw-r--r--nixos/modules/system/boot/systemd.nix17
-rw-r--r--nixos/modules/system/boot/systemd/logind.nix3
-rw-r--r--nixos/modules/virtualisation/appvm.nix49
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix51
-rw-r--r--nixos/modules/virtualisation/nixos-containers.nix4
-rw-r--r--nixos/modules/virtualisation/vmware-guest.nix1
-rw-r--r--nixos/tests/all-tests.nix4
-rw-r--r--nixos/tests/btrbk-no-timer.nix37
-rw-r--r--nixos/tests/containers-imperative.nix3
-rw-r--r--nixos/tests/custom-ca.nix2
-rw-r--r--nixos/tests/dendrite.nix3
-rw-r--r--nixos/tests/ecryptfs.nix10
-rw-r--r--nixos/tests/gitolite.nix2
-rw-r--r--nixos/tests/grafana-mimir.nix50
-rw-r--r--nixos/tests/home-assistant.nix1
-rw-r--r--nixos/tests/libreddit.nix14
-rw-r--r--nixos/tests/login.nix6
-rw-r--r--nixos/tests/matrix/mjolnir.nix2
-rw-r--r--nixos/tests/meilisearch.nix11
-rw-r--r--nixos/tests/mosquitto.nix28
-rw-r--r--nixos/tests/mysql/mysql-backup.nix1
-rw-r--r--nixos/tests/nextcloud/default.nix2
-rw-r--r--nixos/tests/nginx-http3.nix90
-rw-r--r--nixos/tests/os-prober.nix23
-rw-r--r--nixos/tests/pam/pam-oath-login.nix22
-rw-r--r--nixos/tests/restic.nix191
-rw-r--r--nixos/tests/shadow.nix24
-rw-r--r--nixos/tests/sway.nix6
-rw-r--r--nixos/tests/uptermd.nix2
-rw-r--r--nixos/tests/user-activation-scripts.nix4
-rw-r--r--nixos/tests/user-home-mode.nix27
-rw-r--r--nixos/tests/web-apps/peertube.nix7
-rw-r--r--nixos/tests/zsh-history.nix6
97 files changed, 2459 insertions, 883 deletions
diff --git a/nixos/doc/manual/development/option-declarations.section.md b/nixos/doc/manual/development/option-declarations.section.md
index 2e11218e823..ef7255557a1 100644
--- a/nixos/doc/manual/development/option-declarations.section.md
+++ b/nixos/doc/manual/development/option-declarations.section.md
@@ -120,14 +120,14 @@ lib.mkOption {
 ```nix
 lib.mkPackageOption pkgs "GHC" {
   default = [ "ghc" ];
-  example = "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])";
+  example = "pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])";
 }
 # is like
 lib.mkOption {
   type = lib.types.package;
   default = pkgs.ghc;
   defaultText = lib.literalExpression "pkgs.ghc";
-  example = lib.literalExpression "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])";
+  example = lib.literalExpression "pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])";
   description = "The GHC package to use.";
 }
 ```
diff --git a/nixos/doc/manual/development/option-types.section.md b/nixos/doc/manual/development/option-types.section.md
index 00f1d85bdb6..d32d4fc50ad 100644
--- a/nixos/doc/manual/development/option-types.section.md
+++ b/nixos/doc/manual/development/option-types.section.md
@@ -308,6 +308,10 @@ The option set can be defined directly
 ([Example: Directly defined submodule](#ex-submodule-direct)) or as reference
 ([Example: Submodule defined as a reference](#ex-submodule-reference)).
 
+Note that even if your submodule’s options all have a default value,
+you will still need to provide a default value (e.g. an empty attribute set)
+if you want to allow users to leave it undefined.
+
 ::: {#ex-submodule-direct .example}
 ::: {.title}
 **Example: Directly defined submodule**
diff --git a/nixos/doc/manual/development/writing-nixos-tests.section.md b/nixos/doc/manual/development/writing-nixos-tests.section.md
index e5ee1cb01ff..583b8f712b4 100644
--- a/nixos/doc/manual/development/writing-nixos-tests.section.md
+++ b/nixos/doc/manual/development/writing-nixos-tests.section.md
@@ -332,6 +332,19 @@ repository):
     '';
 ```
 
+Similarly, the type checking of test scripts can be disabled in the following
+way:
+
+```nix
+import ./make-test-python.nix {
+  skipTypeCheck = true;
+  nodes.machine =
+    { config, pkgs, ... }:
+    { configuration…
+    };
+}
+```
+
 ## Failing tests early {#ssec-failing-tests-early}
 
 To fail tests early when certain invariables are no longer met (instead of waiting for the build to time out), the decorator `polling_condition` is provided. For example, if we are testing a program `foo` that should not quit after being started, we might write the following:
diff --git a/nixos/doc/manual/from_md/development/option-declarations.section.xml b/nixos/doc/manual/from_md/development/option-declarations.section.xml
index 91867c22410..381163dd7c7 100644
--- a/nixos/doc/manual/from_md/development/option-declarations.section.xml
+++ b/nixos/doc/manual/from_md/development/option-declarations.section.xml
@@ -183,14 +183,14 @@ lib.mkOption {
         <programlisting language="bash">
 lib.mkPackageOption pkgs &quot;GHC&quot; {
   default = [ &quot;ghc&quot; ];
-  example = &quot;pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
+  example = &quot;pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
 }
 # is like
 lib.mkOption {
   type = lib.types.package;
   default = pkgs.ghc;
   defaultText = lib.literalExpression &quot;pkgs.ghc&quot;;
-  example = lib.literalExpression &quot;pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
+  example = lib.literalExpression &quot;pkgs.haskell.package.ghc923.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
   description = &quot;The GHC package to use.&quot;;
 }
 </programlisting>
diff --git a/nixos/doc/manual/from_md/development/option-types.section.xml b/nixos/doc/manual/from_md/development/option-types.section.xml
index 44472929270..c67e183581c 100644
--- a/nixos/doc/manual/from_md/development/option-types.section.xml
+++ b/nixos/doc/manual/from_md/development/option-types.section.xml
@@ -617,6 +617,12 @@
       (<link linkend="ex-submodule-reference">Example: Submodule defined
       as a reference</link>).
     </para>
+    <para>
+      Note that even if your submodule’s options all have a default
+      value, you will still need to provide a default value (e.g. an
+      empty attribute set) if you want to allow users to leave it
+      undefined.
+    </para>
     <anchor xml:id="ex-submodule-direct" />
     <para>
       <emphasis role="strong">Example: Directly defined
diff --git a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml
index 7ce3e4cb290..79df3b9c376 100644
--- a/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml
+++ b/nixos/doc/manual/from_md/development/writing-nixos-tests.section.xml
@@ -590,6 +590,19 @@ import ./make-test-python.nix {
       # fmt: on
     '';
 </programlisting>
+    <para>
+      Similarly, the type checking of test scripts can be disabled in
+      the following way:
+    </para>
+    <programlisting language="bash">
+import ./make-test-python.nix {
+  skipTypeCheck = true;
+  nodes.machine =
+    { config, pkgs, ... }:
+    { configuration…
+    };
+}
+</programlisting>
   </section>
   <section xml:id="ssec-failing-tests-early">
     <title>Failing tests early</title>
diff --git a/nixos/doc/manual/from_md/installation/upgrading.chapter.xml b/nixos/doc/manual/from_md/installation/upgrading.chapter.xml
index e3b77d4c365..11fe1d317cc 100644
--- a/nixos/doc/manual/from_md/installation/upgrading.chapter.xml
+++ b/nixos/doc/manual/from_md/installation/upgrading.chapter.xml
@@ -12,7 +12,7 @@
     <listitem>
       <para>
         <emphasis>Stable channels</emphasis>, such as
-        <link xlink:href="https://nixos.org/channels/nixos-21.11"><literal>nixos-21.11</literal></link>.
+        <link xlink:href="https://nixos.org/channels/nixos-22.05"><literal>nixos-22.05</literal></link>.
         These only get conservative bug fixes and package upgrades. For
         instance, a channel update may cause the Linux kernel on your
         system to be upgraded from 4.19.34 to 4.19.38 (a minor bug fix),
@@ -33,7 +33,7 @@
     <listitem>
       <para>
         <emphasis>Small channels</emphasis>, such as
-        <link xlink:href="https://nixos.org/channels/nixos-21.11-small"><literal>nixos-21.11-small</literal></link>
+        <link xlink:href="https://nixos.org/channels/nixos-22.05-small"><literal>nixos-22.05-small</literal></link>
         or
         <link xlink:href="https://nixos.org/channels/nixos-unstable-small"><literal>nixos-unstable-small</literal></link>.
         These are identical to the stable and unstable channels
@@ -60,8 +60,8 @@
   <para>
     When you first install NixOS, you’re automatically subscribed to the
     NixOS channel that corresponds to your installation source. For
-    instance, if you installed from a 21.11 ISO, you will be subscribed
-    to the <literal>nixos-21.11</literal> channel. To see which NixOS
+    instance, if you installed from a 22.05 ISO, you will be subscribed
+    to the <literal>nixos-22.05</literal> channel. To see which NixOS
     channel you’re subscribed to, run the following as root:
   </para>
   <programlisting>
@@ -76,17 +76,17 @@ nixos https://nixos.org/channels/nixos-unstable
 </programlisting>
   <para>
     (Be sure to include the <literal>nixos</literal> parameter at the
-    end.) For instance, to use the NixOS 21.11 stable channel:
+    end.) For instance, to use the NixOS 22.05 stable channel:
   </para>
   <programlisting>
-# nix-channel --add https://nixos.org/channels/nixos-21.11 nixos
+# nix-channel --add https://nixos.org/channels/nixos-22.05 nixos
 </programlisting>
   <para>
     If you have a server, you may want to use the <quote>small</quote>
     channel instead:
   </para>
   <programlisting>
-# nix-channel --add https://nixos.org/channels/nixos-21.11-small nixos
+# nix-channel --add https://nixos.org/channels/nixos-22.05-small nixos
 </programlisting>
   <para>
     And if you want to live on the bleeding edge:
@@ -146,7 +146,7 @@ system.autoUpgrade.allowReboot = true;
       also specify a channel explicitly, e.g.
     </para>
     <programlisting language="bash">
-system.autoUpgrade.channel = https://nixos.org/channels/nixos-21.11;
+system.autoUpgrade.channel = https://nixos.org/channels/nixos-22.05;
 </programlisting>
   </section>
 </chapter>
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 19aaf12f26a..5208671e4da 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
@@ -1,9 +1,5 @@
 <section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-release-22.05">
-  <title>Release 22.05 (“Quokka”, 2022.05/??)</title>
-  <para>
-    In addition to numerous new and upgraded packages, this release has
-    the following highlights:
-  </para>
+  <title>Release 22.05 (“Quokka”, 2022.05/30)</title>
   <itemizedlist spacing="compact">
     <listitem>
       <para>
@@ -14,77 +10,36 @@
   </itemizedlist>
   <section xml:id="sec-release-22.05-highlights">
     <title>Highlights</title>
+    <para>
+      In addition to numerous new and upgraded packages, this release
+      has the following highlights:
+    </para>
     <itemizedlist>
       <listitem>
-        <para>
-          The <literal>firefox</literal> browser on
-          <literal>x86_64-linux</literal> is now making use of
-          profile-guided optimization resulting in a much more
-          responsive browsing experience.
-        </para>
+<literallayout>Nix has been updated from 2.3 to 2.8. This mainly brings experimental support for Flakes, but also marks the <literal>nix</literal> command as experimental which now has to be enabled via the configuration explicitly. For more information and instructions for upgrades, see the relase notes for <link xlink:href="https://nixos.org/manual/nix/stable/release-notes/rl-2.4.html">nix-2.4</link>,
+<link xlink:href="https://nixos.org/manual/nix/stable/release-notes/rl-2.5.html">nix-2.5</link>, <link xlink:href="https://nixos.org/manual/nix/stable/release-notes/rl-2.6.html">nix-2.6</link>, <link xlink:href="https://nixos.org/manual/nix/stable/release-notes/rl-2.7.html">nix-2.7</link> and <link xlink:href="https://nixos.org/manual/nix/stable/release-notes/rl-2.8.html">nix-2.8</link></literallayout>
       </listitem>
       <listitem>
         <para>
-          <literal>security.acme.defaults</literal> has been added to
-          simplify configuring settings for many certificates at once.
-          This also opens up the the option to use DNS-01 validation
-          when using <literal>enableACME</literal> on web server virtual
-          hosts (e.g.
-          <literal>services.nginx.virtualHosts.*.enableACME</literal>).
+          The <literal>firefox</literal> browser on
+          <literal>x86_64-linux</literal> now makes use of
+          profile-guided optimisation, resulting in a much more
+          responsive browsing experience.
         </para>
       </listitem>
       <listitem>
         <para>
           GNOME has been upgraded to 42. Please take a look at their
           <link xlink:href="https://release.gnome.org/42/">Release
-          Notes</link> for details. Notably, it replaces gedit with
-          GNOME Text Editor, GNOME Terminal with GNOME Console (formerly
-          King’s Cross), and GNOME Screenshot with a tool built into the
-          Shell.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
-          <literal>stdenv.mkDerivation</literal> now supports a
-          self-referencing <literal>finalAttrs:</literal> parameter
-          containing the final <literal>mkDerivation</literal> arguments
-          including overrides. <literal>drv.overrideAttrs</literal> now
-          supports two parameters
-          <literal>finalAttrs: previousAttrs:</literal>. This allows
-          packaging configuration to be overridden in a consistent
-          manner by providing an alternative to
-          <literal>rec {}</literal> syntax.
-        </para>
-        <para>
-          Additionally, <literal>passthru</literal> can now reference
-          <literal>finalAttrs.finalPackage</literal> containing the
-          final package, including attributes such as the output paths
-          and <literal>overrideAttrs</literal>.
-        </para>
-        <para>
-          New language integrations can be simplified by overriding a
-          <quote>prototype</quote> package containing the
-          language-specific logic. This removes the need for a extra
-          layer of overriding for the <quote>generic builder</quote>
-          arguments, thus removing a usability problem and source of
-          error.
+          Notes</link> for details. In particular, it replaces gedit
+          with GNOME Text Editor, GNOME Terminal with GNOME Console
+          (formerly King’s Cross) and GNOME Screenshot by a tool
+          integrated into the Shell.
         </para>
       </listitem>
       <listitem>
         <para>
-          PHP 8.1 is now available
-        </para>
-      </listitem>
-      <listitem>
-        <para>
-          Mattermost has been updated to extended support release 6.3,
-          as the previously packaged extended support release 5.37 is
-          <link xlink:href="https://docs.mattermost.com/upgrade/extended-support-release.html">reaching
-          its end of life</link>. Migrations may take a while, see the
-          <link xlink:href="https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release">changelog</link>
-          and
-          <link xlink:href="https://docs.mattermost.com/upgrade/important-upgrade-notes.html">important
-          upgrade notes</link>.
+          PHP 8.1 is now available.
         </para>
       </listitem>
       <listitem>
@@ -102,37 +57,22 @@
       </listitem>
       <listitem>
         <para>
-          Pulseaudio has been upgraded to version 15.0 and now
-          optionally
+          Pulseaudio has been updated to version 15.0 and now optionally
           <link xlink:href="https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/15.0/#supportforldacandaptxbluetoothcodecsplussbcxqsbcwithhigher-qualityparameters">supports
-          additional Bluetooth audio codecs</link> like aptX or LDAC,
-          with codec switching support being available in
+          additional Bluetooth audio codecs</link> such as aptX or LDAC,
+          with codec switching available in
           <literal>pavucontrol</literal>. This feature is disabled by
-          default but can be enabled by using
+          default, but can be enabled with the option
           <literal>hardware.pulseaudio.package = pkgs.pulseaudioFull;</literal>.
-          Existing 3rd party modules that provided similar
-          functionality, like <literal>pulseaudio-modules-bt</literal>
-          or <literal>pulseaudio-hsphfpd</literal> are deprecated and
-          have been removed.
+          Existing third-party modules that offered similar functions,
+          such as <literal>pulseaudio-modules-bt</literal> or
+          <literal>pulseaudio-hsphfpd</literal>, are obsolete and have
+          been removed.
         </para>
       </listitem>
       <listitem>
         <para>
-          The new
-          <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#sec-postgresqlTestHook"><literal>postgresqlTestHook</literal></link>
-          runs a PostgreSQL server for the duration of package checks.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
-          <link xlink:href="https://kops.sigs.k8s.io"><literal>kops</literal></link>
-          defaults to 1.22.4, which will enable
-          <link xlink:href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html">Instance
-          Metadata Service Version 2</link> and require tokens on new
-          clusters with Kubernetes 1.22. This will increase security by
-          default, but may break some types of workloads. See the
-          <link xlink:href="https://kops.sigs.k8s.io/releases/1.22-notes/">release
-          notes</link> for details.
+          PostgreSQL now defaults to major version 14.
         </para>
       </listitem>
       <listitem>
@@ -159,6 +99,16 @@
           users to easily install and set up NixOS with a GUI.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          <literal>security.acme.defaults</literal> has been added to
+          simplify the configuration of settings for many certificates
+          at once. This also opens up the option to use DNS-01
+          validation when using <literal>enableACME</literal> web server
+          virtual hosts (e.g.
+          <literal>services.nginx.virtualHosts.*.enableACME</literal>).
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
   <section xml:id="sec-release-22.05-new-services">
@@ -166,6 +116,16 @@
     <itemizedlist>
       <listitem>
         <para>
+          <link xlink:href="https://1password.com/">1password</link>,
+          command-lines and graphic interface for 1Password. Available
+          as
+          <link linkend="opt-programs._1password.enable">programs._1password</link>
+          and
+          <link linkend="opt-programs._1password.enable">programs._1password-gui</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           <link xlink:href="https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw">aesmd</link>,
           the Intel SGX Architectural Enclave Service Manager. Available
           as
@@ -174,90 +134,148 @@
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://docs.docker.com/engine/security/rootless/">rootless
-          Docker</link>, a <literal>systemd --user</literal> Docker
-          service which runs without root permissions. Available as
-          <link xlink:href="options.html#opt-virtualisation.docker.rootless.enable">virtualisation.docker.rootless.enable</link>.
+          <link xlink:href="https://github.com/mbrubeck/agate">agate</link>,
+          a very simple server for the Gemini hypertext protocol.
+          Available as
+          <link linkend="opt-services.agate.enable">services.agate</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://conduit.rs/">matrix-conduit</link>,
-          a simple, fast and reliable chat server powered by matrix.
-          Available as
-          <link xlink:href="option.html#opt-services.matrix-conduit.enable">services.matrix-conduit</link>.
+          <link xlink:href="https://github.com/linux-apfs/linux-apfs-rw">apfs</link>,
+          a kernel module for mounting the Apple File System (APFS).
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/vvilhonen/nethoscope">nethoscope</link>,
-          listen to your network traffic. Available as
-          <link linkend="opt-programs.nethoscope.enable">programs.nethoscope</link>.
+          <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm">ArchiSteamFarm</link>,
+          a C# application with primary purpose of idling Steam cards
+          from multiple accounts simultaneously. Available as
+          <link linkend="opt-services.archisteamfarm.enable">services.archisteamfarm</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html">filebeat</link>,
-          a lightweight shipper for forwarding and centralizing log
-          data. Available as
-          <link linkend="opt-services.filebeat.enable">services.filebeat</link>.
+          <link xlink:href="https://loic-sharma.github.io/BaGet/">BaGet</link>,
+          a lightweight NuGet and symbol server. Available at
+          <link linkend="opt-services.baget.enable">services.baget</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/linux-apfs/linux-apfs-rw">apfs</link>,
-          a kernel module for mounting the Apple File System (APFS).
+          <link xlink:href="https://github.com/xddxdd/bird-lg-go">bird-lg</link>,
+          a BGP looking glass for Bird Routing. Available as
+          <link linkend="opt-services.bird-lg.package">services.bird-lg</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://frrouting.org/">FRRouting</link>, a
-          popular suite of Internet routing protocol daemons (BGP, BFD,
-          OSPF, IS-IS, VRRP and others). Available as
-          <link linkend="opt-services.frr.babel.enable">services.frr</link>
+          <link xlink:href="https://0xerr0r.github.io/blocky/">blocky</link>,
+          fast and lightweight DNS proxy as ad-blocker for local network
+          with many features. Available as
+          <link linkend="opt-services.blocky.enable">services.blocky</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/hifi/heisenbridge">heisenbridge</link>,
-          a bouncer-style Matrix IRC bridge. Available as
-          <link xlink:href="options.html#opt-services.heisenbridge.enable">services.heisenbridge</link>.
+          <link xlink:href="https://github.com/kissgyorgy/cloudflare-dyndns">cloudflare-dyndns</link>,
+          CloudFlare Dynamic DNS client. Available as
+          <link linkend="opt-services.cloudflare-dyndns.enable">services.cloudflare-dyndns</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://snowflake.torproject.org/">snowflake-proxy</link>,
-          a system to defeat internet censorship. Available as
-          <link xlink:href="options.html#opt-services.snowflake-proxy.enable">services.snowflake-proxy</link>.
+          <link xlink:href="https://corosync.github.io/corosync/">Corosync</link>
+          and
+          <link xlink:href="https://clusterlabs.org/pacemaker/">Pacemaker</link>,
+          A open-source high availability resource manager. Available as
+          <link linkend="opt-services.corosync.enable">services.corosync</link>
+          and
+          <link linkend="opt-services.pacemaker.enable">services.pacemaker</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/lakinduakash/linux-wifi-hotspot">create_ap</link>,
+          a module for creating wifi hotspots using the program
+          linux-wifi-hotspot. Available as
+          <link linkend="opt-services.create_ap.enable">services.create_ap</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://www.envoyproxy.io/">Envoy</link>, a
+          high-performance reverse proxy. Available as
+          <link linkend="opt-services.envoy.enable">services.envoy</link>.
         </para>
       </listitem>
       <listitem>
         <para>
           <link xlink:href="https://ergo.chat">ergochat</link>, a modern
           IRC with IRCv3 features. Available as
-          <link xlink:href="options.html#opt-services.ergochat.enable">services.ergochat</link>.
+          <link linkend="opt-services.ergochat.enable">services.ergochat</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://snipeitapp.com">Snipe-IT</link>, a
-          free open source IT asset/license management system. Available
-          as
-          <link xlink:href="options.html#opt-services.snipe-it.enable">services.snipe-it</link>.
+          <link xlink:href="https://github.com/audreyt/ethercalc">ethercalc</link>,
+          an online collaborative spreadsheet. Available as
+          <link linkend="opt-services.ethercalc.enable">services.ethercalc</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</link>,
-          a web interface for the PowerDNS server. Available at
-          <link xlink:href="options.html#opt-services.powerdns-admin.enable">services.powerdns-admin</link>.
+          <link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html">filebeat</link>,
+          a lightweight shipper for forwarding and centralizing log
+          data. Available as
+          <link linkend="opt-services.filebeat.enable">services.filebeat</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/postgres/pgadmin4">pgadmin4</link>,
-          an admin interface for the PostgreSQL database. Available at
-          <link xlink:href="options.html#opt-services.pgadmin.enable">services.pgadmin</link>.
+          <link xlink:href="https://frrouting.org/">FRRouting</link>, a
+          popular suite of Internet routing protocol daemons (BGP, BFD,
+          OSPF, IS-IS, VRRP and others). Available as
+          <link linkend="opt-services.frr.babel.enable">services.frr</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://grafana.com/oss/mimir/">Grafana
+          Mimir</link>, an open source, horizontally scalable, highly
+          available, multi-tenant, long-term storage for Prometheus.
+          Available as
+          <link linkend="opt-services.mimir.enable">services.mimir</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://hastebin.com/about.md">Haste</link>,
+          a pastebin written in node.js. Available as
+          <link linkend="opt-services.haste-server.enable">services.haste</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/juanfont/headscale">headscale</link>,
+          an Open Source implementation of the
+          <link xlink:href="https://tailscale.io">Tailscale</link>
+          Control Server. Available as
+          <link linkend="opt-services.headscale.enable">services.headscale</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/hifi/heisenbridge">heisenbridge</link>,
+          a bouncer-style Matrix IRC bridge. Available as
+          <link linkend="opt-services.heisenbridge.enable">services.heisenbridge</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/aarond10/https_dns_proxy">https-dns-proxy</link>,
+          DNS to DNS over HTTPS (DoH) proxy. Available as
+          <link linkend="opt-services.https-dns-proxy.enable">services.https-dns-proxy</link>.
         </para>
       </listitem>
       <listitem>
@@ -265,7 +283,7 @@
           <link xlink:href="https://github.com/sezanzeb/input-remapper">input-remapper</link>,
           an easy to use tool to change the mapping of your input device
           buttons. Available at
-          <link xlink:href="options.html#opt-services.input-remapper.enable">services.input-remapper</link>.
+          <link linkend="opt-services.input-remapper.enable">services.input-remapper</link>.
         </para>
       </listitem>
       <listitem>
@@ -273,109 +291,133 @@
           <link xlink:href="https://invoiceplane.com">InvoicePlane</link>,
           web application for managing and creating invoices. Available
           at
-          <link xlink:href="options.html#opt-services.invoiceplane.enable">services.invoiceplane</link>.
+          <link linkend="opt-services.invoiceplane.sites._name_.enable">services.invoiceplane</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://maddy.email">maddy</link>, a
-          composable all-in-one mail server. Available as
-          <link xlink:href="options.html#opt-services.maddy.enable">services.maddy</link>.
+          <link xlink:href="https://userbase.kde.org/K3b">k3b</link>,
+          the KDE disk burning application. Available as
+          <link linkend="opt-programs.k3b.enable">programs.k3b</link>.
         </para>
       </listitem>
       <listitem>
         <para>
           <link xlink:href="https://www.scorchworks.com/K40whisperer/k40whisperer.html">K40-Whisperer</link>,
           a program to control cheap Chinese laser cutters. Available as
-          <link xlink:href="options.html#opt-programs.k4-whisperer.enable">programs.k40-whisperer.enable</link>.
+          <link linkend="opt-programs.k40-whisperer.enable">programs.k40-whisperer.enable</link>.
           Users must add themselves to the <literal>k40</literal> group
           to be able to access the device.
         </para>
       </listitem>
       <listitem>
         <para>
+          <link xlink:href="https://kanidm.github.io/kanidm/stable/">kanidm</link>,
+          an identity management server written in Rust. Available as
+          <link linkend="opt-services.kanidm.enableServer">services.kanidm</link>
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://maddy.email/">Maddy</link>, a free
+          an open source mail server. Availabe as
+          <link linkend="opt-services.maddy.enable">services.maddy</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://conduit.rs/">matrix-conduit</link>,
+          a simple, fast and reliable chat server powered by matrix.
+          Available as
+          <link xlink:href="option.html#opt-services.matrix-conduit.enable">services.matrix-conduit</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://moosefs.com">Moosefs</link>, fault
+          tolerant petabyte distributed file system. Available as
+          <link linkend="opt-services.moosefs.master.enable">moosefs</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           <link xlink:href="https://github.com/mozilla-mobile/mozilla-vpn-client">mozillavpn</link>,
           the client for the
           <link xlink:href="https://vpn.mozilla.org/">Mozilla VPN</link>
           service. Available as
-          <link xlink:href="options.html#opt-services.mozillavpn">services.mozillavpn</link>.
+          <link linkend="opt-services.mozillavpn.enable">services.mozillavpn</link>.
         </para>
       </listitem>
       <listitem>
         <para>
           <link xlink:href="https://github.com/mgumz/mtr-exporter">mtr-exporter</link>,
           a Prometheus exporter for mtr metrics. Available as
-          <link xlink:href="options.html#opt-services.mtr-exporter.enable">services.mtr-exporter</link>.
+          <link linkend="opt-services.mtr-exporter.enable">services.mtr-exporter</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/prometheus-pve/prometheus-pve-exporter">prometheus-pve-exporter</link>,
-          a tool that exposes information from the Proxmox VE API for
-          use by Prometheus. Available as
-          <link xlink:href="options.html#opt-services.prometheus.exporters.pve">services.prometheus.exporters.pve</link>.
+          <link xlink:href="https://nbd.sourceforge.io/">nbd</link>, a
+          Network Block Device server. Available as
+          <link linkend="opt-services.nbd.server.enable">services.nbd</link>.
         </para>
       </listitem>
       <listitem>
         <para>
           <link xlink:href="https://github.com/netbox-community/netbox">netbox</link>,
           infrastructure resource modeling (IRM) tool. Available as
-          <link xlink:href="options.html#opt-services.netbox.enable">services.netbox</link>.
+          <link linkend="opt-services.netbox.enable">services.netbox</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://tetrd.app">tetrd</link>, share your
-          internet connection from your device to your PC and vice versa
-          through a USB cable. Available at
-          <link linkend="opt-services.tetrd.enable">services.tetrd</link>.
+          <link xlink:href="https://github.com/vvilhonen/nethoscope">nethoscope</link>,
+          listen to your network traffic. Available as
+          <link linkend="opt-programs.nethoscope.enable">programs.nethoscope</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://upterm.dev">uptermd</link>, an
-          open-source solution for sharing terminal sessions instantly
-          over the public internet via secure tunnels. Available at
-          <link linkend="opt-services.uptermd.enable">services.uptermd</link>.
+          <link xlink:href="https://nifi.apache.org">nifi</link>, an
+          easy to use, powerful, and reliable system to process and
+          distribute data. Available as
+          <link linkend="opt-services.nifi.enable">services.nifi</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/mbrubeck/agate">agate</link>,
-          a very simple server for the Gemini hypertext protocol.
-          Available as
-          <link xlink:href="options.html#opt-services.agate.enable">services.agate</link>.
+          <link xlink:href="https://github.com/Mic92/nix-ld">nix-ld</link>,
+          Run unpatched dynamic binaries on NixOS. Available as
+          <link linkend="opt-programs.nix-ld.enable">programs.nix-ld</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm">ArchiSteamFarm</link>,
-          a C# application with primary purpose of idling Steam cards
-          from multiple accounts simultaneously. Available as
-          <link xlink:href="options.html#opt-services.archisteamfarm.enable">services.archisteamfarm</link>.
+          <link xlink:href="http://www.nncpgo.org">NNCP</link>, NNCP
+          (Node to Node copy) utilities and configuration, Available as
+          <link linkend="opt-programs.nncp.enable">programs.nncp</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://goteleport.com">teleport</link>,
-          allows engineers and security professionals to unify access
-          for SSH servers, Kubernetes clusters, web applications, and
-          databases across all environments. Available at
-          <link linkend="opt-services.teleport.enable">services.teleport</link>.
+          <link xlink:href="https://github.com/postgres/pgadmin4">pgadmin4</link>,
+          an admin interface for the PostgreSQL database. Available at
+          <link linkend="opt-services.pgadmin.enable">services.pgadmin</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://loic-sharma.github.io/BaGet/">BaGet</link>,
-          a lightweight NuGet and symbol server. Available at
-          <link linkend="opt-services.baget.enable">services.baget</link>.
+          <link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</link>,
+          a web interface for the PowerDNS server. Available at
+          <link linkend="opt-services.powerdns-admin.enable">services.powerdns-admin</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://moosefs.com">moosefs</link>, fault
-          tolerant petabyte distributed file system. Available as
-          <link linkend="opt-services.moosefs.client.enable">moosefs</link>.
+          <link xlink:href="https://github.com/prometheus-pve/prometheus-pve-exporter">prometheus-pve-exporter</link>,
+          a tool that exposes information from the Proxmox VE API for
+          use by Prometheus. Available as
+          <link linkend="opt-services.prometheus.exporters.pve.enable">services.prometheus.exporters.pve</link>.
         </para>
       </listitem>
       <listitem>
@@ -387,94 +429,145 @@
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/rfjakob/systembus-notify">systembus-notify</link>,
-          allow system level notifications to reach the users. Available
+          <link xlink:href="https://public-inbox.org">Public
+          Inbox</link>, an <quote>archives first</quote> approach to
+          mailing lists. Available as
+          <link linkend="opt-services.public-inbox.enable">services.public-inbox</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/fleaz/r53-ddns">r53-ddns</link>,
+          a small tool to run your own DDNS service via AWS Route53.
+          Available as
+          <link linkend="opt-services.r53-ddns.enable">services.r53-ddns</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://ddvk.github.io/rmfakecloud/">rmfakecloud</link>,
+          a clone of the cloud sync the remarkable tablet. Available as
+          <link linkend="opt-services.rmfakecloud.enable">services.rmfakecloud</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://docs.docker.com/engine/security/rootless/">rootless
+          Docker</link>, a <literal>systemd --user</literal> Docker
+          service which runs without root permissions. Available as
+          <link linkend="opt-virtualisation.docker.rootless.enable">virtualisation.docker.rootless.enable</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://www.rstudio.com/products/rstudio/#rstudio-server">rstudio-server</link>,
+          a browser-based version of the RStudio IDE for the R
+          programming language. Available as
+          <link linkend="opt-services.rstudio-server.enable">services.rstudio-server</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/aler9/rtsp-simple-server">rtsp-simple-server</link>,
+          ready-to-use RTSP / RTMP / HLS server and proxy that allows to
+          read, publish and proxy video and audio streams. Available as
+          <link linkend="opt-services.rtsp-simple-server.enable">services.rtsp-simple-server</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <link xlink:href="https://snipeitapp.com">Snipe-IT</link>, a
+          free open source IT asset/license management system. Available
           as
-          <link xlink:href="opt-services.systembus-notify.enable">services.systembus-notify</link>.
-          Please keep in mind that this service should only be enabled
-          on machines with fully trusted users, as any local user is
-          able to DoS user sessions by spamming notifications.
+          <link linkend="opt-services.snipe-it.enable">services.snipe-it</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/audreyt/ethercalc">ethercalc</link>,
-          an online collaborative spreadsheet. Available as
-          <link xlink:href="options.html#opt-services.ethercalc.enable">services.ethercalc</link>.
+          <link xlink:href="https://snowflake.torproject.org/">snowflake-proxy</link>,
+          a system to defeat internet censorship. Available as
+          <link linkend="opt-services.snowflake-proxy.enable">services.snowflake-proxy</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://nbd.sourceforge.io/">nbd</link>, a
-          Network Block Device server. Available as
-          <link xlink:href="options.html#opt-services.nbd.server.enable">services.nbd</link>.
+          <link xlink:href="https://sslmate.com/">sslmate-agent</link>,
+          a daemon for managing SSL/TLS certificates on a server.
+          Available as
+          <link xlink:href="services.sslmate-agent.enable">services.sslmate-agent</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/Mic92/nix-ld">nix-ld</link>,
-          Run unpatched dynamic binaries on NixOS. Available as
-          <link xlink:href="options.html#opt-programs.nix-ld.enable">programs.nix-ld</link>.
+          <link xlink:href="https://starship.rs">starship</link>, a
+          minimal, blazing-fast, and infinitely customizable prompt for
+          any shell. Available at
+          <link linkend="opt-programs.starship.enable">programs.startship</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://timetagger.app">timetagger</link>,
-          an open source time-tracker with an intuitive user experience
-          and powerful reporting.
-          <link xlink:href="options.html#opt-services.timetagger.enable">services.timetagger</link>.
+          <link xlink:href="https://github.com/rfjakob/systembus-notify">systembus-notify</link>,
+          allow system level notifications to reach the users. Available
+          as
+          <link xlink:href="opt-services.systembus-notify.enable">services.systembus-notify</link>.
+          Please keep in mind that this service should only be enabled
+          on machines with fully trusted users, as any local user is
+          able to DoS user sessions by spamming notifications.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://www.rstudio.com/products/rstudio/#rstudio-server">rstudio-server</link>,
-          a browser-based version of the RStudio IDE for the R
-          programming language. Available as
-          <link xlink:href="options.html#opt-services.rstudio-server.enable">services.rstudio-server</link>.
+          <link xlink:href="https://goteleport.com">teleport</link>,
+          allows engineers and security professionals to unify access
+          for SSH servers, Kubernetes clusters, web applications, and
+          databases across all environments. Available at
+          <link linkend="opt-services.teleport.enable">services.teleport</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/juanfont/headscale">headscale</link>,
-          an Open Source implementation of the
-          <link xlink:href="https://tailscale.io">Tailscale</link>
-          Control Server. Available as
-          <link xlink:href="options.html#opt-services.headscale.enable">services.headscale</link>
+          <link xlink:href="https://tetrd.app">tetrd</link>, share your
+          internet connection from your device to your PC and vice versa
+          through a USB cable. Available at
+          <link linkend="opt-services.tetrd.enable">services.tetrd</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://github.com/lakinduakash/linux-wifi-hotspot">create_ap</link>,
-          a module for creating wifi hotspots using the program
-          linux-wifi-hotspot. Available as
-          <link xlink:href="options.html#opt-services.create_ap.enable">services.create_ap</link>.
+          <link xlink:href="https://upterm.dev">uptermd</link>, an
+          open-source solution for sharing terminal sessions instantly
+          over the public internet via secure tunnels. Available at
+          <link linkend="opt-services.uptermd.enable">services.uptermd</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://0xerr0r.github.io/blocky/">blocky</link>,
-          fast and lightweight DNS proxy as ad-blocker for local network
-          with many features.
+          <link xlink:href="https://github.com/darrylb123/usbrelay">usbrelayd</link>,
+          an USB Relay MQTT daemon. Available as
+          <link linkend="opt-services.usbrelayd.enable">services.usbrelayd</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://clusterlabs.org/pacemaker/">pacemaker</link>
-          cluster resource manager
+          <link xlink:href="https://github.com/miquels/webdav-server-rs">webdav-server-rs</link>,
+          Webdav server in rust. Available as
+          <link linkend="opt-services.webdav-server-rs.enable">services.webdav-server-rs</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://nifi.apache.org">nifi</link>, an
-          easy to use, powerful, and reliable system to process and
-          distribute data. Available as
-          <link xlink:href="options.html#opt-services.nifi.enable">services.nifi</link>.
+          <link xlink:href="https://github.com/gin66/wg_netmanager">wg-netmanager</link>,
+          the Wireguard network manager. Available as
+          <link linkend="opt-services.wg-netmanager.enable">services.wg-netmanager</link>.
         </para>
       </listitem>
       <listitem>
         <para>
-          <link xlink:href="https://kanidm.github.io/kanidm/stable/">kanidm</link>,
-          an identity management server written in Rust.
+          <link xlink:href="https://zammad.org/">Zammad</link>, a
+          web-based, open source user support/ticketing solution.
+          Available as
+          <link linkend="opt-services.zammad.enable">services.zammad</link>.
         </para>
       </listitem>
     </itemizedlist>
@@ -522,7 +615,7 @@
           version of the <literal>xmonad</literal> module, which will
           break your configuration if you use <literal>launch</literal>
           as entrypoint. The example code the corresponding nixos module
-          was adjusted, you way want to have a look at it.
+          was adjusted, you may want to have a look at it.
         </para>
       </listitem>
       <listitem>
@@ -577,6 +670,15 @@
       </listitem>
       <listitem>
         <para>
+          <literal>lib.systems.supported</literal> has been removed, as
+          it was overengineered for determining the systems to support
+          in the nixpkgs flake. The list of systems exposed by the
+          nixpkgs flake can now be accessed as
+          <literal>lib.systems.flakeExposed</literal>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           For new installations
           <literal>virtualisation.oci-containers.backend</literal> is
           now set to <literal>podman</literal> by default. If you still
@@ -683,6 +785,25 @@
       </listitem>
       <listitem>
         <para>
+          <literal>openldap</literal> (and therefore the slapd LDAP
+          server) were updated to version 2.6.2. The project introduced
+          backwards-incompatible changes, namely the removal of the bdb,
+          hdb, ndb, and shell backends in slapd. Therefore before
+          updating, dump your database <literal>slapcat -n 1</literal>
+          in LDIF format, and reimport it after updating your
+          <literal>services.openldap.settings</literal>, which
+          represents your <literal>cn=config</literal>.
+        </para>
+        <para>
+          Additionally with 2.5 the argon2 module was included in the
+          standard distrubtion and renamed from
+          <literal>pw-argon2</literal> to <literal>argon2</literal>.
+          Remember to update your <literal>olcModuleLoad</literal> entry
+          in <literal>cn=config</literal>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           <literal>openssh</literal> has been update to 8.9p1, changing
           the FIDO security key middleware interface.
         </para>
@@ -885,7 +1006,7 @@
     };
 
     extraConfigFiles = [
-      /run/keys/matrix-synapse/secrets.yaml
+      &quot;/run/keys/matrix-synapse/secrets.yaml&quot;
     ];
   };
 }
@@ -893,7 +1014,9 @@
         <para>
           The secrets in your original config should be migrated into a
           YAML file that is included via
-          <literal>extraConfigFiles</literal>.
+          <literal>extraConfigFiles</literal>. The filename must be
+          quoted to prevent nix from copying it to the (world readable)
+          store.
         </para>
         <para>
           Additionally a few option defaults have been synced up with
@@ -1647,6 +1770,19 @@
       </listitem>
       <listitem>
         <para>
+          The default version of <literal>nextcloud</literal> is
+          <emphasis role="strong">nextcloud24</emphasis>. Please note
+          that it’s <emphasis role="strong">not</emphasis> possible to
+          upgrade <literal>nextcloud</literal> across multiple major
+          versions! This means it’s e.g. not possible to upgrade from
+          <literal>nextcloud22</literal> to
+          <literal>nextcloud24</literal> in a single deploy and most
+          <literal>21.11</literal> users will have to upgrade to
+          <literal>nextcloud23</literal> first.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           <literal>pkgs.vimPlugins.onedark-nvim</literal> now refers to
           <link xlink:href="https://github.com/navarasu/onedark.nvim">navarasu/onedark.nvim</link>
           (formerly refers to
@@ -1853,6 +1989,43 @@
       </listitem>
       <listitem>
         <para>
+          <link xlink:href="https://kops.sigs.k8s.io"><literal>kops</literal></link>
+          defaults to 1.23.2, which will enable
+          <link xlink:href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html">Instance
+          Metadata Service Version 2</link> and require tokens on new
+          clusters with Kubernetes &gt;= 1.22. This will increase
+          security by default, but may break some types of workloads.
+          The default behaviour for
+          <literal>spec.kubeDNS.nodeLocalDNS.forwardToKubeDNS</literal>
+          has changed from <literal>true</literal> to
+          <literal>false</literal>. Cilium now has
+          <literal>disable-cnp-status-updates: true</literal> by
+          default. Set this to false if you rely on the
+          CiliumNetworkPolicy status fields. Support for Kubernetes
+          1.17, the Lyft CNI, Weave CNI on Kubernetes &gt;= 1.23, CentOS
+          7 and 8, Debian 9, RHEL 7, and Ubuntu 16.05 (Xenial) has been
+          removed. See the
+          <link xlink:href="https://kops.sigs.k8s.io/releases/1.22-notes/">1.22
+          release notes</link> and
+          <link xlink:href="https://kops.sigs.k8s.io/releases/1.23-notes/">1.23
+          release notes</link> for more details, including other
+          significant changes.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          Mattermost has been upgraded to extended support version 6.3
+          as the previously packaged extended support version 5.37 is
+          <link xlink:href="https://docs.mattermost.com/upgrade/extended-support-release.html">reaching
+          end of life</link>. Migration may take some time, see the
+          <link xlink:href="https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release">changelog</link>
+          and
+          <link xlink:href="https://docs.mattermost.com/upgrade/important-upgrade-notes.html">important
+          upgrade notes</link>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           The
           <literal>writers.writePyPy2</literal>/<literal>writers.writePyPy3</literal>
           and corresponding
@@ -1929,6 +2102,28 @@ cp /var/lib/redis/dump.rdb &quot;/var/lib/redis-mastodon/dump.rdb&quot;
       </listitem>
       <listitem>
         <para>
+          Peertube now uses services.redis.servers to start a new redis
+          server, instead of using a global redis server. This improves
+          compatibility with other services that use redis.
+        </para>
+        <para>
+          Redis database is used for storage only cache and job queue.
+          More information can be found here -
+          <link xlink:href="https://docs.joinpeertube.org/contribute-architecture">Peertube
+          architecture</link>.
+        </para>
+        <para>
+          If you do want to save the redis database, you can use the
+          following commands before upgrade OS:
+        </para>
+        <programlisting language="bash">
+redis-cli save
+sudo mkdir /var/lib/redis-peertube
+sudo cp /var/lib/redis/dump.rdb /var/lib/redis-peertube/dump.rdb
+</programlisting>
+      </listitem>
+      <listitem>
+        <para>
           If you are using Wayland you can choose to use the Ozone
           Wayland support in Chrome and several Electron apps by setting
           the environment variable <literal>NIXOS_OZONE_WL=1</literal>
@@ -2100,13 +2295,6 @@ cp /var/lib/redis/dump.rdb &quot;/var/lib/redis-mastodon/dump.rdb&quot;
       </listitem>
       <listitem>
         <para>
-          A new module was added for the Envoy reverse proxy, providing
-          the options <literal>services.envoy.enable</literal> and
-          <literal>services.envoy.settings</literal>.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
           The option <literal>services.duplicati.dataDir</literal> has
           been added to allow changing the location of duplicati’s
           files.
@@ -2302,15 +2490,6 @@ cp /var/lib/redis/dump.rdb &quot;/var/lib/redis-mastodon/dump.rdb&quot;
       </listitem>
       <listitem>
         <para>
-          A new module was added for the
-          <link xlink:href="https://starship.rs/">Starship</link> shell
-          prompt, providing the options
-          <literal>programs.starship.enable</literal> and
-          <literal>programs.starship.settings</literal>.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
           The <link xlink:href="https://dino.im">Dino</link> XMPP client
           was updated to 0.3, adding support for audio and video calls.
         </para>
@@ -2517,6 +2696,14 @@ cp /var/lib/redis/dump.rdb &quot;/var/lib/redis-mastodon/dump.rdb&quot;
       </listitem>
       <listitem>
         <para>
+          The default <literal>scribus</literal> version is now 1.5,
+          while version 1.4 is still available as
+          <literal>scribus_1_4</literal>
+          (<link xlink:href="https://github.com/NixOS/nixpkgs/pull/172700">#172700</link>).
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           The Nextcloud module now supports to create a Mysql database
           automatically with
           <literal>services.nextcloud.database.createLocally</literal>
@@ -2560,12 +2747,6 @@ cp /var/lib/redis/dump.rdb &quot;/var/lib/redis-mastodon/dump.rdb&quot;
       </listitem>
       <listitem>
         <para>
-          The <literal>programs.nncp</literal> options were added for
-          generating host-global NNCP configuration.
-        </para>
-      </listitem>
-      <listitem>
-        <para>
           The option <literal>services.snapserver.openFirewall</literal>
           will no longer default to <literal>true</literal> starting
           with NixOS 22.11. Enable it explicitly if you need to control
@@ -2588,6 +2769,40 @@ cp /var/lib/redis/dump.rdb &quot;/var/lib/redis-mastodon/dump.rdb&quot;
           case of scripted networking, no behavior was changed.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          The new
+          <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#sec-postgresqlTestHook"><literal>postgresqlTestHook</literal></link>
+          runs a PostgreSQL server for the duration of package checks.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          <literal>stdenv.mkDerivation</literal> now supports a
+          self-referencing <literal>finalAttrs:</literal> parameter
+          containing the final <literal>mkDerivation</literal> arguments
+          including overrides. <literal>drv.overrideAttrs</literal> now
+          supports two parameters
+          <literal>finalAttrs: previousAttrs:</literal>. This allows
+          packaging configuration to be overridden in a consistent
+          manner by providing an alternative to
+          <literal>rec {}</literal> syntax.
+        </para>
+        <para>
+          Additionally, <literal>passthru</literal> can now reference
+          <literal>finalAttrs.finalPackage</literal> containing the
+          final package, including attributes such as the output paths
+          and <literal>overrideAttrs</literal>.
+        </para>
+        <para>
+          New language integrations can be simplified by overriding a
+          <quote>prototype</quote> package containing the
+          language-specific logic. This removes the need for a extra
+          layer of overriding for the <quote>generic builder</quote>
+          arguments, thus removing a usability problem and source of
+          error.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
 </section>
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
new file mode 100644
index 00000000000..6181d2c3eeb
--- /dev/null
+++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
@@ -0,0 +1,114 @@
+<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-release-22.11">
+  <title>Release 22.11 (“Raccoon”, 2022.11/??)</title>
+  <para>
+    Support is planned until the end of June 2023, handing over to
+    23.05.
+  </para>
+  <section xml:id="sec-release-22.11-highlights">
+    <title>Highlights</title>
+    <para>
+      In addition to numerous new and upgraded packages, this release
+      has the following highlights:
+    </para>
+    <itemizedlist>
+      <listitem>
+        <para>
+          During cross-compilation, tests are now executed if the test
+          suite can be executed by the build platform. This is the case
+          when doing “native” cross-compilation where the build and host
+          platforms are largely the same, but the nixpkgs’ cross
+          compilation infrastructure is used, e.g.
+          <literal>pkgsStatic</literal> and <literal>pkgsLLVM</literal>.
+          Another possibility is that the build platform is a superset
+          of the host platform, e.g. when cross-compiling from
+          <literal>x86_64-unknown-linux</literal> to
+          <literal>i686-unknown-linux</literal>. The predicate gating
+          test suite execution is the newly added
+          <literal>canExecute</literal> predicate: You can e.g. check if
+          <literal>stdenv.buildPlatform</literal> can execute binaries
+          built for <literal>stdenv.hostPlatform</literal> (i.e.
+          produced by <literal>stdenv.cc</literal>) by evaluating
+          <literal>stdenv.buildPlatform.canExecute stdenv.hostPlatform</literal>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          PHP now defaults to PHP 8.1, updated from 8.0.
+        </para>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section xml:id="sec-release-22.11-new-services">
+    <title>New Services</title>
+    <itemizedlist spacing="compact">
+      <listitem>
+        <para>
+          <link xlink:href="https://github.com/jollheef/appvm">appvm</link>,
+          Nix based app VMs. Available as
+          <link xlink:href="options.html#opt-virtualisation.appvm.enable">virtualisation.appvm</link>.
+        </para>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section xml:id="sec-release-22.11-incompatibilities">
+    <title>Backward Incompatibilities</title>
+    <itemizedlist>
+      <listitem>
+        <para>
+          The <literal>isCompatible</literal> predicate checking CPU
+          compatibility is no longer exposed by the platform sets
+          generated using <literal>lib.systems.elaborate</literal>. In
+          most cases you will want to use the new
+          <literal>canExecute</literal> predicate instead which also
+          considers the kernel / syscall interface. It is briefly
+          described in the release’s
+          <link linkend="sec-release-22.11-highlights">highlights
+          section</link>.
+          <literal>lib.systems.parse.isCompatible</literal> still
+          exists, but has changed semantically: Architectures with
+          differing endianness modes are <emphasis>no longer considered
+          compatible</emphasis>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          The <literal>isPowerPC</literal> predicate, found on
+          <literal>platform</literal> attrsets
+          (<literal>hostPlatform</literal>,
+          <literal>buildPlatform</literal>,
+          <literal>targetPlatform</literal>, etc) has been removed in
+          order to reduce confusion. The predicate was was defined such
+          that it matches only the 32-bit big-endian members of the
+          POWER/PowerPC family, despite having a name which would imply
+          a broader set of systems. If you were using this predicate,
+          you can replace <literal>foo.isPowerPC</literal> with
+          <literal>(with foo; isPower &amp;&amp; is32bit &amp;&amp; isBigEndian)</literal>.
+        </para>
+      </listitem>
+    </itemizedlist>
+  </section>
+  <section xml:id="sec-release-22.11-notable-changes">
+    <title>Other Notable Changes</title>
+    <itemizedlist>
+      <listitem>
+        <para>
+          A new module was added for the Saleae Logic device family,
+          providing the options
+          <literal>hardware.saleae-logic.enable</literal> and
+          <literal>hardware.saleae-logic.package</literal>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
+          Matrix Synapse now requires entries in the
+          <literal>state_group_edges</literal> table to be unique, in
+          order to prevent accidentally introducing duplicate
+          information (for example, because a database backup was
+          restored multiple times). If your Synapse database already has
+          duplicate rows in this table, this could fail with an error
+          and require manual remediation.
+        </para>
+      </listitem>
+    </itemizedlist>
+  </section>
+</section>
diff --git a/nixos/doc/manual/installation/upgrading.chapter.md b/nixos/doc/manual/installation/upgrading.chapter.md
index faeefc4451d..2644979bc9d 100644
--- a/nixos/doc/manual/installation/upgrading.chapter.md
+++ b/nixos/doc/manual/installation/upgrading.chapter.md
@@ -6,7 +6,7 @@ expressions and associated binaries. The NixOS channels are updated
 automatically from NixOS's Git repository after certain tests have
 passed and all packages have been built. These channels are:
 
--   *Stable channels*, such as [`nixos-21.11`](https://nixos.org/channels/nixos-21.11).
+-   *Stable channels*, such as [`nixos-22.05`](https://nixos.org/channels/nixos-22.05).
     These only get conservative bug fixes and package upgrades. For
     instance, a channel update may cause the Linux kernel on your system
     to be upgraded from 4.19.34 to 4.19.38 (a minor bug fix), but not
@@ -19,7 +19,7 @@ passed and all packages have been built. These channels are:
     radical changes between channel updates. It's not recommended for
     production systems.
 
--   *Small channels*, such as [`nixos-21.11-small`](https://nixos.org/channels/nixos-21.11-small)
+-   *Small channels*, such as [`nixos-22.05-small`](https://nixos.org/channels/nixos-22.05-small)
     or [`nixos-unstable-small`](https://nixos.org/channels/nixos-unstable-small).
     These are identical to the stable and unstable channels described above,
     except that they contain fewer binary packages. This means they get updated
@@ -38,8 +38,8 @@ newest supported stable release.
 
 When you first install NixOS, you're automatically subscribed to the
 NixOS channel that corresponds to your installation source. For
-instance, if you installed from a 21.11 ISO, you will be subscribed to
-the `nixos-21.11` channel. To see which NixOS channel you're subscribed
+instance, if you installed from a 22.05 ISO, you will be subscribed to
+the `nixos-22.05` channel. To see which NixOS channel you're subscribed
 to, run the following as root:
 
 ```ShellSession
@@ -54,16 +54,16 @@ To switch to a different NixOS channel, do
 ```
 
 (Be sure to include the `nixos` parameter at the end.) For instance, to
-use the NixOS 21.11 stable channel:
+use the NixOS 22.05 stable channel:
 
 ```ShellSession
-# nix-channel --add https://nixos.org/channels/nixos-21.11 nixos
+# nix-channel --add https://nixos.org/channels/nixos-22.05 nixos
 ```
 
 If you have a server, you may want to use the "small" channel instead:
 
 ```ShellSession
-# nix-channel --add https://nixos.org/channels/nixos-21.11-small nixos
+# nix-channel --add https://nixos.org/channels/nixos-22.05-small nixos
 ```
 
 And if you want to live on the bleeding edge:
@@ -114,5 +114,5 @@ the new generation contains a different kernel, initrd or kernel
 modules. You can also specify a channel explicitly, e.g.
 
 ```nix
-system.autoUpgrade.channel = https://nixos.org/channels/nixos-21.11;
+system.autoUpgrade.channel = https://nixos.org/channels/nixos-22.05;
 ```
diff --git a/nixos/doc/manual/release-notes/release-notes.xml b/nixos/doc/manual/release-notes/release-notes.xml
index 216fea67775..ee5009faf6f 100644
--- a/nixos/doc/manual/release-notes/release-notes.xml
+++ b/nixos/doc/manual/release-notes/release-notes.xml
@@ -8,6 +8,7 @@
   This section lists the release notes for each stable version of NixOS and
   current unstable revision.
  </para>
+ <xi:include href="../from_md/release-notes/rl-2211.section.xml" />
  <xi:include href="../from_md/release-notes/rl-2205.section.xml" />
  <xi:include href="../from_md/release-notes/rl-2111.section.xml" />
  <xi:include href="../from_md/release-notes/rl-2105.section.xml" />
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index 9261511e7b8..faf941f5699 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -1,53 +1,44 @@
-# Release 22.05 (“Quokka”, 2022.05/??) {#sec-release-22.05}
-
-In addition to numerous new and upgraded packages, this release has the following highlights:
+# Release 22.05 (“Quokka”, 2022.05/30) {#sec-release-22.05}
 
 - Support is planned until the end of December 2022, handing over to 22.11.
 
 ## Highlights {#sec-release-22.05-highlights}
 
-- The `firefox` browser on `x86_64-linux` is now making use of
-  profile-guided optimization resulting in a much more responsive
-  browsing experience.
+In addition to numerous new and upgraded packages, this release has the following highlights:
 
-- `security.acme.defaults` has been added to simplify configuring
-  settings for many certificates at once. This also opens up the
-  the option to use DNS-01 validation when using `enableACME` on
-  web server virtual hosts (e.g. `services.nginx.virtualHosts.*.enableACME`).
+- Nix has been updated from 2.3 to 2.8. This mainly brings experimental support
+  for Flakes, but also marks the `nix` command as experimental which now has to
+  be enabled via the configuration explicitly. For more information and
+  instructions for upgrades, see the 
+  relase notes for [nix-2.4](https://nixos.org/manual/nix/stable/release-notes/rl-2.4.html),  
+  [nix-2.5](https://nixos.org/manual/nix/stable/release-notes/rl-2.5.html),
+  [nix-2.6](https://nixos.org/manual/nix/stable/release-notes/rl-2.6.html),
+  [nix-2.7](https://nixos.org/manual/nix/stable/release-notes/rl-2.7.html) and
+  [nix-2.8](https://nixos.org/manual/nix/stable/release-notes/rl-2.8.html)
 
-- GNOME has been upgraded to 42. Please take a look at their [Release Notes](https://release.gnome.org/42/) for details. Notably, it replaces gedit with GNOME Text Editor, GNOME Terminal with GNOME Console (formerly King’s Cross), and GNOME Screenshot with a tool built into the Shell.
+- The `firefox` browser on `x86_64-linux` now makes use of profile-guided
+  optimisation, resulting in a much more responsive browsing experience.
 
-- `stdenv.mkDerivation` now supports a self-referencing `finalAttrs:` parameter
-  containing the final `mkDerivation` arguments including overrides.
-  `drv.overrideAttrs` now supports two parameters `finalAttrs: previousAttrs:`.
-  This allows packaging configuration to be overridden in a consistent manner by
-  providing an alternative to `rec {}` syntax.
+- GNOME has been upgraded to 42. Please take a look at their [Release
+  Notes](https://release.gnome.org/42/) for details. In particular, it replaces
+  gedit with GNOME Text Editor, GNOME Terminal with GNOME Console (formerly
+  King's Cross) and GNOME Screenshot by a tool integrated into the Shell.
 
-  Additionally, `passthru` can now reference `finalAttrs.finalPackage` containing
-  the final package, including attributes such as the output paths and
-  `overrideAttrs`.
-
-  New language integrations can be simplified by overriding a "prototype"
-  package containing the language-specific logic. This removes the need for a
-  extra layer of overriding for the "generic builder" arguments, thus removing a
-  usability problem and source of error.
-
-- PHP 8.1 is now available
-
-- Mattermost has been updated to extended support release 6.3, as the previously packaged extended support release 5.37 is [reaching its end of life](https://docs.mattermost.com/upgrade/extended-support-release.html).
-  Migrations may take a while, see the [changelog](https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release)
-  and [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html).
+- PHP 8.1 is now available.
 
 - systemd services can now set [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services) instead of `reloadIfChanged` for a more granular distinction between reloads and restarts.
 
 - Systemd has been upgraded to the version 250.
 
-- Pulseaudio has been upgraded to version 15.0 and now optionally [supports additional Bluetooth audio codecs](https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/15.0/#supportforldacandaptxbluetoothcodecsplussbcxqsbcwithhigher-qualityparameters) like aptX or LDAC, with codec switching support being available in `pavucontrol`. This feature is disabled by default but can be enabled by using `hardware.pulseaudio.package = pkgs.pulseaudioFull;`.
-  Existing 3rd party modules that provided similar functionality, like `pulseaudio-modules-bt` or `pulseaudio-hsphfpd` are deprecated and have been removed.
-
-- The new [`postgresqlTestHook`](https://nixos.org/manual/nixpkgs/stable/#sec-postgresqlTestHook) runs a PostgreSQL server for the duration of package checks.
+- Pulseaudio has been updated to version 15.0 and now optionally 
+  [supports additional Bluetooth audio codecs](https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/15.0/#supportforldacandaptxbluetoothcodecsplussbcxqsbcwithhigher-qualityparameters)
+  such as aptX or LDAC, with codec switching available in `pavucontrol`. This
+  feature is disabled by default, but can be enabled with the option
+  `hardware.pulseaudio.package = pkgs.pulseaudioFull;`. Existing third-party
+  modules that offered similar functions, such as `pulseaudio-modules-bt` or
+  `pulseaudio-hsphfpd`, are obsolete and have been removed.
 
-- [`kops`](https://kops.sigs.k8s.io) defaults to 1.22.4, which will enable [Instance Metadata Service Version 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) and require tokens on new clusters with Kubernetes 1.22. This will increase security by default, but may break some types of workloads. See the [release notes](https://kops.sigs.k8s.io/releases/1.22-notes/) for details.
+- PostgreSQL now defaults to major version 14.
 
 - Module authors can use `mkRenamedOptionModuleWith` to automate the deprecation cycle without annoying out-of-tree module authors and their users.
 
@@ -55,91 +46,130 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - The GNOME and Plasma installation CDs now use `pkgs.calamares` and `pkgs.calamares-nixos-extensions` to allow users to easily install and set up NixOS with a GUI.
 
+- `security.acme.defaults` has been added to simplify the configuration of
+  settings for many certificates at once. This also opens up the option to use
+  DNS-01 validation when using `enableACME` web server virtual hosts (e.g.
+  `services.nginx.virtualHosts.*.enableACME`).
+  
 ## New Services {#sec-release-22.05-new-services}
 
+- [1password](https://1password.com/), command-lines and graphic interface for 1Password. Available as [programs._1password](#opt-programs._1password.enable) and [programs._1password-gui](#opt-programs._1password.enable).
+
 - [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.enable).
 
-- [rootless Docker](https://docs.docker.com/engine/security/rootless/), a `systemd --user` Docker service which runs without root permissions. Available as [virtualisation.docker.rootless.enable](options.html#opt-virtualisation.docker.rootless.enable).
+- [agate](https://github.com/mbrubeck/agate), a very simple server for the Gemini hypertext protocol. Available as [services.agate](#opt-services.agate.enable).
 
-- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable).
+- [apfs](https://github.com/linux-apfs/linux-apfs-rw), a kernel module for mounting the Apple File System (APFS).
 
-- [nethoscope](https://github.com/vvilhonen/nethoscope), listen to your network traffic. Available as [programs.nethoscope](#opt-programs.nethoscope.enable).
+- [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm), a C# application with primary purpose of idling Steam cards from multiple accounts simultaneously. Available as [services.archisteamfarm](#opt-services.archisteamfarm.enable).
+
+- [BaGet](https://loic-sharma.github.io/BaGet/), a lightweight NuGet and symbol server. Available at [services.baget](#opt-services.baget.enable).
+
+- [bird-lg](https://github.com/xddxdd/bird-lg-go), a BGP looking glass for Bird Routing. Available as [services.bird-lg](#opt-services.bird-lg.package).
+
+- [blocky](https://0xerr0r.github.io/blocky/), fast and lightweight DNS proxy as ad-blocker for local network with many features. Available as [services.blocky](#opt-services.blocky.enable).
+
+- [cloudflare-dyndns](https://github.com/kissgyorgy/cloudflare-dyndns), CloudFlare Dynamic DNS client. Available as [services.cloudflare-dyndns](#opt-services.cloudflare-dyndns.enable).
+
+- [Corosync](https://corosync.github.io/corosync/) and [Pacemaker](https://clusterlabs.org/pacemaker/), A open-source high availability resource manager. Available as [services.corosync](#opt-services.corosync.enable) and [services.pacemaker](#opt-services.pacemaker.enable).
+
+- [create_ap](https://github.com/lakinduakash/linux-wifi-hotspot), a module for creating wifi hotspots using the program linux-wifi-hotspot. Available as [services.create_ap](#opt-services.create_ap.enable).
+
+- [Envoy](https://www.envoyproxy.io/), a high-performance reverse proxy. Available as [services.envoy](#opt-services.envoy.enable).
+
+- [ergochat](https://ergo.chat), a modern IRC with IRCv3 features. Available as [services.ergochat](#opt-services.ergochat.enable).
+
+- [ethercalc](https://github.com/audreyt/ethercalc), an online collaborative spreadsheet. Available as [services.ethercalc](#opt-services.ethercalc.enable).
 
 - [filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html), a lightweight shipper for forwarding and centralizing log data. Available as [services.filebeat](#opt-services.filebeat.enable).
 
-- [apfs](https://github.com/linux-apfs/linux-apfs-rw), a kernel module for mounting the Apple File System (APFS).
+- [FRRouting](https://frrouting.org/), a popular suite of Internet routing protocol daemons (BGP, BFD, OSPF, IS-IS, VRRP and others). Available as [services.frr](#opt-services.frr.babel.enable).
 
-- [FRRouting](https://frrouting.org/), a popular suite of Internet routing protocol daemons (BGP, BFD, OSPF, IS-IS, VRRP and others). Available as [services.frr](#opt-services.frr.babel.enable)
+- [Grafana Mimir](https://grafana.com/oss/mimir/), an open source, horizontally scalable, highly available, multi-tenant, long-term storage for Prometheus. Available as [services.mimir](#opt-services.mimir.enable).
 
-- [heisenbridge](https://github.com/hifi/heisenbridge), a bouncer-style Matrix IRC bridge. Available as [services.heisenbridge](options.html#opt-services.heisenbridge.enable).
+- [Haste](https://hastebin.com/about.md), a pastebin written in node.js. Available as [services.haste](#opt-services.haste-server.enable).
 
-- [snowflake-proxy](https://snowflake.torproject.org/), a system to defeat internet censorship. Available as [services.snowflake-proxy](options.html#opt-services.snowflake-proxy.enable).
+- [headscale](https://github.com/juanfont/headscale), an Open Source implementation of the [Tailscale](https://tailscale.io) Control Server. Available as [services.headscale](#opt-services.headscale.enable).
 
-- [ergochat](https://ergo.chat), a modern IRC with IRCv3 features. Available as [services.ergochat](options.html#opt-services.ergochat.enable).
+- [heisenbridge](https://github.com/hifi/heisenbridge), a bouncer-style Matrix IRC bridge. Available as [services.heisenbridge](#opt-services.heisenbridge.enable).
 
-- [Snipe-IT](https://snipeitapp.com), a free open source IT asset/license management system. Available as [services.snipe-it](options.html#opt-services.snipe-it.enable).
+- [https-dns-proxy](https://github.com/aarond10/https_dns_proxy), DNS to DNS over HTTPS (DoH) proxy. Available as [services.https-dns-proxy](#opt-services.https-dns-proxy.enable).
 
-- [PowerDNS-Admin](https://github.com/ngoduykhanh/PowerDNS-Admin), a web interface for the PowerDNS server. Available at [services.powerdns-admin](options.html#opt-services.powerdns-admin.enable).
+- [input-remapper](https://github.com/sezanzeb/input-remapper), an easy to use tool to change the mapping of your input device buttons. Available at [services.input-remapper](#opt-services.input-remapper.enable).
 
-- [pgadmin4](https://github.com/postgres/pgadmin4), an admin interface for the PostgreSQL database. Available at [services.pgadmin](options.html#opt-services.pgadmin.enable).
+- [InvoicePlane](https://invoiceplane.com), web application for managing and creating invoices. Available at [services.invoiceplane](#opt-services.invoiceplane.sites._name_.enable).
 
-- [input-remapper](https://github.com/sezanzeb/input-remapper), an easy to use tool to change the mapping of your input device buttons. Available at [services.input-remapper](options.html#opt-services.input-remapper.enable).
+- [k3b](https://userbase.kde.org/K3b), the KDE disk burning application. Available as [programs.k3b](#opt-programs.k3b.enable).
 
-- [InvoicePlane](https://invoiceplane.com), web application for managing and creating invoices. Available at [services.invoiceplane](options.html#opt-services.invoiceplane.enable).
+- [K40-Whisperer](https://www.scorchworks.com/K40whisperer/k40whisperer.html), a program to control cheap Chinese laser cutters. Available as [programs.k40-whisperer.enable](#opt-programs.k40-whisperer.enable). Users must add themselves to the `k40` group to be able to access the device.
 
-- [maddy](https://maddy.email), a composable all-in-one mail server. Available as [services.maddy](options.html#opt-services.maddy.enable).
+- [kanidm](https://kanidm.github.io/kanidm/stable/), an identity management server written in Rust. Available as [services.kanidm](#opt-services.kanidm.enableServer)
 
-- [K40-Whisperer](https://www.scorchworks.com/K40whisperer/k40whisperer.html), a program to control cheap Chinese laser cutters. Available as [programs.k40-whisperer.enable](options.html#opt-programs.k4-whisperer.enable). Users must add themselves to the `k40` group to be able to access the device.
+- [Maddy](https://maddy.email/), a free an open source mail server. Availabe as [services.maddy](#opt-services.maddy.enable).
 
-- [mozillavpn](https://github.com/mozilla-mobile/mozilla-vpn-client), the client for the [Mozilla VPN](https://vpn.mozilla.org/) service. Available as [services.mozillavpn](options.html#opt-services.mozillavpn).
+- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable).
 
-- [mtr-exporter](https://github.com/mgumz/mtr-exporter), a Prometheus exporter for mtr metrics. Available as [services.mtr-exporter](options.html#opt-services.mtr-exporter.enable).
+- [Moosefs](https://moosefs.com), fault tolerant petabyte distributed file system. Available as [moosefs](#opt-services.moosefs.master.enable).
 
-- [prometheus-pve-exporter](https://github.com/prometheus-pve/prometheus-pve-exporter), a tool that exposes information from the Proxmox VE API for use by Prometheus. Available as [services.prometheus.exporters.pve](options.html#opt-services.prometheus.exporters.pve).
+- [mozillavpn](https://github.com/mozilla-mobile/mozilla-vpn-client), the client for the [Mozilla VPN](https://vpn.mozilla.org/) service. Available as [services.mozillavpn](#opt-services.mozillavpn.enable).
 
-- [netbox](https://github.com/netbox-community/netbox), infrastructure resource modeling (IRM) tool. Available as [services.netbox](options.html#opt-services.netbox.enable).
+- [mtr-exporter](https://github.com/mgumz/mtr-exporter), a Prometheus exporter for mtr metrics. Available as [services.mtr-exporter](#opt-services.mtr-exporter.enable).
 
-- [tetrd](https://tetrd.app), share your internet connection from your device to your PC and vice versa through a USB cable. Available at [services.tetrd](#opt-services.tetrd.enable).
+- [nbd](https://nbd.sourceforge.io/), a Network Block Device server. Available as [services.nbd](#opt-services.nbd.server.enable).
 
-- [uptermd](https://upterm.dev), an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels. Available at [services.uptermd](#opt-services.uptermd.enable).
+- [netbox](https://github.com/netbox-community/netbox), infrastructure resource modeling (IRM) tool. Available as [services.netbox](#opt-services.netbox.enable).
 
-- [agate](https://github.com/mbrubeck/agate), a very simple server for the Gemini hypertext protocol. Available as [services.agate](options.html#opt-services.agate.enable).
+- [nethoscope](https://github.com/vvilhonen/nethoscope), listen to your network traffic. Available as [programs.nethoscope](#opt-programs.nethoscope.enable).
 
-- [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm), a C# application with primary purpose of idling Steam cards from multiple accounts simultaneously. Available as [services.archisteamfarm](options.html#opt-services.archisteamfarm.enable).
+- [nifi](https://nifi.apache.org), an easy to use, powerful, and reliable system to process and distribute data. Available as [services.nifi](#opt-services.nifi.enable).
 
-- [teleport](https://goteleport.com), allows engineers and security professionals to unify access for SSH servers, Kubernetes clusters, web applications, and databases across all environments. Available at [services.teleport](#opt-services.teleport.enable).
+- [nix-ld](https://github.com/Mic92/nix-ld), Run unpatched dynamic binaries on NixOS. Available as [programs.nix-ld](#opt-programs.nix-ld.enable).
 
-- [BaGet](https://loic-sharma.github.io/BaGet/), a lightweight NuGet and symbol server. Available at [services.baget](#opt-services.baget.enable).
+- [NNCP](http://www.nncpgo.org), NNCP (Node to Node copy) utilities and configuration, Available as [programs.nncp](#opt-programs.nncp.enable).
+
+- [pgadmin4](https://github.com/postgres/pgadmin4), an admin interface for the PostgreSQL database. Available at [services.pgadmin](#opt-services.pgadmin.enable).
+
+- [PowerDNS-Admin](https://github.com/ngoduykhanh/PowerDNS-Admin), a web interface for the PowerDNS server. Available at [services.powerdns-admin](#opt-services.powerdns-admin.enable).
 
-- [moosefs](https://moosefs.com), fault tolerant petabyte distributed file system.
-  Available as [moosefs](#opt-services.moosefs.client.enable).
+- [prometheus-pve-exporter](https://github.com/prometheus-pve/prometheus-pve-exporter), a tool that exposes information from the Proxmox VE API for use by Prometheus. Available as [services.prometheus.exporters.pve](#opt-services.prometheus.exporters.pve.enable).
 
 - [prosody-filer](https://github.com/ThomasLeister/prosody-filer), a server for handling XMPP HTTP Upload requests. Available at [services.prosody-filer](#opt-services.prosody-filer.enable).
 
-- [systembus-notify](https://github.com/rfjakob/systembus-notify), allow system level notifications to reach the users. Available as [services.systembus-notify](opt-services.systembus-notify.enable). Please keep in mind that this service should only be enabled on machines with fully trusted users, as any local user is able to DoS user sessions by spamming notifications.
+- [Public Inbox](https://public-inbox.org), an "archives first" approach to mailing lists. Available as [services.public-inbox](#opt-services.public-inbox.enable).
+
+- [r53-ddns](https://github.com/fleaz/r53-ddns), a small tool to run your own DDNS service via AWS Route53. Available as [services.r53-ddns](#opt-services.r53-ddns.enable).
+
+- [rmfakecloud](https://ddvk.github.io/rmfakecloud/), a clone of the cloud sync the remarkable tablet. Available as [services.rmfakecloud](#opt-services.rmfakecloud.enable).
 
-- [ethercalc](https://github.com/audreyt/ethercalc), an online collaborative
-  spreadsheet. Available as [services.ethercalc](options.html#opt-services.ethercalc.enable).
+- [rootless Docker](https://docs.docker.com/engine/security/rootless/), a `systemd --user` Docker service which runs without root permissions. Available as [virtualisation.docker.rootless.enable](#opt-virtualisation.docker.rootless.enable).
 
-- [nbd](https://nbd.sourceforge.io/), a Network Block Device server. Available as [services.nbd](options.html#opt-services.nbd.server.enable).
+- [rstudio-server](https://www.rstudio.com/products/rstudio/#rstudio-server), a browser-based version of the RStudio IDE for the R programming language. Available as [services.rstudio-server](#opt-services.rstudio-server.enable).
 
-- [nix-ld](https://github.com/Mic92/nix-ld), Run unpatched dynamic binaries on NixOS. Available as [programs.nix-ld](options.html#opt-programs.nix-ld.enable).
+- [rtsp-simple-server](https://github.com/aler9/rtsp-simple-server), ready-to-use RTSP / RTMP / HLS server and proxy that allows to read, publish and proxy video and audio streams. Available as [services.rtsp-simple-server](#opt-services.rtsp-simple-server.enable).
 
-- [timetagger](https://timetagger.app), an open source time-tracker with an intuitive user experience and powerful reporting. [services.timetagger](options.html#opt-services.timetagger.enable).
+- [Snipe-IT](https://snipeitapp.com), a free open source IT asset/license management system. Available as [services.snipe-it](#opt-services.snipe-it.enable).
 
-- [rstudio-server](https://www.rstudio.com/products/rstudio/#rstudio-server), a browser-based version of the RStudio IDE for the R programming language. Available as [services.rstudio-server](options.html#opt-services.rstudio-server.enable).
+- [snowflake-proxy](https://snowflake.torproject.org/), a system to defeat internet censorship. Available as [services.snowflake-proxy](#opt-services.snowflake-proxy.enable).
 
-- [headscale](https://github.com/juanfont/headscale), an Open Source implementation of the [Tailscale](https://tailscale.io) Control Server. Available as [services.headscale](options.html#opt-services.headscale.enable)
+- [sslmate-agent](https://sslmate.com/), a daemon for managing SSL/TLS certificates on a server. Available as [services.sslmate-agent](services.sslmate-agent.enable).
+
+- [starship](https://starship.rs), a minimal, blazing-fast, and infinitely customizable prompt for any shell. Available at [programs.startship](#opt-programs.starship.enable).
+
+- [systembus-notify](https://github.com/rfjakob/systembus-notify), allow system level notifications to reach the users. Available as [services.systembus-notify](opt-services.systembus-notify.enable). Please keep in mind that this service should only be enabled on machines with fully trusted users, as any local user is able to DoS user sessions by spamming notifications.
 
-- [create_ap](https://github.com/lakinduakash/linux-wifi-hotspot), a module for creating wifi hotspots using the program linux-wifi-hotspot. Available as [services.create_ap](options.html#opt-services.create_ap.enable).
+- [teleport](https://goteleport.com), allows engineers and security professionals to unify access for SSH servers, Kubernetes clusters, web applications, and databases across all environments. Available at [services.teleport](#opt-services.teleport.enable).
+
+- [tetrd](https://tetrd.app), share your internet connection from your device to your PC and vice versa through a USB cable. Available at [services.tetrd](#opt-services.tetrd.enable).
+
+- [uptermd](https://upterm.dev), an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels. Available at [services.uptermd](#opt-services.uptermd.enable).
 
-- [blocky](https://0xerr0r.github.io/blocky/), fast and lightweight DNS proxy as ad-blocker for local network with many features.
+- [usbrelayd](https://github.com/darrylb123/usbrelay), an USB Relay MQTT daemon. Available as [services.usbrelayd](#opt-services.usbrelayd.enable).
 
-- [pacemaker](https://clusterlabs.org/pacemaker/) cluster resource manager
+- [webdav-server-rs](https://github.com/miquels/webdav-server-rs), Webdav server in rust. Available as [services.webdav-server-rs](#opt-services.webdav-server-rs.enable).
 
-- [nifi](https://nifi.apache.org), an easy to use, powerful, and reliable system to process and distribute data. Available as [services.nifi](options.html#opt-services.nifi.enable).
+- [wg-netmanager](https://github.com/gin66/wg_netmanager), the Wireguard network manager. Available as [services.wg-netmanager](#opt-services.wg-netmanager.enable).
 
-- [kanidm](https://kanidm.github.io/kanidm/stable/), an identity management server written in Rust.
+- [Zammad](https://zammad.org/), a web-based, open source user support/ticketing solution. Available as [services.zammad](#opt-services.zammad.enable).
 
 <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
 
@@ -165,7 +195,7 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - The update of the haskell package set brings with it a new version of the `xmonad`
   module, which will break your configuration if you use `launch` as entrypoint. The
-  example code the corresponding nixos module was adjusted, you way want to have a look at it.
+  example code the corresponding nixos module was adjusted, you may want to have a look at it.
 
 - The `home-assistant` module now requires users that don't want their
   configuration to be managed declaratively to set
@@ -191,6 +221,8 @@ In addition to numerous new and upgraded packages, this release has the followin
   This is to improve compatibility with `libcontainer` based software such as Podman and Skopeo
   which assumes they have ownership over `/etc/containers`.
 
+- `lib.systems.supported` has been removed, as it was overengineered for determining the systems to support in the nixpkgs flake. The list of systems exposed by the nixpkgs flake can now be accessed as `lib.systems.flakeExposed`.
+
 - For new installations `virtualisation.oci-containers.backend` is now set to `podman` by default.
   If you still want to use Docker on systems where `system.stateVersion` is set to to `"22.05"` set `virtualisation.oci-containers.backend = "docker";`.Old systems with older `stateVersion`s stay with "docker".
 
@@ -242,6 +274,10 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - In the ncdns module, the default value of `services.ncdns.address` has been changed to the IPv6 loopback address (`::1`).
 
+- `openldap` (and therefore the slapd LDAP server) were updated to version 2.6.2. The project introduced backwards-incompatible changes, namely the removal of the bdb, hdb, ndb, and shell backends in slapd. Therefore before updating, dump your database `slapcat -n 1` in LDIF format, and reimport it after updating your `services.openldap.settings`, which represents your `cn=config`.
+
+  Additionally with 2.5 the argon2 module was included in the standard distrubtion and renamed from `pw-argon2` to `argon2`. Remember to update your `olcModuleLoad` entry in `cn=config`.
+
 - `openssh` has been update to 8.9p1, changing the FIDO security key middleware interface.
 
 - `git` no longer hardcodes the path to openssh' ssh binary to reduce the amount of rebuilds. If you are using git with ssh remotes and do not have a ssh binary in your enviroment consider adding `openssh` to it or switching to `gitFull`.
@@ -360,13 +396,13 @@ In addition to numerous new and upgraded packages, this release has the followin
       };
 
       extraConfigFiles = [
-        /run/keys/matrix-synapse/secrets.yaml
+        "/run/keys/matrix-synapse/secrets.yaml"
       ];
     };
   }
   ```
 
-  The secrets in your original config should be migrated into a YAML file that is included via `extraConfigFiles`.
+  The secrets in your original config should be migrated into a YAML file that is included via `extraConfigFiles`. The filename must be quoted to prevent nix from copying it to the (world readable) store.
 
   Additionally a few option defaults have been synced up with upstream default values, for example the `max_upload_size` grew from `10M` to `50M`. For the same reason, the default
   `media_store_path` was changed from `${dataDir}/media` to `${dataDir}/media_store` if `system.stateVersion` is at least `22.05`. Files will need to be manually moved to the new
@@ -632,6 +668,10 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - The `vpnc` package has been changed to use GnuTLS instead of OpenSSL by default for licensing reasons.
 
+- The default version of `nextcloud` is **nextcloud24**. Please note that it's **not** possible to upgrade
+  `nextcloud` across multiple major versions! This means it's e.g. not possible to upgrade from `nextcloud22`
+  to `nextcloud24` in a single deploy and most `21.11` users will have to upgrade to `nextcloud23` first.
+
 - `pkgs.vimPlugins.onedark-nvim` now refers to [navarasu/onedark.nvim](https://github.com/navarasu/onedark.nvim)
   (formerly refers to [olimorris/onedarkpro.nvim](https://github.com/olimorris/onedarkpro.nvim)).
 
@@ -693,6 +733,13 @@ In addition to numerous new and upgraded packages, this release has the followin
 - The configuration portion of the `nix-daemon` module has been reworked and exposed as [nix.settings](options.html#opt-nix-settings):
   * Legacy options have been mapped to the corresponding options under under [nix.settings](options.html#opt-nix.settings) and will be deprecated when NixOS 21.11 reaches end of life.
   * [nix.buildMachines.publicHostKey](options.html#opt-nix.buildMachines.publicHostKey) has been added.
+  
+- [`kops`](https://kops.sigs.k8s.io) defaults to 1.23.2, which will enable [Instance Metadata Service Version 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) and require tokens on new clusters with Kubernetes >= 1.22. This will increase security by default, but may break some types of workloads. The default behaviour for `spec.kubeDNS.nodeLocalDNS.forwardToKubeDNS` has changed from `true` to `false`. Cilium now has `disable-cnp-status-updates: true` by default. Set this to false if you rely on the CiliumNetworkPolicy status fields. Support for Kubernetes 1.17, the Lyft CNI, Weave CNI on Kubernetes >= 1.23, CentOS 7 and 8, Debian 9, RHEL 7, and Ubuntu 16.05 (Xenial) has been removed. See the [1.22 release notes](https://kops.sigs.k8s.io/releases/1.22-notes/) and [1.23 release notes](https://kops.sigs.k8s.io/releases/1.23-notes/) for more details, including other significant changes.
+
+- Mattermost has been upgraded to extended support version 6.3 as the previously
+  packaged extended support version 5.37 is [reaching end of life](https://docs.mattermost.com/upgrade/extended-support-release.html). 
+  Migration may take some time, see the [changelog](https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release)
+  and [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html).
 
 - The `writers.writePyPy2`/`writers.writePyPy3` and corresponding `writers.writePyPy2Bin`/`writers.writePyPy3Bin` convenience functions to create executable Python 2/3 scripts using the PyPy interpreter were added.
 
@@ -718,6 +765,17 @@ In addition to numerous new and upgraded packages, this release has the followin
   redis-cli save
   cp /var/lib/redis/dump.rdb "/var/lib/redis-mastodon/dump.rdb"
   ```
+- Peertube now uses services.redis.servers to start a new redis server, instead of using a global redis server.
+  This improves compatibility with other services that use redis.
+
+  Redis database is used for storage only cache and job queue. More information can be found here - [Peertube architecture](https://docs.joinpeertube.org/contribute-architecture).
+
+  If you do want to save the redis database, you can use the following commands before upgrade OS:
+  ```bash
+  redis-cli save
+  sudo mkdir /var/lib/redis-peertube
+  sudo cp /var/lib/redis/dump.rdb /var/lib/redis-peertube/dump.rdb
+  ```
 
 - If you are using Wayland you can choose to use the Ozone Wayland support
   in Chrome and several Electron apps by setting the environment variable
@@ -785,7 +843,6 @@ In addition to numerous new and upgraded packages, this release has the followin
   If you are using only a window manager without a desktop manager, you need to enable
   `services.xserver.desktopManager.runXdgAutostartIfNone` or using the `dex` package to make `fcitx5` work.
 
-- A new module was added for the Envoy reverse proxy, providing the options `services.envoy.enable` and `services.envoy.settings`.
 
 - The option `services.duplicati.dataDir` has been added to allow changing the location of duplicati's files.
 
@@ -831,9 +888,6 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - The default value for `programs.spacefm.settings.graphical_su` got unset. It previously pointed to `gksu` which has been removed.
 
-- A new module was added for the [Starship](https://starship.rs/) shell prompt,
-  providing the options `programs.starship.enable` and `programs.starship.settings`.
-
 - The [Dino](https://dino.im) XMPP client was updated to 0.3, adding support for audio and video calls.
 
 - `services.mattermost.plugins` has been added to allow the declarative installation of Mattermost plugins.
@@ -893,6 +947,8 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - The `nss` package was split into `nss_esr` and `nss_latest`, with `nss` being an alias for `nss_esr`. This was done to ease maintenance of `nss` and dependent high-profile packages like `firefox`.
 
+- The default `scribus` version is now 1.5, while version 1.4 is still available as `scribus_1_4` ([#172700](https://github.com/NixOS/nixpkgs/pull/172700)).
+
 - The Nextcloud module now supports to create a Mysql database automatically
   with `services.nextcloud.database.createLocally` enabled.
 
@@ -903,8 +959,6 @@ In addition to numerous new and upgraded packages, this release has the followin
   - Testing has been enabled for `aarch64-linux` in addition to `x86_64-linux`.
   - The `spark3` package is now usable on `aarch64-darwin` as a result of [#158613](https://github.com/NixOS/nixpkgs/pull/158613) and [#158992](https://github.com/NixOS/nixpkgs/pull/158992).
 
-- The `programs.nncp` options were added for generating host-global NNCP configuration.
-
 - The option `services.snapserver.openFirewall` will no longer default to
   `true` starting with NixOS 22.11. Enable it explicitly if you need to control
   Snapserver remotely or connect streamig clients from other hosts.
@@ -915,5 +969,22 @@ In addition to numerous new and upgraded packages, this release has the followin
   or `wl*` with priority 99 (which means that it doesn't have any effect if such an interface is matched
   by a `.network-`unit with a lower priority). In case of scripted networking, no behavior
   was changed.
+  
+- The new [`postgresqlTestHook`](https://nixos.org/manual/nixpkgs/stable/#sec-postgresqlTestHook) runs a PostgreSQL server for the duration of package checks.
+  
+- `stdenv.mkDerivation` now supports a self-referencing `finalAttrs:` parameter
+  containing the final `mkDerivation` arguments including overrides.
+  `drv.overrideAttrs` now supports two parameters `finalAttrs: previousAttrs:`.
+  This allows packaging configuration to be overridden in a consistent manner by
+  providing an alternative to `rec {}` syntax.
+
+  Additionally, `passthru` can now reference `finalAttrs.finalPackage` containing
+  the final package, including attributes such as the output paths and
+  `overrideAttrs`.
+
+  New language integrations can be simplified by overriding a "prototype"
+  package containing the language-specific logic. This removes the need for a
+  extra layer of overriding for the "generic builder" arguments, thus removing a
+  usability problem and source of error.
 
 <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md
new file mode 100644
index 00000000000..145393d0deb
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-2211.section.md
@@ -0,0 +1,51 @@
+# Release 22.11 (“Raccoon”, 2022.11/??) {#sec-release-22.11}
+
+Support is planned until the end of June 2023, handing over to 23.05.
+
+## Highlights {#sec-release-22.11-highlights}
+
+In addition to numerous new and upgraded packages, this release has the following highlights:
+
+- During cross-compilation, tests are now executed if the test suite can be executed
+  by the build platform. This is the case when doing “native” cross-compilation
+  where the build and host platforms are largely the same, but the nixpkgs' cross
+  compilation infrastructure is used, e.g. `pkgsStatic` and `pkgsLLVM`. Another
+  possibility is that the build platform is a superset of the host platform, e.g. when
+  cross-compiling from `x86_64-unknown-linux` to `i686-unknown-linux`.
+  The predicate gating test suite execution is the newly added `canExecute`
+  predicate: You can e.g. check if `stdenv.buildPlatform` can execute binaries
+  built for `stdenv.hostPlatform` (i.e. produced by `stdenv.cc`) by evaluating
+  `stdenv.buildPlatform.canExecute stdenv.hostPlatform`.
+
+- PHP now defaults to PHP 8.1, updated from 8.0.
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+## New Services {#sec-release-22.11-new-services}
+
+- [appvm](https://github.com/jollheef/appvm), Nix based app VMs. Available as [virtualisation.appvm](options.html#opt-virtualisation.appvm.enable).
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+## Backward Incompatibilities {#sec-release-22.11-incompatibilities}
+
+- The `isCompatible` predicate checking CPU compatibility is no longer exposed
+  by the platform sets generated using `lib.systems.elaborate`. In most cases
+  you will want to use the new `canExecute` predicate instead which also
+  considers the kernel / syscall interface. It is briefly described in the
+  release's [highlights section](#sec-release-22.11-highlights).
+  `lib.systems.parse.isCompatible` still exists, but has changed semantically:
+  Architectures with differing endianness modes are *no longer considered compatible*.
+
+- The `isPowerPC` predicate, found on `platform` attrsets (`hostPlatform`, `buildPlatform`, `targetPlatform`, etc) has been removed in order to reduce confusion.  The predicate was was defined such that it matches only the 32-bit big-endian members of the POWER/PowerPC family, despite having a name which would imply a broader set of systems.  If you were using this predicate, you can replace `foo.isPowerPC` with `(with foo; isPower && is32bit && isBigEndian)`.
+
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+
+## Other Notable Changes {#sec-release-22.11-notable-changes}
+
+- A new module was added for the Saleae Logic device family, providing the options `hardware.saleae-logic.enable` and `hardware.saleae-logic.package`.
+
+- Matrix Synapse now requires entries in the `state_group_edges` table to be unique, in order to prevent accidentally introducing duplicate information (for example, because a database backup was restored multiple times). If your Synapse database already has duplicate rows in this table, this could fail with an error and require manual remediation.
+
+<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix
index 2daaa8a1186..3b58ef29797 100644
--- a/nixos/lib/eval-config.nix
+++ b/nixos/lib/eval-config.nix
@@ -50,11 +50,6 @@ let
       # they way through, but has the last priority behind everything else.
       nixpkgs.system = lib.mkDefault system;
 
-      # Stash the value of the `system` argument. When using `nesting.children`
-      # we want to have the same default value behavior (immediately above)
-      # without any interference from the user's configuration.
-      nixpkgs.initialSystem = system;
-
       _module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
     };
   };
diff --git a/nixos/lib/test-driver/default.nix b/nixos/lib/test-driver/default.nix
index 3aee9134318..6cd0ffe222d 100644
--- a/nixos/lib/test-driver/default.nix
+++ b/nixos/lib/test-driver/default.nix
@@ -25,6 +25,8 @@ python3Packages.buildPythonApplication rec {
   checkPhase = ''
     mypy --disallow-untyped-defs \
           --no-implicit-optional \
+          --pretty \
+          --no-color-output \
           --ignore-missing-imports ${src}/test_driver
     pylint --errors-only --enable=unused-import ${src}/test_driver
     black --check --diff ${src}/test_driver
diff --git a/nixos/lib/test-driver/test_driver/machine.py b/nixos/lib/test-driver/test_driver/machine.py
index 035e3ffe897..3ff3cf5645f 100644
--- a/nixos/lib/test-driver/test_driver/machine.py
+++ b/nixos/lib/test-driver/test_driver/machine.py
@@ -682,7 +682,7 @@ class Machine:
         with self.nested("waiting for {} to appear on tty {}".format(regexp, tty)):
             retry(tty_matches)
 
-    def send_chars(self, chars: List[str]) -> None:
+    def send_chars(self, chars: str) -> None:
         with self.nested("sending keys ‘{}‘".format(chars)):
             for char in chars:
                 self.send_key(char)
diff --git a/nixos/lib/test-driver/test_driver/py.typed b/nixos/lib/test-driver/test_driver/py.typed
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/nixos/lib/test-driver/test_driver/py.typed
diff --git a/nixos/lib/test-script-prepend.py b/nixos/lib/test-script-prepend.py
new file mode 100644
index 00000000000..15e59ce0104
--- /dev/null
+++ b/nixos/lib/test-script-prepend.py
@@ -0,0 +1,42 @@
+# This file contains type hints that can be prepended to Nix test scripts so they can be type
+# checked.
+
+from test_driver.driver import Driver
+from test_driver.vlan import VLan
+from test_driver.machine import Machine
+from test_driver.logger import Logger
+from typing import Callable, Iterator, ContextManager, Optional, List, Dict, Any, Union
+from typing_extensions import Protocol
+from pathlib import Path
+
+
+class RetryProtocol(Protocol):
+    def __call__(self, fn: Callable, timeout: int = 900) -> None:
+        raise Exception("This is just type information for the Nix test driver")
+
+
+class PollingConditionProtocol(Protocol):
+    def __call__(
+        self,
+        fun_: Optional[Callable] = None,
+        *,
+        seconds_interval: float = 2.0,
+        description: Optional[str] = None,
+    ) -> Union[Callable[[Callable], ContextManager], ContextManager]:
+        raise Exception("This is just type information for the Nix test driver")
+
+
+start_all: Callable[[], None]
+subtest: Callable[[str], ContextManager[None]]
+retry: RetryProtocol
+test_script: Callable[[], None]
+machines: List[Machine]
+vlans: List[VLan]
+driver: Driver
+log: Logger
+create_machine: Callable[[Dict[str, Any]], Machine]
+run_tests: Callable[[], None]
+join_all: Callable[[], None]
+serial_stdout_off: Callable[[], None]
+serial_stdout_on: Callable[[], None]
+polling_condition: PollingConditionProtocol
diff --git a/nixos/lib/testing-python.nix b/nixos/lib/testing-python.nix
index 4ab3cf53045..8ba2d32ddda 100644
--- a/nixos/lib/testing-python.nix
+++ b/nixos/lib/testing-python.nix
@@ -50,6 +50,7 @@ rec {
     , qemu_pkg ? pkgs.qemu_test
     , enableOCR ? false
     , skipLint ? false
+    , skipTypeCheck ? false
     , passthru ? {}
     , interactive ? false
   }:
@@ -85,7 +86,7 @@ rec {
 
       nodeHostNames = let
         nodesList = map (c: c.config.system.name) (lib.attrValues nodes);
-      in nodesList ++ lib.optional (lib.length nodesList == 1) "machine";
+      in nodesList ++ lib.optional (lib.length nodesList == 1 && !lib.elem "machine" nodesList) "machine";
 
       # TODO: This is an implementation error and needs fixing
       # the testing famework cannot legitimately restrict hostnames further
@@ -100,6 +101,9 @@ rec {
         then testScript { inherit nodes; }
         else testScript;
 
+      uniqueVlans = lib.unique (builtins.concatLists vlans);
+      vlanNames = map (i: "vlan${toString i}: VLan;") uniqueVlans;
+      machineNames = map (name: "${name}: Machine;") nodeHostNames;
     in
     if lib.length invalidNodeNames > 0 then
       throw ''
@@ -113,7 +117,7 @@ rec {
     else lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName
       {
         inherit testName;
-        nativeBuildInputs = [ makeWrapper ];
+        nativeBuildInputs = [ makeWrapper mypy ];
         testScript = testScript';
         preferLocalBuild = true;
         passthru = passthru // {
@@ -125,7 +129,25 @@ rec {
         mkdir -p $out/bin
 
         vmStartScripts=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
-        echo -n "$testScript" > $out/test-script
+
+        ${lib.optionalString (!skipTypeCheck) ''
+          # prepend type hints so the test script can be type checked with mypy
+          cat "${./test-script-prepend.py}" >> testScriptWithTypes
+          echo "${builtins.toString machineNames}" >> testScriptWithTypes
+          echo "${builtins.toString vlanNames}" >> testScriptWithTypes
+          echo -n "$testScript" >> testScriptWithTypes
+
+          # set pythonpath so mypy knows where to find the imports. this requires the py.typed file.
+          export PYTHONPATH='${./test-driver}'
+          mypy  --no-implicit-optional \
+                --pretty \
+                --no-color-output \
+                testScriptWithTypes
+          unset PYTHONPATH
+        ''}
+
+        echo -n "$testScript" >> $out/test-script
+
         ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver
 
         ${testDriver}/bin/generate-driver-symbols
@@ -152,6 +174,7 @@ rec {
     , testScript
     , enableOCR ? false
     , name ? "unnamed"
+    , skipTypeCheck ? false
       # Skip linting (mainly intended for faster dev cycles)
     , skipLint ? false
     , passthru ? {}
@@ -207,19 +230,19 @@ rec {
             )];
           };
         in
-          lib.warnIf (t?machine) "In test `${name}': The `machine' attribute in NixOS tests (pkgs.nixosTest / make-test-pyton.nix / testing-python.nix / makeTest) is deprecated. Please use the equivalent `nodes.machine'."
+          lib.warnIf (t?machine) "In test `${name}': The `machine' attribute in NixOS tests (pkgs.nixosTest / make-test-python.nix / testing-python.nix / makeTest) is deprecated. Please use the equivalent `nodes.machine'."
           build-vms.buildVirtualNetwork (
               nodes // lib.optionalAttrs (machine != null) { inherit machine; }
           );
 
       driver = setupDriverForTest {
-        inherit testScript enableOCR skipLint passthru;
+        inherit testScript enableOCR skipTypeCheck skipLint passthru;
         testName = name;
         qemu_pkg = pkgs.qemu_test;
         nodes = mkNodes pkgs.qemu_test;
       };
       driverInteractive = setupDriverForTest {
-        inherit testScript enableOCR skipLint passthru;
+        inherit testScript enableOCR skipTypeCheck skipLint passthru;
         testName = name;
         qemu_pkg = pkgs.qemu;
         nodes = mkNodes pkgs.qemu;
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index 26ce561013b..5a21cb45d52 100644
--- a/nixos/modules/config/update-users-groups.pl
+++ b/nixos/modules/config/update-users-groups.pl
@@ -223,10 +223,10 @@ foreach my $u (@{$spec->{users}}) {
     }
 
     # Ensure home directory incl. ownership and permissions.
-    if ($u->{createHome}) {
-        make_path($u->{home}, { mode => 0700 }) if ! -e $u->{home} and ! $is_dry;
+    if ($u->{createHome} and !$is_dry) {
+        make_path($u->{home}, { mode => oct($u->{homeMode}) }) if ! -e $u->{home};
         chown $u->{uid}, $u->{gid}, $u->{home};
-        chmod 0700, $u->{home};
+        chmod oct($u->{homeMode}), $u->{home};
     }
 
     if (defined $u->{passwordFile}) {
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index b0f96c754fa..d3bdf218c33 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -48,7 +48,7 @@ let
     services such as SSH, or indirectly via <command>su</command> or
     <command>sudo</command>). This should only be used for e.g. bootable
     live systems. Note: this is different from setting an empty password,
-    which ca be achieved using <option>users.users.&lt;name?&gt;.password</option>.
+    which can be achieved using <option>users.users.&lt;name?&gt;.password</option>.
 
     If set to <literal>null</literal> (default) this user will not
     be able to log in using a password (i.e. via <command>login</command>
@@ -139,6 +139,12 @@ let
         description = "The user's home directory.";
       };
 
+      homeMode = mkOption {
+        type = types.strMatching "[0-7]{1,5}";
+        default = "700";
+        description = "The user's home directory mode in numeric format. See chmod(1). The mode is only applied if <option>users.users.&lt;name&gt;.createHome</option> is true.";
+      };
+
       cryptHomeLuks = mkOption {
         type = with types; nullOr str;
         default = null;
@@ -319,6 +325,7 @@ let
           group = mkDefault "users";
           createHome = mkDefault true;
           home = mkDefault "/home/${config.name}";
+          homeMode = mkDefault "700";
           useDefaultShell = mkDefault true;
           isSystemUser = mkDefault false;
         })
@@ -430,7 +437,7 @@ let
     inherit (cfg) mutableUsers;
     users = mapAttrsToList (_: u:
       { inherit (u)
-          name uid group description home createHome isSystemUser
+          name uid group description home homeMode createHome isSystemUser
           password passwordFile hashedPassword
           autoSubUidGidRange subUidRanges subGidRanges
           initialPassword initialHashedPassword;
diff --git a/nixos/modules/hardware/new-lg4ff.nix b/nixos/modules/hardware/new-lg4ff.nix
new file mode 100644
index 00000000000..3c7f66f8d89
--- /dev/null
+++ b/nixos/modules/hardware/new-lg4ff.nix
@@ -0,0 +1,29 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+  cfg = config.hardware.new-lg4ff;
+  kernelPackages = config.boot.kernelPackages;
+in {
+  options.hardware.new-lg4ff = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enables improved Linux module drivers for Logitech driving wheels.
+        This will replace the existing in-kernel hid-logitech modules.
+        Works most notably on the Logitech G25, G27, G29 and Driving Force (GT).
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    boot = {
+      extraModulePackages = [ kernelPackages.new-lg4ff ];
+      kernelModules = [ "hid-logitech-new" ];
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ matthiasbenaets ];
+}
diff --git a/nixos/modules/hardware/saleae-logic.nix b/nixos/modules/hardware/saleae-logic.nix
new file mode 100644
index 00000000000..a3810d640c4
--- /dev/null
+++ b/nixos/modules/hardware/saleae-logic.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.hardware.saleae-logic;
+in
+{
+  options.hardware.saleae-logic = {
+    enable = lib.mkEnableOption "udev rules for Saleae Logic devices";
+
+    package = lib.mkOption {
+      type = lib.types.package;
+      default = pkgs.saleae-logic-2;
+      defaultText = lib.literalExpression "pkgs.saleae-logic-2";
+      description = ''
+        Saleae Logic package to use.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    services.udev.packages = [ cfg.package ];
+  };
+
+  meta.maintainers = with lib.maintainers; [ chivay ];
+}
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 210d45ac841..a9b04bcc859 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -163,8 +163,19 @@ in
       '';
     };
 
+    hardware.nvidia.forceFullCompositionPipeline = lib.mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Whether to force-enable the full composition pipeline.
+        This sometimes fixes screen tearing issues.
+        This has been reported to reduce the performance of some OpenGL applications and may produce issues in WebGL.
+        It also drastically increases the time the driver needs to clock down after load.
+      '';
+    };
+
     hardware.nvidia.package = lib.mkOption {
-      type = lib.types.package;
+      type = types.package;
       default = config.boot.kernelPackages.nvidiaPackages.stable;
       defaultText = literalExpression "config.boot.kernelPackages.nvidiaPackages.stable";
       description = ''
@@ -255,13 +266,18 @@ in
         ''
           BusID "${pCfg.nvidiaBusId}"
           ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
-          ${optionalString cfg.powerManagement.finegrained "Option \"NVreg_DynamicPowerManagement=0x02\""}
         '';
       screenSection =
         ''
           Option "RandRRotation" "on"
-          ${optionalString syncCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
-        '';
+        '' + optionalString syncCfg.enable ''
+          Option "AllowEmptyInitialConfiguration"
+        '' + optionalString cfg.forceFullCompositionPipeline ''
+          Option         "metamodes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}"
+          Option         "AllowIndirectGLXProtocol" "off"
+          Option         "TripleBuffer" "on"
+        ''
+        ;
     };
 
     services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
@@ -367,7 +383,8 @@ in
           RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia%c{3} c 195 %c{3}"
         KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 0'"
         KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 1'"
-      '' + optionalString cfg.powerManagement.finegrained ''
+      '' + optionalString cfg.powerManagement.finegrained (
+      optionalString (versionOlder config.boot.kernelPackages.kernel.version "5.5") ''
         # Remove NVIDIA USB xHCI Host Controller devices, if present
         ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
 
@@ -376,7 +393,7 @@ in
 
         # Remove NVIDIA Audio devices, if present
         ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
-
+      '' + ''
         # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
         ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
         ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
@@ -384,7 +401,7 @@ in
         # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
         ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
         ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
-      '';
+      '');
 
     boot.extraModprobeConfig = mkIf cfg.powerManagement.finegrained ''
       options nvidia "NVreg_DynamicPowerManagement=0x02"
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 1eaa940afb1..d1ccc6c2072 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -479,7 +479,7 @@ in
                 + lib.optionalString (isx86_32 || isx86_64) "-Xbcj x86"
                 # Untested but should also reduce size for these platforms
                 + lib.optionalString (isAarch32 || isAarch64) "-Xbcj arm"
-                + lib.optionalString (isPowerPC) "-Xbcj powerpc"
+                + lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc"
                 + lib.optionalString (isSparc) "-Xbcj sparc";
       description = ''
         Compression settings to use for the squashfs nix store.
diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix
index 69967c8a760..866bb351600 100644
--- a/nixos/modules/misc/nixpkgs.nix
+++ b/nixos/modules/misc/nixpkgs.nix
@@ -67,6 +67,7 @@ in
   imports = [
     ./assertions.nix
     ./meta.nix
+    (mkRemovedOptionModule [ "nixpkgs" "initialSystem" ] "The NixOS options `nesting.clone` and `nesting.children` have been deleted, and replaced with named specialisation. Therefore `nixpgks.initialSystem` has no effect anymore.")
   ];
 
   options.nixpkgs = {
@@ -219,14 +220,6 @@ in
         Ignored when <code>nixpkgs.pkgs</code> is set.
       '';
     };
-
-    initialSystem = mkOption {
-      type = types.str;
-      internal = true;
-      description = ''
-        Preserved value of <literal>system</literal> passed to <literal>eval-config.nix</literal>.
-      '';
-    };
   };
 
   config = {
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index 010acdb72f6..da458a57484 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -13,7 +13,7 @@ let
   attrsToText = attrs:
     concatStringsSep "\n" (
       mapAttrsToList (n: v: ''${n}=${escapeIfNeccessary (toString v)}'') attrs
-    );
+    ) + "\n";
 
   osReleaseContents = {
     NAME = "NixOS";
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 35de34aac10..902fffd60f9 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -66,6 +66,7 @@
   ./hardware/network/ath-user-regd.nix
   ./hardware/network/b43.nix
   ./hardware/network/intel-2200bg.nix
+  ./hardware/new-lg4ff.nix
   ./hardware/nitrokey.nix
   ./hardware/opengl.nix
   ./hardware/openrazer.nix
@@ -73,6 +74,7 @@
   ./hardware/printers.nix
   ./hardware/raid/hpsa.nix
   ./hardware/rtl-sdr.nix
+  ./hardware/saleae-logic.nix
   ./hardware/steam-hardware.nix
   ./hardware/system-76.nix
   ./hardware/tuxedo-keyboard.nix
@@ -137,6 +139,7 @@
   ./programs/captive-browser.nix
   ./programs/ccache.nix
   ./programs/cdemu.nix
+  ./programs/cfs-zen-tweaks.nix
   ./programs/chromium.nix
   ./programs/clickshare.nix
   ./programs/cnping.nix
@@ -733,6 +736,7 @@
   ./services/networking/bitcoind.nix
   ./services/networking/autossh.nix
   ./services/networking/bird.nix
+  ./services/networking/bird-lg.nix
   ./services/networking/bitlbee.nix
   ./services/networking/blockbook-frontend.nix
   ./services/networking/blocky.nix
@@ -877,6 +881,7 @@
   ./services/networking/quassel.nix
   ./services/networking/quorum.nix
   ./services/networking/quicktun.nix
+  ./services/networking/r53-ddns.nix
   ./services/networking/radicale.nix
   ./services/networking/radvd.nix
   ./services/networking/rdnssd.nix
@@ -1233,6 +1238,7 @@
   ./tasks/powertop.nix
   ./testing/service-runner.nix
   ./virtualisation/anbox.nix
+  ./virtualisation/appvm.nix
   ./virtualisation/build-vm.nix
   ./virtualisation/container-config.nix
   ./virtualisation/containerd.nix
diff --git a/nixos/modules/programs/atop.nix b/nixos/modules/programs/atop.nix
index ad75ab27666..a31078a891a 100644
--- a/nixos/modules/programs/atop.nix
+++ b/nixos/modules/programs/atop.nix
@@ -136,6 +136,24 @@ in
           packages = [ atop (lib.mkIf cfg.netatop.enable cfg.netatop.package) ];
           services =
             mkService cfg.atopService.enable "atop" [ atop ]
+            // lib.mkIf cfg.atopService.enable {
+              # always convert logs to newer version first
+              # XXX might trigger TimeoutStart but restarting atop.service will
+              # convert remainings logs and start eventually
+              atop.serviceConfig.ExecStartPre = pkgs.writeShellScript "atop-update-log-format" ''
+                set -e -u
+                for logfile in "$LOGPATH"/atop_*
+                do
+                  ${atop}/bin/atopconvert "$logfile" "$logfile".new
+                  # only replace old file if version was upgraded to avoid
+                  # false positives for atop-rotate.service
+                  if ! ${pkgs.diffutils}/bin/cmp -s "$logfile" "$logfile".new
+                  then
+                    ${pkgs.coreutils}/bin/mv -v -f "$logfile".new "$logfile"
+                  fi
+                done
+              '';
+            }
             // mkService cfg.atopacctService.enable "atopacct" [ atop ]
             // mkService cfg.netatop.enable "netatop" [ cfg.netatop.package ]
             // mkService cfg.atopgpu.enable "atopgpu" [ atop ];
diff --git a/nixos/modules/programs/cfs-zen-tweaks.nix b/nixos/modules/programs/cfs-zen-tweaks.nix
new file mode 100644
index 00000000000..f168662bbef
--- /dev/null
+++ b/nixos/modules/programs/cfs-zen-tweaks.nix
@@ -0,0 +1,28 @@
+# CFS Zen Tweaks
+
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.cfs-zen-tweaks;
+
+in
+
+{
+
+  meta = {
+    maintainers = with maintainers; [ mkg20001 ];
+  };
+
+  options = {
+    programs.cfs-zen-tweaks.enable = mkEnableOption "CFS Zen Tweaks";
+  };
+
+  config = mkIf cfg.enable {
+    systemd.packages = [ pkgs.cfs-zen-tweaks ];
+
+    systemd.services.set-cfs-tweak.wantedBy = [ "multi-user.target" "suspend.target" "hibernate.target" "hybrid-sleep.target" "suspend-then-hibernate.target" ];
+  };
+}
diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix
index b41f30287ea..7d8ab7dda96 100644
--- a/nixos/modules/programs/gnupg.nix
+++ b/nixos/modules/programs/gnupg.nix
@@ -17,7 +17,7 @@ let
     else if xserverCfg.enable || config.programs.sway.enable then
       "gnome3"
     else
-      null;
+      "curses";
 
 in
 
diff --git a/nixos/modules/services/backup/btrbk.nix b/nixos/modules/services/backup/btrbk.nix
index 0c00b934405..e17761ffc3c 100644
--- a/nixos/modules/services/backup/btrbk.nix
+++ b/nixos/modules/services/backup/btrbk.nix
@@ -1,18 +1,36 @@
 { config, pkgs, lib, ... }:
 let
+  inherit (lib)
+    concatMapStringsSep
+    concatStringsSep
+    filterAttrs
+    flatten
+    isAttrs
+    isString
+    literalExpression
+    mapAttrs'
+    mapAttrsToList
+    mkIf
+    mkOption
+    optionalString
+    partition
+    typeOf
+    types
+    ;
+
   cfg = config.services.btrbk;
   sshEnabled = cfg.sshAccess != [ ];
   serviceEnabled = cfg.instances != { };
   attr2Lines = attr:
     let
-      pairs = lib.attrsets.mapAttrsToList (name: value: { inherit name value; }) attr;
+      pairs = mapAttrsToList (name: value: { inherit name value; }) attr;
       isSubsection = value:
-        if builtins.isAttrs value then true
-        else if builtins.isString value then false
-        else throw "invalid type in btrbk config ${builtins.typeOf value}";
-      sortedPairs = lib.lists.partition (x: isSubsection x.value) pairs;
+        if isAttrs value then true
+        else if isString value then false
+        else throw "invalid type in btrbk config ${typeOf value}";
+      sortedPairs = partition (x: isSubsection x.value) pairs;
     in
-    lib.flatten (
+    flatten (
       # non subsections go first
       (
         map (pair: [ "${pair.name} ${pair.value}" ]) sortedPairs.wrong
@@ -22,7 +40,7 @@ let
         map
           (
             pair:
-            lib.mapAttrsToList
+            mapAttrsToList
               (
                 childname: value:
                   [ "${pair.name} ${childname}" ] ++ (map (x: " " + x) (attr2Lines value))
@@ -34,7 +52,7 @@ let
     )
   ;
   addDefaults = settings: { backend = "btrfs-progs-sudo"; } // settings;
-  mkConfigFile = settings: lib.concatStringsSep "\n" (attr2Lines (addDefaults settings));
+  mkConfigFile = settings: concatStringsSep "\n" (attr2Lines (addDefaults settings));
   mkTestedConfigFile = name: settings:
     let
       configFile = pkgs.writeText "btrbk-${name}.conf" (mkConfigFile settings);
@@ -51,37 +69,42 @@ let
     '';
 in
 {
+  meta.maintainers = with lib.maintainers; [ oxalica ];
+
   options = {
     services.btrbk = {
-      extraPackages = lib.mkOption {
+      extraPackages = mkOption {
         description = "Extra packages for btrbk, like compression utilities for <literal>stream_compress</literal>";
-        type = lib.types.listOf lib.types.package;
+        type = types.listOf types.package;
         default = [ ];
-        example = lib.literalExpression "[ pkgs.xz ]";
+        example = literalExpression "[ pkgs.xz ]";
       };
-      niceness = lib.mkOption {
+      niceness = mkOption {
         description = "Niceness for local instances of btrbk. Also applies to remote ones connecting via ssh when positive.";
-        type = lib.types.ints.between (-20) 19;
+        type = types.ints.between (-20) 19;
         default = 10;
       };
-      ioSchedulingClass = lib.mkOption {
+      ioSchedulingClass = mkOption {
         description = "IO scheduling class for btrbk (see ionice(1) for a quick description). Applies to local instances, and remote ones connecting by ssh if set to idle.";
-        type = lib.types.enum [ "idle" "best-effort" "realtime" ];
+        type = types.enum [ "idle" "best-effort" "realtime" ];
         default = "best-effort";
       };
-      instances = lib.mkOption {
+      instances = mkOption {
         description = "Set of btrbk instances. The instance named <literal>btrbk</literal> is the default one.";
-        type = with lib.types;
+        type = with types;
           attrsOf (
             submodule {
               options = {
-                onCalendar = lib.mkOption {
-                  type = lib.types.str;
+                onCalendar = mkOption {
+                  type = types.nullOr types.str;
                   default = "daily";
-                  description = "How often this btrbk instance is started. See systemd.time(7) for more information about the format.";
+                  description = ''
+                    How often this btrbk instance is started. See systemd.time(7) for more information about the format.
+                    Setting it to null disables the timer, thus this instance can only be started manually.
+                  '';
                 };
-                settings = lib.mkOption {
-                  type = let t = lib.types.attrsOf (lib.types.either lib.types.str (t // { description = "instances of this type recursively"; })); in t;
+                settings = mkOption {
+                  type = let t = types.attrsOf (types.either types.str (t // { description = "instances of this type recursively"; })); in t;
                   default = { };
                   example = {
                     snapshot_preserve_min = "2d";
@@ -103,16 +126,16 @@ in
           );
         default = { };
       };
-      sshAccess = lib.mkOption {
+      sshAccess = mkOption {
         description = "SSH keys that should be able to make or push snapshots on this system remotely with btrbk";
-        type = with lib.types; listOf (
+        type = with types; listOf (
           submodule {
             options = {
-              key = lib.mkOption {
+              key = mkOption {
                 type = str;
                 description = "SSH public key allowed to login as user <literal>btrbk</literal> to run remote backups.";
               };
-              roles = lib.mkOption {
+              roles = mkOption {
                 type = listOf (enum [ "info" "source" "target" "delete" "snapshot" "send" "receive" ]);
                 example = [ "source" "info" "send" ];
                 description = "What actions can be performed with this SSH key. See ssh_filter_btrbk(1) for details";
@@ -125,7 +148,7 @@ in
     };
 
   };
-  config = lib.mkIf (sshEnabled || serviceEnabled) {
+  config = mkIf (sshEnabled || serviceEnabled) {
     environment.systemPackages = [ pkgs.btrbk ] ++ cfg.extraPackages;
     security.sudo.extraRules = [
       {
@@ -152,14 +175,14 @@ in
         (
           v:
           let
-            options = lib.concatMapStringsSep " " (x: "--" + x) v.roles;
+            options = concatMapStringsSep " " (x: "--" + x) v.roles;
             ioniceClass = {
               "idle" = 3;
               "best-effort" = 2;
               "realtime" = 1;
             }.${cfg.ioSchedulingClass};
           in
-          ''command="${pkgs.util-linux}/bin/ionice -t -c ${toString ioniceClass} ${lib.optionalString (cfg.niceness >= 1) "${pkgs.coreutils}/bin/nice -n ${toString cfg.niceness}"} ${pkgs.btrbk}/share/btrbk/scripts/ssh_filter_btrbk.sh --sudo ${options}" ${v.key}''
+          ''command="${pkgs.util-linux}/bin/ionice -t -c ${toString ioniceClass} ${optionalString (cfg.niceness >= 1) "${pkgs.coreutils}/bin/nice -n ${toString cfg.niceness}"} ${pkgs.btrbk}/share/btrbk/scripts/ssh_filter_btrbk.sh --sudo ${options}" ${v.key}''
         )
         cfg.sshAccess;
     };
@@ -169,7 +192,7 @@ in
       "d /var/lib/btrbk/.ssh 0700 btrbk btrbk"
       "f /var/lib/btrbk/.ssh/config 0700 btrbk btrbk - StrictHostKeyChecking=accept-new"
     ];
-    environment.etc = lib.mapAttrs'
+    environment.etc = mapAttrs'
       (
         name: instance: {
           name = "btrbk/${name}.conf";
@@ -177,7 +200,7 @@ in
         }
       )
       cfg.instances;
-    systemd.services = lib.mapAttrs'
+    systemd.services = mapAttrs'
       (
         name: _: {
           name = "btrbk-${name}";
@@ -199,7 +222,7 @@ in
       )
       cfg.instances;
 
-    systemd.timers = lib.mapAttrs'
+    systemd.timers = mapAttrs'
       (
         name: instance: {
           name = "btrbk-${name}";
@@ -214,7 +237,8 @@ in
           };
         }
       )
-      cfg.instances;
+      (filterAttrs (name: instance: instance.onCalendar != null)
+        cfg.instances);
   };
 
 }
diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix
index 8ff8e31864b..333fdd494e3 100644
--- a/nixos/modules/services/backup/restic.nix
+++ b/nixos/modules/services/backup/restic.nix
@@ -96,13 +96,22 @@ in
         };
 
         repository = mkOption {
-          type = types.str;
+          type = with types; nullOr str;
+          default = null;
           description = ''
             repository to backup to.
           '';
           example = "sftp:backup@192.168.1.100:/backups/${name}";
         };
 
+        repositoryFile = mkOption {
+          type = with types; nullOr path;
+          default = null;
+          description = ''
+            Path to the file containing the repository location to backup to.
+          '';
+        };
+
         paths = mkOption {
           type = types.nullOr (types.listOf types.str);
           default = null;
@@ -142,7 +151,7 @@ in
 
         extraBackupArgs = mkOption {
           type = types.listOf types.str;
-          default = [];
+          default = [ ];
           description = ''
             Extra arguments passed to restic backup.
           '';
@@ -153,7 +162,7 @@ in
 
         extraOptions = mkOption {
           type = types.listOf types.str;
-          default = [];
+          default = [ ];
           description = ''
             Extra extended options to be passed to the restic --option flag.
           '';
@@ -172,7 +181,7 @@ in
 
         pruneOpts = mkOption {
           type = types.listOf types.str;
-          default = [];
+          default = [ ];
           description = ''
             A list of options (--keep-* et al.) for 'restic forget
             --prune', to automatically prune old snapshots.  The
@@ -197,9 +206,25 @@ in
           '';
           example = "find /home/matt/git -type d -name .git";
         };
+
+        backupPrepareCommand = mkOption {
+          type = with types; nullOr str;
+          default = null;
+          description = ''
+            A script that must run before starting the backup process.
+          '';
+        };
+
+        backupCleanupCommand = mkOption {
+          type = with types; nullOr str;
+          default = null;
+          description = ''
+            A script that must run after finishing the backup process.
+          '';
+        };
       };
     }));
-    default = {};
+    default = { };
     example = {
       localbackup = {
         paths = [ "/home" ];
@@ -225,66 +250,85 @@ in
   config = {
     warnings = mapAttrsToList (n: v: "services.restic.backups.${n}.s3CredentialsFile is deprecated, please use services.restic.backups.${n}.environmentFile instead.") (filterAttrs (n: v: v.s3CredentialsFile != null) config.services.restic.backups);
     systemd.services =
-      mapAttrs' (name: backup:
-        let
-          extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
-          resticCmd = "${pkgs.restic}/bin/restic${extraOptions}";
-          filesFromTmpFile = "/run/restic-backups-${name}/includes";
-          backupPaths = if (backup.dynamicFilesFrom == null)
-                        then if (backup.paths != null) then concatStringsSep " " backup.paths else ""
-                        else "--files-from ${filesFromTmpFile}";
-          pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [
-            ( resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts) )
-            ( resticCmd + " check" )
-          ];
-          # Helper functions for rclone remotes
-          rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1;
-          rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v);
-          rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v);
-          toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
-        in nameValuePair "restic-backups-${name}" ({
-          environment = {
-            RESTIC_PASSWORD_FILE = backup.passwordFile;
-            RESTIC_REPOSITORY = backup.repository;
-          } // optionalAttrs (backup.rcloneOptions != null) (mapAttrs' (name: value:
-            nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
-          ) backup.rcloneOptions) // optionalAttrs (backup.rcloneConfigFile != null) {
-            RCLONE_CONFIG = backup.rcloneConfigFile;
-          } // optionalAttrs (backup.rcloneConfig != null) (mapAttrs' (name: value:
-            nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
-          ) backup.rcloneConfig);
-          path = [ pkgs.openssh ];
-          restartIfChanged = false;
-          serviceConfig = {
-            Type = "oneshot";
-            ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup --cache-dir=%C/restic-backups-${name} ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ])
-                        ++ pruneCmd;
-            User = backup.user;
-            RuntimeDirectory = "restic-backups-${name}";
-            CacheDirectory = "restic-backups-${name}";
-            CacheDirectoryMode = "0700";
-          } // optionalAttrs (backup.environmentFile != null) {
-            EnvironmentFile = backup.environmentFile;
-          };
-        } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null) {
-          preStart = ''
-            ${optionalString (backup.initialize) ''
-              ${resticCmd} snapshots || ${resticCmd} init
-            ''}
-            ${optionalString (backup.dynamicFilesFrom != null) ''
-              ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile}
-            ''}
-          '';
-        } // optionalAttrs (backup.dynamicFilesFrom != null) {
-          postStart = ''
-            rm ${filesFromTmpFile}
-          '';
-        })
-      ) config.services.restic.backups;
+      mapAttrs'
+        (name: backup:
+          let
+            extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
+            resticCmd = "${pkgs.restic}/bin/restic${extraOptions}";
+            filesFromTmpFile = "/run/restic-backups-${name}/includes";
+            backupPaths =
+              if (backup.dynamicFilesFrom == null)
+              then if (backup.paths != null) then concatStringsSep " " backup.paths else ""
+              else "--files-from ${filesFromTmpFile}";
+            pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [
+              (resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts))
+              (resticCmd + " check")
+            ];
+            # Helper functions for rclone remotes
+            rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1;
+            rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v);
+            rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v);
+            toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
+          in
+          nameValuePair "restic-backups-${name}" ({
+            environment = {
+              RESTIC_PASSWORD_FILE = backup.passwordFile;
+              RESTIC_REPOSITORY = backup.repository;
+              RESTIC_REPOSITORY_FILE = backup.repositoryFile;
+            } // optionalAttrs (backup.rcloneOptions != null) (mapAttrs'
+              (name: value:
+                nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
+              )
+              backup.rcloneOptions) // optionalAttrs (backup.rcloneConfigFile != null) {
+              RCLONE_CONFIG = backup.rcloneConfigFile;
+            } // optionalAttrs (backup.rcloneConfig != null) (mapAttrs'
+              (name: value:
+                nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
+              )
+              backup.rcloneConfig);
+            path = [ pkgs.openssh ];
+            restartIfChanged = false;
+            serviceConfig = {
+              Type = "oneshot";
+              ExecStart = (optionals (backupPaths != "") [ "${resticCmd} backup --cache-dir=%C/restic-backups-${name} ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ])
+                ++ pruneCmd;
+              User = backup.user;
+              RuntimeDirectory = "restic-backups-${name}";
+              CacheDirectory = "restic-backups-${name}";
+              CacheDirectoryMode = "0700";
+            } // optionalAttrs (backup.environmentFile != null) {
+              EnvironmentFile = backup.environmentFile;
+            };
+          } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null || backup.backupPrepareCommand != null) {
+            preStart = ''
+              ${optionalString (backup.backupPrepareCommand != null) ''
+                ${pkgs.writeScript "backupPrepareCommand" backup.backupPrepareCommand}
+              ''}
+              ${optionalString (backup.initialize) ''
+                ${resticCmd} snapshots || ${resticCmd} init
+              ''}
+              ${optionalString (backup.dynamicFilesFrom != null) ''
+                ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile}
+              ''}
+            '';
+          } // optionalAttrs (backup.dynamicFilesFrom != null || backup.backupCleanupCommand != null) {
+            postStart = ''
+              ${optionalString (backup.backupCleanupCommand != null) ''
+                ${pkgs.writeScript "backupCleanupCommand" backup.backupCleanupCommand}
+              ''}
+              ${optionalString (backup.dynamicFilesFrom != null) ''
+                rm ${filesFromTmpFile}
+              ''}
+            '';
+          })
+        )
+        config.services.restic.backups;
     systemd.timers =
-      mapAttrs' (name: backup: nameValuePair "restic-backups-${name}" {
-        wantedBy = [ "timers.target" ];
-        timerConfig = backup.timerConfig;
-      }) config.services.restic.backups;
+      mapAttrs'
+        (name: backup: nameValuePair "restic-backups-${name}" {
+          wantedBy = [ "timers.target" ];
+          timerConfig = backup.timerConfig;
+        })
+        config.services.restic.backups;
   };
 }
diff --git a/nixos/modules/services/computing/slurm/slurm.nix b/nixos/modules/services/computing/slurm/slurm.nix
index 8cbe54c6060..b9792fd1334 100644
--- a/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixos/modules/services/computing/slurm/slurm.nix
@@ -361,8 +361,13 @@ in
         ++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
 
       wantedBy = [ "multi-user.target" ];
-      after = [ "systemd-tmpfiles-clean.service" ];
-      requires = [ "network.target" ];
+      after = [
+        "systemd-tmpfiles-clean.service"
+        "munge.service"
+        "network-online.target"
+        "remote-fs.target"
+      ];
+      wants = [ "network-online.target" ];
 
       serviceConfig = {
         Type = "forking";
@@ -371,6 +376,7 @@ in
         PIDFile = "/run/slurmd.pid";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         LimitMEMLOCK = "infinity";
+        Delegate="Yes";
       };
     };
 
diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix
index 2c1e25d4308..1967a2371bd 100644
--- a/nixos/modules/services/databases/openldap.nix
+++ b/nixos/modules/services/databases/openldap.nix
@@ -268,9 +268,14 @@ in {
     };
 
     systemd.services.openldap = {
-      description = "LDAP server";
+      description = "OpenLDAP Server Daemon";
+      documentation = [
+        "man:slapd"
+        "man:slapd-config"
+        "man:slapd-mdb"
+      ];
       wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" ];
+      after = [ "network-online.target" ];
       preStart = let
         settingsFile = pkgs.writeText "config.ldif" (lib.concatStringsSep "\n" (attrsToLdif "cn=config" cfg.settings));
 
@@ -306,7 +311,7 @@ in {
           "${openldap}/libexec/slapd" "-u" cfg.user "-g" cfg.group "-F" configDir
           "-h" (lib.concatStringsSep " " cfg.urlList)
         ]);
-        Type = "forking";
+        Type = "notify";
         PIDFile = cfg.settings.attrs.olcPidFile;
       };
     };
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 2919022496a..550bd36efff 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -295,7 +295,8 @@ in
       # Note: when changing the default, make it conditional on
       # ‘system.stateVersion’ to maintain compatibility with existing
       # systems!
-      mkDefault (if versionAtLeast config.system.stateVersion "21.11" then pkgs.postgresql_13
+      mkDefault (if versionAtLeast config.system.stateVersion "22.05" then pkgs.postgresql_14
+            else if versionAtLeast config.system.stateVersion "21.11" then pkgs.postgresql_13
             else if versionAtLeast config.system.stateVersion "20.03" then pkgs.postgresql_11
             else if versionAtLeast config.system.stateVersion "17.09" then mkThrow "9_6"
             else mkThrow "9_5");
diff --git a/nixos/modules/services/games/asf.nix b/nixos/modules/services/games/asf.nix
index ea2bfd40fff..31a112d6c74 100644
--- a/nixos/modules/services/games/asf.nix
+++ b/nixos/modules/services/games/asf.nix
@@ -13,6 +13,8 @@ let
     # is in theory not needed as this is already the default for default builds
     UpdateChannel = 0;
     Headless = true;
+  } // lib.optionalAttrs (cfg.ipcPasswordFile != "") {
+    IPCPassword = "#ipcPassword#";
   });
 
   ipc-config = format.generate "IPC.config" cfg.ipcSettings;
@@ -81,8 +83,7 @@ in
       type = format.type;
       description = ''
         The ASF.json file, all the options are documented <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#global-config">here</link>.
-        Do note that `AutoRestart`  and `UpdateChannel` is always to `false`
-respectively `0` because NixOS takes care of updating everything.
+        Do note that `AutoRestart`  and `UpdateChannel` is always to `false` respectively `0` because NixOS takes care of updating everything.
         `Headless` is also always set to `true` because there is no way to provide inputs via a systemd service.
         You should try to keep ASF up to date since upstream does not provide support for anything but the latest version and you're exposing yourself to all kinds of issues - as is outlined <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#updateperiod">here</link>.
       '';
@@ -92,6 +93,11 @@ respectively `0` because NixOS takes care of updating everything.
       default = { };
     };
 
+    ipcPasswordFile = mkOption {
+      type = types.path;
+      description = "Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group.";
+    };
+
     ipcSettings = mkOption {
       type = format.type;
       description = ''
@@ -115,14 +121,12 @@ respectively `0` because NixOS takes care of updating everything.
         options = {
           username = mkOption {
             type = types.str;
-            description =
-              "Name of the user to log in. Default is attribute name.";
+            description = "Name of the user to log in. Default is attribute name.";
             default = "";
           };
           passwordFile = mkOption {
             type = types.path;
-            description =
-              "Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group.";
+            description = "Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group.";
           };
           enabled = mkOption {
             type = types.bool;
@@ -131,8 +135,7 @@ respectively `0` because NixOS takes care of updating everything.
           };
           settings = mkOption {
             type = types.attrs;
-            description =
-              "Additional settings that are documented <link xlink:href=\"https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config\">here</link>.";
+            description = "Additional settings that are documented <link xlink:href=\"https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config\">here</link>.";
             default = { };
           };
         };
@@ -156,6 +159,7 @@ respectively `0` because NixOS takes care of updating everything.
     users = {
       users.asf = {
         home = cfg.dataDir;
+        homeMode = "700";
         isSystemUser = true;
         group = "asf";
         description = "Archis-Steam-Farm service user";
@@ -176,8 +180,7 @@ respectively `0` because NixOS takes care of updating everything.
             Group = "asf";
             WorkingDirectory = cfg.dataDir;
             Type = "simple";
-            ExecStart =
-              "${cfg.package}/bin/ArchiSteamFarm --path ${cfg.dataDir} --process-required --no-restart --service --no-config-migrate";
+            ExecStart = "${cfg.package}/bin/ArchiSteamFarm --path ${cfg.dataDir} --process-required --no-restart --service --no-config-migrate";
 
             # mostly copied from the default systemd service
             PrivateTmp = true;
@@ -202,29 +205,38 @@ respectively `0` because NixOS takes care of updating everything.
           }
         ];
 
-        preStart = ''
-          mkdir -p config
-          rm -f www
-          rm -f config/{*.json,*.config}
-
-          ln -s ${asf-config} config/ASF.json
-
-          ${strings.optionalString (cfg.ipcSettings != {}) ''
-            ln -s ${ipc-config} config/IPC.config
-          ''}
-
-          ln -s ${pkgs.runCommandLocal "ASF-bots" {} ''
-            mkdir -p $out/lib/asf/bots
-            for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=",";
-              set -- $i
-              ln -s $2 $out/lib/asf/bots/$1
-            done
-          ''}/lib/asf/bots/* config/
-
-          ${strings.optionalString cfg.web-ui.enable ''
-            ln -s ${cfg.web-ui.package}/lib/dist www
-          ''}
-        '';
+        preStart =
+          let
+            createBotsScript = pkgs.runCommandLocal "ASF-bots" { } ''
+              mkdir -p $out
+              # clean potential removed bots
+              rm -rf $out/*.json
+              for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=",";
+                set -- $i
+                ln -fs $2 $out/$1
+              done
+            '';
+            replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret";
+          in
+          ''
+            mkdir -p config
+
+            cp --no-preserve=mode ${asf-config} config/ASF.json
+            ${replaceSecretBin} '#ipcPassword#' '${cfg.ipcPasswordFile}' config/ASF.json
+
+            ${optionalString (cfg.ipcSettings != {}) ''
+              ln -fs ${ipc-config} config/IPC.config
+            ''}
+
+            ${optionalString (cfg.ipcSettings != {}) ''
+              ln -fs ${createBotsScript}/* config/
+            ''}
+
+            rm -f www
+            ${optionalString cfg.web-ui.enable ''
+              ln -s ${cfg.web-ui.package}/lib/dist www
+            ''}
+          '';
       };
     };
   };
diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix
index f1e074587b3..5b714c384de 100644
--- a/nixos/modules/services/mail/mailman.nix
+++ b/nixos/modules/services/mail/mailman.nix
@@ -6,10 +6,10 @@ let
 
   cfg = config.services.mailman;
 
-  pythonEnv = pkgs.python3.withPackages (ps:
-    [ps.mailman ps.mailman-web]
-    ++ lib.optional cfg.hyperkitty.enable ps.mailman-hyperkitty
-    ++ cfg.extraPythonPackages);
+  inherit (pkgs.mailmanPackages.buildEnvs { withHyperkitty = cfg.hyperkitty.enable; })
+    mailmanEnv webEnv;
+
+  withPostgresql = config.services.postgresql.enable;
 
   # This deliberately doesn't use recursiveUpdate so users can
   # override the defaults.
@@ -72,6 +72,9 @@ in {
       stored in the world-readable Nix store.  To continue using
       Hyperkitty, you must set services.mailman.hyperkitty.enable = true.
     '')
+    (mkRemovedOptionModule [ "services" "mailman" "package" ] ''
+      Didn't have an effect for several years.
+    '')
   ];
 
   options = {
@@ -84,14 +87,6 @@ in {
         description = "Enable Mailman on this host. Requires an active MTA on the host (e.g. Postfix).";
       };
 
-      package = mkOption {
-        type = types.package;
-        default = pkgs.mailman;
-        defaultText = literalExpression "pkgs.mailman";
-        example = literalExpression "pkgs.mailman.override { archivers = []; }";
-        description = "Mailman package to use";
-      };
-
       enablePostfix = mkOption {
         type = types.bool;
         default = true;
@@ -185,7 +180,7 @@ in {
       mailman.layout = "fhs";
 
       "paths.fhs" = {
-        bin_dir = "${pkgs.python3Packages.mailman}/bin";
+        bin_dir = "${pkgs.mailmanPackages.mailman}/bin";
         var_dir = "/var/lib/mailman";
         queue_dir = "$var_dir/queue";
         template_dir = "$var_dir/templates";
@@ -295,9 +290,12 @@ in {
       name = "mailman-tools";
       # We don't want to pollute the system PATH with a python
       # interpreter etc. so let's pick only the stuff we actually
-      # want from pythonEnv
+      # want from {web,mailman}Env
       pathsToLink = ["/bin"];
-      paths = [pythonEnv];
+      paths = [ mailmanEnv webEnv ];
+      # Only mailman-related stuff is installed, the rest is removed
+      # in `postBuild`.
+      ignoreCollisions = true;
       postBuild = ''
         find $out/bin/ -mindepth 1 -not -name "mailman*" -delete
       '';
@@ -320,12 +318,14 @@ in {
         description = "GNU Mailman Master Process";
         before = lib.optional cfg.enablePostfix "postfix.service";
         after = [ "network.target" ]
-          ++ lib.optional cfg.enablePostfix "postfix-setup.service";
+          ++ lib.optional cfg.enablePostfix "postfix-setup.service"
+          ++ lib.optional withPostgresql "postgresql.service";
         restartTriggers = [ config.environment.etc."mailman.cfg".source ];
+        requires = optional withPostgresql "postgresql.service";
         wantedBy = [ "multi-user.target" ];
         serviceConfig = {
-          ExecStart = "${pythonEnv}/bin/mailman start";
-          ExecStop = "${pythonEnv}/bin/mailman stop";
+          ExecStart = "${mailmanEnv}/bin/mailman start";
+          ExecStop = "${mailmanEnv}/bin/mailman stop";
           User = "mailman";
           Group = "mailman";
           Type = "forking";
@@ -340,6 +340,8 @@ in {
         before = [ "mailman.service" "mailman-web-setup.service" "mailman-uwsgi.service" "hyperkitty.service" ];
         requiredBy = [ "mailman.service" "mailman-web-setup.service" "mailman-uwsgi.service" "hyperkitty.service" ];
         path = with pkgs; [ jq ];
+        after = optional withPostgresql "postgresql.service";
+        requires = optional withPostgresql "postgresql.service";
         serviceConfig.Type = "oneshot";
         script = ''
           mailmanDir=/var/lib/mailman
@@ -381,9 +383,9 @@ in {
         restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
         script = ''
           [[ -e "${webSettings.STATIC_ROOT}" ]] && find "${webSettings.STATIC_ROOT}/" -mindepth 1 -delete
-          ${pythonEnv}/bin/mailman-web migrate
-          ${pythonEnv}/bin/mailman-web collectstatic
-          ${pythonEnv}/bin/mailman-web compress
+          ${webEnv}/bin/mailman-web migrate
+          ${webEnv}/bin/mailman-web collectstatic
+          ${webEnv}/bin/mailman-web compress
         '';
         serviceConfig = {
           User = cfg.webUser;
@@ -397,14 +399,16 @@ in {
         uwsgiConfig.uwsgi = {
           type = "normal";
           plugins = ["python3"];
-          home = pythonEnv;
+          home = webEnv;
           module = "mailman_web.wsgi";
           http = "127.0.0.1:18507";
         };
         uwsgiConfigFile = pkgs.writeText "uwsgi-mailman.json" (builtins.toJSON uwsgiConfig);
       in {
         wantedBy = ["multi-user.target"];
-        requires = ["mailman-uwsgi.socket" "mailman-web-setup.service"];
+        after = optional withPostgresql "postgresql.service";
+        requires = ["mailman-uwsgi.socket" "mailman-web-setup.service"]
+          ++ optional withPostgresql "postgresql.service";
         restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
         serviceConfig = {
           # Since the mailman-web settings.py obstinately creates a logs
@@ -422,7 +426,7 @@ in {
         startAt = "daily";
         restartTriggers = [ config.environment.etc."mailman.cfg".source ];
         serviceConfig = {
-          ExecStart = "${pythonEnv}/bin/mailman digests --send";
+          ExecStart = "${mailmanEnv}/bin/mailman digests --send";
           User = "mailman";
           Group = "mailman";
         };
@@ -434,7 +438,7 @@ in {
         restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
         wantedBy = [ "mailman.service" "multi-user.target" ];
         serviceConfig = {
-          ExecStart = "${pythonEnv}/bin/mailman-web qcluster";
+          ExecStart = "${webEnv}/bin/mailman-web qcluster";
           User = cfg.webUser;
           Group = "mailman";
           WorkingDirectory = "/var/lib/mailman-web";
@@ -453,7 +457,7 @@ in {
         inherit startAt;
         restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
         serviceConfig = {
-          ExecStart = "${pythonEnv}/bin/mailman-web runjobs ${name}";
+          ExecStart = "${webEnv}/bin/mailman-web runjobs ${name}";
           User = cfg.webUser;
           Group = "mailman";
           WorkingDirectory = "/var/lib/mailman-web";
@@ -462,7 +466,7 @@ in {
   };
 
   meta = {
-    maintainers = with lib.maintainers; [ lheckemann qyliss ];
+    maintainers = with lib.maintainers; [ lheckemann qyliss ma27 ];
     doc = ./mailman.xml;
   };
 
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index da14b6eef7e..de00c87b95a 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -725,6 +725,7 @@ in
 
       systemd.services.postfix-setup =
         { description = "Setup for Postfix mail server";
+          serviceConfig.RemainAfterExit = true;
           serviceConfig.Type = "oneshot";
           script = ''
             # Backwards compatibility
diff --git a/nixos/modules/services/misc/dendrite.nix b/nixos/modules/services/misc/dendrite.nix
index ac5df9951b3..54052084b33 100644
--- a/nixos/modules/services/misc/dendrite.nix
+++ b/nixos/modules/services/misc/dendrite.nix
@@ -74,6 +74,18 @@ in
         <literal>dendrite</literal> is running.
       '';
     };
+    loadCredential = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      default = [ ];
+      example = [ "private_key:/path/to/my_private_key" ];
+      description = ''
+        This can be used to pass secrets to the systemd service without adding them to
+        the nix store.
+        To use the example setting, see the example of
+        <option>services.dendrite.settings.global.private_key</option>.
+        See the LoadCredential section of systemd.exec manual for more information.
+      '';
+    };
     settings = lib.mkOption {
       type = lib.types.submodule {
         freeformType = settingsFormat.type;
@@ -88,8 +100,10 @@ in
             '';
           };
           private_key = lib.mkOption {
-            type = lib.types.path;
-            example = "${workingDir}/matrix_key.pem";
+            type = lib.types.either
+              lib.types.path
+              (lib.types.strMatching "^\\$CREDENTIALS_DIRECTORY/.+");
+            example = "$CREDENTIALS_DIRECTORY/private_key";
             description = ''
               The path to the signing private key file, used to sign
               requests and events.
@@ -256,6 +270,7 @@ in
         RuntimeDirectoryMode = "0700";
         LimitNOFILE = 65535;
         EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
+        LoadCredential = cfg.loadCredential;
         ExecStartPre = ''
           ${pkgs.envsubst}/bin/envsubst \
             -i ${configurationYaml} \
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index 0811b34156e..24eefb7bf30 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -17,8 +17,8 @@ let
   gitalySocket = "${cfg.statePath}/tmp/sockets/gitaly.socket";
   pathUrlQuote = url: replaceStrings ["/"] ["%2F"] url;
 
-  databaseConfig = {
-    production = {
+  databaseConfig = let
+    val = {
       adapter = "postgresql";
       database = cfg.databaseName;
       host = cfg.databaseHost;
@@ -26,6 +26,10 @@ let
       encoding = "utf8";
       pool = cfg.databasePool;
     } // cfg.extraDatabaseConfig;
+  in if lib.versionAtLeast (lib.getVersion cfg.packages.gitlab) "15.0" then {
+    production.main = val;
+  } else {
+    production = val;
   };
 
   # We only want to create a database if we're actually going to connect to it.
@@ -1184,7 +1188,7 @@ in {
                 fi
 
                 jq <${pkgs.writeText "database.yml" (builtins.toJSON databaseConfig)} \
-                   '.production.password = $ENV.db_password' \
+                   '.${if lib.versionAtLeast (lib.getVersion cfg.packages.gitlab) "15.0" then "production.main" else "production"}.password = $ENV.db_password' \
                    >'${cfg.statePath}/config/database.yml'
               ''
               else ''
diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix
index cad73a871ba..354278fad22 100644
--- a/nixos/modules/services/misc/gollum.nix
+++ b/nixos/modules/services/misc/gollum.nix
@@ -44,6 +44,12 @@ in
       description = "Enable uploads of external files";
     };
 
+    user-icons = mkOption {
+      type = types.nullOr (types.enum [ "gravatar" "identicon" ]);
+      default = null;
+      description = "User icons for history view";
+    };
+
     emoji = mkOption {
       type = types.bool;
       default = false;
@@ -56,6 +62,12 @@ in
       description = "Use the first h1 as page title";
     };
 
+    no-edit = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Disable editing pages";
+    };
+
     branch = mkOption {
       type = types.str;
       default = "master";
@@ -110,12 +122,14 @@ in
             ${optionalString cfg.mathjax "--mathjax"} \
             ${optionalString cfg.emoji "--emoji"} \
             ${optionalString cfg.h1-title "--h1-title"} \
+            ${optionalString cfg.no-edit "--no-edit"} \
             ${optionalString (cfg.allowUploads != null) "--allow-uploads ${cfg.allowUploads}"} \
+            ${optionalString (cfg.user-icons != null) "--user-icons ${cfg.user-icons}"} \
             ${cfg.stateDir}
         '';
       };
     };
   };
 
-  meta.maintainers = with lib.maintainers; [ erictapen ];
+  meta.maintainers = with lib.maintainers; [ erictapen bbenno ];
 }
diff --git a/nixos/modules/services/misc/jellyfin.nix b/nixos/modules/services/misc/jellyfin.nix
index 04cf82f8a46..789b78702e9 100644
--- a/nixos/modules/services/misc/jellyfin.nix
+++ b/nixos/modules/services/misc/jellyfin.nix
@@ -53,7 +53,10 @@ in
         User = cfg.user;
         Group = cfg.group;
         StateDirectory = "jellyfin";
+        StateDirectoryMode = "0700";
         CacheDirectory = "jellyfin";
+        CacheDirectoryMode = "0700";
+        UMask = "0077";
         ExecStart = "${cfg.package}/bin/jellyfin --datadir '/var/lib/${StateDirectory}' --cachedir '/var/cache/${CacheDirectory}'";
         Restart = "on-failure";
 
diff --git a/nixos/modules/services/misc/libreddit.nix b/nixos/modules/services/misc/libreddit.nix
index 77b34a85620..e21a8844784 100644
--- a/nixos/modules/services/misc/libreddit.nix
+++ b/nixos/modules/services/misc/libreddit.nix
@@ -2,14 +2,13 @@
 
 with lib;
 
-  let
-    cfg = config.services.libreddit;
-
-    args = concatStringsSep " " ([
-      "--port ${toString cfg.port}"
-      "--address ${cfg.address}"
-    ] ++ optional cfg.redirect "--redirect-https");
+let
+  cfg = config.services.libreddit;
 
+  args = concatStringsSep " " ([
+    "--port ${toString cfg.port}"
+    "--address ${cfg.address}"
+  ]);
 in
 {
   options = {
@@ -30,12 +29,6 @@ in
         description = "The port to listen on";
       };
 
-      redirect = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Enable the redirecting to HTTPS";
-      };
-
       openFirewall = mkOption {
         type = types.bool;
         default = false;
@@ -56,6 +49,31 @@ in
           AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
           Restart = "on-failure";
           RestartSec = "2s";
+          # Hardening
+          CapabilityBoundingSet = if (cfg.port < 1024) then [ "CAP_NET_BIND_SERVICE" ] else [ "" ];
+          DeviceAllow = [ "" ];
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          PrivateDevices = true;
+          # A private user cannot have process capabilities on the host's user
+          # namespace and thus CAP_NET_BIND_SERVICE has no effect.
+          PrivateUsers = (cfg.port >= 1024);
+          ProcSubset = "pid";
+          ProtectClock = true;
+          ProtectControlGroups = true;
+          ProtectHome = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          ProtectProc = "invisible";
+          RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+          RestrictNamespaces = true;
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          SystemCallArchitectures = "native";
+          SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ];
+          UMask = "0077";
         };
     };
 
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index b959379d331..497d4674138 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -14,6 +14,7 @@ let
     PATHS_PLUGINS = if builtins.isNull cfg.declarativePlugins then "${cfg.dataDir}/plugins" else declarativePlugins;
     PATHS_LOGS = "${cfg.dataDir}/log";
 
+    SERVER_SERVE_FROM_SUBPATH = boolToString cfg.server.serveFromSubPath;
     SERVER_PROTOCOL = cfg.protocol;
     SERVER_HTTP_ADDR = cfg.addr;
     SERVER_HTTP_PORT = cfg.port;
@@ -41,9 +42,23 @@ let
     USERS_AUTO_ASSIGN_ORG = boolToString cfg.users.autoAssignOrg;
     USERS_AUTO_ASSIGN_ORG_ROLE = cfg.users.autoAssignOrgRole;
 
+    AUTH_DISABLE_LOGIN_FORM = boolToString cfg.auth.disableLoginForm;
+
     AUTH_ANONYMOUS_ENABLED = boolToString cfg.auth.anonymous.enable;
     AUTH_ANONYMOUS_ORG_NAME = cfg.auth.anonymous.org_name;
     AUTH_ANONYMOUS_ORG_ROLE = cfg.auth.anonymous.org_role;
+
+    AUTH_AZUREAD_NAME = "Azure AD";
+    AUTH_AZUREAD_ENABLED = boolToString cfg.auth.azuread.enable;
+    AUTH_AZUREAD_ALLOW_SIGN_UP = boolToString cfg.auth.azuread.allowSignUp;
+    AUTH_AZUREAD_CLIENT_ID = cfg.auth.azuread.clientId;
+    AUTH_AZUREAD_SCOPES = "openid email profile";
+    AUTH_AZUREAD_AUTH_URL = "https://login.microsoftonline.com/${cfg.auth.azuread.tenantId}/oauth2/v2.0/authorize";
+    AUTH_AZUREAD_TOKEN_URL = "https://login.microsoftonline.com/${cfg.auth.azuread.tenantId}/oauth2/v2.0/token";
+    AUTH_AZUREAD_ALLOWED_DOMAINS = cfg.auth.azuread.allowedDomains;
+    AUTH_AZUREAD_ALLOWED_GROUPS = cfg.auth.azuread.allowedGroups;
+    AUTH_AZUREAD_ROLE_ATTRIBUTE_STRICT = false;
+
     AUTH_GOOGLE_ENABLED = boolToString cfg.auth.google.enable;
     AUTH_GOOGLE_ALLOW_SIGN_UP = boolToString cfg.auth.google.allowSignUp;
     AUTH_GOOGLE_CLIENT_ID = cfg.auth.google.clientId;
@@ -484,6 +499,14 @@ in {
       };
     };
 
+    server = {
+      serveFromSubPath = mkOption {
+        description = "Serve Grafana from subpath specified in rootUrl setting";
+        default = false;
+        type = types.bool;
+      };
+    };
+
     smtp = {
       enable = mkEnableOption "smtp";
       host = mkOption {
@@ -546,6 +569,12 @@ in {
     };
 
     auth = {
+      disableLoginForm = mkOption {
+        description = "Set to true to disable (hide) the login form, useful if you use OAuth";
+        default = false;
+        type = types.bool;
+      };
+
       anonymous = {
         enable = mkOption {
           description = "Whether to allow anonymous access.";
@@ -563,6 +592,53 @@ in {
           type = types.str;
         };
       };
+      azuread = {
+        enable = mkOption {
+          description = "Whether to allow Azure AD OAuth.";
+          default = false;
+          type = types.bool;
+        };
+        allowSignUp = mkOption {
+          description = "Whether to allow sign up with Azure AD OAuth.";
+          default = false;
+          type = types.bool;
+        };
+        clientId = mkOption {
+          description = "Azure AD OAuth client ID.";
+          default = "";
+          type = types.str;
+        };
+        clientSecretFile = mkOption {
+          description = "Azure AD OAuth client secret.";
+          default = null;
+          type = types.nullOr types.path;
+        };
+        tenantId = mkOption {
+          description = ''
+            Tenant id used to create auth and token url. Default to "common"
+            , let user sign in with any tenant.
+            '';
+          default = "common";
+          type = types.str;
+        };
+        allowedDomains = mkOption {
+          description = ''
+            To limit access to authenticated users who are members of one or more groups,
+            set allowedGroups to a comma- or space-separated list of group object IDs.
+            You can find object IDs for a specific group on the Azure portal.
+          '';
+          default = "";
+          type = types.str;
+        };
+        allowedGroups = mkOption {
+          description = ''
+            Limits access to users who belong to specific domains.
+            Separate domains with space or comma.
+          '';
+          default = "";
+          type = types.str;
+        };
+      };
       google = {
         enable = mkOption {
           description = "Whether to allow Google OAuth2.";
@@ -652,6 +728,10 @@ in {
         set -o errexit -o pipefail -o nounset -o errtrace
         shopt -s inherit_errexit
 
+        ${optionalString (cfg.auth.azuread.clientSecretFile != null) ''
+          GF_AUTH_AZUREAD_CLIENT_SECRET="$(<${escapeShellArg cfg.auth.azuread.clientSecretFile})"
+          export GF_AUTH_AZUREAD_CLIENT_SECRET
+        ''}
         ${optionalString (cfg.auth.google.clientSecretFile != null) ''
           GF_AUTH_GOOGLE_CLIENT_SECRET="$(<${escapeShellArg cfg.auth.google.clientSecretFile})"
           export GF_AUTH_GOOGLE_CLIENT_SECRET
diff --git a/nixos/modules/services/monitoring/mimir.nix b/nixos/modules/services/monitoring/mimir.nix
index df853f037ee..f85f3ab02c3 100644
--- a/nixos/modules/services/monitoring/mimir.nix
+++ b/nixos/modules/services/monitoring/mimir.nix
@@ -28,6 +28,9 @@ in {
   };
 
   config = mkIf cfg.enable {
+    # for mimirtool
+    environment.systemPackages = [ pkgs.mimir ];
+
     assertions = [{
       assertion = (
         (cfg.configuration == {} -> cfg.configFile != null) &&
@@ -56,6 +59,7 @@ in {
         ProtectSystem = "full";
         DevicePolicy = "closed";
         NoNewPrivileges = true;
+        WorkingDirectory = "/var/lib/mimir";
         StateDirectory = "mimir";
       };
     };
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix b/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix
index 330610a15d9..25950e1ece9 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/dmarc.nix
@@ -108,7 +108,7 @@ in {
           -i ${pkgs.writeText "dmarc-exporter.json.template" json} \
           -o ''${STATE_DIRECTORY}/dmarc-exporter.json
 
-        exec ${pkgs.prometheus-dmarc-exporter}/bin/prometheus-dmarc-exporter \
+        exec ${pkgs.dmarc-metrics-exporter}/bin/dmarc-metrics-exporter \
           --configuration /var/lib/prometheus-dmarc-exporter/dmarc-exporter.json \
           ${optionalString cfg.debug "--debug"}
       ''}";
diff --git a/nixos/modules/services/networking/bird-lg.nix b/nixos/modules/services/networking/bird-lg.nix
new file mode 100644
index 00000000000..515ef38608b
--- /dev/null
+++ b/nixos/modules/services/networking/bird-lg.nix
@@ -0,0 +1,269 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.bird-lg;
+in
+{
+  options = {
+    services.bird-lg = {
+      package = mkOption {
+        type = types.package;
+        default = pkgs.bird-lg;
+        defaultText = literalExpression "pkgs.bird-lg";
+        description = "The Bird Looking Glass package to use.";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "bird-lg";
+        description = "User to run the service.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "bird-lg";
+        description = "Group to run the service.";
+      };
+
+      frontend = {
+        enable = mkEnableOption "Bird Looking Glass Frontend Webserver";
+
+        listenAddress = mkOption {
+          type = types.str;
+          default = "127.0.0.1:5000";
+          description = "Address to listen on.";
+        };
+
+        proxyPort = mkOption {
+          type = types.port;
+          default = 8000;
+          description = "Port bird-lg-proxy is running on.";
+        };
+
+        domain = mkOption {
+          type = types.str;
+          default = "";
+          example = "dn42.lantian.pub";
+          description = "Server name domain suffixes.";
+        };
+
+        servers = mkOption {
+          type = types.listOf types.str;
+          default = [ ];
+          example = [ "gigsgigscloud" "hostdare" ];
+          description = "Server name prefixes.";
+        };
+
+        whois = mkOption {
+          type = types.str;
+          default = "whois.verisign-grs.com";
+          description = "Whois server for queries.";
+        };
+
+        dnsInterface = mkOption {
+          type = types.str;
+          default = "asn.cymru.com";
+          description = "DNS zone to query ASN information.";
+        };
+
+        bgpMapInfo = mkOption {
+          type = types.listOf types.str;
+          default = [ "asn" "as-name" "ASName" "descr" ];
+          description = "Information displayed in bgpmap.";
+        };
+
+        titleBrand = mkOption {
+          type = types.str;
+          default = "Bird-lg Go";
+          description = "Prefix of page titles in browser tabs.";
+        };
+
+        netSpecificMode = mkOption {
+          type = types.str;
+          default = "";
+          example = "dn42";
+          description = "Apply network-specific changes for some networks.";
+        };
+
+        protocolFilter = mkOption {
+          type = types.listOf types.str;
+          default = [ ];
+          example = [ "ospf" ];
+          description = "Information displayed in bgpmap.";
+        };
+
+        nameFilter = mkOption {
+          type = types.str;
+          default = "";
+          example = "^ospf";
+          description = "Protocol names to hide in summary tables (RE2 syntax),";
+        };
+
+        timeout = mkOption {
+          type = types.int;
+          default = 120;
+          description = "Time before request timed out, in seconds.";
+        };
+
+        navbar = {
+          brand = mkOption {
+            type = types.str;
+            default = "Bird-lg Go";
+            description = "Brand to show in the navigation bar .";
+          };
+
+          brandURL = mkOption {
+            type = types.str;
+            default = "/";
+            description = "URL of the brand to show in the navigation bar.";
+          };
+
+          allServers = mkOption {
+            type = types.str;
+            default = "ALL Servers";
+            description = "Text of 'All server' button in the navigation bar.";
+          };
+
+          allServersURL = mkOption {
+            type = types.str;
+            default = "all";
+            description = "URL of 'All servers' button.";
+          };
+        };
+
+        extraArgs = mkOption {
+          type = types.lines;
+          default = "";
+          description = "
+            Extra parameters documented <link xlink:href=\"https://github.com/xddxdd/bird-lg-go#frontend\">here</link>.
+          ";
+        };
+      };
+
+      proxy = {
+        enable = mkEnableOption "Bird Looking Glass Proxy";
+
+        listenAddress = mkOption {
+          type = types.str;
+          default = "127.0.0.1:8000";
+          description = "Address to listen on.";
+        };
+
+        allowedIPs = mkOption {
+          type = types.listOf types.str;
+          default = [ ];
+          example = [ "192.168.25.52" "192.168.25.53" ];
+          description = "List of IPs to allow (default all allowed).";
+        };
+
+        birdSocket = mkOption {
+          type = types.str;
+          default = "/run/bird.ctl";
+          example = "/var/run/bird/bird.ctl";
+          description = "Bird control socket path.";
+        };
+
+        traceroute = {
+          binary = mkOption {
+            type = types.str;
+            default = "${pkgs.traceroute}/bin/traceroute";
+            defaultText = literalExpression ''"''${pkgs.traceroute}/bin/traceroute"'';
+            description = "Traceroute's binary path.";
+          };
+
+          rawOutput = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Display traceroute output in raw format.";
+          };
+        };
+
+        extraArgs = mkOption {
+          type = types.lines;
+          default = "";
+          description = "
+            Extra parameters documented <link xlink:href=\"https://github.com/xddxdd/bird-lg-go#proxy\">here</link>.
+          ";
+        };
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = {
+    systemd.services = {
+      bird-lg-frontend = mkIf cfg.frontend.enable {
+        enable = true;
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        description = "Bird Looking Glass Frontend Webserver";
+        serviceConfig = {
+          Type = "simple";
+          Restart = "on-failure";
+          ProtectSystem = "full";
+          ProtectHome = "yes";
+          MemoryDenyWriteExecute = "yes";
+          User = cfg.user;
+          Group = cfg.group;
+        };
+        script = ''
+          ${cfg.package}/bin/frontend \
+            --servers ${concatStringsSep "," cfg.frontend.servers } \
+            --domain ${cfg.frontend.domain} \
+            --listen ${cfg.frontend.listenAddress} \
+            --proxy-port ${toString cfg.frontend.proxyPort} \
+            --whois ${cfg.frontend.whois} \
+            --dns-interface ${cfg.frontend.dnsInterface} \
+            --bgpmap-info ${concatStringsSep "," cfg.frontend.bgpMapInfo } \
+            --title-brand ${cfg.frontend.titleBrand} \
+            --navbar-brand ${cfg.frontend.navbar.brand} \
+            --navbar-brand-url ${cfg.frontend.navbar.brandURL} \
+            --navbar-all-servers ${cfg.frontend.navbar.allServers} \
+            --navbar-all-url ${cfg.frontend.navbar.allServersURL} \
+            --net-specific-mode ${cfg.frontend.netSpecificMode} \
+            --protocol-filter ${concatStringsSep "," cfg.frontend.protocolFilter } \
+            --name-filter ${cfg.frontend.nameFilter} \
+            --time-out ${toString cfg.frontend.timeout} \
+            ${cfg.frontend.extraArgs}
+        '';
+      };
+
+      bird-lg-proxy = mkIf cfg.proxy.enable {
+        enable = true;
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        description = "Bird Looking Glass Proxy";
+        serviceConfig = {
+          Type = "simple";
+          Restart = "on-failure";
+          ProtectSystem = "full";
+          ProtectHome = "yes";
+          MemoryDenyWriteExecute = "yes";
+          User = cfg.user;
+          Group = cfg.group;
+        };
+        script = ''
+          ${cfg.package}/bin/proxy \
+          --allowed ${concatStringsSep "," cfg.proxy.allowedIPs } \
+          --bird ${cfg.proxy.birdSocket} \
+          --listen ${cfg.proxy.listenAddress} \
+          --traceroute_bin ${cfg.proxy.traceroute.binary}
+          --traceroute_raw ${boolToString cfg.proxy.traceroute.rawOutput}
+          ${cfg.proxy.extraArgs}
+        '';
+      };
+    };
+    users = mkIf (cfg.frontend.enable || cfg.proxy.enable) {
+      groups."bird-lg" = mkIf (cfg.group == "bird-lg") { };
+      users."bird-lg" = mkIf (cfg.user == "bird-lg") {
+        description = "Bird Looking Glass user";
+        extraGroups = lib.optionals (config.services.bird2.enable) [ "bird2" ];
+        group = cfg.group;
+        isSystemUser = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix
index b41a2fd27be..256d9457d39 100644
--- a/nixos/modules/services/networking/mosquitto.nix
+++ b/nixos/modules/services/networking/mosquitto.nix
@@ -199,6 +199,7 @@ let
     allow_anonymous = 1;
     allow_zero_length_clientid = 1;
     auto_id_prefix = 1;
+    bind_interface = 1;
     cafile = 1;
     capath = 1;
     certfile = 1;
@@ -295,7 +296,7 @@ let
   };
 
   listenerAsserts = prefix: listener:
-    assertKeysValid prefix freeformListenerKeys listener.settings
+    assertKeysValid "${prefix}.settings" freeformListenerKeys listener.settings
     ++ userAsserts prefix listener.users
     ++ imap0
       (i: v: authAsserts "${prefix}.authPlugins.${toString i}" v)
@@ -397,7 +398,7 @@ let
   };
 
   bridgeAsserts = prefix: bridge:
-    assertKeysValid prefix freeformBridgeKeys bridge.settings
+    assertKeysValid "${prefix}.settings" freeformBridgeKeys bridge.settings
     ++ [ {
       assertion = length bridge.addresses > 0;
       message = "Bridge ${prefix} needs remote broker addresses";
@@ -526,7 +527,7 @@ let
 
   globalAsserts = prefix: cfg:
     flatten [
-      (assertKeysValid prefix freeformGlobalKeys cfg.settings)
+      (assertKeysValid "${prefix}.settings" freeformGlobalKeys cfg.settings)
       (imap0 (n: l: listenerAsserts "${prefix}.listener.${toString n}" l) cfg.listeners)
       (mapAttrsToList (n: b: bridgeAsserts "${prefix}.bridge.${n}" b) cfg.bridges)
     ];
@@ -629,9 +630,10 @@ in
                ]));
         RemoveIPC = true;
         RestrictAddressFamilies = [
-          "AF_UNIX"  # for sd_notify() call
+          "AF_UNIX"
           "AF_INET"
           "AF_INET6"
+          "AF_NETLINK"
         ];
         RestrictNamespaces = true;
         RestrictRealtime = true;
diff --git a/nixos/modules/services/networking/openconnect.nix b/nixos/modules/services/networking/openconnect.nix
index de4b505130e..bc873b2198b 100644
--- a/nixos/modules/services/networking/openconnect.nix
+++ b/nixos/modules/services/networking/openconnect.nix
@@ -9,6 +9,12 @@ let
   };
   interfaceOptions = {
     options = {
+      autoStart = mkOption {
+        default = true;
+        description = "Whether this VPN connection should be started automatically.";
+        type = types.bool;
+      };
+
       gateway = mkOption {
         description = "Gateway server to connect to.";
         example = "gateway.example.com";
@@ -95,7 +101,7 @@ let
     description = "OpenConnect Interface - ${name}";
     requires = [ "network-online.target" ];
     after = [ "network.target" "network-online.target" ];
-    wantedBy = [ "multi-user.target" ];
+    wantedBy = optional icfg.autoStart "multi-user.target";
 
     serviceConfig = {
       Type = "simple";
diff --git a/nixos/modules/services/networking/r53-ddns.nix b/nixos/modules/services/networking/r53-ddns.nix
new file mode 100644
index 00000000000..a8839762d53
--- /dev/null
+++ b/nixos/modules/services/networking/r53-ddns.nix
@@ -0,0 +1,72 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.r53-ddns;
+  pkg = pkgs.r53-ddns;
+in
+{
+  options = {
+    services.r53-ddns = {
+
+      enable = mkEnableOption "r53-ddyns";
+
+      interval = mkOption {
+        type = types.str;
+        default = "15min";
+        description = "How often to update the entry";
+      };
+
+      zoneID = mkOption {
+        type = types.str;
+        description = "The ID of your zone in Route53";
+      };
+
+      domain = mkOption {
+        type = types.str;
+        description = "The name of your domain in Route53";
+      };
+
+      hostname = mkOption {
+        type = types.str;
+        description = ''
+          Manually specify the hostname. Otherwise the tool will try to use the name
+          returned by the OS (Call to gethostname)
+        '';
+      };
+
+      environmentFile = mkOption {
+        type = types.str;
+        description = ''
+          File containing the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
+          in the format of an EnvironmentFile as described by systemd.exec(5)
+        '';
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.timers.r53-ddns = {
+      description = "r53-ddns timer";
+      wantedBy = [ "timers.target" ];
+      timerConfig = {
+        OnBootSec = cfg.interval;
+        OnUnitActiveSec = cfg.interval;
+      };
+    };
+
+    systemd.services.r53-ddns = {
+      description = "r53-ddns service";
+      serviceConfig = {
+        ExecStart = "${pkg}/bin/r53-ddns -zone-id ${cfg.zoneID} -domain ${cfg.domain}"
+          + lib.optionalString (cfg.hostname != null) " -hostname ${cfg.hostname}";
+        EnvironmentFile = "${cfg.environmentFile}";
+        DynamicUser = true;
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/networking/zeronet.nix b/nixos/modules/services/networking/zeronet.nix
index dd83b7facc1..8be6692561d 100644
--- a/nixos/modules/services/networking/zeronet.nix
+++ b/nixos/modules/services/networking/zeronet.nix
@@ -19,6 +19,13 @@ in with lib; {
   options.services.zeronet = {
     enable = mkEnableOption "zeronet";
 
+    package = mkOption {
+      type = types.package;
+      default = pkgs.zeronet;
+      defaultText = literalExpression "pkgs.zeronet";
+      description = "ZeroNet package to use";
+    };
+
     settings = mkOption {
       type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
       default = {};
@@ -72,7 +79,7 @@ in with lib; {
 
     systemd.services.zeronet = {
       description = "zeronet";
-      after = [ "network.target" (optionalString cfg.tor "tor.service") ];
+      after = [ "network.target" ] ++ optional cfg.tor "tor.service";
       wantedBy = [ "multi-user.target" ];
 
       serviceConfig = {
@@ -80,7 +87,7 @@ in with lib; {
         DynamicUser = true;
         StateDirectory = "zeronet";
         SupplementaryGroups = mkIf cfg.tor [ "tor" ];
-        ExecStart = "${pkgs.zeronet}/bin/zeronet --config_file ${configFile}";
+        ExecStart = "${cfg.package}/bin/zeronet --config_file ${configFile}";
       };
     };
   };
diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix
index 8f23454af9d..6383e454e76 100644
--- a/nixos/modules/services/system/localtime.nix
+++ b/nixos/modules/services/system/localtime.nix
@@ -3,30 +3,26 @@
 with lib;
 
 let
-  cfg = config.services.localtime;
+  cfg = config.services.localtimed;
 in {
   options = {
-    services.localtime = {
+    services.localtimed = {
       enable = mkOption {
         type = types.bool;
         default = false;
         description = ''
-          Enable <literal>localtime</literal>, simple daemon for keeping the system
-          timezone up-to-date based on the current location. It uses geoclue2 to
-          determine the current location and systemd-timedated to actually set
-          the timezone.
+          Enable <literal>localtimed</literal>, a simple daemon for keeping the
+          system timezone up-to-date based on the current location. It uses
+          geoclue2 to determine the current location.
         '';
       };
     };
   };
 
   config = mkIf cfg.enable {
-    services.geoclue2 = {
-      enable = true;
-      appConfig.localtime = {
-        isAllowed = true;
-        isSystem = true;
-      };
+    services.geoclue2.appConfig.localtimed = {
+      isAllowed = true;
+      isSystem = true;
     };
 
     # Install the polkit rules.
@@ -34,16 +30,6 @@ in {
     # Install the systemd unit.
     systemd.packages = [ pkgs.localtime ];
 
-    users.users.localtimed = {
-      description = "localtime daemon";
-      isSystemUser = true;
-      group = "localtimed";
-    };
-    users.groups.localtimed = {};
-
-    systemd.services.localtime = {
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig.Restart = "on-failure";
-    };
+    systemd.services.localtime.wantedBy = [ "multi-user.target" ];
   };
 }
diff --git a/nixos/modules/services/web-apps/hedgedoc.nix b/nixos/modules/services/web-apps/hedgedoc.nix
index 6a46ffbd17d..13893cbf005 100644
--- a/nixos/modules/services/web-apps/hedgedoc.nix
+++ b/nixos/modules/services/web-apps/hedgedoc.nix
@@ -197,6 +197,13 @@ in
           Whether to allow note creation by accessing a nonexistent note URL.
         '';
       };
+      requireFreeURLAuthentication = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to require authentication for FreeURL mode style note creation.
+        '';
+      };
       defaultPermission = mkOption {
         type = types.enum [ "freely" "editable" "limited" "locked" "private" ];
         default = "editable";
@@ -431,7 +438,7 @@ in
                 Minio secret key.
               '';
             };
-            endpoint = mkOption {
+            endPoint = mkOption {
               type = types.str;
               description = ''
                 Minio endpoint.
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 52287a834c9..dd2f2479f4e 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 = [ "nextcloud22" "nextcloud23" "nextcloud24" ];
+      relatedPackages = [ "nextcloud23" "nextcloud24" ];
     };
     phpPackage = mkOption {
       type = types.package;
@@ -625,7 +625,6 @@ in {
               nextcloud defined in an overlay, please set `services.nextcloud.package` to
               `pkgs.nextcloud`.
             ''
-          else if versionOlder stateVersion "21.11" then nextcloud21
           else if versionOlder stateVersion "22.05" then nextcloud22
           else nextcloud24
         );
@@ -634,8 +633,13 @@ in {
 
       services.nextcloud.phpPackage =
         if versionOlder cfg.package.version "21" then pkgs.php74
-        else if versionOlder cfg.package.version "24" then pkgs.php80
-        else pkgs.php81;
+        # FIXME: Use PHP 8.1 with Nextcloud 24 and higher, once issues like this one are fixed:
+        #
+        # https://github.com/nextcloud/twofactor_totp/issues/1192
+        #
+        # else if versionOlder cfg.package.version "24" then pkgs.php80
+        # else pkgs.php81;
+        else pkgs.php80;
     }
 
     { assertions = [
@@ -729,7 +733,7 @@ in {
               'trusted_domains' => ${writePhpArrary ([ cfg.hostName ] ++ c.extraTrustedDomains)},
               'trusted_proxies' => ${writePhpArrary (c.trustedProxies)},
               ${optionalString (c.defaultPhoneRegion != null) "'default_phone_region' => '${c.defaultPhoneRegion}',"}
-              ${optionalString (nextcloudGreaterOrEqualThan "23") "'profile.enabled' => ${boolToString cfg.globalProfiles}"}
+              ${optionalString (nextcloudGreaterOrEqualThan "23") "'profile.enabled' => ${boolToString cfg.globalProfiles},"}
               ${objectstoreConfig}
             ];
           '';
@@ -826,7 +830,7 @@ in {
             ${occ}/bin/nextcloud-occ config:system:delete trusted_domains
 
             ${optionalString (cfg.extraAppsEnable && cfg.extraApps != { }) ''
-                # Try to enable apps (don't fail when one of them cannot be enabled , eg. due to incompatible version)
+                # Try to enable apps
                 ${occ}/bin/nextcloud-occ app:enable ${concatStringsSep " " (attrNames cfg.extraApps)}
             ''}
 
diff --git a/nixos/modules/services/web-apps/peertube.nix b/nixos/modules/services/web-apps/peertube.nix
index e195e6e6e82..e6b6aa273e7 100644
--- a/nixos/modules/services/web-apps/peertube.nix
+++ b/nixos/modules/services/web-apps/peertube.nix
@@ -209,7 +209,7 @@ in {
 
       port = lib.mkOption {
         type = lib.types.nullOr lib.types.port;
-        default = if cfg.redis.createLocally && cfg.redis.enableUnixSocket then null else 6379;
+        default = if cfg.redis.createLocally && cfg.redis.enableUnixSocket then null else 31638;
         defaultText = lib.literalExpression ''
           if config.${opt.redis.createLocally} && config.${opt.redis.enableUnixSocket}
           then null
@@ -344,7 +344,7 @@ in {
           };
         };
       }
-      (lib.mkIf cfg.redis.enableUnixSocket { redis = { socket = "/run/redis/redis.sock"; }; })
+      (lib.mkIf cfg.redis.enableUnixSocket { redis = { socket = "/run/redis-peertube/redis.sock"; }; })
     ];
 
     systemd.tmpfiles.rules = [
@@ -441,13 +441,17 @@ in {
       enable = true;
     };
 
-    services.redis = lib.mkMerge [
+    services.redis.servers.peertube = lib.mkMerge [
       (lib.mkIf cfg.redis.createLocally {
         enable = true;
       })
+      (lib.mkIf (cfg.redis.createLocally && !cfg.redis.enableUnixSocket) {
+        bind = "127.0.0.1";
+        port = cfg.redis.port;
+      })
       (lib.mkIf (cfg.redis.createLocally && cfg.redis.enableUnixSocket) {
-        unixSocket = "/run/redis/redis.sock";
-        unixSocketPerm = 770;
+        unixSocket = "/run/redis-peertube/redis.sock";
+        unixSocketPerm = 660;
       })
     ];
 
@@ -465,7 +469,7 @@ in {
         };
       })
       (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package peertubeEnv peertubeCli pkgs.ffmpeg pkgs.nodejs-16_x pkgs.yarn ])
-      (lib.mkIf cfg.redis.enableUnixSocket {${config.services.peertube.user}.extraGroups = [ "redis" ];})
+      (lib.mkIf cfg.redis.enableUnixSocket {${config.services.peertube.user}.extraGroups = [ "redis-peertube" ];})
     ];
 
     users.groups = lib.optionalAttrs (cfg.group == "peertube") {
diff --git a/nixos/modules/services/web-apps/timetagger.nix b/nixos/modules/services/web-apps/timetagger.nix
deleted file mode 100644
index 373f4fcd52f..00000000000
--- a/nixos/modules/services/web-apps/timetagger.nix
+++ /dev/null
@@ -1,80 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-let
-  inherit (lib) mkEnableOption mkIf mkOption types literalExpression;
-
-  cfg = config.services.timetagger;
-in {
-
-  options = {
-    services.timetagger = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Tag your time, get the insight
-
-          <note><para>
-            This app does not do authentication.
-            You must setup authentication yourself or run it in an environment where
-            only allowed users have access.
-          </para></note>
-        '';
-      };
-
-      bindAddr = mkOption {
-        description = "Address to bind to.";
-        type = types.str;
-        default = "127.0.0.1";
-      };
-
-      port = mkOption {
-        description = "Port to bind to.";
-        type = types.port;
-        default = 8080;
-      };
-
-      package = mkOption {
-        description = ''
-          Use own package for starting timetagger web application.
-
-          The ${literalExpression ''pkgs.timetagger''} package only provides a
-          "run.py" script for the actual package
-          ${literalExpression ''pkgs.python3Packages.timetagger''}.
-
-          If you want to provide a "run.py" script for starting timetagger
-          yourself, you can do so with this option.
-          If you do so, the 'bindAddr' and 'port' options are ignored.
-        '';
-
-        default = pkgs.timetagger.override { addr = cfg.bindAddr; port = cfg.port; };
-        defaultText = literalExpression ''
-          pkgs.timetagger.override {
-            addr = ${cfg.bindAddr};
-            port = ${cfg.port};
-          };
-        '';
-        type = types.package;
-      };
-    };
-  };
-
-  config = mkIf cfg.enable {
-    systemd.services.timetagger = {
-      description = "Timetagger service";
-      wantedBy = [ "multi-user.target" ];
-
-      serviceConfig = {
-        User = "timetagger";
-        Group = "timetagger";
-        StateDirectory = "timetagger";
-
-        ExecStart = "${cfg.package}/bin/timetagger";
-
-        Restart = "on-failure";
-        RestartSec = 1;
-      };
-    };
-  };
-}
-
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 0c2333399e8..160d76597c8 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -932,7 +932,7 @@ in
         # System Call Filtering
         SystemCallArchitectures = "native";
         SystemCallFilter = [ "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid" ]
-          ++ optionals ((cfg.package != pkgs.tengine) && (!lib.any (mod: (mod.disableIPC or false)) cfg.package.modules)) [ "~@ipc" ];
+          ++ optionals ((cfg.package != pkgs.tengine) && (cfg.package != pkgs.openresty) && (!lib.any (mod: (mod.disableIPC or false)) cfg.package.modules)) [ "~@ipc" ];
       };
     };
 
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 8983bc5d758..083b12193da 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -291,6 +291,7 @@ in
         # Only install appcenter if flatpak is enabled before
         # https://github.com/NixOS/nixpkgs/issues/15932 is resolved.
         appcenter
+        sideload
       ])) config.environment.pantheon.excludePackages;
 
       # needed by screenshot
diff --git a/nixos/modules/services/x11/desktop-managers/phosh.nix b/nixos/modules/services/x11/desktop-managers/phosh.nix
index 4bf78fa16e7..5efe645d8aa 100644
--- a/nixos/modules/services/x11/desktop-managers/phosh.nix
+++ b/nixos/modules/services/x11/desktop-managers/phosh.nix
@@ -78,7 +78,13 @@ let
         description = ''
           Display scaling factor.
         '';
-        type = types.nullOr types.ints.unsigned;
+        type = types.nullOr (
+          types.addCheck
+          (types.either types.int types.float)
+          (x : x > 0)
+        ) // {
+          description = "null or positive integer or float";
+        };
         default = null;
         example = 2;
       };
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index fa879437fd8..aca6a1ca2cc 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -204,7 +204,6 @@ def get_profiles() -> List[str]:
     else:
         return []
 
-
 def main() -> None:
     parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files')
     parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default NixOS config to boot')
@@ -244,27 +243,29 @@ def main() -> None:
         subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@"] + flags + ["install"])
     else:
         # Update bootloader to latest if needed
-        systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2]
-        sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True)
+        available_out = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[2]
+        installed_out = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True)
 
         # See status_binaries() in systemd bootctl.c for code which generates this
-        m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$",
-                      sdboot_status, re.IGNORECASE | re.MULTILINE)
+        installed_match = re.search(r"^\W+File:.*/EFI/(?:BOOT|systemd)/.*\.efi \(systemd-boot ([\d.]+[^)]*)\)$",
+                      installed_out, re.IGNORECASE | re.MULTILINE)
 
-        needs_install = False
+        available_match = re.search(r"^\((.*)\)$", available_out)
 
-        if m is None:
-            print("could not find any previously installed systemd-boot, installing.")
-            # Let systemd-boot attempt an installation if a previous one wasn't found
-            needs_install = True
-        else:
-            sdboot_version = f'({m.group(2)})'
-            if systemd_version != sdboot_version:
-                print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version))
-                needs_install = True
+        if installed_match is None:
+            raise Exception("could not find any previously installed systemd-boot")
+
+        if available_match is None:
+            raise Exception("could not determine systemd-boot version")
 
-        if needs_install:
+        installed_version = installed_match.group(1)
+        available_version = available_match.group(1)
+
+        if installed_version < available_version:
+            print("updating systemd-boot from %s to %s" % (installed_version, available_version))
             subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"])
+        else:
+            print("leaving systemd-boot %s in place (%s is not newer)" % (installed_version, available_version))
 
     mkdir_p("@efiSysMountPoint@/efi/nixos")
     mkdir_p("@efiSysMountPoint@/loader/entries")
diff --git a/nixos/modules/system/boot/plymouth.nix b/nixos/modules/system/boot/plymouth.nix
index 8b57cae3c40..59037d4e6b4 100644
--- a/nixos/modules/system/boot/plymouth.nix
+++ b/nixos/modules/system/boot/plymouth.nix
@@ -282,18 +282,18 @@ in
       EOF
     '';
 
-    boot.initrd.extraUtilsCommandsTest = mkIf (!config.boot.initrd.enable) ''
+    boot.initrd.extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) ''
       $out/bin/plymouthd --help >/dev/null
       $out/bin/plymouth --help >/dev/null
     '';
 
-    boot.initrd.extraUdevRulesCommands = mkIf (!config.boot.initrd.enable) ''
+    boot.initrd.extraUdevRulesCommands = mkIf (!config.boot.initrd.systemd.enable) ''
       cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out
       sed -i '/loginctl/d' $out/71-seat.rules
     '';
 
     # We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen.
-    boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.enable) (mkAfter ''
+    boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.systemd.enable) (mkAfter ''
       mkdir -p /etc/plymouth
       mkdir -p /run/plymouth
       ln -s ${configFile} /etc/plymouth/plymouthd.conf
@@ -307,12 +307,12 @@ in
       plymouth show-splash
     '');
 
-    boot.initrd.postMountCommands = mkIf (!config.boot.initrd.enable) ''
+    boot.initrd.postMountCommands = mkIf (!config.boot.initrd.systemd.enable) ''
       plymouth update-root-fs --new-root-dir="$targetRoot"
     '';
 
     # `mkBefore` to ensure that any custom prompts would be visible.
-    boot.initrd.preFailCommands = mkIf (!config.boot.initrd.enable) (mkBefore ''
+    boot.initrd.preFailCommands = mkIf (!config.boot.initrd.systemd.enable) (mkBefore ''
       plymouth quit --wait
     '');
 
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 22d5ec76af7..337064034ef 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -14,6 +14,8 @@ extraUtils="@extraUtils@"
 export LD_LIBRARY_PATH=@extraUtils@/lib
 export PATH=@extraUtils@/bin
 ln -s @extraUtils@/bin /bin
+# hardcoded in util-linux's mount helper search path `/run/wrappers/bin:/run/current-system/sw/bin:/sbin`
+ln -s @extraUtils@/bin /sbin
 
 # Copy the secrets to their needed location
 if [ -d "@extraUtils@/secrets" ]; then
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index d10ebac5682..e35ccff2907 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -31,6 +31,9 @@ let
   # mounting `/`, like `/` on a loopback).
   fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems;
 
+  # Determine whether zfs-mount(8) is needed.
+  zfsRequiresMountHelper = any (fs: lib.elem "zfsutil" fs.options) fileSystems;
+
   # A utility for enumerating the shared-library dependencies of a program
   findLibs = pkgs.buildPackages.writeShellScriptBin "find-libs" ''
     set -euo pipefail
@@ -107,6 +110,22 @@ let
         copy_bin_and_libs $BIN
       done
 
+      ${optionalString zfsRequiresMountHelper ''
+        # Filesystems using the "zfsutil" option are mounted regardless of the
+        # mount.zfs(8) helper, but it is required to ensure that ZFS properties
+        # are used as mount options.
+        #
+        # BusyBox does not use the ZFS helper in the first place.
+        # util-linux searches /sbin/ as last path for helpers (stage-1-init.sh
+        # must symlink it to the store PATH).
+        # Without helper program, both `mount`s silently fails back to internal
+        # code, using default options and effectively ignore security relevant
+        # ZFS properties such as `setuid=off` and `exec=off` (unless manually
+        # duplicated in `fileSystems.*.options`, defeating "zfsutil"'s purpose).
+        copy_bin_and_libs ${pkgs.util-linux}/bin/mount
+        copy_bin_and_libs ${pkgs.zfs}/bin/mount.zfs
+      ''}
+
       # Copy some util-linux stuff.
       copy_bin_and_libs ${pkgs.util-linux}/sbin/blkid
 
@@ -204,24 +223,29 @@ let
 
       # Run patchelf to make the programs refer to the copied libraries.
       find $out/bin $out/lib -type f | while read i; do
-        if ! test -L $i; then
-          nuke-refs -e $out $i
-        fi
+        nuke-refs -e $out $i
       done
 
       find $out/bin -type f | while read i; do
-        if ! test -L $i; then
-          echo "patching $i..."
-          patchelf --set-interpreter $out/lib/ld*.so.? --set-rpath $out/lib $i || true
-        fi
+        echo "patching $i..."
+        patchelf --set-interpreter $out/lib/ld*.so.? --set-rpath $out/lib $i || true
+      done
+
+      find $out/lib -type f \! -name 'ld*.so.?' | while read i; do
+        echo "patching $i..."
+        patchelf --set-rpath $out/lib $i
       done
 
       if [ -z "${toString (pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform)}" ]; then
       # Make sure that the patchelf'ed binaries still work.
       echo "testing patched programs..."
       $out/bin/ash -c 'echo hello world' | grep "hello world"
-      export LD_LIBRARY_PATH=$out/lib
-      $out/bin/mount --help 2>&1 | grep -q "BusyBox"
+      ${if zfsRequiresMountHelper then ''
+        $out/bin/mount -V 1>&1 | grep -q "mount from util-linux"
+        $out/bin/mount.zfs -h 2>&1 | grep -q "Usage: mount.zfs"
+      '' else ''
+        $out/bin/mount --help 2>&1 | grep -q "BusyBox"
+      ''}
       $out/bin/blkid -V 2>&1 | grep -q 'libblkid'
       $out/bin/udevadm --version
       $out/bin/dmsetup --version 2>&1 | tee -a log | grep -q "version:"
@@ -260,8 +284,6 @@ let
     } ''
       mkdir -p $out
 
-      echo 'ENV{LD_LIBRARY_PATH}="${extraUtils}/lib"' > $out/00-env.rules
-
       cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/
       cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
       cp -v ${udev}/lib/udev/rules.d/75-net-description.rules $out/
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 2c9ee9fc319..679c5210a6b 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -35,11 +35,11 @@ let
       "nss-lookup.target"
       "nss-user-lookup.target"
       "time-sync.target"
-    ] ++ (optionals cfg.package.withCryptsetup [
+    ] ++ optionals cfg.package.withCryptsetup [
       "cryptsetup.target"
       "cryptsetup-pre.target"
       "remote-cryptsetup.target"
-    ]) ++ [
+    ] ++ [
       "sigpwr.target"
       "timers.target"
       "paths.target"
@@ -133,20 +133,27 @@ let
 
       # Slices / containers.
       "slices.target"
+    ] ++ optionals cfg.package.withImportd [
+      "systemd-importd.service"
+    ] ++ optionals cfg.package.withMachined [
       "machine.slice"
       "machines.target"
-      "systemd-importd.service"
       "systemd-machined.service"
+    ] ++ [
       "systemd-nspawn@.service"
 
       # Misc.
       "systemd-sysctl.service"
+    ] ++ optionals cfg.package.withTimedated [
       "dbus-org.freedesktop.timedate1.service"
-      "dbus-org.freedesktop.locale1.service"
-      "dbus-org.freedesktop.hostname1.service"
       "systemd-timedated.service"
+    ] ++ optionals cfg.package.withLocaled [
+      "dbus-org.freedesktop.locale1.service"
       "systemd-localed.service"
+    ] ++ optionals cfg.package.withHostnamed [
+      "dbus-org.freedesktop.hostname1.service"
       "systemd-hostnamed.service"
+    ] ++ [
       "systemd-exit.service"
       "systemd-update-done.service"
     ] ++ cfg.additionalUpstreamSystemUnits;
diff --git a/nixos/modules/system/boot/systemd/logind.nix b/nixos/modules/system/boot/systemd/logind.nix
index c1e6cfe61d0..97ac588bce1 100644
--- a/nixos/modules/system/boot/systemd/logind.nix
+++ b/nixos/modules/system/boot/systemd/logind.nix
@@ -81,8 +81,11 @@ in
       "systemd-logind.service"
       "autovt@.service"
       "systemd-user-sessions.service"
+    ] ++ optionals config.systemd.package.withImportd [
       "dbus-org.freedesktop.import1.service"
+    ] ++ optionals config.systemd.package.withMachined [
       "dbus-org.freedesktop.machine1.service"
+    ] ++ [
       "dbus-org.freedesktop.login1.service"
       "user@.service"
       "user-runtime-dir@.service"
diff --git a/nixos/modules/virtualisation/appvm.nix b/nixos/modules/virtualisation/appvm.nix
new file mode 100644
index 00000000000..24315a85d0e
--- /dev/null
+++ b/nixos/modules/virtualisation/appvm.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.virtualisation.appvm;
+
+in {
+
+  options = {
+    virtualisation.appvm = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          This enables AppVMs and related virtualisation settings.
+        '';
+      };
+      user = mkOption {
+        type = types.str;
+        description = ''
+          AppVM user login. Currenly only AppVMs are supported for a single user only.
+        '';
+      };
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+    virtualisation.libvirtd = {
+      enable = true;
+      qemu.verbatimConfig = ''
+        namespaces = []
+        user = "${cfg.user}"
+        group = "users"
+        remember_owner = 0
+      '';
+    };
+
+    users.users."${cfg.user}" = {
+      packages = [ pkgs.appvm ];
+      extraGroups = [ "libvirtd" ];
+    };
+
+  };
+
+}
+
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index e0bccb83a97..31d18ae7344 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -11,10 +11,9 @@ let
     auth_unix_rw = "polkit"
     ${cfg.extraConfig}
   '';
-  ovmfFilePrefix = if pkgs.stdenv.isAarch64 then "AAVMF" else "OVMF";
   qemuConfigFile = pkgs.writeText "qemu.conf" ''
     ${optionalString cfg.qemu.ovmf.enable ''
-      nvram = [ "/run/libvirt/nix-ovmf/${ovmfFilePrefix}_CODE.fd:/run/libvirt/nix-ovmf/${ovmfFilePrefix}_VARS.fd" ]
+      nvram = [ "/run/libvirt/nix-ovmf/AAVMF_CODE.fd:/run/libvirt/nix-ovmf/AAVMF_VARS.fd", "/run/libvirt/nix-ovmf/OVMF_CODE.fd:/run/libvirt/nix-ovmf/OVMF_VARS.fd" ]
     ''}
     ${optionalString (!cfg.qemu.runAsRoot) ''
       user = "qemu-libvirtd"
@@ -36,13 +35,20 @@ let
         '';
       };
 
+      # mkRemovedOptionModule does not work in submodules, do it manually
       package = mkOption {
-        type = types.package;
-        default = pkgs.OVMF;
-        defaultText = literalExpression "pkgs.OVMF";
-        example = literalExpression "pkgs.OVMFFull";
+        type = types.nullOr types.package;
+        default = null;
+        internal = true;
+      };
+
+      packages = mkOption {
+        type = types.listOf types.package;
+        default = [ pkgs.OVMF.fd ];
+        defaultText = literalExpression "[ pkgs.OVMF.fd ]";
+        example = literalExpression "[ pkgs.OVMFFull.fd pkgs.pkgsCross.aarch64-multiplatform.OVMF.fd ]";
         description = ''
-          OVMF package to use.
+          List of OVMF packages to use. Each listed package must contain files names FV/OVMF_CODE.fd and FV/OVMF_VARS.fd or FV/AAVMF_CODE.fd and FV/AAVMF_VARS.fd
         '';
       };
     };
@@ -141,9 +147,9 @@ in
     (mkRenamedOptionModule
       [ "virtualisation" "libvirtd" "qemuOvmf" ]
       [ "virtualisation" "libvirtd" "qemu" "ovmf" "enable" ])
-    (mkRenamedOptionModule
+    (mkRemovedOptionModule
       [ "virtualisation" "libvirtd" "qemuOvmfPackage" ]
-      [ "virtualisation" "libvirtd" "qemu" "ovmf" "package" ])
+      "If this option was set to `foo`, set the option `virtualisation.libvirtd.qemu.ovmf.packages' to `[foo.fd]` instead.")
     (mkRenamedOptionModule
       [ "virtualisation" "libvirtd" "qemuSwtpm" ]
       [ "virtualisation" "libvirtd" "qemu" "swtpm" "enable" ])
@@ -238,12 +244,15 @@ in
 
     assertions = [
       {
-        assertion = config.security.polkit.enable;
-        message = "The libvirtd module currently requires Polkit to be enabled ('security.polkit.enable = true').";
+        assertion = config.virtualisation.libvirtd.qemu.ovmf.package == null;
+        message = ''
+        The option virtualisation.libvirtd.qemu.ovmf.package is superseded by virtualisation.libvirtd.qemu.ovmf.packages.
+        If this option was set to `foo`, set the option `virtualisation.libvirtd.qemu.ovmf.packages' to `[foo.fd]` instead.
+        '';
       }
       {
-        assertion = builtins.elem "fd" cfg.qemu.ovmf.package.outputs;
-        message = "The option 'virtualisation.libvirtd.qemuOvmfPackage' needs a package that has an 'fd' output.";
+        assertion = config.security.polkit.enable;
+        message = "The libvirtd module currently requires Polkit to be enabled ('security.polkit.enable = true').";
       }
     ];
 
@@ -303,10 +312,18 @@ in
           ln -s --force ${cfg.qemu.package}/$helper /run/${dirName}/nix-helpers/
         done
 
-        ${optionalString cfg.qemu.ovmf.enable ''
-          ln -s --force ${cfg.qemu.ovmf.package.fd}/FV/${ovmfFilePrefix}_CODE.fd /run/${dirName}/nix-ovmf/
-          ln -s --force ${cfg.qemu.ovmf.package.fd}/FV/${ovmfFilePrefix}_VARS.fd /run/${dirName}/nix-ovmf/
-        ''}
+        ${optionalString cfg.qemu.ovmf.enable (let
+          ovmfpackage = pkgs.buildEnv {
+            name = "qemu-ovmf";
+            paths = cfg.qemu.ovmf.packages;
+          };
+        in
+          ''
+          ln -s --force ${ovmfpackage}/FV/AAVMF_CODE.fd /run/${dirName}/nix-ovmf/
+          ln -s --force ${ovmfpackage}/FV/OVMF_CODE.fd /run/${dirName}/nix-ovmf/
+          ln -s --force ${ovmfpackage}/FV/AAVMF_VARS.fd /run/${dirName}/nix-ovmf/
+          ln -s --force ${ovmfpackage}/FV/OVMF_VARS.fd /run/${dirName}/nix-ovmf/
+        '')}
       '';
 
       serviceConfig = {
diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix
index 23228a109bc..b9301515712 100644
--- a/nixos/modules/virtualisation/nixos-containers.nix
+++ b/nixos/modules/virtualisation/nixos-containers.nix
@@ -284,7 +284,7 @@ let
     DeviceAllow = map (d: "${d.node} ${d.modifier}") cfg.allowedDevices;
   };
 
-  system = config.nixpkgs.localSystem.system;
+  inherit (config.nixpkgs) localSystem;
   kernelVersion = config.boot.kernelPackages.kernel.version;
 
   bindMountOpts = { name, ... }: {
@@ -478,12 +478,12 @@ in
               type = lib.mkOptionType {
                 name = "Toplevel NixOS config";
                 merge = loc: defs: (import "${toString config.nixpkgs}/nixos/lib/eval-config.nix" {
-                  inherit system;
                   modules =
                     let
                       extraConfig = {
                         _file = "module at ${__curPos.file}:${toString __curPos.line}";
                         config = {
+                          nixpkgs = { inherit localSystem; };
                           boot.isContainer = true;
                           networking.hostName = mkDefault name;
                           networking.useDHCP = false;
diff --git a/nixos/modules/virtualisation/vmware-guest.nix b/nixos/modules/virtualisation/vmware-guest.nix
index 3caed746ca9..d468a200872 100644
--- a/nixos/modules/virtualisation/vmware-guest.nix
+++ b/nixos/modules/virtualisation/vmware-guest.nix
@@ -64,7 +64,6 @@ in
     environment.etc.vmware-tools.source = "${open-vm-tools}/etc/vmware-tools/*";
 
     services.xserver = mkIf (!cfg.headless) {
-      videoDrivers = mkOverride 50 [ "vmware" ];
       modules = [ xf86inputvmmouse ];
 
       config = ''
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index e86dda9cb3d..e61798676a0 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -62,6 +62,7 @@ in
   breitbandmessung = handleTest ./breitbandmessung.nix {};
   brscan5 = handleTest ./brscan5.nix {};
   btrbk = handleTest ./btrbk.nix {};
+  btrbk-no-timer = handleTest ./btrbk-no-timer.nix {};
   buildbot = handleTest ./buildbot.nix {};
   buildkite-agents = handleTest ./buildkite-agents.nix {};
   caddy = handleTest ./caddy.nix {};
@@ -169,6 +170,7 @@ in
   frr = handleTest ./frr.nix {};
   fsck = handleTest ./fsck.nix {};
   ft2-clone = handleTest ./ft2-clone.nix {};
+  grafana-mimir = handleTest ./grafana-mimir.nix {};
   gerrit = handleTest ./gerrit.nix {};
   geth = handleTest ./geth.nix {};
   ghostunnel = handleTest ./ghostunnel.nix {};
@@ -364,6 +366,7 @@ in
   nginx = handleTest ./nginx.nix {};
   nginx-auth = handleTest ./nginx-auth.nix {};
   nginx-etag = handleTest ./nginx-etag.nix {};
+  nginx-http3 = handleTest ./nginx-http3.nix {};
   nginx-modsecurity = handleTest ./nginx-modsecurity.nix {};
   nginx-pubhtml = handleTest ./nginx-pubhtml.nix {};
   nginx-sandbox = handleTestOn ["x86_64-linux"] ./nginx-sandbox.nix {};
@@ -578,6 +581,7 @@ in
   uptermd = handleTest ./uptermd.nix {};
   usbguard = handleTest ./usbguard.nix {};
   user-activation-scripts = handleTest ./user-activation-scripts.nix {};
+  user-home-mode = handleTest ./user-home-mode.nix {};
   uwsgi = handleTest ./uwsgi.nix {};
   v2ray = handleTest ./v2ray.nix {};
   vault = handleTest ./vault.nix {};
diff --git a/nixos/tests/btrbk-no-timer.nix b/nixos/tests/btrbk-no-timer.nix
new file mode 100644
index 00000000000..4fcab8839c8
--- /dev/null
+++ b/nixos/tests/btrbk-no-timer.nix
@@ -0,0 +1,37 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }:
+  {
+    name = "btrbk-no-timer";
+    meta.maintainers = with lib.maintainers; [ oxalica ];
+
+    nodes.machine = { ... }: {
+      environment.systemPackages = with pkgs; [ btrfs-progs ];
+      services.btrbk.instances.local = {
+        onCalendar = null;
+        settings.volume."/mnt" = {
+          snapshot_dir = "btrbk/local";
+          subvolume = "to_backup";
+        };
+      };
+    };
+
+    testScript = ''
+      start_all()
+
+      # Create btrfs partition at /mnt
+      machine.succeed("truncate --size=128M /data_fs")
+      machine.succeed("mkfs.btrfs /data_fs")
+      machine.succeed("mkdir /mnt")
+      machine.succeed("mount /data_fs /mnt")
+      machine.succeed("btrfs subvolume create /mnt/to_backup")
+      machine.succeed("mkdir -p /mnt/btrbk/local")
+
+      # The service should not have any triggering timer.
+      unit = machine.get_unit_info('btrbk-local.service')
+      assert "TriggeredBy" not in unit
+
+      # Manually starting the service should still work.
+      machine.succeed("echo foo > /mnt/to_backup/bar")
+      machine.start_job("btrbk-local.service")
+      machine.wait_until_succeeds("cat /mnt/btrbk/local/*/bar | grep foo")
+    '';
+  })
diff --git a/nixos/tests/containers-imperative.nix b/nixos/tests/containers-imperative.nix
index a21ce97a23b..3007efaf887 100644
--- a/nixos/tests/containers-imperative.nix
+++ b/nixos/tests/containers-imperative.nix
@@ -18,8 +18,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
       # container available within the VM, because we don't have network access.
       virtualisation.additionalPaths = let
         emptyContainer = import ../lib/eval-config.nix {
-          inherit (config.nixpkgs.localSystem) system;
           modules = lib.singleton {
+            nixpkgs = { inherit (config.nixpkgs) localSystem; };
+
             containers.foo.config = {
               system.stateVersion = "18.03";
             };
diff --git a/nixos/tests/custom-ca.nix b/nixos/tests/custom-ca.nix
index 8e91bd3eead..73e47c3c9d0 100644
--- a/nixos/tests/custom-ca.nix
+++ b/nixos/tests/custom-ca.nix
@@ -11,6 +11,8 @@
 with import ../lib/testing-python.nix { inherit system pkgs; };
 
 let
+  inherit (pkgs) lib;
+
   makeCert = { caName, domain }: pkgs.runCommand "example-cert"
   { buildInputs = [ pkgs.gnutls ]; }
   ''
diff --git a/nixos/tests/dendrite.nix b/nixos/tests/dendrite.nix
index d4a5bb13226..1ff415433b4 100644
--- a/nixos/tests/dendrite.nix
+++ b/nixos/tests/dendrite.nix
@@ -17,10 +17,11 @@ import ./make-test-python.nix (
           homeserver = { pkgs, ... }: {
             services.dendrite = {
               enable = true;
+              loadCredential = [ "test_private_key:${private_key}" ];
               openRegistration = true;
               settings = {
                 global.server_name = "test-dendrite-server.com";
-                global.private_key = private_key;
+                global.private_key = "$CREDENTIALS_DIRECTORY/test_private_key";
                 client_api.registration_disabled = false;
               };
             };
diff --git a/nixos/tests/ecryptfs.nix b/nixos/tests/ecryptfs.nix
index e3cfb2ed998..1c67d307a00 100644
--- a/nixos/tests/ecryptfs.nix
+++ b/nixos/tests/ecryptfs.nix
@@ -11,16 +11,16 @@ import ./make-test-python.nix ({ ... }:
 
   testScript = ''
     def login_as_alice():
-        machine.wait_until_tty_matches(1, "login: ")
+        machine.wait_until_tty_matches("1", "login: ")
         machine.send_chars("alice\n")
-        machine.wait_until_tty_matches(1, "Password: ")
+        machine.wait_until_tty_matches("1", "Password: ")
         machine.send_chars("foobar\n")
-        machine.wait_until_tty_matches(1, "alice\@machine")
+        machine.wait_until_tty_matches("1", "alice\@machine")
 
 
     def logout():
         machine.send_chars("logout\n")
-        machine.wait_until_tty_matches(1, "login: ")
+        machine.wait_until_tty_matches("1", "login: ")
 
 
     machine.wait_for_unit("default.target")
@@ -36,7 +36,7 @@ import ./make-test-python.nix ({ ... }:
     with subtest("Log alice in (ecryptfs passwhrase is wrapped during first login)"):
         login_as_alice()
         machine.send_chars("logout\n")
-        machine.wait_until_tty_matches(1, "login: ")
+        machine.wait_until_tty_matches("1", "login: ")
 
     # Why do I need to do this??
     machine.succeed("su alice -c ecryptfs-umount-private || true")
diff --git a/nixos/tests/gitolite.nix b/nixos/tests/gitolite.nix
index 128677cebde..9b3af59e4fb 100644
--- a/nixos/tests/gitolite.nix
+++ b/nixos/tests/gitolite.nix
@@ -107,7 +107,7 @@ in
     with subtest("gitolite server starts"):
         server.wait_for_unit("gitolite-init.service")
         server.wait_for_unit("sshd.service")
-        client.succeed("ssh gitolite@server info")
+        client.succeed("ssh -n gitolite@server info")
 
     with subtest("admin can clone and configure gitolite-admin.git"):
         client.succeed(
diff --git a/nixos/tests/grafana-mimir.nix b/nixos/tests/grafana-mimir.nix
new file mode 100644
index 00000000000..0aafa956f0b
--- /dev/null
+++ b/nixos/tests/grafana-mimir.nix
@@ -0,0 +1,50 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "grafana-mimir";
+  nodes = {
+    server = { ... }: {
+      environment.systemPackages = [ pkgs.jq ];
+      services.mimir.enable = true;
+      services.mimir.configuration = {
+        ingester.ring.replication_factor = 1;
+      };
+
+      services.telegraf.enable = true;
+      services.telegraf.extraConfig = {
+        agent.interval = "1s";
+        agent.flush_interval = "1s";
+        inputs.exec = {
+          commands = [
+            "${pkgs.coreutils}/bin/echo 'foo i=42i'"
+          ];
+          data_format = "influx";
+        };
+        outputs = {
+          http = {
+            # test remote write
+            url = "http://localhost:8080/api/v1/push";
+
+            # Data format to output.
+            data_format = "prometheusremotewrite";
+
+            headers = {
+              Content-Type = "application/x-protobuf";
+              Content-Encoding = "snappy";
+              X-Scope-OrgID = "nixos";
+              X-Prometheus-Remote-Write-Version = "0.1.0";
+            };
+          };
+        };
+      };
+    };
+  };
+
+  testScript = ''
+    start_all()
+    server.wait_for_unit("mimir.service")
+    server.wait_for_unit("telegraf.service")
+    server.wait_for_open_port(8080)
+    server.wait_until_succeeds(
+        "curl -H 'X-Scope-OrgID: nixos' http://127.0.0.1:8080/prometheus/api/v1/label/host/values | jq -r '.data[0]' | grep server"
+    )
+  '';
+})
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
index 10f9cb05c9c..f7b9d283e45 100644
--- a/nixos/tests/home-assistant.nix
+++ b/nixos/tests/home-assistant.nix
@@ -111,6 +111,7 @@ in {
     pattern = re.compile(r"path=(?P<path>[\/a-z0-9-.]+)\/bin\/hass")
     response = hass.execute("systemctl show -p ExecStart home-assistant.service")[1]
     match = pattern.search(response)
+    assert match
     package = match.group('path')
 
     hass.wait_for_unit("home-assistant.service")
diff --git a/nixos/tests/libreddit.nix b/nixos/tests/libreddit.nix
index f7ef701d086..01f6aeffb36 100644
--- a/nixos/tests/libreddit.nix
+++ b/nixos/tests/libreddit.nix
@@ -6,14 +6,16 @@ with lib;
   name = "libreddit";
   meta.maintainers = with maintainers; [ fab ];
 
-  nodes.machine =
-    { pkgs, ... }:
-    { services.libreddit.enable = true; };
+  nodes.machine = {
+    services.libreddit.enable = true;
+    # Test CAP_NET_BIND_SERVICE
+    services.libreddit.port = 80;
+  };
 
   testScript = ''
     machine.wait_for_unit("libreddit.service")
-    machine.wait_for_open_port("8080")
-    # The service wants to get data from https://www.reddit.com
-    machine.succeed("curl http://localhost:8080/")
+    machine.wait_for_open_port("80")
+    # Query a page that does not require Internet access
+    machine.succeed("curl --fail http://localhost:80/settings")
   '';
 })
diff --git a/nixos/tests/login.nix b/nixos/tests/login.nix
index 0d6f81b1721..2cff38d2005 100644
--- a/nixos/tests/login.nix
+++ b/nixos/tests/login.nix
@@ -29,11 +29,11 @@ import ./make-test-python.nix ({ pkgs, latestKernel ? false, ... }:
           machine.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
 
       with subtest("Log in as alice on a virtual console"):
-          machine.wait_until_tty_matches(2, "login: ")
+          machine.wait_until_tty_matches("2", "login: ")
           machine.send_chars("alice\n")
-          machine.wait_until_tty_matches(2, "login: alice")
+          machine.wait_until_tty_matches("2", "login: alice")
           machine.wait_until_succeeds("pgrep login")
-          machine.wait_until_tty_matches(2, "Password: ")
+          machine.wait_until_tty_matches("2", "Password: ")
           machine.send_chars("foobar\n")
           machine.wait_until_succeeds("pgrep -u alice bash")
           machine.send_chars("touch done\n")
diff --git a/nixos/tests/matrix/mjolnir.nix b/nixos/tests/matrix/mjolnir.nix
index 54094ab9d61..3864f0ff2bb 100644
--- a/nixos/tests/matrix/mjolnir.nix
+++ b/nixos/tests/matrix/mjolnir.nix
@@ -43,7 +43,9 @@ import ../make-test-python.nix (
             tls_certificate_path = "${cert}";
             tls_private_key_path = "${key}";
             enable_registration = true;
+            enable_registration_without_verification = true;
             registration_shared_secret = "supersecret-registration";
+            enable_registration_without_verification = true;
 
             listeners = [ {
               # The default but tls=false
diff --git a/nixos/tests/meilisearch.nix b/nixos/tests/meilisearch.nix
index 9f54aa97d6a..05109a944bc 100644
--- a/nixos/tests/meilisearch.nix
+++ b/nixos/tests/meilisearch.nix
@@ -5,9 +5,10 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
     apiUrl = "http://${listenAddress}:${toString listenPort}";
     uid = "movies";
     indexJSON = pkgs.writeText "index.json" (builtins.toJSON { inherit uid; });
-    moviesJSON = pkgs.runCommand "movies.json" {} ''
-      sed -n '1,5p;$p' ${pkgs.meilisearch.src}/datasets/movies/movies.json > $out
-    '';
+    moviesJSON = pkgs.fetchurl {
+      url = "https://github.com/meilisearch/meilisearch/raw/v0.23.1/datasets/movies/movies.json";
+      sha256 = "1r3srld63dpmg9yrmysm6xl175661j5cspi93mk5q2wf8xwn50c5";
+    };
   in {
     name = "meilisearch";
     meta.maintainers = with lib.maintainers; [ Br1ght0ne ];
@@ -34,7 +35,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
 
       with subtest("create index"):
           machine.succeed(
-              "curl -XPOST ${apiUrl}/indexes --data @${indexJSON}"
+              "curl -XPOST --header 'Content-Type: application/json' ${apiUrl}/indexes --data @${indexJSON}"
           )
           indexes = json.loads(machine.succeed("curl ${apiUrl}/indexes"))
           assert len(indexes) == 1, "index wasn't created"
@@ -42,7 +43,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
       with subtest("add documents"):
           response = json.loads(
               machine.succeed(
-                  "curl -XPOST ${apiUrl}/indexes/${uid}/documents --data @${moviesJSON}"
+                  "curl -XPOST --header 'Content-Type: application/json' ${apiUrl}/indexes/${uid}/documents --data @${moviesJSON}"
               )
           )
           update_id = response["updateId"]
diff --git a/nixos/tests/mosquitto.nix b/nixos/tests/mosquitto.nix
index 36cc8e3e3d9..d516d3373d9 100644
--- a/nixos/tests/mosquitto.nix
+++ b/nixos/tests/mosquitto.nix
@@ -4,6 +4,7 @@ let
   port = 1888;
   tlsPort = 1889;
   anonPort = 1890;
+  bindTestPort = 1891;
   password = "VERY_secret";
   hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw==";
   topic = "test/foo";
@@ -125,6 +126,10 @@ in {
               };
             };
           }
+          {
+            settings.bind_interface = "eth0";
+            port = bindTestPort;
+          }
         ];
       };
     };
@@ -134,6 +139,8 @@ in {
   };
 
   testScript = ''
+    import json
+
     def mosquitto_cmd(binary, user, topic, port):
         return (
             "mosquitto_{} "
@@ -162,6 +169,27 @@ in {
     start_all()
     server.wait_for_unit("mosquitto.service")
 
+    with subtest("bind_interface"):
+        addrs = dict()
+        for iface in json.loads(server.succeed("ip -json address show")):
+            for addr in iface['addr_info']:
+                # don't want to deal with multihoming here
+                assert addr['local'] not in addrs
+                addrs[addr['local']] = (iface['ifname'], addr['family'])
+
+        # mosquitto grabs *one* random address per type for bind_interface
+        (has4, has6) = (False, False)
+        for line in server.succeed("ss -HlptnO sport = ${toString bindTestPort}").splitlines():
+            items = line.split()
+            if "mosquitto" not in items[5]: continue
+            listener = items[3].rsplit(':', maxsplit=1)[0].strip('[]')
+            assert listener in addrs
+            assert addrs[listener][0] == "eth0"
+            has4 |= addrs[listener][1] == 'inet'
+            has6 |= addrs[listener][1] == 'inet6'
+        assert has4
+        assert has6
+
     with subtest("check passwords"):
         client1.succeed(publish("-m test", "password_store"))
         client1.succeed(publish("-m test", "password_file"))
diff --git a/nixos/tests/mysql/mysql-backup.nix b/nixos/tests/mysql/mysql-backup.nix
index 9335b233327..968f56dd3c9 100644
--- a/nixos/tests/mysql/mysql-backup.nix
+++ b/nixos/tests/mysql/mysql-backup.nix
@@ -51,7 +51,6 @@ let
 
       # Do a backup and wait for it to start
       master.start_job("mysql-backup.service")
-      master.wait_for_unit("mysql-backup.service")
 
       # wait for backup to fail, because of database 'doesnotexist'
       master.wait_until_fails("systemctl is-active -q mysql-backup.service")
diff --git a/nixos/tests/nextcloud/default.nix b/nixos/tests/nextcloud/default.nix
index 76feac314d5..45165b04bf8 100644
--- a/nixos/tests/nextcloud/default.nix
+++ b/nixos/tests/nextcloud/default.nix
@@ -18,4 +18,4 @@ foldl
     };
   })
 { }
-  [ 22 23 24 ]
+  [ 23 24 ]
diff --git a/nixos/tests/nginx-http3.nix b/nixos/tests/nginx-http3.nix
new file mode 100644
index 00000000000..edd0759464c
--- /dev/null
+++ b/nixos/tests/nginx-http3.nix
@@ -0,0 +1,90 @@
+import ./make-test-python.nix ({lib, pkgs, ...}:
+let
+  hosts = ''
+    192.168.2.101 acme.test
+  '';
+
+in
+{
+  name = "nginx-http3";
+  meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
+
+  nodes = {
+    server = { pkgs, ... }: {
+      networking = {
+        interfaces.eth1 = {
+          ipv4.addresses = [
+            { address = "192.168.2.101"; prefixLength = 24; }
+          ];
+        };
+        extraHosts = hosts;
+        firewall.allowedTCPPorts = [ 443 ];
+        firewall.allowedUDPPorts = [ 443 ];
+      };
+
+      security.pki.certificates = [
+        (builtins.readFile ./common/acme/server/ca.cert.pem)
+      ];
+
+      services.nginx = {
+        enable = true;
+        package = pkgs.nginxQuic;
+
+        virtualHosts."acme.test" = {
+          onlySSL = true;
+          sslCertificate = ./common/acme/server/acme.test.cert.pem;
+          sslCertificateKey = ./common/acme/server/acme.test.key.pem;
+          http2 = true;
+          http3 = true;
+          reuseport = true;
+          root = lib.mkForce (pkgs.runCommandLocal "testdir2" {} ''
+            mkdir "$out"
+            cat > "$out/index.html" <<EOF
+            <html><body>Hello World!</body></html>
+            EOF
+            cat > "$out/example.txt" <<EOF
+            Check http3 protocol.
+            EOF
+          '');
+        };
+      };
+    };
+
+    client = { pkgs, ... }: {
+      environment.systemPackages = [ pkgs.curlHTTP3 ];
+      networking = {
+        interfaces.eth1 = {
+          ipv4.addresses = [
+            { address = "192.168.2.201"; prefixLength = 24; }
+          ];
+        };
+        extraHosts = hosts;
+      };
+
+      security.pki.certificates = [
+        (builtins.readFile ./common/acme/server/ca.cert.pem)
+      ];
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    # Check http connections
+    client.succeed("curl --verbose --http3 https://acme.test | grep 'Hello World!'")
+
+    # Check downloadings
+    client.succeed("curl --verbose --http3 https://acme.test/example.txt --output /tmp/example.txt")
+    client.succeed("cat /tmp/example.txt | grep 'Check http3 protocol.'")
+
+    # Check header reading
+    client.succeed("curl --verbose --http3 --head https://acme.test | grep 'content-type'")
+
+    # Check change User-Agent
+    client.succeed("curl --verbose --http3 --user-agent 'Curl test 3.0' https://acme.test")
+    server.succeed("cat /var/log/nginx/access.log | grep 'Curl test 3.0'")
+
+    server.shutdown()
+    client.shutdown()
+  '';
+})
diff --git a/nixos/tests/os-prober.nix b/nixos/tests/os-prober.nix
index ac05bd80c60..1c89cf8c1c6 100644
--- a/nixos/tests/os-prober.nix
+++ b/nixos/tests/os-prober.nix
@@ -75,21 +75,30 @@ in {
       # The test cannot access the network, so any packages
       # nixos-rebuild needs must be included in the VM.
       system.extraDependencies = with pkgs;
-        [ sudo
-          libxml2.bin
-          libxslt.bin
+        [
+          brotli
+          brotli.dev
+          brotli.lib
           desktop-file-utils
           docbook5
           docbook_xsl_ns
-          unionfs-fuse
-          ntp
+          grub2
+          kmod.dev
+          libarchive
+          libarchive.dev
+          libxml2.bin
+          libxslt.bin
           nixos-artwork.wallpapers.simple-dark-gray-bottom
-          perlPackages.XMLLibXML
+          ntp
           perlPackages.ListCompare
+          perlPackages.XMLLibXML
+          python3Minimal
           shared-mime-info
+          stdenv
+          sudo
           texinfo
+          unionfs-fuse
           xorg.lndir
-          grub2
 
           # add curl so that rather than seeing the test attempt to download
           # curl's tarball, we see what it's trying to download
diff --git a/nixos/tests/pam/pam-oath-login.nix b/nixos/tests/pam/pam-oath-login.nix
index c532e81e674..dd6ef4a0abc 100644
--- a/nixos/tests/pam/pam-oath-login.nix
+++ b/nixos/tests/pam/pam-oath-login.nix
@@ -77,28 +77,28 @@ in
     machine.screenshot("postboot")
 
     with subtest("Invalid password"):
-        switch_to_tty(2)
-        enter_user_alice(2)
+        switch_to_tty("2")
+        enter_user_alice("2")
 
         machine.send_chars("${oathSnakeOilPassword1}\n")
-        machine.wait_until_tty_matches(2, "Password: ")
+        machine.wait_until_tty_matches("2", "Password: ")
         machine.send_chars("blorg\n")
-        machine.wait_until_tty_matches(2, "Login incorrect")
+        machine.wait_until_tty_matches("2", "Login incorrect")
 
     with subtest("Invalid oath token"):
-        switch_to_tty(3)
-        enter_user_alice(3)
+        switch_to_tty("3")
+        enter_user_alice("3")
 
         machine.send_chars("000000\n")
-        machine.wait_until_tty_matches(3, "Login incorrect")
-        machine.wait_until_tty_matches(3, "login:")
+        machine.wait_until_tty_matches("3", "Login incorrect")
+        machine.wait_until_tty_matches("3", "login:")
 
     with subtest("Happy path: Both passwords are mandatory to get us in"):
-        switch_to_tty(4)
-        enter_user_alice(4)
+        switch_to_tty("4")
+        enter_user_alice("4")
 
         machine.send_chars("${oathSnakeOilPassword2}\n")
-        machine.wait_until_tty_matches(4, "Password: ")
+        machine.wait_until_tty_matches("4", "Password: ")
         machine.send_chars("${alicePassword}\n")
 
         machine.wait_until_succeeds("pgrep -u alice bash")
diff --git a/nixos/tests/restic.nix b/nixos/tests/restic.nix
index 16979eab821..7523d5e5ed5 100644
--- a/nixos/tests/restic.nix
+++ b/nixos/tests/restic.nix
@@ -1,96 +1,119 @@
 import ./make-test-python.nix (
   { pkgs, ... }:
 
-    let
-      password = "some_password";
-      repository = "/tmp/restic-backup";
-      rcloneRepository = "rclone:local:/tmp/restic-rclone-backup";
+  let
+    password = "some_password";
+    repository = "/tmp/restic-backup";
+    repositoryFile = "${pkgs.writeText "repositoryFile" "/tmp/restic-backup-from-file"}";
+    rcloneRepository = "rclone:local:/tmp/restic-rclone-backup";
 
-      passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
-      initialize = true;
-      paths = [ "/opt" ];
-      pruneOpts = [
-        "--keep-daily 2"
-        "--keep-weekly 1"
-        "--keep-monthly 1"
-        "--keep-yearly 99"
-      ];
-    in
-      {
-        name = "restic";
+    backupPrepareCommand = ''
+      touch /opt/backupPrepareCommand
+      test ! -e /opt/backupCleanupCommand
+    '';
 
-        meta = with pkgs.lib.maintainers; {
-          maintainers = [ bbigras i077 ];
-        };
+    backupCleanupCommand = ''
+      rm /opt/backupPrepareCommand
+      touch /opt/backupCleanupCommand
+    '';
 
-        nodes = {
-          server =
-            { pkgs, ... }:
-              {
-                services.restic.backups = {
-                  remotebackup = {
-                    inherit repository passwordFile initialize paths pruneOpts;
-                  };
-                  rclonebackup = {
-                    repository = rcloneRepository;
-                    rcloneConfig = {
-                      type = "local";
-                      one_file_system = true;
-                    };
+    passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
+    initialize = true;
+    paths = [ "/opt" ];
+    pruneOpts = [
+      "--keep-daily 2"
+      "--keep-weekly 1"
+      "--keep-monthly 1"
+      "--keep-yearly 99"
+    ];
+  in
+  {
+    name = "restic";
 
-                    # This gets overridden by rcloneConfig.type
-                    rcloneConfigFile = pkgs.writeText "rclone.conf" ''
-                      [local]
-                      type=ftp
-                    '';
-                    inherit passwordFile initialize paths pruneOpts;
-                  };
-                  remoteprune = {
-                    inherit repository passwordFile;
-                    pruneOpts = [ "--keep-last 1" ];
-                  };
-                };
+    meta = with pkgs.lib.maintainers; {
+      maintainers = [ bbigras i077 ];
+    };
 
-                environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local";
+    nodes = {
+      server =
+        { pkgs, ... }:
+        {
+          services.restic.backups = {
+            remotebackup = {
+              inherit repository passwordFile initialize paths pruneOpts backupPrepareCommand backupCleanupCommand;
+            };
+            remotebackup-from-file = {
+              inherit repositoryFile passwordFile initialize paths pruneOpts;
+            };
+            rclonebackup = {
+              repository = rcloneRepository;
+              rcloneConfig = {
+                type = "local";
+                one_file_system = true;
               };
+
+              # This gets overridden by rcloneConfig.type
+              rcloneConfigFile = pkgs.writeText "rclone.conf" ''
+                [local]
+                type=ftp
+              '';
+              inherit passwordFile initialize paths pruneOpts;
+            };
+            remoteprune = {
+              inherit repository passwordFile;
+              pruneOpts = [ "--keep-last 1" ];
+            };
+          };
+
+          environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local";
         };
+    };
 
-        testScript = ''
-          server.start()
-          server.wait_for_unit("dbus.socket")
-          server.fail(
-              "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots",
-              "${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots",
-          )
-          server.succeed(
-              "mkdir -p /opt",
-              "touch /opt/some_file",
-              "mkdir -p /tmp/restic-rclone-backup",
-              "timedatectl set-time '2016-12-13 13:45'",
-              "systemctl start restic-backups-remotebackup.service",
-              "systemctl start restic-backups-rclonebackup.service",
-              '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
-              '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
-              "timedatectl set-time '2017-12-13 13:45'",
-              "systemctl start restic-backups-remotebackup.service",
-              "systemctl start restic-backups-rclonebackup.service",
-              "timedatectl set-time '2018-12-13 13:45'",
-              "systemctl start restic-backups-remotebackup.service",
-              "systemctl start restic-backups-rclonebackup.service",
-              "timedatectl set-time '2018-12-14 13:45'",
-              "systemctl start restic-backups-remotebackup.service",
-              "systemctl start restic-backups-rclonebackup.service",
-              "timedatectl set-time '2018-12-15 13:45'",
-              "systemctl start restic-backups-remotebackup.service",
-              "systemctl start restic-backups-rclonebackup.service",
-              "timedatectl set-time '2018-12-16 13:45'",
-              "systemctl start restic-backups-remotebackup.service",
-              "systemctl start restic-backups-rclonebackup.service",
-              '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
-              '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
-              "systemctl start restic-backups-remoteprune.service",
-              '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
-          )
-        '';
-      }
+    testScript = ''
+      server.start()
+      server.wait_for_unit("dbus.socket")
+      server.fail(
+          "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots",
+          '${pkgs.restic}/bin/restic --repository-file ${repositoryFile} -p ${passwordFile} snapshots"',
+          "${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots",
+      )
+      server.succeed(
+          "mkdir -p /opt",
+          "touch /opt/some_file",
+          "mkdir -p /tmp/restic-rclone-backup",
+          "timedatectl set-time '2016-12-13 13:45'",
+          "systemctl start restic-backups-remotebackup.service",
+          "rm /opt/backupCleanupCommand",
+          "systemctl start restic-backups-remotebackup-from-file.service",
+          "systemctl start restic-backups-rclonebackup.service",
+          '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
+          '${pkgs.restic}/bin/restic --repository-file ${repositoryFile} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
+          '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
+          "timedatectl set-time '2017-12-13 13:45'",
+          "systemctl start restic-backups-remotebackup.service",
+          "rm /opt/backupCleanupCommand",
+          "systemctl start restic-backups-rclonebackup.service",
+          "timedatectl set-time '2018-12-13 13:45'",
+          "systemctl start restic-backups-remotebackup.service",
+          "rm /opt/backupCleanupCommand",
+          "systemctl start restic-backups-rclonebackup.service",
+          "timedatectl set-time '2018-12-14 13:45'",
+          "systemctl start restic-backups-remotebackup.service",
+          "rm /opt/backupCleanupCommand",
+          "systemctl start restic-backups-rclonebackup.service",
+          "timedatectl set-time '2018-12-15 13:45'",
+          "systemctl start restic-backups-remotebackup.service",
+          "rm /opt/backupCleanupCommand",
+          "systemctl start restic-backups-rclonebackup.service",
+          "timedatectl set-time '2018-12-16 13:45'",
+          "systemctl start restic-backups-remotebackup.service",
+          "rm /opt/backupCleanupCommand",
+          "systemctl start restic-backups-rclonebackup.service",
+          '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
+          '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
+          "systemctl start restic-backups-remoteprune.service",
+          '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
+      )
+    '';
+  }
 )
diff --git a/nixos/tests/shadow.nix b/nixos/tests/shadow.nix
index dd2a575b193..50a9f712464 100644
--- a/nixos/tests/shadow.nix
+++ b/nixos/tests/shadow.nix
@@ -39,9 +39,9 @@ in import ./make-test-python.nix ({ pkgs, ... }: {
         shadow.wait_until_succeeds("[ $(fgconsole) = 2 ]")
         shadow.wait_for_unit("getty@tty2.service")
         shadow.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
-        shadow.wait_until_tty_matches(2, "login: ")
+        shadow.wait_until_tty_matches("2", "login: ")
         shadow.send_chars("emma\n")
-        shadow.wait_until_tty_matches(2, "login: emma")
+        shadow.wait_until_tty_matches("2", "login: emma")
         shadow.wait_until_succeeds("pgrep login")
         shadow.sleep(2)
         shadow.send_chars("${password1}\n")
@@ -63,9 +63,9 @@ in import ./make-test-python.nix ({ pkgs, ... }: {
         shadow.wait_until_succeeds("[ $(fgconsole) = 3 ]")
         shadow.wait_for_unit("getty@tty3.service")
         shadow.wait_until_succeeds("pgrep -f 'agetty.*tty3'")
-        shadow.wait_until_tty_matches(3, "login: ")
+        shadow.wait_until_tty_matches("3", "login: ")
         shadow.send_chars("emma\n")
-        shadow.wait_until_tty_matches(3, "login: emma")
+        shadow.wait_until_tty_matches("3", "login: emma")
         shadow.wait_until_succeeds("pgrep login")
         shadow.sleep(2)
         shadow.send_chars("${password1}\n")
@@ -81,16 +81,16 @@ in import ./make-test-python.nix ({ pkgs, ... }: {
         shadow.wait_until_succeeds("[ $(fgconsole) = 4 ]")
         shadow.wait_for_unit("getty@tty4.service")
         shadow.wait_until_succeeds("pgrep -f 'agetty.*tty4'")
-        shadow.wait_until_tty_matches(4, "login: ")
+        shadow.wait_until_tty_matches("4", "login: ")
         shadow.send_chars("emma\n")
-        shadow.wait_until_tty_matches(4, "login: emma")
+        shadow.wait_until_tty_matches("4", "login: emma")
         shadow.wait_until_succeeds("pgrep login")
         shadow.sleep(2)
         shadow.send_chars("${password1}\n")
-        shadow.wait_until_tty_matches(4, "Login incorrect")
-        shadow.wait_until_tty_matches(4, "login:")
+        shadow.wait_until_tty_matches("4", "Login incorrect")
+        shadow.wait_until_tty_matches("4", "login:")
         shadow.send_chars("emma\n")
-        shadow.wait_until_tty_matches(4, "login: emma")
+        shadow.wait_until_tty_matches("4", "login: emma")
         shadow.wait_until_succeeds("pgrep login")
         shadow.sleep(2)
         shadow.send_chars("${password3}\n")
@@ -109,11 +109,11 @@ in import ./make-test-python.nix ({ pkgs, ... }: {
         shadow.wait_until_succeeds("[ $(fgconsole) = 5 ]")
         shadow.wait_for_unit("getty@tty5.service")
         shadow.wait_until_succeeds("pgrep -f 'agetty.*tty5'")
-        shadow.wait_until_tty_matches(5, "login: ")
+        shadow.wait_until_tty_matches("5", "login: ")
         shadow.send_chars("layla\n")
-        shadow.wait_until_tty_matches(5, "login: layla")
+        shadow.wait_until_tty_matches("5", "login: layla")
         shadow.wait_until_succeeds("pgrep login")
         shadow.send_chars("${password2}\n")
-        shadow.wait_until_tty_matches(5, "login:")
+        shadow.wait_until_tty_matches("5", "login:")
   '';
 })
diff --git a/nixos/tests/sway.nix b/nixos/tests/sway.nix
index 8f95f2a030d..52e2c7c99ec 100644
--- a/nixos/tests/sway.nix
+++ b/nixos/tests/sway.nix
@@ -4,6 +4,12 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
     maintainers = with lib.maintainers; [ primeos synthetica ];
   };
 
+  # testScriptWithTypes:49: error: Cannot call function of unknown type
+  #           (machine.succeed if succeed else machine.execute)(
+  #           ^
+  # Found 1 error in 1 file (checked 1 source file)
+  skipTypeCheck = true;
+
   nodes.machine = { config, ... }: {
     # Automatically login on tty1 as a normal user:
     imports = [ ./common/user-account.nix ];
diff --git a/nixos/tests/uptermd.nix b/nixos/tests/uptermd.nix
index d504ef06419..429e3c9dd5f 100644
--- a/nixos/tests/uptermd.nix
+++ b/nixos/tests/uptermd.nix
@@ -42,7 +42,7 @@ in
 
     client1.wait_for_unit("multi-user.target")
     client1.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
-    client1.wait_until_tty_matches(1, "login: ")
+    client1.wait_until_tty_matches("1", "login: ")
     client1.send_chars("root\n")
     client1.wait_until_succeeds("pgrep -u root bash")
 
diff --git a/nixos/tests/user-activation-scripts.nix b/nixos/tests/user-activation-scripts.nix
index 93457357818..5df072ce050 100644
--- a/nixos/tests/user-activation-scripts.nix
+++ b/nixos/tests/user-activation-scripts.nix
@@ -19,9 +19,9 @@ import ./make-test-python.nix ({ lib, ... }: {
 
     machine.wait_for_unit("multi-user.target")
     machine.wait_for_unit("getty@tty1.service")
-    machine.wait_until_tty_matches(1, "login: ")
+    machine.wait_until_tty_matches("1", "login: ")
     machine.send_chars("alice\n")
-    machine.wait_until_tty_matches(1, "Password: ")
+    machine.wait_until_tty_matches("1", "Password: ")
     machine.send_chars("pass1\n")
     machine.send_chars("touch login-ok\n")
     machine.wait_for_file("/home/alice/login-ok")
diff --git a/nixos/tests/user-home-mode.nix b/nixos/tests/user-home-mode.nix
new file mode 100644
index 00000000000..070cb0b75cc
--- /dev/null
+++ b/nixos/tests/user-home-mode.nix
@@ -0,0 +1,27 @@
+import ./make-test-python.nix ({ lib, ... }: {
+  name = "user-home-mode";
+  meta = with lib.maintainers; { maintainers = [ fbeffa ]; };
+
+  nodes.machine = {
+    users.users.alice = {
+      initialPassword = "pass1";
+      isNormalUser = true;
+    };
+    users.users.bob = {
+      initialPassword = "pass2";
+      isNormalUser = true;
+      homeMode = "750";
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("multi-user.target")
+    machine.wait_for_unit("getty@tty1.service")
+    machine.wait_until_tty_matches("1", "login: ")
+    machine.send_chars("alice\n")
+    machine.wait_until_tty_matches("1", "Password: ")
+    machine.send_chars("pass1\n")
+    machine.succeed('[ "$(stat -c %a /home/alice)" == "700" ]')
+    machine.succeed('[ "$(stat -c %a /home/bob)" == "750" ]')
+  '';
+})
diff --git a/nixos/tests/web-apps/peertube.nix b/nixos/tests/web-apps/peertube.nix
index d42b4e3d677..ecc45bff2e2 100644
--- a/nixos/tests/web-apps/peertube.nix
+++ b/nixos/tests/web-apps/peertube.nix
@@ -11,7 +11,7 @@ import ../make-test-python.nix ({pkgs, ...}:
             { address = "192.168.2.10"; prefixLength = 24; }
           ];
         };
-        firewall.allowedTCPPorts = [ 5432 6379 ];
+        firewall.allowedTCPPorts = [ 5432 31638 ];
       };
 
       services.postgresql = {
@@ -34,7 +34,7 @@ import ../make-test-python.nix ({pkgs, ...}:
         enable = true;
         bind = "0.0.0.0";
         requirePass = "turrQfaQwnanGbcsdhxy";
-        port = 6379;
+        port = 31638;
       };
     };
 
@@ -76,6 +76,7 @@ import ../make-test-python.nix ({pkgs, ...}:
 
         redis = {
           host = "192.168.2.10";
+          port = 31638;
           passwordFile = "/etc/peertube/password-redis-db";
         };
 
@@ -113,7 +114,7 @@ import ../make-test-python.nix ({pkgs, ...}:
     database.wait_for_unit("redis-peertube.service")
 
     database.wait_for_open_port(5432)
-    database.wait_for_open_port(6379)
+    database.wait_for_open_port(31638)
 
     server.wait_for_unit("peertube.service")
     server.wait_for_open_port(9000)
diff --git a/nixos/tests/zsh-history.nix b/nixos/tests/zsh-history.nix
index 35568779840..64f32a07e21 100644
--- a/nixos/tests/zsh-history.nix
+++ b/nixos/tests/zsh-history.nix
@@ -21,13 +21,13 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     default.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
 
     # Login
-    default.wait_until_tty_matches(1, "login: ")
+    default.wait_until_tty_matches("1", "login: ")
     default.send_chars("root\n")
-    default.wait_until_tty_matches(1, r"\nroot@default\b")
+    default.wait_until_tty_matches("1", r"\nroot@default\b")
 
     # Generate some history
     default.send_chars("echo foobar\n")
-    default.wait_until_tty_matches(1, "foobar")
+    default.wait_until_tty_matches("1", "foobar")
 
     # Ensure that command was recorded in history
     default.succeed("/run/current-system/sw/bin/history list | grep -q foobar")