summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2019-08-31 09:50:38 +0200
committerFrederik Rietdijk <fridh@fridh.nl>2019-08-31 09:50:38 +0200
commitfc74ba8291a8a93cba428de6bc2e7c8c7f9330f4 (patch)
tree982675c7719f2060a550e80747dfa49c1a9d6b06 /nixos/modules
parent98640fd48212f8e6552517f667bba1901f5936d4 (diff)
parent81760f32353fa7f309a49fda17d90f43ac1e9a42 (diff)
downloadnixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.tar
nixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.tar.gz
nixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.tar.bz2
nixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.tar.lz
nixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.tar.xz
nixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.tar.zst
nixpkgs-fc74ba8291a8a93cba428de6bc2e7c8c7f9330f4.zip
Merge master into staging-next
Diffstat (limited to 'nixos/modules')
-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.nix154
-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
32 files changed, 631 insertions, 209 deletions
diff --git a/nixos/modules/config/fonts/fontconfig-penultimate.nix b/nixos/modules/config/fonts/fontconfig-penultimate.nix
index 24ed9c97668..7100f10dcfc 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 a7e57b8608d..99daec5ff5b 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 27f4166e100..6e9eefd74d1 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 092704c6fc3..feb54affbf8 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}")
@@ -377,9 +298,6 @@ in
           };
         })
       );
-
-      systemd.targets."acme-selfsigned-certificates" = mkIf cfg.preliminarySelfsigned {};
-      systemd.targets."acme-certificates" = {};
     })
 
   ];
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 6bc88c66dc1..088dfd71860 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 8b918dab86d..c69b77f9dee 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 0046dcd366f..65df93a00da 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 2a0360b12cb..a7951385062 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 b65374c9257..b61558b2201 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 = {};