summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2019-08-31 10:04:20 +0200
committerFrederik Rietdijk <fridh@fridh.nl>2019-08-31 10:04:20 +0200
commitad1d58c6227abf2a9c80311eb09166a532384ed2 (patch)
tree852498ff298f9b01c0d2c8b4c883da1a00912260 /nixos
parentebe4fd146b29c92fb59f243f75e46afc9f1a9048 (diff)
parentfc74ba8291a8a93cba428de6bc2e7c8c7f9330f4 (diff)
downloadnixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.tar
nixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.tar.gz
nixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.tar.bz2
nixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.tar.lz
nixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.tar.xz
nixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.tar.zst
nixpkgs-ad1d58c6227abf2a9c80311eb09166a532384ed2.zip
Merge staging-next into staging
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/profiles/clone-config.xml7
-rw-r--r--nixos/doc/manual/configuration/profiles/installation-device.xml38
-rw-r--r--nixos/doc/manual/release-notes/rl-1909.xml64
-rw-r--r--nixos/modules/config/fonts/fontconfig-penultimate.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image.nix4
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/profiles/installation-device.nix17
-rw-r--r--nixos/modules/programs/bash/bash.nix2
-rw-r--r--nixos/modules/programs/zsh/zsh.nix1
-rw-r--r--nixos/modules/rename.nix5
-rw-r--r--nixos/modules/security/acme.nix151
-rw-r--r--nixos/modules/security/acme.xml4
-rw-r--r--nixos/modules/services/continuous-integration/gitlab-runner.nix5
-rw-r--r--nixos/modules/services/databases/redis.nix19
-rw-r--r--nixos/modules/services/desktops/gnome3/gnome-user-share.nix20
-rw-r--r--nixos/modules/services/editors/emacs.xml20
-rw-r--r--nixos/modules/services/hardware/fwupd.nix22
-rw-r--r--nixos/modules/services/mail/dovecot.nix3
-rw-r--r--nixos/modules/services/mail/mailman.nix114
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix7
-rw-r--r--nixos/modules/services/monitoring/netdata.nix2
-rw-r--r--nixos/modules/services/networking/nsd.nix3
-rw-r--r--nixos/modules/services/networking/softether.nix2
-rw-r--r--nixos/modules/services/networking/strongswan-swanctl/module.nix5
-rw-r--r--nixos/modules/services/networking/strongswan.nix3
-rw-r--r--nixos/modules/services/security/vault.nix2
-rw-r--r--nixos/modules/services/torrent/magnetico.nix214
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix3
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix21
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce4-14.nix157
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix2
-rw-r--r--nixos/modules/system/boot/systemd.nix2
-rw-r--r--nixos/modules/virtualisation/containers.nix17
-rw-r--r--nixos/release-combined.nix1
-rw-r--r--nixos/tests/acme.nix98
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/magnetico.nix28
-rw-r--r--nixos/tests/systemd.nix10
-rw-r--r--nixos/tests/xfce4-14.nix33
41 files changed, 876 insertions, 241 deletions
diff --git a/nixos/doc/manual/configuration/profiles/clone-config.xml b/nixos/doc/manual/configuration/profiles/clone-config.xml
index 234835845e2..21c4ea75d6d 100644
--- a/nixos/doc/manual/configuration/profiles/clone-config.xml
+++ b/nixos/doc/manual/configuration/profiles/clone-config.xml
@@ -11,4 +11,11 @@
   creating the image in the first place. As a result it allows users to edit
   and rebuild the live-system.
  </para>
+
+ <para>
+  On images where the installation media also becomes an installation target,
+  copying over <literal>configuration.nix</literal> should be disabled by
+  setting <literal>installer.cloneConfig</literal> to <literal>false</literal>.
+  This is already done in <literal>sd-image.nix</literal>.
+ </para>
 </section>
diff --git a/nixos/doc/manual/configuration/profiles/installation-device.xml b/nixos/doc/manual/configuration/profiles/installation-device.xml
index 3dcdf403d89..192ae955b68 100644
--- a/nixos/doc/manual/configuration/profiles/installation-device.xml
+++ b/nixos/doc/manual/configuration/profiles/installation-device.xml
@@ -6,33 +6,31 @@
  <title>Installation Device</title>
 
  <para>
-  Provides a basic configuration for installation devices like CDs. This means
-  enabling hardware scans, using the <link linkend="sec-profile-clone-config">
-  Clone Config profile</link> to guarantee
-  <filename>/etc/nixos/configuration.nix</filename> exists (for
-  <command>nixos-rebuild</command> to work), a copy of the Nixpkgs channel
-  snapshot used to create the install media.
+  Provides a basic configuration for installation devices like CDs.
+  This enables redistributable firmware, includes the
+  <link linkend="sec-profile-clone-config">Clone Config profile</link>
+  and a copy of the Nixpkgs channel, so <command>nixos-install</command>
+  works out of the box.
  </para>
-
  <para>
