summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2016-02-03 16:54:03 +0100
committerVladimír Čunát <vcunat@gmail.com>2016-02-03 16:57:19 +0100
commitae74c356d94b795eb07dfe9978788b49b70f5959 (patch)
treec13c6894b75f95d3a4dc4627efef508bb03dfba8 /nixos
parentc9790126312119ce5a2a8ac946d9f086e7ea9f55 (diff)
parent53e0f8b1cdf36574bfede6e62e2ac2739c3ef804 (diff)
downloadnixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.gz
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.bz2
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.lz
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.xz
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.tar.zst
nixlib-ae74c356d94b795eb07dfe9978788b49b70f5959.zip
Merge recent 'staging' into closure-size
Let's get rid of those merge conflicts.
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/user-mgmt.xml8
-rw-r--r--nixos/doc/manual/default.nix26
-rw-r--r--nixos/doc/manual/development/writing-modules.xml76
-rw-r--r--nixos/doc/manual/release-notes/rl-unstable.xml40
-rw-r--r--nixos/modules/config/fonts/fontconfig.nix17
-rw-r--r--nixos/modules/config/networking.nix16
-rw-r--r--nixos/modules/hardware/opengl.nix39
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl17
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh187
-rw-r--r--nixos/modules/misc/locate.nix127
-rw-r--r--nixos/modules/programs/ssh.nix5
-rw-r--r--nixos/modules/programs/venus.nix2
-rw-r--r--nixos/modules/rename.nix3
-rw-r--r--nixos/modules/security/audit.nix4
-rw-r--r--nixos/modules/security/ca.nix10
-rw-r--r--nixos/modules/services/mail/dovecot.nix104
-rw-r--r--nixos/modules/services/mail/postfix.nix37
-rw-r--r--nixos/modules/services/misc/ihaskell.nix2
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/monitoring/bosun.nix18
-rw-r--r--nixos/modules/services/monitoring/dd-agent.nix2
-rw-r--r--nixos/modules/services/networking/ddclient.nix2
-rw-r--r--nixos/modules/services/networking/gale.nix12
-rw-r--r--nixos/modules/services/networking/gateone.nix4
-rw-r--r--nixos/modules/services/networking/softether.nix31
-rw-r--r--nixos/modules/services/printing/cupsd.nix188
-rw-r--r--nixos/modules/services/search/elasticsearch.nix4
-rw-r--r--nixos/modules/services/system/uptimed.nix71
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix9
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix11
-rw-r--r--nixos/modules/services/x11/window-managers/i3.nix2
-rw-r--r--nixos/modules/services/x11/xserver.nix9
-rw-r--r--nixos/modules/system/activation/activation-script.nix22
-rw-r--r--nixos/modules/system/boot/networkd.nix31
-rw-r--r--nixos/modules/system/boot/systemd.nix6
-rw-r--r--nixos/modules/virtualisation/container-config.nix3
-rwxr-xr-x[-rw-r--r--]nixos/modules/virtualisation/nixos-container.pl2
-rw-r--r--nixos/modules/virtualisation/nova.nix2
-rw-r--r--nixos/modules/virtualisation/rkt.nix2
-rw-r--r--nixos/release.nix2
-rw-r--r--nixos/tests/grsecurity.nix19
-rw-r--r--nixos/tests/postgresql.nix26
42 files changed, 826 insertions, 374 deletions
diff --git a/nixos/doc/manual/configuration/user-mgmt.xml b/nixos/doc/manual/configuration/user-mgmt.xml
index 40362fbbb23f..631742059278 100644
--- a/nixos/doc/manual/configuration/user-mgmt.xml
+++ b/nixos/doc/manual/configuration/user-mgmt.xml
@@ -65,6 +65,14 @@ account named <literal>alice</literal>:
 <screen>
 $ useradd -m alice</screen>
 
+To make all nix tools available to this new user use `su - USER` which 
+opens a login shell (==shell that loads the profile) for given user. 
+This will create the ~/.nix-defexpr symlink. So run:
+
+<screen>
+$ su - alice -c "true"</screen>
+
+
 The flag <option>-m</option> causes the creation of a home directory
 for the new user, which is generally what you want.  The user does not
 have an initial password and therefore cannot log in.  A password can
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index be2d69a5f531..c1f21a2f5da6 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -1,4 +1,4 @@
-{ pkgs, options, version, revision }:
+{ pkgs, options, version, revision, extraSources ? [] }:
 
 with pkgs;
 with pkgs.lib;
@@ -17,19 +17,27 @@ let
 
   # Clean up declaration sites to not refer to the NixOS source tree.
   optionsList' = flip map optionsList (opt: opt // {
-    declarations = map (fn: stripPrefix fn) opt.declarations;
+    declarations = map (fn: stripAnyPrefixes fn) opt.declarations;
   }
   // optionalAttrs (opt ? example) { example = substFunction opt.example; }
   // optionalAttrs (opt ? default) { default = substFunction opt.default; }
   // optionalAttrs (opt ? type) { type = substFunction opt.type; });
 
-  prefix = toString ../../..;
-
-  stripPrefix = fn:
-    if substring 0 (stringLength prefix) fn == prefix then
-      substring (stringLength prefix + 1) 1000 fn
-    else
-      fn;
+  # We need to strip references to /nix/store/* from options,
+  # including any `extraSources` if some modules came from elsewhere,
+  # or else the build will fail.
+  #
+  # E.g. if some `options` came from modules in ${pkgs.customModules}/nix,
+  # you'd need to include `extraSources = [ "#{pkgs.customModules}" ]`
+  herePrefix = toString ../../..;
+  prefixesToStrip = [ herePrefix ] ++ extraSources;
+
+  stripAnyPrefixes = fn:
+    flip (flip fold fn) prefixesToStrip (fn: prefix:
+      if substring 0 (stringLength prefix) fn == prefix then
+        substring (stringLength prefix + 1) 1000 fn
+      else
+        fn);
 
   # Convert the list of options into an XML file.
   optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList');
diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml
index a699e74e5f62..971e586f20bd 100644
--- a/nixos/doc/manual/development/writing-modules.xml
+++ b/nixos/doc/manual/development/writing-modules.xml
@@ -107,12 +107,12 @@ the file system.  This module declares two options that can be defined
 by other modules (typically the user’s
 <filename>configuration.nix</filename>):
 <option>services.locate.enable</option> (whether the database should
-be updated) and <option>services.locate.period</option> (when the
+be updated) and <option>services.locate.interval</option> (when the
 update should be done).  It implements its functionality by defining
 two options declared by other modules:
 <option>systemd.services</option> (the set of all systemd services)
-and <option>services.cron.systemCronJobs</option> (the list of
-commands to be executed periodically by <command>cron</command>).</para>
+and <option>systemd.timers</option> (the list of commands to be
+executed periodically by <command>systemd</command>).</para>
 
 <example xml:id='locate-example'><title>NixOS Module for the “locate” Service</title>
 <programlisting>
@@ -120,53 +120,59 @@ commands to be executed periodically by <command>cron</command>).</para>
 
 with lib;
 
-let locatedb = "/var/cache/locatedb"; in
-
-{
-  options = {
-
-    services.locate = {
-
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          If enabled, NixOS will periodically update the database of
-          files used by the <command>locate</command> command.
-        '';
-      };
-
-      period = mkOption {
-        type = types.str;
-        default = "15 02 * * *";
-        description = ''
-          This option defines (in the format used by cron) when the
-          locate database is updated.  The default is to update at
-          02:15 at night every day.
-        '';
-      };
+let
+  cfg = config.services.locate;
+in {
+  options.services.locate = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        If enabled, NixOS will periodically update the database of
+        files used by the <command>locate</command> command.
+      '';
+    };
 
+    interval = mkOption {
+      type = types.str;
+      default = "02:15";
+      example = "hourly";
+      description = ''
+        Update the locate database at this interval. Updates by
+        default at 2:15 AM every day.
+
+        The format is described in
+        <citerefentry><refentrytitle>systemd.time</refentrytitle>
+        <manvolnum>7</manvolnum></citerefentry>.
+      '';
     };
 
+    # Other options omitted for documentation
   };
 
   config = {
-
     systemd.services.update-locatedb =
       { description = "Update Locate Database";
         path  = [ pkgs.su ];
         script =
           ''
-            mkdir -m 0755 -p $(dirname ${locatedb})
-            exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /run'
+            mkdir -m 0755 -p $(dirname ${toString cfg.output})
+            exec updatedb \
+              --localuser=${cfg.localuser} \
+              ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \
+              --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
           '';
       };
 
-    services.cron.systemCronJobs = optional config.services.locate.enable
-      "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service";
-
+    systemd.timers.update-locatedb = mkIf cfg.enable
+      { description = "Update timer for locate database";
+        partOf      = [ "update-locatedb.service" ];
+        wantedBy    = [ "timers.target" ];
+        timerConfig.OnCalendar = cfg.interval;
+      };
   };
-}</programlisting>
+}
+</programlisting>
 </example>
 
 <xi:include href="option-declarations.xml" />
