summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/wireless.xml21
-rw-r--r--nixos/doc/manual/default.nix1
-rwxr-xr-xnixos/doc/manual/development/releases.xml7
-rw-r--r--nixos/doc/manual/installation/installing.xml4
-rw-r--r--nixos/doc/manual/man-nixos-rebuild.xml14
-rw-r--r--nixos/doc/manual/release-notes/release-notes.xml1
-rw-r--r--nixos/doc/manual/release-notes/rl-1903.xml68
-rw-r--r--nixos/doc/manual/release-notes/rl-1909.xml68
-rw-r--r--nixos/lib/eval-config.nix4
-rw-r--r--nixos/modules/config/no-x-libs.nix2
-rw-r--r--nixos/modules/config/zram.nix6
-rw-r--r--nixos/modules/hardware/video/nvidia.nix5
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh13
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh21
-rw-r--r--nixos/modules/misc/documentation.nix17
-rw-r--r--nixos/modules/module-list.nix6
-rw-r--r--nixos/modules/programs/bash/bash.nix2
-rw-r--r--nixos/modules/programs/fish.nix53
-rw-r--r--nixos/modules/programs/fish_completion-generator.patch11
-rw-r--r--nixos/modules/programs/gnupg.nix4
-rw-r--r--nixos/modules/rename.nix3
-rw-r--r--nixos/modules/security/duosec.nix19
-rw-r--r--nixos/modules/security/pam.nix21
-rw-r--r--nixos/modules/services/audio/snapserver.nix217
-rw-r--r--nixos/modules/services/backup/duplicity.nix141
-rw-r--r--nixos/modules/services/cluster/kubernetes/apiserver.nix2
-rw-r--r--nixos/modules/services/cluster/kubernetes/controller-manager.nix2
-rw-r--r--nixos/modules/services/cluster/kubernetes/default.nix2
-rw-r--r--nixos/modules/services/databases/openldap.nix2
-rw-r--r--nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix45
-rw-r--r--nixos/modules/services/hardware/thinkfan.nix20
-rw-r--r--nixos/modules/services/mail/rmilter.nix4
-rw-r--r--nixos/modules/services/misc/bepasty.nix6
-rw-r--r--nixos/modules/services/misc/home-assistant.nix20
-rw-r--r--nixos/modules/services/misc/redmine.nix72
-rw-r--r--nixos/modules/services/misc/tautulli.nix (renamed from nixos/modules/services/misc/plexpy.nix)40
-rw-r--r--nixos/modules/services/misc/zoneminder.nix12
-rw-r--r--nixos/modules/services/monitoring/datadog-agent.nix6
-rw-r--r--nixos/modules/services/monitoring/hdaps.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/alertmanager.nix3
-rw-r--r--nixos/modules/services/network-filesystems/openafs/client.nix2
-rw-r--r--nixos/modules/services/networking/coredns.nix50
-rw-r--r--nixos/modules/services/networking/gnunet.nix4
-rw-r--r--nixos/modules/services/networking/mosquitto.nix9
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix5
-rw-r--r--nixos/modules/services/networking/strongswan-swanctl/module.nix9
-rw-r--r--nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix36
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix67
-rw-r--r--nixos/modules/services/web-apps/restya-board.nix53
-rw-r--r--nixos/modules/services/web-apps/youtrack.nix1
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix25
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix29
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix8
-rw-r--r--nixos/modules/services/x11/xserver.nix6
-rw-r--r--nixos/modules/system/activation/top-level.nix4
-rw-r--r--nixos/modules/system/etc/make-etc.sh15
-rw-r--r--nixos/modules/system/etc/setup-etc.pl19
-rw-r--r--nixos/modules/tasks/auto-upgrade.nix4
-rw-r--r--nixos/modules/virtualisation/docker.nix25
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/docker-tools.nix4
-rw-r--r--nixos/tests/fish.nix21
-rw-r--r--nixos/tests/gitea.nix2
-rw-r--r--nixos/tests/installer.nix70
-rw-r--r--nixos/tests/ndppd.nix3
-rw-r--r--nixos/tests/openssh.nix23
-rw-r--r--nixos/tests/rspamd.nix16
72 files changed, 1151 insertions, 340 deletions
diff --git a/nixos/doc/manual/configuration/wireless.xml b/nixos/doc/manual/configuration/wireless.xml
index f7e99ff0e35..dda2193dd93 100644
--- a/nixos/doc/manual/configuration/wireless.xml
+++ b/nixos/doc/manual/configuration/wireless.xml
@@ -36,8 +36,25 @@
  </para>
 
  <para>
-  If you are using WPA2 the <command>wpa_passphrase</command> tool might be
-  useful to generate the <literal>wpa_supplicant.conf</literal>.
+  If you are using WPA2 you can generate pskRaw key using
+  <command>wpa_passphrase</command>:
+<screen>
+$ wpa_passphrase ESSID PSK
+network={
+        ssid="echelon"
+        #psk="abcdefgh"
+        psk=dca6d6ed41f4ab5a984c9f55f6f66d4efdc720ebf66959810f4329bb391c5435
+}
+</screen>
+<programlisting>
+<xref linkend="opt-networking.wireless.networks"/> = {
+  echelon = {
+    pskRaw = "dca6d6ed41f4ab5a984c9f55f6f66d4efdc720ebf66959810f4329bb391c5435";
+  };
+}
+</programlisting>
+  or you can use it to directly generate the
+  <literal>wpa_supplicant.conf</literal>:
 <screen>
 # wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf</screen>
   After you have edited the <literal>wpa_supplicant.conf</literal>, you need to
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 02b91773f5d..4e0d486e94c 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -327,6 +327,7 @@ in rec {
       # Generate manpages.
       mkdir -p $out/share/man
       xsltproc --nonet \
+        --maxdepth 6000 \
         --param man.output.in.separate.dir 1 \
         --param man.output.base.dir "'$out/share/man/'" \
         --param man.endnotes.are.numbered 0 \
diff --git a/nixos/doc/manual/development/releases.xml b/nixos/doc/manual/development/releases.xml
index d4e5ff3f431..dcedad540e1 100755
--- a/nixos/doc/manual/development/releases.xml
+++ b/nixos/doc/manual/development/releases.xml
@@ -62,13 +62,6 @@
     </listitem>
     <listitem>
      <para>
-      <link xlink:href="https://github.com/NixOS/nixpkgs/settings/branches">
-      Let a GitHub nixpkgs admin lock the branch on github for you. (so
-      developers can’t force push) </link>
-     </para>
-    </listitem>
-    <listitem>
-     <para>
       <link xlink:href="https://github.com/NixOS/nixpkgs/compare/bdf161ed8d21...6b63c4616790">
       Bump the <literal>system.defaultChannel</literal> attribute in
       <literal>nixos/modules/misc/version.nix</literal> </link>
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
index 8e94f946c5e..f4f8d470f80 100644
--- a/nixos/doc/manual/installation/installing.xml
+++ b/nixos/doc/manual/installation/installing.xml
@@ -378,6 +378,10 @@
      the grub menu.
     </para>
     <para>
+     If you need to configure networking for your machine the configuration
+     options are described in <xref linkend="sec-networking"/>.
+    </para>
+    <para>
      Another critical option is <option>fileSystems</option>, specifying the
      file systems that need to be mounted by NixOS. However, you typically
      don’t need to set it yourself, because
diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml
index b6a247286d4..654b5f4b284 100644
--- a/nixos/doc/manual/man-nixos-rebuild.xml
+++ b/nixos/doc/manual/man-nixos-rebuild.xml
@@ -39,6 +39,10 @@
    </arg>
 
    <arg choice='plain'>
+    <option>edit</option>
+   </arg>
+
+   <arg choice='plain'>
     <option>build-vm</option>
    </arg>
 
@@ -190,6 +194,16 @@ $ nix-build /path/to/nixpkgs/nixos -A system
     </varlistentry>
     <varlistentry>
      <term>
+      <option>edit</option>
+     </term>
+     <listitem>
+      <para>
+        Opens <filename>configuration.nix</filename> in the default editor.
+      </para>
+     </listitem>
+    </varlistentry>
+    <varlistentry>
+     <term>
       <option>build-vm</option>
      </term>
      <listitem>
diff --git a/nixos/doc/manual/release-notes/release-notes.xml b/nixos/doc/manual/release-notes/release-notes.xml
index a222bfa29d5..02b59147721 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="rl-1909.xml" />
  <xi:include href="rl-1903.xml" />
  <xi:include href="rl-1809.xml" />
  <xi:include href="rl-1803.xml" />
diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml
index a8e4807f238..a82724d7fb5 100644
--- a/nixos/doc/manual/release-notes/rl-1903.xml
+++ b/nixos/doc/manual/release-notes/rl-1903.xml
@@ -106,6 +106,23 @@
     </para>
    </listitem>
   </itemizedlist>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+      <literal>./security/duosec.nix</literal>
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+     The <link xlink:href="https://duo.com/docs/duounix">PAM module for Duo
+     Security</link> has been enabled for use.  One can configure it using
+     the <option>security.duosec</option> options along with the
+     corresponding PAM option in
+     <option>security.pam.services.&lt;name?&gt;.duoSecurity.enable</option>.
+    </para>
+   </listitem>
+  </itemizedlist>
  </section>
 
  <section xmlns="http://docbook.org/ns/docbook"
@@ -167,6 +184,20 @@
    </listitem>
    <listitem>
     <para>
+      The <varname>buildPythonPackage</varname> function now sets <varname>strictDeps = true</varname>
+      to help distinguish between native and non-native dependencies in order to
+      improve cross-compilation compatibility. Note however that this may break
+      user expressions.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+      The <varname>buildPythonPackage</varname> function now sets <varname>LANG = C.UTF-8</varname>
+      to enable Unicode support. The <varname>glibcLocales</varname> package is no longer needed as a build input.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
       The Syncthing state and configuration data has been moved from
       <varname>services.syncthing.dataDir</varname> to the newly defined
       <varname>services.syncthing.configDir</varname>, which default to
@@ -425,8 +456,8 @@
   </listitem>
   <listitem>
    <para>
-    Support for NixOS module system type <literal>types.optionSet</literal> and
-    <literal>lib.mkOption</literal> argument <literal>options</literal> is removed.
+    NixOS module system type <literal>types.optionSet</literal> and
+    <literal>lib.mkOption</literal> argument <literal>options</literal> are deprecated.
     Use <literal>types.submodule</literal> instead.
     (<link xlink:href="https://github.com/NixOS/nixpkgs/pull/54637">#54637</link>)
    </para>
@@ -448,6 +479,11 @@
      been removed.
     </para>
    </listitem>
+   <listitem>
+    <para>
+     <literal>graylog</literal> has been upgraded from version 2.* to 3.*. Some setups making use of extraConfig (especially those exposing Graylog via reverse proxies) need to be updated as upstream removed/replaced some settings. See <link xlink:href="http://docs.graylog.org/en/3.0/pages/upgrade/graylog-3.0.html#simplified-http-interface-configuration">Upgrading Graylog</link> for details.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
@@ -541,7 +577,7 @@
        but is still possible by setting <literal>zramSwap.swapDevices</literal> explicitly.
      </para>
      <para>
-      Default algorithm for ZRAM swap was changed to <literal>zstd</literal>.
+      ZRAM algorithm can be changed now.
      </para>
      <para>
       Changes to ZRAM algorithm are applied during <literal>nixos-rebuild switch</literal>,
@@ -551,20 +587,6 @@
    </listitem>
    <listitem>
     <para>
-     Symlinks in <filename>/etc</filename> (except <filename>/etc/static</filename>)
-     are now relative instead of absolute. This makes possible to examine
-     NixOS container's <filename>/etc</filename> directory from host system
-     (previously it pointed to host <filename>/etc</filename> when viewed from host,
-     and to container <filename>/etc</filename> when viewed from container chroot).
-    </para>
-    <para>
-     This also makes <filename>/etc/os-release</filename> adhere to
-     <link xlink:href="https://www.freedesktop.org/software/systemd/man/os-release.html">the standard</link>
-     for NixOS containers.
-    </para>
-   </listitem>
-   <listitem>
-    <para>
       Flat volumes are now disabled by default in <literal>hardware.pulseaudio</literal>.
       This has been done to prevent applications, which are unaware of this feature, setting
       their volumes to 100% on startup causing harm to your audio hardware and potentially your ears.
@@ -644,6 +666,10 @@
         Some OpenCL and VA-API applications might also break
         (Beignet seems to provide OpenCL support with
         <literal>modesetting</literal> driver, too).
+        Kernel mode setting API does not support backlight control,
+        so <literal>xbacklight</literal> tool will not work;
+        backlight level can be controlled directly via <literal>/sys/</literal>
+        or with <literal>brightnessctl</literal>.
         Users who need this functionality more than multi-output XRandR are advised
         to add `intel` to `videoDrivers` and report an issue (or provide additional
         details in an existing one)
@@ -655,6 +681,14 @@
        This may break some older applications that still rely on those symbols.
        An upgrade guide can be found <link xlink:href="https://www.open-mpi.org/faq/?category=mpi-removed">here</link>.
      </para>
+    <para>
+     The nginx package now relies on OpenSSL 1.1 and supports TLS 1.3 by default. You can set the protocols used by the nginx service using <xref linkend="opt-services.nginx.sslProtocols"/>.
+    </para>
+   </listitem>
+   <listitem>
+     <para>
+       A new subcommand <command>nixos-rebuild edit</command> was added.
+     </para>
    </listitem>
   </itemizedlist>
  </section>
diff --git a/nixos/doc/manual/release-notes/rl-1909.xml b/nixos/doc/manual/release-notes/rl-1909.xml
new file mode 100644
index 00000000000..f54592b6bf6
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-1909.xml
@@ -0,0 +1,68 @@
+<section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-release-19.09">
+ <title>Release 19.09 (“Loris”, 2019/09/??)</title>
+
+ <section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-release-19.09-highlights">
+  <title>Highlights</title>
+
+  <para>
+   In addition to numerous new and upgraded packages, this release has the
+   following highlights:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para />
+   </listitem>
+  </itemizedlist>
+ </section>
+
+ <section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-release-19.09-new-services">
+  <title>New Services</title>
+
+  <para>
+   The following new services were added since the last release:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para />
+   </listitem>
+  </itemizedlist>
+ </section>
+
+ <section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-release-19.09-notable-changes">
+  <title>Other Notable Changes</title>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     The <option>documentation</option> module gained an option named
+     <option>documentation.nixos.includeAllModules</option> which makes the generated
+     <citerefentry><refentrytitle>configuration.nix</refentrytitle>
+     <manvolnum>5</manvolnum></citerefentry> manual page include all options from all NixOS modules
+     included in a given <literal>configuration.nix</literal> configuration file. Currently, it is
+     set to <literal>false</literal> by default as enabling it frequently prevents evaluation. But
+     the plan is to eventually have it set to <literal>true</literal> by default. Please set it to
+     <literal>true</literal> now in your <literal>configuration.nix</literal> and fix all the bugs
+     it uncovers.
+    </para>
+   </listitem>
+  </itemizedlist>
+ </section>
+</section>
diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix
index 5f05b037bdd..77490ca3762 100644
--- a/nixos/lib/eval-config.nix
+++ b/nixos/lib/eval-config.nix
@@ -51,7 +51,7 @@ in rec {
   # system configuration.
   inherit (lib.evalModules {
     inherit prefix check;
-    modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ];
+    modules = baseModules ++ extraModules ++ [ pkgsModule ] ++ modules;
     args = extraArgs;
     specialArgs =
       { modulesPath = builtins.toString ../modules; } // specialArgs;
@@ -60,7 +60,7 @@ in rec {
   # These are the extra arguments passed to every module.  In
   # particular, Nixpkgs is passed through the "pkgs" argument.
   extraArgs = extraArgs_ // {
-    inherit modules baseModules;
+    inherit baseModules extraModules modules;
   };
 
   inherit (config._module.args) pkgs;
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix
index 37e66c64542..9d202347702 100644
--- a/nixos/modules/config/no-x-libs.nix
+++ b/nixos/modules/config/no-x-libs.nix
@@ -34,7 +34,7 @@ with lib;
       networkmanager-openvpn = super.networkmanager-openvpn.override { withGnome = false; };
       networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
       networkmanager-iodine = super.networkmanager-iodine.override { withGnome = false; };
-      pinentry = super.pinentry_ncurses;
+      pinentry = super.pinentry.override { gtk2 = null; qt = null; };
       gobject-introspection = super.gobject-introspection.override { x11Support = false; };
     }));
   };
diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix
index 925d945c081..5d411c73a56 100644
--- a/nixos/modules/config/zram.nix
+++ b/nixos/modules/config/zram.nix
@@ -91,13 +91,13 @@ in
       };
 
       algorithm = mkOption {
-        default = "zstd";
-        example = "lzo";
+        default = "lzo";
+        example = "lz4";
         type = with types; either (enum [ "lzo" "lz4" "zstd" ]) str;
         description = ''
           Compression algorithm. <literal>lzo</literal> has good compression,
           but is slow. <literal>lz4</literal> has bad compression, but is fast.
-          <literal>zstd</literal> is both good compression and fast.
+          <literal>zstd</literal> is both good compression and fast, but requires newer kernel.
           You can check what other algorithms are supported by your zram device with
           <programlisting>cat /sys/class/block/zram*/comp_algorithm</programlisting>
         '';
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 6ba8130af71..80ea7bc5d5c 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -172,6 +172,11 @@ in
     environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ]
       ++ lib.filter (p: p != null) [ nvidia_x11.persistenced ];
 
+    systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
+        "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
+      ++ optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
+        "L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
+
     boot.extraModulePackages = [ nvidia_x11.bin ];
 
     # nvidia-uvm is required by CUDA applications.
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index defc46ad2a7..8685cb345e1 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -138,7 +138,18 @@ fi
 # Ask the user to set a root password, but only if the passwd command
 # exists (i.e. when mutable user accounts are enabled).
 if [[ -z $noRootPasswd ]] && [ -t 0 ]; then
-    nixos-enter --root "$mountPoint" -c '[[ -e /nix/var/nix/profiles/system/sw/bin/passwd ]] && echo "setting root password..." && /nix/var/nix/profiles/system/sw/bin/passwd'
+    if nixos-enter --root "$mountPoint" -c 'test -e /nix/var/nix/profiles/system/sw/bin/passwd'; then
+        set +e
+        nixos-enter --root "$mountPoint" -c 'echo "setting root password..." && /nix/var/nix/profiles/system/sw/bin/passwd'
+        exit_code=$?
+        set -e
+
+        if [[ $exit_code != 0 ]]; then
+            echo "Setting a root password failed with the above printed error."
+            echo "You can set the root password manually by executing \`nixos-enter --root ${mountPoint@Q}\` and then running \`passwd\` in the shell of the new system."
+            exit $exit_code
+        fi
+    fi
 fi
 
 echo "installation finished!"
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 361c2e49e05..6a08c9b4c6c 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -29,7 +29,7 @@ while [ "$#" -gt 0 ]; do
       --help)
         showSyntax
         ;;
-      switch|boot|test|build|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader)
+      switch|boot|test|build|edit|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader)
         if [ "$i" = dry-run ]; then i=dry-build; fi
         action="$i"
         ;;
@@ -227,6 +227,13 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
     fi
 fi
 
+# Find configuration.nix and open editor instead of building.
+if [ "$action" = edit ]; then
+    NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
+    exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+    exit 1
+fi
+
 
 tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX)
 SSHOPTS="$NIX_SSHOPTS -o ControlMaster=auto -o ControlPath=$tmpDir/ssh-%n -o ControlPersist=60"
@@ -260,6 +267,14 @@ if [ -n "$rollback" -o "$action" = dry-build ]; then
     buildNix=
 fi
 
+nixSystem() {
+    machine="$(uname -m)"
+    if [[ "$machine" =~ i.86 ]]; then
+        machine=i686
+    fi
+    echo $machine-linux
+}
+
 prebuiltNix() {
     machine="$1"
     if [ "$machine" = x86_64 ]; then
@@ -279,7 +294,9 @@ if [ -n "$buildNix" ]; then
     nixDrv=
     if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then
         if ! nixDrv="$(nix-instantiate '<nixpkgs>' --add-root $tmpDir/nix.drv --indirect -A nix "${extraBuildFlags[@]}")"; then
-            nixStorePath="$(prebuiltNix "$(uname -m)")"
+            if ! nixStorePath="$(nix-instantiate --eval '<nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix>' -A $(nixSystem) | sed -e 's/^"//' -e 's/"$//')"; then
+                nixStorePath="$(prebuiltNix "$(uname -m)")"
+            fi
             if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \
                 --option extra-binary-caches https://cache.nixos.org/; then
                 echo "warning: don't know how to get latest Nix" >&2
diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix
index 9b2e1235b74..834ac0de912 100644
--- a/nixos/modules/misc/documentation.nix
+++ b/nixos/modules/misc/documentation.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, baseModules, ... }:
+{ config, lib, pkgs, baseModules, extraModules, modules, ... }:
 
 with lib;
 
@@ -6,6 +6,8 @@ let
 
   cfg = config.documentation;
 