-  Additionally, documentation for <link linkend="opt-documentation.enable">
-  Nixpkgs</link> and <link linkend="opt-documentation.nixos.enable">NixOS
-  </link> are forcefully enabled (to override the
+  Documentation for <link linkend="opt-documentation.enable">Nixpkgs</link>
+  and <link linkend="opt-documentation.nixos.enable">NixOS</link> are
+  forcefully enabled (to override the
   <link linkend="sec-profile-minimal">Minimal profile</link> preference); the
-  NixOS manual is shown automatically on TTY 8, sudo and udisks are disabled.
-  Autologin is enabled as root.
+  NixOS manual is shown automatically on TTY 8, udisks is disabled.
+  Autologin is enabled as <literal>nixos</literal> user, while passwordless
+  login as both <literal>root</literal> and <literal>nixos</literal> is possible.
+  Passwordless <command>sudo</command> is enabled too.
+  <link linkend="opt-networking.wireless.enable">wpa_supplicant</link> is
+  enabled, but configured to not autostart.
  </para>
-
  <para>
-  A message is shown to the user to start a display manager if needed, ssh with
-  <xref linkend="opt-services.openssh.permitRootLogin"/> are enabled (but
-  doesn't autostart). WPA Supplicant is also enabled without autostart.
+  It is explained how to login, start the ssh server, and if available,
+  how to start the display manager.
  </para>
 
  <para>
-  Finally, vim is installed, root is set to not have a password, the kernel is
-  made more silent for remote public IP installs, and several settings are
-  tweaked so that the installer has a better chance of succeeding under
-  low-memory environments.
+  Several settings are tweaked so that the installer has a better chance of
+  succeeding under low-memory environments.
  </para>
 </section>
diff --git a/nixos/doc/manual/release-notes/rl-1909.xml b/nixos/doc/manual/release-notes/rl-1909.xml
index 6e29091d91d..560b3198517 100644
--- a/nixos/doc/manual/release-notes/rl-1909.xml
+++ b/nixos/doc/manual/release-notes/rl-1909.xml
@@ -48,6 +48,15 @@
      To gain root privileges use <literal>sudo -i</literal> without a password.
     </para>
    </listitem>
+   <listitem>
+    <para>
+      We've updated to Xfce 4.14, which brings a new module <option>services.xserver.desktopManager.xfce4-14</option>.
+      If you'd like to upgrade, please switch from the <option>services.xserver.desktopManager.xfce</option> module as it
+      will be deprecated in a future release. They're incompatibilities with the current Xfce module; it doesn't support
+      <option>thunarPlugins</option> and it isn't recommended to use <option>services.xserver.desktopManager.xfce</option>
+      and <option>services.xserver.desktopManager.xfce4-14</option> simultaneously or to downgrade from Xfce 4.14 after upgrading.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
@@ -291,6 +300,55 @@
        configuration while being better type-checked and mergeable.
      </para>
    </listitem>
+   <listitem>
+    <para>
+     No service depends on <literal>keys.target</literal> anymore which is a systemd
+     target that indicates if all <link xlink:href="https://nixos.org/nixops/manual/#idm140737322342384">NixOps keys</link> were successfully uploaded.
+     Instead, <literal>&lt;key-name&gt;-key.service</literal> should be used to define
+     a dependency of a key in a service. The full issue behind the <literal>keys.target</literal>
+     dependency is described at <link xlink:href="https://github.com/NixOS/nixpkgs/issues/67265">NixOS/nixpkgs#67265</link>.
+    </para>
+    <para>
+     The following services are affected by this:
+     <itemizedlist>
+      <listitem><para><link linkend="opt-services.dovecot2.enable"><literal>services.dovecot2</literal></link></para></listitem>
+      <listitem><para><link linkend="opt-services.nsd.enable"><literal>services.nsd</literal></link></para></listitem>
+      <listitem><para><link linkend="opt-services.softether.enable"><literal>services.softether</literal></link></para></listitem>
+      <listitem><para><link linkend="opt-services.strongswan.enable"><literal>services.strongswan</literal></link></para></listitem>
+      <listitem><para><link linkend="opt-services.strongswan-swanctl.enable"><literal>services.strongswan-swanctl</literal></link></para></listitem>
+      <listitem><para><link linkend="opt-services.httpd.enable"><literal>services.httpd</literal></link></para></listitem>
+     </itemizedlist>
+    </para>
+   </listitem>
+   <listitem>
+     <para>
+       The <option>security.acme.directory</option> option has been replaced by a read-only <option>security.acme.certs.&lt;cert&gt;.directory</option> option for each certificate you define. This will be
+       a subdirectory of <literal>/var/lib/acme</literal>. You can use this read-only option to figure out where the certificates are stored for a specific certificate. For example,
+       the <option>services.nginx.virtualhosts.&lt;name&gt;.enableACME</option>  option will use this directory option to find the certs for the virtual host.
+     </para>
+     <para>
+       <option>security.acme.preDelay</option> and <option>security.acme.activationDelay</option> options have been removed. To execute a service before certificates
+       are provisioned or renewed add a <literal>RequiredBy=acme-${cert}.service</literal> to any service.
+     </para>
+     <para>
+       Furthermore, the acme module will not automatically add a dependency on <literal>lighttpd.service</literal> anymore. If you are using certficates provided by letsencrypt
+       for lighttpd, then you should depend on the certificate service <literal>acme-${cert}.service></literal> manually.
+     </para>
+     <para>
+       For nginx, the dependencies are still automatically managed when <option>services.nginx.virtualhosts.&lt;name&gt;.enableACME</option> is enabled just like before. What changed is that nginx now directly depends on the specific certificates that it needs,
+       instead of depending on the catch-all <literal>acme-certificates.target</literal>. This target unit was also removed from the codebase.
+       This will mean nginx will no longer depend on certificates it isn't explicitly managing and fixes a bug with certificate renewal
+       ordering racing with nginx restarting which could lead to nginx getting in a broken state as described at
+        <link xlink:href="https://github.com/NixOS/nixpkgs/issues/60180">NixOS/nixpkgs#60180</link>.
+     </para>
+   </listitem>
+   <listitem>
+     <para>
+       The old deprecated <literal>emacs</literal> package sets have been dropped.
+       What used to be called <literal>emacsPackagesNg</literal> is now simply called <literal>emacsPackages</literal>.
+     </para>
+   </listitem>
+
   </itemizedlist>
  </section>
 
@@ -527,6 +585,12 @@
       features.
     </para>
    </listitem>
+   <listitem>
+    <para>
+     We no longer enable custom font rendering settings with <option>fonts.fontconfig.penultimate.enable</option> by default.
+     The defaults from fontconfig are sufficient.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 </section>
diff --git a/nixos/modules/config/fonts/fontconfig-penultimate.nix b/nixos/modules/config/fonts/fontconfig-penultimate.nix
index 9790bdde566..7e311a21acf 100644
--- a/nixos/modules/config/fonts/fontconfig-penultimate.nix
+++ b/nixos/modules/config/fonts/fontconfig-penultimate.nix
@@ -269,7 +269,7 @@ in
         penultimate = {
           enable = mkOption {
             type = types.bool;
-            default = true;
+            default = false;
             description = ''
               Enable fontconfig-penultimate settings to supplement the
               NixOS defaults by providing per-font rendering defaults and
diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix
index 7f355a13249..07f6f627e6c 100644
--- a/nixos/modules/installer/cd-dvd/sd-image.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -194,5 +194,9 @@ in
         rm -f /nix-path-registration
       fi
     '';
+
+    # the installation media is also the installation target,
+    # so we don't want to provide the installation configuration.nix.
+    installer.cloneConfig = false;
   };
 }
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index efd8544d6a2..ac6af1ce8b7 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -340,7 +340,7 @@
       cockroachdb = 313;
       zoneminder = 314;
       paperless = 315;
-      mailman = 316;
+      #mailman = 316;  # removed 2019-08-30
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -641,7 +641,7 @@
       cockroachdb = 313;
       zoneminder = 314;
       paperless = 315;
-      mailman = 316;
+      #mailman = 316;  # removed 2019-08-30
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 6331e76c648..22fd5d7609d 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -376,6 +376,7 @@
   ./services/mail/mail.nix
   ./services/mail/mailcatcher.nix
   ./services/mail/mailhog.nix
+  ./services/mail/mailman.nix
   ./services/mail/mlmmj.nix
   ./services/mail/offlineimap.nix
   ./services/mail/opendkim.nix
@@ -770,6 +771,7 @@
   ./services/system/uptimed.nix
   ./services/torrent/deluge.nix
   ./services/torrent/flexget.nix
+  ./services/torrent/magnetico.nix
   ./services/torrent/opentracker.nix
   ./services/torrent/peerflix.nix
   ./services/torrent/transmission.nix
diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix
index 1a6e0699560..fd30220ce1c 100644
--- a/nixos/modules/profiles/installation-device.nix
+++ b/nixos/modules/profiles/installation-device.nix
@@ -55,13 +55,16 @@ with lib;
     services.mingetty.autologinUser = "nixos";
 
     # Some more help text.
-    services.mingetty.helpLine =
-      ''
-
-        The "nixos" and "root" account have empty passwords.  ${
-          optionalString config.services.xserver.enable
-            "Type `sudo systemctl start display-manager' to\nstart the graphical user interface."}
-      '';
+    services.mingetty.helpLine = ''
+      The "nixos" and "root" accounts have empty passwords.
+
+      Type `sudo systemctl start sshd` to start the SSH daemon.
+      You then must set a password for either "root" or "nixos"
+      with `passwd` to be able to login.
+    '' + optionalString config.services.xserver.enable ''
+      Type `sudo systemctl start display-manager' to
+      start the graphical user interface.
+    '';
 
     # Allow sshd to be started manually through "systemctl start sshd".
     services.openssh = {
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index fe24246c22c..548babac38c 100644
--- a/nixos/modules/programs/bash/bash.nix
+++ b/nixos/modules/programs/bash/bash.nix
@@ -98,7 +98,7 @@ in
           if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]; then
             PROMPT_COLOR="1;31m"
             let $UID && PROMPT_COLOR="1;32m"
-            if [ -n "$INSIDE_EMACS" ]; then
+            if [ -n "$INSIDE_EMACS" -o "$TERM" == "eterm" -o "$TERM" == "eterm-color" ]; then
               # Emacs term mode doesn't support xterm title escape sequence (\e]0;)
               PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
             else
diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix
index 9816436cf95..c66c29ed45f 100644
--- a/nixos/modules/programs/zsh/zsh.nix
+++ b/nixos/modules/programs/zsh/zsh.nix
@@ -214,7 +214,6 @@ in
         # Need to disable features to support TRAMP
         if [ "$TERM" = dumb ]; then
             unsetopt zle prompt_cr prompt_subst
-            unfunction precmd preexec
             unset RPS1 RPROMPT
             PS1='$ '
             PROMPT='$ '
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 348ad094e5a..1048c2af2ea 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -256,6 +256,11 @@ with lib;
 
     # binfmt
     (mkRenamedOptionModule [ "boot" "binfmtMiscRegistrations" ] [ "boot" "binfmt" "registrations" ])
+    
+    # ACME
+    (mkRemovedOptionModule [ "security" "acme" "directory"] "ACME Directory is now hardcoded to /var/lib/acme and its permisisons are managed by systemd. See https://github.com/NixOS/nixpkgs/issues/53852 for more info.")
+    (mkRemovedOptionModule [ "security" "acme" "preDelay"] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
+    (mkRemovedOptionModule [ "security" "acme" "activationDelay"] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
 
     # KSM
     (mkRenamedOptionModule [ "hardware" "enableKSM" ] [ "hardware" "ksm" "enable" ])
diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index a6f9ed4329a..b321c04e574 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -80,25 +80,11 @@ let
         '';
       };
 
-      activationDelay = mkOption {
-        type = types.nullOr types.str;
-        default = null;
-        description = ''
-          Systemd time span expression to delay copying new certificates to main
-          state directory. See <citerefentry><refentrytitle>systemd.time</refentrytitle>
-          <manvolnum>7</manvolnum></citerefentry>.
-        '';
-      };
-
-      preDelay = mkOption {
-        type = types.lines;
-        default = "";
-        description = ''
-          Commands to run after certificates are re-issued but before they are
-          activated. Typically the new certificate is published to DNS.
-
-          Executed in the same directory with the new certificate.
-        '';
+      directory = mkOption {
+        type = types.str;
+        readOnly = true;
+        default = "/var/lib/acme/${name}";
+        description = "Directory where certificate and other state is stored.";
       };
 
       extraDomains = mkOption {
@@ -126,13 +112,6 @@ in
 
   options = {
     security.acme = {
-      directory = mkOption {
-        default = "/var/lib/acme";
-        type = types.str;
-        description = ''
-          Directory where certs and other state will be stored by default.
-        '';
-      };
 
       validMin = mkOption {
         type = types.int;
@@ -181,7 +160,11 @@ in
         default = { };
         type = with types; attrsOf (submodule certOpts);
         description = ''
-          Attribute set of certificates to get signed and renewed.
+          Attribute set of certificates to get signed and renewed. Creates
+          <literal>acme-''${cert}.{service,timer}</literal> systemd units for
+          each certificate defined here. Other services can add dependencies
+          to those units if they rely on the certificates being present,
+          or trigger restarts of the service if certificates get renewed.
         '';
         example = literalExample ''
           {
@@ -209,8 +192,7 @@ in
           servicesLists = mapAttrsToList certToServices cfg.certs;
           certToServices = cert: data:
               let
-                cpath = lpath + optionalString (data.activationDelay != null) ".staging";
-                lpath = "${cfg.directory}/${cert}";
+                lpath = "acme/${cert}";
                 rights = if data.allowKeysForGroup then "750" else "700";
                 cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
                           ++ optionals (data.email != null) [ "--email" data.email ]
@@ -224,79 +206,27 @@ in
                   serviceConfig = {
                     Type = "oneshot";
                     SuccessExitStatus = [ "0" "1" ];
-                    PermissionsStartOnly = true;
                     User = data.user;
                     Group = data.group;
                     PrivateTmp = true;
+                    StateDirectory = lpath;
+                    StateDirectoryMode = rights;
+                    WorkingDirectory = "/var/lib/${lpath}";
+                    ExecStart = "${pkgs.simp_le}/bin/simp_le ${escapeShellArgs cmdline}";
+                    ExecStopPost =
+                      let
+                        script = pkgs.writeScript "acme-post-stop" ''
+                          #!${pkgs.runtimeShell} -e
+                          ${data.postRun}
+                        '';
+                      in
+                        "+${script}";
                   };
-                  path = with pkgs; [ simp_le systemd ];
-                  preStart = ''
-                    mkdir -p '${cfg.directory}'
-                    chown 'root:root' '${cfg.directory}'
-                    chmod 755 '${cfg.directory}'
-                    if [ ! -d '${cpath}' ]; then
-                      mkdir '${cpath}'
-                    fi
-                    chmod ${rights} '${cpath}'
-                    chown -R '${data.user}:${data.group}' '${cpath}'
-                    mkdir -p '${data.webroot}/.well-known/acme-challenge'
-                    chown -R '${data.user}:${data.group}' '${data.webroot}/.well-known/acme-challenge'
-                  '';
-                  script = ''
-                    cd '${cpath}'
-                    set +e
-                    simp_le ${escapeShellArgs cmdline}
-                    EXITCODE=$?
-                    set -e
-                    echo "$EXITCODE" > /tmp/lastExitCode
-                    exit "$EXITCODE"
-                  '';
-                  postStop = ''
-                    cd '${cpath}'
-
-                    if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then
-                      ${if data.activationDelay != null then ''
-
-                      ${data.preDelay}
-
-                      if [ -d '${lpath}' ]; then
-                        systemd-run --no-block --on-active='${data.activationDelay}' --unit acme-setlive-${cert}.service
-                      else
-                        systemctl --wait start acme-setlive-${cert}.service
-                      fi
-                      '' else data.postRun}
-
-                      # noop ensuring that the "if" block is non-empty even if
-                      # activationDelay == null and postRun == ""
-                      true
-                    fi
-                  '';
-
-                  before = [ "acme-certificates.target" ];
-                  wantedBy = [ "acme-certificates.target" ];
-                };
-                delayService = {
-                  description = "Set certificate for ${cert} live";
-                  path = with pkgs; [ rsync ];
-                  serviceConfig = {
-                    Type = "oneshot";
-                  };
-                  script = ''
-                    rsync -a --delete-after '${cpath}/' '${lpath}'
-                  '';
-                  postStop = data.postRun;
+
                 };
                 selfsignedService = {
                   description = "Create preliminary self-signed certificate for ${cert}";
                   path = [ pkgs.openssl ];
-                  preStart = ''
-                      if [ ! -d '${cpath}' ]
-                      then
-                        mkdir -p '${cpath}'
-                        chmod ${rights} '${cpath}'
-                        chown '${data.user}:${data.group}' '${cpath}'
-                      fi
-                  '';
                   script =
                     ''
                       workdir="$(mktemp -d)"
@@ -318,50 +248,41 @@ in
                         -out $workdir/server.crt
 
                       # Copy key to destination
-                      cp $workdir/server.key ${cpath}/key.pem
+                      cp $workdir/server.key /var/lib/${lpath}/key.pem
 
                       # Create fullchain.pem (same format as "simp_le ... -f fullchain.pem" creates)
-                      cat $workdir/{server.crt,ca.crt} > "${cpath}/fullchain.pem"
+                      cat $workdir/{server.crt,ca.crt} > "/var/lib/${lpath}/fullchain.pem"
 
                       # Create full.pem for e.g. lighttpd
-                      cat $workdir/{server.key,server.crt,ca.crt} > "${cpath}/full.pem"
+                      cat $workdir/{server.key,server.crt,ca.crt} > "/var/lib/${lpath}/full.pem"
 
                       # Give key acme permissions
-                      chown '${data.user}:${data.group}' "${cpath}/"{key,fullchain,full}.pem
-                      chmod ${rights} "${cpath}/"{key,fullchain,full}.pem
+                      chown '${data.user}:${data.group}' "/var/lib/${lpath}/"{key,fullchain,full}.pem
+                      chmod ${rights} "/var/lib/${lpath}/"{key,fullchain,full}.pem
                     '';
                   serviceConfig = {
                     Type = "oneshot";
-                    PermissionsStartOnly = true;
                     PrivateTmp = true;
+                    StateDirectory = lpath;
                     User = data.user;
                     Group = data.group;
                   };
                   unitConfig = {
                     # Do not create self-signed key when key already exists
-                    ConditionPathExists = "!${cpath}/key.pem";
+                    ConditionPathExists = "!/var/lib/${lpath}/key.pem";
                   };
-                  before = [
-                    "acme-selfsigned-certificates.target"
-                  ];
-                  wantedBy = [
-                    "acme-selfsigned-certificates.target"
-                  ];
                 };
               in (
                 [ { name = "acme-${cert}"; value = acmeService; } ]
                 ++ optional cfg.preliminarySelfsigned { name = "acme-selfsigned-${cert}"; value = selfsignedService; }
-                ++ optional (data.activationDelay != null) { name = "acme-setlive-${cert}"; value = delayService; }
               );
           servicesAttr = listToAttrs services;
-          injectServiceDep = {
-            after = [ "acme-selfsigned-certificates.target" ];
-            wants = [ "acme-selfsigned-certificates.target" "acme-certificates.target" ];
-          };
         in
-          servicesAttr //
-          (if config.services.nginx.enable then { nginx = injectServiceDep; } else {}) //
-          (if config.services.lighttpd.enable then { lighttpd = injectServiceDep; } else {});
+          servicesAttr;
+
+      systemd.tmpfiles.rules =
+        flip mapAttrsToList cfg.certs
+        (cert: data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}");
 
       systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair
         ("acme-${cert}")
diff --git a/nixos/modules/security/acme.xml b/nixos/modules/security/acme.xml
index ef71fe53d0c..9d0a1995e0f 100644
--- a/nixos/modules/security/acme.xml
+++ b/nixos/modules/security/acme.xml
@@ -59,10 +59,8 @@ http {
   <para>
    The private key <filename>key.pem</filename> and certificate
    <filename>fullchain.pem</filename> will be put into
-   <filename>/var/lib/acme/foo.example.com</filename>. The target directory can
-   be configured with the option <xref linkend="opt-security.acme.directory"/>.
+   <filename>/var/lib/acme/foo.example.com</filename>.
   </para>
-
   <para>
    Refer to <xref linkend="ch-options" /> for all available configuration
    options for the <link linkend="opt-security.acme.certs">security.acme</link>
diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix
index 3ceaa6f5ff3..3d307b1abcf 100644
--- a/nixos/modules/services/continuous-integration/gitlab-runner.nix
+++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -111,7 +111,10 @@ in
   config = mkIf cfg.enable {
     systemd.services.gitlab-runner = {
       path = cfg.packages;
-      environment = config.networking.proxy.envVars;
+      environment = config.networking.proxy.envVars // {
+        # Gitlab runner will not start if the HOME variable is not set
+        HOME = cfg.workDir;
+      };
       description = "Gitlab Runner";
       after = [ "network.target" ]
         ++ optional hasDocker "docker.service";
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index c04cc1283b2..3f2857100f5 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -224,26 +224,17 @@ in
 
     environment.systemPackages = [ cfg.package ];
 
-    systemd.services.redis_init =
-      { description = "Redis Server Initialisation";
-
-        wantedBy = [ "redis.service" ];
-        before = [ "redis.service" ];
-
-        serviceConfig.Type = "oneshot";
-
-        script = ''
-          install -d -m0700 -o ${cfg.user} ${cfg.dbpath}
-          chown -R ${cfg.user} ${cfg.dbpath}
-        '';
-      };
-
     systemd.services.redis =
       { description = "Redis Server";
 
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
 
+        preStart = ''
+          install -d -m0700 -o ${cfg.user} ${cfg.dbpath}
+          chown -R ${cfg.user} ${cfg.dbpath}
+        '';
+
         serviceConfig = {
           ExecStart = "${cfg.package}/bin/redis-server ${redisConfig}";
           User = cfg.user;
diff --git a/nixos/modules/services/desktops/gnome3/gnome-user-share.nix b/nixos/modules/services/desktops/gnome3/gnome-user-share.nix
index 1f6ce2ae968..f8396287770 100644
--- a/nixos/modules/services/desktops/gnome3/gnome-user-share.nix
+++ b/nixos/modules/services/desktops/gnome3/gnome-user-share.nix
@@ -12,14 +12,7 @@ with lib;
 
     services.gnome3.gnome-user-share = {
 
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to enable GNOME User Share, a service that exports the
-          contents of the Public folder in your home directory on the local network.
-        '';
-      };
+      enable = mkEnableOption "GNOME User Share, a user-level file sharing service for GNOME";
 
     };
 
@@ -30,12 +23,13 @@ with lib;
 
   config = mkIf config.services.gnome3.gnome-user-share.enable {
 
-    environment.systemPackages = [ pkgs.gnome3.gnome-user-share ];
+    environment.systemPackages = [
+      pkgs.gnome3.gnome-user-share
+    ];
 
-    services.xserver.displayManager.sessionCommands = with pkgs.gnome3; ''
-      # Don't let gnome-control-center depend upon gnome-user-share
-      export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${gnome-user-share}/share/gsettings-schemas/${gnome-user-share.name}
-    '';
+    systemd.packages = [
+      pkgs.gnome3.gnome-user-share
+    ];
 
   };
 
diff --git a/nixos/modules/services/editors/emacs.xml b/nixos/modules/services/editors/emacs.xml
index acd69f18376..8ced302bad1 100644
--- a/nixos/modules/services/editors/emacs.xml
+++ b/nixos/modules/services/editors/emacs.xml
@@ -9,6 +9,7 @@
       Damien Cassou @DamienCassou
       Thomas Tuegel @ttuegel
       Rodney Lorrimar @rvl
+      Adam Hoese @adisbladis
   -->
  <para>
   <link xlink:href="https://www.gnu.org/software/emacs/">Emacs</link> is an
@@ -130,15 +131,6 @@
     Emacs packages through nixpkgs.
    </para>
 
-   <note>
-    <para>
-     This documentation describes the new Emacs packages framework in NixOS
-     16.03 (<varname>emacsPackagesNg</varname>) which should not be confused
-     with the previous and deprecated framework
-     (<varname>emacs24Packages</varname>).
-    </para>
-   </note>
-
    <para>
     The first step to declare the list of packages you want in your Emacs
     installation is to create a dedicated derivation. This can be done in a
@@ -164,7 +156,7 @@ $ ./result/bin/emacs
 
 let
   myEmacs = pkgs.emacs; <co xml:id="ex-emacsNix-2" />
-  emacsWithPackages = (pkgs.emacsPackagesNgGen myEmacs).emacsWithPackages; <co xml:id="ex-emacsNix-3" />
+  emacsWithPackages = (pkgs.emacsPackagesGen myEmacs).emacsWithPackages; <co xml:id="ex-emacsNix-3" />
 in
   emacsWithPackages (epkgs: (with epkgs.melpaStablePackages; [ <co xml:id="ex-emacsNix-4" />
     magit          # ; Integrate git &lt;C-x g&gt;
@@ -262,10 +254,10 @@ in
     <example xml:id="module-services-emacs-querying-packages">
      <title>Querying Emacs packages</title>
 <programlisting><![CDATA[
-nix-env -f "<nixpkgs>" -qaP -A emacsPackagesNg.elpaPackages
-nix-env -f "<nixpkgs>" -qaP -A emacsPackagesNg.melpaPackages
-nix-env -f "<nixpkgs>" -qaP -A emacsPackagesNg.melpaStablePackages
-nix-env -f "<nixpkgs>" -qaP -A emacsPackagesNg.orgPackages
+nix-env -f "<nixpkgs>" -qaP -A emacsPackages.elpaPackages
+nix-env -f "<nixpkgs>" -qaP -A emacsPackages.melpaPackages
+nix-env -f "<nixpkgs>" -qaP -A emacsPackages.melpaStablePackages
+nix-env -f "<nixpkgs>" -qaP -A emacsPackages.orgPackages
 ]]></programlisting>
     </example>
    </para>
diff --git a/nixos/modules/services/hardware/fwupd.nix b/nixos/modules/services/hardware/fwupd.nix
index cad9fa20de0..223adfee96e 100644
--- a/nixos/modules/services/hardware/fwupd.nix
+++ b/nixos/modules/services/hardware/fwupd.nix
@@ -8,8 +8,8 @@ let
   cfg = config.services.fwupd;
   originalEtc =
     let
-      mkEtcFile = n: nameValuePair n { source = "${pkgs.fwupd}/etc/${n}"; };
-    in listToAttrs (map mkEtcFile pkgs.fwupd.filesInstalledToEtc);
+      mkEtcFile = n: nameValuePair n { source = "${cfg.package}/etc/${n}"; };
+    in listToAttrs (map mkEtcFile cfg.package.filesInstalledToEtc);
   extraTrustedKeys =
     let
       mkName = p: "pki/fwupd/${baseNameOf (toString p)}";
@@ -24,7 +24,7 @@ let
     "fwupd/remotes.d/fwupd-tests.conf" = {
       source = pkgs.runCommand "fwupd-tests-enabled.conf" {} ''
         sed "s,^Enabled=false,Enabled=true," \
-        "${pkgs.fwupd.installedTests}/etc/fwupd/remotes.d/fwupd-tests.conf" > "$out"
+        "${cfg.package.installedTests}/etc/fwupd/remotes.d/fwupd-tests.conf" > "$out"
       '';
     };
   } else {};
@@ -77,13 +77,21 @@ in {
           <link xlink:href="https://github.com/hughsie/fwupd/blob/master/data/installed-tests/README.md">installed tests</link>.
         '';
       };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.fwupd;
+        description = ''
+          Which fwupd package to use.
+        '';
+      };
     };
   };
 
 
   ###### implementation
   config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.fwupd ];
+    environment.systemPackages = [ cfg.package ];
 
     environment.etc = {
       "fwupd/daemon.conf" = {
@@ -102,11 +110,11 @@ in {
 
     } // originalEtc // extraTrustedKeys // testRemote;
 
-    services.dbus.packages = [ pkgs.fwupd ];
+    services.dbus.packages = [ cfg.package ];
 
-    services.udev.packages = [ pkgs.fwupd ];
+    services.udev.packages = [ cfg.package ];
 
-    systemd.packages = [ pkgs.fwupd ];
+    systemd.packages = [ cfg.package ];
 
     systemd.tmpfiles.rules = [
       "d /var/lib/fwupd 0755 root root -"
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index 139011dca23..cdbb776454b 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -344,8 +344,7 @@ in
     systemd.services.dovecot2 = {
       description = "Dovecot IMAP/POP3 server";
 
-      after = [ "keys.target" "network.target" ];
-      wants = [ "keys.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       restartTriggers = [ cfg.configFile ];
 
diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix
new file mode 100644
index 00000000000..11dd5cb48db
--- /dev/null
+++ b/nixos/modules/services/mail/mailman.nix
@@ -0,0 +1,114 @@
+{ config, pkgs, lib, ... }:          # mailman.nix
+
+with lib;
+
+let
+
+  cfg = config.services.mailman;
+
+  pythonEnv = pkgs.python3.withPackages (ps: [ps.mailman]);
+
+  mailmanExe = with pkgs; stdenv.mkDerivation {
+    name = "mailman-" + python3Packages.mailman.version;
+    unpackPhase = ":";
+    installPhase = ''
+      mkdir -p $out/bin
+      sed >"$out/bin/mailman" <"${pythonEnv}/bin/mailman" \
+        -e "2 iexport MAILMAN_CONFIG_FILE=/etc/mailman.cfg"
+      chmod +x $out/bin/mailman
+    '';
+  };
+
+  mailmanCfg = ''
+    [mailman]
+    site_owner: ${cfg.siteOwner}
+    layout: fhs
+
+    [paths.fhs]
+    bin_dir: ${pkgs.python3Packages.mailman}/bin
+    var_dir: /var/lib/mailman
+    queue_dir: $var_dir/queue
+    log_dir: $var_dir/log
+    lock_dir: $var_dir/lock
+    etc_dir: /etc
+    ext_dir: $etc_dir/mailman.d
+    pid_file: /run/mailman/master.pid
+  '';
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.mailman = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable Mailman on this host. Requires an active Postfix installation.";
+      };
+
+      siteOwner = mkOption {
+        type = types.str;
+        default = "postmaster";
+        description = ''
+          Certain messages that must be delivered to a human, but which can't
+          be delivered to a list owner (e.g. a bounce from a list owner), will
+          be sent to this address. It should point to a human.
+        '';
+      };
+
+
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    assertions = [
+      { assertion = cfg.enable -> config.services.postfix.enable;
+        message = "Mailman requires Postfix";
+      }
+      { assertion = config.services.postfix.recipientDelimiter == "+";
+        message = "Postfix's recipientDelimiter must be set to '+'.";
+      }
+    ];
+
+    users.users.mailman = { description = "GNU Mailman"; isSystemUser = true; };
+
+    environment = {
+      systemPackages = [ mailmanExe ];
+      etc."mailman.cfg".text = mailmanCfg;
+    };
+
+    services.postfix = {
+      relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ];
+      config = {
+        transport_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
+        local_recipient_maps = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
+        # Mailman uses recipient delimiters, so we don't need special handling.
+        owner_request_special = "no";
+      };
+    };
+
+    systemd.services.mailman = {
+      description = "GNU Mailman Master Process";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${mailmanExe}/bin/mailman start";
+        ExecStop = "${mailmanExe}/bin/mailman stop";
+        User = "mailman";
+        Type = "forking";
+        StateDirectory = "mailman";
+        StateDirectoryMode = "0700";
+        RuntimeDirectory = "mailman";
+        PIDFile = "/run/mailman/master.pid";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index aa781f93b66..3826f728afd 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -8,7 +8,9 @@ let
 
   nix = cfg.package.out;
 
-  isNix20 = versionAtLeast (getVersion nix) "2.0pre";
+  nixVersion = getVersion nix;
+
+  isNix20 = versionAtLeast nixVersion "2.0pre";
 
   makeNixBuildUser = nr:
     { name = "nixbld${toString nr}";
@@ -61,6 +63,9 @@ let
           builders =
         ''}
         system-features = ${toString cfg.systemFeatures}
+        ${optionalString (versionAtLeast nixVersion "2.3pre") ''
+          sandbox-fallback = false
+        ''}
         $extraOptions
         END
       '' + optionalString cfg.checkConfig (
diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index f9b7550af23..463b1b882ac 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -156,6 +156,8 @@ in {
       };
     };
 
+    systemd.enableCgroupAccounting = true;
+
     security.wrappers."apps.plugin" = {
       source = "${pkgs.netdata}/libexec/netdata/plugins.d/apps.plugin.org";
       capabilities = "cap_dac_read_search,cap_sys_ptrace+ep";
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index 03771c8b5aa..bc0966e6b8e 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -916,9 +916,8 @@ in
     systemd.services.nsd = {
       description = "NSD authoritative only domain name service";
 
-      after = [ "keys.target" "network.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      wants = [ "keys.target" ];
 
       serviceConfig = {
         ExecStart = "${nsdPkg}/sbin/nsd -d -c ${nsdEnv}/nsd.conf";
diff --git a/nixos/modules/services/networking/softether.nix b/nixos/modules/services/networking/softether.nix
index 2e1ce3ccc50..2aa3ad4be03 100644
--- a/nixos/modules/services/networking/softether.nix
+++ b/nixos/modules/services/networking/softether.nix
@@ -70,8 +70,6 @@ in
 
       systemd.services.softether-init = {
         description = "SoftEther VPN services initial task";
-        after = [ "keys.target" ];
-        wants = [ "keys.target" ];
         wantedBy = [ "network.target" ];
         serviceConfig = {
           Type = "oneshot";
diff --git a/nixos/modules/services/networking/strongswan-swanctl/module.nix b/nixos/modules/services/networking/strongswan-swanctl/module.nix
index 817b5ec55f7..0fec3ef00ad 100644
--- a/nixos/modules/services/networking/strongswan-swanctl/module.nix
+++ b/nixos/modules/services/networking/strongswan-swanctl/module.nix
@@ -62,9 +62,8 @@ in  {
     systemd.services.strongswan-swanctl = {
       description = "strongSwan IPsec IKEv1/IKEv2 daemon using swanctl";
       wantedBy = [ "multi-user.target" ];
-      after    = [ "network-online.target" "keys.target" ];
-      wants    = [ "keys.target" ];
-      path = with pkgs; [ kmod iproute iptables utillinux ];
+      after    = [ "network-online.target" ];
+      path     = with pkgs; [ kmod iproute iptables utillinux ];
       environment = {
         STRONGSWAN_CONF = pkgs.writeTextFile {
           name = "strongswan.conf";
diff --git a/nixos/modules/services/networking/strongswan.nix b/nixos/modules/services/networking/strongswan.nix
index 41b69039ba7..4ff9c486059 100644
--- a/nixos/modules/services/networking/strongswan.nix
+++ b/nixos/modules/services/networking/strongswan.nix
@@ -151,8 +151,7 @@ in
       description = "strongSwan IPSec Service";
       wantedBy = [ "multi-user.target" ];
       path = with pkgs; [ kmod iproute iptables utillinux ]; # XXX Linux
-      wants = [ "keys.target" ];
-      after = [ "network-online.target" "keys.target" ];
+      after = [ "network-online.target" ];
       environment = {
         STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secretsFile managePlugins enabledPlugins; };
       };
diff --git a/nixos/modules/services/security/vault.nix b/nixos/modules/services/security/vault.nix
index 8176c168ca9..d5962ba9af9 100644
--- a/nixos/modules/services/security/vault.nix
+++ b/nixos/modules/services/security/vault.nix
@@ -70,7 +70,7 @@ in
       };
 
       storageBackend = mkOption {
-        type = types.enum [ "inmem" "file" "consul" "zookeeper" "s3" "azure" "dynamodb" "etcd" "mssql" "mysql" "postgresql" "swift" "gcs" ];
+        type = types.enum [ "inmem" "file" "consul" "zookeeper" "s3" "azure" "dynamodb" "etcd" "mssql" "mysql" "postgresql" "swift" "gcs" "raft" ];
         default = "inmem";
         description = "The name of the type of storage backend";
       };
diff --git a/nixos/modules/services/torrent/magnetico.nix b/nixos/modules/services/torrent/magnetico.nix
new file mode 100644
index 00000000000..02fa2ac0750
--- /dev/null
+++ b/nixos/modules/services/torrent/magnetico.nix
@@ -0,0 +1,214 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.magnetico;
+
+  dataDir = "/var/lib/magnetico";
+
+  credFile = with cfg.web;
+    if credentialsFile != null
+      then credentialsFile
+      else pkgs.writeText "magnetico-credentials"
+        (concatStrings (mapAttrsToList
+          (user: hash: "${user}:${hash}\n")
+          cfg.web.credentials));
+
+  # default options in magneticod/main.go
+  dbURI = concatStrings
+    [ "sqlite3://${dataDir}/database.sqlite3"
+      "?_journal_mode=WAL"
+      "&_busy_timeout=3000"
+      "&_foreign_keys=true"
+    ];
+
+  crawlerArgs = with cfg.crawler; escapeShellArgs
+    ([ "--database=${dbURI}"
+       "--indexer-addr=${address}:${toString port}"
+       "--indexer-max-neighbors=${toString maxNeighbors}"
+       "--leech-max-n=${toString maxLeeches}"
+     ] ++ extraOptions);
+
+  webArgs = with cfg.web; escapeShellArgs
+    ([ "--database=${dbURI}"
+       (if (cfg.web.credentialsFile != null || cfg.web.credentials != { })
+         then "--credentials=${toString credFile}"
+         else "--no-auth")
+     ] ++ extraOptions);
+
+in {
+
+  ###### interface
+
+  options.services.magnetico = {
+    enable = mkEnableOption "Magnetico, Bittorrent DHT crawler";
+
+    crawler.address = mkOption {
+      type = types.str;
+      default = "0.0.0.0";
+      example = "1.2.3.4";
+      description = ''
+        Address to be used for indexing DHT nodes.
+      '';
+    };
+
+    crawler.port = mkOption {
+      type = types.port;
+      default = 0;
+      description = ''
+        Port to be used for indexing DHT nodes.
+        This port should be added to
+        <option>networking.firewall.allowedTCPPorts</option>.
+      '';
+    };
+
+    crawler.maxNeighbors = mkOption {
+      type = types.ints.positive;
+      default = 1000;
+      description = ''
+        Maximum number of simultaneous neighbors of an indexer.
+        Be careful changing this number: high values can very
+        easily cause your network to be congested or even crash
+        your router.
+      '';
+    };
+
+    crawler.maxLeeches = mkOption {
+      type = types.ints.positive;
+      default = 200;
+      description = ''
+        Maximum number of simultaneous leeches.
+      '';
+    };
+
+    crawler.extraOptions = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      description = ''
+        Extra command line arguments to pass to magneticod.
+      '';
+    };
+
+    web.address = mkOption {
+      type = types.str;
+      default = "localhost";
+      example = "1.2.3.4";
+      description = ''
+        Address the web interface will listen to.
+      '';
+    };
+
+    web.port = mkOption {
+      type = types.port;
+      default = 8080;
+      description = ''
+        Port the web interface will listen to.
+      '';
+    };
+
+    web.credentials = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = lib.literalExample ''
+        {
+          myuser = "$2y$12$YE01LZ8jrbQbx6c0s2hdZO71dSjn2p/O9XsYJpz.5968yCysUgiaG";
+        }
+      '';
+      description = ''
+        The credentials to access the web interface, in case authentication is
+        enabled, in the format <literal>username:hash</literal>. If unset no
+        authentication will be required.
+
+        Usernames must start with a lowercase ([a-z]) ASCII character, might
+        contain non-consecutive underscores except at the end, and consists of
+        small-case a-z characters and digits 0-9.  The
+        <command>htpasswd</command> tool from the <package>apacheHttpd
+        </package> package may be used to generate the hash: <command>htpasswd
+        -bnBC 12 username password</command>
+
+        <warning>
+        <para>
+          The hashes will be stored world-readable in the nix store.
+          Consider using the <literal>credentialsFile</literal> option if you
+          don't want this.
+        </para>
+        </warning>
+      '';
+    };
+
+    web.credentialsFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        The path to the file holding the credentials to access the web
+        interface. If unset no authentication will be required.
+
+        The file must constain user names and password hashes in the format
+        <literal>username:hash </literal>, one for each line.  Usernames must
+        start with a lowecase ([a-z]) ASCII character, might contain
+        non-consecutive underscores except at the end, and consists of
+        small-case a-z characters and digits 0-9.
+        The <command>htpasswd</command> tool from the <package>apacheHttpd
+        </package> package may be used to generate the hash:
+        <command>htpasswd -bnBC 12 username password</command>
+      '';
+    };
+
+    web.extraOptions = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      description = ''
+        Extra command line arguments to pass to magneticow.
+      '';
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.users.magnetico = {
+      description = "Magnetico daemons user";
+    };
+
+    systemd.services.magneticod = {
+      description = "Magnetico DHT crawler";
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network-online.target" ];
+
+      serviceConfig = {
+        User      = "magnetico";
+        Restart   = "on-failure";
+        ExecStart = "${pkgs.magnetico}/bin/magneticod ${crawlerArgs}";
+      };
+    };
+
+    systemd.services.magneticow = {
+      description = "Magnetico web interface";
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network-online.target" "magneticod.service"];
+
+      serviceConfig = {
+        User           = "magnetico";
+        StateDirectory = "magnetico";
+        Restart        = "on-failure";
+        ExecStart      = "${pkgs.magnetico}/bin/magneticow ${webArgs}";
+      };
+    };
+
+    assertions =
+    [
+      {
+        assertion = cfg.web.credentialsFile != null || cfg.web.credentials != { };
+        message = ''
+          The options services.magnetico.web.credentialsFile and
+          services.magnetico.web.credentials are mutually exclusives.
+        '';
+      }
+    ];
+
+  };
+
+}
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 12200c879be..098160ee369 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -670,8 +670,7 @@ in
       { description = "Apache HTTPD";
 
         wantedBy = [ "multi-user.target" ];
-        wants = [ "keys.target" ];
-        after = [ "network.target" "fs.target" "keys.target" ];
+        after = [ "network.target" "fs.target" ];
 
         path =
           [ httpd pkgs.coreutils pkgs.gnugrep ]
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index c1a51fbf8b4..5c65a2388d6 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -4,23 +4,25 @@ with lib;
 
 let
   cfg = config.services.nginx;
+  certs = config.security.acme.certs;
+  vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
+  acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME && vhostConfig.useACMEHost == null) vhostsConfigs;
   virtualHosts = mapAttrs (vhostName: vhostConfig:
     let
       serverName = if vhostConfig.serverName != null
         then vhostConfig.serverName
         else vhostName;
-      acmeDirectory = config.security.acme.directory;
     in
     vhostConfig // {
       inherit serverName;
     } // (optionalAttrs vhostConfig.enableACME {
-      sslCertificate = "${acmeDirectory}/${serverName}/fullchain.pem";
-      sslCertificateKey = "${acmeDirectory}/${serverName}/key.pem";
-      sslTrustedCertificate = "${acmeDirectory}/${serverName}/fullchain.pem";
+      sslCertificate = "${certs.${serverName}.directory}/fullchain.pem";
+      sslCertificateKey = "${certs.${serverName}.directory}/key.pem";
+      sslTrustedCertificate = "${certs.${serverName}.directory}/full.pem";
     }) // (optionalAttrs (vhostConfig.useACMEHost != null) {
-      sslCertificate = "${acmeDirectory}/${vhostConfig.useACMEHost}/fullchain.pem";
-      sslCertificateKey = "${acmeDirectory}/${vhostConfig.useACMEHost}/key.pem";
-      sslTrustedCertificate = "${acmeDirectory}/${vhostConfig.useACMEHost}/fullchain.pem";
+      sslCertificate = "${certs.${vhostConfig.useACMEHost}.directory}/fullchain.pem";
+      sslCertificateKey = "${certs.${vhostConfig.useACMEHost}.directory}/key.pem";
+      sslTrustedCertificate = "${certs.${vhostConfig.useACMEHost}.directory}/fullchain.pem";
     })
   ) cfg.virtualHosts;
   enableIPv6 = config.networking.enableIPv6;
@@ -646,8 +648,9 @@ in
 
     systemd.services.nginx = {
       description = "Nginx Web Server";
-      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
+      wants = concatLists (map (vhostConfig: ["acme-${vhostConfig.serverName}.service" "acme-selfsigned-${vhostConfig.serverName}.service"]) acmeEnabledVhosts);
+      after = [ "network.target" ] ++ map (vhostConfig: "acme-selfsigned-${vhostConfig.serverName}.service") acmeEnabledVhosts;
       stopIfChanged = false;
       preStart =
         ''
@@ -680,8 +683,6 @@ in
 
     security.acme.certs = filterAttrs (n: v: v != {}) (
       let
-        vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
-        acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME && vhostConfig.useACMEHost == null) vhostsConfigs;
         acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = {
             user = cfg.user;
             group = lib.mkDefault cfg.group;
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 671a959cdde..dfb84113e13 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -18,7 +18,7 @@ in
   # determines the default: later modules (if enabled) are preferred.
   # E.g., if Plasma 5 is enabled, it supersedes xterm.
   imports = [
-    ./none.nix ./xterm.nix ./xfce.nix ./plasma5.nix ./lumina.nix
+    ./none.nix ./xterm.nix ./xfce.nix ./xfce4-14.nix ./plasma5.nix ./lumina.nix
     ./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix ./maxx.nix
     ./mate.nix ./pantheon.nix ./surf-display.nix
   ];
diff --git a/nixos/modules/services/x11/desktop-managers/xfce4-14.nix b/nixos/modules/services/x11/desktop-managers/xfce4-14.nix
new file mode 100644
index 00000000000..16329c093f9
--- /dev/null
+++ b/nixos/modules/services/x11/desktop-managers/xfce4-14.nix
@@ -0,0 +1,157 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.desktopManager.xfce4-14;
+in
+
+{
+  # added 2019-08-18
+  # needed to preserve some semblance of UI familarity
+  # with original XFCE module
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "xserver" "desktopManager" "xfce4-14" "extraSessionCommands" ]
+      [ "services" "xserver" "displayManager" "sessionCommands" ])
+  ];
+
+  options = {
+    services.xserver.desktopManager.xfce4-14 = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable the Xfce desktop environment.";
+      };
+
+    # TODO: support thunar plugins
+    #   thunarPlugins = mkOption {
+    #     default = [];
+    #     type = types.listOf types.package;
+    #     example = literalExample "[ pkgs.xfce4-14.thunar-archive-plugin ]";
+    #     description = ''
+    #       A list of plugin that should be installed with Thunar.
+    #     '';
+    #  };
+
+      noDesktop = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Don't install XFCE desktop components (xfdesktop, panel and notification daemon).";
+      };
+
+      enableXfwm = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Enable the XFWM (default) window manager.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = with pkgs.xfce4-14 // pkgs; [
+      glib # for gsettings
+      gtk3.out # gtk-update-icon-cache
+
+      gnome3.adwaita-icon-theme
+      hicolor-icon-theme
+      tango-icon-theme
+      xfce4-icon-theme
+
+      desktop-file-utils
+      shared-mime-info # for update-mime-database
+
+      # For a polkit authentication agent
+      polkit_gnome
+
+      # Needed by Xfce's xinitrc script
+      xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
+
+      exo
+      garcon
+      gtk-xfce-engine
+      libxfce4ui
+      xfconf
+
+      mousepad
+      ristretto
+      xfce4-appfinder
+      xfce4-screenshooter
+      xfce4-session
+      xfce4-settings
+      xfce4-terminal
+
+      # TODO: resync patch for plugins
+      #(thunar.override { thunarPlugins = cfg.thunarPlugins; })
+      thunar
+    ] # TODO: NetworkManager doesn't belong here
+      ++ optional config.networking.networkmanager.enable networkmanagerapplet
+      ++ optional config.hardware.pulseaudio.enable xfce4-pulseaudio-plugin
+      ++ optional config.powerManagement.enable xfce4-power-manager
+      ++ optional cfg.enableXfwm xfwm4
+      ++ optionals (!cfg.noDesktop) [
+        xfce4-panel
+        xfce4-notifyd
+        xfdesktop
+      ];
+
+    environment.pathsToLink = [
+      "/share/xfce4"
+      "/lib/xfce4"
+      "/share/gtksourceview-3.0"
+      "/share/gtksourceview-4.0"
+    ];
+
+    # Use the correct gnome3 packageSet
+    networking.networkmanager.basePackages = mkIf config.networking.networkmanager.enable {
+      inherit (pkgs) networkmanager modemmanager wpa_supplicant crda;
+      inherit (pkgs.gnome3) networkmanager-openvpn networkmanager-vpnc
+      networkmanager-openconnect networkmanager-fortisslvpn
+      networkmanager-iodine networkmanager-l2tp;
+    };
+
+    services.xserver.desktopManager.session = [{
+      name = "xfce4-14";
+      bgSupport = true;
+      start = ''
+        # Set GTK_PATH so that GTK+ can find the theme engines.
+        export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
+
+        # Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes.
+        export GTK_DATA_PREFIX=${config.system.path}
+
+        ${pkgs.runtimeShell} ${pkgs.xfce4-14.xinitrc} &
+        waitPID=$!
+      '';
+    }];
+
+    services.xserver.updateDbusEnvironment = true;
+    services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+
+    # Enable helpful DBus services.
+    services.udisks2.enable = true;
+    security.polkit.enable = true;
+    services.accounts-daemon.enable = true;
+    services.upower.enable = config.powerManagement.enable;
+    services.gnome3.glib-networking.enable = true;
+    services.gvfs.enable = true;
+    services.gvfs.package = pkgs.xfce.gvfs;
+    services.tumbler.enable = true;
+    services.dbus.packages =
+      optional config.services.printing.enable pkgs.system-config-printer;
+    services.xserver.libinput.enable = mkDefault true; # used in xfce4-settings-manager
+
+    # Enable default programs
+    programs.dconf.enable = true;
+
+    # Shell integration for VTE terminals
+    programs.bash.vteIntegration = mkDefault true;
+    programs.zsh.vteIntegration = mkDefault true;
+
+    # Systemd services
+    systemd.packages = with pkgs.xfce4-14; [
+      thunar
+    ] ++ optional (!cfg.noDesktop) xfce4-notifyd;
+
+  };
+}
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 0e87e6adbab..bf6b048654b 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -109,7 +109,7 @@ let
 
       # Allow the user to setup a custom session type.
       if test -x ~/.xsession; then
-          exec ~/.xsession
+          eval exec ~/.xsession "$@"
       fi
 
       if test "$1"; then
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index f9f86b5c87b..2287a82418f 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -112,11 +112,13 @@ let
       # Hibernate / suspend.
       "hibernate.target"
       "suspend.target"
+      "suspend-then-hibernate.target"
       "sleep.target"
       "hybrid-sleep.target"
       "systemd-hibernate.service"
       "systemd-hybrid-sleep.service"
       "systemd-suspend.service"
+      "systemd-suspend-then-hibernate.service"
 
       # Reboot stuff.
       "reboot.target"
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 9fe577bd83e..510b91904c5 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -256,6 +256,10 @@ let
     RestartForceExitStatus = "133";
     SuccessExitStatus = "133";
 
+    # Some containers take long to start
+    # especially when you automatically start many at once
+    TimeoutStartSec = cfg.timeoutStartSec;
+
     Restart = "on-failure";
 
     Slice = "machine.slice";
@@ -423,6 +427,7 @@ let
       extraVeths = {};
       additionalCapabilities = [];
       ephemeral = false;
+      timeoutStartSec = "15s";
       allowedDevices = [];
       hostAddress = null;
       hostAddress6 = null;
@@ -595,6 +600,18 @@ in
               '';
             };
 
+		    timeoutStartSec = mkOption {
+		      type = types.str;
+		      default = "1min";
+		      description = ''
+		        Time for the container to start. In case of a timeout,
+		        the container processes get killed.
+		        See <citerefentry><refentrytitle>systemd.time</refentrytitle>
+		        <manvolnum>7</manvolnum></citerefentry>
+		        for more information about the format.
+		       '';
+		    };
+
             bindMounts = mkOption {
               type = with types; loaOf (submodule bindMountOpts);
               default = {};
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index 7146aebf54b..ffa087bb6f2 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -136,6 +136,7 @@ in rec {
         (all nixos.tests.switchTest)
         (all nixos.tests.udisks2)
         (all nixos.tests.xfce)
+        (all nixos.tests.xfce4-14)
 
         nixpkgs.tarball
         (all allSupportedNixpkgs.emacs)
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix
index 4669a092433..8cfdea4a16e 100644
--- a/nixos/tests/acme.nix
+++ b/nixos/tests/acme.nix
@@ -3,19 +3,49 @@ let
 in import ./make-test.nix {
   name = "acme";
 
-  nodes = {
+  nodes = rec {
     letsencrypt = ./common/letsencrypt;
 
+    acmeStandalone = { config, pkgs, ... }: {
+      imports = [ commonConfig ];
+      networking.firewall.allowedTCPPorts = [ 80 ];
+      networking.extraHosts = ''
+        ${config.networking.primaryIPAddress} standalone.com
+      '';
+      security.acme.certs."standalone.com" = {
+        webroot = "/var/lib/acme/acme-challenges";
+      };
+      systemd.targets."acme-finished-standalone.com" = {};
+      systemd.services."acme-standalone.com" = {
+        wants = [ "acme-finished-standalone.com.target" ];
+        before = [ "acme-finished-standalone.com.target" ];
+      };
+      services.nginx.enable = true;
+      services.nginx.virtualHosts."standalone.com" = {
+        locations."/.well-known/acme-challenge".root = "/var/lib/acme/acme-challenges";
+      };
+    };
+
     webserver = { config, pkgs, ... }: {
       imports = [ commonConfig ];
       networking.firewall.allowedTCPPorts = [ 80 443 ];
 
       networking.extraHosts = ''
-        ${config.networking.primaryIPAddress} example.com
+        ${config.networking.primaryIPAddress} a.example.com
+        ${config.networking.primaryIPAddress} b.example.com
       '';
 
+      # A target remains active. Use this to probe the fact that
+      # a service fired eventhough it is not RemainAfterExit
+      systemd.targets."acme-finished-a.example.com" = {};
+      systemd.services."acme-a.example.com" = {
+        wants = [ "acme-finished-a.example.com.target" ];
+        before = [ "acme-finished-a.example.com.target" ];
+      };
+
       services.nginx.enable = true;
-      services.nginx.virtualHosts."example.com" = {
+
+      services.nginx.virtualHosts."a.example.com" = {
         enableACME = true;
         forceSSL = true;
         locations."/".root = pkgs.runCommand "docroot" {} ''
@@ -23,17 +53,63 @@ in import ./make-test.nix {
           echo hello world > "$out/index.html"
         '';
       };
+
+      nesting.clone = [
+        ({pkgs, ...}: {
+
+          networking.extraHosts = ''
+            ${config.networking.primaryIPAddress} b.example.com
+          '';
+          systemd.targets."acme-finished-b.example.com" = {};
+          systemd.services."acme-b.example.com" = {
+            wants = [ "acme-finished-b.example.com.target" ];
+            before = [ "acme-finished-b.example.com.target" ];
+          };
+          services.nginx.virtualHosts."b.example.com" = {
+            enableACME = true;
+            forceSSL = true;
+            locations."/".root = pkgs.runCommand "docroot" {} ''
+              mkdir -p "$out"
+              echo hello world > "$out/index.html"
+            '';
+          };
+        })
+      ];
     };
 
     client = commonConfig;
   };
 
-  testScript = ''
-    $letsencrypt->waitForUnit("default.target");
-    $letsencrypt->waitForUnit("boulder.service");
-    $webserver->waitForUnit("default.target");
-    $webserver->waitForUnit("acme-certificates.target");
-    $client->waitForUnit("default.target");
-    $client->succeed('curl https://example.com/ | grep -qF "hello world"');
-  '';
+  testScript = {nodes, ...}: 
+    let
+      newServerSystem = nodes.webserver2.config.system.build.toplevel;
+      switchToNewServer = "${newServerSystem}/bin/switch-to-configuration test";
+    in
+    # Note, waitForUnit does not work for oneshot services that do not have RemainAfterExit=true,
+    # this is because a oneshot goes from inactive => activating => inactive, and never
+    # reaches the active state. To work around this, we create some mock target units which
+    # get pulled in by the oneshot units. The target units linger after activation, and hence we
+    # can use them to probe that a oneshot fired. It is a bit ugly, but it is the best we can do
+    ''
+      $client->waitForUnit("default.target");
+      $letsencrypt->waitForUnit("default.target");
+      $letsencrypt->waitForUnit("boulder.service");
+
+      subtest "can request certificate with HTTPS-01 challenge", sub {
+        $acmeStandalone->waitForUnit("default.target");
+        $acmeStandalone->succeed("systemctl start acme-standalone.com.service");
+        $acmeStandalone->waitForUnit("acme-finished-standalone.com.target");
+      };
+
+      subtest "Can request certificate for nginx service", sub {
+        $webserver->waitForUnit("acme-finished-a.example.com.target");
+        $client->succeed('curl https://a.example.com/ | grep -qF "hello world"');
+      };
+
+      subtest "Can add another certificate for nginx service", sub {
+        $webserver->succeed("/run/current-system/fine-tune/child-1/bin/switch-to-configuration test");
+        $webserver->waitForUnit("acme-finished-b.example.com.target");
+        $client->succeed('curl https://b.example.com/ | grep -qF "hello world"');
+      };
+    '';
 }
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index e3e4ddab72c..557ee78df7c 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -278,6 +278,7 @@ in
   xautolock = handleTest ./xautolock.nix {};
   xdg-desktop-portal = handleTest ./xdg-desktop-portal.nix {};
   xfce = handleTest ./xfce.nix {};
+  xfce4-14 = handleTest ./xfce4-14.nix {};
   xmonad = handleTest ./xmonad.nix {};
   xrdp = handleTest ./xrdp.nix {};
   xss-lock = handleTest ./xss-lock.nix {};
diff --git a/nixos/tests/magnetico.nix b/nixos/tests/magnetico.nix
new file mode 100644
index 00000000000..bc7aef653ee
--- /dev/null
+++ b/nixos/tests/magnetico.nix
@@ -0,0 +1,28 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "magnetico";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ rnhmjoj ];
+  };
+
+  machine = { ... }: {
+    imports = [ ../modules/profiles/minimal.nix ];
+
+    networking.firewall.allowedTCPPorts = [ 9000 ];
+
+    services.magnetico = {
+      enable = true;
+      crawler.port = 9000;
+      web.credentials.user = "$2y$12$P88ZF6soFthiiAeXnz64aOWDsY3Dw7Yw8fZ6GtiqFNjknD70zDmNe";
+    };
+  };
+
+  testScript =
+    ''
+      startAll;
+      $machine->waitForUnit("magneticod");
+      $machine->waitForUnit("magneticow");
+      $machine->succeed("${pkgs.curl}/bin/curl -u user:password http://localhost:8080");
+      $machine->succeed("${pkgs.curl}/bin/curl -u user:wrongpwd http://localhost:8080") =~ "Unauthorised." or die;
+      $machine->shutdown();
+    '';
+})
diff --git a/nixos/tests/systemd.nix b/nixos/tests/systemd.nix
index 1c201e3b5dc..4b71b4d6759 100644
--- a/nixos/tests/systemd.nix
+++ b/nixos/tests/systemd.nix
@@ -71,11 +71,13 @@ import ./make-test.nix ({ pkgs, ... }: {
 
     # Regression test for https://github.com/NixOS/nixpkgs/issues/35268
     subtest "file system with x-initrd.mount is not unmounted", sub {
+      $machine->succeed('mountpoint -q /test-x-initrd-mount');
       $machine->shutdown;
-      $machine->waitForUnit('multi-user.target');
-      # If the file system was unmounted during the shutdown the file system
-      # has a last mount time, because the file system wasn't checked.
-      $machine->fail('dumpe2fs /dev/vdb | grep -q "^Last mount time: *n/a"');
+      system('qemu-img', 'convert', '-O', 'raw',
+             'vm-state-machine/empty2.qcow2', 'x-initrd-mount.raw');
+      my $extinfo = `${pkgs.e2fsprogs}/bin/dumpe2fs x-initrd-mount.raw`;
+      die "File system was not cleanly unmounted: $extinfo"
+        unless $extinfo =~ /^Filesystem state: *clean$/m;
     };
 
     subtest "systemd-shutdown works", sub {
diff --git a/nixos/tests/xfce4-14.nix b/nixos/tests/xfce4-14.nix
new file mode 100644
index 00000000000..d9b10aabaa1
--- /dev/null
+++ b/nixos/tests/xfce4-14.nix
@@ -0,0 +1,33 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "xfce4-14";
+
+  machine =
+    { pkgs, ... }:
+
+    { imports = [ ./common/user-account.nix ];
+
+      services.xserver.enable = true;
+
+      services.xserver.displayManager.auto.enable = true;
+      services.xserver.displayManager.auto.user = "alice";
+
+      services.xserver.desktopManager.xfce4-14.enable = true;
+    };
+
+  testScript =
+    ''
+      $machine->waitForX;
+      $machine->waitForFile("/home/alice/.Xauthority");
+      $machine->succeed("xauth merge ~alice/.Xauthority");
+      $machine->waitForWindow(qr/xfce4-panel/);
+      $machine->sleep(10);
+
+      # Check that logging in has given the user ownership of devices.
+      $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
+
+      $machine->succeed("su - alice -c 'DISPLAY=:0.0 xfce4-terminal &'");
+      $machine->waitForWindow(qr/Terminal/);
+      $machine->sleep(10);
+      $machine->screenshot("screen");
+    '';
+})