diff --git a/nixos/doc/manual/release-notes/rl-unstable.xml b/nixos/doc/manual/release-notes/rl-unstable.xml
index cd828dfc8887..ffde542d4e18 100644
--- a/nixos/doc/manual/release-notes/rl-unstable.xml
+++ b/nixos/doc/manual/release-notes/rl-unstable.xml
@@ -145,6 +145,41 @@ nginx.override {
     from the ELPA, MELPA, and MELPA Stable repositories.
     </para>
   </listitem>
+
+  <listitem>
+    <para>Data directory for Postfix MTA server is moved from
+    <filename>/var/postfix</filename> to <filename>/var/lib/postfix</filename>.
+    Old configurations are migrated automatically. <literal>service.postfix</literal>
+    module has also received many improvements, such as correct directories' access
+    rights, new <literal>aliasFiles</literal> and <literal>mapFiles</literal>
+    options and more.</para>
+  </listitem>
+
+  <listitem>
+    <para>CUPS, installed by <literal>services.printing</literal> module, now
+    has its data directory in <filename>/var/lib/cups</filename>. Old
+    configurations from <filename>/etc/cups</filename> are moved there
+    automatically, but there might be problems. Also configuration options
+    <literal>services.printing.cupsdConf</literal> and
+    <literal>services.printing.cupsdFilesConf</literal> were removed
+    because they had been allowing one to override configuration variables
+    required for CUPS to work at all on NixOS. For most use cases,
+    <literal>services.printing.extraConf</literal> and new option
+    <literal>services.printing.extraFilesConf</literal> should be enough;
+    if you encounter a situation when they are not, please file a bug.</para>
+
+    <para>There are also Gutenprint improvements; in particular, a new option
+    <literal>services.printing.gutenprint</literal> is added to enable automatic
+    updating of Gutenprint PPMs; it's greatly recommended to enable it instead
+    of adding <literal>gutenprint</literal> to the <literal>drivers</literal> list.
+    </para>
+  </listitem>
+
+  <listitem>
+    <para><literal>services.xserver.vaapiDrivers</literal> has been removed. Use
+    <literal>services.hardware.opengl.extraPackages{,32}</literal> instead. You can
+    also specify VDPAU drivers there.</para>
+  </listitem>
 </itemizedlist>
 
 
@@ -158,6 +193,11 @@ nginx.override {
     <command>nix-shell</command> (without installing anything). </para>
   </listitem>
 
+  <listitem>
+    <para><literal>ejabberd</literal> module is brought back and now works on
+    NixOS.</para>
+  </listitem>
+
 </itemizedlist></para>
 
 </section>
diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix
index c027796d5476..1eaebe4b2bbd 100644
--- a/nixos/modules/config/fonts/fontconfig.nix
+++ b/nixos/modules/config/fonts/fontconfig.nix
@@ -129,6 +129,14 @@ with lib;
 
         };
 
+        cache32Bit = mkOption {
+          default = false;
+          type = types.bool;
+          description = ''
+            Generate system fonts cache for 32-bit applications.
+          '';
+        };
+
       };
 
     };
@@ -231,12 +239,19 @@ with lib;
         "${pkgs.fontconfig.out}/etc/fonts/fonts.conf";
 
       environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/00-nixos.conf".text =
-        ''
+        let
+          cache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
+        in ''
           <?xml version='1.0'?>
           <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
           <fontconfig>
             <!-- Font directories -->
             ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)}
+            <!-- Pre-generated font caches -->
+            <cachedir>${cache pkgs.fontconfig}</cachedir>
+            ${optionalString (pkgs.stdenv.isx86_64 && config.fonts.fontconfig.cache32Bit) ''
+              <cachedir>${cache pkgs.pkgsi686Linux.fontconfig}</cachedir>
+            ''}
           </fontconfig>
         '';
 
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index cbda34348930..0c4f4cbfa5c6 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -39,6 +39,17 @@ in
       '';
     };
 
+    networking.dnsExtensionMechanism = lib.mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable the <code>edns0</code> option in <filename>resolv.conf</filename>. With
+        that option set, <code>glibc</code> supports use of the extension mechanisms for
+        DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
+        which does not work without it.
+      '';
+    };
+
     networking.extraResolvconfConf = lib.mkOption {
       type = types.lines;
       default = "";
@@ -162,7 +173,10 @@ in
               libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null'
             '' + optionalString cfg.dnsSingleRequest ''
               # only send one DNS request at a time
-              resolv_conf_options='single-request'
+              resolv_conf_options+=' single-request'
+            '' + optionalString cfg.dnsExtensionMechanism ''
+              # enable extension mechanisms for DNS
+              resolv_conf_options+=' edns0'
             '' + optionalString hasLocalResolver ''
               # This hosts runs a full-blown DNS resolver.
               name_servers='127.0.0.1'
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index 7693bd5bb453..d3b146be6b33 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -10,7 +10,7 @@ let
 
   videoDrivers = config.services.xserver.videoDrivers;
 
-  makePackage = p: p.buildEnv {
+  makePackage = p: pkgs.buildEnv {
     name = "mesa-drivers+txc-${p.mesa_drivers.version}";
     paths =
       [ p.mesa_drivers
@@ -19,6 +19,16 @@ let
       ];
   };
 
+  package = pkgs.buildEnv {
+    name = "opengl-drivers";
+    paths = [ cfg.package ] ++ cfg.extraPackages;
+  };
+
+  package32 = pkgs.buildEnv {
+    name = "opengl-drivers-32bit";
+    paths = [ cfg.package32 ] ++ cfg.extraPackages32;
+  };
+
 in
 
 {
@@ -75,11 +85,32 @@ in
       internal = true;
       description = ''
         The package that provides the 32-bit OpenGL implementation on
-        64-bit systems.  Used when <option>driSupport32Bit</option> is
+        64-bit systems. Used when <option>driSupport32Bit</option> is
         set.
       '';
     };
 
+    hardware.opengl.extraPackages = mkOption {
+      type = types.listOf types.package;
+      default = [];
+      example = literalExample "with pkgs; [ vaapiIntel libvdpau-va-gl vaapiVdpau ]";
+      description = ''
+        Additional packages to add to OpenGL drivers. This can be used
+        to add additional VA-API/VDPAU drivers.
+      '';
+    };
+
+    hardware.opengl.extraPackages32 = mkOption {
+      type = types.listOf types.package;
+      default = [];
+      example = literalExample "with pkgs; [ vaapiIntel libvdpau-va-gl vaapiVdpau ]";
+      description = ''
+        Additional packages to add to 32-bit OpenGL drivers on
+        64-bit systems. Used when <option>driSupport32Bit</option> is
+        set. This can be used to add additional VA-API/VDPAU drivers.
+      '';
+    };
+
   };
 
   config = mkIf cfg.enable {
@@ -91,11 +122,11 @@ in
 
     system.activationScripts.setup-opengl =
       ''
-        ln -sfn ${cfg.package} /run/opengl-driver
+        ln -sfn ${package} /run/opengl-driver
         ${if pkgs.stdenv.isi686 then ''
           ln -sfn opengl-driver /run/opengl-driver-32
         '' else if cfg.driSupport32Bit then ''
-          ln -sfn ${cfg.package32} /run/opengl-driver-32
+          ln -sfn ${package32} /run/opengl-driver-32
         '' else ''
           rm -f /run/opengl-driver-32
         ''}
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index c590c4cde3f0..2284eba07a2d 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -148,7 +148,7 @@ sub pciCheck {
          $device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1"
         ) )
      {
-        push @modulePackages, "\${config.boot.kernelPackages.broadcom_sta}";
+        push @modulePackages, "config.boot.kernelPackages.broadcom_sta";
         push @kernelModules, "wl";
      }
 
@@ -422,13 +422,20 @@ EOF
 
 # Generate the hardware configuration file.
 
-sub toNixExpr {
+sub toNixStringList {
     my $res = "";
     foreach my $s (@_) {
         $res .= " \"$s\"";
     }
     return $res;
 }
+sub toNixList {
+    my $res = "";
+    foreach my $s (@_) {
+        $res .= " $s";
+    }
+    return $res;
+}
 
 sub multiLineList {
     my $indent = shift;
@@ -444,9 +451,9 @@ sub multiLineList {
     return $res;
 }
 
-my $initrdAvailableKernelModules = toNixExpr(uniq @initrdAvailableKernelModules);
-my $kernelModules = toNixExpr(uniq @kernelModules);
-my $modulePackages = toNixExpr(uniq @modulePackages);
+my $initrdAvailableKernelModules = toNixStringList(uniq @initrdAvailableKernelModules);
+my $kernelModules = toNixStringList(uniq @kernelModules);
+my $modulePackages = toNixList(uniq @modulePackages);
 
 my $fsAndSwap = "";
 if (!$noFilesystems) {
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 6792690b4c3b..105d1cd16252 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -19,6 +19,8 @@ rollback=
 upgrade=
 repair=
 profile=/nix/var/nix/profiles/system
+buildHost=
+targetHost=
 
 while [ "$#" -gt 0 ]; do
     i="$1"; shift 1
@@ -73,6 +75,14 @@ while [ "$#" -gt 0 ]; do
         fi
         shift 1
         ;;
+      --build-host|h)
+        buildHost="$1"
+        shift 1
+        ;;
+      --target-host|t)
+        targetHost="$1"
+        shift 1
+        ;;
       *)
         echo "$0: unknown option \`$i'"
         exit 1
@@ -80,6 +90,90 @@ while [ "$#" -gt 0 ]; do
     esac
 done
 
+
+if [ -z "$buildHost" -a -n "$targetHost" ]; then
+    buildHost="$targetHost"
+fi
+if [ "$targetHost" = localhost ]; then
+    targetHost=
+fi
+if [ "$buildHost" = localhost ]; then
+    buildHost=
+fi
+
+buildHostCmd() {
+    if [ -z "$buildHost" ]; then
+        "$@"
+    elif [ -n "$remoteNix" ]; then
+        ssh $SSHOPTS "$buildHost" PATH="$remoteNix:$PATH" "$@"
+    else
+        ssh $SSHOPTS "$buildHost" "$@"
+    fi
+}
+
+targetHostCmd() {
+    if [ -z "$targetHost" ]; then
+        "$@"
+    else
+        ssh $SSHOPTS "$targetHost" "$@"
+    fi
+}
+
+copyToTarget() {
+    if ! [ "$targetHost" = "$buildHost" ]; then
+        if [ -z "$targetHost" ]; then
+            NIX_SSHOPTS=$SSH_OPTS nix-copy-closure --from "$buildHost" "$1"
+        elif [ -z "$buildHost" ]; then
+            NIX_SSHOPTS=$SSH_OPTS nix-copy-closure --to "$targetHost" "$1"
+        else
+            buildHostCmd nix-copy-closure --to "$targetHost" "$1"
+        fi
+    fi
+}
+
+nixBuild() {
+    if [ -z "$buildHost" ]; then
+        nix-build "$@"
+    else
+        local instArgs=()
+        local buildArgs=()
+
+        while [ "$#" -gt 0 ]; do
+            local i="$1"; shift 1
+            case "$i" in
+              -o)
+                local out="$1"; shift 1
+                buildArgs+=("--add-root" "$out" "--indirect")
+                ;;
+              -A)
+                local j="$1"; shift 1
+                instArgs+=("$i" "$j")
+                ;;
+              -I)
+                # We don't want this in buildArgs
+                shift 1
+                ;;
+              "<"*) # nix paths
+                instArgs+=("$i")
+                ;;
+              *)
+                buildArgs+=("$i")
+                ;;
+            esac
+        done
+
+        local drv="$(nix-instantiate "${instArgs[@]}" "${extraBuildFlags[@]}")"
+        if [ -a "$drv" ]; then
+            NIX_SSHOPTS=$SSH_OPTS nix-copy-closure --to "$buildHost" "$drv"
+            buildHostCmd nix-store -r "$drv" "${buildArgs[@]}"
+        else
+            echo "nix-instantiate failed"
+            exit 1
+        fi
+  fi
+}
+
+
 if [ -z "$action" ]; then showSyntax; fi
 
 # Only run shell scripts from the Nixpkgs tree if the action is