+  manualModules = baseModules ++ optionals cfg.nixos.includeAllModules (extraModules ++ modules);
+
   /* For the purpose of generating docs, evaluate options with each derivation
     in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}".
     It isn't perfect, but it seems to cover a vast majority of use cases.
@@ -18,7 +20,7 @@ let
     options =
       let
         scrubbedEval = evalModules {
-          modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ baseModules;
+          modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ manualModules;
           args = (config._module.args) // { modules = [ ]; };
           specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
         };
@@ -146,6 +148,17 @@ in
         '';
       };
 
+      nixos.includeAllModules = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether the generated NixOS's documentation should include documentation for all
+          the options from all the NixOS modules included in the current
+          <literal>configuration.nix</literal>. Disabling this will make the manual
+          generator to ignore options defined outside of <literal>baseModules</literal>.
+        '';
+      };
+
     };
 
   };
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 32b3f14e82d..0accee36034 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -182,6 +182,7 @@
   ./services/audio/mpd.nix
   ./services/audio/mopidy.nix
   ./services/audio/slimserver.nix
+  ./services/audio/snapserver.nix
   ./services/audio/squeezelite.nix
   ./services/audio/ympd.nix
   ./services/backup/bacula.nix
@@ -189,6 +190,7 @@
   ./services/backup/duplicati.nix
   ./services/backup/crashplan.nix
   ./services/backup/crashplan-small-business.nix
+  ./services/backup/duplicity.nix
   ./services/backup/mysql-backup.nix
   ./services/backup/postgresql-backup.nix
   ./services/backup/restic.nix
@@ -268,6 +270,7 @@
   ./services/desktops/gnome3/gnome-online-accounts.nix
   ./services/desktops/gnome3/gnome-remote-desktop.nix
   ./services/desktops/gnome3/gnome-online-miners.nix
+  ./services/desktops/gnome3/gnome-settings-daemon.nix
   ./services/desktops/gnome3/gnome-terminal-server.nix
   ./services/desktops/gnome3/gnome-user-share.nix
   ./services/desktops/gnome3/gpaste.nix
@@ -424,7 +427,7 @@
   ./services/misc/parsoid.nix
   ./services/misc/phd.nix
   ./services/misc/plex.nix
-  ./services/misc/plexpy.nix
+  ./services/misc/tautulli.nix
   ./services/misc/pykms.nix
   ./services/misc/radarr.nix
   ./services/misc/redmine.nix
@@ -528,6 +531,7 @@
   ./services/networking/cntlm.nix
   ./services/networking/connman.nix
   ./services/networking/consul.nix
+  ./services/networking/coredns.nix
   ./services/networking/coturn.nix
   ./services/networking/dante.nix
   ./services/networking/ddclient.nix
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index d22f9dfa319..d53c6b318f1 100644
--- a/nixos/modules/programs/bash/bash.nix
+++ b/nixos/modules/programs/bash/bash.nix
@@ -102,7 +102,7 @@ in
               # Emacs term mode doesn't support xterm title escape sequence (\e]0;)
               PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
             else
-              PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\$\[\033[0m\] "
+              PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\\$\[\033[0m\] "
             fi
             if test "$TERM" = "xterm"; then
               PS1="\[\033]2;\h:\u:\w\007\]$PS1"
diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix
index b38af07b92c..bcb5a3f341b 100644
--- a/nixos/modules/programs/fish.nix
+++ b/nixos/modules/programs/fish.nix
@@ -169,6 +169,59 @@ in
       end
     '';
 
+    programs.fish.interactiveShellInit = ''
+      # add completions generated by NixOS to $fish_complete_path
+      begin
+        # joins with null byte to acommodate all characters in paths, then respectively gets all paths before (exclusive) / after (inclusive) the first one including "generated_completions",
+        # splits by null byte, and then removes all empty lines produced by using 'string'
+        set -l prev (string join0 $fish_complete_path | string match --regex "^.*?(?=\x00[^\x00]*generated_completions.*)" | string split0 | string match -er ".")
+        set -l post (string join0 $fish_complete_path | string match --regex "[^\x00]*generated_completions.*" | string split0 | string match -er ".")
+        set fish_complete_path $prev "/etc/fish/generated_completions" $post
+      end
+    '';
+
+    environment.etc."fish/generated_completions".source =
+      let
+        patchedGenerator = pkgs.stdenv.mkDerivation {
+          name = "fish_patched-completion-generator";
+          srcs = [
+            "${pkgs.fish}/share/fish/tools/create_manpage_completions.py"
+            "${pkgs.fish}/share/fish/tools/deroff.py"
+          ];
+          unpackCmd = "cp $curSrc $(basename $curSrc)";
+          sourceRoot = ".";
+          patches = [ ./fish_completion-generator.patch ]; # to prevent collisions of identical completion files
+          dontBuild = true;
+          installPhase = ''
+            mkdir -p $out
+            cp * $out/
+          '';
+          preferLocalBuild = true;
+          allowSubstitutes = false;
+        };
+        generateCompletions = package: pkgs.runCommand
+          "${package.name}_fish-completions"
+          (
+            {
+              inherit package;
+              preferLocalBuild = true;
+              allowSubstitutes = false;
+            }
+            // optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; }
+          )
+          ''
+            mkdir -p $out
+            if [ -d $package/share/man ]; then
+              find $package/share/man -type f | xargs ${pkgs.python3.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
+            fi
+          '';
+      in
+        pkgs.buildEnv {
+          name = "system_fish-completions";
+          ignoreCollisions = true;
+          paths = map generateCompletions config.environment.systemPackages;
+        };
+
     # include programs that bring their own completions
     environment.pathsToLink = []
       ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
diff --git a/nixos/modules/programs/fish_completion-generator.patch b/nixos/modules/programs/fish_completion-generator.patch
new file mode 100644
index 00000000000..a8c797d185a
--- /dev/null
+++ b/nixos/modules/programs/fish_completion-generator.patch
@@ -0,0 +1,11 @@
+--- a/create_manpage_completions.py
++++ b/create_manpage_completions.py
+@@ -776,8 +776,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
+
+             built_command_output.insert(0, "# " + CMDNAME)
+
+-            # Output the magic word Autogenerated so we can tell if we can overwrite this
+-            built_command_output.insert(1, "# Autogenerated from man page " + manpage_path)
+             # built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABILE PARSER! Was really using Type2 but reporting TypeDeroffManParser
+
+             for line in built_command_output:
diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix
index b01de9efaa5..22521280e93 100644
--- a/nixos/modules/programs/gnupg.nix
+++ b/nixos/modules/programs/gnupg.nix
@@ -85,11 +85,13 @@ in
       # SSH agent protocol doesn't support changing TTYs, so bind the agent
       # to every new TTY.
       ${pkgs.gnupg}/bin/gpg-connect-agent --quiet updatestartuptty /bye > /dev/null
+    '');
 
+    environment.extraInit = mkIf cfg.agent.enableSSHSupport ''
       if [ -z "$SSH_AUTH_SOCK" ]; then
         export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
       fi
-    '');
+    '';
 
     assertions = [
       { assertion = cfg.agent.enableSSHSupport -> !config.programs.ssh.startAgent;
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 1e6557e1f0e..7fb58a2b800 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -186,6 +186,9 @@ with lib;
     # parsoid
     (mkRemovedOptionModule [ "services" "parsoid" "interwikis" ] [ "services" "parsoid" "wikis" ])
 
+    # plexpy / tautulli
+    (mkRenamedOptionModule [ "services" "plexpy" ] [ "services" "tautulli" ])
+
     # piwik was renamed to matomo
     (mkRenamedOptionModule [ "services" "piwik" "enable" ] [ "services" "matomo" "enable" ])
     (mkRenamedOptionModule [ "services" "piwik" "webServerUser" ] [ "services" "matomo" "webServerUser" ])
diff --git a/nixos/modules/security/duosec.nix b/nixos/modules/security/duosec.nix
index df6108dede7..14bf118f2d8 100644
--- a/nixos/modules/security/duosec.nix
+++ b/nixos/modules/security/duosec.nix
@@ -7,7 +7,7 @@ let
 
   boolToStr = b: if b then "yes" else "no";
 
-  configFile = ''
+  configFilePam = ''
     [duo]
     ikey=${cfg.ikey}
     skey=${cfg.skey}
@@ -16,21 +16,24 @@ let
     failmode=${cfg.failmode}
     pushinfo=${boolToStr cfg.pushinfo}
     autopush=${boolToStr cfg.autopush}
-    motd=${boolToStr cfg.motd}
     prompts=${toString cfg.prompts}
-    accept_env_factor=${boolToStr cfg.acceptEnvFactor}
     fallback_local_ip=${boolToStr cfg.fallbackLocalIP}
   '';
 
+  configFileLogin = configFilePam + ''
+    motd=${boolToStr cfg.motd}
+    accept_env_factor=${boolToStr cfg.acceptEnvFactor}
+  '';
+
   loginCfgFile = optional cfg.ssh.enable
-    { source = pkgs.writeText "login_duo.conf" configFile;
+    { source = pkgs.writeText "login_duo.conf" configFileLogin;
       mode   = "0600";
       user   = "sshd";
       target = "duo/login_duo.conf";
     };
 
   pamCfgFile = optional cfg.pam.enable
-    { source = pkgs.writeText "pam_duo.conf" configFile;
+    { source = pkgs.writeText "pam_duo.conf" configFilePam;
       mode   = "0600";
       user   = "sshd";
       target = "duo/pam_duo.conf";
@@ -180,12 +183,6 @@ in
   };
 
   config = mkIf (cfg.ssh.enable || cfg.pam.enable) {
-    assertions =
-      [ { assertion = !cfg.pam.enable;
-          message   = "PAM support is currently not implemented.";
-        }
-      ];
-
      environment.systemPackages = [ pkgs.duo-unix ];
 
      security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo";
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 206b529ed68..03d2f899f2a 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -131,6 +131,18 @@ let
         '';
       };
 
+      duoSecurity = {
+        enable = mkOption {
+          default = false;
+          type = types.bool;
+          description = ''
+            If set, use the Duo Security pam module
+            <literal>pam_duo</literal> for authentication.  Requires
+            configuration of <option>security.duosec</option> options.
+          '';
+        };
+      };
+
       startSession = mkOption {
         default = false;
         type = types.bool;
@@ -340,7 +352,8 @@ let
             || cfg.pamMount
             || cfg.enableKwallet
             || cfg.enableGnomeKeyring
-            || cfg.googleAuthenticator.enable)) ''
+            || cfg.googleAuthenticator.enable
+            || cfg.duoSecurity.enable)) ''
               auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth
               ${optionalString config.security.pam.enableEcryptfs
                 "auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
@@ -350,9 +363,11 @@ let
                 ("auth optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
                  " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
               ${optionalString cfg.enableGnomeKeyring
-                ("auth optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so")}
+                "auth optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so"}
               ${optionalString cfg.googleAuthenticator.enable
-                  "auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp"}
+                "auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp"}
+              ${optionalString cfg.duoSecurity.enable
+                "auth required ${pkgs.duo-unix}/lib/security/pam_duo.so"}
             '') + ''
           ${optionalString cfg.unixAuth
               "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
diff --git a/nixos/modules/services/audio/snapserver.nix b/nixos/modules/services/audio/snapserver.nix
new file mode 100644
index 00000000000..f709dd7fe16
--- /dev/null
+++ b/nixos/modules/services/audio/snapserver.nix
@@ -0,0 +1,217 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  package = "snapcast";
+  name = "snapserver";
+
+  cfg = config.services.snapserver;
+
+  # Using types.nullOr to inherit upstream defaults.
+  sampleFormat = mkOption {
+    type = with types; nullOr str;
+    default = null;
+    description = ''
+      Default sample format.
+    '';
+    example = "48000:16:2";
+  };
+
+  codec = mkOption {
+    type = with types; nullOr str;
+    default = null;
+    description = ''
+      Default audio compression method.
+    '';
+    example = "flac";
+  };
+
+  streamToOption = name: opt:
+    let
+      os = val:
+        optionalString (val != null) "${val}";
+      os' = prefixx: val:
+        optionalString (val != null) (prefixx + "${val}");
+      flatten = key: value:
+        "&${key}=${value}";
+    in
+      "-s ${opt.type}://" + os opt.location + "?" + os' "name=" name
+        + concatStrings (mapAttrsToList flatten opt.query);
+
+  optionalNull = val: ret:
+    optional (val != null) ret;
+
+  optionString = concatStringsSep " " (mapAttrsToList streamToOption cfg.streams
+             ++ ["-p ${toString cfg.port}"]
+             ++ ["--controlPort ${toString cfg.controlPort}"]
+             ++ optionalNull cfg.sampleFormat "--sampleFormat ${cfg.sampleFormat}"
+             ++ optionalNull cfg.codec "-c ${cfg.codec}"
+             ++ optionalNull cfg.streamBuffer "--streamBuffer ${cfg.streamBuffer}"
+             ++ optionalNull cfg.buffer "-b ${cfg.buffer}"
+             ++ optional cfg.sendToMuted "--sendToMuted");
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.snapserver = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable snapserver.
+        '';
+      };
+
+      port = mkOption {
+        type = types.port;
+        default = 1704;
+        description = ''
+          The port that snapclients can connect to.
+        '';
+      };
+
+      controlPort = mkOption {
+        type = types.port;
+        default = 1705;
+        description = ''
+          The port for control connections (JSON-RPC).
+        '';
+      };
+
+      openFirewall = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to automatically open the specified ports in the firewall.
+        '';
+      };
+
+      inherit sampleFormat;
+      inherit codec;
+
+      streams = mkOption {
+        type = with types; attrsOf (submodule {
+          options = {
+            location = mkOption {
+              type = types.path;
+              description = ''
+                The location of the pipe.
+              '';
+            };
+            type = mkOption {
+              type = types.enum [ "pipe" "file" "process" "spotify" "airplay" ];
+              default = "pipe";
+              description = ''
+                The type of input stream.
+              '';
+            };
+            query = mkOption {
+              type = attrsOf str;
+              default = {};
+              description = ''
+                Key-value pairs that convey additional parameters about a stream.
+              '';
+              example = literalExample ''
+                # for type == "pipe":
+                {
+                  mode = "listen";
+                };
+                # for type == "process":
+                {
+                  params = "--param1 --param2";
+                  logStderr = "true";
+                };
+              '';
+            };
+            inherit sampleFormat;
+            inherit codec;
+          };
+        });
+        default = { default = {}; };
+        description = ''
+          The definition for an input source.
+        '';
+        example = literalExample ''
+          {
+            mpd = {
+              type = "pipe";
+              location = "/run/snapserver/mpd";
+              sampleFormat = "48000:16:2";
+              codec = "pcm";
+            };
+          };
+        '';
+      };
+
+      streamBuffer = mkOption {
+        type = with types; nullOr int;
+        default = null;
+        description = ''
+          Stream read (input) buffer in ms.
+        '';
+        example = 20;
+      };
+
+      buffer = mkOption {
+        type = with types; nullOr int;
+        default = null;
+        description = ''
+          Network buffer in ms.
+        '';
+        example = 1000;
+      };
+
+      sendToMuted = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Send audio to muted clients.
+        '';
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.snapserver = {
+      after = [ "network.target" ];
+      description = "Snapserver";
+      wantedBy = [ "multi-user.target" ];
+      before = [ "mpd.service" "mopidy.service" ];
+
+      serviceConfig = {
+        DynamicUser = true;
+        ExecStart = "${pkgs.snapcast}/bin/snapserver --daemon ${optionString}";
+        Type = "forking";
+        LimitRTPRIO = 50;
+        LimitRTTIME = "infinity";
+        NoNewPrivileges = true;
+        PIDFile = "/run/${name}/pid";
+        ProtectKernelTunables = true;
+        ProtectControlGroups = true;
+        ProtectKernelModules = true;
+        RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
+        RestrictNamespaces = true;
+        RuntimeDirectory = name;
+        StateDirectory = name;
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = optionals cfg.openFirewall [ cfg.port cfg.controlPort ];
+  };
+
+  meta = {
+    maintainers = with maintainers; [ tobim ];
+  };
+
+}
diff --git a/nixos/modules/services/backup/duplicity.nix b/nixos/modules/services/backup/duplicity.nix
new file mode 100644
index 00000000000..a8d56424862
--- /dev/null
+++ b/nixos/modules/services/backup/duplicity.nix
@@ -0,0 +1,141 @@
+{ config, lib, pkgs, ...}:
+
+with lib;
+
+let
+  cfg = config.services.duplicity;
+
+  stateDirectory = "/var/lib/duplicity";
+
+  localTarget = if hasPrefix "file://" cfg.targetUrl
+    then removePrefix "file://" cfg.targetUrl else null;
+
+in {
+  options.services.duplicity = {
+    enable = mkEnableOption "backups with duplicity";
+
+    root = mkOption {
+      type = types.path;
+      default = "/";
+      description = ''
+        Root directory to backup.
+      '';
+    };
+
+    include = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "/home" ];
+      description = ''
+        List of paths to include into the backups. See the FILE SELECTION
+        section in <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry> for details on the syntax.
+      '';
+    };
+
+    exclude = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      description = ''
+        List of paths to exclude from backups. See the FILE SELECTION section in
+        <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry> for details on the syntax.
+      '';
+    };
+
+    targetUrl = mkOption {
+      type = types.str;
+      example = "s3://host:port/prefix";
+      description = ''
+        Target url to backup to. See the URL FORMAT section in
+        <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry> for supported urls.
+      '';
+    };
+
+    secretFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Path of a file containing secrets (gpg passphrase, access key...) in
+        the format of EnvironmentFile as described by
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry>. For example:
+        <programlisting>
+        PASSPHRASE=<replaceable>...</replaceable>
+        AWS_ACCESS_KEY_ID=<replaceable>...</replaceable>
+        AWS_SECRET_ACCESS_KEY=<replaceable>...</replaceable>
+        </programlisting>
+      '';
+    };
+
+    frequency = mkOption {
+      type = types.nullOr types.str;
+      default = "daily";
+      description = ''
+        Run duplicity with the given frequency (see
+        <citerefentry><refentrytitle>systemd.time</refentrytitle>
+        <manvolnum>7</manvolnum></citerefentry> for the format).
+        If null, do not run automatically.
+      '';
+    };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "--full-if-older-than" "1M" ];
+      description = ''
+        Extra command-line flags passed to duplicity. See
+        <citerefentry><refentrytitle>duplicity</refentrytitle>
+        <manvolnum>1</manvolnum></citerefentry>.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd = {
+      services.duplicity = {
+        description = "backup files with duplicity";
+
+        environment.HOME = stateDirectory;
+
+        serviceConfig = {
+          ExecStart = ''
+            ${pkgs.duplicity}/bin/duplicity ${escapeShellArgs (
+              [
+                cfg.root
+                cfg.targetUrl
+                "--archive-dir" stateDirectory
+              ]
+              ++ concatMap (p: [ "--include" p ]) cfg.include
+              ++ concatMap (p: [ "--exclude" p ]) cfg.exclude
+              ++ cfg.extraFlags)}
+          '';
+          PrivateTmp = true;
+          ProtectSystem = "strict";
+          ProtectHome = "read-only";
+          StateDirectory = baseNameOf stateDirectory;
+        } // optionalAttrs (localTarget != null) {
+          ReadWritePaths = localTarget;
+        } // optionalAttrs (cfg.secretFile != null) {
+          EnvironmentFile = cfg.secretFile;
+        };
+      } // optionalAttrs (cfg.frequency != null) {
+        startAt = cfg.frequency;
+      };
+
+      tmpfiles.rules = optional (localTarget != null) "d ${localTarget} 0700 root root -";
+    };
+
+    assertions = singleton {
+      # Duplicity will fail if the last file selection option is an include. It
+      # is not always possible to detect but this simple case can be caught.
+      assertion = cfg.include != [] -> cfg.exclude != [] || cfg.extraFlags != [];
+      message = ''
+        Duplicity will fail if you only specify included paths ("Because the
+        default is to include all files, the expression is redundant. Exiting
+        because this probably isn't what you meant.")
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/services/cluster/kubernetes/apiserver.nix b/nixos/modules/services/cluster/kubernetes/apiserver.nix
index 81e45b417de..455d0239604 100644
--- a/nixos/modules/services/cluster/kubernetes/apiserver.nix
+++ b/nixos/modules/services/cluster/kubernetes/apiserver.nix
@@ -350,7 +350,7 @@ in
           listenPeerUrls = mkDefault ["https://0.0.0.0:2380"];
           advertiseClientUrls = mkDefault ["https://${top.masterAddress}:2379"];
           initialCluster = mkDefault ["${top.masterAddress}=https://${top.masterAddress}:2380"];
-          name = top.masterAddress;
+          name = mkDefault top.masterAddress;
           initialAdvertisePeerUrls = mkDefault ["https://${top.masterAddress}:2380"];
         };
 
diff --git a/nixos/modules/services/cluster/kubernetes/controller-manager.nix b/nixos/modules/services/cluster/kubernetes/controller-manager.nix
index dff97f144d5..060fd9b78db 100644
--- a/nixos/modules/services/cluster/kubernetes/controller-manager.nix
+++ b/nixos/modules/services/cluster/kubernetes/controller-manager.nix
@@ -131,7 +131,7 @@ in
           ${optionalString (cfg.tlsCertFile!=null)
             "--tls-cert-file=${cfg.tlsCertFile}"} \
           ${optionalString (cfg.tlsKeyFile!=null)
-            "--tls-key-file=${cfg.tlsKeyFile}"} \
+            "--tls-private-key-file=${cfg.tlsKeyFile}"} \
           ${optionalString (elem "RBAC" top.apiserver.authorizationMode)
             "--use-service-account-credentials"} \
           ${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
diff --git a/nixos/modules/services/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix
index 375e33e91b5..3e53d18f8bb 100644
--- a/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixos/modules/services/cluster/kubernetes/default.nix
@@ -10,7 +10,7 @@ let
     kind = "Config";
     clusters = [{
       name = "local";
-      cluster.certificate-authority = cfg.caFile;
+      cluster.certificate-authority = conf.caFile or cfg.caFile;
       cluster.server = conf.server;
     }];
     users = [{
diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix
index e996211be7d..5c302752781 100644
--- a/nixos/modules/services/databases/openldap.nix
+++ b/nixos/modules/services/databases/openldap.nix
@@ -146,7 +146,7 @@ in
         chown -R "${cfg.user}:${cfg.group}" "${cfg.dataDir}"
       '';
       serviceConfig.ExecStart =
-        "${openldap.out}/libexec/slapd -d ${cfg.logLevel} " +
+        "${openldap.out}/libexec/slapd -d '${cfg.logLevel}' " +
           "-u '${cfg.user}' -g '${cfg.group}' " +
           "-h '${concatStringsSep " " cfg.urlList}' " +
           "${configOpts}";
diff --git a/nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix b/nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix
new file mode 100644
index 00000000000..dbf0f4e9b11
--- /dev/null
+++ b/nixos/modules/services/desktops/gnome3/gnome-settings-daemon.nix
@@ -0,0 +1,45 @@
+# GNOME Settings Daemon
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.gnome3.gnome-settings-daemon;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.gnome3.gnome-settings-daemon = {
+
+      enable = mkEnableOption "GNOME Settings Daemon.";
+
+      # There are many forks of gnome-settings-daemon
+      package = mkOption {
+        type = types.package;
+        default = pkgs.gnome3.gnome-settings-daemon;
+        description = "Which gnome-settings-daemon package to use.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ cfg.package ];
+
+    services.udev.packages = [ cfg.package ];
+
+  };
+
+}
diff --git a/nixos/modules/services/hardware/thinkfan.nix b/nixos/modules/services/hardware/thinkfan.nix
index d17121ca1c5..7c105e99ca5 100644
--- a/nixos/modules/services/hardware/thinkfan.nix
+++ b/nixos/modules/services/hardware/thinkfan.nix
@@ -47,6 +47,8 @@ let
     ${cfg.levels}
   '';
 
+  thinkfan = pkgs.thinkfan.override { smartSupport = cfg.smartSupport; };
+
 in {
 
   options = {
@@ -61,6 +63,15 @@ in {
         '';
       };
 
+      smartSupport = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to build thinkfan with SMART support to read temperatures 
+          directly from hard disks.
+        '';
+      };
+
       sensors = mkOption {
         type = types.lines;
         default = ''
@@ -77,7 +88,7 @@ in {
               Which may be provided by any hwmon drivers (keyword
               hwmon)
 
-            S.M.A.R.T. (since 0.9 and requires the USE_ATASMART compilation flag)
+            S.M.A.R.T. (requires smartSupport to be enabled)
               Which reads the temperature directly from the hard
               disk using libatasmart (keyword atasmart)
 
@@ -125,18 +136,17 @@ in {
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.thinkfan ];
+    environment.systemPackages = [ thinkfan ];
 
     systemd.services.thinkfan = {
       description = "Thinkfan";
       after = [ "basic.target" ];
       wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.thinkfan ];
-      serviceConfig.ExecStart = "${pkgs.thinkfan}/bin/thinkfan -n -c ${configFile}";
+      path = [ thinkfan ];
+      serviceConfig.ExecStart = "${thinkfan}/bin/thinkfan -n -c ${configFile}";
     };
 
     boot.extraModprobeConfig = "options thinkpad_acpi experimental=1 fan_control=1";
 
   };
-
 }
diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix
index 492c6458321..466365b6b30 100644
--- a/nixos/modules/services/mail/rmilter.nix
+++ b/nixos/modules/services/mail/rmilter.nix
@@ -8,7 +8,7 @@ let
   postfixCfg = config.services.postfix;
   cfg = config.services.rmilter;
 
-  inetSocket = addr: port: "inet:[${toString port}@${addr}]";
+  inetSocket = addr: port: "inet:${addr}:${toString port}";
   unixSocket = sock: "unix:${sock}";
 
   systemdSocket = if cfg.bindSocket.type == "unix" then cfg.bindSocket.path
@@ -97,7 +97,7 @@ in
 
       bindSocket.address = mkOption {
         type = types.str;
-        default = "::1";
+        default = "[::1]";
         example = "0.0.0.0";
         description = ''
           Inet address to listen on.
diff --git a/nixos/modules/services/misc/bepasty.nix b/nixos/modules/services/misc/bepasty.nix
index 62835c194e4..006feca42b3 100644
--- a/nixos/modules/services/misc/bepasty.nix
+++ b/nixos/modules/services/misc/bepasty.nix
@@ -2,10 +2,10 @@
 
 with lib;
 let
-  gunicorn = pkgs.pythonPackages.gunicorn;
+  gunicorn = pkgs.python3Packages.gunicorn;
   bepasty = pkgs.bepasty;
-  gevent = pkgs.pythonPackages.gevent;
-  python = pkgs.pythonPackages.python;
+  gevent = pkgs.python3Packages.gevent;
+  python = pkgs.python3Packages.python;
   cfg = config.services.bepasty;
   user = "bepasty";
   group = "bepasty";
diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix
index 95a7f2ea989..7f8d31bcf0b 100644
--- a/nixos/modules/services/misc/home-assistant.nix
+++ b/nixos/modules/services/misc/home-assistant.nix
@@ -9,13 +9,13 @@ let
   configJSON = pkgs.writeText "configuration.json"
     (builtins.toJSON (if cfg.applyDefaultConfig then
     (recursiveUpdate defaultConfig cfg.config) else cfg.config));
-  configFile = pkgs.runCommand "configuration.yaml" { } ''
+  configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
     ${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
   '';
 
   lovelaceConfigJSON = pkgs.writeText "ui-lovelace.json"
     (builtins.toJSON cfg.lovelaceConfig);
-  lovelaceConfigFile = pkgs.runCommand "ui-lovelace.yaml" { } ''
+  lovelaceConfigFile = pkgs.runCommand "ui-lovelace.yaml" { preferLocalBuild = true; } ''
     ${pkgs.remarshal}/bin/json2yaml -i ${lovelaceConfigJSON} -o $out
   '';
 
@@ -29,14 +29,24 @@ let
   #   platform = "luftdaten";
   #   ...
   # } ];
+  #
+  # Beginning with 0.87 Home Assistant is migrating their components to the
+  # scheme "platform.subComponent", e.g. "hue.light" instead of "light.hue".
+  # See https://developers.home-assistant.io/blog/2019/02/19/the-great-migration.html.
+  # Hence, we also check whether we find an entry in the config when interpreting
+  # the first part of the path as the component.
   useComponentPlatform = component:
     let
       path = splitString "." component;
+      # old: platform is the last part of path
       parentConfig = attrByPath (init path) null cfg.config;
       platform = last path;
-    in isList parentConfig && any
-      (item: item.platform or null == platform)
-      parentConfig;
+      # new: platform is the first part of the path
+      parentConfig' = attrByPath (tail path) null cfg.config;
+      platform' = head path;
+    in
+      (isList parentConfig && any (item: item.platform or null == platform) parentConfig)
+      || (isList parentConfig' && any (item: item.platform or null == platform') parentConfig');
 
   # Returns whether component is used in config
   useComponent = component:
diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix
index 98e9c8953c8..c38138d7c97 100644
--- a/nixos/modules/services/misc/redmine.nix
+++ b/nixos/modules/services/misc/redmine.nix
@@ -234,10 +234,33 @@ in
 
     environment.systemPackages = [ cfg.package ];
 
+    # create symlinks for the basic directory layout the redmine package expects
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/cache' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/config' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/files' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/log' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/plugins' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/public' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/public/plugin_assets' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/public/themes' 0750 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.stateDir}/tmp' 0750 ${cfg.user} ${cfg.group} - -"
+
+      "d /run/redmine - - - - -"
+      "d /run/redmine/public - - - - -"
+      "L+ /run/redmine/config - - - - ${cfg.stateDir}/config"
+      "L+ /run/redmine/files - - - - ${cfg.stateDir}/files"
+      "L+ /run/redmine/log - - - - ${cfg.stateDir}/log"
+      "L+ /run/redmine/plugins - - - - ${cfg.stateDir}/plugins"
+      "L+ /run/redmine/public/plugin_assets - - - - ${cfg.stateDir}/public/plugin_assets"
+      "L+ /run/redmine/public/themes - - - - ${cfg.stateDir}/public/themes"
+      "L+ /run/redmine/tmp - - - - ${cfg.stateDir}/tmp"
+    ];
+
     systemd.services.redmine = {
       after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
       wantedBy = [ "multi-user.target" ];
-      environment.HOME = "${cfg.package}/share/redmine";
       environment.RAILS_ENV = "production";
       environment.RAILS_CACHE = "${cfg.stateDir}/cache";
       environment.REDMINE_LANG = "en";
@@ -252,28 +275,16 @@ in
         subversion
       ];
       preStart = ''
-        # ensure cache directory exists for db:migrate command
-        mkdir -p "${cfg.stateDir}/cache"
-
-        # create the basic directory layout the redmine package expects
-        mkdir -p /run/redmine/public
-
-        for i in config files log plugins tmp; do
-          mkdir -p "${cfg.stateDir}/$i"
-          ln -fs "${cfg.stateDir}/$i" /run/redmine/
-        done
-
-        for i in plugin_assets themes; do
-          mkdir -p "${cfg.stateDir}/public/$i"
-          ln -fs "${cfg.stateDir}/public/$i" /run/redmine/public/
-        done
-
+        rm -rf "${cfg.stateDir}/plugins/"*
+        rm -rf "${cfg.stateDir}/public/themes/"*
 
         # start with a fresh config directory
         # the config directory is copied instead of linked as some mutable data is stored in there
-        rm -rf "${cfg.stateDir}/config/"*
+        find "${cfg.stateDir}/config" ! -name "secret_token.rb" -type f -exec rm -f {} +
         cp -r ${cfg.package}/share/redmine/config.dist/* "${cfg.stateDir}/config/"
 
+        chmod -R u+w "${cfg.stateDir}/config"
+
         # link in the application configuration
         ln -fs ${configurationYml} "${cfg.stateDir}/config/configuration.yml"
 
@@ -282,7 +293,6 @@ in
 
 
         # link in all user specified themes
-        rm -rf "${cfg.stateDir}/public/themes/"*
         for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do
           ln -fs $theme/* "${cfg.stateDir}/public/themes"
         done
@@ -292,16 +302,11 @@ in
 
 
         # link in all user specified plugins
-        rm -rf "${cfg.stateDir}/plugins/"*
         for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do
           ln -fs $plugin/* "${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-}"
         done
 
 
-        # ensure correct permissions for most files
-        chmod -R ug+rwX,o-rwx+x "${cfg.stateDir}/"
-
-
         # handle database.passwordFile & permissions
         DBPASS=$(head -n1 ${cfg.database.passwordFile})
         cp -f ${databaseYml} "${cfg.stateDir}/config/database.yml"
@@ -315,25 +320,13 @@ in
           chmod 440 "${cfg.stateDir}/config/initializers/secret_token.rb"
         fi
 
-
-        # ensure everything is owned by ${cfg.user}
-        chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}"
-
-
         # execute redmine required commands prior to starting the application
-        # NOTE: su required in case using mysql socket authentication
-        /run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake db:migrate'
-        /run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake redmine:plugins:migrate'
-        /run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake redmine:load_default_data'
-
-
-        # log files don't exist until after first command has been executed
-        # correct ownership of files generated by calling exec rake ...
-        chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}/log"
+        ${bundle} exec rake db:migrate
+        ${bundle} exec rake redmine:plugins:migrate
+        ${bundle} exec rake redmine:load_default_data
       '';
 
       serviceConfig = {
-        PermissionsStartOnly = true; # preStart must be run as root
         Type = "simple";
         User = cfg.user;
         Group = cfg.group;
@@ -348,7 +341,6 @@ in
       { name = "redmine";
         group = cfg.group;
         home = cfg.stateDir;
-        createHome = true;
         uid = config.ids.uids.redmine;
       });
 
diff --git a/nixos/modules/services/misc/plexpy.nix b/nixos/modules/services/misc/tautulli.nix
index 2a589fdfb27..50e45036647 100644
--- a/nixos/modules/services/misc/plexpy.nix
+++ b/nixos/modules/services/misc/tautulli.nix
@@ -3,73 +3,69 @@
 with lib;
 
 let
-  cfg = config.services.plexpy;
+  cfg = config.services.tautulli;
 in
 {
   options = {
-    services.plexpy = {
-      enable = mkEnableOption "PlexPy Plex Monitor";
+    services.tautulli = {
+      enable = mkEnableOption "Tautulli Plex Monitor";
 
       dataDir = mkOption {
         type = types.str;
         default = "/var/lib/plexpy";
-        description = "The directory where PlexPy stores its data files.";
+        description = "The directory where Tautulli stores its data files.";
       };
 
       configFile = mkOption {
         type = types.str;
         default = "/var/lib/plexpy/config.ini";
-        description = "The location of PlexPy's config file.";
+        description = "The location of Tautulli's config file.";
       };
 
       port = mkOption {
         type = types.int;
         default = 8181;
-        description = "TCP port where PlexPy listens.";
+        description = "TCP port where Tautulli listens.";
       };
 
       user = mkOption {
         type = types.str;
         default = "plexpy";
-        description = "User account under which PlexPy runs.";
+        description = "User account under which Tautulli runs.";
       };
 
       group = mkOption {
         type = types.str;
         default = "nogroup";
-        description = "Group under which PlexPy runs.";
+        description = "Group under which Tautulli runs.";
       };
 
       package = mkOption {
         type = types.package;
-        default = pkgs.plexpy;
-        defaultText = "pkgs.plexpy";
+        default = pkgs.tautulli;
+        defaultText = "pkgs.tautulli";
         description = ''
-          The PlexPy package to use.
+          The Tautulli package to use.
         '';
       };
     };
   };
 
   config = mkIf cfg.enable {
-    systemd.services.plexpy = {
-      description = "PlexPy Plex Monitor";
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - ${cfg.user} ${cfg.group} - -"
+    ];
+
+    systemd.services.tautulli = {
+      description = "Tautulli Plex Monitor";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        test -d "${cfg.dataDir}" || {
-          echo "Creating initial PlexPy data directory in \"${cfg.dataDir}\"."
-          mkdir -p "${cfg.dataDir}"
-          chown ${cfg.user}:${cfg.group} "${cfg.dataDir}"
-        }
-     '';
       serviceConfig = {
         Type = "simple";
         User = cfg.user;
         Group = cfg.group;
-        PermissionsStartOnly = "true";
         GuessMainPID = "false";
-        ExecStart = "${cfg.package}/bin/plexpy --datadir ${cfg.dataDir} --config ${cfg.configFile} --port ${toString cfg.port} --pidfile ${cfg.dataDir}/plexpy.pid --nolaunch";
+        ExecStart = "${cfg.package}/bin/tautulli --datadir ${cfg.dataDir} --config ${cfg.configFile} --port ${toString cfg.port} --pidfile ${cfg.dataDir}/tautulli.pid --nolaunch";
         Restart = "on-failure";
       };
     };
diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix
index ae7de7850d9..fb9c4c41ae2 100644
--- a/nixos/modules/services/misc/zoneminder.nix
+++ b/nixos/modules/services/misc/zoneminder.nix
@@ -275,14 +275,14 @@ in {
       };
 
       phpfpm = lib.mkIf useNginx {
-        phpOptions = ''
-          date.timezone = "${config.time.timeZone}"
-
-          ${lib.concatStringsSep "\n" (map (e:
-          "extension=${e.pkg}/lib/php/extensions/${e.name}.so") phpExtensions)}
-        '';
         pools.zoneminder = {
           listen = socket;
+          phpOptions = ''
+            date.timezone = "${config.time.timeZone}"
+
+            ${lib.concatStringsSep "\n" (map (e:
+            "extension=${e.pkg}/lib/php/extensions/${e.name}.so") phpExtensions)}
+          '';
           extraConfig = ''
             user = ${user}
             group = ${group}
diff --git a/nixos/modules/services/monitoring/datadog-agent.nix b/nixos/modules/services/monitoring/datadog-agent.nix
index a4d29d45bac..b4ac0ca184d 100644
--- a/nixos/modules/services/monitoring/datadog-agent.nix
+++ b/nixos/modules/services/monitoring/datadog-agent.nix
@@ -202,7 +202,7 @@ in {
     };
   };
   config = mkIf cfg.enable {
-    environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps ];
+    environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps pkgs.iproute ];
 
     users.extraUsers.datadog = {
       description = "Datadog Agent User";
@@ -216,7 +216,7 @@ in {
 
     systemd.services = let
       makeService = attrs: recursiveUpdate {
-        path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps ];
+        path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.iproute ];
         wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           User = "datadog";
@@ -260,7 +260,7 @@ in {
         path = [ ];
         script = ''
           export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
-          ${pkgs.datadog-trace-agent}/bin/trace-agent -config /etc/datadog-agent/datadog.yaml
+          ${datadogPkg}/bin/trace-agent -config /etc/datadog-agent/datadog.yaml
         '';
       });
 
diff --git a/nixos/modules/services/monitoring/hdaps.nix b/nixos/modules/services/monitoring/hdaps.nix
index be26c44e78d..2cad3b84d84 100644
--- a/nixos/modules/services/monitoring/hdaps.nix
+++ b/nixos/modules/services/monitoring/hdaps.nix
@@ -16,6 +16,7 @@ in
   };
 
   config = mkIf cfg.enable {
+    boot.kernelModules = [ "hdapsd" ];
     services.udev.packages = hdapsd;
     systemd.packages = hdapsd;
   };
diff --git a/nixos/modules/services/monitoring/prometheus/alertmanager.nix b/nixos/modules/services/monitoring/prometheus/alertmanager.nix
index 43b4a41eaf3..7d790b6b590 100644
--- a/nixos/modules/services/monitoring/prometheus/alertmanager.nix
+++ b/nixos/modules/services/monitoring/prometheus/alertmanager.nix
@@ -106,7 +106,8 @@ in {
         type = types.str;
         default = "";
         description = ''
-          Address to listen on for the web interface and API.
+          Address to listen on for the web interface and API. Empty string will listen on all interfaces.
+          "localhost" will listen on 127.0.0.1 (but not ::1).
         '';
       };
 
diff --git a/nixos/modules/services/network-filesystems/openafs/client.nix b/nixos/modules/services/network-filesystems/openafs/client.nix
index 93d2d7fcd97..79c4b7aee06 100644
--- a/nixos/modules/services/network-filesystems/openafs/client.nix
+++ b/nixos/modules/services/network-filesystems/openafs/client.nix
@@ -155,7 +155,7 @@ in
         };
         programs = mkOption {
           default = getBin pkgs.openafs;
-          defaultText = "config.boot.kernelPackages.openafs";
+          defaultText = "getBin pkgs.openafs";
           type = types.package;
           description = "OpenAFS programs package. MUST match the kernel module package!";
         };
diff --git a/nixos/modules/services/networking/coredns.nix b/nixos/modules/services/networking/coredns.nix
new file mode 100644
index 00000000000..afb2b547a46
--- /dev/null
+++ b/nixos/modules/services/networking/coredns.nix
@@ -0,0 +1,50 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.coredns;
+  configFile = pkgs.writeText "Corefile" cfg.config;
+in {
+  options.services.coredns = {
+    enable = mkEnableOption "Coredns dns server";
+
+    config = mkOption {
+      default = "";
+      example = ''
+        . {
+          whoami
+        }
+      '';
+      type = types.lines;
+      description = "Verbatim Corefile to use. See <link xlink:href=\"https://coredns.io/manual/toc/#configuration\"/> for details.";
+    };
+
+    package = mkOption {
+      default = pkgs.coredns;
+      defaultText = "pkgs.coredns";
+      type = types.package;
+      description = "Coredns package to use.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.coredns = {
+      description = "Coredns dns server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        PermissionsStartOnly = true;
+        LimitNPROC = 512;
+        LimitNOFILE = 1048576;
+        CapabilityBoundingSet = "cap_net_bind_service";
+        AmbientCapabilities = "cap_net_bind_service";
+        NoNewPrivileges = true;
+        DynamicUser = true;
+        ExecStart = "${getBin cfg.package}/bin/coredns -conf=${configFile}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -SIGUSR1 $MAINPID";
+        Restart = "on-failure";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/gnunet.nix b/nixos/modules/services/networking/gnunet.nix
index 6a1db81413c..178a832c166 100644
--- a/nixos/modules/services/networking/gnunet.nix
+++ b/nixos/modules/services/networking/gnunet.nix
@@ -130,7 +130,7 @@ in
       group = "gnunet";
       description = "GNUnet User";
       home = homeDir;
-      createHome = true; 
+      createHome = true;
       uid = config.ids.uids.gnunet;
     };
 
@@ -146,7 +146,7 @@ in
       wantedBy = [ "multi-user.target" ];
       path = [ cfg.package pkgs.miniupnpc ];
       environment.TMPDIR = "/tmp";
-      serviceConfig.PrivateTemp = true;
+      serviceConfig.PrivateTmp = true;
       serviceConfig.ExecStart = "${cfg.package}/lib/gnunet/libexec/gnunet-service-arm -c ${configFile}";
       serviceConfig.User = "gnunet";
       serviceConfig.UMask = "0007";
diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix
index 332dc541345..9974cbd89d1 100644
--- a/nixos/modules/services/networking/mosquitto.nix
+++ b/nixos/modules/services/networking/mosquitto.nix
@@ -17,7 +17,6 @@ let
   '';
 
   mosquittoConf = pkgs.writeText "mosquitto.conf" ''
-    pid_file /run/mosquitto/pid
     acl_file ${aclFile}
     persistence true
     allow_anonymous ${boolToString cfg.allowAnonymous}
@@ -196,15 +195,15 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
       serviceConfig = {
-        Type = "forking";
+        Type = "notify";
+        NotifyAccess = "main";
         User = "mosquitto";
         Group = "mosquitto";
         RuntimeDirectory = "mosquitto";
         WorkingDirectory = cfg.dataDir;
         Restart = "on-failure";
-        ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf} -d";
+        ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-        PIDFile = "/run/mosquitto/pid";
       };
       preStart = ''
         rm -f ${cfg.dataDir}/passwd
@@ -214,7 +213,7 @@ in
           if c.hashedPassword != null then
             "echo '${n}:${c.hashedPassword}' >> ${cfg.dataDir}/passwd"
           else optionalString (c.password != null)
-            "${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}"
+            "${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} '${c.password}'"
         ) cfg.users);
     };
 
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 95dc8a62a45..b9b5d40c457 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -400,7 +400,10 @@ in
         sockets.sshd =
           { description = "SSH Socket";
             wantedBy = [ "sockets.target" ];
-            socketConfig.ListenStream = cfg.ports;
+            socketConfig.ListenStream = if cfg.listenAddresses != [] then
+              map (l: "${l.addr}:${toString (if l.port != null then l.port else 22)}") cfg.listenAddresses
+            else
+              cfg.ports;
             socketConfig.Accept = true;
           };
 
diff --git a/nixos/modules/services/networking/strongswan-swanctl/module.nix b/nixos/modules/services/networking/strongswan-swanctl/module.nix
index d770094960b..817b5ec55f7 100644
--- a/nixos/modules/services/networking/strongswan-swanctl/module.nix
+++ b/nixos/modules/services/networking/strongswan-swanctl/module.nix
@@ -65,9 +65,12 @@ in  {
       after    = [ "network-online.target" "keys.target" ];
       wants    = [ "keys.target" ];
       path = with pkgs; [ kmod iproute iptables utillinux ];
-      environment.STRONGSWAN_CONF = pkgs.writeTextFile {
-        name = "strongswan.conf";
-        text = cfg.strongswan.extraConfig;
+      environment = {
+        STRONGSWAN_CONF = pkgs.writeTextFile {
+          name = "strongswan.conf";
+          text = cfg.strongswan.extraConfig;
+        };
+        SWANCTL_DIR = "/etc/swanctl";
       };
       restartTriggers = [ config.environment.etc."swanctl/swanctl.conf".source ];
       serviceConfig = {
diff --git a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix
index ccaa2cff1c2..50775c5262f 100644
--- a/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix
+++ b/nixos/modules/services/web-apps/icingaweb2/icingaweb2.nix
@@ -546,26 +546,26 @@ in {
 
   config = mkIf cfg.enable {
     services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") {
-      "${poolName}" = ''
-        listen = "${phpfpmSocketName}"
-        listen.owner = nginx
-        listen.group = nginx
-        listen.mode = 0600
-        user = icingaweb2
-        pm = dynamic
-        pm.max_children = 75
-        pm.start_servers = 2
-        pm.min_spare_servers = 2
-        pm.max_spare_servers = 10
-      '';
+      "${poolName}" = {
+        listen = phpfpmSocketName;
+        phpOptions = ''
+          extension = ${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so
+          date.timezone = "${cfg.timezone}"
+        '';
+        extraConfig = ''
+          listen.owner = nginx
+          listen.group = nginx
+          listen.mode = 0600
+          user = icingaweb2
+          pm = dynamic
+          pm.max_children = 75
+          pm.start_servers = 2
+          pm.min_spare_servers = 2
+          pm.max_spare_servers = 10
+        '';
+      };
     };
 
-    services.phpfpm.phpOptions = mkIf (cfg.pool == "${poolName}")
-      ''
-        extension = ${pkgs.phpPackages.imagick}/lib/php/extensions/imagick.so
-        date.timezone = "${cfg.timezone}"
-      '';
-
     systemd.services."phpfpm-${poolName}".serviceConfig.ReadWritePaths = [ "/etc/icingaweb2" ];
 
     services.nginx = {
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index ee1354d6a99..5ad241ace5c 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -5,14 +5,18 @@ with lib;
 let
   cfg = config.services.nextcloud;
 
+  phpPackage = pkgs.php73;
+  phpPackages = pkgs.php73Packages;
+
   toKeyValue = generators.toKeyValue {
     mkKeyValue = generators.mkKeyValueDefault {} " = ";
   };
 
   phpOptionsExtensions = ''
-    ${optionalString cfg.caching.apcu "extension=${cfg.phpPackages.apcu}/lib/php/extensions/apcu.so"}
-    ${optionalString cfg.caching.redis "extension=${cfg.phpPackages.redis}/lib/php/extensions/redis.so"}
-    ${optionalString cfg.caching.memcached "extension=${cfg.phpPackages.memcached}/lib/php/extensions/memcached.so"}
+    ${optionalString cfg.caching.apcu "extension=${phpPackages.apcu}/lib/php/extensions/apcu.so"}
+    ${optionalString cfg.caching.redis "extension=${phpPackages.redis}/lib/php/extensions/redis.so"}
+    ${optionalString cfg.caching.memcached "extension=${phpPackages.memcached}/lib/php/extensions/memcached.so"}
+    extension=${phpPackages.imagick}/lib/php/extensions/imagick.so
     zend_extension = opcache.so
     opcache.enable = 1
   '';
@@ -45,6 +49,11 @@ in {
       default = "/var/lib/nextcloud";
       description = "Storage path of nextcloud.";
     };
+    logLevel = mkOption {
+      type = types.ints.between 0 4;
+      default = 2;
+      description = "Log level value between 0 (DEBUG) and 4 (FATAL).";
+    };
     https = mkOption {
       type = types.bool;
       default = false;
@@ -89,18 +98,6 @@ in {
       '';
     };
 
-    phpPackages = mkOption {
-      type = types.attrs;
-      default = pkgs.php71Packages;
-      defaultText = "pkgs.php71Packages";
-      description = ''
-        Overridable attribute of the PHP packages set to use.  If any caching
-        module is enabled, it will be taken from here.  Therefore it should
-        match the version of PHP given to
-        <literal>services.phpfpm.phpPackage</literal>.
-      '';
-    };
-
     phpOptions = mkOption {
       type = types.attrsOf types.str;
       default = {
@@ -218,6 +215,19 @@ in {
           <literal>services.nextcloud.hostname</literal> here.
         '';
       };
+
+      overwriteProtocol = mkOption {
+        type = types.nullOr (types.enum [ "http" "https" ]);
+        default = null;
+        example = "https";
+
+        description = ''
+          Force Nextcloud to always use HTTPS i.e. for link generation. Nextcloud
+          uses the currently used protocol by default, but when behind a reverse-proxy,
+          it may use <literal>http</literal> for everything although Nextcloud
+          may be served via HTTPS.
+        '';
+      };
     };
 
     caching = {
@@ -281,6 +291,8 @@ in {
               'skeletondirectory' => '${cfg.skeletonDirectory}',
               ${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
               'log_type' => 'syslog',
+              'log_level' => '${builtins.toString cfg.logLevel}',
+              ${optionalString (cfg.config.overwriteProtocol != null) "'overwriteprotocol' => '${cfg.config.overwriteProtocol}',"}
             ];
           '';
           occInstallCmd = let
@@ -353,14 +365,14 @@ in {
       };
 
       services.phpfpm = {
-        phpOptions = phpOptionsExtensions;
-        phpPackage = pkgs.php71;
         pools.nextcloud = let
           phpAdminValues = (toKeyValue
             (foldr (a: b: a // b) {}
               (mapAttrsToList (k: v: { "php_admin_value[${k}]" = v; })
                 phpOptions)));
         in {
+          phpOptions = phpOptionsExtensions;
+          phpPackage = phpPackage;
           listen = "/run/phpfpm/nextcloud";
           extraConfig = ''
             listen.owner = nginx
@@ -401,7 +413,7 @@ in {
               };
               "/" = {
                 priority = 200;
-                extraConfig = "rewrite ^ /index.php$uri;";
+                extraConfig = "rewrite ^ /index.php$request_uri;";
               };
               "~ ^/store-apps" = {
                 priority = 201;
@@ -415,19 +427,19 @@ in {
                 priority = 210;
                 extraConfig = "return 301 $scheme://$host/remote.php/dav;";
               };
-              "~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/" = {
+              "~ ^\\/(?:build|tests|config|lib|3rdparty|templates|data)\\/" = {
                 priority = 300;
                 extraConfig = "deny all;";
               };
-              "~ ^/(?:\\.|autotest|occ|issue|indie|db_|console)" = {
+              "~ ^\\/(?:\\.|autotest|occ|issue|indie|db_|console)" = {
                 priority = 300;
                 extraConfig = "deny all;";
               };
-              "~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\\.php(?:$|/)" = {
+              "~ ^\\/(?:index|remote|public|cron|core/ajax\\/update|status|ocs\\/v[12]|updater\\/.+|ocs-provider\\/.+|ocm-provider\\/.+)\\.php(?:$|\\/)" = {
                 priority = 500;
                 extraConfig = ''
                   include ${config.services.nginx.package}/conf/fastcgi.conf;
-                  fastcgi_split_path_info ^(.+\.php)(/.*)$;
+                  fastcgi_split_path_info ^(.+\.php)(\\/.*)$;
                   fastcgi_param PATH_INFO $fastcgi_path_info;
                   fastcgi_param HTTPS ${if cfg.https then "on" else "off"};
                   fastcgi_param modHeadersAvailable true;
@@ -438,22 +450,23 @@ in {
                   fastcgi_read_timeout 120s;
                 '';
               };
-              "~ ^/(?:updater|ocs-provider)(?:$|/)".extraConfig = ''
+              "~ ^\\/(?:updater|ocs-provider|ocm-provider)(?:$|\\/)".extraConfig = ''
                 try_files $uri/ =404;
                 index index.php;
               '';
-              "~ \\.(?:css|js|woff|svg|gif)$".extraConfig = ''
-                try_files $uri /index.php$uri$is_args$args;
+              "~ \\.(?:css|js|woff2?|svg|gif)$".extraConfig = ''
+                try_files $uri /index.php$request_uri;
                 add_header Cache-Control "public, max-age=15778463";
                 add_header X-Content-Type-Options nosniff;
                 add_header X-XSS-Protection "1; mode=block";
                 add_header X-Robots-Tag none;
                 add_header X-Download-Options noopen;
                 add_header X-Permitted-Cross-Domain-Policies none;
+                add_header Referrer-Policy no-referrer;
                 access_log off;
               '';
               "~ \\.(?:png|html|ttf|ico|jpg|jpeg)$".extraConfig = ''
-                try_files $uri /index.php$uri$is_args$args;
+                try_files $uri /index.php$request_uri;
                 access_log off;
               '';
             };
@@ -463,10 +476,12 @@ in {
               add_header X-Robots-Tag none;
               add_header X-Download-Options noopen;
               add_header X-Permitted-Cross-Domain-Policies none;
+              add_header Referrer-Policy no-referrer;
               error_page 403 /core/templates/403.php;
               error_page 404 /core/templates/404.php;
               client_max_body_size ${cfg.maxUploadSize};
               fastcgi_buffers 64 4K;
+              fastcgi_hide_header X-Powered-By;
               gzip on;
               gzip_vary on;
               gzip_comp_level 4;
diff --git a/nixos/modules/services/web-apps/restya-board.nix b/nixos/modules/services/web-apps/restya-board.nix
index bc6689bdb27..b064eae248e 100644
--- a/nixos/modules/services/web-apps/restya-board.nix
+++ b/nixos/modules/services/web-apps/restya-board.nix
@@ -179,34 +179,35 @@ in
   config = mkIf cfg.enable {
 
     services.phpfpm.poolConfigs = {
-      "${poolName}" = ''
-        listen = "${phpfpmSocketName}";
-        listen.owner = nginx
-        listen.group = nginx
-        listen.mode = 0600
-        user = ${cfg.user}
-        group = ${cfg.group}
-        pm = dynamic
-        pm.max_children = 75
-        pm.start_servers = 10
-        pm.min_spare_servers = 5
-        pm.max_spare_servers = 20
-        pm.max_requests = 500
-        catch_workers_output = 1
-      '';
+      "${poolName}" = {
+        listen = phpfpmSocketName;
+        phpOptions = ''
+          date.timezone = "CET"
+
+          ${optionalString (!isNull cfg.email.server) ''
+            SMTP = ${cfg.email.server}
+            smtp_port = ${toString cfg.email.port}
+            auth_username = ${cfg.email.login}
+            auth_password = ${cfg.email.password}
+          ''}
+        '';
+        extraConfig = ''
+          listen.owner = nginx
+          listen.group = nginx
+          listen.mode = 0600
+          user = ${cfg.user}
+          group = ${cfg.group}
+          pm = dynamic
+          pm.max_children = 75
+          pm.start_servers = 10
+          pm.min_spare_servers = 5
+          pm.max_spare_servers = 20
+          pm.max_requests = 500
+          catch_workers_output = 1
+        '';
+      };
     };
 
-    services.phpfpm.phpOptions = ''
-      date.timezone = "CET"
-
-      ${optionalString (!isNull cfg.email.server) ''
-        SMTP = ${cfg.email.server}
-        smtp_port = ${toString cfg.email.port}
-        auth_username = ${cfg.email.login}
-        auth_password = ${cfg.email.password}
-      ''}
-    '';
-
     services.nginx.enable = true;
     services.nginx.virtualHosts."${cfg.virtualHost.serverName}" = {
       listen = [ { addr = cfg.virtualHost.listenHost; port = cfg.virtualHost.listenPort; } ];
diff --git a/nixos/modules/services/web-apps/youtrack.nix b/nixos/modules/services/web-apps/youtrack.nix
index 6ad38028a64..691cbdc8d1d 100644
--- a/nixos/modules/services/web-apps/youtrack.nix
+++ b/nixos/modules/services/web-apps/youtrack.nix
@@ -121,6 +121,7 @@ in
       environment.YOUTRACK_JVM_OPTS = "${extraAttr}";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
+      path = with pkgs; [ unixtools.hostname ];
       serviceConfig = {
         Type = "simple";
         User = "youtrack";
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 89dc8b3795e..1c9fbe048f8 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -44,7 +44,7 @@ let
     }
   ''));
 
-  awkFormat = pkgs.writeText "awkFormat-nginx.awk" ''
+  awkFormat = builtins.toFile "awkFormat-nginx.awk" ''
     awk -f
     {sub(/^[ \t]+/,"");idx=0}
     /\{/{ctx++;idx=1}
@@ -52,15 +52,9 @@ let
     {id="";for(i=idx;i<ctx;i++)id=sprintf("%s%s", id, "\t");printf "%s%s\n", id, $0}
   '';
 
-  configFile = pkgs.stdenv.mkDerivation {
-    name = "nginx-config";
-    src = "";
-    phases = [ "installPhase" ];
-    installPhase = ''
-      mkdir $out
-      awk -f ${awkFormat} ${pre-configFile} | sed '/^\s*$/d' > $out/nginx.conf
-    '';
-  };
+  configFile = pkgs.runCommand "nginx.conf" {} (''
+    awk -f ${awkFormat} ${pre-configFile} | sed '/^\s*$/d' > $out
+  '');
 
   pre-configFile = pkgs.writeText "pre-nginx.conf" ''
     user ${cfg.user} ${cfg.group};
@@ -200,11 +194,12 @@ let
             then filter (x: x.ssl) defaultListen
             else defaultListen;
 
-        listenString = { addr, port, ssl, ... }:
+        listenString = { addr, port, ssl, extraParameters ? [], ... }:
           "listen ${addr}:${toString port} "
           + optionalString ssl "ssl "
           + optionalString (ssl && vhost.http2) "http2 "
           + optionalString vhost.default "default_server "
+          + optionalString (extraParameters != []) (concatStringsSep " " extraParameters)
           + ";";
 
         redirectListen = filter (x: !x.ssl) defaultListen;
@@ -497,8 +492,8 @@ in
 
       sslProtocols = mkOption {
         type = types.str;
-        default = "TLSv1.2";
-        example = "TLSv1 TLSv1.1 TLSv1.2";
+        default = "TLSv1.2 TLSv1.3";
+        example = "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3";
         description = "Allowed TLS protocol versions.";
       };
 
@@ -656,10 +651,10 @@ in
       preStart =
         ''
         ${cfg.preStart}
-        ${cfg.package}/bin/nginx -c ${configFile}/nginx.conf -p ${cfg.stateDir} -t
+        ${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t
         '';
       serviceConfig = {
-        ExecStart = "${cfg.package}/bin/nginx -c ${configFile}/nginx.conf -p ${cfg.stateDir}";
+        ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         Restart = "always";
         RestartSec = "10s";
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index 6a50d8ed5cd..15b933c984a 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -31,6 +31,7 @@ with lib;
         addr = mkOption { type = str;  description = "IP address.";  };
         port = mkOption { type = int;  description = "Port number."; default = 80; };
         ssl  = mkOption { type = bool; description = "Enable SSL.";  default = false; };
+        extraParameters = mkOption { type = listOf str; description = "Extra parameters of this listen directive."; default = []; example = [ "reuseport" "deferred" ]; };
       }; });
       default = [];
       example = [
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 6255dce8276..ea01749349d 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -133,6 +133,7 @@ in {
     services.gnome3.gnome-keyring.enable = true;
     services.gnome3.gnome-online-accounts.enable = mkDefault true;
     services.gnome3.gnome-remote-desktop.enable = mkDefault true;
+    services.gnome3.gnome-settings-daemon.enable = true;
     services.gnome3.gnome-terminal-server.enable = mkDefault true;
     services.gnome3.gnome-user-share.enable = mkDefault true;
     services.gnome3.gvfs.enable = true;
@@ -153,7 +154,6 @@ in {
     hardware.bluetooth.enable = mkDefault true;
     services.hardware.bolt.enable = mkDefault true;
     services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
-    services.udev.packages = [ pkgs.gnome3.gnome-settings-daemon ];
     systemd.packages = [ pkgs.gnome3.vino ];
     services.flatpak.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix
index 4d2fafd1496..bf6685ff7ea 100644
--- a/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -56,9 +56,6 @@ in
 
         export XDG_MENU_PREFIX=mate-
 
-        # Find the mouse
-        export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons
-
         # Let caja find extensions
         export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0
 
@@ -78,9 +75,6 @@ in
         # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
         ${addToXDGDirs pkgs.mate.mate-control-center}
 
-        # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
-        ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
-
         ${pkgs.mate.mate-session-manager}/bin/mate-session ${optionalString cfg.debug "--debug"} &
         waitPID=$!
       '';
@@ -90,18 +84,27 @@ in
       pkgs.mate.basePackages ++
       (pkgs.gnome3.removePackagesByName
         pkgs.mate.extraPackages
-        config.environment.mate.excludePackages);
-
-    services.dbus.packages = [
-      pkgs.gnome3.dconf
-      pkgs.at-spi2-core
-    ];
-
+        config.environment.mate.excludePackages) ++
+      [
+        pkgs.desktop-file-utils
+        pkgs.glib
+        pkgs.gtk3.out
+        pkgs.shared-mime-info
+        pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
+      ];
+
+    programs.dconf.enable = true;
+    services.gnome3.at-spi2-core.enable = true;
     services.gnome3.gnome-keyring.enable = true;
+    services.gnome3.gnome-settings-daemon.enable = true;
+    services.gnome3.gnome-settings-daemon.package = pkgs.mate.mate-settings-daemon;
+    services.gnome3.gvfs.enable = true;
     services.upower.enable = config.powerManagement.enable;
 
     security.pam.services."mate-screensaver".unixAuth = true;
 
+    environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.gnome3.gvfs}/lib/gio/modules" ];
+
     environment.pathsToLink = [ "/share" ];
   };
 
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 0f49439bf7c..31bbbd55829 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -117,11 +117,12 @@ in
     services.gnome3.file-roller.enable = true;
     # TODO: gnome-keyring's xdg autostarts will still be in the environment (from elementary-session-settings) if disabled forcefully
     services.gnome3.gnome-keyring.enable = true;
+    services.gnome3.gnome-settings-daemon.enable = true;
+    services.gnome3.gnome-settings-daemon.package = pkgs.pantheon.elementary-settings-daemon;
     services.gnome3.gvfs.enable = true;
     services.gnome3.rygel.enable = true;
     services.gsignond.enable = true;
     services.gsignond.plugins = with pkgs.gsignondPlugins; [ lastfm mail oauth ];
-    services.udev.packages = [ pkgs.pantheon.elementary-settings-daemon ];
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
     services.xserver.libinput.enable = mkDefault true;
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 704cc78c152..ace9dd5321b 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -163,6 +163,8 @@ in
 
           libsForQt56.phonon-backend-gstreamer
           libsForQt5.phonon-backend-gstreamer
+
+          xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
         ]
 
         ++ lib.optionals cfg.enableQt4Support [ pkgs.phonon-backend-gstreamer ]
@@ -175,9 +177,9 @@ in
         ++ lib.optional config.services.colord.enable colord-kde
         ++ lib.optionals config.services.samba.enable [ kdenetwork-filesharing pkgs.samba ];
 
-      environment.pathsToLink = [ 
+      environment.pathsToLink = [
         # FIXME: modules should link subdirs of `/share` rather than relying on this
-        "/share" 
+        "/share"
       ];
 
       environment.etc = singleton {
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index dabf09418da..6852154378d 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -53,7 +53,7 @@ in
 
       # Supplies some abstract icons such as:
       # utilities-terminal, accessories-text-editor
-      gnome3.defaultIconTheme
+      gnome3.adwaita-icon-theme
 
       hicolor-icon-theme
       tango-icon-theme
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
index 772cc95e84e..5b280b02423 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -96,8 +96,8 @@ in
 
         package = mkOption {
           type = types.package;
-          default = pkgs.gnome3.defaultIconTheme;
-          defaultText = "pkgs.gnome3.defaultIconTheme";
+          default = pkgs.gnome3.adwaita-icon-theme;
+          defaultText = "pkgs.gnome3.adwaita-icon-theme";
           description = ''
             The package path that contains the icon theme given in the name option.
           '';
@@ -116,8 +116,8 @@ in
       cursorTheme = {
 
         package = mkOption {
-          default = pkgs.gnome3.defaultIconTheme;
-          defaultText = "pkgs.gnome3.defaultIconTheme";
+          default = pkgs.gnome3.adwaita-icon-theme;
+          defaultText = "pkgs.gnome3.adwaita-icon-theme";
           description = ''
             The package path that contains the cursor theme given in the name option.
           '';
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index d84ab3ced6f..c4d5b6a9cde 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -61,7 +61,9 @@ let
       '';
       description = ''
         Extra lines to append to the <literal>Monitor</literal> section
-        verbatim.
+        verbatim. Available options are documented in the MONITOR section in
+        <citerefentry><refentrytitle>xorg.conf</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry>.
       '';
     };
   };
@@ -633,7 +635,7 @@ in
 
     environment.pathsToLink = [ "/share/X11" ];
 
-    xdg = { 
+    xdg = {
       autostart.enable = true;
       menus.enable = true;
       mime.enable = true;
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index a560af5ce96..5c88d27b6c6 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -130,11 +130,9 @@ let
 
   failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
 
-  showWarnings = res: fold (w: x: builtins.trace "warning: ${w}" x) res config.warnings;
-
   baseSystemAssertWarn = if failedAssertions != []
     then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
-    else showWarnings baseSystem;
+    else showWarnings config.warnings baseSystem;
 
   # Replace runtime dependencies
   system = fold ({ oldDependency, newDependency }: drv:
diff --git a/nixos/modules/system/etc/make-etc.sh b/nixos/modules/system/etc/make-etc.sh
index 9c0520e92fc..1ca4c3046f0 100644
--- a/nixos/modules/system/etc/make-etc.sh
+++ b/nixos/modules/system/etc/make-etc.sh
@@ -10,11 +10,6 @@ users_=($users)
 groups_=($groups)
 set +f
 
-# Create relative symlinks, so that the links can be followed if
-# the NixOS installation is not mounted as filesystem root.
-# Absolute symlinks violate the os-release format
-# at https://www.freedesktop.org/software/systemd/man/os-release.html
-# and break e.g. systemd-nspawn and os-prober.
 for ((i = 0; i < ${#targets_[@]}; i++)); do
     source="${sources_[$i]}"
     target="${targets_[$i]}"
@@ -24,14 +19,14 @@ for ((i = 0; i < ${#targets_[@]}; i++)); do
         # If the source name contains '*', perform globbing.
         mkdir -p $out/etc/$target
         for fn in $source; do
-            ln -s --relative "$fn" $out/etc/$target/
+            ln -s "$fn" $out/etc/$target/
         done
 
     else
-
+        
         mkdir -p $out/etc/$(dirname $target)
         if ! [ -e $out/etc/$target ]; then
-            ln -s --relative $source $out/etc/$target
+            ln -s $source $out/etc/$target
         else
             echo "duplicate entry $target -> $source"
             if test "$(readlink $out/etc/$target)" != "$source"; then
@@ -39,13 +34,13 @@ for ((i = 0; i < ${#targets_[@]}; i++)); do
                 exit 1
             fi
         fi
-
+        
         if test "${modes_[$i]}" != symlink; then
             echo "${modes_[$i]}"  > $out/etc/$target.mode
             echo "${users_[$i]}"  > $out/etc/$target.uid
             echo "${groups_[$i]}" > $out/etc/$target.gid
         fi
-
+        
     fi
 done
 
diff --git a/nixos/modules/system/etc/setup-etc.pl b/nixos/modules/system/etc/setup-etc.pl
index 82ef49a2a27..eed20065087 100644
--- a/nixos/modules/system/etc/setup-etc.pl
+++ b/nixos/modules/system/etc/setup-etc.pl
@@ -4,7 +4,6 @@ use File::Copy;
 use File::Path;
 use File::Basename;
 use File::Slurp;
-use File::Spec;
 
 my $etc = $ARGV[0] or die;
 my $static = "/etc/static";
@@ -18,20 +17,6 @@ sub atomicSymlink {
     return 1;
 }
 
-# Create relative symlinks, so that the links can be followed if
-# the NixOS installation is not mounted as filesystem root.
-# Absolute symlinks violate the os-release format
-# at https://www.freedesktop.org/software/systemd/man/os-release.html
-# and break e.g. systemd-nspawn and os-prober.
-sub atomicRelativeSymlink {
-    my ($source, $target) = @_;
-    my $tmp = "$target.tmp";
-    unlink $tmp;
-    my $rel = File::Spec->abs2rel($source, dirname $target);
-    symlink $rel, $tmp or return 0;
-    rename $tmp, $target or return 0;
-    return 1;
-}
 
 # Atomically update /etc/static to point at the etc files of the
 # current configuration.
@@ -118,7 +103,7 @@ sub link {
     if (-e "$_.mode") {
         my $mode = read_file("$_.mode"); chomp $mode;
         if ($mode eq "direct-symlink") {
-            atomicRelativeSymlink readlink("$static/$fn"), $target or warn;
+            atomicSymlink readlink("$static/$fn"), $target or warn;
         } else {
             my $uid = read_file("$_.uid"); chomp $uid;
             my $gid = read_file("$_.gid"); chomp $gid;
@@ -132,7 +117,7 @@ sub link {
         push @copied, $fn;
         print CLEAN "$fn\n";
     } elsif (-l "$_") {
-        atomicRelativeSymlink "$static/$fn", $target or warn;
+        atomicSymlink "$static/$fn", $target or warn;
     }
 }
 
diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix
index d225778a387..91f4ae79ee9 100644
--- a/nixos/modules/tasks/auto-upgrade.nix
+++ b/nixos/modules/tasks/auto-upgrade.nix
@@ -57,7 +57,7 @@ let cfg = config.system.autoUpgrade; in
 
   };
 
-  config = {
+  config = lib.mkIf cfg.enable {
 
     system.autoUpgrade.flags =
       [ "--no-build-output" ]
@@ -84,7 +84,7 @@ let cfg = config.system.autoUpgrade; in
         ${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch ${toString cfg.flags}
       '';
 
-      startAt = optional cfg.enable cfg.dates;
+      startAt = cfg.dates;
     };
 
   };
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index a1a32c1c59a..4ee84c5268e 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -52,6 +52,15 @@ in
           '';
       };
 
+    enableNvidia =
+      mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable nvidia-docker wrapper, supporting NVIDIA GPUs inside docker containers.
+        '';
+      };
+
     liveRestore =
       mkOption {
         type = types.bool;
@@ -140,7 +149,8 @@ in
   ###### implementation
 
   config = mkIf cfg.enable (mkMerge [{
-      environment.systemPackages = [ cfg.package ];
+      environment.systemPackages = [ cfg.package ]
+        ++ optional cfg.enableNvidia pkgs.nvidia-docker;
       users.groups.docker.gid = config.ids.gids.docker;
       systemd.packages = [ cfg.package ];
 
@@ -157,6 +167,7 @@ in
                 --log-driver=${cfg.logDriver} \
                 ${optionalString (cfg.storageDriver != null) "--storage-driver=${cfg.storageDriver}"} \
                 ${optionalString cfg.liveRestore "--live-restore" } \
+                ${optionalString cfg.enableNvidia "--add-runtime nvidia=${pkgs.nvidia-docker}/bin/nvidia-container-runtime" } \
                 ${cfg.extraOptions}
             ''];
           ExecReload=[
@@ -165,7 +176,8 @@ in
           ];
         };
 
-        path = [ pkgs.kmod ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs);
+        path = [ pkgs.kmod ] ++ optional (cfg.storageDriver == "zfs") pkgs.zfs
+          ++ optional cfg.enableNvidia pkgs.nvidia-docker;
       };
 
       systemd.sockets.docker = {
@@ -179,7 +191,6 @@ in
         };
       };
 
-
       systemd.services.docker-prune = {
         description = "Prune docker resources";
 
@@ -194,7 +205,15 @@ in
 
         startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates;
       };
+
+      assertions = [
+        { assertion = cfg.enableNvidia -> config.hardware.opengl.driSupport32Bit or false;
+          message = "Option enableNvidia requires 32bit support libraries";
+        }];
     }
+    (mkIf cfg.enableNvidia {
+      environment.etc."nvidia-container-runtime/config.toml".source = "${pkgs.nvidia-docker}/etc/config.toml";
+    })
   ]);
 
   imports = [
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 65227857a38..2ddb54bcc3d 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -74,6 +74,7 @@ in
   ferm = handleTest ./ferm.nix {};
   firefox = handleTest ./firefox.nix {};
   firewall = handleTest ./firewall.nix {};
+  fish = handleTest ./fish.nix {};
   flannel = handleTestOn ["x86_64-linux"] ./flannel.nix {};
   flatpak = handleTest ./flatpak.nix {};
   fsck = handleTest ./fsck.nix {};
diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix
index 58f106314ab..399e4d4e428 100644
--- a/nixos/tests/docker-tools.nix
+++ b/nixos/tests/docker-tools.nix
@@ -34,8 +34,8 @@ import ./make-test.nix ({ pkgs, ... }: {
 
       # To test the pullImage tool
       $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nixFromDockerHub}'");
-      $docker->succeed("docker run --rm nixos/nix:1.11 nix-store --version");
-      $docker->succeed("docker rmi nixos/nix:1.11");
+      $docker->succeed("docker run --rm nixos/nix:2.2.1 nix-store --version");
+      $docker->succeed("docker rmi nixos/nix:2.2.1");
 
       # To test runAsRoot and entry point
       $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nginx}'");
diff --git a/nixos/tests/fish.nix b/nixos/tests/fish.nix
new file mode 100644
index 00000000000..97c4e8e37ac
--- /dev/null
+++ b/nixos/tests/fish.nix
@@ -0,0 +1,21 @@
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "fish";
+
+  machine =
+    { pkgs, ... }:
+
+    {
+      programs.fish.enable = true;
+      environment.systemPackages = with pkgs; [
+        coreutils
+        procps # kill collides with coreutils' to test https://github.com/NixOS/nixpkgs/issues/56432
+      ];
+    };
+
+  testScript =
+    ''
+      $machine->waitForFile("/etc/fish/generated_completions/coreutils.fish");
+      $machine->waitForFile("/etc/fish/generated_completions/kill.fish");
+      $machine->succeed("fish -ic 'echo \$fish_complete_path' | grep -q '/share/fish/completions /etc/fish/generated_completions /root/.local/share/fish/generated_completions\$'");
+    '';
+})
diff --git a/nixos/tests/gitea.nix b/nixos/tests/gitea.nix
index 28e6479e9cb..d43efc3687a 100644
--- a/nixos/tests/gitea.nix
+++ b/nixos/tests/gitea.nix
@@ -45,7 +45,7 @@ with pkgs.lib;
       {
         services.gitea.enable = true;
         services.gitea.database.type = "postgres";
-        services.gitea.database.password = "secret";
+        services.gitea.database.passwordFile = pkgs.writeText "db-password" "secret";
       };
 
     testScript = ''
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 2553a0d116a..5e363f5d09e 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -273,6 +273,37 @@ let
       };
     };
 
+    makeLuksRootTest = name: luksFormatOpts: makeInstallerTest "luksroot-format2"
+      { createPartitions = ''
+          $machine->succeed(
+            "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+            . " mkpart primary ext2 1M 50MB" # /boot
+            . " mkpart primary linux-swap 50M 1024M"
+            . " mkpart primary 1024M -1s", # LUKS
+            "udevadm settle",
+            "mkswap /dev/vda2 -L swap",
+            "swapon -L swap",
+            "modprobe dm_mod dm_crypt",
+            "echo -n supersecret | cryptsetup luksFormat ${luksFormatOpts} -q /dev/vda3 -",
+            "echo -n supersecret | cryptsetup luksOpen --key-file - /dev/vda3 cryptroot",
+            "mkfs.ext3 -L nixos /dev/mapper/cryptroot",
+            "mount LABEL=nixos /mnt",
+            "mkfs.ext3 -L boot /dev/vda1",
+            "mkdir -p /mnt/boot",
+            "mount LABEL=boot /mnt/boot",
+          );
+        '';
+        extraConfig = ''
+          boot.kernelParams = lib.mkAfter [ "console=tty0" ];
+        '';
+        enableOCR = true;
+        preBootCommands = ''
+          $machine->start;
+          $machine->waitForText(qr/Passphrase for/);
+          $machine->sendChars("supersecret\n");
+        '';
+      };
+
 
 in {
 
@@ -446,37 +477,14 @@ in {
         '';
     };
 
-  # Boot off an encrypted root partition
-  luksroot = makeInstallerTest "luksroot"
-    { createPartitions = ''
-        $machine->succeed(
-          "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
-          . " mkpart primary ext2 1M 50MB" # /boot
-          . " mkpart primary linux-swap 50M 1024M"
-          . " mkpart primary 1024M -1s", # LUKS
-          "udevadm settle",
-          "mkswap /dev/vda2 -L swap",
-          "swapon -L swap",
-          "modprobe dm_mod dm_crypt",
-          "echo -n supersecret | cryptsetup luksFormat -q /dev/vda3 -",
-          "echo -n supersecret | cryptsetup luksOpen --key-file - /dev/vda3 cryptroot",
-          "mkfs.ext3 -L nixos /dev/mapper/cryptroot",
-          "mount LABEL=nixos /mnt",
-          "mkfs.ext3 -L boot /dev/vda1",
-          "mkdir -p /mnt/boot",
-          "mount LABEL=boot /mnt/boot",
-        );
-      '';
-      extraConfig = ''
-        boot.kernelParams = lib.mkAfter [ "console=tty0" ];
-      '';
-      enableOCR = true;
-      preBootCommands = ''
-        $machine->start;
-        $machine->waitForText(qr/Passphrase for/);
-        $machine->sendChars("supersecret\n");
-      '';
-    };
+  # Boot off an encrypted root partition with the default LUKS header format
+  luksroot = makeLuksRootTest "luksroot-format1" "";
+
+  # Boot off an encrypted root partition with LUKS1 format
+  luksroot-format1 = makeLuksRootTest "luksroot-format1" "--type=LUKS1";
+
+  # Boot off an encrypted root partition with LUKS2 format
+  luksroot-format2 = makeLuksRootTest "luksroot-format2" "--type=LUKS2";
 
   # Test whether opening encrypted filesystem with keyfile
   # Checks for regression of missing cryptsetup, when no luks device without
diff --git a/nixos/tests/ndppd.nix b/nixos/tests/ndppd.nix
index 9f24eb6d9d4..c53ff93a91f 100644
--- a/nixos/tests/ndppd.nix
+++ b/nixos/tests/ndppd.nix
@@ -37,8 +37,7 @@ import ./make-test.nix ({ pkgs, lib, ...} : {
       };
       services.ndppd = {
         enable = true;
-        interface = "eth1";
-        network = "fd42::/112";
+        proxies."eth1".rules."fd42::/112" = {};
       };
       containers.client = {
         autoStart = true;
diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix
index 219a20c5c7e..8b9e2170f15 100644
--- a/nixos/tests/openssh.nix
+++ b/nixos/tests/openssh.nix
@@ -34,6 +34,24 @@ in {
         ];
       };
 
+    server_localhost_only =
+      { ... }:
+
+      {
+        services.openssh = {
+          enable = true; listenAddresses = [ { addr = "127.0.0.1"; port = 22; } ];
+        };
+      };
+
+    server_localhost_only_lazy =
+      { ... }:
+
+      {
+        services.openssh = {
+          enable = true; startWhenNeeded = true; listenAddresses = [ { addr = "127.0.0.1"; port = 22; } ];
+        };
+      };
+
     client =
       { ... }: { };
 
@@ -77,5 +95,10 @@ in {
                        " server_lazy true");
 
     };
+
+    subtest "localhost-only", sub {
+      $server_localhost_only->succeed("ss -nlt | grep '127.0.0.1:22'");
+      $server_localhost_only_lazy->succeed("ss -nlt | grep '127.0.0.1:22'");
+    }
   '';
 })
diff --git a/nixos/tests/rspamd.nix b/nixos/tests/rspamd.nix
index 396cd5b67d8..0cc94728f80 100644
--- a/nixos/tests/rspamd.nix
+++ b/nixos/tests/rspamd.nix
@@ -52,8 +52,18 @@ in
     machine = {
       services.rspamd = {
         enable = true;
-        bindSocket = [ "/run/rspamd.sock mode=0600 user=root group=root" ];
-        bindUISocket = [ "/run/rspamd-worker.sock mode=0666 user=root group=root" ];
+        workers.normal.bindSockets = [{
+          socket = "/run/rspamd.sock";
+          mode = "0600";
+          owner = "root";
+          group = "root";
+        }];
+        workers.controller.bindSockets = [{
+          socket = "/run/rspamd-worker.sock";
+          mode = "0666";
+          owner = "root";
+          group = "root";
+        }];
       };
     };
 
@@ -235,7 +245,7 @@ in
       services.rspamd = {
         enable = true;
         postfix.enable = true;
-        workers.rspamd_proxy.type = "proxy";
+        workers.rspamd_proxy.type = "rspamd_proxy";
       };
     };
     testScript = ''