summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/development/sources.xml10
-rw-r--r--nixos/doc/manual/release-notes/rl-1703.xml8
-rw-r--r--nixos/doc/manual/release-notes/rl-1709.xml2
-rw-r--r--nixos/lib/test-driver/Machine.pm18
-rw-r--r--nixos/lib/testing.nix5
-rwxr-xr-xnixos/maintainers/scripts/ec2/create-amis.sh15
-rwxr-xr-xnixos/maintainers/scripts/gce/create-gce.sh28
-rw-r--r--nixos/modules/config/fonts/fontconfig-penultimate.nix221
-rw-r--r--nixos/modules/config/fonts/fontconfig-ultimate.nix10
-rw-r--r--nixos/modules/config/fonts/fontconfig.nix54
-rw-r--r--nixos/modules/config/fonts/fonts.nix1
-rw-r--r--nixos/modules/config/shells-environment.nix3
-rw-r--r--nixos/modules/hardware/all-firmware.nix1
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh153
-rw-r--r--nixos/modules/installer/tools/nixos-prepare-root.sh105
-rw-r--r--nixos/modules/installer/tools/tools.nix13
-rw-r--r--nixos/modules/module-list.nix5
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.nix93
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.pl2
-rw-r--r--nixos/modules/programs/slock.nix26
-rw-r--r--nixos/modules/programs/ssmtp.nix45
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/security/acme.nix9
-rw-r--r--nixos/modules/security/polkit.nix2
-rw-r--r--nixos/modules/services/audio/slimserver.nix69
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix39
-rw-r--r--nixos/modules/services/continuous-integration/hydra/default.nix2
-rw-r--r--nixos/modules/services/databases/cassandra.nix8
-rw-r--r--nixos/modules/services/databases/mongodb.nix2
-rw-r--r--nixos/modules/services/hardware/bluetooth.nix31
-rw-r--r--nixos/modules/services/hardware/tlp.nix3
-rw-r--r--nixos/modules/services/logging/graylog.nix5
-rw-r--r--nixos/modules/services/misc/autorandr.nix43
-rw-r--r--nixos/modules/services/misc/cgminer.nix2
-rwxr-xr-xnixos/modules/services/misc/confd.nix2
-rw-r--r--nixos/modules/services/misc/etcd.nix2
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix25
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix4
-rw-r--r--nixos/modules/services/misc/plex.nix5
-rw-r--r--nixos/modules/services/misc/taskserver/default.nix2
-rw-r--r--nixos/modules/services/monitoring/collectd.nix2
-rw-r--r--nixos/modules/services/monitoring/grafana.nix12
-rw-r--r--nixos/modules/services/monitoring/graphite.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/default.nix9
-rw-r--r--nixos/modules/services/network-filesystems/netatalk.nix2
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix2
-rw-r--r--nixos/modules/services/network-filesystems/tahoe.nix6
-rw-r--r--nixos/modules/services/networking/aiccu.nix15
-rw-r--r--nixos/modules/services/networking/avahi-daemon.nix34
-rw-r--r--nixos/modules/services/networking/btsync.nix9
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix3
-rw-r--r--nixos/modules/services/networking/firefox/sync-server.nix2
-rw-r--r--nixos/modules/services/networking/i2pd.nix20
-rw-r--r--nixos/modules/services/networking/ircd-hybrid/default.nix2
-rw-r--r--nixos/modules/services/networking/mosquitto.nix2
-rw-r--r--nixos/modules/services/networking/murmur.nix10
-rw-r--r--nixos/modules/services/networking/networkmanager.nix7
-rw-r--r--nixos/modules/services/networking/prosody.nix4
-rw-r--r--nixos/modules/services/networking/searx.nix15
-rw-r--r--nixos/modules/services/networking/smokeping.nix7
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix2
-rw-r--r--nixos/modules/services/networking/sslh.nix2
-rw-r--r--nixos/modules/services/networking/znc.nix2
-rw-r--r--nixos/modules/services/scheduling/fcron.nix8
-rw-r--r--nixos/modules/services/security/oauth2_proxy.nix17
-rw-r--r--nixos/modules/services/system/earlyoom.nix96
-rw-r--r--nixos/modules/services/torrent/transmission.nix3
-rw-r--r--nixos/modules/services/web-apps/atlassian/crowd.nix2
-rw-r--r--nixos/modules/services/web-apps/quassel-webserver.nix4
-rw-r--r--nixos/modules/services/web-apps/tt-rss.nix2
-rw-r--r--nixos/modules/services/web-servers/lighttpd/gitweb.nix3
-rw-r--r--nixos/modules/services/x11/compton.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix10
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix2
-rw-r--r--nixos/modules/services/x11/hardware/multitouch.nix2
-rw-r--r--nixos/modules/services/x11/window-managers/default.nix1
-rw-r--r--nixos/modules/services/x11/window-managers/fvwm.nix41
-rw-r--r--nixos/modules/system/activation/top-level.nix2
-rw-r--r--nixos/modules/system/boot/initrd-ssh.nix33
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py10
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix2
-rw-r--r--nixos/modules/system/boot/luksroot.nix51
-rw-r--r--nixos/modules/system/boot/readonly-mountpoint.c20
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh8
-rw-r--r--nixos/modules/system/boot/stage-1.nix93
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh68
-rw-r--r--nixos/modules/system/boot/stage-2.nix19
-rw-r--r--nixos/modules/system/boot/systemd-lib.nix2
-rw-r--r--nixos/modules/system/boot/systemd.nix3
-rw-r--r--nixos/modules/tasks/filesystems.nix2
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix35
-rw-r--r--nixos/modules/tasks/powertop.nix27
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix6
-rw-r--r--nixos/modules/virtualisation/amazon-options.nix4
-rw-r--r--nixos/modules/virtualisation/docker.nix12
-rw-r--r--nixos/modules/virtualisation/ec2-amis.nix32
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix9
-rw-r--r--nixos/release.nix2
-rw-r--r--nixos/tests/docker.nix17
-rw-r--r--nixos/tests/installer.nix18
-rw-r--r--nixos/tests/postgresql.nix62
101 files changed, 1382 insertions, 596 deletions
diff --git a/nixos/doc/manual/development/sources.xml b/nixos/doc/manual/development/sources.xml
index 0b2528e9a77..a2896cd7a13 100644
--- a/nixos/doc/manual/development/sources.xml
+++ b/nixos/doc/manual/development/sources.xml
@@ -8,7 +8,7 @@
 
 <para>By default, NixOS’s <command>nixos-rebuild</command> command
 uses the NixOS and Nixpkgs sources provided by the