@@ -128,7 +222,16 @@ fi
 
 
 tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX)
-trap 'rm -rf "$tmpDir"' EXIT
+SSHOPTS="$NIX_SSHOPTS -o ControlMaster=auto -o ControlPath=$tmpDir/ssh-%n -o ControlPersist=60"
+
+cleanup() {
+    for ctrl in "$tmpDir"/ssh-*; do
+        ssh -o ControlPath="$ctrl" -O exit dummyhost 2>/dev/null || true
+    done
+    rm -rf "$tmpDir"
+}
+trap cleanup EXIT
+
 
 
 # If the Nix daemon is running, then use it.  This allows us to use
@@ -150,30 +253,56 @@ if [ -n "$rollback" -o "$action" = dry-build ]; then
     buildNix=
 fi
 
+prebuiltNix() {
+    machine="$1"
+    if [ "$machine" = x86_64 ]; then
+        return /nix/store/xryr9g56h8yjddp89d6dw12anyb4ch7c-nix-1.10
+    elif [[ "$machine" =~ i.86 ]]; then
+        return /nix/store/2w92k5wlpspf0q2k9mnf2z42prx3bwmv-nix-1.10
+    else
+        echo "$0: unsupported platform"
+        exit 1
+    fi
+}
+
+remotePATH=
+
 if [ -n "$buildNix" ]; then
     echo "building Nix..." >&2
-    if ! nix-build '<nixpkgs/nixos>' -A config.nix.package -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
-        if ! nix-build '<nixpkgs/nixos>' -A nixFallback -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
-            if ! nix-build '<nixpkgs>' -A nix -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
-                machine="$(uname -m)"
-                if [ "$machine" = x86_64 ]; then
-                    nixStorePath=/nix/store/xryr9g56h8yjddp89d6dw12anyb4ch7c-nix-1.10
-                elif [[ "$machine" =~ i.86 ]]; then
-                    nixStorePath=/nix/store/2w92k5wlpspf0q2k9mnf2z42prx3bwmv-nix-1.10
-                else
-                    echo "$0: unsupported platform"
-                    exit 1
-                fi
+    nixDrv=
+    if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package "${extraBuildFlags[@]}")"; then
+        if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A nixFallback "${extraBuildFlags[@]}")"; then
+            if ! nixDrv="$(nix-instantiate '<nixpkgs>' --add-root $tmpDir/nix.drv --indirect -A nix "${extraBuildFlags[@]}")"; then
+                nixStorePath="$(prebuiltNix "$(uname -m)")"
                 if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \
                     --option extra-binary-caches https://cache.nixos.org/; then
                     echo "warning: don't know how to get latest Nix" >&2
                 fi
                 # Older version of nix-store -r don't support --add-root.
                 [ -e $tmpDir/nix ] || ln -sf $nixStorePath $tmpDir/nix
+                if [ -n "$buildHost" ]; then
+                    remoteNixStorePath="$(prebuiltNix "$(buildHostCmd uname -m)")"
+                    remoteNix="$remoteNixStorePath/bin"
+                    if ! buildHostCmd nix-store -r $remoteNixStorePath \
+                      --option extra-binary-caches https://cache.nixos.org/ >/dev/null; then
+                        remoteNix=
+                        echo "warning: don't know how to get latest Nix" >&2
+                    fi
+                fi
             fi
         fi
     fi
-    PATH=$tmpDir/nix/bin:$PATH
+    if [ -a "$nixDrv" ]; then
+        nix-store -r "$nixDrv"'!'"out" --add-root $tmpDir/nix --indirect >/dev/null
+        if [ -n "$buildHost" ]; then
+            nix-copy-closure --to "$buildHost" "$nixDrv"
+            # The nix build produces multiple outputs, we add them all to the remote path
+            for p in $(buildHostCmd nix-store -r "$(readlink "$nixDrv")" "${buildArgs[@]}"); do
+                remoteNix="$remoteNix${remoteNix:+:}$p/bin"
+            done
+        fi
+    fi
+    PATH="$tmpDir/nix/bin:$PATH"
 fi
 
 
@@ -200,31 +329,35 @@ fi
 if [ -z "$rollback" ]; then
     echo "building the system configuration..." >&2
     if [ "$action" = switch -o "$action" = boot ]; then
-        nix-env "${extraBuildFlags[@]}" -p "$profile" -f '<nixpkgs/nixos>' --set -A system
-        pathToConfig="$profile"
+        pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system "${extraBuildFlags[@]}")"
+        copyToTarget "$pathToConfig"
+        targetHostCmd nix-env -p "$profile" --set "$pathToConfig"
     elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
-        nix-build '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}" > /dev/null
-        pathToConfig=./result
+        pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")"
     elif [ "$action" = build-vm ]; then
-        nix-build '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}" > /dev/null
-        pathToConfig=./result
+        pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
     elif [ "$action" = build-vm-with-bootloader ]; then
-        nix-build '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}" > /dev/null
-        pathToConfig=./result
+        pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
     else
         showSyntax
     fi
+    # Copy build to target host if we haven't already done it
+    if ! [ "$action" = switch -o "$action" = boot ]; then
+        copyToTarget "$pathToConfig"
+    fi
 else # [ -n "$rollback" ]
     if [ "$action" = switch -o "$action" = boot ]; then
-        nix-env --rollback -p "$profile"
+        targetHostCmd nix-env --rollback -p "$profile"
         pathToConfig="$profile"
     elif [ "$action" = test -o "$action" = build ]; then
         systemNumber=$(
-            nix-env -p "$profile" --list-generations |
+            targetHostCmd nix-env -p "$profile" --list-generations |
             sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h'
         )
-        ln -sT "$profile"-${systemNumber}-link ./result
-        pathToConfig=./result
+        pathToConfig="$profile"-${systemNumber}-link
+        if [ -z "$targetHost" ]; then
+            ln -sT "$pathToConfig" ./result
+        fi
     else
         showSyntax
     fi
@@ -234,7 +367,7 @@ fi
 # If we're not just building, then make the new configuration the boot
 # default and/or activate it now.
 if [ "$action" = switch -o "$action" = boot -o "$action" = test -o "$action" = dry-activate ]; then
-    if ! $pathToConfig/bin/switch-to-configuration "$action"; then
+    if ! targetHostCmd $pathToConfig/bin/switch-to-configuration "$action"; then
         echo "warning: error(s) occurred while switching to the new configuration" >&2
         exit 1
     fi
diff --git a/nixos/modules/misc/locate.nix b/nixos/modules/misc/locate.nix
index 4f9c8d4e5ba1..318b81ca07c2 100644
--- a/nixos/modules/misc/locate.nix
+++ b/nixos/modules/misc/locate.nix
@@ -1,76 +1,74 @@
-{ config, lib, pkgs, ... }:
+{ config, options, lib, pkgs, ... }:
 
 with lib;
 
 let
   cfg = config.services.locate;
 in {
+  options.services.locate = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        If enabled, NixOS will periodically update the database of
+        files used by the <command>locate</command> command.
+      '';
+    };
 
-  ###### interface
-
-  options = {
-
-    services.locate = {
-
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          If enabled, NixOS will periodically update the database of
-          files used by the <command>locate</command> command.
-        '';
-      };
-
-      period = mkOption {
-        type = types.str;
-        default = "15 02 * * *";
-        description = ''
-          This option defines (in the format used by cron) when the
-          locate database is updated.
-          The default is to update at 02:15 at night every day.
-        '';
-      };
-
-      extraFlags = mkOption {
-        type = types.listOf types.str;
-        default = [ ];
-        description = ''
-          Extra flags to pass to <command>updatedb</command>.
-        '';
-      };
+    interval = mkOption {
+      type = types.str;
+      default = "02:15";
+      example = "hourly";
+      description = ''
+        Update the locate database at this interval. Updates by
+        default at 2:15 AM every day.
+
+        The format is described in
+        <citerefentry><refentrytitle>systemd.time</refentrytitle>
+        <manvolnum>7</manvolnum></citerefentry>.
+      '';
+    };
 
-      output = mkOption {
-        type = types.path;
-        default = "/var/cache/locatedb";
-        description = ''
-          The database file to build.
-        '';
-      };
+    # This is no longer supported, but we keep it to give a better warning below
+    period = mkOption { visible = false; };
 
-      localuser = mkOption {
-        type = types.str;
-        default = "nobody";
-        description = ''
-          The user to search non-network directories as, using
-          <command>su</command>.
-        '';
-      };
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      description = ''
+        Extra flags to pass to <command>updatedb</command>.
+      '';
+    };
 
-      includeStore = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to include <filename>/nix/store</filename> in the locate database.
-        '';
-      };
+    output = mkOption {
+      type = types.path;
+      default = "/var/cache/locatedb";
+      description = ''
+        The database file to build.
+      '';
+    };
 
+    localuser = mkOption {
+      type = types.str;
+      default = "nobody";
+      description = ''
+        The user to search non-network directories as, using
+        <command>su</command>.
+      '';
     };
 
+    includeStore = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to include <filename>/nix/store</filename> in the locate database.
+      '';
+    };
   };
 
-  ###### implementation
-
   config = {
+    warnings = let opt = options.services.locate.period; in optional opt.isDefined "The `period` definition in ${showFiles opt.files} has been removed; please replace it with `interval`, using the new systemd.time interval specifier.";
+
     systemd.services.update-locatedb =
       { description = "Update Locate Database";
         path  = [ pkgs.su ];
@@ -84,11 +82,18 @@ in {
           '';
         serviceConfig.Nice = 19;
         serviceConfig.IOSchedulingClass = "idle";
+        serviceConfig.PrivateTmp = "yes";
+        serviceConfig.PrivateNetwork = "yes";
+        serviceConfig.NoNewPrivileges = "yes";
+        serviceConfig.ReadOnlyDirectories = "/";
+        serviceConfig.ReadWriteDirectories = cfg.output;
       };
 
-    services.cron.systemCronJobs = optional config.services.locate.enable
-      "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service";
-
+    systemd.timers.update-locatedb = mkIf cfg.enable
+      { description = "Update timer for locate database";
+        partOf      = [ "update-locatedb.service" ];
+        wantedBy    = [ "timers.target" ];
+        timerConfig.OnCalendar = cfg.interval;
+      };
   };
-
 }
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 260888be485f..2da8ff738fbc 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -221,10 +221,7 @@ in
         fi
       '';
 
-    environment.interactiveShellInit = optionalString config.services.xserver.enable
-      ''
-        export SSH_ASKPASS=${askPassword}
-      '';
+    environment.variables.SSH_ASKPASS = optionalString config.services.xserver.enable askPassword;
 
     programs.ssh.askPassword = mkDefault "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
 
diff --git a/nixos/modules/programs/venus.nix b/nixos/modules/programs/venus.nix
index 8f85b602fe2c..c3756b4838c7 100644
--- a/nixos/modules/programs/venus.nix
+++ b/nixos/modules/programs/venus.nix
@@ -165,7 +165,7 @@ in
         script = "exec venus-planet ${configFile}";
         serviceConfig.User = "${cfg.user}";
         serviceConfig.Group = "${cfg.group}";
-        environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+        environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
         startAt = cfg.dates;
       };
 
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 010d44c40d19..6e10b47f03cc 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -77,6 +77,7 @@ with lib;
     (mkRenamedOptionModule [ "services" "xserver" "driSupport32Bit" ] [ "hardware" "opengl" "driSupport32Bit" ])
     (mkRenamedOptionModule [ "services" "xserver" "s3tcSupport" ] [ "hardware" "opengl" "s3tcSupport" ])
     (mkRenamedOptionModule [ "hardware" "opengl" "videoDrivers" ] [ "services" "xserver" "videoDrivers" ])
+    (mkRenamedOptionModule [ "services" "xserver" "vaapiDrivers" ] [ "hardware" "opengl" "extraPackages" ])
 
     (mkRenamedOptionModule [ "services" "mysql55" ] [ "services" "mysql" ])
 
@@ -99,6 +100,8 @@ with lib;
     (mkRemovedOptionModule [ "services" "syslog-ng" "listenToJournal" ])
     (mkRemovedOptionModule [ "ec2" "metadata" ])
     (mkRemovedOptionModule [ "services" "openvpn" "enable" ])
+    (mkRemovedOptionModule [ "services" "printing" "cupsFilesConf" ])
+    (mkRemovedOptionModule [ "services" "printing" "cupsdConf" ])
 
   ];
 }