-<literal>nixos-unstable</literal> channel (kept in
+<literal>nixos</literal> channel (kept in
 <filename>/nix/var/nix/profiles/per-user/root/channels/nixos</filename>).
 To modify NixOS, however, you should check out the latest sources from
 Git.  This is as follows:
@@ -41,7 +41,7 @@ branch based on your current NixOS version:
 $ nixos-version
 17.09pre104379.6e0b727 (Hummingbird)
 
-$ git checkout -b local e3938c8
+$ git checkout -b local 6e0b727
 </screen>
 
 Or, to base your local branch on the latest version available in a
@@ -87,7 +87,11 @@ $ ln -s <replaceable>/my/sources</replaceable>/nixpkgs ~/.nix-defexpr/nixpkgs
 
 You may want to delete the symlink
 <filename>~/.nix-defexpr/channels_root</filename> to prevent root’s
-NixOS channel from clashing with your own tree.</para>
+NixOS channel from clashing with your own tree (this may break the
+command-not-found utility though). If you want to go back to the default
+state, you may just remove the <filename>~/.nix-defexpr</filename>
+directory completely, log out and log in again and it should have been
+recreated with a link to the root channels.</para>
 
 <!-- FIXME: not sure what this means.
 <para>You should not pass the base directory
diff --git a/nixos/doc/manual/release-notes/rl-1703.xml b/nixos/doc/manual/release-notes/rl-1703.xml
index 639b23b229b..28c573e6d23 100644
--- a/nixos/doc/manual/release-notes/rl-1703.xml
+++ b/nixos/doc/manual/release-notes/rl-1703.xml
@@ -501,6 +501,14 @@ following incompatible changes:</para>
       necessary to pull in all of <literal>bind</literal> to use them.
     </para>
   </listitem>
+
+  <listitem>
+    <para>
+      Per-user configuration was moved from <filename>~/.nixpkgs</filename> to
+      <filename>~/.config/nixpkgs</filename>. The former is still valid for
+      <filename>config.nix</filename> for backwards compatibility.
+    </para>
+  </listitem>
 </itemizedlist>
 </section>
 </section>
diff --git a/nixos/doc/manual/release-notes/rl-1709.xml b/nixos/doc/manual/release-notes/rl-1709.xml
index bd999b60013..5fba4c34ec8 100644
--- a/nixos/doc/manual/release-notes/rl-1709.xml
+++ b/nixos/doc/manual/release-notes/rl-1709.xml
@@ -35,6 +35,8 @@ following incompatible changes:</para>
 <itemizedlist>
   <listitem>
     <para>
+      Top-level <literal>idea</literal> package collection was renamed.
+      All JetBrains IDEs are now at <literal>jetbrains</literal>.
     </para>
   </listitem>
 </itemizedlist>
diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm
index 30664406b26..c619264eb94 100644
--- a/nixos/lib/test-driver/Machine.pm
+++ b/nixos/lib/test-driver/Machine.pm
@@ -542,16 +542,20 @@ sub getScreenText {
     $self->nest("performing optical character recognition", sub {
         my $tmpbase = Cwd::abs_path(".")."/ocr";
         my $tmpin = $tmpbase."in.ppm";
-        my $tmpout = "$tmpbase.ppm";
 
         $self->sendMonitorCommand("screendump $tmpin");
-        system("ppmtopgm $tmpin | pamscale 4 -filter=lanczos > $tmpout") == 0
-            or die "cannot scale screenshot";
+
+        my $magickArgs = "-filter Catrom -density 72 -resample 300 "
+                       . "-contrast -normalize -despeckle -type grayscale "
+                       . "-sharpen 1 -posterize 3 -negate -gamma 100 "
+                       . "-blur 1x65535";
+        my $tessArgs = "-c debug_file=/dev/null --psm 11 --oem 2";
+
+        $text = `convert $magickArgs $tmpin tiff:- | tesseract - - $tessArgs`;
+        my $status = $? >> 8;
         unlink $tmpin;
-        system("tesseract $tmpout $tmpbase") == 0 or die "OCR failed";
-        unlink $tmpout;
-        $text = read_file("$tmpbase.txt");
-        unlink "$tmpbase.txt";
+
+        die "OCR failed with exit code $status" if $status != 0;
     });
     return $text;
 }
diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix
index 8539fef0a19..58c447c76db 100644
--- a/nixos/lib/testing.nix
+++ b/nixos/lib/testing.nix
@@ -93,7 +93,7 @@ rec {
 
       vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
 
-      ocrProg = tesseract;
+      ocrProg = tesseract_4.override { enableLanguages = [ "eng" ]; };
 
       # Generate onvenience wrappers for running the test driver
       # interactively with the specified network, and for starting the
@@ -111,7 +111,8 @@ rec {
           vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
           wrapProgram $out/bin/nixos-test-driver \
             --add-flags "''${vms[*]}" \
-            ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \
+            ${lib.optionalString enableOCR
+              "--prefix PATH : '${ocrProg}/bin:${imagemagick}/bin'"} \
             --run "testScript=\"\$(cat $out/test-script)\"" \
             --set testScript '$testScript' \
             --set VLANS '${toString vlans}'
diff --git a/nixos/maintainers/scripts/ec2/create-amis.sh b/nixos/maintainers/scripts/ec2/create-amis.sh
index 1e397b0f176..24ced8da531 100755
--- a/nixos/maintainers/scripts/ec2/create-amis.sh
+++ b/nixos/maintainers/scripts/ec2/create-amis.sh
@@ -3,21 +3,20 @@
 
 # To start with do: nix-shell -p awscli --run "aws configure"
 
-
+set -e
 set -o pipefail
-#set -x
-
-stateDir=${TMPDIR:-/tmp}/ec2-image
-echo "keeping state in $stateDir"
-mkdir -p $stateDir
 
 version=$(nix-instantiate --eval --strict '<nixpkgs>' -A lib.nixpkgsVersion | sed s/'"'//g)
 major=${version:0:5}
 echo "NixOS version is $version ($major)"
 
+stateDir=/var/tmp/ec2-image-$version
+echo "keeping state in $stateDir"
+mkdir -p $stateDir
+
 rm -f ec2-amis.nix
 
-types="hvm pv"
+types="hvm"
 stores="ebs s3"
 regions="eu-west-1 eu-west-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1"
 
@@ -206,7 +205,7 @@ for type in $types; do
 
                     # Register the AMI.
                     if [ $type = pv ]; then
-                        kernel=$(aws ec2 describe-images --owner amazon --filters "Name=name,Values=pv-grub-hd0_1.04-$arch.gz" | jq -r .Images[0].ImageId)
+                        kernel=$(aws ec2 describe-images --owner amazon --filters "Name=name,Values=pv-grub-hd0_1.05-$arch.gz" | jq -r .Images[0].ImageId)
                         if [ "$kernel" = null ]; then break; fi
                         echo "using PV-GRUB kernel $kernel"
                         extraFlags+=" --virtualization-type paravirtual --kernel $kernel"
diff --git a/nixos/maintainers/scripts/gce/create-gce.sh b/nixos/maintainers/scripts/gce/create-gce.sh
index 7f8a0d23027..ef1801fe54b 100755
--- a/nixos/maintainers/scripts/gce/create-gce.sh
+++ b/nixos/maintainers/scripts/gce/create-gce.sh
@@ -1,15 +1,23 @@
-#! /bin/sh -e
+#!/usr/bin/env nix-shell
+#! nix-shell -i bash -p google-cloud-sdk
 
-BUCKET_NAME=${BUCKET_NAME:-nixos-images}
-export NIX_PATH=nixpkgs=../../../..
-export NIXOS_CONFIG=$(dirname $(readlink -f $0))/../../../modules/virtualisation/google-compute-image.nix
-export TIMESTAMP=$(date +%Y%m%d%H%M)
+set -euo pipefail
+
+BUCKET_NAME="${BUCKET_NAME:-nixos-images}"
+TIMESTAMP="$(date +%Y%m%d%H%M)"
+export TIMESTAMP
 
 nix-build '<nixpkgs/nixos>' \
-   -A config.system.build.googleComputeImage --argstr system x86_64-linux -o gce --option extra-binary-caches http://hydra.nixos.org -j 10
+   -A config.system.build.googleComputeImage \
+   --arg configuration "{ imports = [ <nixpkgs/nixos/modules/virtualisation/google-compute-image.nix> ]; }" \
+   --argstr system x86_64-linux \
+   -o gce \
+   -j 10
 
-img=$(echo gce/*.tar.gz)
-if ! gsutil ls gs://${BUCKET_NAME}/$(basename $img); then
-  gsutil cp $img gs://${BUCKET_NAME}/$(basename $img)
+img_path=$(echo gce/*.tar.gz)
+img_name=$(basename "$img_path")
+img_id=$(echo "$img_name" | sed 's|.raw.tar.gz$||;s|\.|-|g;s|_|-|g')
+if ! gsutil ls "gs://${BUCKET_NAME}/$img_name"; then
+  gsutil cp "$img_path" "gs://${BUCKET_NAME}/$img_name"
 fi
-gcloud compute images create $(basename $img .raw.tar.gz | sed 's|\.|-|' | sed 's|_|-|') --source-uri gs://${BUCKET_NAME}/$(basename $img)
+gcloud compute images create "$img_id" --source-uri "gs://${BUCKET_NAME}/$img_name"
diff --git a/nixos/modules/config/fonts/fontconfig-penultimate.nix b/nixos/modules/config/fonts/fontconfig-penultimate.nix
index 8e41d342117..3e163b8ec51 100644
--- a/nixos/modules/config/fonts/fontconfig-penultimate.nix
+++ b/nixos/modules/config/fonts/fontconfig-penultimate.nix
@@ -3,23 +3,236 @@
 with lib;
 
 let
-  cfg = config.fonts.fontconfig.penultimate;
+  cfg = config.fonts.fontconfig;
 
+  fcBool = x: "<bool>" + (boolToString x) + "</bool>";
+
+  # back-supported fontconfig version and package
+  # version is used for font cache generation
+  supportVersion = "210";
+  supportPkg     = pkgs."fontconfig_${supportVersion}";
+
+  # latest fontconfig version and package
+  # version is used for configuration folder name, /etc/fonts/VERSION/
+  # note: format differs from supportVersion and can not be used with makeCacheConf
   latestVersion  = pkgs.fontconfig.configVersion;
+  latestPkg      = pkgs.fontconfig;
+
+  # supported version fonts.conf
+  supportFontsConf = pkgs.makeFontsConf { fontconfig = supportPkg; fontDirectories = config.fonts.fonts; };
+
+  # configuration file to read fontconfig cache
+  # version dependent
+  # priority 0
+  cacheConfSupport = makeCacheConf { version = supportVersion; };
+  cacheConfLatest  = makeCacheConf {};
+
+  # generate the font cache setting file for a fontconfig version
+  # use latest when no version is passed
+  makeCacheConf = { version ? null }:
+    let
+      fcPackage = if builtins.isNull version
+                  then "fontconfig"
+                  else "fontconfig_${version}";
+      makeCache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
+      cache     = makeCache pkgs."${fcPackage}";
+      cache32   = makeCache pkgs.pkgsi686Linux."${fcPackage}";
+    in
+    pkgs.writeText "fc-00-nixos-cache.conf" ''
+      <?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}</cachedir>
+        ${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) ''
+          <cachedir>${cache32}</cachedir>
+        ''}
+      </fontconfig>
+    '';
 
   # The configuration to be included in /etc/font/
-  confPkg = pkgs.runCommand "font-penultimate-conf" {} ''
+  penultimateConf = pkgs.runCommand "font-penultimate-conf" {} ''
     support_folder=$out/etc/fonts/conf.d
     latest_folder=$out/etc/fonts/${latestVersion}/conf.d
 
     mkdir -p $support_folder
     mkdir -p $latest_folder
 
-    # fontconfig ultimate various configuration files
+    ln -s ${supportFontsConf} $support_folder/../fonts.conf
+    ln -s ${latestPkg.out}/etc/fonts/fonts.conf \
+          $latest_folder/../fonts.conf
+
+    # fontconfig-penultimate various configuration files
     ln -s ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/*.conf \
           $support_folder
     ln -s ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/*.conf \
           $latest_folder
+
+    ln -s ${cacheConfSupport} $support_folder/00-nixos-cache.conf
+    ln -s ${cacheConfLatest}  $latest_folder/00-nixos-cache.conf
+
+    rm $support_folder/10-antialias.conf $latest_folder/10-antialias.conf
+    ln -s ${antialiasConf} $support_folder/10-antialias.conf
+    ln -s ${antialiasConf} $latest_folder/10-antialias.conf
+
+    rm $support_folder/10-hinting.conf $latest_folder/10-hinting.conf
+    ln -s ${hintingConf} $support_folder/10-hinting.conf
+    ln -s ${hintingConf} $latest_folder/10-hinting.conf
+
+    ${optionalString cfg.useEmbeddedBitmaps ''
+    rm $support_folder/10-no-embedded-bitmaps.conf
+    rm $latest_folder/10-no-embedded-bitmaps.conf
+    ''}
+
+    rm $support_folder/10-subpixel.conf $latest_folder/10-subpixel.conf
+    ln -s ${subpixelConf} $support_folder/10-subpixel.conf
+    ln -s ${subpixelConf} $latest_folder/10-subpixel.conf
+
+    ${optionalString (cfg.dpi != 0) ''
+    ln -s ${dpiConf} $support_folder/11-dpi.conf
+    ln -s ${dpiConf} $latest_folder/11-dpi.conf
+    ''}
+
+    ${optionalString (!cfg.includeUserConf) ''
+    rm $support_folder/50-user.conf
+    rm $latest_folder/50-user.conf
+    ''}
+
+    # 51-local.conf
+    rm $latest_folder/51-local.conf
+    substitute \
+      ${pkgs.fontconfig-penultimate}/etc/fonts/conf.d/51-local.conf \
+      $latest_folder/51-local.conf \
+      --replace local.conf /etc/fonts/${latestVersion}/local.conf
+
+    ln -s ${defaultFontsConf} $support_folder/52-default-fonts.conf
+    ln -s ${defaultFontsConf} $latest_folder/52-default-fonts.conf
+
+    ${optionalString cfg.allowBitmaps ''
+    rm $support_folder/53-no-bitmaps.conf
+    rm $latest_folder/53-no-bitmaps.conf
+    ''}
+
+    ${optionalString (!cfg.allowType1) ''
+    ln -s ${rejectType1} $support_folder/53-no-type1.conf
+    ln -s ${rejectType1} $latest_folder/53-no-type1.conf
+    ''}
+  '';
+
+  hintingConf = pkgs.writeText "fc-10-hinting.conf" ''
+    <?xml version='1.0'?>
+    <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+    <fontconfig>
+
+      <!-- Default rendering settings -->
+      <match target="pattern">
+        <edit mode="append" name="hinting">
+          ${fcBool cfg.hinting.enable}
+        </edit>
+        <edit mode="append" name="autohint">
+          ${fcBool cfg.hinting.autohint}
+        </edit>
+        <edit mode="append" name="hintstyle">
+          <const>hintslight</const>
+        </edit>
+      </match>
+
+    </fontconfig>
+  '';
+
+  antialiasConf = pkgs.writeText "fc-10-antialias.conf" ''
+    <?xml version='1.0'?>
+    <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+    <fontconfig>
+
+      <!-- Default rendering settings -->
+      <match target="pattern">
+        <edit mode="append" name="antialias">
+          ${fcBool cfg.antialias}
+        </edit>
+      </match>
+
+    </fontconfig>
+  '';
+
+  subpixelConf = pkgs.writeText "fc-10-subpixel.conf" ''
+    <?xml version='1.0'?>
+    <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+    <fontconfig>
+
+      <!-- Default rendering settings -->
+      <match target="pattern">
+        <edit mode="append" name="rgba">
+          <const>${cfg.subpixel.rgba}</const>
+        </edit>
+        <edit mode="append" name="lcdfilter">
+          <const>lcd${cfg.subpixel.lcdfilter}</const>
+        </edit>
+      </match>
+
+    </fontconfig>
+  '';
+
+  dpiConf = pkgs.writeText "fc-11-dpi.conf" ''
+    <?xml version='1.0'?>
+    <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+    <fontconfig>
+
+      <match target="pattern">
+        <edit name="dpi" mode="assign">
+          <double>${toString cfg.dpi}</double>
+        </edit>
+      </match>
+
+    </fontconfig>
+  '';
+
+  defaultFontsConf =
+    let genDefault = fonts: name:
+      optionalString (fonts != []) ''
+        <alias>
+          <family>${name}</family>
+          <prefer>
+          ${concatStringsSep ""
+          (map (font: ''
+            <family>${font}</family>
+          '') fonts)}
+          </prefer>
+        </alias>
+      '';
+    in
+    pkgs.writeText "fc-52-nixos-default-fonts.conf" ''
+    <?xml version='1.0'?>
+    <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+    <fontconfig>
+
+      <!-- Default fonts -->
+      ${genDefault cfg.defaultFonts.sansSerif "sans-serif"}
+
+      ${genDefault cfg.defaultFonts.serif     "serif"}
+
+      ${genDefault cfg.defaultFonts.monospace "monospace"}
+
+    </fontconfig>
+  '';
+
+  rejectType1 = pkgs.writeText "fc-53-no-type1.conf" ''
+    <?xml version="1.0"?>
+    <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+    <fontconfig>
+
+    <!-- Reject Type 1 fonts -->
+    <selectfont>
+      <rejectfont>
+        <pattern>
+          <patelt name="fontformat"><string>Type 1</string></patelt>
+        </pattern>
+      </rejectfont>
+    </selectfont>
+
+    </fontconfig>
   '';
 
 in
@@ -50,7 +263,7 @@ in
 
   config = mkIf (config.fonts.fontconfig.enable && cfg.enable) {
 
-    fonts.fontconfig.confPackages = [ confPkg ];
+    fonts.fontconfig.confPackages = [ penultimateConf ];
 
   };
 
diff --git a/nixos/modules/config/fonts/fontconfig-ultimate.nix b/nixos/modules/config/fonts/fontconfig-ultimate.nix
index e412146a039..1bf9fdb1984 100644
--- a/nixos/modules/config/fonts/fontconfig-ultimate.nix
+++ b/nixos/modules/config/fonts/fontconfig-ultimate.nix
@@ -63,6 +63,15 @@ in
               <literal>none</literal> disables the substitutions.
             '';
           };
+
+          preset = mkOption {
+            type = types.enum ["ultimate1" "ultimate2" "ultimate3" "ultimate4" "ultimate5" "osx" "windowsxp"];
+            default = "ultimate3";
+            description = ''
+              FreeType rendering settings preset. Any of the presets may be
+              customized by setting environment variables.
+            '';
+          };
         };
       };
     };
@@ -72,6 +81,7 @@ in
   config = mkIf (config.fonts.fontconfig.enable && cfg.enable) {
 
     fonts.fontconfig.confPackages = [ confPkg ];
+    environment.variables."INFINALITY_FT" = cfg.preset;
 
   };
 
diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix
index 4d3cc26365f..12f5ca2e799 100644
--- a/nixos/modules/config/fonts/fontconfig.nix
+++ b/nixos/modules/config/fonts/fontconfig.nix
@@ -20,7 +20,7 @@ with lib;
 
 let cfg = config.fonts.fontconfig;
 
-    fcBool = x: "<bool>" + (if x then "true" else "false") + "</bool>";
+    fcBool = x: "<bool>" + (boolToString x) + "</bool>";
 
     # back-supported fontconfig version and package
     # version is used for font cache generation
@@ -104,13 +104,6 @@ let cfg = config.fonts.fontconfig;
         </match>
         ''}
 
-        <!-- Force autohint always -->
-        <match target="font">
-          <edit name="force_autohint" mode="assign">
-            ${fcBool cfg.forceAutohint}
-          </edit>
-        </match>
-
       </fontconfig>
     '';
 
@@ -174,13 +167,6 @@ let cfg = config.fonts.fontconfig;
         </edit>
       </match>
 
-      <!-- Render some monospace TTF fonts as bitmaps -->
-      <match target="pattern">
-        <edit name="bitmap_monospace" mode="assign">
-          ${fcBool cfg.renderMonoTTFAsBitmap}
-        </edit>
-      </match>
-
       </fontconfig>
     '';
 
@@ -372,11 +358,11 @@ in
 
           autohint = mkOption {
             type = types.bool;
-            default = true;
+            default = false;
             description = ''
-              Enable the autohinter, which provides hinting for otherwise
-              un-hinted fonts. The results are usually lower quality than
-              correctly-hinted fonts.
+              Enable the autohinter in place of the default interpreter.
+              The results are usually lower quality than correctly-hinted
+              fonts, but better than unhinted fonts.
             '';
           };
         };
@@ -453,31 +439,19 @@ in
           description = ''Use embedded bitmaps in fonts like Calibri.'';
         };
 
-        forceAutohint = mkOption {
-          type = types.bool;
-          default = false;
-          description = ''
-            Force use of the TrueType Autohinter. Useful for debugging or
-            free-software purists.
-          '';
-        };
-
-        renderMonoTTFAsBitmap = mkOption {
-          type = types.bool;
-          default = false;
-          description = ''Render some monospace TTF fonts as bitmaps.'';
-        };
-
       };
 
     };
 
   };
-  config = mkIf cfg.enable {
-    fonts.fontconfig.confPackages = [ confPkg ];
-
-    environment.systemPackages    = [ pkgs.fontconfig ];
-    environment.etc.fonts.source  = "${fontconfigEtc}/etc/fonts/";
-  };
+  config = mkMerge [
+    (mkIf cfg.enable {
+      environment.systemPackages    = [ pkgs.fontconfig ];
+      environment.etc.fonts.source  = "${fontconfigEtc}/etc/fonts/";
+    })
+    (mkIf (cfg.enable && !cfg.penultimate.enable) {
+      fonts.fontconfig.confPackages = [ confPkg ];
+    })
+  ];
 
 }
diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix
index af3d93fc1bc..0dd01df9da7 100644
--- a/nixos/modules/config/fonts/fonts.nix
+++ b/nixos/modules/config/fonts/fonts.nix
@@ -37,6 +37,7 @@ with lib;
         pkgs.xorg.fontbhlucidatypewriter75dpi
         pkgs.dejavu_fonts
         pkgs.freefont_ttf
+        pkgs.gyre-fonts # TrueType substitutes for standard PostScript fonts
         pkgs.liberation_ttf
         pkgs.xorg.fontbh100dpi
         pkgs.xorg.fontmiscmisc
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index 8a7b3ea0bfd..152493151fd 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -168,9 +168,6 @@ in
 
          ${cfg.extraInit}
 
-         # The setuid/setcap wrappers override other bin directories.
-         export PATH="${config.security.wrapperDir}:$PATH"
-
          # ~/bin if it exists overrides other bin directories.
          export PATH="$HOME/bin:$PATH"
        '';
diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix
index fb8e1ccab66..bc82bfd066c 100644
--- a/nixos/modules/hardware/all-firmware.nix
+++ b/nixos/modules/hardware/all-firmware.nix
@@ -26,6 +26,7 @@ with lib;
       firmwareLinuxNonfree
       intel2200BGFirmware
       rtl8723bs-firmware
+      rtl8192su-firmware
     ];
   };
 
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index 57bc249360e..e2ae2ee9fdf 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -87,38 +87,6 @@ if ! test -e "$mountPoint"; then
     exit 1
 fi
 
-
-# Mount some stuff in the target root directory.
-mkdir -m 0755 -p $mountPoint/dev $mountPoint/proc $mountPoint/sys $mountPoint/etc $mountPoint/run $mountPoint/home
-mkdir -m 01777 -p $mountPoint/tmp
-mkdir -m 0755 -p $mountPoint/tmp/root
-mkdir -m 0755 -p $mountPoint/var
-mkdir -m 0700 -p $mountPoint/root
-mount --rbind /dev $mountPoint/dev
-mount --rbind /proc $mountPoint/proc
-mount --rbind /sys $mountPoint/sys
-mount --rbind / $mountPoint/tmp/root
-mount -t tmpfs -o "mode=0755" none $mountPoint/run
-rm -rf $mountPoint/var/run
-ln -s /run $mountPoint/var/run
-for f in /etc/resolv.conf /etc/hosts; do rm -f $mountPoint/$f; [ -f "$f" ] && cp -Lf $f $mountPoint/etc/; done
-for f in /etc/passwd /etc/group;      do touch $mountPoint/$f; [ -f "$f" ] && mount --rbind -o ro $f $mountPoint/$f; done
-
-cp -Lf "@cacert@" "$mountPoint/tmp/ca-cert.crt"
-export SSL_CERT_FILE=/tmp/ca-cert.crt
-# For Nix 1.7
-export CURL_CA_BUNDLE=/tmp/ca-cert.crt
-
-if [ -n "$runChroot" ]; then
-    if ! [ -L $mountPoint/nix/var/nix/profiles/system ]; then
-        echo "$0: installation not finished; cannot chroot into installation directory"
-        exit 1
-    fi
-    ln -s /nix/var/nix/profiles/system $mountPoint/run/current-system
-    exec chroot $mountPoint "${chrootCommand[@]}"
-fi
-
-
 # Get the path of the NixOS configuration file.
 if test -z "$NIXOS_CONFIG"; then
     NIXOS_CONFIG=/etc/nixos/configuration.nix
@@ -130,121 +98,60 @@ if [ ! -e "$mountPoint/$NIXOS_CONFIG" ] && [ -z "$closure" ]; then
 fi
 
 
-# Create the necessary Nix directories on the target device, if they
-# don't already exist.
-mkdir -m 0755 -p \
-    $mountPoint/nix/var/nix/gcroots \
-    $mountPoint/nix/var/nix/temproots \
-    $mountPoint/nix/var/nix/userpool \
-    $mountPoint/nix/var/nix/profiles \
-    $mountPoint/nix/var/nix/db \
-    $mountPoint/nix/var/log/nix/drvs
-
-mkdir -m 1775 -p $mountPoint/nix/store
-chown @root_uid@:@nixbld_gid@ $mountPoint/nix/store
-
-
-# There is no daemon in the chroot.
-unset NIX_REMOTE
-
-
-# We don't have locale-archive in the chroot, so clear $LANG.
-export LANG=
-export LC_ALL=
-export LC_TIME=
-
-
 # Builds will use users that are members of this group
 extraBuildFlags+=(--option "build-users-group" "$buildUsersGroup")
 
-
 # Inherit binary caches from the host
+# TODO: will this still work with Nix 1.12 now that it has no perl? Probably not... 
 binary_caches="$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"binary-caches"};')"
 extraBuildFlags+=(--option "binary-caches" "$binary_caches")
 
+nixpkgs="$(readlink -f "$(nix-instantiate --find-file nixpkgs)")"
+export NIX_PATH="nixpkgs=$nixpkgs:nixos-config=$mountPoint/$NIXOS_CONFIG"
+unset NIXOS_CONFIG
 
-# Copy Nix to the Nix store on the target device, unless it's already there.
-if ! NIX_DB_DIR=$mountPoint/nix/var/nix/db nix-store --check-validity @nix@ 2> /dev/null; then
-    echo "copying Nix to $mountPoint...."
-    for i in $(@perl@/bin/perl @pathsFromGraph@ @nixClosure@); do
-        echo "  $i"
-        chattr -R -i $mountPoint/$i 2> /dev/null || true # clear immutable bit
-        @rsync@/bin/rsync -a $i $mountPoint/nix/store/
-    done
-
-    # Register the paths in the Nix closure as valid.  This is necessary
-    # to prevent them from being deleted the first time we install
-    # something.  (I.e., Nix will see that, e.g., the glibc path is not
-    # valid, delete it to get it out of the way, but as a result nothing
-    # will work anymore.)
-    chroot $mountPoint @nix@/bin/nix-store --register-validity < @nixClosure@
-fi
-
-
-# Create the required /bin/sh symlink; otherwise lots of things
-# (notably the system() function) won't work.
-mkdir -m 0755 -p $mountPoint/bin
-# !!! assuming that @shell@ is in the closure
-ln -sf @shell@ $mountPoint/bin/sh
+# TODO: do I need to set NIX_SUBSTITUTERS here or is the --option binary-caches above enough?
 
 
-# Build hooks likely won't function correctly in the minimal chroot; just disable them.
-unset NIX_BUILD_HOOK
+# A place to drop temporary closures
+trap "rm -rf $tmpdir" EXIT
+tmpdir="$(mktemp -d)"
 
-# Make the build below copy paths from the CD if possible.  Note that
-# /tmp/root in the chroot is the root of the CD.
-export NIX_OTHER_STORES=/tmp/root/nix:$NIX_OTHER_STORES
-
-p=@nix@/libexec/nix/substituters
-export NIX_SUBSTITUTERS=$p/copy-from-other-stores.pl:$p/download-from-binary-cache.pl
+# Build a closure (on the host; we then copy it into the guest)
+function closure() {
+    nix-build "${extraBuildFlags[@]}" --no-out-link -E "with import <nixpkgs> {}; runCommand \"closure\" { exportReferencesGraph = [ \"x\" (buildEnv { name = \"env\"; paths = [ ($1) stdenv ]; }) ]; } \"cp x \$out\""
+}
 
+system_closure="$tmpdir/system.closure"
 
 if [ -z "$closure" ]; then
-    # Get the absolute path to the NixOS/Nixpkgs sources.
-    nixpkgs="$(readlink -f $(nix-instantiate --find-file nixpkgs))"
-
-    nixEnvAction="-f <nixpkgs/nixos> --set -A system"
+    expr="(import <nixpkgs/nixos> {}).system"
+    system_root="$(nix-build -E "$expr")"
+    system_closure="$(closure "$expr")"
 else
-    nixpkgs=""
-    nixEnvAction="--set $closure"
+    system_root=$closure
+    # Create a temporary file ending in .closure (so nixos-prepare-root knows to --import it) to transport the store closure
+    # to the filesytem we're preparing. Also delete it on exit!
+    nix-store --export $(nix-store -qR $closure) > $system_closure
 fi
 
-# Build the specified Nix expression in the target store and install
-# it into the system configuration profile.
-echo "building the system configuration..."
-NIX_PATH="nixpkgs=/tmp/root/$nixpkgs:nixos-config=$NIXOS_CONFIG" NIXOS_CONFIG= \
-    chroot $mountPoint @nix@/bin/nix-env \
-    "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/system $nixEnvAction
+channel_root="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")"
+channel_closure="$tmpdir/channel.closure"
+nix-store --export $channel_root > $channel_closure
 
+# Populate the target root directory with the basics
+@prepare_root@/bin/nixos-prepare-root $mountPoint $channel_root $system_root @nixClosure@ $system_closure $channel_closure
 
-# Copy the NixOS/Nixpkgs sources to the target as the initial contents
-# of the NixOS channel.
-mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles
-mkdir -m 1777 -p $mountPoint/nix/var/nix/profiles/per-user
-mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles/per-user/root
-srcs=$(nix-env "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")
-if [ -z "$noChannelCopy" ] && [ -n "$srcs" ]; then
-    echo "copying NixOS/Nixpkgs sources..."
-    chroot $mountPoint @nix@/bin/nix-env \
-        "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -i "$srcs" --quiet
-fi
-mkdir -m 0700 -p $mountPoint/root/.nix-defexpr
-ln -sfn /nix/var/nix/profiles/per-user/root/channels $mountPoint/root/.nix-defexpr/channels
-
-
-# Get rid of the /etc bind mounts.
-for f in /etc/passwd /etc/group; do [ -f "$f" ] && umount $mountPoint/$f; done
+# nixos-prepare-root doesn't currently do anything with file ownership, so we set it up here instead
+chown @root_uid@:@nixbld_gid@ $mountPoint/nix/store
 
+mount --rbind /dev $mountPoint/dev
+mount --rbind /proc $mountPoint/proc
+mount --rbind /sys $mountPoint/sys
 
 # Grub needs an mtab.
 ln -sfn /proc/mounts $mountPoint/etc/mtab
 
-
-# Mark the target as a NixOS installation, otherwise
-# switch-to-configuration will chicken out.
-touch $mountPoint/etc/NIXOS
-
-
 # Switch to the new system configuration.  This will install Grub with
 # a menu default pointing at the kernel/initrd/etc of the new
 # configuration.
diff --git a/nixos/modules/installer/tools/nixos-prepare-root.sh b/nixos/modules/installer/tools/nixos-prepare-root.sh
new file mode 100644
index 00000000000..c374330f846
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-prepare-root.sh
@@ -0,0 +1,105 @@
+#! @shell@
+
+# This script's goal is to perform all "static" setup of a filesystem structure from pre-built store paths. Everything
+# in here should run in a non-root context and inside a Nix builder. It's designed primarily to be called from image-
+# building scripts and from nixos-install, but because it makes very few assumptions about the context in which it runs,
+# it could be useful in other contexts as well.
+#
+# Current behavior:
+#  - set up basic filesystem structure
+#  - make Nix store etc.
+#  - copy Nix, system, channel, and misceallaneous closures to target Nix store
+#  - register validity of all paths in the target store
+#  - set up channel and system profiles
+
+# Ensure a consistent umask.
+umask 0022
+
+set -e
+
+mountPoint="$1"
+channel="$2"
+system="$3"
+shift 3
+closures="$@"
+
+PATH="@coreutils@/bin:@nix@/bin:@perl@/bin:@utillinux@/bin:@rsync@/bin"
+
+if ! test -e "$mountPoint"; then
+    echo "mount point $mountPoint doesn't exist"
+    exit 1
+fi
+
+# Create a few of the standard directories in the target root directory.
+mkdir -m 0755 -p $mountPoint/dev $mountPoint/proc $mountPoint/sys $mountPoint/etc $mountPoint/run $mountPoint/home
+mkdir -m 01777 -p $mountPoint/tmp
+mkdir -m 0755 -p $mountPoint/tmp/root
+mkdir -m 0755 -p $mountPoint/var
+mkdir -m 0700 -p $mountPoint/root
+
+ln -s /run $mountPoint/var/run
+
+# Create the necessary Nix directories on the target device
+mkdir -m 0755 -p \
+    $mountPoint/nix/var/nix/gcroots \
+    $mountPoint/nix/var/nix/temproots \
+    $mountPoint/nix/var/nix/userpool \
+    $mountPoint/nix/var/nix/profiles \
+    $mountPoint/nix/var/nix/db \
+    $mountPoint/nix/var/log/nix/drvs
+
+mkdir -m 1775 -p $mountPoint/nix/store
+
+# All Nix operations below should operate on our target store, not /nix/store.
+# N.B: this relies on Nix 1.12 or higher
+export NIX_REMOTE=local?root=$mountPoint
+
+# Copy our closures to the Nix store on the target mount point, unless they're already there.
+for i in $closures; do
+    # We support closures both in the format produced by `nix-store --export` and by `exportReferencesGraph`,
+    # mostly because there doesn't seem to be a single format that can be produced outside of a nix build and
+    # inside one. See https://github.com/NixOS/nix/issues/1242 for more discussion.
+    if [[ "$i" =~ \.closure$ ]]; then
+        echo "importing serialized closure $i to $mountPoint..."
+        nix-store --import < $i
+    else
+        # There has to be a better way to do this, right?
+        echo "copying closure $i to $mountPoint..."
+        for j in $(perl @pathsFromGraph@ $i); do
+            echo "  $j... "
+            rsync -a $j $mountPoint/nix/store/
+        done
+
+        nix-store --register-validity < $i
+    fi
+done
+
+# Create the required /bin/sh symlink; otherwise lots of things
+# (notably the system() function) won't work.
+if [ ! -x $mountPoint/@shell@ ]; then
+    echo "Error: @shell@ wasn't included in the closure" >&2
+    exit 1
+fi
+mkdir -m 0755 -p $mountPoint/bin
+ln -sf @shell@ $mountPoint/bin/sh
+
+echo "setting the system closure to '$system'..."
+nix-env "${extraBuildFlags[@]}" -p $mountPoint/nix/var/nix/profiles/system --set "$system"
+
+ln -sfn /nix/var/nix/profiles/system $mountPoint/run/current-system
+
+# Copy the NixOS/Nixpkgs sources to the target as the initial contents of the NixOS channel.
+mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles
+mkdir -m 1777 -p $mountPoint/nix/var/nix/profiles/per-user
+mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles/per-user/root
+
+if [ -z "$noChannelCopy" ] && [ -n "$channel" ]; then
+    echo "copying channel..."
+    nix-env --option build-use-substitutes false "${extraBuildFlags[@]}" -p $mountPoint/nix/var/nix/profiles/per-user/root/channels --set "$channel" --quiet
+fi
+mkdir -m 0700 -p $mountPoint/root/.nix-defexpr
+ln -sfn /nix/var/nix/profiles/per-user/root/channels $mountPoint/root/.nix-defexpr/channels
+
+# Mark the target as a NixOS installation, otherwise switch-to-configuration will chicken out.
+touch $mountPoint/etc/NIXOS
+
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index a35f6ad8ae5..a3bae78c0ff 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -4,7 +4,6 @@
 { config, pkgs, modulesPath, ... }:
 
 let
-
   cfg = config.installer;
 
   makeProg = args: pkgs.substituteAll (args // {
@@ -17,6 +16,14 @@ let
     src = ./nixos-build-vms/nixos-build-vms.sh;
   };
 
+  nixos-prepare-root = makeProg {
+    name = "nixos-prepare-root";
+    src = ./nixos-prepare-root.sh;
+
+    nix = pkgs.nixUnstable;
+    inherit (pkgs) perl pathsFromGraph rsync utillinux coreutils;
+  };
+
   nixos-install = makeProg {
     name = "nixos-install";
     src = ./nixos-install.sh;
@@ -26,6 +33,7 @@ let
     cacert = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
     root_uid = config.ids.uids.root;
     nixbld_gid = config.ids.gids.nixbld;
+    prepare_root = nixos-prepare-root;
 
     nixClosure = pkgs.runCommand "closure"
       { exportReferencesGraph = ["refs" config.nix.package.out]; }
@@ -69,6 +77,7 @@ in
 
     environment.systemPackages =
       [ nixos-build-vms
+        nixos-prepare-root
         nixos-install
         nixos-rebuild
         nixos-generate-config
@@ -77,7 +86,7 @@ in
       ];
 
     system.build = {
-      inherit nixos-install nixos-generate-config nixos-option nixos-rebuild;
+      inherit nixos-install nixos-prepare-root nixos-generate-config nixos-option nixos-rebuild;
     };
 
   };
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 0035368273c..52de4b23370 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -89,6 +89,7 @@
   ./programs/nano.nix
   ./programs/oblogout.nix
   ./programs/screen.nix
+  ./programs/slock.nix
   ./programs/shadow.nix
   ./programs/shell.nix
   ./programs/spacefm.nix
@@ -130,6 +131,7 @@
   ./services/audio/liquidsoap.nix
   ./services/audio/mpd.nix
   ./services/audio/mopidy.nix
+  ./services/audio/slimserver.nix
   ./services/audio/squeezelite.nix
   ./services/audio/ympd.nix
   ./services/backup/almir.nix
@@ -247,6 +249,7 @@
   ./services/mail/rmilter.nix
   ./services/misc/apache-kafka.nix
   ./services/misc/autofs.nix
+  ./services/misc/autorandr.nix
   ./services/misc/bepasty.nix
   ./services/misc/canto-daemon.nix
   ./services/misc/calibre-server.nix
@@ -529,6 +532,7 @@
   ./services/system/cgmanager.nix
   ./services/system/cloud-init.nix
   ./services/system/dbus.nix
+  ./services/system/earlyoom.nix
   ./services/system/kerberos.nix
   ./services/system/nscd.nix
   ./services/system/uptimed.nix
@@ -656,6 +660,7 @@
   ./tasks/scsi-link-power-management.nix
   ./tasks/swraid.nix
   ./tasks/trackpoint.nix
+  ./tasks/powertop.nix
   ./testing/service-runner.nix
   ./virtualisation/container-config.nix
   ./virtualisation/containers.nix
diff --git a/nixos/modules/programs/command-not-found/command-not-found.nix b/nixos/modules/programs/command-not-found/command-not-found.nix
index 9741aa7ca53..6fb926fe1d5 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.nix
+++ b/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -8,13 +8,14 @@
 with lib;
 
 let
-
+  cfg = config.programs.command-not-found;
   commandNotFound = pkgs.substituteAll {
     name = "command-not-found";
     dir = "bin";
     src = ./command-not-found.pl;
     isExecutable = true;
     inherit (pkgs) perl;
+    inherit (cfg) dbPath;
     perlFlags = concatStrings (map (path: "-I ${path}/lib/perl5/site_perl ")
       [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite pkgs.perlPackages.StringShellQuote ]);
   };
@@ -22,50 +23,66 @@ let
 in
 
 {
+  options.programs.command-not-found = {
+
+    enable = mkEnableOption "command-not-found hook for interactive shell";
+
+    dbPath = mkOption {
+      default = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite" ;
+      description = ''
+        Absolute path to programs.sqlite.
+
+        By default this file will be provided by your channel
+        (nixexprs.tar.xz).
+      '';
+      type = types.path;
+    };
+  };
 
-  programs.bash.interactiveShellInit =
-    ''
-      # This function is called whenever a command is not found.
-      command_not_found_handle() {
-        local p=/run/current-system/sw/bin/command-not-found
-        if [ -x $p -a -f /nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite ]; then
-          # Run the helper program.
-          $p "$@"
-          # Retry the command if we just installed it.
-          if [ $? = 126 ]; then
-            "$@"
+  config = mkIf cfg.enable {
+    programs.bash.interactiveShellInit =
+      ''
+        # This function is called whenever a command is not found.
+        command_not_found_handle() {
+          local p=${commandNotFound}
+          if [ -x $p -a -f ${cfg.dbPath} ]; then
+            # Run the helper program.
+            $p "$@"
+            # Retry the command if we just installed it.
+            if [ $? = 126 ]; then
+              "$@"
+            else
+              return 127
+            fi
           else
+            echo "$1: command not found" >&2
             return 127
           fi
-        else
-          echo "$1: command not found" >&2
-          return 127
-        fi
-      }
-    '';
+        }
+      '';
 
-  programs.zsh.interactiveShellInit =
-    ''
-      # This function is called whenever a command is not found.
-      command_not_found_handler() {
-        local p=/run/current-system/sw/bin/command-not-found
-        if [ -x $p -a -f /nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite ]; then
-          # Run the helper program.
-          $p "$@"
+    programs.zsh.interactiveShellInit =
+      ''
+        # This function is called whenever a command is not found.
+        command_not_found_handler() {
+          local p=${commandNotFound}
+          if [ -x $p -a -f ${cfg.dbPath} ]; then
+            # Run the helper program.
+            $p "$@"
 
-          # Retry the command if we just installed it.
-          if [ $? = 126 ]; then
-            "$@"
+            # Retry the command if we just installed it.
+            if [ $? = 126 ]; then
+              "$@"
+            fi
+          else
+            # Indicate than there was an error so ZSH falls back to its default handler
+            echo "$1: command not found" >&2
+            return 127
           fi
-        else
-          # Indicate than there was an error so ZSH falls back to its default handler
-          return 127
-        fi
-      }
-    '';
+        }
+      '';
 
-  environment.systemPackages = [ commandNotFound ];
-
-  # TODO: tab completion for uninstalled commands! :-)
+    environment.systemPackages = [ commandNotFound ];
+  };
 
 }
diff --git a/nixos/modules/programs/command-not-found/command-not-found.pl b/nixos/modules/programs/command-not-found/command-not-found.pl
index 5bdda26592e..ab7aa204653 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.pl
+++ b/nixos/modules/programs/command-not-found/command-not-found.pl
@@ -8,7 +8,7 @@ use Config;
 
 my $program = $ARGV[0];
 
-my $dbPath = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite";
+my $dbPath = "@dbPath@";
 
 my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
     or die "cannot open database `$dbPath'";
diff --git a/nixos/modules/programs/slock.nix b/nixos/modules/programs/slock.nix
new file mode 100644
index 00000000000..0e1281e62cd
--- /dev/null
+++ b/nixos/modules/programs/slock.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.slock;
+
+in
+{
+  options = {
+    programs.slock = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to install slock screen locker with setuid wrapper.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.slock ];
+    security.wrappers.slock.source = "${pkgs.slock.out}/bin/slock";
+  };
+}
diff --git a/nixos/modules/programs/ssmtp.nix b/nixos/modules/programs/ssmtp.nix
index 7d0cb332099..44756171b74 100644
--- a/nixos/modules/programs/ssmtp.nix
+++ b/nixos/modules/programs/ssmtp.nix
@@ -39,7 +39,8 @@ in
         example = "mail.example.org";
         description = ''
           The host name of the default mail server to use to deliver
-          e-mail.
+          e-mail. Can also contain a port number (ex: mail.example.org:587),
+          defaults to port 25 if no port is given.
         '';
       };
 
@@ -95,9 +96,28 @@ in
         example = "correctHorseBatteryStaple";
         description = ''
           Password used for SMTP auth. (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)
+
+          It's recommended to use <option>authPassFile</option>
+          which takes precedence over <option>authPass</option>.
+        '';
+      };
+
+      authPassFile = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "/run/keys/ssmtp-authpass";
+        description = ''
+          Path to a file that contains the password used for SMTP auth. The file
+          should not contain a trailing newline, if the password does not contain one.
+          This file should be readable by the users that need to execute ssmtp.
+
+          <option>authPassFile</option> takes precedence over <option>authPass</option>.
+
+          Warning: when <option>authPass</option> is non-empty <option>authPassFile</option>
+          defaults to a file in the WORLD-READABLE Nix store containing that password.
         '';
       };
-      
+
       setSendmail = mkOption {
         type = types.bool;
         default = true;
@@ -111,21 +131,28 @@ in
 
   config = mkIf cfg.directDelivery {
 
+    networking.defaultMailServer.authPassFile = mkIf (cfg.authPass != "")
+      (mkDefault (toString (pkgs.writeTextFile {
+        name = "ssmtp-authpass";
+        text = cfg.authPass;
+      })));
+
     environment.etc."ssmtp/ssmtp.conf".text =
+      let yesNo = yes : if yes then "YES" else "NO"; in
       ''
         MailHub=${cfg.hostName}
         FromLineOverride=YES
-        ${if cfg.root != "" then "root=${cfg.root}" else ""}
-        ${if cfg.domain != "" then "rewriteDomain=${cfg.domain}" else ""}
-        UseTLS=${if cfg.useTLS then "YES" else "NO"}
-        UseSTARTTLS=${if cfg.useSTARTTLS then "YES" else "NO"}
+        ${optionalString (cfg.root   != "") "root=${cfg.root}"}
+        ${optionalString (cfg.domain != "") "rewriteDomain=${cfg.domain}"}
+        UseTLS=${yesNo cfg.useTLS}
+        UseSTARTTLS=${yesNo cfg.useSTARTTLS}
         #Debug=YES
-        ${if cfg.authUser != "" then "AuthUser=${cfg.authUser}" else ""}
-        ${if cfg.authPass != "" then "AuthPass=${cfg.authPass}" else ""}
+        ${optionalString (cfg.authUser != "")       "AuthUser=${cfg.authUser}"}
+        ${optionalString (!isNull cfg.authPassFile) "AuthPassFile=${cfg.authPassFile}"}
       '';
 
     environment.systemPackages = [pkgs.ssmtp];
-    
+
     services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail {
       program = "sendmail";
       source = "${pkgs.ssmtp}/bin/sendmail";
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 54433e20597..0174fe544e3 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -202,5 +202,7 @@ with lib;
     (mkRemovedOptionModule [ "fonts" "fontconfig" "hinting" "style" ] "")
     (mkRemovedOptionModule [ "services" "xserver" "displayManager" "sddm" "themes" ]
       "Set the option `services.xserver.displayManager.sddm.package' instead.")
+    (mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
+    (mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
   ];
 }
diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index ada198e0e58..5301ac14805 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -19,6 +19,12 @@ let
         '';
       };
 
+      domain = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "Domain to fetch certificate for (defaults to the entry name)";
+      };
+
       email = mkOption {
         type = types.nullOr types.str;
         default = null;
@@ -157,9 +163,10 @@ in
           servicesLists = mapAttrsToList certToServices cfg.certs;
           certToServices = cert: data:
               let
+                domain = if data.domain != null then data.domain else cert;
                 cpath = "${cfg.directory}/${cert}";
                 rights = if data.allowKeysForGroup then "750" else "700";
-                cmdline = [ "-v" "-d" cert "--default_root" data.webroot "--valid_min" cfg.validMin ]
+                cmdline = [ "-v" "-d" domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
                           ++ optionals (data.email != null) [ "--email" data.email ]
                           ++ concatMap (p: [ "-f" p ]) data.plugins
                           ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains);
diff --git a/nixos/modules/security/polkit.nix b/nixos/modules/security/polkit.nix
index 8d9d5348063..7e59408a5b0 100644
--- a/nixos/modules/security/polkit.nix
+++ b/nixos/modules/security/polkit.nix
@@ -64,7 +64,7 @@ in
     systemd.packages = [ pkgs.polkit.out ];
 
     systemd.services.polkit.restartTriggers = [ config.system.path ];
-    systemd.services.polkit.unitConfig.X-StopIfChanged = false;
+    systemd.services.polkit.stopIfChanged = false;
 
     # The polkit daemon reads action/rule files
     environment.pathsToLink = [ "/share/polkit-1" ];
diff --git a/nixos/modules/services/audio/slimserver.nix b/nixos/modules/services/audio/slimserver.nix
new file mode 100644
index 00000000000..7d661dd6040
--- /dev/null
+++ b/nixos/modules/services/audio/slimserver.nix
@@ -0,0 +1,69 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.slimserver;
+
+in {
+  options = {
+
+    services.slimserver = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable slimserver.
+        '';
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.slimserver;
+        defaultText = "pkgs.slimserver";
+        description = "Slimserver package to use.";
+      };
+
+      dataDir = mkOption {
+        type = types.path;
+        default = "/var/lib/slimserver";
+        description = ''
+          The directory where slimserver stores its state, tag cache,
+          playlists etc.
+        '';
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.slimserver = {
+      after = [ "network.target" ];
+      description = "Slim Server for Logitech Squeezebox Players";
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = "mkdir -p ${cfg.dataDir} && chown -R slimserver:slimserver ${cfg.dataDir}";
+      serviceConfig = {
+        User = "slimserver";
+        PermissionsStartOnly = true;
+        ExecStart = "${cfg.package}/slimserver.pl --logdir ${cfg.dataDir}/logs --prefsdir ${cfg.dataDir}/prefs --cachedir ${cfg.dataDir}/cache";
+      };
+    };
+
+    users = {
+      users.slimserver = {
+        description = "Slimserver daemon user";
+        home = cfg.dataDir;
+        group = "slimserver";
+      };
+      groups.slimserver = {};
+    };
+  };
+
+}
+
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index 9ccc7295019..f58306ab63e 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -45,7 +45,7 @@ let
   cniConfig = pkgs.buildEnv {
     name = "kubernetes-cni-config";
     paths = imap (i: entry:
-      pkgs.writeTextDir "${10+i}-${entry.type}.conf" (builtins.toJSON entry)
+      pkgs.writeTextDir "${toString (10+i)}-${entry.type}.conf" (builtins.toJSON entry)
     ) cfg.kubelet.cni.config;
   };
 
@@ -597,7 +597,7 @@ in {
     (mkIf cfg.kubelet.enable {
       systemd.services.kubelet = {
         description = "Kubernetes Kubelet Service";
-        wantedBy = [ "multi-user.target" ];
+        wantedBy = [ "kubernetes.target" ];
         after = [ "network.target" "docker.service" "kube-apiserver.service" ];
         path = with pkgs; [ gitMinimal openssh docker utillinux iproute ethtool thin-provisioning-tools iptables ];
         preStart = ''
@@ -606,14 +606,15 @@ in {
           ${concatMapStringsSep "\n" (p: "ln -fs ${p.plugins}/* /opt/cni/bin") cfg.kubelet.cni.packages}
         '';
         serviceConfig = {
+          Slice = "kubernetes.slice";
           ExecStart = ''${cfg.package}/bin/kubelet \
             --pod-manifest-path=${manifests} \
             --kubeconfig=${kubeconfig} \
             --require-kubeconfig \
             --address=${cfg.kubelet.address} \
             --port=${toString cfg.kubelet.port} \
-            --register-node=${if cfg.kubelet.registerNode then "true" else "false"} \
-            --register-schedulable=${if cfg.kubelet.registerSchedulable then "true" else "false"} \
+            --register-node=${boolToString cfg.kubelet.registerNode} \
+            --register-schedulable=${boolToString cfg.kubelet.registerSchedulable} \
             ${optionalString (cfg.kubelet.tlsCertFile != null)
               "--tls-cert-file=${cfg.kubelet.tlsCertFile}"} \
             ${optionalString (cfg.kubelet.tlsKeyFile != null)
@@ -621,7 +622,7 @@ in {
             --healthz-bind-address=${cfg.kubelet.healthz.bind} \
             --healthz-port=${toString cfg.kubelet.healthz.port} \
             --hostname-override=${cfg.kubelet.hostname} \
-            --allow-privileged=${if cfg.kubelet.allowPrivileged then "true" else "false"} \
+            --allow-privileged=${boolToString cfg.kubelet.allowPrivileged} \
             --root-dir=${cfg.dataDir} \
             --cadvisor_port=${toString cfg.kubelet.cadvisorPort} \
             ${optionalString (cfg.kubelet.clusterDns != "")
@@ -655,9 +656,10 @@ in {
     (mkIf cfg.apiserver.enable {
       systemd.services.kube-apiserver = {
         description = "Kubernetes Kubelet Service";
-        wantedBy = [ "multi-user.target" ];
+        wantedBy = [ "kubernetes.target" ];
         after = [ "network.target" "docker.service" ];
         serviceConfig = {
+          Slice = "kubernetes.slice";
           ExecStart = ''${cfg.package}/bin/kube-apiserver \
             --etcd-servers=${concatStringsSep "," cfg.etcd.servers} \
             ${optionalString (cfg.etcd.caFile != null)
@@ -670,14 +672,14 @@ in {
             --bind-address=0.0.0.0 \
             ${optionalString (cfg.apiserver.advertiseAddress != null)
               "--advertise-address=${cfg.apiserver.advertiseAddress}"} \
-            --allow-privileged=${if cfg.apiserver.allowPrivileged then "true" else "false"} \
+            --allow-privileged=${boolToString cfg.apiserver.allowPrivileged}\
             ${optionalString (cfg.apiserver.tlsCertFile != null)
               "--tls-cert-file=${cfg.apiserver.tlsCertFile}"} \
             ${optionalString (cfg.apiserver.tlsKeyFile != null)
               "--tls-private-key-file=${cfg.apiserver.tlsKeyFile}"} \
             ${optionalString (cfg.apiserver.tokenAuth != null)
               "--token-auth-file=${cfg.apiserver.tokenAuth}"} \
-            --kubelet-https=${if cfg.apiserver.kubeletHttps then "true" else "false"} \
+            --kubelet-https=${boolToString cfg.apiserver.kubeletHttps} \
             ${optionalString (cfg.apiserver.kubeletClientCaFile != null)
               "--kubelet-certificate-authority=${cfg.apiserver.kubeletClientCaFile}"} \
             ${optionalString (cfg.apiserver.kubeletClientCertFile != null)
@@ -713,13 +715,14 @@ in {
     (mkIf cfg.scheduler.enable {
       systemd.services.kube-scheduler = {
         description = "Kubernetes Scheduler Service";
-        wantedBy = [ "multi-user.target" ];
+        wantedBy = [ "kubernetes.target" ];
         after = [ "kube-apiserver.service" ];
         serviceConfig = {
+          Slice = "kubernetes.slice";
           ExecStart = ''${cfg.package}/bin/kube-scheduler \
             --address=${cfg.scheduler.address} \
             --port=${toString cfg.scheduler.port} \
-            --leader-elect=${if cfg.scheduler.leaderElect then "true" else "false"} \
+            --leader-elect=${boolToString cfg.scheduler.leaderElect} \
             --kubeconfig=${kubeconfig} \
             ${optionalString cfg.verbose "--v=6"} \
             ${optionalString cfg.verbose "--log-flush-frequency=1s"} \
@@ -735,16 +738,17 @@ in {
     (mkIf cfg.controllerManager.enable {
       systemd.services.kube-controller-manager = {
         description = "Kubernetes Controller Manager Service";
-        wantedBy = [ "multi-user.target" ];
+        wantedBy = [ "kubernetes.target" ];
         after = [ "kube-apiserver.service" ];
         serviceConfig = {
           RestartSec = "30s";
           Restart = "on-failure";
+          Slice = "kubernetes.slice";
           ExecStart = ''${cfg.package}/bin/kube-controller-manager \
             --address=${cfg.controllerManager.address} \
             --port=${toString cfg.controllerManager.port} \
             --kubeconfig=${kubeconfig} \
-            --leader-elect=${if cfg.controllerManager.leaderElect then "true" else "false"} \
+            --leader-elect=${boolToString cfg.controllerManager.leaderElect} \
             ${if (cfg.controllerManager.serviceAccountKeyFile!=null)
               then "--service-account-private-key-file=${cfg.controllerManager.serviceAccountKeyFile}"
               else "--service-account-private-key-file=/var/run/kubernetes/apiserver.key"} \
@@ -767,10 +771,11 @@ in {
     (mkIf cfg.proxy.enable {
       systemd.services.kube-proxy = {
         description = "Kubernetes Proxy Service";
-        wantedBy = [ "multi-user.target" ];
+        wantedBy = [ "kubernetes.target" ];
         after = [ "kube-apiserver.service" ];
         path = [pkgs.iptables];
         serviceConfig = {
+          Slice = "kubernetes.slice";
           ExecStart = ''${cfg.package}/bin/kube-proxy \
             --kubeconfig=${kubeconfig} \
             --bind-address=${cfg.proxy.address} \
@@ -786,9 +791,10 @@ in {
     (mkIf cfg.dns.enable {
       systemd.services.kube-dns = {
         description = "Kubernetes Dns Service";
-        wantedBy = [ "multi-user.target" ];
+        wantedBy = [ "kubernetes.target" ];
         after = [ "kube-apiserver.service" ];
         serviceConfig = {
+          Slice = "kubernetes.slice";
           ExecStart = ''${cfg.package}/bin/kube-dns \
             --kubecfg-file=${kubeconfig} \
             --dns-port=${toString cfg.dns.port} \
@@ -836,6 +842,11 @@ in {
         cfg.proxy.enable ||
         cfg.dns.enable
     ) {
+      systemd.targets.kubernetes = {
+        description = "Kubernetes";
+        wantedBy = [ "multi-user.target" ];
+      };
+
       systemd.tmpfiles.rules = [
         "d /opt/cni/bin 0755 root root -"
         "d /var/run/kubernetes 0755 kubernetes kubernetes -"
diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix
index fa550f68b33..57f592a2e55 100644
--- a/nixos/modules/services/continuous-integration/hydra/default.nix
+++ b/nixos/modules/services/continuous-integration/hydra/default.nix
@@ -328,7 +328,7 @@ in
           IN_SYSTEMD = "1"; # to get log severity levels
         };
         serviceConfig =
-          { ExecStart = "@${cfg.package}/bin/hydra-queue-runner hydra-queue-runner -v --option build-use-substitutes ${if cfg.useSubstitutes then "true" else "false"}";
+          { ExecStart = "@${cfg.package}/bin/hydra-queue-runner hydra-queue-runner -v --option build-use-substitutes ${boolToString cfg.useSubstitutes}";
             ExecStopPost = "${cfg.package}/bin/hydra-queue-runner --unlock";
             User = "hydra-queue-runner";
             Restart = "always";
diff --git a/nixos/modules/services/databases/cassandra.nix b/nixos/modules/services/databases/cassandra.nix
index 5df4ae57f80..1e5cd8f5413 100644
--- a/nixos/modules/services/databases/cassandra.nix
+++ b/nixos/modules/services/databases/cassandra.nix
@@ -21,8 +21,8 @@ let
   cassandraConf = ''
     cluster_name: ${cfg.clusterName}
     num_tokens: 256
-    auto_bootstrap: ${if cfg.autoBootstrap then "true" else "false"}
-    hinted_handoff_enabled: ${if cfg.hintedHandOff then "true" else "false"}
+    auto_bootstrap: ${boolToString cfg.autoBootstrap}
+    hinted_handoff_enabled: ${boolToString cfg.hintedHandOff}
     hinted_handoff_throttle_in_kb: ${builtins.toString cfg.hintedHandOffThrottle}
     max_hints_delivery_threads: 2
     max_hint_window_in_ms: 10800000 # 3 hours
@@ -62,7 +62,7 @@ let
     rpc_keepalive: true
     rpc_server_type: sync
     thrift_framed_transport_size_in_mb: 15
-    incremental_backups: ${if cfg.incrementalBackups then "true" else "false"}
+    incremental_backups: ${boolToString cfg.incrementalBackups}
     snapshot_before_compaction: false
     auto_snapshot: true
     column_index_size_in_kb: 64
@@ -89,7 +89,7 @@ let
       truststore: ${cfg.trustStorePath}
       truststore_password: ${cfg.trustStorePassword}
     client_encryption_options:
-      enabled: ${if cfg.clientEncryption then "true" else "false"}
+      enabled: ${boolToString cfg.clientEncryption}
       keystore: ${cfg.keyStorePath}
       keystore_password: ${cfg.keyStorePassword}
     internode_compression: all
diff --git a/nixos/modules/services/databases/mongodb.nix b/nixos/modules/services/databases/mongodb.nix
index 38e46a0c6ef..c56564f57f3 100644
--- a/nixos/modules/services/databases/mongodb.nix
+++ b/nixos/modules/services/databases/mongodb.nix
@@ -4,8 +4,6 @@ with lib;
 
 let
 
-  b2s = x: if x then "true" else "false";
-
   cfg = config.services.mongodb;
 
   mongodb = cfg.package;
diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix
index f1fcb436934..4a8cd86b0b1 100644
--- a/nixos/modules/services/hardware/bluetooth.nix
+++ b/nixos/modules/services/hardware/bluetooth.nix
@@ -6,9 +6,7 @@ let
   bluez-bluetooth = pkgs.bluez;
   cfg = config.hardware.bluetooth;
 
-in
-
-{
+in {
 
   ###### interface
 
@@ -32,6 +30,8 @@ in
         '';
         description = ''
           Set additional configuration for system-wide bluetooth (/etc/bluetooth/main.conf).
+
+          NOTE: We already include [Policy], so any configuration under the Policy group should come first.
         '';
       };
     };
@@ -45,7 +45,12 @@ in
     environment.systemPackages = [ bluez-bluetooth pkgs.openobex pkgs.obexftp ];
 
     environment.etc = singleton {
-      source = pkgs.writeText "main.conf" cfg.extraConfig;
+      source = pkgs.writeText "main.conf" ''
+        [Policy]
+        AutoEnable=${lib.boolToString cfg.powerOnBoot}
+
+        ${cfg.extraConfig}
+      '';
       target = "bluetooth/main.conf";
     };
 
@@ -53,29 +58,11 @@ in
     services.dbus.packages = [ bluez-bluetooth ];
     systemd.packages       = [ bluez-bluetooth ];
 
-    services.udev.extraRules = optionalString cfg.powerOnBoot ''
-      ACTION=="add", KERNEL=="hci[0-9]*", ENV{SYSTEMD_WANTS}="bluetooth-power@%k.service"
-    '';
-
     systemd.services = {
       bluetooth = {
         wantedBy = [ "bluetooth.target" ];
         aliases  = [ "dbus-org.bluez.service" ];
       };
-
-      "bluetooth-power@" = mkIf cfg.powerOnBoot {
-        description = "Power up bluetooth controller";
-        after = [
-          "bluetooth.service"
-          "suspend.target"
-          "sys-subsystem-bluetooth-devices-%i.device"
-        ];
-        wantedBy = [ "suspend.target" ];
-
-        serviceConfig.Type      = "oneshot";
-        serviceConfig.ExecStart = "${pkgs.bluez.out}/bin/hciconfig %i up";
-      };
-
     };
 
     systemd.user.services = {
diff --git a/nixos/modules/services/hardware/tlp.nix b/nixos/modules/services/hardware/tlp.nix
index f36a9e7b459..3b108c87edd 100644
--- a/nixos/modules/services/hardware/tlp.nix
+++ b/nixos/modules/services/hardware/tlp.nix
@@ -58,6 +58,9 @@ in
     powerManagement.cpuFreqGovernor = null;
 
     systemd.services = {
+      "systemd-rfkill@".enable = false;
+      "systemd-rfkill".enable = false;
+
       tlp = {
         description = "TLP system startup/shutdown";
 
diff --git a/nixos/modules/services/logging/graylog.nix b/nixos/modules/services/logging/graylog.nix
index 95283096662..9f0fb11f025 100644
--- a/nixos/modules/services/logging/graylog.nix
+++ b/nixos/modules/services/logging/graylog.nix
@@ -4,16 +4,15 @@ with lib;
 
 let
   cfg = config.services.graylog;
-  configBool = b: if b then "true" else "false";
 
   confFile = pkgs.writeText "graylog.conf" ''
-    is_master = ${configBool cfg.isMaster}
+    is_master = ${boolToString cfg.isMaster}
     node_id_file = ${cfg.nodeIdFile}
     password_secret = ${cfg.passwordSecret}
     root_username = ${cfg.rootUsername}
     root_password_sha2 = ${cfg.rootPasswordSha2}
     elasticsearch_cluster_name = ${cfg.elasticsearchClusterName}
-    elasticsearch_discovery_zen_ping_multicast_enabled = ${configBool cfg.elasticsearchDiscoveryZenPingMulticastEnabled}
+    elasticsearch_discovery_zen_ping_multicast_enabled = ${boolToString cfg.elasticsearchDiscoveryZenPingMulticastEnabled}
     elasticsearch_discovery_zen_ping_unicast_hosts = ${cfg.elasticsearchDiscoveryZenPingUnicastHosts}
     message_journal_dir = ${cfg.messageJournalDir}
     mongodb_uri = ${cfg.mongodbUri}
diff --git a/nixos/modules/services/misc/autorandr.nix b/nixos/modules/services/misc/autorandr.nix
new file mode 100644
index 00000000000..6746f3fec69
--- /dev/null
+++ b/nixos/modules/services/misc/autorandr.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.autorandr;
+
+in {
+
+  options = {
+
+    services.autorandr = {
+      enable = mkEnableOption "handling of hotplug and sleep events by autorandr";
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    services.udev.packages = [ pkgs.autorandr ];
+
+    environment.systemPackages = [ pkgs.autorandr ];
+
+    # systemd.unitPackages = [ pkgs.autorandr ];
+    systemd.services.autorandr = {
+      unitConfig = {
+        Description = "autorandr execution hook";
+        After = [ "sleep.target" ];
+        StartLimitInterval = "5";
+        StartLimitBurst = "1";
+      };
+      serviceConfig = {
+        ExecStart = "${pkgs.autorandr}/bin/autorandr --batch --change --default default";
+        Type = "oneshot";
+        RemainAfterExit = false;
+      };
+      wantedBy = [ "sleep.target" ];
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/cgminer.nix b/nixos/modules/services/misc/cgminer.nix
index 5f97cc03414..d5071d8ff76 100644
--- a/nixos/modules/services/misc/cgminer.nix
+++ b/nixos/modules/services/misc/cgminer.nix
@@ -6,7 +6,7 @@ let
   cfg = config.services.cgminer;
 
   convType = with builtins;
-    v: if isBool v then (if v then "true" else "false") else toString v;
+    v: if isBool v then boolToString v else toString v;
   mergedHwConfig =
     mapAttrsToList (n: v: ''"${n}": "${(concatStringsSep "," (map convType v))}"'')
       (foldAttrs (n: a: [n] ++ a) [] cfg.hardware);
diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix
index fe13013286b..8e9bec15dd4 100755
--- a/nixos/modules/services/misc/confd.nix
+++ b/nixos/modules/services/misc/confd.nix
@@ -12,7 +12,7 @@ let
     nodes = [ ${concatMapStringsSep "," (s: ''"${s}"'') cfg.nodes}, ]
     prefix = "${cfg.prefix}"
     log-level = "${cfg.logLevel}"
-    watch = ${if cfg.watch then "true" else "false"}
+    watch = ${boolToString cfg.watch}
   '';
 
 in {
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index 1de02d76ba0..7c91462883f 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -119,7 +119,7 @@ in {
     extraConf = mkOption {
       description = ''
         Etcd extra configuration. See
-        <link xlink:href='https://github.com/coreos/etcd/blob/master/Documentation/configuration.md#environment-variables' />
+        <link xlink:href='https://github.com/coreos/etcd/blob/master/Documentation/op-guide/configuration.md#configuration-flags' />
       '';
       type = types.attrsOf types.str;
       default = {};
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index 4a1bea50c14..ae9826968b1 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -5,9 +5,8 @@ with lib;
 let
   cfg = config.services.matrix-synapse;
   logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
-  mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${fromBool r.compress}}'';
-  mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${fromBool l.tls}, x_forwarded: ${fromBool l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
-  fromBool = x: if x then "true" else "false";
+  mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
+  mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${boolToString l.tls}, x_forwarded: ${boolToString l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
   configFile = pkgs.writeText "homeserver.yaml" ''
 ${optionalString (cfg.tls_certificate_path != null) ''
 tls_certificate_path: "${cfg.tls_certificate_path}"
@@ -18,7 +17,7 @@ tls_private_key_path: "${cfg.tls_private_key_path}"
 ${optionalString (cfg.tls_dh_params_path != null) ''
 tls_dh_params_path: "${cfg.tls_dh_params_path}"
 ''}
-no_tls: ${fromBool cfg.no_tls}
+no_tls: ${boolToString cfg.no_tls}
 ${optionalString (cfg.bind_port != null) ''
 bind_port: ${toString cfg.bind_port}
 ''}
@@ -30,7 +29,7 @@ bind_host: "${cfg.bind_host}"
 ''}
 server_name: "${cfg.server_name}"
 pid_file: "/var/run/matrix-synapse.pid"
-web_client: ${fromBool cfg.web_client}
+web_client: ${boolToString cfg.web_client}
 ${optionalString (cfg.public_baseurl != null) ''
 public_baseurl: "${cfg.public_baseurl}"
 ''}
@@ -58,8 +57,8 @@ media_store_path: "/var/lib/matrix-synapse/media"
 uploads_path: "/var/lib/matrix-synapse/uploads"
 max_upload_size: "${cfg.max_upload_size}"
 max_image_pixels: "${cfg.max_image_pixels}"
-dynamic_thumbnails: ${fromBool cfg.dynamic_thumbnails}
-url_preview_enabled: ${fromBool cfg.url_preview_enabled}
+dynamic_thumbnails: ${boolToString cfg.dynamic_thumbnails}
+url_preview_enabled: ${boolToString cfg.url_preview_enabled}
 ${optionalString (cfg.url_preview_enabled == true) ''
 url_preview_ip_range_blacklist: ${builtins.toJSON cfg.url_preview_ip_range_blacklist}
 url_preview_ip_range_whitelist: ${builtins.toJSON cfg.url_preview_ip_range_whitelist}
@@ -67,10 +66,10 @@ url_preview_url_blacklist: ${builtins.toJSON cfg.url_preview_url_blacklist}
 ''}
 recaptcha_private_key: "${cfg.recaptcha_private_key}"
 recaptcha_public_key: "${cfg.recaptcha_public_key}"
-enable_registration_captcha: ${fromBool cfg.enable_registration_captcha}
+enable_registration_captcha: ${boolToString cfg.enable_registration_captcha}
 turn_uris: ${builtins.toJSON cfg.turn_uris}
 turn_shared_secret: "${cfg.turn_shared_secret}"
-enable_registration: ${fromBool cfg.enable_registration}
+enable_registration: ${boolToString cfg.enable_registration}
 ${optionalString (cfg.registration_shared_secret != null) ''
 registration_shared_secret: "${cfg.registration_shared_secret}"
 ''}
@@ -78,15 +77,15 @@ recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
 turn_user_lifetime: "${cfg.turn_user_lifetime}"
 user_creation_max_duration: ${cfg.user_creation_max_duration}
 bcrypt_rounds: ${cfg.bcrypt_rounds}
-allow_guest_access: ${fromBool cfg.allow_guest_access}
+allow_guest_access: ${boolToString cfg.allow_guest_access}
 trusted_third_party_id_servers: ${builtins.toJSON cfg.trusted_third_party_id_servers}
 room_invite_state_types: ${builtins.toJSON cfg.room_invite_state_types}
 ${optionalString (cfg.macaroon_secret_key != null) ''
   macaroon_secret_key: "${cfg.macaroon_secret_key}"
 ''}
-expire_access_token: ${fromBool cfg.expire_access_token}
-enable_metrics: ${fromBool cfg.enable_metrics}
-report_stats: ${fromBool cfg.report_stats}
+expire_access_token: ${boolToString cfg.expire_access_token}
+enable_metrics: ${boolToString cfg.enable_metrics}
+report_stats: ${boolToString cfg.report_stats}
 signing_key_path: "/var/lib/matrix-synapse/homeserver.signing.key"
 key_refresh_interval: "${cfg.key_refresh_interval}"
 perspectives:
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 4fe89838e29..bf1304ee7ac 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -41,12 +41,12 @@ let
         build-users-group = nixbld
         build-max-jobs = ${toString (cfg.maxJobs)}
         build-cores = ${toString (cfg.buildCores)}
-        build-use-sandbox = ${if (builtins.isBool cfg.useSandbox) then (if cfg.useSandbox then "true" else "false") else cfg.useSandbox}
+        build-use-sandbox = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox}
         build-sandbox-paths = ${toString cfg.sandboxPaths} /bin/sh=${sh} $(echo $extraPaths)
         binary-caches = ${toString cfg.binaryCaches}
         trusted-binary-caches = ${toString cfg.trustedBinaryCaches}
         binary-cache-public-keys = ${toString cfg.binaryCachePublicKeys}
-        auto-optimise-store = ${if cfg.autoOptimiseStore then "true" else "false"}
+        auto-optimise-store = ${boolToString cfg.autoOptimiseStore}
         ${optionalString cfg.requireSignedBinaryCaches ''
           signed-binary-caches = *
         ''}
diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix
index f6bf2dee986..9c0bea8d3bf 100644
--- a/nixos/modules/services/misc/plex.nix
+++ b/nixos/modules/services/misc/plex.nix
@@ -93,7 +93,9 @@ in
         # why this is done.
         test -d "${cfg.dataDir}/.skeleton" || mkdir "${cfg.dataDir}/.skeleton"
         for db in "com.plexapp.plugins.library.db"; do
-            cp "${cfg.package}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db"
+            if [ ! -e  "${cfg.dataDir}/.skeleton/$db" ]; then
+              cp "${cfg.package}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db"
+            fi
             chmod u+w "${cfg.dataDir}/.skeleton/$db"
             chown ${cfg.user}:${cfg.group} "${cfg.dataDir}/.skeleton/$db"
         done
@@ -136,6 +138,7 @@ in
         Group = cfg.group;
         PermissionsStartOnly = "true";
         ExecStart = "/bin/sh -c ${cfg.package}/usr/lib/plexmediaserver/Plex\\ Media\\ Server";
+        KillSignal = "SIGQUIT";
         Restart = "on-failure";
       };
       environment = {
diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix
index ba9f52f1904..ab9a6ce32f4 100644
--- a/nixos/modules/services/misc/taskserver/default.nix
+++ b/nixos/modules/services/misc/taskserver/default.nix
@@ -128,7 +128,7 @@ let
         certBits = cfg.pki.auto.bits;
         clientExpiration = cfg.pki.auto.expiration.client;
         crlExpiration = cfg.pki.auto.expiration.crl;
-        isAutoConfig = if needToCreateCA then "True" else "False";
+        isAutoConfig = boolToString needToCreateCA;
       }}" > "$out/main.py"
       cat > "$out/setup.py" <<EOF
       from setuptools import setup
diff --git a/nixos/modules/services/monitoring/collectd.nix b/nixos/modules/services/monitoring/collectd.nix
index 641da60e9ad..79a8a1ff5ae 100644
--- a/nixos/modules/services/monitoring/collectd.nix
+++ b/nixos/modules/services/monitoring/collectd.nix
@@ -8,7 +8,7 @@ let
   conf = pkgs.writeText "collectd.conf" ''
     BaseDir "${cfg.dataDir}"
     PIDFile "${cfg.pidFile}"
-    AutoLoadPlugin ${if cfg.autoLoadPlugin then "true" else "false"}
+    AutoLoadPlugin ${boolToString cfg.autoLoadPlugin}
     Hostname "${config.networking.hostName}"
 
     LoadPlugin syslog
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index 97806d5d83e..4fbacef788f 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -5,8 +5,6 @@ with lib;
 let
   cfg = config.services.grafana;
 
-  b2s = val: if val then "true" else "false";
-
   envOptions = {
     PATHS_DATA = cfg.dataDir;
     PATHS_PLUGINS = "${cfg.dataDir}/plugins";
@@ -32,16 +30,16 @@ let
     SECURITY_ADMIN_PASSWORD = cfg.security.adminPassword;
     SECURITY_SECRET_KEY = cfg.security.secretKey;
 
-    USERS_ALLOW_SIGN_UP = b2s cfg.users.allowSignUp;
-    USERS_ALLOW_ORG_CREATE = b2s cfg.users.allowOrgCreate;
-    USERS_AUTO_ASSIGN_ORG = b2s cfg.users.autoAssignOrg;
+    USERS_ALLOW_SIGN_UP = boolToString cfg.users.allowSignUp;
+    USERS_ALLOW_ORG_CREATE = boolToString cfg.users.allowOrgCreate;
+    USERS_AUTO_ASSIGN_ORG = boolToString cfg.users.autoAssignOrg;
     USERS_AUTO_ASSIGN_ORG_ROLE = cfg.users.autoAssignOrgRole;
 
-    AUTH_ANONYMOUS_ENABLED = b2s cfg.auth.anonymous.enable;
+    AUTH_ANONYMOUS_ENABLED = boolToString cfg.auth.anonymous.enable;
     AUTH_ANONYMOUS_ORG_NAME = cfg.auth.anonymous.org_name;
     AUTH_ANONYMOUS_ORG_ROLE = cfg.auth.anonymous.org_role;
 
-    ANALYTICS_REPORTING_ENABLED = b2s cfg.analytics.reporting.enable;
+    ANALYTICS_REPORTING_ENABLED = boolToString cfg.analytics.reporting.enable;
   } // cfg.extraOptions;
 
 in {
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index c5352e5887d..98931e65bb5 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -4,7 +4,7 @@ with lib;
 
 let
   cfg = config.services.graphite;
-  writeTextOrNull = f: t: if t == null then null else pkgs.writeTextDir f t;
+  writeTextOrNull = f: t: mapNullable (pkgs.writeTextDir f) t;
 
   dataDir = cfg.dataDir;
 
diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix
index cf9deccbffe..b9435c02b1d 100644
--- a/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixos/modules/services/monitoring/prometheus/default.nix
@@ -116,6 +116,13 @@ let
           The URL scheme with which to fetch metrics from targets.
         '';
       };
+      params = mkOption {
+        type = types.attrsOf (types.listOf types.str);
+        default = {};
+        description = ''
+          Optional HTTP URL parameters.
+        '';
+      };
       basic_auth = mkOption {
         type = types.nullOr (types.submodule {
           options = {
@@ -134,7 +141,7 @@ let
           };
         });
         default = null;
-        apply = x: if x == null then null else _filter x;
+        apply = x: mapNullable _filter x;
         description = ''
           Optional http login credentials for metrics scraping.
         '';
diff --git a/nixos/modules/services/network-filesystems/netatalk.nix b/nixos/modules/services/network-filesystems/netatalk.nix
index bff54406a2b..1dd869043f0 100644
--- a/nixos/modules/services/network-filesystems/netatalk.nix
+++ b/nixos/modules/services/network-filesystems/netatalk.nix
@@ -9,7 +9,7 @@ let
   extmapFile = pkgs.writeText "extmap.conf" cfg.extmap;
 
   afpToString = x: if builtins.typeOf x == "bool"
-                   then (if x then "true" else "false")
+                   then boolToString x
                    else toString x;
 
   volumeConfig = name:
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 6ae5292fc30..87c4f7a8ebc 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -5,7 +5,7 @@ with lib;
 let
 
   smbToString = x: if builtins.typeOf x == "bool"
-                   then (if x then "true" else "false")
+                   then boolToString x
                    else toString x;
 
   cfg = config.services.samba;
diff --git a/nixos/modules/services/network-filesystems/tahoe.nix b/nixos/modules/services/network-filesystems/tahoe.nix
index 3d78ac096a2..9815a5434ee 100644
--- a/nixos/modules/services/network-filesystems/tahoe.nix
+++ b/nixos/modules/services/network-filesystems/tahoe.nix
@@ -290,14 +290,14 @@ in
                 shares.total = ${toString settings.client.shares.total}
 
                 [storage]
-                enabled = ${if settings.storage.enable then "true" else "false"}
+                enabled = ${boolToString settings.storage.enable}
                 reserved_space = ${settings.storage.reservedSpace}
 
                 [helper]
-                enabled = ${if settings.helper.enable then "true" else "false"}
+                enabled = ${boolToString settings.helper.enable}
 
                 [sftpd]
-                enabled = ${if settings.sftpd.enable then "true" else "false"}
+                enabled = ${boolToString settings.sftpd.enable}
                 ${optionalString (settings.sftpd.port != null)
                   "port = ${toString settings.sftpd.port}"}
                 ${optionalString (settings.sftpd.hostPublicKeyFile != null)
diff --git a/nixos/modules/services/networking/aiccu.nix b/nixos/modules/services/networking/aiccu.nix
index aeb0910d624..ac755270951 100644
--- a/nixos/modules/services/networking/aiccu.nix
+++ b/nixos/modules/services/networking/aiccu.nix
@@ -5,7 +5,6 @@ with lib;
 let
 
   cfg = config.services.aiccu;
-  showBool = b: if b then "true" else "false";
   notNull = a: ! isNull a;
   configFile = pkgs.writeText "aiccu.conf" ''
     ${if notNull cfg.username then "username " + cfg.username else ""}
@@ -13,16 +12,16 @@ let
     protocol ${cfg.protocol}
     server ${cfg.server}
     ipv6_interface ${cfg.interfaceName}
-    verbose ${showBool cfg.verbose}
+    verbose ${boolToString cfg.verbose}
     daemonize true
-    automatic ${showBool cfg.automatic}
-    requiretls ${showBool cfg.requireTLS}
+    automatic ${boolToString cfg.automatic}
+    requiretls ${boolToString cfg.requireTLS}
     pidfile ${cfg.pidFile}
-    defaultroute ${showBool cfg.defaultRoute}
+    defaultroute ${boolToString cfg.defaultRoute}
     ${if notNull cfg.setupScript then cfg.setupScript else ""}
-    makebeats ${showBool cfg.makeHeartBeats}
-    noconfigure ${showBool cfg.noConfigure}
-    behindnat ${showBool cfg.behindNAT}
+    makebeats ${boolToString cfg.makeHeartBeats}
+    noconfigure ${boolToString cfg.noConfigure}
+    behindnat ${boolToString cfg.behindNAT}
     ${if cfg.localIPv4Override then "local_ipv4_override" else ""}
   '';
 
diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix
index 6a786e75bbc..3985f8561d3 100644
--- a/nixos/modules/services/networking/avahi-daemon.nix
+++ b/nixos/modules/services/networking/avahi-daemon.nix
@@ -7,31 +7,32 @@ let
 
   cfg = config.services.avahi;
 
+  yesNo = yes : if yes then "yes" else "no";
+
   avahiDaemonConf = with cfg; pkgs.writeText "avahi-daemon.conf" ''
     [server]
     ${# Users can set `networking.hostName' to the empty string, when getting
       # a host name from DHCP.  In that case, let Avahi take whatever the
       # current host name is; setting `host-name' to the empty string in
       # `avahi-daemon.conf' would be invalid.
-      if hostName != ""
-      then "host-name=${hostName}"
-      else ""}
+      optionalString (hostName != "") "host-name=${hostName}"}
     browse-domains=${concatStringsSep ", " browseDomains}
-    use-ipv4=${if ipv4 then "yes" else "no"}
-    use-ipv6=${if ipv6 then "yes" else "no"}
+    use-ipv4=${yesNo ipv4}
+    use-ipv6=${yesNo ipv6}
     ${optionalString (interfaces!=null) "allow-interfaces=${concatStringsSep "," interfaces}"}
     ${optionalString (domainName!=null) "domain-name=${domainName}"}
+    allow-point-to-point=${yesNo allowPointToPoint}
 
     [wide-area]
-    enable-wide-area=${if wideArea then "yes" else "no"}
+    enable-wide-area=${yesNo wideArea}
 
     [publish]
-    disable-publishing=${if publish.enable then "no" else "yes"}
-    disable-user-service-publishing=${if publish.userServices then "no" else "yes"}
-    publish-addresses=${if publish.userServices || publish.addresses then "yes" else "no"}
-    publish-hinfo=${if publish.hinfo then "yes" else "no"}
-    publish-workstation=${if publish.workstation then "yes" else "no"}
-    publish-domain=${if publish.domain then "yes" else "no"}
+    disable-publishing=${yesNo (!publish.enable)}
+    disable-user-service-publishing=${yesNo (!publish.userServices)}
+    publish-addresses=${yesNo (publish.userServices || publish.addresses)}
+    publish-hinfo=${yesNo publish.hinfo}
+    publish-workstation=${yesNo publish.workstation}
+    publish-domain=${yesNo publish.domain}
   '';
 
 in
@@ -98,6 +99,15 @@ in
         '';
       };
 
+      allowPointToPoint = mkOption {
+        default = false;
+        description= ''
+          Whether to use POINTTOPOINT interfaces. Might make mDNS unreliable due to usually large
+          latencies with such links and opens a potential security hole by allowing mDNS access from Internet
+          connections. Use with care and YMMV!
+        '';
+      };
+
       wideArea = mkOption {
         default = true;
         description = ''Whether to enable wide-area service discovery.'';
diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix
index 92e9fa7be41..6e479a5860a 100644
--- a/nixos/modules/services/networking/btsync.nix
+++ b/nixos/modules/services/networking/btsync.nix
@@ -9,7 +9,6 @@ let
 
   listenAddr = cfg.httpListenAddr + ":" + (toString cfg.httpListenPort);
 
-  boolStr = x: if x then "true" else "false";
   optionalEmptyStr = b: v: optionalString (b != "") v;
 
   webUIConfig = optionalString cfg.enableWebUI
@@ -31,7 +30,7 @@ let
   sharedFoldersRecord =
     concatStringsSep "," (map (entry:
       let helper = attr: v:
-        if (entry ? attr) then boolStr entry.attr else boolStr v;
+        if (entry ? attr) then boolToString entry.attr else boolToString v;
       in
       ''
         {
@@ -65,11 +64,11 @@ let
         "listening_port":  ${toString cfg.listeningPort},
         "use_gui":         false,
 
-        "check_for_updates": ${boolStr cfg.checkForUpdates},
-        "use_upnp":          ${boolStr cfg.useUpnp},
+        "check_for_updates": ${boolToString cfg.checkForUpdates},
+        "use_upnp":          ${boolToString cfg.useUpnp},
         "download_limit":    ${toString cfg.downloadLimit},
         "upload_limit":      ${toString cfg.uploadLimit},
-        "lan_encrypt_data":  ${boolStr cfg.encryptLAN},
+        "lan_encrypt_data":  ${boolToString cfg.encryptLAN},
 
         ${webUIConfig}
         ${sharedFoldersConfig}
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 7eeceb7407c..cdba14be21f 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -71,8 +71,7 @@ let
           # anything ever again ("couldn't resolve ..., giving up on
           # it"), so we silently lose time synchronisation. This also
           # applies to openntpd.
-          ${config.systemd.package}/bin/systemctl try-restart ntpd.service
-          ${config.systemd.package}/bin/systemctl try-restart openntpd.service
+          ${config.systemd.package}/bin/systemctl try-reload-or-restart ntpd.service openntpd.service || true
       fi
 
       ${cfg.runHook}
diff --git a/nixos/modules/services/networking/firefox/sync-server.nix b/nixos/modules/services/networking/firefox/sync-server.nix
index 5c14ceff6a0..3a95b9c4ec9 100644
--- a/nixos/modules/services/networking/firefox/sync-server.nix
+++ b/nixos/modules/services/networking/firefox/sync-server.nix
@@ -19,7 +19,7 @@ let
     [syncserver]
     public_url = ${cfg.publicUrl}
     ${optionalString (cfg.sqlUri != "") "sqluri = ${cfg.sqlUri}"}
-    allow_new_users = ${if cfg.allowNewUsers then "true" else "false"}
+    allow_new_users = ${boolToString cfg.allowNewUsers}
 
     [browserid]
     backend = tokenserver.verifiers.LocalVerifier
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index c5b27350b3c..24a3196bed4 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -10,8 +10,6 @@ let
 
   extip = "EXTIP=\$(${pkgs.curl.bin}/bin/curl -sLf \"http://jsonip.com\" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
 
-  toYesNo = b: if b then "true" else "false";
-
   mkEndpointOpt = name: addr: port: {
     enable = mkEnableOption name;
     name = mkOption {
@@ -76,10 +74,10 @@ let
 
   i2pdConf = pkgs.writeText "i2pd.conf"
   ''
-  ipv4 = ${toYesNo cfg.enableIPv4}
-  ipv6 = ${toYesNo cfg.enableIPv6}
-  notransit = ${toYesNo cfg.notransit}
-  floodfill = ${toYesNo cfg.floodfill}
+  ipv4 = ${boolToString cfg.enableIPv4}
+  ipv6 = ${boolToString cfg.enableIPv6}
+  notransit = ${boolToString cfg.notransit}
+  floodfill = ${boolToString cfg.floodfill}
   netid = ${toString cfg.netid}
   ${if isNull cfg.bandwidth then "" else "bandwidth = ${toString cfg.bandwidth}" }
   ${if isNull cfg.port then "" else "port = ${toString cfg.port}"}
@@ -88,14 +86,14 @@ let
   transittunnels = ${toString cfg.limits.transittunnels}
 
   [upnp]
-  enabled = ${toYesNo cfg.upnp.enable}
+  enabled = ${boolToString cfg.upnp.enable}
   name = ${cfg.upnp.name}
 
   [precomputation]
-  elgamal = ${toYesNo cfg.precomputation.elgamal}
+  elgamal = ${boolToString cfg.precomputation.elgamal}
 
   [reseed]
-  verify = ${toYesNo cfg.reseed.verify}
+  verify = ${boolToString cfg.reseed.verify}
   file = ${cfg.reseed.file}
   urls = ${builtins.concatStringsSep "," cfg.reseed.urls}
 
@@ -107,11 +105,11 @@ let
       (proto: let portStr = toString proto.port; in
         ''
           [${proto.name}]
-          enabled = ${toYesNo proto.enable}
+          enabled = ${boolToString proto.enable}
           address = ${proto.address}
           port = ${toString proto.port}
           ${if proto ? keys then "keys = ${proto.keys}" else ""}
-          ${if proto ? auth then "auth = ${toYesNo proto.auth}" else ""}
+          ${if proto ? auth then "auth = ${boolToString proto.auth}" else ""}
           ${if proto ? user then "user = ${proto.user}" else ""}
           ${if proto ? pass then "pass = ${proto.pass}" else ""}
           ${if proto ? outproxy then "outproxy = ${proto.outproxy}" else ""}
diff --git a/nixos/modules/services/networking/ircd-hybrid/default.nix b/nixos/modules/services/networking/ircd-hybrid/default.nix
index ede57c5046d..bd583fb020e 100644
--- a/nixos/modules/services/networking/ircd-hybrid/default.nix
+++ b/nixos/modules/services/networking/ircd-hybrid/default.nix
@@ -12,7 +12,7 @@ let
     substFiles = [ "=>/conf" ./ircd.conf ];
     inherit (pkgs) ircdHybrid coreutils su iproute gnugrep procps;
 
-    ipv6Enabled = if config.networking.enableIPv6 then "true" else "false";
+    ipv6Enabled = boolToString config.networking.enableIPv6;
 
     inherit (cfg) serverName sid description adminEmail
             extraPort;
diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix
index 2325424ff3c..5451500b56f 100644
--- a/nixos/modules/services/networking/mosquitto.nix
+++ b/nixos/modules/services/networking/mosquitto.nix
@@ -16,7 +16,7 @@ let
     pid_file /run/mosquitto/pid
     acl_file ${aclFile}
     persistence true
-    allow_anonymous ${if cfg.allowAnonymous then "true" else "false"}
+    allow_anonymous ${boolToString cfg.allowAnonymous}
     bind_address ${cfg.host}
     port ${toString cfg.port}
     ${listenerConf}
diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix
index 81f968ae9fe..13d7c3254f9 100644
--- a/nixos/modules/services/networking/murmur.nix
+++ b/nixos/modules/services/networking/murmur.nix
@@ -26,21 +26,21 @@ let
 
     textmessagelength=${toString cfg.textMsgLength}
     imagemessagelength=${toString cfg.imgMsgLength}
-    allowhtml=${if cfg.allowHtml then "true" else "false"}
+    allowhtml=${boolToString cfg.allowHtml}
     logdays=${toString cfg.logDays}
-    bonjour=${if cfg.bonjour then "true" else "false"}
-    sendversion=${if cfg.sendVersion then "true" else "false"}
+    bonjour=${boolToString cfg.bonjour}
+    sendversion=${boolToString cfg.sendVersion}
 
     ${if cfg.registerName     == "" then "" else "registerName="+cfg.registerName}
     ${if cfg.registerPassword == "" then "" else "registerPassword="+cfg.registerPassword}
     ${if cfg.registerUrl      == "" then "" else "registerUrl="+cfg.registerUrl}
     ${if cfg.registerHostname == "" then "" else "registerHostname="+cfg.registerHostname}
 
-    certrequired=${if cfg.clientCertRequired then "true" else "false"}
+    certrequired=${boolToString cfg.clientCertRequired}
     ${if cfg.sslCert == "" then "" else "sslCert="+cfg.sslCert}
     ${if cfg.sslKey  == "" then "" else "sslKey="+cfg.sslKey}
     ${if cfg.sslCa   == "" then "" else "sslCA="+cfg.sslCa}
-    
+
     ${cfg.extraConfig}
   '';
 in
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 7255ffc5af4..220107a2411 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -162,9 +162,9 @@ in {
         type = types.listOf (types.submodule {
           options = {
             source = mkOption {
-              type = types.str;
+              type = types.path;
               description = ''
-                A script source.
+                A script.
               '';
             };
 
@@ -224,7 +224,7 @@ in {
              target = "NetworkManager/dispatcher.d/02overridedns";
            }
       ++ lib.imap (i: s: {
-        text = s.source;
+        inherit (s) source;
         target = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}";
       }) cfg.dispatcherScripts;
 
@@ -241,6 +241,7 @@ in {
     users.extraUsers = [{
       name = "nm-openvpn";
       uid = config.ids.uids.nm-openvpn;
+      extraGroups = [ "networkmanager" ];
     }];
 
     systemd.packages = cfg.packages;
diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix
index feaa007de15..fb9c9dc67f2 100644
--- a/nixos/modules/services/networking/prosody.nix
+++ b/nixos/modules/services/networking/prosody.nix
@@ -219,7 +219,7 @@ in
 
       data_path = "/var/lib/prosody"
 
-      allow_registration = ${ if cfg.allowRegistration then "true" else "false" };
+      allow_registration = ${boolToString cfg.allowRegistration};
 
       ${ optionalString cfg.modules.console "console_enabled = true;" }
 
@@ -244,7 +244,7 @@ in
 
       ${ lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
         VirtualHost "${v.domain}"
-          enabled = ${if v.enabled then "true" else "false"};
+          enabled = ${boolToString v.enabled};
           ${ optionalString (v.ssl != null) (createSSLOptsStr v.ssl) }
           ${ v.extraConfig }
         '') cfg.virtualHosts) }
diff --git a/nixos/modules/services/networking/searx.nix b/nixos/modules/services/networking/searx.nix
index 3520c6d3f7d..e0eef9ed96f 100644
--- a/nixos/modules/services/networking/searx.nix
+++ b/nixos/modules/services/networking/searx.nix
@@ -18,17 +18,12 @@ in
 
     services.searx = {
 
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = "
-          Whether to enable the Searx server. See https://github.com/asciimoo/searx
-        ";
-      };
+      enable = mkEnableOption
+        "the searx server. See https://github.com/asciimoo/searx";
 
       configFile = mkOption {
-        type = types.path;
-        default = "";
+        type = types.nullOr types.path;
+        default = null;
         description = "
           The path of the Searx server configuration file. If no file
           is specified, a default file is used (default config file has
@@ -72,7 +67,7 @@ in
           User = "searx";
           ExecStart = "${cfg.package}/bin/searx-run";
         };
-      } // (optionalAttrs (configFile != "") {
+      } // (optionalAttrs (configFile != null) {
         environment.SEARX_SETTINGS_PATH = configFile;
       });
 
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index bac79474527..c5c131cb4c5 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -288,8 +288,11 @@ in
     };
     systemd.services.smokeping = {
       wantedBy = [ "multi-user.target"];
-      serviceConfig.User = cfg.user;
-      serviceConfig.PermissionsStartOnly = true;
+      serviceConfig = {
+        User = cfg.user;
+        PermissionsStartOnly = true;
+        Restart = "on-failure";
+      };
       preStart = ''
         mkdir -m 0755 -p ${smokepingHome}/cache ${smokepingHome}/data
         rm -f ${smokepingHome}/cropper
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 42b50d0426a..bebf4e145ca 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -316,8 +316,6 @@ in
 
         UsePAM yes
 
-        UsePrivilegeSeparation sandbox
-
         AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
         ${concatMapStrings (port: ''
           Port ${toString port}
diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix
index bd584a3a85d..e3d65c49fbf 100644
--- a/nixos/modules/services/networking/sslh.nix
+++ b/nixos/modules/services/networking/sslh.nix
@@ -5,7 +5,7 @@ with lib;
 let
   cfg = config.services.sslh;
   configFile = pkgs.writeText "sslh.conf" ''
-    verbose: ${if cfg.verbose then "true" else "false"};
+    verbose: ${boolToString cfg.verbose};
     foreground: true;
     inetd: false;
     numeric: false;
diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix
index 6d68b790e86..1c63d800e26 100644
--- a/nixos/modules/services/networking/znc.nix
+++ b/nixos/modules/services/networking/znc.nix
@@ -35,7 +35,7 @@ let
             Port = ${toString confOpts.port}
             IPv4 = true
             IPv6 = true
-            SSL = ${if confOpts.useSSL then "true" else "false"}
+            SSL = ${boolToString confOpts.useSSL}
     </Listener>
     
     <User ${confOpts.userName}>
diff --git a/nixos/modules/services/scheduling/fcron.nix b/nixos/modules/services/scheduling/fcron.nix
index bd1ecb40969..bc631bdd044 100644
--- a/nixos/modules/services/scheduling/fcron.nix
+++ b/nixos/modules/services/scheduling/fcron.nix
@@ -143,10 +143,12 @@ in
       };
 
       preStart = ''
-        ${pkgs.coreutils}/bin/mkdir -m 0770 -p /var/spool/fcron
-        ${pkgs.coreutils}/bin/chown -R fcron:fcron /var/spool/fcron
+        install \
+          --mode 0770 \
+          --owner fcron \
+          --group fcron \
+          --directory /var/spool/fcron
         # load system crontab file
-        set -x
         #${pkgs.fcron}/bin/fcrontab -u systab ${pkgs.writeText "systab" cfg.systab}
       '';
 
diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2_proxy.nix
index caa7d9d5081..e292fd9851e 100644
--- a/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixos/modules/services/security/oauth2_proxy.nix
@@ -10,9 +10,6 @@ let
   #   repeatedArgs (arg: "--arg=${arg}") args
   repeatedArgs = concatMapStringsSep " ";
 
-  # 'toString' doesn't quite do what we want for bools.
-  fromBool = x: if x then "true" else "false";
-
   # oauth2_proxy provides many options that are only relevant if you are using
   # a certain provider. This set maps from provider name to a function that
   # takes the configuration and returns a string that can be inserted into the
@@ -49,24 +46,24 @@ let
     --client-secret='${cfg.clientSecret}' \
     ${optionalString (!isNull cfg.cookie.domain) "--cookie-domain='${cfg.cookie.domain}'"} \
     --cookie-expire='${cfg.cookie.expire}' \
-    --cookie-httponly=${fromBool cfg.cookie.httpOnly} \
+    --cookie-httponly=${boolToString cfg.cookie.httpOnly} \
     --cookie-name='${cfg.cookie.name}' \
     --cookie-secret='${cfg.cookie.secret}' \
-    --cookie-secure=${fromBool cfg.cookie.secure} \
+    --cookie-secure=${boolToString cfg.cookie.secure} \
     ${optionalString (!isNull cfg.cookie.refresh) "--cookie-refresh='${cfg.cookie.refresh}'"} \
     ${optionalString (!isNull cfg.customTemplatesDir) "--custom-templates-dir='${cfg.customTemplatesDir}'"} \
     ${repeatedArgs (x: "--email-domain='${x}'") cfg.email.domains} \
     --http-address='${cfg.httpAddress}' \
-    ${optionalString (!isNull cfg.htpasswd.file) "--htpasswd-file='${cfg.htpasswd.file}' --display-htpasswd-form=${fromBool cfg.htpasswd.displayForm}"} \
+    ${optionalString (!isNull cfg.htpasswd.file) "--htpasswd-file='${cfg.htpasswd.file}' --display-htpasswd-form=${boolToString cfg.htpasswd.displayForm}"} \
     ${optionalString (!isNull cfg.loginURL) "--login-url='${cfg.loginURL}'"} \
-    --pass-access-token=${fromBool cfg.passAccessToken} \
-    --pass-basic-auth=${fromBool cfg.passBasicAuth} \
-    --pass-host-header=${fromBool cfg.passHostHeader} \
+    --pass-access-token=${boolToString cfg.passAccessToken} \
+    --pass-basic-auth=${boolToString cfg.passBasicAuth} \
+    --pass-host-header=${boolToString cfg.passHostHeader} \
     --proxy-prefix='${cfg.proxyPrefix}' \
     ${optionalString (!isNull cfg.profileURL) "--profile-url='${cfg.profileURL}'"} \
     ${optionalString (!isNull cfg.redeemURL) "--redeem-url='${cfg.redeemURL}'"} \
     ${optionalString (!isNull cfg.redirectURL) "--redirect-url='${cfg.redirectURL}'"} \
-    --request-logging=${fromBool cfg.requestLogging} \
+    --request-logging=${boolToString cfg.requestLogging} \
     ${optionalString (!isNull cfg.scope) "--scope='${cfg.scope}'"} \
     ${repeatedArgs (x: "--skip-auth-regex='${x}'") cfg.skipAuthRegexes} \
     ${optionalString (!isNull cfg.signatureKey) "--signature-key='${cfg.signatureKey}'"} \
diff --git a/nixos/modules/services/system/earlyoom.nix b/nixos/modules/services/system/earlyoom.nix
new file mode 100644
index 00000000000..daa46838bfa
--- /dev/null
+++ b/nixos/modules/services/system/earlyoom.nix
@@ -0,0 +1,96 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  ecfg = config.services.earlyoom;
+in
+{
+  options = {
+    services.earlyoom = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable early out of memory killing.
+        '';
+      };
+
+      freeMemThreshold = mkOption {
+        type = types.int;
+        default = 10;
+        description = ''
+          Minimum of availabe memory (in percent).
+          If the free memory falls below this threshold and the analog is true for
+          <option>services.earlyoom.freeSwapThreshold</option>
+          the killing begins.
+        '';
+      };
+
+      freeSwapThreshold = mkOption {
+        type = types.int;
+        default = 10;
+        description = ''
+          Minimum of availabe swap space (in percent).
+          If the available swap space falls below this threshold and the analog
+          is true for <option>services.earlyoom.freeMemThreshold</option>
+          the killing begins.
+        '';
+      };
+
+      useKernelOOMKiller= mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Use kernel OOM killer instead of own user-space implementation.
+        '';
+      };
+
+      ignoreOOMScoreAdjust = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Ignore oom_score_adjust values of processes.
+          User-space implementation only.
+        '';
+      };
+
+      enableDebugInfo = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable debugging messages.
+        '';
+      };
+    };
+  };
+
+  config = mkIf ecfg.enable {
+    assertions = [
+      { assertion = ecfg.freeMemThreshold > 0 && ecfg.freeMemThreshold <= 100;
+        message = "Needs to be a positive percentage"; }
+      { assertion = ecfg.freeSwapThreshold > 0 && ecfg.freeSwapThreshold <= 100;
+        message = "Needs to be a positive percentage"; }
+      { assertion = !ecfg.useKernelOOMKiller || !ecfg.ignoreOOMScoreAdjust;
+        message = "Both options in conjunction do not make sense"; }
+    ];
+
+    systemd.services.earlyoom = {
+      description = "Early OOM Daemon for Linux";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        StandardOutput = "null";
+        StandardError = "syslog";
+        ExecStart = ''
+          ${pkgs.earlyoom}/bin/earlyoom \
+          -m ${toString ecfg.freeMemThreshold} \
+          -s ${toString ecfg.freeSwapThreshold} \
+          ${optionalString ecfg.useKernelOOMKiller "-k"} \
+          ${optionalString ecfg.ignoreOOMScoreAdjust "-i"} \
+          ${optionalString ecfg.enableDebugInfo "-d"}
+        '';
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
index 5b2e4ca1606..1f319df794b 100644
--- a/nixos/modules/services/torrent/transmission.nix
+++ b/nixos/modules/services/torrent/transmission.nix
@@ -15,8 +15,7 @@ let
 
   # Strings must be quoted, ints and bools must not (for settings.json).
   toOption = x:
-    if x == true then "true"
-    else if x == false then "false"
+    if isBool x then boolToString x
     else if isInt x then toString x
     else toString ''"${x}"'';
 
diff --git a/nixos/modules/services/web-apps/atlassian/crowd.nix b/nixos/modules/services/web-apps/atlassian/crowd.nix
index 7ff7dc4e574..b54c91d7de9 100644
--- a/nixos/modules/services/web-apps/atlassian/crowd.nix
+++ b/nixos/modules/services/web-apps/atlassian/crowd.nix
@@ -137,7 +137,7 @@ in
 
         sed -e 's,port="8095",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
         '' + (lib.optionalString cfg.proxy.enable ''
-          -e 's,compression="on",compression="off" protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${toString cfg.proxy.secure}",' \
+          -e 's,compression="on",compression="off" protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${boolToString cfg.proxy.secure}",' \
         '') + ''
           ${pkg}/apache-tomcat/conf/server.xml.dist > ${cfg.home}/server.xml
       '';
diff --git a/nixos/modules/services/web-apps/quassel-webserver.nix b/nixos/modules/services/web-apps/quassel-webserver.nix
index d19e4bc5827..2ba5698d6cb 100644
--- a/nixos/modules/services/web-apps/quassel-webserver.nix
+++ b/nixos/modules/services/web-apps/quassel-webserver.nix
@@ -12,11 +12,11 @@ let
         port: ${toString cfg.quasselCorePort},  // quasselcore port
         initialBacklogLimit: ${toString cfg.initialBacklogLimit},  // Amount of backlogs to fetch per buffer on connection
         backlogLimit: ${toString cfg.backlogLimit},  // Amount of backlogs to fetch per buffer after first retrieval
-        securecore: ${if cfg.secureCore then "true" else "false"},  // Connect to the core using SSL
+        securecore: ${boolToString cfg.secureCore},  // Connect to the core using SSL
         theme: '${cfg.theme}'  // Default UI theme
       },
       themes: ['default', 'darksolarized'],  //  Available themes
-      forcedefault: ${if cfg.forceHostAndPort then "true" else "false"},  // Will force default host and port to be used, and will hide the corresponding fields in the UI
+      forcedefault: ${boolToString cfg.forceHostAndPort},  // Will force default host and port to be used, and will hide the corresponding fields in the UI
       prefixpath: '${cfg.prefixPath}'  // Configure this if you use a reverse proxy
     };
   '';
diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix
index 5193814da72..76b0ee6da96 100644
--- a/nixos/modules/services/web-apps/tt-rss.nix
+++ b/nixos/modules/services/web-apps/tt-rss.nix
@@ -6,8 +6,6 @@ let
 
   configVersion = 26;
 
-  boolToString = b: if b then "true" else "false";
-
   cacheDir = "cache";
   lockDir = "lock";
   feedIconsDir = "feed-icons";
diff --git a/nixos/modules/services/web-servers/lighttpd/gitweb.nix b/nixos/modules/services/web-servers/lighttpd/gitweb.nix
index f12cc973446..c8d9836b0b6 100644
--- a/nixos/modules/services/web-servers/lighttpd/gitweb.nix
+++ b/nixos/modules/services/web-servers/lighttpd/gitweb.nix
@@ -60,7 +60,8 @@ in
               "/gitweb/"        => "${pkgs.git}/share/gitweb/gitweb.cgi"
           )
           setenv.add-environment = (
-              "GITWEB_CONFIG" => "${gitwebConfigFile}"
+              "GITWEB_CONFIG" => "${gitwebConfigFile}",
+              "HOME" => "${cfg.projectroot}"
           )
       }
     '';
diff --git a/nixos/modules/services/x11/compton.nix b/nixos/modules/services/x11/compton.nix
index d1f7f164e64..d75d24830f8 100644
--- a/nixos/modules/services/x11/compton.nix
+++ b/nixos/modules/services/x11/compton.nix
@@ -83,7 +83,7 @@ in {
         "focused = 1" 
       ];
       description = ''
-        List of condition of windows that should have no shadow.
+        List of conditions of windows that should not be faded.
         See <literal>compton(1)</literal> man page for more examples.
       '';
     };
@@ -123,7 +123,7 @@ in {
         "focused = 1" 
       ];
       description = ''
-        List of condition of windows that should have no shadow.
+        List of conditions of windows that should have no shadow.
         See <literal>compton(1)</literal> man page for more examples.
       '';
     };
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 4e2c0e01ca0..543fd939914 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -32,8 +32,14 @@ let
     ''
       #! ${pkgs.bash}/bin/bash
 
-      # Handle being called by SDDM.
-      if test "''${1:0:1}" = / ; then eval exec $1 $2 ; fi
+      # SDDM splits "Exec" line in .desktop file by whitespace and pass script path as $1
+      if [[ "$0" = "$1" ]]; then
+        # remove superfluous $1 again
+        shift
+        # join arguments again and evaluate them in a shell context
+        # to interpret shell quoting
+        eval exec "$0" "$@"
+      fi
 
       ${optionalString cfg.displayManager.logToJournal ''
         if [ -z "$_DID_SYSTEMD_CAT" ]; then
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
index affc1261d19..99c03ca81c2 100644
--- a/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -59,7 +59,7 @@ let
     [Autologin]
     User=${cfg.autoLogin.user}
     Session=${defaultSessionName}.desktop
-    Relogin=${if cfg.autoLogin.relogin then "true" else "false"}
+    Relogin=${boolToString cfg.autoLogin.relogin}
     ''}
 
     ${cfg.extraConfig}
diff --git a/nixos/modules/services/x11/hardware/multitouch.nix b/nixos/modules/services/x11/hardware/multitouch.nix
index 0e9eb021494..c03bb3b494f 100644
--- a/nixos/modules/services/x11/hardware/multitouch.nix
+++ b/nixos/modules/services/x11/hardware/multitouch.nix
@@ -74,7 +74,7 @@ in {
           MatchIsTouchpad "on"
           Identifier "Touchpads"
           Driver "mtrack"
-          Option "IgnorePalm" "${if cfg.ignorePalm then "true" else "false"}"
+          Option "IgnorePalm" "${boolToString cfg.ignorePalm}"
           Option "ClickFinger1" "${builtins.elemAt cfg.buttonsMap 0}"
           Option "ClickFinger2" "${builtins.elemAt cfg.buttonsMap 1}"
           Option "ClickFinger3" "${builtins.elemAt cfg.buttonsMap 2}"
diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix
index 42785b25158..32ef34bdad2 100644
--- a/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixos/modules/services/x11/window-managers/default.nix
@@ -15,6 +15,7 @@ in
     ./dwm.nix
     ./exwm.nix
     ./fluxbox.nix
+    ./fvwm.nix
     ./herbstluftwm.nix
     ./i3.nix
     ./jwm.nix
diff --git a/nixos/modules/services/x11/window-managers/fvwm.nix b/nixos/modules/services/x11/window-managers/fvwm.nix
new file mode 100644
index 00000000000..9a51b9cd660
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/fvwm.nix
@@ -0,0 +1,41 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.fvwm;
+  fvwm = pkgs.fvwm.override { gestures = cfg.gestures; };
+in
+
+{
+
+  ###### interface
+
+  options = {
+    services.xserver.windowManager.fvwm = {
+      enable = mkEnableOption "Fvwm window manager";
+
+      gestures = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Whether or not to enable libstroke for gesture support";
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton
+      { name = "fvwm";
+        start =
+          ''
+            ${fvwm}/bin/fvwm &
+            waitPID=$!
+          '';
+      };
+
+    environment.systemPackages = [ fvwm ];
+  };
+}
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index 84c23bed3e3..e9897cc01b6 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -53,6 +53,8 @@ let
 
         ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd
 
+        ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
+
         ln -s ${config.hardware.firmware}/lib/firmware $out/firmware
       ''}
 
diff --git a/nixos/modules/system/boot/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix
index 59ecaf8d5a6..d78775c2758 100644
--- a/nixos/modules/system/boot/initrd-ssh.nix
+++ b/nixos/modules/system/boot/initrd-ssh.nix
@@ -44,9 +44,10 @@ in
       description = ''
         RSA SSH private key file in the Dropbear format.
 
-        WARNING: This key is contained insecurely in the global Nix store. Do NOT
-        use your regular SSH host private keys for this purpose or you'll expose
-        them to regular users!
+        WARNING: Unless your bootloader supports initrd secrets, this key is
+        contained insecurely in the global Nix store. Do NOT use your regular
+        SSH host private keys for this purpose or you'll expose them to
+        regular users!
       '';
     };
 
@@ -56,9 +57,10 @@ in
       description = ''
         DSS SSH private key file in the Dropbear format.
 
-        WARNING: This key is contained insecurely in the global Nix store. Do NOT
-        use your regular SSH host private keys for this purpose or you'll expose
-        them to regular users!
+        WARNING: Unless your bootloader supports initrd secrets, this key is
+        contained insecurely in the global Nix store. Do NOT use your regular
+        SSH host private keys for this purpose or you'll expose them to
+        regular users!
       '';
     };
 
@@ -68,9 +70,10 @@ in
       description = ''
         ECDSA SSH private key file in the Dropbear format.
 
-        WARNING: This key is contained insecurely in the global Nix store. Do NOT
-        use your regular SSH host private keys for this purpose or you'll expose
-        them to regular users!
+        WARNING: Unless your bootloader supports initrd secrets, this key is
+        contained insecurely in the global Nix store. Do NOT use your regular
+        SSH host private keys for this purpose or you'll expose them to
+        regular users!
       '';
     };
 
@@ -97,10 +100,6 @@ in
     boot.initrd.extraUtilsCommands = ''
       copy_bin_and_libs ${pkgs.dropbear}/bin/dropbear
       cp -pv ${pkgs.glibc.out}/lib/libnss_files.so.* $out/lib
-
-      ${optionalString (cfg.hostRSAKey != null) "install -D ${cfg.hostRSAKey} $out/etc/dropbear/dropbear_rsa_host_key"}
-      ${optionalString (cfg.hostDSSKey != null) "install -D ${cfg.hostDSSKey} $out/etc/dropbear/dropbear_dss_host_key"}
-      ${optionalString (cfg.hostECDSAKey != null) "install -D ${cfg.hostECDSAKey} $out/etc/dropbear/dropbear_ecdsa_host_key"}
     '';
 
     boot.initrd.extraUtilsCommandsTest = ''
@@ -116,9 +115,6 @@ in
       touch /var/log/lastlog
 
       mkdir -p /etc/dropbear
-      ${optionalString (cfg.hostRSAKey != null) "ln -s $extraUtils/etc/dropbear/dropbear_rsa_host_key /etc/dropbear/dropbear_rsa_host_key"}
-      ${optionalString (cfg.hostDSSKey != null) "ln -s $extraUtils/etc/dropbear/dropbear_dss_host_key /etc/dropbear/dropbear_dss_host_key"}
-      ${optionalString (cfg.hostECDSAKey != null) "ln -s $extraUtils/etc/dropbear/dropbear_ecdsa_host_key /etc/dropbear/dropbear_ecdsa_host_key"}
 
       mkdir -p /root/.ssh
       ${concatStrings (map (key: ''
@@ -128,6 +124,11 @@ in
       dropbear -s -j -k -E -m -p ${toString cfg.port}
     '';
 
+    boot.initrd.secrets =
+     (optionalAttrs (cfg.hostRSAKey != null) { "/etc/dropbear/dropbear_rsa_host_key" = cfg.hostRSAKey; }) //
+     (optionalAttrs (cfg.hostDSSKey != null) { "/etc/dropbear/dropbear_dss_host_key" = cfg.hostDSSKey; }) //
+     (optionalAttrs (cfg.hostECDSAKey != null) { "/etc/dropbear/dropbear_ecdsa_host_key" = cfg.hostECDSAKey; });
+
   };
 
 }
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index 04cf17c1b0b..d5e00129a82 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -32,8 +32,11 @@ def write_loader_conf(generation):
             f.write("editor 0");
     os.rename("@efiSysMountPoint@/loader/loader.conf.tmp", "@efiSysMountPoint@/loader/loader.conf")
 
+def profile_path(generation, name):
+    return os.readlink("%s/%s" % (system_dir(generation), name))
+
 def copy_from_profile(generation, name, dry_run=False):
-    store_file_path = os.readlink("%s/%s" % (system_dir(generation), name))
+    store_file_path = profile_path(generation, name)
     suffix = os.path.basename(store_file_path)
     store_dir = os.path.basename(os.path.dirname(store_file_path))
     efi_file_path = "/efi/nixos/%s-%s.efi" % (store_dir, suffix)
@@ -44,6 +47,11 @@ def copy_from_profile(generation, name, dry_run=False):
 def write_entry(generation, machine_id):
     kernel = copy_from_profile(generation, "kernel")
     initrd = copy_from_profile(generation, "initrd")
+    try:
+        append_initrd_secrets = profile_path(generation, "append-initrd-secrets")
+        subprocess.check_call([append_initrd_secrets, "@efiSysMountPoint@%s" % (initrd)])
+    except FileNotFoundError:
+        pass
     entry_file = "@efiSysMountPoint@/loader/entries/nixos-generation-%d.conf" % (generation)
     generation_dir = os.readlink(system_dir(generation))
     tmp_path = "%s.tmp" % (entry_file)
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index ec02f73cada..a5a88a99be8 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -65,6 +65,8 @@ in {
 
     boot.loader.grub.enable = mkDefault false;
 
+    boot.loader.supportsInitrdSecrets = true;
+
     system = {
       build.installBootLoader = gummibootBuilder;
 
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 8978b73749b..6e867b67439 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -6,29 +6,38 @@ let
   luks = config.boot.initrd.luks;
 
   openCommand = name': { name, device, header, keyFile, keyFileSize, allowDiscards, yubikey, ... }: assert name' == name; ''
-    # Wait for luksRoot to appear, e.g. if on a usb drive.
-    # XXX: copied and adapted from stage-1-init.sh - should be
-    # available as a function.
-    if ! test -e ${device}; then
-        echo -n "waiting 10 seconds for device ${device} to appear..."
-        for try in $(seq 10); do
-            sleep 1
-            if test -e ${device}; then break; fi
-            echo -n .
-        done
-        echo "ok"
-    fi
+
+    # Wait for a target (e.g. device, keyFile, header, ...) to appear.
+    wait_target() {
+        local name="$1"
+        local target="$2"
+
+        if [ ! -e $target ]; then
+            echo -n "Waiting 10 seconds for $name $target to appear"
+            local success=false;
+            for try in $(seq 10); do
+                echo -n "."
+                sleep 1
+                if [ -e $target ]; then success=true break; fi
+            done
+            if [ $success = true ]; then
+                echo " - success";
+            else
+                echo " - failure";
+            fi
+        fi
+    }
+
+    # Wait for luksRoot (and optionally keyFile and/or header) to appear, e.g.
+    # if on a USB drive.
+    wait_target "device" ${device}
 
     ${optionalString (keyFile != null) ''
-    if ! test -e ${keyFile}; then
-        echo -n "waiting 10 seconds for key file ${keyFile} to appear..."
-        for try in $(seq 10); do
-            sleep 1
-            if test -e ${keyFile}; then break; fi
-            echo -n .
-        done
-        echo "ok"
-    fi
+      wait_target "key file" ${keyFile}
+    ''}
+
+    ${optionalString (header != null) ''
+      wait_target "header" ${header}
     ''}
 
     open_normally() {
diff --git a/nixos/modules/system/boot/readonly-mountpoint.c b/nixos/modules/system/boot/readonly-mountpoint.c
deleted file mode 100644
index 27b66687382..00000000000
--- a/nixos/modules/system/boot/readonly-mountpoint.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <sys/statvfs.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char ** argv) {
-	struct statvfs stat;
-	if (argc != 2) {
-		fprintf(stderr, "Usage: %s PATH", argv[0]);
-		exit(2);
-	}
-	if (statvfs(argv[1], &stat) != 0) {
-		perror("statvfs");
-		exit(3);
-	}
-	if (stat.f_flag & ST_RDONLY)
-		exit(0);
-	else
-		exit(1);
-}
-
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index f0699ad9832..c75e637124a 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -8,6 +8,14 @@ export LD_LIBRARY_PATH=@extraUtils@/lib
 export PATH=@extraUtils@/bin
 ln -s @extraUtils@/bin /bin
 
+# Copy the secrets to their needed location
+if [ -d "@extraUtils@/secrets" ]; then
+    for secret in $(cd "@extraUtils@/secrets"; find . -type f); do
+        mkdir -p $(dirname "/$secret")
+        ln -s "@extraUtils@/secrets/$secret" "$secret"
+    done
+fi
+
 # Stop LVM complaining about fd3
 export LVM_SUPPRESS_FD_WARNINGS=true
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 61def24efd8..e3a3b6f88cf 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -82,6 +82,17 @@ let
         copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
       ''}
 
+      # Copy secrets if needed.
+      ${optionalString (!config.boot.loader.supportsInitrdSecrets)
+          (concatStringsSep "\n" (mapAttrsToList (dest: source:
+             let source' = if source == null then dest else source; in
+               ''
+                  mkdir -p $(dirname "$out/secrets/${dest}")
+                  cp -a ${source'} "$out/secrets/${dest}"
+                ''
+          ) config.boot.initrd.secrets))
+       }
+
       ${config.boot.initrd.extraUtilsCommands}
 
       # Copy ld manually since it isn't detected correctly
@@ -242,6 +253,52 @@ let
       ];
   };
 
+  # Script to add secret files to the initrd at bootloader update time
+  initialRamdiskSecretAppender =
+    pkgs.writeScriptBin "append-initrd-secrets"
+      ''
+        #!${pkgs.bash}/bin/bash -e
+        function usage {
+          echo "USAGE: $0 INITRD_FILE" >&2
+          echo "Appends this configuration's secrets to INITRD_FILE" >&2
+        }
+
+        if [ $# -ne 1 ]; then
+          usage
+          exit 1
+        fi
+
+        if [ "$1"x = "--helpx" ]; then
+          usage
+          exit 0
+        fi
+
+        ${lib.optionalString (config.boot.initrd.secrets == {})
+            "exit 0"}
+
+        export PATH=${pkgs.coreutils}/bin:${pkgs.cpio}/bin:${pkgs.gzip}/bin:${pkgs.findutils}/bin
+
+        function cleanup {
+          if [ -n "$tmp" -a -d "$tmp" ]; then
+            rm -fR "$tmp"
+          fi
+        }
+        trap cleanup EXIT
+
+        tmp=$(mktemp -d initrd-secrets.XXXXXXXXXX)
+
+        ${lib.concatStringsSep "\n" (mapAttrsToList (dest: source:
+            let source' = if source == null then dest else toString source; in
+              ''
+                mkdir -p $(dirname "$tmp/${dest}")
+                cp -a ${source'} "$tmp/${dest}"
+              ''
+          ) config.boot.initrd.secrets)
+         }
+
+        (cd "$tmp" && find . | cpio -H newc -o) | gzip >>"$1"
+      '';
+
 in
 
 {
@@ -370,6 +427,25 @@ in
       example = "xz";
     };
 
+    boot.initrd.secrets = mkOption
+      { internal = true;
+        default = {};
+        type = types.attrsOf (types.nullOr types.path);
+        description =
+          ''
+            Secrets to append to the initrd. The attribute name is the
+            path the secret should have inside the initrd, the value
+            is the path it should be copied from (or null for the same
+            path inside and out).
+          '';
+        example = literalExample
+          ''
+            { "/etc/dropbear/dropbear_rsa_host_key" =
+                ./secret-dropbear-key;
+            }
+          '';
+      };
+
     boot.initrd.supportedFilesystems = mkOption {
       default = [ ];
       example = [ "btrfs" ];
@@ -377,6 +453,18 @@ in
       description = "Names of supported filesystem types in the initial ramdisk.";
     };
 
+    boot.loader.supportsInitrdSecrets = mkOption
+      { internal = true;
+        default = false;
+        type = types.bool;
+        description =
+          ''
+            Whether the bootloader setup runs append-initrd-secrets.
+            If not, any needed secrets must be copied into the initrd
+            and thus added to the store.
+          '';
+      };
+
     fileSystems = mkOption {
       options.neededForBoot = mkOption {
         default = false;
@@ -404,9 +492,8 @@ in
       }
     ];
 
-    system.build.bootStage1 = bootStage1;
-    system.build.initialRamdisk = initialRamdisk;
-    system.build.extraUtils = extraUtils;
+    system.build =
+      { inherit bootStage1 initialRamdisk initialRamdiskSecretAppender extraUtils; };
 
     system.requiredKernelConfig = with config.lib.kernelConfig; [
       (isYes "TMPFS")
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index f827e530f87..46aed44bf10 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -2,7 +2,22 @@
 
 systemConfig=@systemConfig@
 
-export HOME=/root
+export HOME=/root PATH="@path@"
+
+
+# Process the kernel command line.
+for o in $(</proc/cmdline); do
+    case $o in
+        boot.debugtrace)
+            # Show each command.
+            set -x
+            ;;
+        resume=*)
+            set -- $(IFS==; echo $o)
+            resumeDevice=$2
+            ;;
+    esac
+done
 
 
 # Print a greeting.
@@ -11,21 +26,6 @@ echo -e "\e[1;32m<<< NixOS Stage 2 >>>\e[0m"
 echo
 
 
-# Set the PATH.
-setPath() {
-    local dirs="$1"
-    export PATH=/empty
-    for i in $dirs; do
-        PATH=$PATH:$i/bin
-        if test -e $i/sbin; then
-            PATH=$PATH:$i/sbin
-        fi
-    done
-}
-
-setPath "@path@"
-
-
 # Normally, stage 1 mounts the root filesystem read/writable.
 # However, in some environments, stage 2 is executed directly, and the
 # root is read-only.  So make it writable here.
@@ -61,7 +61,9 @@ echo "booting system configuration $systemConfig" > /dev/kmsg
 chown -f 0:30000 /nix/store
 chmod -f 1775 /nix/store
 if [ -n "@readOnlyStore@" ]; then
-    if ! readonly-mountpoint /nix/store; then
+    if ! [[ "$(findmnt --noheadings --output OPTIONS /nix/store)" =~ ro(,|$) ]]; then
+        # FIXME when linux < 4.5 is EOL, switch to atomic bind mounts
+        #mount /nix/store /nix/store -o bind,remount,ro
         mount --bind /nix/store /nix/store
         mount -o remount,ro,bind /nix/store
     fi
@@ -75,31 +77,12 @@ rm -f /etc/mtab* # not that we care about stale locks
 ln -s /proc/mounts /etc/mtab
 
 
-# Process the kernel command line.
-for o in $(cat /proc/cmdline); do
-    case $o in
-        boot.debugtrace)
-            # Show each command.
-            set -x
-            ;;
-        resume=*)
-            set -- $(IFS==; echo $o)
-            resumeDevice=$2
-            ;;
-    esac
-done
-
-
 # More special file systems, initialise required directories.
 [ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
 mkdir -m 01777 -p /tmp
-mkdir -m 0755 -p /var /var/log /var/lib /var/db
-mkdir -m 0755 -p /nix/var
-mkdir -m 0700 -p /root
-chmod 0700 /root
-mkdir -m 0755 -p /bin # for the /bin/sh symlink
-mkdir -m 0755 -p /home
-mkdir -m 0755 -p /etc/nixos
+mkdir -m 0755 -p /var/{log,lib,db} /nix/var /etc/nixos/ \
+    /run/lock /home /bin # for the /bin/sh symlink
+install -m 0700 -d /root
 
 
 # Miscellaneous boot time cleanup.
@@ -111,9 +94,6 @@ rm -f /etc/{group,passwd,shadow}.lock
 rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots
 
 
-mkdir -m 0755 -p /run/lock
-
-
 # For backwards compatibility, symlink /var/run to /run, and /var/lock
 # to /run/lock.
 ln -s /run /var/run
@@ -127,8 +107,8 @@ fi
 
 
 # Use /etc/resolv.conf supplied by systemd-nspawn, if applicable.
-if [ -n "@useHostResolvConf@" -a -e /etc/resolv.conf ]; then
-    cat /etc/resolv.conf | resolvconf -m 1000 -a host
+if [ -n "@useHostResolvConf@" ] && [ -e /etc/resolv.conf ]; then
+    resolvconf -m 1000 -a host </etc/resolv.conf
 fi
 
 # Log the script output to /dev/kmsg or /run/log/stage-2-init.log.
diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix
index 7e4ec2a4a67..8db6d2d2f73 100644
--- a/nixos/modules/system/boot/stage-2.nix
+++ b/nixos/modules/system/boot/stage-2.nix
@@ -7,15 +7,6 @@ let
   kernel = config.boot.kernelPackages.kernel;
   activateConfiguration = config.system.activationScripts.script;
 
-  readonlyMountpoint = pkgs.stdenv.mkDerivation {
-    name = "readonly-mountpoint";
-    unpackPhase = "true";
-    installPhase = ''
-      mkdir -p $out/bin
-      cc -O3 ${./readonly-mountpoint.c} -o $out/bin/readonly-mountpoint
-    '';
-  };
-
   bootStage2 = pkgs.substituteAll {
     src = ./stage-2-init.sh;
     shellDebug = "${pkgs.bashInteractive}/bin/bash";
@@ -23,11 +14,11 @@ let
     inherit (config.nix) readOnlyStore;
     inherit (config.networking) useHostResolvConf;
     inherit (config.system.build) earlyMountScript;
-    path =
-      [ pkgs.coreutils
-        pkgs.utillinux
-        pkgs.openresolv
-      ] ++ optional config.nix.readOnlyStore readonlyMountpoint;
+    path = lib.makeBinPath [
+      pkgs.coreutils
+      pkgs.utillinux
+      pkgs.openresolv
+    ];
     postBootCommands = pkgs.writeText "local-cmds"
       ''
         ${config.boot.postBootCommands}
diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix
index 7dbf3b25cdb..7c01f8ea9b7 100644
--- a/nixos/modules/system/boot/systemd-lib.nix
+++ b/nixos/modules/system/boot/systemd-lib.nix
@@ -10,7 +10,7 @@ rec {
 
   makeUnit = name: unit:
     let
-      pathSafeName = lib.replaceChars ["@" ":" "\\"] ["-" "-" "-"] name;
+      pathSafeName = lib.replaceChars ["@" ":" "\\" "[" "]"] ["-" "-" "-" "" ""] name;
     in
     if unit.enable then
       pkgs.runCommand "unit-${pathSafeName}"
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index bff6739db61..f798862513c 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -829,7 +829,8 @@ in
 
     # Some overrides to upstream units.
     systemd.services."systemd-backlight@".restartIfChanged = false;
-    systemd.services."systemd-rfkill@".restartIfChanged = false;
+    systemd.services."systemd-fsck@".restartIfChanged = false;
+    systemd.services."systemd-fsck@".path = [ config.system.path ];
     systemd.services."user@".restartIfChanged = false;
     systemd.services.systemd-journal-flush.restartIfChanged = false;
     systemd.services.systemd-random-seed.restartIfChanged = false;
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index 9f30eb61146..3951d617f6f 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -221,7 +221,7 @@ in
 
     environment.etc.fstab.text =
       let
-        fsToSkipCheck = [ "none" "btrfs" "zfs" "tmpfs" "nfs" "vboxsf" "glusterfs" ];
+        fsToSkipCheck = [ "none" "bindfs" "btrfs" "zfs" "tmpfs" "nfs" "vboxsf" "glusterfs" ];
         skipCheck = fs: fs.noCheck || fs.device == "none" || builtins.elem fs.fsType fsToSkipCheck;
       in ''
         # This is a generated file.  Do not edit!
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index f30906b84a2..f6f104ce7a6 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -120,7 +120,7 @@ let
                     optionalString (cfg.defaultGatewayWindowSize != null)
                       "window ${toString cfg.defaultGatewayWindowSize}"} ${
                     optionalString (cfg.defaultGateway.interface != null)
-                      "dev ${cfg.defaultGateway.interface}"} || true
+                      "dev ${cfg.defaultGateway.interface}"} proto static || true
                 ''}
                 ${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "") ''
                   # FIXME: get rid of "|| true" (necessary to make it idempotent).
@@ -130,7 +130,7 @@ let
                     optionalString (cfg.defaultGatewayWindowSize != null)
                       "window ${toString cfg.defaultGatewayWindowSize}"} ${
                     optionalString (cfg.defaultGateway6.interface != null)
-                      "dev ${cfg.defaultGateway6.interface}"} || true
+                      "dev ${cfg.defaultGateway6.interface}"} proto static || true
                 ''}
               '';
           };
@@ -159,35 +159,42 @@ let
             after = [ "network-pre.target" ] ++ (deviceDependency i.name);
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
+            # Restart rather than stop+start this unit to prevent the
+            # network from dying during switch-to-configuration.
+            stopIfChanged = false;
             path = [ pkgs.iproute ];
             script =
               ''
+                # FIXME: shouldn't this be done in network-link?
                 echo "bringing up interface..."
                 ip link set "${i.name}" up
 
-                restart_network_interfaces=false
+                state="/run/nixos/network/addresses/${i.name}"
+
+                mkdir -p $(dirname "$state")
+
               '' + flip concatMapStrings (ips) (ip:
                 let
                   address = "${ip.address}/${toString ip.prefixLength}";
                 in
                 ''
-                  echo "checking ip ${address}..."
+                  echo "${address}" >> $state
                   if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then
-                    echo "added ip ${address}..."
+                    echo "added ip ${address}"
                   elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
                     echo "failed to add ${address}"
                     exit 1
                   fi
                 '');
-            preStop = flip concatMapStrings (ips) (ip:
-                let
-                  address = "${ip.address}/${toString ip.prefixLength}";
-                in
-                ''
-                  echo -n "deleting ${address}..."
-                  ip addr del "${address}" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed"
-                  echo ""
-                '');
+            preStop = ''
+              state="/run/nixos/network/addresses/${i.name}"
+              while read address; do
+                echo -n "deleting $address..."
+                ip addr del "$address" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed"
+                echo ""
+              done < "$state"
+              rm -f "$state"
+            '';
           };
 
         createTunDevice = i: nameValuePair "${i.name}-netdev"
diff --git a/nixos/modules/tasks/powertop.nix b/nixos/modules/tasks/powertop.nix
new file mode 100644
index 00000000000..6f57f5f5c25
--- /dev/null
+++ b/nixos/modules/tasks/powertop.nix
@@ -0,0 +1,27 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.powerManagment.powertop;
+in {
+  ###### interface
+
+  options.powerManagment.powertop.enable = mkEnableOption "powertop auto tuning on startup";
+
+  ###### implementation
+
+  config = mkIf (cfg.enable) {
+    systemd.services = {
+      powertop = {
+        wantedBy = [ "multi-user.target" ];
+        description = "Powertop tunings";
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = "yes";
+          ExecStart = "${pkgs.powertop}/bin/powertop --auto-tune";
+        };
+      };
+    };
+  };
+}
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index 80e481d79b9..3e47710361a 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -15,6 +15,12 @@ let cfg = config.ec2; in
 
   config = {
 
+    assertions = [
+      { assertion = cfg.hvm;
+        message = "Paravirtualized EC2 instances are no longer supported.";
+      }
+    ];
+
     virtualisation.growPartition = cfg.hvm;
 
     fileSystems."/" = {
diff --git a/nixos/modules/virtualisation/amazon-options.nix b/nixos/modules/virtualisation/amazon-options.nix
index 34a50dcab16..349fd3adfc9 100644
--- a/nixos/modules/virtualisation/amazon-options.nix
+++ b/nixos/modules/virtualisation/amazon-options.nix
@@ -3,7 +3,7 @@
   options = {
     ec2 = {
       hvm = lib.mkOption {
-        default = false;
+        default = lib.versionAtLeast config.system.stateVersion "17.03";
         internal = true;
         description = ''
           Whether the EC2 instance is a HVM instance.
@@ -11,6 +11,4 @@
       };
     };
   };
-
-  config = {};
 }
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index 4b30a38f832..f1101d7ea66 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -126,7 +126,17 @@ in
 
         path = [ pkgs.kmod ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs);
       };
-      systemd.sockets.docker.socketConfig.ListenStream = cfg.listenOptions;
+
+      systemd.sockets.docker = {
+        description = "Docker Socket for the API";
+        wantedBy = [ "sockets.target" ];
+        socketConfig = {
+          ListenStream = cfg.listenOptions;
+          SocketMode = "0660";
+          SocketUser = "root";
+          SocketGroup = "docker";
+        };
+      };
     }
   ]);
 
diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix
index d592a23c303..745518f8597 100644
--- a/nixos/modules/virtualisation/ec2-amis.nix
+++ b/nixos/modules/virtualisation/ec2-amis.nix
@@ -193,5 +193,35 @@ let self = {
   "16.09".us-west-2.pv-ebs = "ami-6d4af60d";
   "16.09".us-west-2.pv-s3 = "ami-de48f4be";
 
-  latest = self."16.09";
+  # 17.03.885.6024dd4067
+  "17.03".ap-northeast-1.hvm-ebs = "ami-dbd0f7bc";
+  "17.03".ap-northeast-1.hvm-s3 = "ami-7cdff81b";
+  "17.03".ap-northeast-2.hvm-ebs = "ami-c59a48ab";
+  "17.03".ap-northeast-2.hvm-s3 = "ami-0b944665";
+  "17.03".ap-south-1.hvm-ebs = "ami-4f413220";
+  "17.03".ap-south-1.hvm-s3 = "ami-864033e9";
+  "17.03".ap-southeast-1.hvm-ebs = "ami-e08c3383";
+  "17.03".ap-southeast-1.hvm-s3 = "ami-c28f30a1";
+  "17.03".ap-southeast-2.hvm-ebs = "ami-fca9a69f";
+  "17.03".ap-southeast-2.hvm-s3 = "ami-3daaa55e";
+  "17.03".ca-central-1.hvm-ebs = "ami-9b00bdff";
+  "17.03".ca-central-1.hvm-s3 = "ami-e800bd8c";
+  "17.03".eu-central-1.hvm-ebs = "ami-5450803b";
+  "17.03".eu-central-1.hvm-s3 = "ami-6e2efe01";
+  "17.03".eu-west-1.hvm-ebs = "ami-10754c76";
+  "17.03".eu-west-1.hvm-s3 = "ami-11734a77";
+  "17.03".eu-west-2.hvm-ebs = "ami-ff1d099b";
+  "17.03".eu-west-2.hvm-s3 = "ami-fe1d099a";
+  "17.03".sa-east-1.hvm-ebs = "ami-d95d3eb5";
+  "17.03".sa-east-1.hvm-s3 = "ami-fca2c190";
+  "17.03".us-east-1.hvm-ebs = "ami-0940c61f";
+  "17.03".us-east-1.hvm-s3 = "ami-674fc971";
+  "17.03".us-east-2.hvm-ebs = "ami-afc2e6ca";
+  "17.03".us-east-2.hvm-s3 = "ami-a1cde9c4";
+  "17.03".us-west-1.hvm-ebs = "ami-587b2138";
+  "17.03".us-west-1.hvm-s3 = "ami-70411b10";
+  "17.03".us-west-2.hvm-ebs = "ami-a93daac9";
+  "17.03".us-west-2.hvm-s3 = "ami-5139ae31";
+
+  latest = self."17.03";
 }; in self
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index a3dd3bd55d1..5673d55b339 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -2,10 +2,10 @@
 
 with lib;
 let
-  diskSize = "100G";
+  diskSize = "1G";
 in
 {
-  imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ];
+  imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ./grow-partition.nix ];
 
   # https://cloud.google.com/compute/docs/tutorials/building-images
   networking.firewall.enable = mkDefault false;
@@ -94,7 +94,10 @@ in
         ''
     );
 
-  fileSystems."/".label = "nixos";
+  fileSystems."/" = {
+    device = "/dev/disk/by-label/nixos";
+    autoResize = true;
+  };
 
   boot.kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ];
   boot.initrd.kernelModules = [ "virtio_scsi" ];
diff --git a/nixos/release.nix b/nixos/release.nix
index 5f9a5b0e064..95b284cb705 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -288,8 +288,8 @@ in rec {
   tests.pam-oath-login = callTest tests/pam-oath-login.nix {};
   #tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
   tests.peerflix = callTest tests/peerflix.nix {};
+  tests.postgresql = callSubTests tests/postgresql.nix {};
   tests.pgjwt = callTest tests/pgjwt.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/docker.nix b/nixos/tests/docker.nix
index 1b57a94a05d..9096a5868f6 100644
--- a/nixos/tests/docker.nix
+++ b/nixos/tests/docker.nix
@@ -11,6 +11,21 @@ import ./make-test.nix ({ pkgs, ...} : {
       { config, pkgs, ... }:
         {
           virtualisation.docker.enable = true;
+
+          users.users = {
+            noprivs = {
+              isNormalUser = true;
+              description = "Can't access the docker daemon";
+              password = "foobar";
+            };
+
+            hasprivs = {
+              isNormalUser = true;
+              description = "Can access the docker daemon";
+              password = "foobar";
+              extraGroups = [ "docker" ];
+            };
+          };
         };
     };
 
@@ -21,6 +36,8 @@ import ./make-test.nix ({ pkgs, ...} : {
     $docker->succeed("tar cv --files-from /dev/null | docker import - scratchimg");
     $docker->succeed("docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10");
     $docker->succeed("docker ps | grep sleeping");
+    $docker->succeed("sudo -u hasprivs docker ps");
+    $docker->fail("sudo -u noprivs docker ps");
     $docker->succeed("docker stop sleeping");
   '';
 })
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 35dd00fe630..3ab3c1bac48 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -34,6 +34,12 @@ let
           boot.loader.systemd-boot.enable = true;
         ''}
 
+        users.extraUsers.alice = {
+          isNormalUser = true;
+          home = "/home/alice";
+          description = "Alice Foobar";
+        };
+
         hardware.enableAllFirmware = lib.mkForce false;
 
         ${replaceChars ["\n"] ["\n  "] extraConfig}
@@ -96,7 +102,7 @@ let
       $machine->shutdown;
 
       # Now see if we can boot the installation.
-      $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" });
+      $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "boot-after-install" });
 
       # For example to enter LUKS passphrase.
       ${preBootCommands}
@@ -118,11 +124,17 @@ let
       $machine->waitForUnit("swap.target");
       $machine->succeed("cat /proc/swaps | grep -q /dev");
 
+      # Check that the store is in good shape
+      $machine->succeed("nix-store --verify --check-contents >&2");
+
       # Check whether the channel works.
       $machine->succeed("nix-env -iA nixos.procps >&2");
       $machine->succeed("type -tP ps | tee /dev/stderr") =~ /.nix-profile/
           or die "nix-env failed";
 
+      # Check that the daemon works, and that non-root users can run builds (this will build a new profile generation through the daemon)
+      $machine->succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2");
+
       # We need to a writable nix-store on next boot.
       $machine->copyFileFromHost(
           "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier extraConfig; forceGrubReinstallCount = 1; } }",
@@ -139,7 +151,7 @@ let
       $machine->shutdown;
 
       # Check whether a writable store build works
-      $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" });
+      $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "rebuild-switch" });
       ${preBootCommands}
       $machine->waitForUnit("multi-user.target");
       $machine->copyFileFromHost(
@@ -150,7 +162,7 @@ let
 
       # And just to be sure, check that the machine still boots after
       # "nixos-rebuild switch".
-      $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" });
+      $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", "boot-after-rebuild-switch" });
       ${preBootCommands}
       $machine->waitForUnit("network.target");
       $machine->shutdown;
diff --git a/nixos/tests/postgresql.nix b/nixos/tests/postgresql.nix
index f17384b44ba..1f4f43a2666 100644
--- a/nixos/tests/postgresql.nix
+++ b/nixos/tests/postgresql.nix
@@ -1,26 +1,46 @@
-import ./make-test.nix ({ pkgs, ...} : {
-  name = "postgresql";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ zagy ];
-  };
-
-  nodes = {
-    master =
-      { pkgs, config, ... }:
+{ system ? builtins.currentSystem }:
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
+let
+  postgresql-versions = pkgs.callPackages ../../pkgs/servers/sql/postgresql { };
+  test-sql = pkgs.writeText "postgresql-test" ''
+    CREATE EXTENSION pgcrypto; -- just to check if lib loading works
+    CREATE TABLE sth (
+      id int
+    );
+    INSERT INTO sth (id) VALUES (1);
+    INSERT INTO sth (id) VALUES (1);
+    INSERT INTO sth (id) VALUES (1);
+    INSERT INTO sth (id) VALUES (1);
+    INSERT INTO sth (id) VALUES (1);
+  '';
+  make-postgresql-test = postgresql-name: postgresql-package: {
+    name = postgresql-name;
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ zagy ];
+    };
 
+    machine = {pkgs, config, ...}:
       {
+        services.postgresql.package=postgresql-package;
         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");
-  '';
-})
+    testScript = ''
+      $machine->start;
+      $machine->waitForUnit("postgresql");
+      # postgresql should be available just after unit start
+      $machine->succeed("cat ${test-sql} | psql postgres");
+      $machine->shutdown; # make sure that postgresql survive restart (bug #1735)
+      sleep(2);
+      $machine->start;
+      $machine->waitForUnit("postgresql");
+      $machine->fail('test $(psql postgres -tAc "SELECT * FROM sth;"|wc -l) -eq 3');
+      $machine->succeed('test $(psql postgres -tAc "SELECT * FROM sth;"|wc -l) -eq 5');
+      $machine->fail('test $(psql postgres -tAc "SELECT * FROM sth;"|wc -l) -eq 4');
+      $machine->shutdown;
+    '';
+
+  };
+in
+  mapAttrs' (p-name: p-package: {name=p-name; value=make-postgresql-test p-name p-package;}) postgresql-versions