diff --git a/nixos/modules/security/audit.nix b/nixos/modules/security/audit.nix
index 3aa31e079073..f223f52ec487 100644
--- a/nixos/modules/security/audit.nix
+++ b/nixos/modules/security/audit.nix
@@ -93,9 +93,11 @@ in {
 
   config = mkIf (cfg.enable == "lock" || cfg.enable) {
     systemd.services.audit = {
-      description = "pseudo-service representing the kernel audit state";
+      description = "Kernel Auditing";
       wantedBy = [ "basic.target" ];
 
+      unitConfig.ConditionVirtualization = "!container";
+
       path = [ pkgs.audit ];
 
       serviceConfig = {
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index ddfad52d42ed..98d73ed25426 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -4,7 +4,7 @@ with lib;
 
 let
 
-  caBundle = pkgs.runCommand "ca-bundle.crt"
+  caCertificates = pkgs.runCommand "ca-certificates.crt"
     { files =
         config.security.pki.certificateFiles ++
         [ (builtins.toFile "extra.crt" (concatStringsSep "\n" config.security.pki.certificates)) ];
@@ -26,7 +26,7 @@ in
       description = ''
         A list of files containing trusted root certificates in PEM
         format. These are concatenated to form
-        <filename>/etc/ssl/certs/ca-bundle.crt</filename>, which is
+        <filename>/etc/ssl/certs/ca-certificates.crt</filename>, which is
         used by many programs that use OpenSSL, such as
         <command>curl</command> and <command>git</command>.
       '';
@@ -56,13 +56,13 @@ in
     security.pki.certificateFiles = [ "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ];
 
     # NixOS canonical location + Debian/Ubuntu/Arch/Gentoo compatibility.
-    environment.etc."ssl/certs/ca-certificates.crt".source = caBundle;
+    environment.etc."ssl/certs/ca-certificates.crt".source = caCertificates;
 
     # Old NixOS compatibility.
-    environment.etc."ssl/certs/ca-bundle.crt".source = caBundle;
+    environment.etc."ssl/certs/ca-bundle.crt".source = caCertificates;
 
     # CentOS/Fedora compatibility.
-    environment.etc."pki/tls/certs/ca-bundle.crt".source = caBundle;
+    environment.etc."pki/tls/certs/ca-bundle.crt".source = caCertificates;
 
     environment.sessionVariables =
       { SSL_CERT_FILE          = "/etc/ssl/certs/ca-certificates.crt";
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index 36bdcaca47a3..11e8b26c75ef 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -9,16 +9,10 @@ let
   baseDir = "/run/dovecot2";
   stateDir = "/var/lib/dovecot";
 
-  protocols = concatStrings [
-    (optionalString cfg.enableImap "imap")
-    (optionalString cfg.enablePop3 "pop3")
-    (optionalString cfg.enableLmtp "lmtp")
-  ];
-
   dovecotConf = concatStrings [
     ''
       base_dir = ${baseDir}
-      protocols = ${protocols}
+      protocols = ${concatStringsSep " " cfg.protocols}
     ''
 
     (if isNull cfg.sslServerCert then ''
@@ -33,6 +27,8 @@ let
 
     ''
       default_internal_user = ${cfg.user}
+      ${optionalString (cfg.mailUser != null) "mail_uid = ${cfg.mailUser}"}
+      ${optionalString (cfg.mailGroup != null) "mail_gid = ${cfg.mailGroup}"}
 
       mail_location = ${cfg.mailLocation}
 
@@ -57,11 +53,17 @@ let
       }
     '')
 
+    (optionalString (cfg.sieveScripts != {}) ''
+      plugin {
+        ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
+      }
+    '')
+
     cfg.extraConfig
   ];
 
   modulesDir = pkgs.symlinkJoin "dovecot-modules"
-    (map (module: "${module}/lib/dovecot") cfg.modules);
+    (map (pkg: "${pkg}/lib/dovecot") ([ dovecotPkg ] ++ map (module: module.override { dovecot = dovecotPkg; }) cfg.modules));
 
 in
 {
@@ -87,6 +89,12 @@ in
       description = "Start the LMTP listener (when Dovecot is enabled).";
     };
 
+    protocols = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      description = "Additional listeners to start when Dovecot is enabled.";
+    };
+
     package = mkOption {
       type = types.package;
       default = pkgs.dovecot22;
@@ -129,13 +137,25 @@ in
       '';
     };
 
+    mailUser = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = "Default user to store mail for virtual users.";
+    };
+
+    mailGroup = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = "Default group to store mail for virtual users.";
+    };
+
     modules = mkOption {
       type = types.listOf types.package;
       default = [];
       example = literalExample "[ pkgs.dovecot_pigeonhole ]";
       description = ''
         Symlinks the contents of lib/dovecot of every given package into
-        /var/lib/dovecot/modules. This will make the given modules available
+        /etc/dovecot/modules. This will make the given modules available
         if a dovecot package with the module_dir patch applied (like
         pkgs.dovecot22, the default) is being used.
       '';
@@ -162,7 +182,13 @@ in
     enablePAM = mkOption {
       type = types.bool;
       default = true;
-      description = "Wether to create a own Dovecot PAM service and configure PAM user logins.";
+      description = "Whether to create a own Dovecot PAM service and configure PAM user logins.";
+    };
+
+    sieveScripts = mkOption {
+      type = types.attrsOf types.path;
+      default = {};
+      description = "Sieve scripts to be executed. Key is a sequence, e.g. 'before2', 'after' etc.";
     };
 
     showPAMFailure = mkOption {
@@ -177,23 +203,31 @@ in
 
     security.pam.services.dovecot2 = mkIf cfg.enablePAM {};
 
+    services.dovecot2.protocols =
+     optional cfg.enableImap "imap"
+     ++ optional cfg.enablePop3 "pop3"
+     ++ optional cfg.enableLmtp "lmtp";
+
     users.extraUsers = [
-      { name = cfg.user;
-        uid = config.ids.uids.dovecot2;
-        description = "Dovecot user";
-        group = cfg.group;
-      }
       { name = "dovenull";
         uid = config.ids.uids.dovenull2;
         description = "Dovecot user for untrusted logins";
         group = cfg.group;
       }
-    ];
+    ] ++ optional (cfg.user == "dovecot2")
+         { name = "dovecot2";
+           uid = config.ids.uids.dovecot2;
+           description = "Dovecot user";
+           group = cfg.group;
+         };
+
+    users.extraGroups = optional (cfg.group == "dovecot2")
+      { name = "dovecot2";
+        gid = config.ids.gids.dovecot2;
+      };
 
-    users.extraGroups = singleton {
-      name = cfg.group;
-      gid = config.ids.gids.dovecot2;
-    };
+    environment.etc."dovecot/modules".source = modulesDir;
+    environment.etc."dovecot/dovecot.conf".source = cfg.configFile;
 
     systemd.services.dovecot2 = {
       description = "Dovecot IMAP/POP3 server";
@@ -201,26 +235,38 @@ in
       after = [ "keys.target" "network.target" ];
       wants = [ "keys.target" ];
       wantedBy = [ "multi-user.target" ];
-
-      preStart = ''
-        mkdir -p "${baseDir}/login"
-        chown -R ${cfg.user}:${cfg.group} "${baseDir}"
-        rm -f "${stateDir}/modules"
-        ln -s "${modulesDir}" "${stateDir}/modules"
-      '';
+      restartTriggers = [ cfg.configFile ];
 
       serviceConfig = {
-        ExecStart = "${dovecotPkg}/sbin/dovecot -F -c ${cfg.configFile}";
+        ExecStart = "${dovecotPkg}/sbin/dovecot -F";
+        ExecReload = "${dovecotPkg}/sbin/doveadm reload";
         Restart = "on-failure";
         RestartSec = "1s";
         StartLimitInterval = "1min";
+        RuntimeDirectory = [ "dovecot2" ];
       };
+
+      preStart = ''
+        rm -rf ${stateDir}/sieve
+      '' + optionalString (cfg.sieveScripts != {}) ''
+        mkdir -p ${stateDir}/sieve
+        ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
+          if [ -d '${from}' ]; then
+            mkdir '${stateDir}/sieve/${to}'
+            cp ${from}/*.sieve '${stateDir}/sieve/${to}'
+          else
+            cp '${from}' '${stateDir}/sieve/${to}'
+          fi
+           ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
+        '') cfg.sieveScripts)}
+        chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve'
+      '';
     };
 
     environment.systemPackages = [ dovecotPkg ];
 
     assertions = [
-      { assertion = cfg.enablePop3 || cfg.enableImap;
+      { assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
         message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";
       }
       { assertion = isNull cfg.sslServerCert == isNull cfg.sslServerKey
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index 6c5d7e92702b..f2d8189de6ef 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -20,6 +20,23 @@ let
       mail_owner = ${user}
       default_privs = nobody
 
+      # NixOS specific locations
+      data_directory = /var/lib/postfix/data
+      queue_directory = /var/lib/postfix/queue
+
+      # Default location of everything in package
+      meta_directory = ${pkgs.postfix}/etc/postfix
+      command_directory = ${pkgs.postfix}/bin
+      sample_directory = /etc/postfix
+      newaliases_path = ${pkgs.postfix}/bin/newaliases
+      mailq_path = ${pkgs.postfix}/bin/mailq
+      readme_directory = no
+      sendmail_path = ${pkgs.postfix}/bin/sendmail
+      daemon_directory = ${pkgs.postfix}/libexec/postfix
+      manpage_directory = ${pkgs.postfix}/share/man
+      html_directory = ${pkgs.postfix}/share/postfix/doc/html
+      shlib_directory = no
+
     ''
     + optionalString config.networking.enableIPv6 ''
       inet_protocols = all
@@ -435,31 +452,35 @@ in
               mkdir -p /var/lib
               mv /var/postfix /var/lib/postfix
             fi
-            mkdir -p /var/lib/postfix/data /var/lib/postfix/queue/{pid,public,maildrop}
 
-            chown -R ${user}:${group} /var/lib/postfix
-            chown root /var/lib/postfix/queue
-            chown root /var/lib/postfix/queue/pid
-            chgrp -R ${setgidGroup} /var/lib/postfix/queue/{public,maildrop}
-            chmod 770 /var/lib/postfix/queue/{public,maildrop}
+            # All permissions set according ${pkgs.postfix}/etc/postfix/postfix-files script
+            mkdir -p /var/lib/postfix /var/lib/postfix/queue/{pid,public,maildrop}
+            chmod 0755 /var/lib/postfix
+            chown root:root /var/lib/postfix
 
             rm -rf /var/lib/postfix/conf
             mkdir -p /var/lib/postfix/conf
+            chmod 0755 /var/lib/postfix/conf
+            ln -sf ${pkgs.postfix}/etc/postfix/postfix-files
             ln -sf ${mainCfFile} /var/lib/postfix/conf/main.cf
             ln -sf ${masterCfFile} /var/lib/postfix/conf/master.cf
+
             ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
               ln -sf ${from} /var/lib/postfix/conf/${to}
-              postalias /var/lib/postfix/conf/${to}
+              ${pkgs.postfix}/bin/postalias /var/lib/postfix/conf/${to}
             '') cfg.aliasFiles)}
             ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
               ln -sf ${from} /var/lib/postfix/conf/${to}
-              postmap /var/lib/postfix/conf/${to}
+              ${pkgs.postfix}/bin/postmap /var/lib/postfix/conf/${to}
             '') cfg.mapFiles)}
 
             mkdir -p /var/spool/mail
             chown root:root /var/spool/mail
             chmod a+rwxt /var/spool/mail
             ln -sf /var/spool/mail /var/
+
+            #Finally delegate to postfix checking remain directories in /var/lib/postfix and set permissions on them
+            ${pkgs.postfix}/bin/postfix set-permissions config_directory=/var/lib/postfix/conf
           '';
         };
     }
diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix
index 1927922909ee..d0e9b839e754 100644
--- a/nixos/modules/services/misc/ihaskell.nix
+++ b/nixos/modules/services/misc/ihaskell.nix
@@ -6,7 +6,6 @@ let
 
   cfg = config.services.ihaskell;
   ihaskell = pkgs.ihaskell.override {
-    inherit (cfg.haskellPackages) ihaskell ghcWithPackages;
     packages = self: cfg.extraPackages self;
   };
 
@@ -22,7 +21,6 @@ in
       };
 
       haskellPackages = mkOption {
-        type = types.attrsOf types.package;
         default = pkgs.haskellPackages;
         defaultText = "pkgs.haskellPackages";
         example = literalExample "pkgs.haskell.packages.ghc784";
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 60e826bafd1e..24ae515a6b87 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -364,7 +364,7 @@ in
           ++ optionals cfg.distributedBuilds [ pkgs.gzip ];
 
         environment = cfg.envVars
-          // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; }
+          // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; }
           // config.networking.proxy.envVars;
 
         serviceConfig =
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
index 46273fc12187..51d38e8db4de 100644
--- a/nixos/modules/services/monitoring/bosun.nix
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -129,17 +129,19 @@ in {
       description = "bosun metrics collector (part of Bosun)";
       wantedBy = [ "multi-user.target" ];
 
-      preStart =
-        ''
-        mkdir -p `dirname ${cfg.stateFile}`;
-        touch ${cfg.stateFile}
-        touch ${cfg.stateFile}.tmp
+      preStart = ''
+        mkdir -p "$(dirname "${cfg.stateFile}")";
+        touch "${cfg.stateFile}"
+        touch "${cfg.stateFile}.tmp"
+
+        mkdir -p "${cfg.ledisDir}";
 
         if [ "$(id -u)" = 0 ]; then
-          chown ${cfg.user}:${cfg.group} ${cfg.stateFile}
-          chown ${cfg.user}:${cfg.group} ${cfg.stateFile}.tmp
+          chown ${cfg.user}:${cfg.group} "${cfg.stateFile}"
+          chown ${cfg.user}:${cfg.group} "${cfg.stateFile}.tmp"
+          chown ${cfg.user}:${cfg.group} "${cfg.ledisDir}"
         fi
-        '';
+      '';
 
       serviceConfig = {
         PermissionsStartOnly = true;
diff --git a/nixos/modules/services/monitoring/dd-agent.nix b/nixos/modules/services/monitoring/dd-agent.nix
index 8c847af3bfc0..ed9be73ba65b 100644
--- a/nixos/modules/services/monitoring/dd-agent.nix
+++ b/nixos/modules/services/monitoring/dd-agent.nix
@@ -183,7 +183,7 @@ in {
         Restart = "always";
         RestartSec = 2;
       };
-      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
       restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig ];
     };
 
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index ee06dfbbca3a..e60520c742bd 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -127,7 +127,7 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
 
-      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+      environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
       serviceConfig = {
         # Uncomment this if too many problems occur:
         # Type = "forking";
diff --git a/nixos/modules/services/networking/gale.nix b/nixos/modules/services/networking/gale.nix
index 3a5d9bd63c7b..bc975159cdfd 100644
--- a/nixos/modules/services/networking/gale.nix
+++ b/nixos/modules/services/networking/gale.nix
@@ -76,7 +76,7 @@ in
 
        system.activationScripts.gale = mkIf cfg.enable (
          stringAfter [ "users" "groups" ] ''
-           chmod -R 755 ${home}
+           chmod 755 ${home}
            mkdir -m 0777 -p ${home}/auth/cache
            mkdir -m 1777 -p ${home}/auth/local # GALE_DOMAIN.gpub
            mkdir -m 0700 -p ${home}/auth/private # ROOT.gpub
@@ -86,7 +86,8 @@ in
            mkdir -m 0700 -p ${home}/.gale/auth/private # GALE_DOMAIN.gpri
 
            ln -sf ${pkgs.gale}/etc/gale/auth/trusted/ROOT "${home}/auth/trusted/ROOT"
-           chown -R ${cfg.user}:${cfg.group} ${home}
+           chown ${cfg.user}:${cfg.group} ${home} ${home}/auth ${home}/auth/*
+           chown ${cfg.user}:${cfg.group} ${home}/.gale ${home}/.gale/auth ${home}/.gale/auth/private
          ''
        );
 
@@ -149,10 +150,9 @@ in
          after = [ "network.target" ];
 
          preStart = ''
-           install -m 0640 ${keyPath}/${cfg.domain}.gpri "${home}/.gale/auth/private/"
-           install -m 0644 ${gpubFile} "${home}/.gale/auth/private/${cfg.domain}.gpub"
-           install -m 0644 ${gpubFile} "${home}/auth/local/${cfg.domain}.gpub"
-           chown -R ${cfg.user}:${cfg.group} ${home}
+           install -m 0640 -o ${cfg.user} -g ${cfg.group} ${keyPath}/${cfg.domain}.gpri "${home}/.gale/auth/private/"
+           install -m 0644 -o ${cfg.user} -g ${cfg.group} ${gpubFile} "${home}/.gale/auth/private/${cfg.domain}.gpub"
+           install -m 0644 -o ${cfg.user} -g ${cfg.group} ${gpubFile} "${home}/auth/local/${cfg.domain}.gpub"
          '';
 
          serviceConfig = {
diff --git a/nixos/modules/services/networking/gateone.nix b/nixos/modules/services/networking/gateone.nix
index 93273837181e..78ff0b76198c 100644
--- a/nixos/modules/services/networking/gateone.nix
+++ b/nixos/modules/services/networking/gateone.nix
@@ -21,7 +21,7 @@ options = {
 };
 config = mkIf cfg.enable {
   environment.systemPackages = with pkgs.pythonPackages; [
-    gateone pkgs.openssh pkgs.procps pkgs.coreutils ];
+    gateone pkgs.openssh pkgs.procps pkgs.coreutils pkgs.cacert];
 
   users.extraUsers.gateone = {
     description = "GateOne privilege separation user";
@@ -49,8 +49,6 @@ config = mkIf cfg.enable {
       User = "gateone";
       Group = "gateone";
       WorkingDirectory = cfg.settingsDir;
-      PermissionsStartOnly = true;
-
     };
 
     wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/networking/softether.nix b/nixos/modules/services/networking/softether.nix
index a421b32f02c2..5e49efc3aa3a 100644
--- a/nixos/modules/services/networking/softether.nix
+++ b/nixos/modules/services/networking/softether.nix
@@ -61,11 +61,14 @@ in
             dataDir = cfg.dataDir;
           }))
         ];
-      systemd.services.softether = {
-        description = "SoftEther VPN services initial job";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
-        preStart = ''
+      systemd.services."softether-init" = {
+        description = "SoftEther VPN services initial task";
+        wantedBy = [ "network-interfaces.target" ];
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = false;
+        };
+        script = ''
             for d in vpnserver vpnbridge vpnclient vpncmd; do
                 if ! test -e ${cfg.dataDir}/$d; then
                     ${pkgs.coreutils}/bin/mkdir -m0700 -p ${cfg.dataDir}/$d
@@ -81,12 +84,12 @@ in
     (mkIf (cfg.vpnserver.enable) {
       systemd.services.vpnserver = {
         description = "SoftEther VPN Server";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
+        after = [ "softether-init.service" ];
+        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
+          Type = "forking";
           ExecStart = "${pkg}/bin/vpnserver start";
           ExecStop = "${pkg}/bin/vpnserver stop";
-          Type = "forking";
         };
         preStart = ''
             rm -rf ${cfg.dataDir}/vpnserver/vpnserver
@@ -101,12 +104,12 @@ in
     (mkIf (cfg.vpnbridge.enable) {
       systemd.services.vpnbridge = {
         description = "SoftEther VPN Bridge";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
+        after = [ "softether-init.service" ];
+        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
+          Type = "forking";
           ExecStart = "${pkg}/bin/vpnbridge start";
           ExecStop = "${pkg}/bin/vpnbridge stop";
-          Type = "forking";
         };
         preStart = ''
             rm -rf ${cfg.dataDir}/vpnbridge/vpnbridge
@@ -121,12 +124,12 @@ in
     (mkIf (cfg.vpnclient.enable) {
       systemd.services.vpnclient = {
         description = "SoftEther VPN Client";
-        after = [ "network-interfaces.target" ];
-        wantedBy = [ "multi-user.target" ];
+        after = [ "softether-init.service" ];
+        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
+          Type = "forking";
           ExecStart = "${pkg}/bin/vpnclient start";
           ExecStop = "${pkg}/bin/vpnclient stop";
-          Type = "forking";
         };
         preStart = ''
             rm -rf ${cfg.dataDir}/vpnclient/vpnclient
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index ba288a5d0611..9411a225beb3 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -4,10 +4,13 @@ with lib;
 
 let
 
-  inherit (pkgs) cups cups_filters;
+  inherit (pkgs) cups cups-pk-helper cups_filters gutenprint;
 
   cfg = config.services.printing;
 
+  avahiEnabled = config.services.avahi.enable;
+  polkitEnabled = config.security.polkit.enable;
+
   additionalBackends = pkgs.runCommand "additional-cups-backends" { }
     ''
       mkdir -p $out
@@ -30,12 +33,75 @@ let
   # cupsd.conf tells cupsd to use this tree.
   bindir = pkgs.buildEnv {
     name = "cups-progs";
-    paths = cfg.drivers;
-    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" "/etc/cups" ];
+    paths =
+      [ cups additionalBackends cups_filters pkgs.ghostscript ]
+      ++ optional cfg.gutenprint gutenprint
+      ++ cfg.drivers;
+    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" ];
     postBuild = cfg.bindirCmds;
     ignoreCollisions = true;
   };
 
+  writeConf = name: text: pkgs.writeTextFile {
+    inherit name text;
+    destination = "/etc/cups/${name}";
+  };
+
+  cupsFilesFile = writeConf "cups-files.conf" ''
+    SystemGroup root wheel
+
+    ServerBin ${bindir}/lib/cups
+    DataDir ${bindir}/share/cups
+
+    AccessLog syslog
+    ErrorLog syslog
+    PageLog syslog
+
+    TempDir ${cfg.tempDir}
+
+    # User and group used to run external programs, including
+    # those that actually send the job to the printer.  Note that
+    # Udev sets the group of printer devices to `lp', so we want
+    # these programs to run as `lp' as well.
+    User cups
+    Group lp
+
+    ${cfg.extraFilesConf}
+  '';
+
+  cupsdFile = writeConf "cupsd.conf" ''
+    ${concatMapStrings (addr: ''
+      Listen ${addr}
+    '') cfg.listenAddresses}
+    Listen /var/run/cups/cups.sock
+
+    SetEnv PATH ${bindir}/lib/cups/filter:${bindir}/bin
+
+    DefaultShared ${if cfg.defaultShared then "Yes" else "No"}
+
+    Browsing ${if cfg.browsing then "Yes" else "No"}
+
+    WebInterface ${if cfg.webInterface then "Yes" else "No"}
+
+    ${cfg.extraConf}
+  '';
+
+  browsedFile = writeConf "cups-browsed.conf" cfg.browsedConf;
+
+  rootdir = pkgs.buildEnv {
+    name = "cups-progs";
+    paths = [
+      cupsFilesFile
+      cupsdFile
+      (writeConf "client.conf" cfg.clientConf)
+      (writeConf "snmp.conf" cfg.snmpConf)
+    ] ++ optional avahiEnabled browsedFile
+      ++ optional cfg.gutenprint gutenprint
+      ++ cfg.drivers;
+    pathsToLink = [ "/etc/cups" ];
+    ignoreCollisions = true;
+  };
+
 in
 
 {
@@ -96,25 +162,11 @@ in
         '';
       };
 
-      cupsdConf = mkOption {
-        type = types.lines;
-        default = "";
-        example =
-          ''
-            BrowsePoll cups.example.com
-            LogLevel debug
-          '';
-        description = ''
-          The contents of the configuration file of the CUPS daemon
-          (<filename>cupsd.conf</filename>).
-        '';
-      };
-
-      cupsFilesConf = mkOption {
+      extraFilesConf = mkOption {
         type = types.lines;
         default = "";
         description = ''
-          The contents of the configuration file of the CUPS daemon
+          Extra contents of the configuration file of the CUPS daemon
           (<filename>cups-files.conf</filename>).
         '';
       };
@@ -171,8 +223,18 @@ in
         '';
       };
 
+      gutenprint = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable Gutenprint drivers for CUPS. This includes auto-updating
+          Gutenprint PPD files.
+        '';
+      };
+
       drivers = mkOption {
         type = types.listOf types.path;
+        default = [];
         example = literalExample "[ pkgs.splix ]";
         description = ''
           CUPS drivers to use. Drivers provided by CUPS, cups-filters, Ghostscript
@@ -204,15 +266,10 @@ in
         description = "CUPS printing services";
       };
 
-    environment.systemPackages = [ cups ];
+    environment.systemPackages = [ cups ] ++ optional polkitEnabled cups-pk-helper;
+    environment.etc."cups".source = "/var/lib/cups";
 
-    environment.etc."cups/client.conf".text = cfg.clientConf;
-    environment.etc."cups/cups-files.conf".text = cfg.cupsFilesConf;
-    environment.etc."cups/cupsd.conf".text = cfg.cupsdConf;
-    environment.etc."cups/cups-browsed.conf".text = cfg.browsedConf;
-    environment.etc."cups/snmp.conf".text = cfg.snmpConf;
-
-    services.dbus.packages = [ cups ];
+    services.dbus.packages = [ cups ] ++ optional polkitEnabled cups-pk-helper;
 
     # Cups uses libusb to talk to printers, and does not use the
     # linux kernel driver. If the driver is not in a black list, it
@@ -230,19 +287,35 @@ in
 
         preStart =
           ''
-            mkdir -m 0755 -p /etc/cups
             mkdir -m 0700 -p /var/cache/cups
             mkdir -m 0700 -p /var/spool/cups
             mkdir -m 0755 -p ${cfg.tempDir}
-          '';
 
-        restartTriggers =
-          [ config.environment.etc."cups/cups-files.conf".source
-            config.environment.etc."cups/cupsd.conf".source
-          ];
+            mkdir -m 0755 -p /var/lib/cups
+            # Backwards compatibility
+            if [ ! -L /etc/cups ]; then
+              mv /etc/cups/* /var/lib/cups
+              rmdir /etc/cups
+              ln -s /var/lib/cups /etc/cups
+            fi
+            # First, clean existing symlinks
+            if [ -n "$(ls /var/lib/cups)" ]; then
+              for i in /var/lib/cups/*; do
+                [ -L "$i" ] && rm "$i"
+              done
+            fi
+            # Then, populate it with static files
+            cd ${rootdir}/etc/cups
+            for i in *; do
+              [ ! -e "/var/lib/cups/$i" ] && ln -s "${rootdir}/etc/cups/$i" "/var/lib/cups/$i"
+            done
+            ${optionalString cfg.gutenprint ''
+              ${gutenprint}/bin/cups-genppdupdate
+            ''}
+          '';
       };
 
-    systemd.services.cups-browsed = mkIf config.services.avahi.enable
+    systemd.services.cups-browsed = mkIf avahiEnabled
       { description = "CUPS Remote Printer Discovery";
 
         wantedBy = [ "multi-user.target" ];
@@ -255,54 +328,13 @@ in
 
         serviceConfig.ExecStart = "${cups_filters}/bin/cups-browsed";
 
-        restartTriggers =
-          [ config.environment.etc."cups/cups-browsed.conf".source
-          ];
+        restartTriggers = [ browsedFile ];
       };
 
-    services.printing.drivers =
-      [ cups pkgs.ghostscript pkgs.cups_filters additionalBackends
-        pkgs.perl pkgs.coreutils pkgs.gnused pkgs.bc pkgs.gawk pkgs.gnugrep
-      ];
-
-    services.printing.cupsFilesConf =
-      ''
-        SystemGroup root wheel
-
-        ServerBin ${bindir}/lib/cups
-        DataDir ${bindir}/share/cups
-
-        AccessLog syslog
-        ErrorLog syslog
-        PageLog syslog
-
-        TempDir ${cfg.tempDir}
-
-        # User and group used to run external programs, including
-        # those that actually send the job to the printer.  Note that
-        # Udev sets the group of printer devices to `lp', so we want
-        # these programs to run as `lp' as well.
-        User cups
-        Group lp
-      '';
-
-    services.printing.cupsdConf =
+    services.printing.extraConf =
       ''
         LogLevel info
 
-        ${concatMapStrings (addr: ''
-          Listen ${addr}
-        '') cfg.listenAddresses}
-        Listen /var/run/cups/cups.sock
-
-        SetEnv PATH ${bindir}/lib/cups/filter:${bindir}/bin:${bindir}/sbin
-
-        DefaultShared ${if cfg.defaultShared then "Yes" else "No"}
-
-        Browsing ${if cfg.browsing then "Yes" else "No"}
-
-        WebInterface ${if cfg.webInterface then "Yes" else "No"}
-
         DefaultAuthType Basic
 
         <Location />
@@ -343,8 +375,6 @@ in
             Order deny,allow
           </Limit>
         </Policy>
-
-        ${cfg.extraConf}
       '';
 
     security.pam.services.cups = {};
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index e586600cdffd..478ebcfb9664 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -128,6 +128,7 @@ in {
       description = "Elasticsearch Daemon";
       wantedBy = [ "multi-user.target" ];
       after = [ "network-interfaces.target" ];
+      path = [ pkgs.inetutils ];
       environment = { ES_HOME = cfg.dataDir; };
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}";
@@ -139,8 +140,7 @@ in {
         if [ "$(id -u)" = 0 ]; then chown -R elasticsearch ${cfg.dataDir}; fi
 
         # Install plugins
-        rm ${cfg.dataDir}/plugins || true
-        ln -s ${esPlugins}/plugins ${cfg.dataDir}/plugins
+        ln -sfT ${esPlugins}/plugins ${cfg.dataDir}/plugins
       '';
       postStart = mkBefore ''
         until ${pkgs.curl.bin}/bin/curl -s -o /dev/null ${cfg.listenAddress}:${toString cfg.port}; do
diff --git a/nixos/modules/services/system/uptimed.nix b/nixos/modules/services/system/uptimed.nix
index 5f8916bbf9a4..b20d60968032 100644
--- a/nixos/modules/services/system/uptimed.nix
+++ b/nixos/modules/services/system/uptimed.nix
@@ -1,66 +1,55 @@
-{pkgs, config, lib, ...}:
+{ config, lib, pkgs, ... }:
 
-let
-
-  inherit (lib) mkOption mkIf singleton;
-
-  inherit (pkgs) uptimed;
+with lib;
 
+let
+  cfg = config.services.uptimed;
   stateDir = "/var/spool/uptimed";
-
-  uptimedUser = "uptimed";
-
 in
-
 {
-
-  ###### interface
-
   options = {
-
     services.uptimed = {
-
       enable = mkOption {
         default = false;
         description = ''
-          Uptimed allows you to track your highest uptimes.
+          Enable <literal>uptimed</literal>, allowing you to track
+          your highest uptimes.
         '';
       };
-
     };
-
   };
 
-
-  ###### implementation
-
-  config = mkIf config.services.uptimed.enable {
-
-    environment.systemPackages = [ uptimed ];
-
-    users.extraUsers = singleton
-      { name = uptimedUser;
-        uid = config.ids.uids.uptimed;
-        description = "Uptimed daemon user";
-        home = stateDir;
-      };
+  config = mkIf cfg.enable {
+    users.extraUsers.uptimed = {
+      description = "Uptimed daemon user";
+      home        = stateDir;
+      createHome  = true;
+      uid         = config.ids.uids.uptimed;
+    };
 
     systemd.services.uptimed = {
-      description = "Uptimed daemon";
-      wantedBy = [ "multi-user.target" ];
+      unitConfig.Documentation = "man:uptimed(8) man:uprecords(1)";
+      description = "uptimed service";
+      wantedBy    = [ "multi-user.target" ];
+
+      serviceConfig = {
+        Restart                 = "on-failure";
+        User                    = "uptimed";
+        Nice                    = 19;
+        IOSchedulingClass       = "idle";
+        PrivateTmp              = "yes";
+        PrivateNetwork          = "yes";
+        NoNewPrivileges         = "yes";
+        ReadWriteDirectories    = stateDir;
+        InaccessibleDirectories = "/home";
+        ExecStart               = "${pkgs.uptimed}/sbin/uptimed -f -p ${stateDir}/pid";
+      };
 
       preStart = ''
-        mkdir -m 0755 -p ${stateDir}
-        chown ${uptimedUser} ${stateDir}
-
         if ! test -f ${stateDir}/bootid ; then
-          ${uptimed}/sbin/uptimed -b
+          ${pkgs.uptimed}/sbin/uptimed -b
         fi
       '';
-
-      script = "${uptimed}/sbin/uptimed";
     };
-
   };
-
 }
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 3aa09193a66e..3437d8f38930 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -16,13 +16,6 @@ let
   cfg = config.services.xserver;
   xorg = pkgs.xorg;
 
-  vaapiDrivers = pkgs.buildEnv {
-    name = "vaapi-drivers";
-    paths = cfg.vaapiDrivers;
-    # We only want /lib/dri, but with a single input path, we need "/" for it to work
-    pathsToLink = [ "/" ];
-  };
-
   fontconfig = config.fonts.fontconfig;
   xresourcesXft = pkgs.writeText "Xresources-Xft" ''
     ${optionalString (fontconfig.dpi != 0) ''Xft.dpi: ${toString fontconfig.dpi}''}
@@ -107,8 +100,6 @@ let
           ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults
       fi
 
-      export LIBVA_DRIVERS_PATH=${vaapiDrivers}/lib/dri
-
       # Speed up application start by 50-150ms according to
       # http://kdemonkey.blogspot.nl/2008/04/magic-trick.html
       rm -rf $HOME/.compose-cache
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
index 6b344822977f..7a17a222bcab 100644
--- a/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -31,6 +31,9 @@ let
     [General]
     HaltCommand=${pkgs.systemd}/bin/systemctl poweroff
     RebootCommand=${pkgs.systemd}/bin/systemctl reboot
+    ${optionalString cfg.autoNumlock ''
+    Numlock=on
+    ''}
 
     [Theme]
     Current=${cfg.theme}
@@ -110,6 +113,14 @@ in
         '';
       };
 
+      autoNumlock = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable numlock at login.
+        '';
+      };
+
       setupScript = mkOption {
         type = types.str;
         default = "";
diff --git a/nixos/modules/services/x11/window-managers/i3.nix b/nixos/modules/services/x11/window-managers/i3.nix
index 0d5816e363d6..d43dacb1be6b 100644
--- a/nixos/modules/services/x11/window-managers/i3.nix
+++ b/nixos/modules/services/x11/window-managers/i3.nix
@@ -34,6 +34,6 @@ in
         '';
       }];
     };
-    environment.systemPackages = [ pkgs.i3 ];
+    environment.systemPackages = with pkgs; [ i3 i3status dmenu ];
   };
 }
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 86f0641b0e37..069653d1e458 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -216,15 +216,6 @@ in
         '';
       };
 
-      vaapiDrivers = mkOption {
-        type = types.listOf types.path;
-        default = [ ];
-        example = literalExample "[ pkgs.vaapiIntel pkgs.vaapiVdpau ]";
-        description = ''
-          Packages providing libva acceleration drivers.
-        '';
-      };
-
       startGnuPGAgent = mkOption {
         type = types.bool;
         default = false;
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index dd2ce1894ae6..72dd9b94a94e 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -95,6 +95,18 @@ in
 
     };
 
+    environment.usrbinenv = mkOption {
+      default = "${pkgs.coreutils}/bin/env";
+      example = literalExample ''
+        "''${pkgs.busybox}/bin/env"
+      '';
+      type = types.nullOr types.path;
+      visible = false;
+      description = ''
+        The env(1) executable that is linked system-wide to
+        <literal>/usr/bin/env</literal>.
+      '';
+    };
   };
 
 
@@ -129,11 +141,15 @@ in
         mkdir -m 0555 -p /var/empty
       '';
 
-    system.activationScripts.usrbinenv =
-      ''
+    system.activationScripts.usrbinenv = if config.environment.usrbinenv != null
+      then ''
         mkdir -m 0755 -p /usr/bin
-        ln -sfn ${pkgs.coreutils}/bin/env /usr/bin/.env.tmp
+        ln -sfn ${config.environment.usrbinenv} /usr/bin/.env.tmp
         mv /usr/bin/.env.tmp /usr/bin/env # atomically replace /usr/bin/env
+      ''
+      else ''
+        rm -f /usr/bin/env
+        rmdir --ignore-fail-on-non-empty /usr/bin /usr
       '';
 
     system.activationScripts.tmpfs =
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 34eea9af83b1..ab7485500261 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -93,11 +93,13 @@ let
 
   checkNetwork = checkUnitConfig "Network" [
     (assertOnlyFields [
-      "Description" "DHCP" "DHCPServer" "IPv4LL" "IPv4LLRoute"
+      "Description" "DHCP" "DHCPServer" "IPForward" "IPMasquerade" "IPv4LL" "IPv4LLRoute"
       "LLMNR" "Domains" "Bridge" "Bond"
     ])
     (assertValueOneOf "DHCP" ["both" "none" "v4" "v6"])
     (assertValueOneOf "DHCPServer" boolValues)
+    (assertValueOneOf "IPForward" ["yes" "no" "ipv4" "ipv6"])
+    (assertValueOneOf "IPMasquerade" boolValues)
     (assertValueOneOf "IPv4LL" boolValues)
     (assertValueOneOf "IPv4LLRoute" boolValues)
     (assertValueOneOf "LLMNR" boolValues)
@@ -129,6 +131,16 @@ let
     (assertValueOneOf "RequestBroadcast" boolValues)
   ];
 
+  checkDhcpServer = checkUnitConfig "DHCPServer" [
+    (assertOnlyFields [
+      "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec"
+      "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitTimezone" "Timezone"
+    ])
+    (assertValueOneOf "EmitDNS" boolValues)
+    (assertValueOneOf "EmitNTP" boolValues)
+    (assertValueOneOf "EmitTimezone" boolValues)
+  ];
+
   commonNetworkOptions = {
 
     enable = mkOption {
@@ -341,6 +353,18 @@ let
       '';
     };
 
+    dhcpServerConfig = mkOption {
+      default = {};
+      example = { PoolOffset = 50; EmitDNS = false; };
+      type = types.addCheck (types.attrsOf unitOption) checkDhcpServer;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[DHCPServer]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
     name = mkOption {
       type = types.nullOr types.str;
       default = null;
@@ -566,6 +590,11 @@ let
             ${attrsToSection def.dhcpConfig}
 
           ''}
+          ${optionalString (def.dhcpServerConfig != { }) ''
+            [DHCPServer]
+            ${attrsToSection def.dhcpServerConfig}
+
+          ''}
           ${flip concatMapStrings def.addresses (x: ''
             [Address]
             ${attrsToSection x.addressConfig}
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 211e0423216e..c5ee95f4c9a4 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -61,6 +61,8 @@ let
       "systemd-user-sessions.service"
       "dbus-org.freedesktop.login1.service"
       "dbus-org.freedesktop.machine1.service"
+      "org.freedesktop.login1.busname"
+      "org.freedesktop.machine1.busname"
       "user@.service"
 
       # Journal.
@@ -147,10 +149,14 @@ let
       "systemd-tmpfiles-setup-dev.service"
 
       # Misc.
+      "org.freedesktop.systemd1.busname"
       "systemd-sysctl.service"
       "dbus-org.freedesktop.timedate1.service"
       "dbus-org.freedesktop.locale1.service"
       "dbus-org.freedesktop.hostname1.service"
+      "org.freedesktop.timedate1.busname"
+      "org.freedesktop.locale1.busname"
+      "org.freedesktop.hostname1.busname"
       "systemd-timedated.service"
       "systemd-localed.service"
       "systemd-hostnamed.service"
diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix
index c210c8d5f25e..b4f9d8b6fc17 100644
--- a/nixos/modules/virtualisation/container-config.nix
+++ b/nixos/modules/virtualisation/container-config.nix
@@ -19,6 +19,9 @@ with lib;
     # Shut up warnings about not having a boot loader.
     system.build.installBootLoader = "${pkgs.coreutils}/bin/true";
 
+    # Not supported in systemd-nspawn containers.
+    security.audit.enable = false;
+
   };
 
 }
diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl
index 004385f728c6..eda57a9751eb 100644..100755
--- a/nixos/modules/virtualisation/nixos-container.pl
+++ b/nixos/modules/virtualisation/nixos-container.pl
@@ -97,10 +97,10 @@ if ($action eq "create") {
     if ($ensureUniqueName) {
         my $base = $containerName;
         for (my $nr = 0; ; $nr++) {
-            $containerName = "$base-$nr";
             $confFile = "/etc/containers/$containerName.conf";
             $root = "/var/lib/containers/$containerName";
             last unless -e $confFile || -e $root;
+            $containerName = "$base-$nr";
         }
     }
 
diff --git a/nixos/modules/virtualisation/nova.nix b/nixos/modules/virtualisation/nova.nix
index f356445abe46..c2837d0e2e24 100644
--- a/nixos/modules/virtualisation/nova.nix
+++ b/nixos/modules/virtualisation/nova.nix
@@ -146,7 +146,7 @@ in
 
         path =
           [ pkgs.sudo pkgs.vlan pkgs.nettools pkgs.iptables pkgs.qemu_kvm
-            pkgs.e2fsprogs pkgs.utillinux pkgs.multipath_tools pkgs.iproute
+            pkgs.e2fsprogs pkgs.utillinux pkgs.multipath-tools pkgs.iproute
             pkgs.bridge-utils
           ];
 
diff --git a/nixos/modules/virtualisation/rkt.nix b/nixos/modules/virtualisation/rkt.nix
index 7b4d46e0749e..c4c5cb3380e8 100644
--- a/nixos/modules/virtualisation/rkt.nix
+++ b/nixos/modules/virtualisation/rkt.nix
@@ -58,5 +58,7 @@ in
         ExecStart = "${pkgs.rkt}/bin/rkt gc ${cfg.gc.options}";
       };
     };
+
+    users.extraGroups.rkt = {};
   };
 }
diff --git a/nixos/release.nix b/nixos/release.nix
index 8a502ae2baa1..9c15b1ea0746 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -230,6 +230,7 @@ in rec {
   #tests.gitlab = callTest tests/gitlab.nix {};
   tests.gnome3 = callTest tests/gnome3.nix {};
   tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {};
+  tests.grsecurity = callTest tests/grsecurity.nix {};
   tests.i3wm = callTest tests/i3wm.nix {};
   tests.installer.grub1 = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).grub1.test);
   tests.installer.lvm = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).lvm.test);
@@ -287,6 +288,7 @@ in rec {
   tests.openssh = callTest tests/openssh.nix {};
   tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
   tests.peerflix = callTest tests/peerflix.nix {};
+  tests.postgresql = callTest tests/postgresql.nix {};
   tests.printing = callTest tests/printing.nix {};
   tests.proxy = callTest tests/proxy.nix {};
   tests.pumpio = callTest tests/pump.io.nix {};
diff --git a/nixos/tests/grsecurity.nix b/nixos/tests/grsecurity.nix
new file mode 100644
index 000000000000..14f1aa9ff885
--- /dev/null
+++ b/nixos/tests/grsecurity.nix
@@ -0,0 +1,19 @@
+# Basic test to make sure grsecurity works
+
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "grsecurity";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ copumpkin ];
+  };
+
+  machine = { config, pkgs, ... }:
+    { boot.kernelPackages = pkgs.linuxPackages_grsec_testing_server; };
+
+  testScript =
+    ''
+      $machine->succeed("uname -a") =~ /grsec/;
+      # FIXME: this seems to hang the whole test. Unclear why, but let's fix it
+      # $machine->succeed("${pkgs.paxtest}/bin/paxtest blackhat");
+    '';
+})
+
diff --git a/nixos/tests/postgresql.nix b/nixos/tests/postgresql.nix
new file mode 100644
index 000000000000..f17384b44ba6
--- /dev/null
+++ b/nixos/tests/postgresql.nix
@@ -0,0 +1,26 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "postgresql";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ zagy ];
+  };
+
+  nodes = {
+    master =
+      { pkgs, config, ... }:
+
+      {
+        services.postgresql.enable = true;
+        services.postgresql.initialScript =  pkgs.writeText "postgresql-init.sql"
+          ''
+          CREATE ROLE postgres WITH superuser login createdb;
+          '';
+      };
+  };
+
+  testScript = ''
+    startAll;
+    $master->waitForUnit("postgresql");
+    $master->sleep(10); # Hopefully this is long enough!!
+    $master->succeed("echo 'select 1' | sudo -u postgres psql");
+  '';
+})