about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/administration/declarative-containers.xml6
-rw-r--r--nixos/doc/manual/configuration/config-file.xml2
-rw-r--r--nixos/doc/manual/configuration/network-manager.xml6
-rw-r--r--nixos/doc/manual/man-nixos-rebuild.xml23
-rw-r--r--nixos/lib/build-vms.nix2
-rw-r--r--nixos/modules/config/nsswitch.nix7
-rw-r--r--nixos/modules/config/update-users-groups.pl10
-rw-r--r--nixos/modules/config/users-groups.nix1
-rw-r--r--nixos/modules/hardware/video/nvidia.nix30
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh11
-rw-r--r--nixos/modules/installer/tools/nixos-version.sh10
-rw-r--r--nixos/modules/installer/tools/tools.nix2
-rw-r--r--nixos/modules/misc/ids.nix14
-rw-r--r--nixos/modules/module-list.nix8
-rw-r--r--nixos/modules/programs/environment.nix3
-rw-r--r--nixos/modules/programs/ssh.nix25
-rw-r--r--nixos/modules/programs/uim.nix4
-rw-r--r--nixos/modules/security/ca.nix39
-rw-r--r--nixos/modules/security/grsecurity.nix3
-rw-r--r--nixos/modules/security/pam.nix43
-rw-r--r--nixos/modules/services/audio/mpd.nix29
-rw-r--r--nixos/modules/services/databases/couchdb.nix9
-rw-r--r--nixos/modules/services/databases/mongodb.nix1
-rw-r--r--nixos/modules/services/databases/redis.nix4
-rw-r--r--nixos/modules/services/mail/exim.nix111
-rw-r--r--nixos/modules/services/misc/disnix.nix2
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix46
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix2
-rw-r--r--nixos/modules/services/network-filesystems/u9fs.nix75
-rw-r--r--nixos/modules/services/networking/consul.nix7
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix2
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix9
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix2
-rw-r--r--nixos/modules/services/networking/haproxy.nix22
-rw-r--r--nixos/modules/services/networking/networkmanager.nix37
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix8
-rw-r--r--nixos/modules/services/networking/vsftpd.nix5
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix10
-rw-r--r--nixos/modules/services/scheduling/chronos.nix2
-rw-r--r--nixos/modules/services/scheduling/marathon.nix58
-rw-r--r--nixos/modules/services/security/fail2ban.nix2
-rw-r--r--nixos/modules/services/torrent/transmission.nix22
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix3
-rw-r--r--nixos/modules/services/web-servers/fcgiwrap.nix51
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix30
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix12
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix23
-rw-r--r--nixos/modules/services/x11/display-managers/kdm.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix55
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix110
-rw-r--r--nixos/modules/services/x11/window-managers/default.nix3
-rw-r--r--nixos/modules/services/x11/window-managers/sawfish.nix28
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl145
-rw-r--r--nixos/modules/system/boot/loader/generations-dir/generations-dir.nix2
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix3
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl4
-rw-r--r--nixos/modules/system/boot/loader/init-script/init-script.nix1
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix1
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh13
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh6
-rw-r--r--nixos/modules/tasks/kbd.nix1
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix5
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix15
-rw-r--r--nixos/modules/virtualisation/amazon-options.nix16
-rw-r--r--nixos/modules/virtualisation/azure-image.nix57
-rw-r--r--nixos/modules/virtualisation/containers.nix17
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix10
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix2
-rw-r--r--nixos/modules/virtualisation/lxc.nix11
-rw-r--r--nixos/modules/virtualisation/nixos-container.pl5
-rw-r--r--nixos/modules/virtualisation/nova.nix4
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix89
-rw-r--r--nixos/modules/virtualisation/xen-dom0.nix263
-rw-r--r--nixos/modules/virtualisation/xen-domU.nix5
-rw-r--r--nixos/release.nix3
-rw-r--r--nixos/tests/chromium.nix2
-rw-r--r--nixos/tests/i3wm.nix28
77 files changed, 1380 insertions, 359 deletions
diff --git a/nixos/doc/manual/administration/declarative-containers.xml b/nixos/doc/manual/administration/declarative-containers.xml
index 177ebdd8db175..5e0bf9d4431f8 100644
--- a/nixos/doc/manual/administration/declarative-containers.xml
+++ b/nixos/doc/manual/administration/declarative-containers.xml
@@ -49,4 +49,8 @@ on container networking.)</para>
 switch</literal>. Note that this will not delete the root directory of
 the container in <literal>/var/lib/containers</literal>.</para>
 
-</section>
\ No newline at end of file
+<para>Declarative containers can be started and stopped using the relative
+systemd service. For example
+<literal>systemctl start container@database</literal>.</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/config-file.xml b/nixos/doc/manual/configuration/config-file.xml
index 2a58ff25941c1..b613c7f06cc89 100644
--- a/nixos/doc/manual/configuration/config-file.xml
+++ b/nixos/doc/manual/configuration/config-file.xml
@@ -68,7 +68,7 @@ instance, if you try to define an option that doesn’t exist (that is,
 doesn’t have a corresponding <emphasis>option declaration</emphasis>),
 <command>nixos-rebuild</command> will give an error like:
 <screen>
-The option `services.httpd.enabl' defined in `/etc/nixos/configuration.nix' does not exist.
+The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist.
 </screen>
 Likewise, values in option definitions must have a correct type.  For
 instance, <option>services.httpd.enable</option> must be a Boolean
diff --git a/nixos/doc/manual/configuration/network-manager.xml b/nixos/doc/manual/configuration/network-manager.xml
index ceac40b7a1f66..b7e47b8729f32 100644
--- a/nixos/doc/manual/configuration/network-manager.xml
+++ b/nixos/doc/manual/configuration/network-manager.xml
@@ -10,7 +10,7 @@
 use NetworkManager. You can enable NetworkManager by setting:
 
 <programlisting>
-services.networkmanager.enable = true;
+networking.networkmanager.enable = true;
 </programlisting>
 
 some desktop managers (e.g., GNOME) enable NetworkManager
@@ -19,8 +19,8 @@ automatically for you.</para>
 <para>All users that should have permission to change network settings
 must belong to the <code>networkmanager</code> group.</para>
 
-<note><para><code>services.networkmanager</code> and
-<code>services.wireless</code> can not be enabled at the same time:
+<note><para><code>networking.networkmanager</code> and
+<code>networking.wireless</code> can not be enabled at the same time:
 you can still connect to the wireless networks using
 NetworkManager.</para></note>
 
diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml
index afc159dbd5d76..c529737c3bf3d 100644
--- a/nixos/doc/manual/man-nixos-rebuild.xml
+++ b/nixos/doc/manual/man-nixos-rebuild.xml
@@ -1,7 +1,7 @@
 <refentry xmlns="http://docbook.org/ns/docbook"
           xmlns:xlink="http://www.w3.org/1999/xlink"
           xmlns:xi="http://www.w3.org/2001/XInclude">
-  
+
 <refmeta>
   <refentrytitle><command>nixos-rebuild</command></refentrytitle>
   <manvolnum>8</manvolnum>
@@ -22,7 +22,8 @@
       <arg choice='plain'><option>boot</option></arg>
       <arg choice='plain'><option>test</option></arg>
       <arg choice='plain'><option>build</option></arg>
-      <arg choice='plain'><option>dry-run</option></arg>
+      <arg choice='plain'><option>dry-build</option></arg>
+      <arg choice='plain'><option>dry-activate</option></arg>
       <arg choice='plain'><option>build-vm</option></arg>
       <arg choice='plain'><option>build-vm-with-bootloader</option></arg>
     </group>
@@ -114,10 +115,22 @@ $ nix-build /path/to/nixpkgs/nixos -A system
   </varlistentry>
 
   <varlistentry>
-    <term><option>dry-run</option></term>
+    <term><option>dry-build</option></term>
+    <listitem>
+      <para>Show what store paths would be built or downloaded by any
+      of the operations above, but otherwise do nothing.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><option>dry-activate</option></term>
     <listitem>
-      <para>Simply show what store paths would be built or downloaded
-      by any of the operations above.</para>
+      <para>Build the new configuration, but instead of activating it,
+      show what changes would be performed by the activation (i.e. by
+      <command>nixos-rebuild test</command>). For
+      instance, this command will print which systemd units would be
+      restarted. The list of changes is not guaranteed to be
+      complete.</para>
     </listitem>
   </varlistentry>
 
diff --git a/nixos/lib/build-vms.nix b/nixos/lib/build-vms.nix
index 50b3b424166ba..d0c9e7c6d236a 100644
--- a/nixos/lib/build-vms.nix
+++ b/nixos/lib/build-vms.nix
@@ -70,7 +70,7 @@ rec {
                   # virtualisation.vlans option).
                   networking.extraHosts = flip concatMapStrings machines
                     (m': let config = (getAttr m' nodes).config; in
-                      optionalString (m.first != m' && config.networking.primaryIPAddress != "")
+                      optionalString (config.networking.primaryIPAddress != "")
                         ("${config.networking.primaryIPAddress} " +
                          "${config.networking.hostName}\n"));
 
diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix
index 549e731f3b08a..a39c2895bf84d 100644
--- a/nixos/modules/config/nsswitch.nix
+++ b/nixos/modules/config/nsswitch.nix
@@ -8,6 +8,7 @@ let
 
   inherit (config.services.avahi) nssmdns;
   inherit (config.services.samba) nsswins;
+  ldap = config.users.ldap.enable;
 
 in
 
@@ -40,9 +41,9 @@ in
     # should define an option used by this module.
     environment.etc."nsswitch.conf".text =
       ''
-        passwd:    files ldap
-        group:     files ldap
-        shadow:    files ldap
+        passwd:    files ${optionalString ldap "ldap"}
+        group:     files ${optionalString ldap "ldap"}
+        shadow:    files ${optionalString ldap "ldap"}
         hosts:     files ${optionalString nssmdns "mdns_minimal [NOTFOUND=return]"} dns ${optionalString nssmdns "mdns"} ${optionalString nsswins "wins"} myhostname mymachines
         networks:  files dns
         ethers:    files
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index d35ecb754bdb0..de73de91629b0 100644
--- a/nixos/modules/config/update-users-groups.pl
+++ b/nixos/modules/config/update-users-groups.pl
@@ -174,12 +174,12 @@ foreach my $u (@{$spec->{users}}) {
         } elsif (defined $u->{initialHashedPassword}) {
             $u->{hashedPassword} = $u->{initialHashedPassword};
         }
+    }
 
-        # Create a home directory.
-        if ($u->{createHome}) {
-            make_path($u->{home}, { mode => 0700 }) if ! -e $u->{home};
-            chown $u->{uid}, $u->{gid}, $u->{home};
-        }
+    # Create a home directory.
+    if ($u->{createHome} && ! -e $u->{home}) {
+        make_path($u->{home}, { mode => 0700 }) if ! -e $u->{home};
+        chown $u->{uid}, $u->{gid}, $u->{home};
     }
 
     if (defined $u->{passwordFile}) {
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index f585a27747994..db87f9fd0b1a5 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -489,6 +489,7 @@ in {
       utmp.gid = ids.gids.utmp;
       adm.gid = ids.gids.adm;
       grsecurity.gid = ids.gids.grsecurity;
+      input.gid = ids.gids.input;
     };
 
     system.activationScripts.users = stringAfter [ "etc" ]
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 325aa5f093f80..209310bec9991 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -11,20 +11,21 @@ let
   # FIXME: should introduce an option like
   # ‘hardware.video.nvidia.package’ for overriding the default NVIDIA
   # driver.
-  enabled = elem "nvidia" drivers || elem "nvidiaLegacy173" drivers
-    || elem "nvidiaLegacy304" drivers || elem "nvidiaLegacy340" drivers;
-
-  nvidia_x11 =
+  nvidiaForKernel = kernelPackages:
     if elem "nvidia" drivers then
-      config.boot.kernelPackages.nvidia_x11
+      kernelPackages.nvidia_x11
     else if elem "nvidiaLegacy173" drivers then
-      config.boot.kernelPackages.nvidia_x11_legacy173
+      kernelPackages.nvidia_x11_legacy173
     else if elem "nvidiaLegacy304" drivers then
-      config.boot.kernelPackages.nvidia_x11_legacy304
+      kernelPackages.nvidia_x11_legacy304
     else if elem "nvidiaLegacy340" drivers then
-      config.boot.kernelPackages.nvidia_x11_legacy340
-    else throw "impossible";
+      kernelPackages.nvidia_x11_legacy340
+    else null;
+
+  nvidia_x11 = nvidiaForKernel config.boot.kernelPackages;
+  nvidia_libs32 = (nvidiaForKernel pkgs_i686.linuxPackages).override { libsOnly = true; kernel = null; };
 
+  enabled = nvidia_x11 != null;
 in
 
 {
@@ -40,12 +41,21 @@ in
       '';
 
     hardware.opengl.package = nvidia_x11;
-    hardware.opengl.package32 = pkgs_i686.linuxPackages.nvidia_x11.override { libsOnly = true; kernel = null; };
+    hardware.opengl.package32 = nvidia_libs32;
 
     environment.systemPackages = [ nvidia_x11 ];
 
     boot.extraModulePackages = [ nvidia_x11 ];
 
+    # nvidia-uvm is required by CUDA applications.
+    boot.kernelModules = [ "nvidia-uvm" ];
+
+    # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
+    services.udev.extraRules =
+      ''
+        KERNEL=="nvidia_uvm", RUN+="${pkgs.stdenv.shell} -c 'mknod -m 666 /dev/nvidia-uvm c $(grep nvidia-uvm /proc/devices | cut -d \  -f 1) 0'"
+      '';
+
     boot.blacklistedKernelModules = [ "nouveau" "nvidiafb" ];
 
     services.acpid.enable = true;
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 8157f8fc7da5d..1d6df8cb3f71a 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -26,7 +26,8 @@ while [ "$#" -gt 0 ]; do
       --help)
         showSyntax
         ;;
-      switch|boot|test|build|dry-run|build-vm|build-vm-with-bootloader)
+      switch|boot|test|build|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader)
+        if [ "$i" = dry-run ]; then i=dry-build; fi
         action="$i"
         ;;
       --install-grub)
@@ -137,7 +138,7 @@ fi
 
 # First build Nix, since NixOS may require a newer version than the
 # current one.
-if [ -n "$rollback" -o "$action" = dry-run ]; then
+if [ -n "$rollback" -o "$action" = dry-build ]; then
     buildNix=
 fi
 
@@ -180,7 +181,7 @@ if [ -n "$canRun" ]; then
 fi
 
 
-if [ "$action" = dry-run ]; then
+if [ "$action" = dry-build ]; then
     extraBuildFlags+=(--dry-run)
 fi
 
@@ -193,7 +194,7 @@ if [ -z "$rollback" ]; then
     if [ "$action" = switch -o "$action" = boot ]; then
         nix-env "${extraBuildFlags[@]}" -p "$profile" -f '<nixpkgs/nixos>' --set -A system
         pathToConfig="$profile"
-    elif [ "$action" = test -o "$action" = build -o "$action" = dry-run ]; then
+    elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
         nix-build '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}" > /dev/null
         pathToConfig=./result
     elif [ "$action" = build-vm ]; then
@@ -224,7 +225,7 @@ fi
 
 # If we're not just building, then make the new configuration the boot
 # default and/or activate it now.
-if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then
+if [ "$action" = switch -o "$action" = boot -o "$action" = test -o "$action" = dry-activate ]; then
     if ! $pathToConfig/bin/switch-to-configuration "$action"; then
         echo "warning: error(s) occured while switching to the new configuration" >&2
         exit 1
diff --git a/nixos/modules/installer/tools/nixos-version.sh b/nixos/modules/installer/tools/nixos-version.sh
index 5dbf277fe4c42..51aa2dd823216 100644
--- a/nixos/modules/installer/tools/nixos-version.sh
+++ b/nixos/modules/installer/tools/nixos-version.sh
@@ -1,2 +1,10 @@
 #! @shell@
-echo "@nixosVersion@ (@nixosCodeName@)"
+
+case "$1" in
+  --hash|--revision)
+    echo "@nixosRevision@"
+    ;;
+  *)
+    echo "@nixosVersion@ (@nixosCodeName@)"
+    ;;
+esac
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 63d2077fbe193..99a74b6d59edf 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -50,7 +50,7 @@ let
   nixos-version = makeProg {
     name = "nixos-version";
     src = ./nixos-version.sh;
-    inherit (config.system) nixosVersion nixosCodeName;
+    inherit (config.system) nixosVersion nixosCodeName nixosRevision;
   };
 
 in
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index f3cda7b954167..158609dcf7931 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -178,6 +178,9 @@
       nylon = 168;
       apache-kafka = 169;
       panamax = 170;
+      marathon = 171;
+      exim = 172;
+      sddm = 175;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -299,8 +302,6 @@
       mlmmj = 135;
       riemann = 137;
       riemanndash = 138;
-      hbase = 139;
-      opentsdb = 140;
       uhub = 142;
       mailpile = 146;
       redmine = 147;
@@ -311,13 +312,18 @@
       systemd-resolve = 153;
       systemd-timesync = 154;
       liquidsoap = 155;
-      fleet = 159;
+      hbase = 158;
+      opentsdb = 159;
       scollector = 160;
       bosun = 161;
       kubernetes = 162;
       gitlab = 165;
-      nylon = 166;
+      nylon = 168;
       panamax = 170;
+      exim = 172;
+      fleet = 173;
+      input = 174;
+      sddm = 175;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 0fad59d55717f..ef1e9d450c865 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -166,6 +166,7 @@
   ./services/logging/syslogd.nix
   ./services/logging/syslog-ng.nix
   ./services/mail/dovecot.nix
+  ./services/mail/exim.nix
   ./services/mail/freepops.nix
   ./services/mail/mail.nix
   ./services/mail/mlmmj.nix
@@ -227,6 +228,7 @@
   ./services/network-filesystems/rsyncd.nix
   ./services/network-filesystems/samba.nix
   ./services/network-filesystems/diod.nix
+  ./services/network-filesystems/u9fs.nix
   ./services/network-filesystems/yandex-disk.nix
   ./services/networking/amuled.nix
   ./services/networking/atftpd.nix
@@ -315,6 +317,7 @@
   ./services/scheduling/chronos.nix
   ./services/scheduling/cron.nix
   ./services/scheduling/fcron.nix
+  ./services/scheduling/marathon.nix
   ./services/search/elasticsearch.nix
   ./services/search/solr.nix
   ./services/security/clamav.nix
@@ -356,6 +359,7 @@
   ./services/x11/display-managers/gdm.nix
   ./services/x11/display-managers/kdm.nix
   ./services/x11/display-managers/lightdm.nix
+  ./services/x11/display-managers/sddm.nix
   ./services/x11/display-managers/slim.nix
   ./services/x11/hardware/multitouch.nix
   ./services/x11/hardware/synaptics.nix
@@ -426,9 +430,9 @@
   ./virtualisation/docker.nix
   ./virtualisation/libvirtd.nix
   ./virtualisation/lxc.nix
-  #./virtualisation/nova.nix
+  ./virtualisation/amazon-options.nix
   ./virtualisation/openvswitch.nix
   ./virtualisation/parallels-guest.nix
   ./virtualisation/virtualbox-guest.nix
-  #./virtualisation/xen-dom0.nix
+  ./virtualisation/xen-dom0.nix
 ]
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index 4d93d2d35b466..e0379a2c02aff 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -47,7 +47,8 @@ in
         KDEDIRS = [ "" ];
         STRIGI_PLUGIN_PATH = [ "/lib/strigi/" ];
         QT_PLUGIN_PATH = [ "/lib/qt4/plugins" "/lib/kde4/plugins" "/lib/qt5/plugins" ];
-        QML2_IMPORT_PATH = [ "/lib/qml" ];
+        QML_IMPORT_PATH = [ "/lib/qt5/imports" ];
+        QML2_IMPORT_PATH = [ "/lib/qt5/qml" ];
         QTWEBKIT_PLUGIN_PATH = [ "/lib/mozilla/plugins/" ];
         GTK_PATH = [ "/lib/gtk-2.0" "/lib/gtk-3.0" ];
         XDG_CONFIG_DIRS = [ "/etc/xdg" ];
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 796740ea636ac..bd9b897158dc1 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -4,8 +4,19 @@
 
 with lib;
 
-let cfg  = config.programs.ssh;
-    cfgd = config.services.openssh;
+let
+
+  cfg  = config.programs.ssh;
+  cfgd = config.services.openssh;
+
+  askPassword = "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
+
+  askPasswordWrapper = pkgs.writeScript "ssh-askpass-wrapper"
+    ''
+      #! ${pkgs.stdenv.shell} -e
+      export DISPLAY="$(systemctl --user show-environment | ${pkgs.gnused}/bin/sed 's/^DISPLAY=\(.*\)/\1/; t; d')"
+      exec ${askPassword}
+    '';
 
 in
 {
@@ -117,6 +128,11 @@ in
             Restart = "on-failure";
             SuccessExitStatus = "0 2";
           };
+        # Allow ssh-agent to ask for confirmation. This requires the
+        # unit to know about the user's $DISPLAY (via ‘systemctl
+        # import-environment’).
+        environment.SSH_ASKPASS = optionalString config.services.xserver.enable askPasswordWrapper;
+        environment.DISPLAY = "fake"; # required to make ssh-agent start $SSH_ASKPASS
       };
 
     environment.extraInit = optionalString cfg.startAgent
@@ -126,5 +142,10 @@ in
         fi
       '';
 
+    environment.interactiveShellInit = optionalString config.services.xserver.enable
+      ''
+        export SSH_ASKPASS=${askPassword}
+      '';
+
   };
 }
diff --git a/nixos/modules/programs/uim.nix b/nixos/modules/programs/uim.nix
index fc25ba6f9694c..4bf2f9a175716 100644
--- a/nixos/modules/programs/uim.nix
+++ b/nixos/modules/programs/uim.nix
@@ -7,14 +7,16 @@ let
 in
 {
   options = {
+
     uim = {
       enable = mkOption {
         type = types.bool;
         default = false;
         example = true;
-        description = "enable UIM input method";
+        description = "Enable UIM input method";
       };
     };
+
   };
 
   config = mkIf cfg.enable {
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index e070ffc95e433..e60cb5cdb67d2 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -2,6 +2,19 @@
 
 with lib;
 
+let
+
+  caBundle = pkgs.runCommand "ca-bundle.crt"
+    { files =
+        config.security.pki.certificateFiles ++
+        [ (builtins.toFile "extra.crt" (concatStringsSep "\n" config.security.pki.certificates)) ];
+     }
+    ''
+      cat $files > $out
+    '';
+
+in
+
 {
 
   options = {
@@ -42,25 +55,21 @@ with lib;
 
     security.pki.certificateFiles = [ "${pkgs.cacert}/etc/ca-bundle.crt" ];
 
-    environment.etc =
-      [ { source = pkgs.runCommand "ca-bundle.crt"
-          { files =
-              config.security.pki.certificateFiles ++
-              [ (builtins.toFile "extra.crt" (concatStringsSep "\n" config.security.pki.certificates)) ];
-           }
-          ''
-            cat $files > $out
-          '';
-          target = "ssl/certs/ca-bundle.crt";
-        }
-      ];
+    # NixOS canonical location + Debian/Ubuntu/Arch/Gentoo compatibility.
+    environment.etc."ssl/certs/ca-certificates.crt".source = caBundle;
+
+    # Old NixOS compatibility.
+    environment.etc."ssl/certs/ca-bundle.crt".source = caBundle;
+
+    # CentOS/Fedora compatibility.
+    environment.etc."pki/tls/certs/ca-bundle.crt".source = caBundle;
 
     environment.sessionVariables =
-      { SSL_CERT_FILE          = "/etc/ssl/certs/ca-bundle.crt";
+      { SSL_CERT_FILE          = "/etc/ssl/certs/ca-certificates.crt";
         # FIXME: unneeded - remove eventually.
-        OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+        OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
         # FIXME: unneeded - remove eventually.
-        GIT_SSL_CAINFO         = "/etc/ssl/certs/ca-bundle.crt";
+        GIT_SSL_CAINFO         = "/etc/ssl/certs/ca-certificates.crt";
       };
 
   };
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index d0c7fa6ec288f..66eeab7503db3 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -286,10 +286,11 @@ in
 
     systemd.services.grsec-lock = mkIf cfg.config.sysctl {
       description     = "grsecurity sysctl-lock Service";
-      requires        = [ "sysctl.service" ];
+      requires        = [ "systemd-sysctl.service" ];
       wantedBy        = [ "multi-user.target" ];
       serviceConfig.Type = "oneshot";
       serviceConfig.RemainAfterExit = "yes";
+      unitConfig.ConditionPathIsReadWrite = "/proc/sys/kernel/grsecurity/grsec_lock";
       script = ''
         locked=`cat /proc/sys/kernel/grsecurity/grsec_lock`
         if [ "$locked" == "0" ]; then
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 65761865859f1..e81278a95d5c5 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -63,6 +63,14 @@ let
         '';
       };
 
+      oathAuth = mkOption {
+        default = config.security.pam.enableOATH;
+        type = types.bool;
+        description = ''
+          If set, the OATH Toolkit will be used.
+        '';
+      };
+
       sshAgentAuth = mkOption {
         default = false;
         type = types.bool;
@@ -203,9 +211,13 @@ let
           ${optionalString cfg.usbAuth
               "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"}
           ${optionalString cfg.unixAuth
-              "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth"}
+              "auth ${if config.security.pam.enableEcryptfs then "required" else "sufficient"} pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth"}
+          ${optionalString config.security.pam.enableEcryptfs
+              "auth required ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
           ${optionalString cfg.otpwAuth
               "auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"}
+          ${optionalString cfg.oathAuth
+              "auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=5 usersfile=/etc/users.oath"}
           ${optionalString config.users.ldap.enable
               "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"}
           ${optionalString config.krb5.enable ''
@@ -213,9 +225,11 @@ let
             auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass
             auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass
           ''}
-          auth required   pam_deny.so
+          ${optionalString (! config.security.pam.enableEcryptfs) "auth required pam_deny.so"}
 
           # Password management.
+          ${optionalString config.security.pam.enableEcryptfs
+              "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
           password requisite pam_unix.so nullok sha512
           ${optionalString config.users.ldap.enable
               "password sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
@@ -235,12 +249,16 @@ let
               "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022"}
           ${optionalString cfg.updateWtmp
               "session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
+          ${optionalString config.security.pam.enableEcryptfs
+              "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
           ${optionalString config.users.ldap.enable
               "session optional ${pam_ldap}/lib/security/pam_ldap.so"}
           ${optionalString config.krb5.enable
               "session optional ${pam_krb5}/lib/security/pam_krb5.so"}
           ${optionalString cfg.otpwAuth
               "session optional ${pkgs.otpw}/lib/security/pam_otpw.so"}
+          ${optionalString cfg.oathAuth
+              "session optional ${pkgs.oathToolkit}/lib/security/pam_oath.so window=5 usersfile=/etc/users.oath"}
           ${optionalString cfg.startSession
               "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"}
           ${optionalString cfg.forwardXAuth
@@ -338,6 +356,20 @@ in
       '';
     };
 
+    security.pam.enableOATH = mkOption {
+      default = false;
+      description = ''
+        Enable the OATH (one-time password) PAM module.
+      '';
+    };
+
+    security.pam.enableEcryptfs = mkOption {
+      default = false;
+      description = ''
+        Enable eCryptfs PAM module (mounting ecryptfs home directory on login).
+      '';
+    };
+
     users.motd = mkOption {
       default = null;
       example = "Today is Sweetmorn, the 4th day of The Aftermath in the YOLD 3178.";
@@ -357,7 +389,12 @@ in
       [ pkgs.pam ]
       ++ optional config.users.ldap.enable pam_ldap
       ++ optionals config.krb5.enable [pam_krb5 pam_ccreds]
-      ++ optionals config.security.pam.enableOTPW [ pkgs.otpw ];
+      ++ optionals config.security.pam.enableOTPW [ pkgs.otpw ]
+      ++ optionals config.security.pam.enableOATH [ pkgs.oathToolkit ]
+      ++ optionals config.security.pam.enableEcryptfs [ pkgs.ecryptfs ];
+
+    security.setuidPrograms =
+        optionals config.security.pam.enableEcryptfs [ "mount.ecryptfs_private" "umount.ecryptfs_private" ];
 
     environment.etc =
       mapAttrsToList (n: v: makePAMService v) config.security.pam.services;
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index b79052337597e..9abfb41087b71 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -15,6 +15,8 @@ let
     state_file          "${cfg.dataDir}/state"
     sticker_file        "${cfg.dataDir}/sticker.sql"
     log_file            "syslog"
+    user                "${cfg.user}"
+    group               "${cfg.group}"
     ${if cfg.network.host != "any" then
    "bind_to_address     ${cfg.network.host}" else ""}
     ${if cfg.network.port != 6600 then
@@ -40,8 +42,7 @@ in {
       musicDirectory = mkOption {
         default = "${cfg.dataDir}/music";
         description = ''
-          Extra configuration added to the end of MPD's
-          configuration file, mpd.conf.
+          The directory where mpd reads music from.
         '';
       };
 
@@ -62,6 +63,16 @@ in {
         '';
       };
 
+      user = mkOption {
+        default = "mpd";
+        description = "User account under which MPD runs.";
+      };
+
+      group = mkOption {
+        default = "mpd";
+        description = "Group account under which MPD runs.";
+      };
+
       network = {
 
         host = mkOption {
@@ -96,7 +107,7 @@ in {
       description = "Music Player Daemon";
       wantedBy = [ "multi-user.target" ];
       path = [ pkgs.mpd ];
-      preStart = "mkdir -p ${cfg.dataDir} && chown -R mpd:mpd  ${cfg.dataDir}";
+      preStart = "mkdir -p ${cfg.dataDir} && chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}";
       script = "exec mpd --no-daemon ${mpdConf}";
       serviceConfig = {
         User = "mpd";
@@ -104,16 +115,18 @@ in {
       };
     };
 
-    users.extraUsers.mpd = {
+    users.extraUsers = optionalAttrs (cfg.user == "mpd") (singleton {
       inherit uid;
-      group = "mpd";
+      name = "mpd";
+      group = cfg.group;
       extraGroups = [ "audio" ];
       description = "Music Player Daemon user";
       home = "${cfg.dataDir}";
-    };
-
-    users.extraGroups.mpd.gid = gid;
+    });
 
+    users.extraGroups = optionalAttrs (cfg.group == "mpd") (singleton {
+      gid = gid;
+    });
   };
 
 }
diff --git a/nixos/modules/services/databases/couchdb.nix b/nixos/modules/services/databases/couchdb.nix
index e1fe6be6f6a36..2b1d07c355ef8 100644
--- a/nixos/modules/services/databases/couchdb.nix
+++ b/nixos/modules/services/databases/couchdb.nix
@@ -131,8 +131,8 @@ in {
         type = types.string;
         default = "/var/lib/couchdb/couchdb.ini";
         description = ''
-          Custom configuration file. File needs to be readable and writable
-          from couchdb user/group.
+          Configuration file for persisting runtime changes. File
+          needs to be readable and writable from couchdb user/group.
         '';
       };
 
@@ -157,12 +157,15 @@ in {
         mkdir -p ${cfg.databaseDir};
         mkdir -p ${cfg.viewIndexDir};
         touch ${cfg.configFile}
+        touch -a ${cfg.logFile}
 
         if [ "$(id -u)" = 0 ]; then
-          chown ${cfg.user}:${cfg.group} ${cfg.uriFile}
+          chown ${cfg.user}:${cfg.group} `dirname ${cfg.uriFile}`;
+          (-f ${cfg.uriFile} && chown ${cfg.user}:${cfg.group} ${cfg.uriFile}) || true
           chown ${cfg.user}:${cfg.group} ${cfg.databaseDir}
           chown ${cfg.user}:${cfg.group} ${cfg.viewIndexDir}
           chown ${cfg.user}:${cfg.group} ${cfg.configFile}
+          chown ${cfg.user}:${cfg.group} ${cfg.logFile}
         fi
         '';
 
diff --git a/nixos/modules/services/databases/mongodb.nix b/nixos/modules/services/databases/mongodb.nix
index 02e44ad887049..14ffdad9217d2 100644
--- a/nixos/modules/services/databases/mongodb.nix
+++ b/nixos/modules/services/databases/mongodb.nix
@@ -120,6 +120,7 @@ in
         };
 
         preStart = ''
+          rm ${cfg.dbpath}/mongod.lock || true
           if ! test -e ${cfg.dbpath}; then
               install -d -m0700 -o ${cfg.user} ${cfg.dbpath}
           fi
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index b91c389e90a2d..f2612d0b43b94 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -201,7 +201,7 @@ in
     environment.systemPackages = [ cfg.package ];
 
     systemd.services.redis_init =
-      { description = "Redis server initialisation";
+      { description = "Redis Server Initialisation";
 
         wantedBy = [ "redis.service" ];
         before = [ "redis.service" ];
@@ -216,7 +216,7 @@ in
       };
 
     systemd.services.redis =
-      { description = "Redis server";
+      { description = "Redis Server";
 
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
diff --git a/nixos/modules/services/mail/exim.nix b/nixos/modules/services/mail/exim.nix
new file mode 100644
index 0000000000000..e0890d96a88bb
--- /dev/null
+++ b/nixos/modules/services/mail/exim.nix
@@ -0,0 +1,111 @@
+{ config, lib, pkgs, ... }:
+
+let
+  inherit (lib) mkIf mkOption singleton types;
+  inherit (pkgs) coreutils exim;
+  cfg = config.services.exim;
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.exim = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the Exim mail transfer agent.";
+      };
+
+      config = mkOption {
+        type = types.string;
+        default = "";
+        description = ''
+          Verbatim Exim configuration.  This should not contain exim_user,
+          exim_group, exim_path, or spool_directory.
+        '';
+      };
+
+      user = mkOption {
+        type = types.string;
+        default = "exim";
+        description = ''
+          User to use when no root privileges are required.
+          In particular, this applies when receiving messages and when doing
+          remote deliveries.  (Local deliveries run as various non-root users,
+          typically as the owner of a local mailbox.) Specifying this value
+          as root is not supported.
+        '';
+      };
+
+      group = mkOption {
+        type = types.string;
+        default = "exim";
+        description = ''
+          Group to use when no root privileges are required.
+        '';
+      };
+
+      spoolDir = mkOption {
+        type = types.string;
+        default = "/var/spool/exim";
+        description = ''
+          Location of the spool directory of exim.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment = {
+      etc."exim.conf".text = ''
+        exim_user = ${cfg.user}
+        exim_group = ${cfg.group}
+        exim_path = /var/setuid-wrappers/exim
+        spool_directory = ${cfg.spoolDir}
+        ${cfg.config}
+      '';
+      systemPackages = [ exim ];
+    };
+
+    users.extraUsers = singleton {
+      name = cfg.user;
+      description = "Exim mail transfer agent user";
+      uid = config.ids.uids.exim;
+      group = cfg.group;
+    };
+
+    users.extraGroups = singleton {
+      name = cfg.group;
+      gid = config.ids.gids.exim;
+    };
+
+    security.setuidPrograms = [ "exim" ];
+
+    systemd.services.exim = {
+      description = "Exim Mail Daemon";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart   = "${exim}/bin/exim -bdf -q30m";
+        ExecReload  = "${coreutils}/bin/kill -HUP $MAINPID";
+      };
+      preStart = ''
+        if ! test -d ${cfg.spoolDir}; then
+          ${coreutils}/bin/mkdir -p ${cfg.spoolDir}
+          ${coreutils}/bin/chown ${cfg.user}:${cfg.group} ${cfg.spoolDir}
+        fi
+      '';
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix
index 219c7ed958749..48bb9e4293e79 100644
--- a/nixos/modules/services/misc/disnix.nix
+++ b/nixos/modules/services/misc/disnix.nix
@@ -132,7 +132,7 @@ in
 
           restartIfChanged = false;
           
-          path = [ pkgs.nix pkgs.disnix dysnomia ];
+          path = [ pkgs.nix pkgs.disnix dysnomia "/run/current-system/sw" ];
           
           environment = {
             HOME = "/root";
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index e2548864af5bb..2da84c031a789 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -20,6 +20,8 @@ let
       extraGroups = [ "nixbld" ];
     };
 
+  nixbldUsers = map makeNixBuildUser (range 1 cfg.nrBuildUsers);
+
   nixConf =
     let
       # If we're using a chroot for builds, then provide /bin/sh in
@@ -41,6 +43,10 @@ let
         build-chroot-dirs = ${toString cfg.chrootDirs} /bin/sh=${sh} $(echo $extraPaths)
         binary-caches = ${toString cfg.binaryCaches}
         trusted-binary-caches = ${toString cfg.trustedBinaryCaches}
+        binary-cache-public-keys = ${toString cfg.binaryCachePublicKeys}
+        ${optionalString cfg.requireSignedBinaryCaches ''
+          signed-binary-caches = *
+        ''}
         $extraOptions
         END
       '';
@@ -67,12 +73,12 @@ in
         type = types.int;
         default = 1;
         example = 64;
-        description = "
+        description = ''
           This option defines the maximum number of jobs that Nix will try
           to build in parallel.  The default is 1.  You should generally
           set it to the number of CPUs in your system (e.g., 2 on an Athlon
           64 X2).
-        ";
+        '';
       };
 
       buildCores = mkOption {
@@ -204,7 +210,6 @@ in
 
       nrBuildUsers = mkOption {
         type = types.int;
-        default = 10;
         description = ''
           Number of <literal>nixbld</literal> user accounts created to
           perform secure concurrent builds.  If you receive an error
@@ -245,6 +250,33 @@ in
         '';
       };
 
+      requireSignedBinaryCaches = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If enabled, Nix will only download binaries from binary
+          caches if they are cryptographically signed with any of the
+          keys listed in
+          <option>nix.binaryCachePublicKeys</option>. If disabled (the
+          default), signatures are neither required nor checked, so
+          it's strongly recommended that you use only trustworthy
+          caches and https to prevent man-in-the-middle attacks.
+        '';
+      };
+
+      binaryCachePublicKeys = mkOption {
+        type = types.listOf types.str;
+        example = [ "hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=" ];
+        description = ''
+          List of public keys used to sign binary caches. If
+          <option>nix.requireSignedBinaryCaches</option> is enabled,
+          then Nix will use a binary from a binary cache if and only
+          if it is signed by <emphasis>any</emphasis> of the keys
+          listed here. By default, only the key for
+          <uri>cache.nixos.org</uri> is included.
+        '';
+      };
+
     };
 
   };
@@ -254,6 +286,8 @@ in
 
   config = {
 
+    nix.binaryCachePublicKeys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
+
     environment.etc."nix/nix.conf".source = nixConf;
 
     # List of machines for distributed Nix builds in the format
@@ -323,7 +357,11 @@ in
         fi
       '';
 
-    users.extraUsers = map makeNixBuildUser (range 1 cfg.nrBuildUsers);
+    nix.nrBuildUsers = mkDefault (lib.max 10 cfg.maxJobs);
+
+    users.extraUsers = nixbldUsers;
+
+    services.xserver.displayManager.hiddenUsers = map ({ name, ... }: name) nixbldUsers;
 
     system.activationScripts.nix = stringAfter [ "etc" "users" ]
       ''
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 8c79bf663d15d..d6babb8e9a51d 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -27,7 +27,7 @@ let
       [ global ]
       security = ${cfg.securityType}
       passwd program = /var/setuid-wrappers/passwd %u
-      pam password change = ${toString cfg.syncPasswordsByPam}
+      pam password change = ${if cfg.syncPasswordsByPam then "yes" else "no"}
       invalid users = ${toString cfg.invalidUsers}
 
       ${cfg.extraConfig}
diff --git a/nixos/modules/services/network-filesystems/u9fs.nix b/nixos/modules/services/network-filesystems/u9fs.nix
new file mode 100644
index 0000000000000..648097274641c
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/u9fs.nix
@@ -0,0 +1,75 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.u9fs;
+in
+{
+
+  options = {
+
+    services.u9fs = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to run the u9fs 9P server for Unix.";
+      };
+
+      listenStreams = mkOption {
+        type = types.listOf types.str;
+        default = [ "564" ];
+        example = [ "192.168.16.1:564" ];
+        description = ''
+          Sockets to listen for clients on.
+          See <command>man 5 systemd.socket</command> for socket syntax.
+        '';
+      };
+
+      extraArgs = mkOption {
+        type = types.str;
+        default = "";
+        example = "-a none -u nobody";
+        description =
+          ''
+            Extra arguments to pass on invocation,
+            see <command>man 4 u9fs</command>
+          '';
+      };
+
+      fsroot = mkOption {
+        type = types.path;
+        default = "/";
+        example = "/srv";
+        description = "File system root to serve to clients.";
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd = {
+      sockets.u9fs = {
+        description = "U9fs Listening Socket";
+        wantedBy = [ "sockets.target" ];
+        inherit (cfg) listenStreams;
+        socketConfig.Accept = "yes";
+      };
+      services."u9fs@" = {
+        description = "9P Protocol Server";
+        reloadIfChanged = true;
+        requires = [ "u9fs.socket" ];
+        serviceConfig =
+          { ExecStart = "-${pkgs.u9fs}/bin/u9fs ${cfg.extraArgs} ${cfg.fsroot}";
+            StandardInput = "socket";
+            StandardError = "journal";
+          };
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index 3ae010e810704..5308fd9950855 100644
--- a/nixos/modules/services/networking/consul.nix
+++ b/nixos/modules/services/networking/consul.nix
@@ -178,7 +178,7 @@ in
         ExecReload = "${pkgs.consul}/bin/consul reload";
         PermissionsStartOnly = true;
         User = if cfg.dropPrivileges then "consul" else null;
-        TimeoutStartSec = "${toString (20 + (3 * cfg.joinRetries))}s";
+        TimeoutStartSec = "0";
       } // (optionalAttrs (cfg.leaveOnStop) {
         ExecStop = "${pkgs.consul}/bin/consul leave";
       });
@@ -209,13 +209,14 @@ in
           echo "$ADDR"
         }
         echo "{" > /etc/consul-addrs.json
+        delim=" "
       ''
       + concatStrings (flip mapAttrsToList cfg.interface (name: i:
         optionalString (i != null) ''
-          echo "    \"${name}_addr\": \"$(getAddr "${i}")\"," >> /etc/consul-addrs.json
+          echo "$delim \"${name}_addr\": \"$(getAddr "${i}")\"" >> /etc/consul-addrs.json
+          delim=","
         ''))
       + ''
-        echo "    \"\": \"\"" >> /etc/consul-addrs.json
         echo "}" >> /etc/consul-addrs.json
       '';
       postStart = ''
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 0430d31b99a72..8552395fdb16d 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -184,7 +184,7 @@ in
         }
       ];
 
-    powerManagement.resumeCommands =
+    powerManagement.resumeCommands = mkIf config.systemd.services.dhcpcd.enable
       ''
         # Tell dhcpcd to rebind its interfaces if it's running.
         ${config.systemd.package}/bin/systemctl reload dhcpcd.service
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index d1b5fbedfa6fe..5cc33f35adb2a 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -88,7 +88,12 @@ in
     security.apparmor.profiles = mkIf apparmorEnabled [
       (pkgs.writeText "apparmor-dnscrypt-proxy" ''
 
-        ${dnscrypt-proxy}/sbin/dnscrypt-proxy {
+        ${dnscrypt-proxy}/bin/dnscrypt-proxy {
+          network inet stream,
+          network inet6 stream,
+          network inet dgram,
+          network inet6 dgram,
+
           capability ipc_lock,
           capability net_bind_service,
           capability net_admin,
@@ -126,7 +131,7 @@ in
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
         Type = "forking";
-        ExecStart = "${dnscrypt-proxy}/sbin/dnscrypt-proxy ${toString daemonArgs}";
+        ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
       };
     };
 
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index fbb211911f1ce..7ddabf73106e0 100644
--- a/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixos/modules/services/networking/dnsmasq.nix
@@ -82,7 +82,7 @@ in
 
     systemd.services.dnsmasq = {
         description = "dnsmasq daemon";
-        after = [ "network.target" "systemd-resolved.conf" ];
+        after = [ "network.target" "systemd-resolved.service" ];
         wantedBy = [ "multi-user.target" ];
         path = [ dnsmasq ];
         preStart = ''
diff --git a/nixos/modules/services/networking/haproxy.nix b/nixos/modules/services/networking/haproxy.nix
index c2e2c2d7a4181..887ea79c34b17 100644
--- a/nixos/modules/services/networking/haproxy.nix
+++ b/nixos/modules/services/networking/haproxy.nix
@@ -9,13 +9,16 @@ with lib;
     services.haproxy = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
-        description = "
-          Enable the HAProxy.
-        ";
+        description = ''
+          Whether to enable HAProxy, the reliable, high performance TCP/HTTP
+          load balancer.
+        '';
       };
 
       config = mkOption {
+        type = types.lines;
         default =
           ''
           global
@@ -51,9 +54,10 @@ with lib;
             stats refresh 5s
             stats realm Haproxy statistics
           '';
-        description = "
-          Default configuration.
-        ";
+        description = ''
+          Contents of the HAProxy configuration file,
+          <filename>haproxy.conf</filename>.
+        '';
       };
 
     };
@@ -68,10 +72,10 @@ with lib;
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
         Type = "forking";
-        PIDFile = "/var/run/haproxy.pid";
+        PIDFile = "/run/haproxy.pid";
         ExecStartPre = "${pkgs.haproxy}/sbin/haproxy -c -q -f ${haproxyCfg}";
-        ExecStart = "${pkgs.haproxy}/sbin/haproxy -D -f ${haproxyCfg} -p /var/run/haproxy.pid";
-        ExecReload = "-${pkgs.bash}/bin/bash -c \"exec ${pkgs.haproxy}/sbin/haproxy -D -f ${haproxyCfg} -p /var/run/haproxy.pid -sf $MAINPID\"";
+        ExecStart = "${pkgs.haproxy}/sbin/haproxy -D -f ${haproxyCfg} -p /run/haproxy.pid";
+        ExecReload = "-${pkgs.bash}/bin/bash -c \"exec ${pkgs.haproxy}/sbin/haproxy -D -f ${haproxyCfg} -p /run/haproxy.pid -sf $MAINPID\"";
       };
     };
 
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index f72c7fb39d6c5..3a64d3f09e025 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -71,6 +71,13 @@ let
     ${coreutils}/bin/rm -f $tmp $tmp.ns
   '';
 
+  # pre-up and pre-down hooks were added in NM 0.9.10, but we still use 0.9.0
+  dispatcherTypesSubdirMap = {
+    "basic" = "";
+    /*"pre-up" = "pre-up.d/";
+    "pre-down" = "pre-down.d/";*/
+  };
+
 in {
 
   ###### interface
@@ -118,6 +125,30 @@ in {
         '';
       };
 
+      dispatcherScripts = mkOption {
+        type = types.listOf (types.submodule {
+          options = {
+            source = mkOption {
+              type = types.str;
+              description = ''
+                A script source.
+              '';
+            };
+
+            type = mkOption {
+              type = types.enum (attrNames dispatcherTypesSubdirMap); 
+              default = "basic";
+              description = ''
+                Dispatcher hook type. Only basic hooks are currently available.
+              '';
+            };
+          };
+        });
+        default = [];
+        description = ''
+          A list of scripts which will be executed in response to  network  events.
+        '';
+      };
     };
   };
 
@@ -155,7 +186,11 @@ in {
     ] ++ optional (cfg.appendNameservers == [] || cfg.insertNameservers == [])
            { source = overrideNameserversScript;
              target = "NetworkManager/dispatcher.d/02overridedns";
-           };
+           }
+      ++ lib.imap (i: s: {
+        text = s.source;
+        target = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}";
+      }) cfg.dispatcherScripts;
 
     environment.systemPackages = cfg.packages ++ [
         networkmanager_openvpn
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index c0ad9e17c4130..b11f996c63cf9 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -195,12 +195,14 @@ in
         default =
           [ { path = "/etc/ssh/ssh_host_dsa_key";
               type = "dsa";
-              bits = 1024;
             }
             { path = "/etc/ssh/ssh_host_ecdsa_key";
               type = "ecdsa";
               bits = 521;
             }
+            { path = "/etc/ssh/ssh_host_ed25519_key";
+              type = "ed25519";
+            }
           ];
         description = ''
           NixOS can automatically generate SSH host keys.  This option
@@ -323,7 +325,7 @@ in
 
                 ${flip concatMapStrings cfg.hostKeys (k: ''
                   if ! [ -f "${k.path}" ]; then
-                      ssh-keygen -t "${k.type}" -b "${toString k.bits}" -f "${k.path}" -N ""
+                      ssh-keygen -t "${k.type}" ${if k ? bits then "-b ${toString k.bits}" else ""} -f "${k.path}" -N ""
                   fi
                 '')}
               '';
@@ -379,6 +381,8 @@ 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/vsftpd.nix b/nixos/modules/services/networking/vsftpd.nix
index 62b6027c01208..447149552f486 100644
--- a/nixos/modules/services/networking/vsftpd.nix
+++ b/nixos/modules/services/networking/vsftpd.nix
@@ -68,6 +68,11 @@ let
       Only applies if <option>sslEnable</option> is true. Non anonymous (local) users
       must use a secure SSL connection for sending/receiving data on data connection.
     '')
+    (yesNoOption "portPromiscuous" "port_promiscuous" false ''
+      Set to YES if you want to disable the PORT security check that ensures that
+      outgoing data connections can only connect to the client. Only enable if you
+      know what you are doing!
+    '')
     (yesNoOption "ssl_tlsv1" "ssl_tlsv1" true  '' '')
     (yesNoOption "ssl_sslv2" "ssl_sslv2" false '' '')
     (yesNoOption "ssl_sslv3" "ssl_sslv3" false '' '')
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index 771eeecd772b7..e2d34ea079c51 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -31,12 +31,14 @@ in
         description = ''
           Whether to start <command>wpa_supplicant</command> to scan for
           and associate with wireless networks.  Note: NixOS currently
-          does not generate <command>wpa_supplicant</command>'s
+          does not manage <command>wpa_supplicant</command>'s
           configuration file, <filename>${configFile}</filename>.  You
           should edit this file yourself to define wireless networks,
           WPA keys and so on (see
           <citerefentry><refentrytitle>wpa_supplicant.conf</refentrytitle>
-          <manvolnum>5</manvolnum></citerefentry>).
+          <manvolnum>5</manvolnum></citerefentry>), or use
+          networking.wireless.userControlled.* to allow users to add entries
+          through <command>wpa_cli</command> and <command>wpa_gui</command>.
         '';
       };
 
@@ -62,7 +64,9 @@ in
           default = false;
           description = ''
             Allow normal users to control wpa_supplicant through wpa_gui or wpa_cli.
-            This is useful for laptop users that switch networks a lot.
+            This is useful for laptop users that switch networks a lot and don't want
+            to depend on a large package such as NetworkManager just to pick nearby
+            access points.
 
             When you want to use this, make sure ${configFile} doesn't exist.
             It will be created for you.
diff --git a/nixos/modules/services/scheduling/chronos.nix b/nixos/modules/services/scheduling/chronos.nix
index 277cdd6328096..f36b886a744b0 100644
--- a/nixos/modules/services/scheduling/chronos.nix
+++ b/nixos/modules/services/scheduling/chronos.nix
@@ -18,7 +18,7 @@ in {
 
     httpPort = mkOption {
       description = "Chronos listening port";
-      default = 8080;
+      default = 4400;
       type = types.int;
     };
 
diff --git a/nixos/modules/services/scheduling/marathon.nix b/nixos/modules/services/scheduling/marathon.nix
new file mode 100644
index 0000000000000..8513d1174c388
--- /dev/null
+++ b/nixos/modules/services/scheduling/marathon.nix
@@ -0,0 +1,58 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.marathon;
+
+in {
+
+  ###### interface
+
+  options.services.marathon = {
+    enable = mkOption {
+      description = "Whether to enable the marathon mesos framework.";
+      default = false;
+      type = types.uniq types.bool;
+    };
+
+    httpPort = mkOption {
+      description = "Marathon listening port";
+      default = 8080;
+      type = types.int;
+    };
+
+    master = mkOption {
+      description = "Marathon mesos master zookeeper address";
+      default = "zk://${head cfg.zookeeperHosts}/mesos";
+      type = types.str;
+    };
+
+    zookeeperHosts = mkOption {
+      description = "Marathon mesos zookepper addresses";
+      default = [ "localhost:2181" ];
+      type = types.listOf types.str;
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.marathon = {
+      description = "Marathon Service";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" "zookeeper.service" "mesos-master.service" "mesos-slave.service" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.marathon}/bin/marathon --master ${cfg.master} --zk zk://${head cfg.zookeeperHosts}/marathon";
+        User = "marathon";
+      };
+    };
+
+    users.extraUsers.marathon = {
+      uid = config.ids.uids.marathon;
+      description = "Marathon mesos framework user";
+    };
+  };
+}
diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix
index c40f41e07d4fc..6288b1b3ba863 100644
--- a/nixos/modules/services/security/fail2ban.nix
+++ b/nixos/modules/services/security/fail2ban.nix
@@ -95,7 +95,7 @@ in
     environment.etc."fail2ban/filter.d".source = "${pkgs.fail2ban}/etc/fail2ban/filter.d/*.conf";
 
     systemd.services.fail2ban =
-      { description = "Fail2ban intrusion prevention system";
+      { description = "Fail2ban Intrusion Prevention System";
 
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
index 1b38ea3b679be..135113b3ceb14 100644
--- a/nixos/modules/services/torrent/transmission.nix
+++ b/nixos/modules/services/torrent/transmission.nix
@@ -9,28 +9,16 @@ let
   homeDir = "/var/lib/transmission";
   downloadDir = "${homeDir}/Downloads";
   incompleteDir = "${homeDir}/.incomplete";
+  
   settingsDir = "${homeDir}/.config/transmission-daemon";
-  settingsFile = "${settingsDir}/settings.json";
+  settingsFile = pkgs.writeText "settings.json" (builtins.toJSON fullSettings);
 
   # 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"
     else if isInt x then toString x
-    else toString ''\"${x}\"'';
-
-  # All lines in settings.json end with a ',' (comma), except for the last
-  # line. This is standard JSON. But a comma can also appear *inside* some
-  # fields, notably the "rpc-whitelist" field. This is difficult to handle in
-  # sed so we simply ignore it and say that if you want to change the option at
-  # the last line of settings.json, you have to do it manually. At this time of
-  # writing, the last option is "utp-enable":true.
-  attrsToSedArgs = as:
-    concatStrings (concatLists (mapAttrsToList (name: value:
-      #map (x: '' -e 's=\(\"${name}\":\)[^,]*\(.*\)=\1 ${toOption x}\2=' '') # breaks if comma inside value field
-      map (x: '' -e 's=\(\"${name}\":\).*=\1 ${toOption x},=' '') # always append ',' (breaks last line in settings.json)
-        (if isList value then value else [value]))
-        as));
+    else toString ''"${x}"'';
 
   # for users in group "transmission" to have access to torrents
   fullSettings = cfg.settings // { umask = 2; };
@@ -73,7 +61,7 @@ in
           boolean values must not.
 
           See https://trac.transmissionbt.com/wiki/EditConfigFiles for
-          documentation and/or look at ${settingsFile}.
+          documentation.
         '';
       };
 
@@ -95,7 +83,7 @@ in
       # 1) Only the "transmission" user and group have access to torrents.
       # 2) Optionally update/force specific fields into the configuration file.
       serviceConfig.ExecStartPre = ''
-          ${pkgs.stdenv.shell} -c "chmod 770 ${homeDir} && mkdir -p ${settingsDir} ${downloadDir} ${incompleteDir} && ${pkgs.transmission}/bin/transmission-daemon -d |& sed ${attrsToSedArgs fullSettings} > ${settingsFile}.tmp && mv ${settingsFile}.tmp ${settingsFile}"
+          ${pkgs.stdenv.shell} -c "chmod 770 ${homeDir} && mkdir -p ${settingsDir} ${downloadDir} ${incompleteDir} && rm -f ${settingsDir}/settings.json && cp -f ${settingsFile} ${settingsDir}/settings.json"
       '';
       serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.port}";
       serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 6a830827fd783..2b5cba68d457a 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -171,6 +171,9 @@ let
 
     SSLRandomSeed startup builtin
     SSLRandomSeed connect builtin
+
+    SSLProtocol All -SSLv2 -SSLv3
+    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!EXP
   '';
 
 
diff --git a/nixos/modules/services/web-servers/fcgiwrap.nix b/nixos/modules/services/web-servers/fcgiwrap.nix
index 7e91e7b60eef3..2c5e433003c8c 100644
--- a/nixos/modules/services/web-servers/fcgiwrap.nix
+++ b/nixos/modules/services/web-servers/fcgiwrap.nix
@@ -4,7 +4,6 @@ with lib;
 
 let
   cfg = config.services.fcgiwrap;
-
 in {
 
   options = {
@@ -21,29 +20,53 @@ in {
         description = "Number of processes to prefork.";
       };
 
-      bindSocket = mkOption {
-        type = types.string;
-        default = "unix:/run/fcgiwrap.sock";
-        description = ''
-          Socket to bind to. Valid socket URLs are:
-            unix:/path/to/socket for Unix sockets
-            tcp:dot.ted.qu.ad:port for IPv4 sockets
-            tcp6:[ipv6_addr]:port for IPv6 sockets
-        '';
+      socketType = mkOption {
+        type = types.addCheck types.str (t: t == "unix" || t == "tcp" || t == "tcp6");
+        default = "unix";
+        description = "Socket type: 'unix', 'tcp' or 'tcp6'.";
+      };
+
+      socketAddress = mkOption {
+        type = types.str;
+        default = "/run/fcgiwrap.sock";
+        example = "1.2.3.4:5678";
+        description = "Socket address. In case of a UNIX socket, this should be its filesystem path.";
+      };
+
+      user = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "User permissions for the socket.";
+      };
+
+      group = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "Group permissions for the socket.";
       };
     };
   };
 
   config = mkIf cfg.enable {
-
     systemd.services.fcgiwrap = {
       after = [ "nss-user-lookup.target" ];
-      wantedBy = [ "multi-user.target" ];
+      wantedBy = optional (cfg.socketType != "unix") "multi-user.target";
 
       serviceConfig = {
-        ExecStart = "${pkgs.fcgiwrap}/sbin/fcgiwrap -c ${builtins.toString cfg.preforkProcesses} -s ${cfg.bindSocket}";
-      };
+        ExecStart = "${pkgs.fcgiwrap}/sbin/fcgiwrap -c ${builtins.toString cfg.preforkProcesses} ${
+          if (cfg.socketType != "unix") then "-s ${cfg.socketType}:${cfg.socketAddress}" else ""
+        }";
+      } // (if cfg.user != null && cfg.group != null then {
+        User = cfg.user;
+        Group = cfg.group;
+      } else { } );
     };
 
+    systemd.sockets = if (cfg.socketType == "unix") then {
+      fcgiwrap = {
+        wantedBy = [ "sockets.target" ];
+        socketConfig.ListenStream = cfg.socketAddress;
+      };
+    } else { };
   };
 }
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index 6d6479da2a1ff..9c3c65dcfaa75 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -11,12 +11,14 @@ let
   phononBackends = {
     gstreamer = [
       pkgs.phonon_backend_gstreamer
+      pkgs.gst_all.gstreamer
       pkgs.gst_all.gstPluginsBase
       pkgs.gst_all.gstPluginsGood
       pkgs.gst_all.gstPluginsUgly
       pkgs.gst_all.gstPluginsBad
       pkgs.gst_all.gstFfmpeg # for mp3 playback
       pkgs.phonon_qt5_backend_gstreamer
+      pkgs.gst_all_1.gstreamer
       pkgs.gst_all_1.gst-plugins-base
       pkgs.gst_all_1.gst-plugins-good
       pkgs.gst_all_1.gst-plugins-ugly
@@ -33,7 +35,7 @@ let
   phononBackendPackages = flip concatMap cfg.phononBackends
     (name: attrByPath [name] (throw "unknown phonon backend `${name}'") phononBackends);
 
-  kf5 = pkgs.kf5_stable;
+  kf5 = plasma5.kf5;
 
   plasma5 = pkgs.plasma5_stable;
 
@@ -56,8 +58,8 @@ in
         default = ["gstreamer"];
         example = ["gstreamer" "vlc"];
         description = ''
-          Phonon backends to use in KDE. Only the VLC and gstreamer backends are
-          available. The VLC backend is preferred by upstream.
+          Phonon backends to use in KDE. Only the VLC and GStreamer backends are
+          available. The GStreamer backend is preferred by upstream.
         '';
       };
 
@@ -85,26 +87,12 @@ in
       setuid = true;
     };
 
-    environment.systemPackages = with plasma5; with kf5;
-      (builtins.attrValues
-        (removeAttrs plasma5
-          [ "deepOverride" "override" "overrideDerivation"
-            "recurseForDerivations" "scope"
-          ]))
-      ++
-      (builtins.attrValues
-        (removeAttrs kf5
-          [ "deepOverride" "extra-cmake-modules" "mkDerivation" "override"
-            "overrideDerivation" "recurseForDerivations" "scope"
-          ]))
-      ++
+    environment.systemPackages =
       [
         pkgs.qt4 # qtconfig is the only way to set Qt 4 theme
 
         kdeApps.kde-baseapps
         kdeApps.kde-base-artwork
-        kdeApps.kde-workspace
-        kdeApps.kde-runtime
         kdeApps.kmix
         kdeApps.konsole
         kdeApps.oxygen-icons
@@ -113,7 +101,8 @@ in
 
         pkgs.orion # GTK theme, nearly identical to Breeze
       ]
-      ++ (optional config.networking.networkmanager.enable plasma-nm)
+      ++ filter isDerivation (builtins.attrValues plasma5)
+      ++ filter isDerivation (builtins.attrValues kf5)
       ++ phononBackendPackages;
 
     environment.pathsToLink = [ "/share" ];
@@ -136,6 +125,9 @@ in
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
 
+    # Extra UDEV rules used by Solid
+    services.udev.packages = [ pkgs.media-player-info ];
+
     security.pam.services.kde = { allowNullPassword = true; };
 
   };
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 601971d27b69f..c5012dbb5e304 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -89,6 +89,10 @@ let
         ${config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
       ''}
 
+      # Tell systemd about our $DISPLAY. This is needed by the
+      # ssh-agent unit.
+      ${config.systemd.package}/bin/systemctl --user import-environment DISPLAY
+
       # Load X defaults.
       ${xorg.xrdb}/bin/xrdb -merge ${xresourcesXft}
       if test -e ~/.Xresources; then
@@ -204,6 +208,14 @@ in
         description = "Shell commands executed just before the window or desktop manager is started.";
       };
 
+      hiddenUsers = mkOption {
+        type = types.listOf types.str;
+        default = [ "nobody" ];
+        description = ''
+          A list of users which will not be shown in the display manager.
+        '';
+      };
+
       desktopManagerHandlesLidAndPower = mkOption {
         type = types.bool;
         default = true;
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index b3da0cda04a30..a7ebafa28b38a 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -95,15 +95,23 @@ in
 
         auth     required       pam_succeed_if.so uid >= 1000 quiet
         auth     optional       ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so
-        auth     sufficient     pam_unix.so nullok likeauth
-        auth     required       pam_deny.so
+        auth     ${if config.security.pam.enableEcryptfs then "required" else "sufficient"} pam_unix.so nullok likeauth
+        ${optionalString config.security.pam.enableEcryptfs
+          "auth required ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
+
+        ${optionalString (! config.security.pam.enableEcryptfs)
+          "auth     required       pam_deny.so"}
 
         account  sufficient     pam_unix.so
 
         password requisite      pam_unix.so nullok sha512
+        ${optionalString config.security.pam.enableEcryptfs
+          "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
 
         session  required       pam_env.so envfile=${config.system.build.pamEnvironment}
         session  required       pam_unix.so
+        ${optionalString config.security.pam.enableEcryptfs
+          "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
         session  required       pam_loginuid.so
         session  optional       ${pkgs.systemd}/lib/security/pam_systemd.so
         session  optional       ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start
@@ -115,15 +123,22 @@ in
 
         auth     required       pam_succeed_if.so uid >= 1000 quiet
         auth     optional       ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so
-        auth     sufficient     pam_unix.so nullok likeauth
-        auth     required       pam_deny.so 
+        auth     ${if config.security.pam.enableEcryptfs then "required" else "sufficient"} pam_unix.so nullok likeauth
+        ${optionalString config.security.pam.enableEcryptfs
+          "auth required ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
+        ${optionalString (! config.security.pam.enableEcryptfs)
+          "auth     required       pam_deny.so"}
 
         account  sufficient     pam_unix.so
         
         password requisite      pam_unix.so nullok sha512
+        ${optionalString config.security.pam.enableEcryptfs
+          "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
 
         session  required       pam_env.so envfile=${config.system.build.pamEnvironment}
         session  required       pam_unix.so
+        ${optionalString config.security.pam.enableEcryptfs
+          "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
         session  required       pam_loginuid.so
         session  optional       ${pkgs.systemd}/lib/security/pam_systemd.so
         session  optional       ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start
diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix
index 42eaacfe84afd..d0b69c5452c2c 100644
--- a/nixos/modules/services/x11/display-managers/kdm.nix
+++ b/nixos/modules/services/x11/display-managers/kdm.nix
@@ -38,7 +38,7 @@ let
       ''} 
 
       [X-*-Greeter]
-      HiddenUsers=root,nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10
+      HiddenUsers=root,${concatStringsSep "," dmcfg.hiddenUsers}
       PluginsLogin=${kdebase_workspace}/lib/kde4/kgreet_classic.so
       ${optionalString (cfg.themeDirectory != null)
       ''
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 98e3fd6d6a5d1..e7ddb7ff254dc 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -18,6 +18,9 @@ let
       exec ${dmcfg.xserverBin} ${dmcfg.xserverArgs}
     '';
 
+  theme = pkgs.gnome3.gnome_themes_standard;
+  icons = pkgs.gnome3.gnome_icon_theme;
+
   # The default greeter provided with this expression is the GTK greeter.
   # Again, we need a few things in the environment for the greeter to run with
   # fonts/icons.
@@ -26,19 +29,16 @@ let
     buildInputs = [ pkgs.makeWrapper ];
 
     buildCommand = ''
-      mkdir -p $out/gtk-3.0/
-
-      # This wrapper ensures that we actually get ?? (fonts should be OK now)
+      # This wrapper ensures that we actually get themes
       makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \
         $out/greeter \
-        --set XDG_DATA_DIRS ${pkgs.gnome2.gnome_icon_theme}/share \
-        --set XDG_CONFIG_HOME $out/
-
-      # We need this to ensure that it actually tries to find icons from gnome-icon-theme
-      cat - > $out/gtk-3.0/settings.ini << EOF
-      [Settings]
-      gtk-icon-theme-name=gnome
-      EOF
+        --prefix PATH : "${pkgs.glibc}/bin" \
+        --set GDK_PIXBUF_MODULE_FILE "$(find ${theme} -name loaders.cache)" \
+        --set GTK_PATH "${theme}:${pkgs.gtk3}" \
+        --set GTK_EXE_PREFIX "${theme}" \
+        --set GTK_DATA_PREFIX "${theme}" \
+        --set XDG_DATA_DIRS "${theme}/share:${icons}/share" \
+        --set XDG_CONFIG_HOME "${theme}/share"
 
       cat - > $out/lightdm-gtk-greeter.desktop << EOF
       [Desktop Entry]
@@ -50,6 +50,14 @@ let
     '';
   };
 
+  usersConf = writeText "users.conf"
+    ''
+      [UserList]
+      minimum-uid=500
+      hidden-users=${concatStringsSep " " dmcfg.hiddenUsers}
+      hidden-shells=/run/current-system/sw/sbin/nologin
+    '';
+
   lightdmConf = writeText "lightdm.conf"
     ''
       [LightDM]
@@ -63,10 +71,19 @@ let
       greeter-session = ${cfg.greeter.name}
     '';
 
+  gtkGreeterConf = writeText "lightdm-gtk-greeter.conf"
+    ''
+    [greeter]
+    theme-name = Adwaita
+    icon-theme-name = Adwaita
+    background = ${cfg.background}
+    '';
+
 in
 {
   options = {
     services.xserver.displayManager.lightdm = {
+
       enable = mkOption {
         default = false;
         description = ''
@@ -84,6 +101,14 @@ in
           package = wrappedGtkGreeter;
         };
       };
+
+      background = mkOption {
+        default = "${pkgs.nixos-artwork}/gnome/Gnome_Dark.png";
+        description = ''
+          The background image or color to use.
+        '';
+      };
+
     };
   };
 
@@ -97,10 +122,14 @@ in
       # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH
       execCmd = ''
         export PATH=${lightdm}/sbin:$PATH
-        ${lightdm}/sbin/lightdm --log-dir=/var/log --run-dir=/run --config=${lightdmConf}
+        exec ${lightdm}/sbin/lightdm --log-dir=/var/log --run-dir=/run
       '';
     };
 
+    environment.etc."lightdm/lightdm-gtk-greeter.conf".source = gtkGreeterConf;
+    environment.etc."lightdm/lightdm.conf".source = lightdmConf;
+    environment.etc."lightdm/users.conf".source = usersConf;
+
     services.dbus.enable = true;
     services.dbus.packages = [ lightdm ];
 
@@ -109,7 +138,7 @@ in
 
     users.extraUsers.lightdm = {
       createHome = true;
-      home = "/var/lib/lightdm";
+      home = "/var/lib/lightdm-data";
       group = "lightdm";
       uid = config.ids.uids.lightdm;
     };
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
new file mode 100644
index 0000000000000..c14c13b1cba90
--- /dev/null
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -0,0 +1,110 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  xcfg = config.services.xserver;
+  dmcfg = xcfg.displayManager;
+  cfg = dmcfg.sddm;
+  xEnv = config.systemd.services."display-manager".environment;
+
+  xserverWrapper = pkgs.writeScript "xserver-wrapper" ''
+    #!/bin/sh
+    ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)}
+    exec ${dmcfg.xserverBin} ${dmcfg.xserverArgs} "$@"
+  '';
+
+  cfgFile = pkgs.writeText "sddm.conf" ''
+    [General]
+    HaltCommand=${pkgs.systemd}/bin/systemctl poweroff
+    RebootCommand=${pkgs.systemd}/bin/systemctl reboot
+
+    [Theme]
+    Current=${cfg.theme}
+
+    [Users]
+    MaximumUid=${toString config.ids.uids.nixbld}
+    HideUsers=${concatStringsSep "," dmcfg.hiddenUsers}
+    HideShells=/run/current-system/sw/sbin/nologin
+
+    [XDisplay]
+    MinimumVT=${toString xcfg.tty}
+    ServerPath=${xserverWrapper}
+    XephyrPath=${pkgs.xorg.xorgserver}/bin/Xephyr
+    SessionCommand=${dmcfg.session.script}
+    SessionDir=${dmcfg.session.desktops}
+    XauthPath=${pkgs.xorg.xauth}/bin/xauth
+  '';
+
+in
+{
+  options = {
+
+    services.xserver.displayManager.sddm = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable sddm as the display manager.
+        '';
+      };
+
+      theme = mkOption {
+        type = types.str;
+        default = "maui";
+        description = ''
+          Greeter theme to use.
+        '';
+      };
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    services.xserver.displayManager.slim.enable = false;
+
+    services.xserver.displayManager.job = {
+      logsXsession = true;
+
+      #execCmd = "${pkgs.sddm}/bin/sddm";
+      execCmd = "exec ${pkgs.sddm}/bin/sddm";
+    };
+
+    security.pam.services = {
+      sddm = {
+        allowNullPassword = true;
+        startSession = true;
+      };
+
+      sddm-greeter.text = ''
+        auth     required       pam_succeed_if.so audit quiet_success user = sddm
+        auth     optional       pam_permit.so
+
+        account  required       pam_succeed_if.so audit quiet_success user = sddm
+        account  sufficient     pam_unix.so
+
+        password required       pam_deny.so
+
+        session  required       pam_succeed_if.so audit quiet_success user = sddm
+        session  required       pam_env.so envfile=${config.system.build.pamEnvironment}
+        session  optional       ${pkgs.systemd}/lib/security/pam_systemd.so
+        session  optional       pam_keyinit.so force revoke
+        session  optional       pam_permit.so
+      '';
+    };
+
+    users.extraUsers.sddm = {
+      createHome = true;
+      home = "/var/lib/sddm";
+      group = "sddm";
+      uid = config.ids.uids.sddm;
+    };
+
+    environment.etc."sddm.conf".source = cfgFile;
+
+    users.extraGroups.sddm.gid = config.ids.gids.sddm;
+
+  };
+}
diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix
index 7ec32fe83b54d..97cc198137c41 100644
--- a/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixos/modules/services/x11/window-managers/default.nix
@@ -8,12 +8,15 @@ in
 
 {
   imports = [
+    ./afterstep.nix
     ./bspwm.nix
     ./compiz.nix
+    ./fluxbox.nix
     ./herbstluftwm.nix
     ./i3.nix
     ./metacity.nix
     ./openbox.nix
+    ./sawfish.nix
     ./stumpwm.nix
     ./twm.nix
     ./windowmaker.nix
diff --git a/nixos/modules/services/x11/window-managers/sawfish.nix b/nixos/modules/services/x11/window-managers/sawfish.nix
new file mode 100644
index 0000000000000..74a119260208b
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/sawfish.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.sawfish;
+in
+{
+  ###### interface
+  options = {
+    services.xserver.windowManager.sawfish.enable = mkOption {
+      default = false;
+      description = "Enable the Sawfish window manager.";
+    };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "sawfish";
+      start = ''
+        ${pkgs.sawfish}/bin/sawfish &
+        waitPID=$!
+      '';
+    };
+    environment.systemPackages = [ pkgs.sawfish ];
+  };
+}
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index dbe13c022f09e..ce36bac2bdcf8 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -9,19 +9,21 @@ use Cwd 'abs_path';
 
 my $out = "@out@";
 
+# To be robust against interruption, record what units need to be started etc.
 my $startListFile = "/run/systemd/start-list";
 my $restartListFile = "/run/systemd/restart-list";
 my $reloadListFile = "/run/systemd/reload-list";
 
 my $action = shift @ARGV;
 
-if (!defined $action || ($action ne "switch" && $action ne "boot" && $action ne "test")) {
+if (!defined $action || ($action ne "switch" && $action ne "boot" && $action ne "test" && $action ne "dry-activate")) {
     print STDERR <<EOF;
 Usage: $0 [switch|boot|test]
 
-switch: make the configuration the boot default and activate now
-boot:   make the configuration the boot default
-test:   activate the configuration, but don\'t make it the boot default
+switch:       make the configuration the boot default and activate now
+boot:         make the configuration the boot default
+test:         activate the configuration, but don\'t make it the boot default
+dry-activate: show what would be done if this configuration were activated
 EOF
     exit 1;
 }
@@ -56,8 +58,6 @@ EOF
     exit 100;
 }
 
-syslog(LOG_NOTICE, "switching to system configuration $out");
-
 # Ignore SIGHUP so that we're not killed if we're running on (say)
 # virtual console 1 and we restart the "tty1" unit.
 $SIG{PIPE} = "IGNORE";
@@ -116,6 +116,11 @@ sub boolIsTrue {
     return $s eq "yes" || $s eq "true";
 }
 
+sub recordUnit {
+    my ($fn, $unit) = @_;
+    write_file($fn, { append => 1 }, "$unit\n") if $action ne "dry-activate";
+}
+
 # As a fingerprint for determining whether a unit has changed, we use
 # its absolute path. If it has an override file, we append *its*
 # absolute path as well.
@@ -124,9 +129,20 @@ sub fingerprintUnit {
     return abs_path($s) . (-f "${s}.d/overrides.conf" ? " " . abs_path "${s}.d/overrides.conf" : "");
 }
 
-# Stop all services that no longer exist or have changed in the new
-# configuration.
-my (@unitsToStop, @unitsToSkip);
+# Figure out what units need to be stopped, started, restarted or reloaded.
+my (%unitsToStop, %unitsToSkip, %unitsToStart, %unitsToRestart, %unitsToReload);
+
+my %unitsToFilter; # units not shown
+
+$unitsToStart{$_} = 1 foreach
+    split('\n', read_file($startListFile, err_mode => 'quiet') // "");
+
+$unitsToRestart{$_} = 1 foreach
+    split('\n', read_file($restartListFile, err_mode => 'quiet') // "");
+
+$unitsToReload{$_} = 1 foreach
+    split '\n', read_file($reloadListFile, err_mode => 'quiet') // "";
+
 my $activePrev = getActiveUnits;
 while (my ($unit, $state) = each %{$activePrev}) {
     my $baseUnit = $unit;
@@ -141,7 +157,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
 
     if (-e $prevUnitFile && ($state->{state} eq "active" || $state->{state} eq "activating")) {
         if (! -e $newUnitFile || abs_path($newUnitFile) eq "/dev/null") {
-            push @unitsToStop, $unit;
+            $unitsToStop{$unit} = 1;
         }
 
         elsif ($unit =~ /\.target$/) {
@@ -155,7 +171,10 @@ while (my ($unit, $state) = each %{$activePrev}) {
             # should not be the case.  Just ignore it.
             if ($unit ne "suspend.target" && $unit ne "hibernate.target" && $unit ne "hybrid-sleep.target") {
                 unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no")) {
-                    write_file($startListFile, { append => 1 }, "$unit\n");
+                    $unitsToStart{$unit} = 1;
+                    recordUnit($startListFile, $unit);
+                    # Don't spam the user with target units that always get started.
+                    $unitsToFilter{$unit} = 1;
                 }
             }
 
@@ -171,7 +190,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
             # (unless there is a PartOf dependency), so this is just a
             # bookkeeping thing to get systemd to do the right thing.
             if (boolIsTrue($unitInfo->{'X-StopOnReconfiguration'} // "no")) {
-                push @unitsToStop, $unit;
+                $unitsToStop{$unit} = 1;
             }
         }
 
@@ -180,16 +199,18 @@ while (my ($unit, $state) = each %{$activePrev}) {
                 # Do nothing.  These cannot be restarted directly.
             } elsif ($unit =~ /\.mount$/) {
                 # Reload the changed mount unit to force a remount.
-                write_file($reloadListFile, { append => 1 }, "$unit\n");
+                $unitsToReload{$unit} = 1;
+                recordUnit($reloadListFile, $unit);
             } elsif ($unit =~ /\.socket$/ || $unit =~ /\.path$/ || $unit =~ /\.slice$/) {
                 # FIXME: do something?
             } else {
                 my $unitInfo = parseUnit($newUnitFile);
                 if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) {
-                    write_file($reloadListFile, { append => 1 }, "$unit\n");
+                    $unitsToReload{$unit} = 1;
+                    recordUnit($reloadListFile, $unit);
                 }
                 elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") ) {
-                    push @unitsToSkip, $unit;
+                    $unitsToSkip{$unit} = 1;
                 } else {
                     # If this unit is socket-activated, then stop the
                     # socket unit(s) as well, and restart the
@@ -202,8 +223,9 @@ while (my ($unit, $state) = each %{$activePrev}) {
                         }
                         foreach my $socket (@sockets) {
                             if (defined $activePrev->{$socket}) {
-                                push @unitsToStop, $socket;
-                                write_file($startListFile, { append => 1 }, "$socket\n");
+                                $unitsToStop{$unit} = 1;
+                                $unitsToStart{$unit} = 1;
+                                recordUnit($startListFile, $socket);
                                 $socketActivated = 1;
                             }
                         }
@@ -213,7 +235,8 @@ while (my ($unit, $state) = each %{$activePrev}) {
 
                         # This unit should be restarted instead of
                         # stopped and started.
-                        write_file($restartListFile, { append => 1 }, "$unit\n");
+                        $unitsToRestart{$unit} = 1;
+                        recordUnit($restartListFile, $unit);
 
                     } else {
 
@@ -222,10 +245,11 @@ while (my ($unit, $state) = each %{$activePrev}) {
                         # We write this to a file to ensure that the
                         # service gets restarted if we're interrupted.
                         if (!$socketActivated) {
-                            write_file($startListFile, { append => 1 }, "$unit\n");
+                            $unitsToStart{$unit} = 1;
+                            recordUnit($startListFile, $unit);
                         }
 
-                        push @unitsToStop, $unit;
+                        $unitsToStop{$unit} = 1;
 
                     }
                 }
@@ -268,14 +292,16 @@ foreach my $mountPoint (keys %$prevFss) {
     my $unit = pathToUnitName($mountPoint) . ".mount";
     if (!defined $new) {
         # Filesystem entry disappeared, so unmount it.
-        push @unitsToStop, $unit;
+        $unitsToStop{$unit} = 1;
     } elsif ($prev->{fsType} ne $new->{fsType} || $prev->{device} ne $new->{device}) {
         # Filesystem type or device changed, so unmount and mount it.
-        write_file($startListFile, { append => 1 }, "$unit\n");
-        push @unitsToStop, $unit;
+        $unitsToStop{$unit} = 1;
+        $unitsToStart{$unit} = 1;
+        recordUnit($startListFile, $unit);
     } elsif ($prev->{options} ne $new->{options}) {
         # Mount options changes, so remount it.
-        write_file($reloadListFile, { append => 1 }, "$unit\n");
+        $unitsToReload{$unit} = 1;
+        recordUnit($reloadListFile, $unit);
     }
 }
 
@@ -294,14 +320,51 @@ foreach my $device (keys %$prevSwaps) {
     # FIXME: update swap options (i.e. its priority).
 }
 
-if (scalar @unitsToStop > 0) {
-    @unitsToStop = unique(@unitsToStop);
-    print STDERR "stopping the following units: ", join(", ", sort(@unitsToStop)), "\n";
-    system("systemctl", "stop", "--", @unitsToStop); # FIXME: ignore errors?
+
+# Should we have systemd re-exec itself?
+my $restartSystemd = abs_path("/proc/1/exe") ne abs_path("@systemd@/lib/systemd/systemd");
+
+
+sub filterUnits {
+    my ($units) = @_;
+    my @res;
+    foreach my $unit (sort(keys %{$units})) {
+        push @res, $unit if !defined $unitsToFilter{$unit};
+    }
+    return @res;
+}
+
+my @unitsToStopFiltered = filterUnits(\%unitsToStop);
+my @unitsToStartFiltered = filterUnits(\%unitsToStart);
+
+
+# Show dry-run actions.
+if ($action eq "dry-activate") {
+    print STDERR "would stop the following units: ", join(", ", @unitsToStopFiltered), "\n"
+        if scalar @unitsToStopFiltered > 0;
+    print STDERR "would NOT stop the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n"
+        if scalar(keys %unitsToSkip) > 0;
+    print STDERR "would restart systemd\n" if $restartSystemd;
+    print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"
+        if scalar(keys %unitsToRestart) > 0;
+    print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
+        if scalar @unitsToStartFiltered;
+    print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
+        if scalar(keys %unitsToReload) > 0;
+    exit 0;
+}
+
+
+syslog(LOG_NOTICE, "switching to system configuration $out");
+
+if (scalar (keys %unitsToStop) > 0) {
+    print STDERR "stopping the following units: ", join(", ", @unitsToStopFiltered), "\n"
+        if scalar @unitsToStopFiltered;
+    system("systemctl", "stop", "--", sort(keys %unitsToStop)); # FIXME: ignore errors?
 }
 
-print STDERR "NOT restarting the following units: ", join(", ", sort(@unitsToSkip)), "\n"
-    if scalar @unitsToSkip > 0;
+print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n"
+    if scalar(keys %unitsToSkip) > 0;
 
 # Activate the new configuration (i.e., update /etc, make accounts,
 # and so on).
@@ -310,7 +373,7 @@ print STDERR "activating the configuration...\n";
 system("$out/activate", "$out") == 0 or $res = 2;
 
 # Restart systemd if necessary.
-if (abs_path("/proc/1/exe") ne abs_path("@systemd@/lib/systemd/systemd")) {
+if ($restartSystemd) {
     print STDERR "restarting systemd...\n";
     system("@systemd@/bin/systemctl", "daemon-reexec") == 0 or $res = 2;
 }
@@ -327,10 +390,9 @@ system("@systemd@/bin/systemctl", "reload-or-restart", "dbus.service");
 
 # Restart changed services (those that have to be restarted rather
 # than stopped and started).
-my @restart = unique(split('\n', read_file($restartListFile, err_mode => 'quiet') // ""));
-if (scalar @restart > 0) {
-    print STDERR "restarting the following units: ", join(", ", sort(@restart)), "\n";
-    system("@systemd@/bin/systemctl", "restart", "--", @restart) == 0 or $res = 4;
+if (scalar(keys %unitsToRestart) > 0) {
+    print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n";
+    system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4;
     unlink($restartListFile);
 }
 
@@ -340,17 +402,16 @@ if (scalar @restart > 0) {
 # that are symlinks to other units.  We shouldn't start both at the
 # same time because we'll get a "Failed to add path to set" error from
 # systemd.
-my @start = unique("default.target", "timers.target", "sockets.target", split('\n', read_file($startListFile, err_mode => 'quiet') // ""));
-print STDERR "starting the following units: ", join(", ", sort(@start)), "\n";
-system("@systemd@/bin/systemctl", "start", "--", @start) == 0 or $res = 4;
+print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n"
+    if scalar @unitsToStartFiltered;
+system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4;
 unlink($startListFile);
 
 # Reload units that need it.  This includes remounting changed mount
 # units.
-my @reload = unique(split '\n', read_file($reloadListFile, err_mode => 'quiet') // "");
-if (scalar @reload > 0) {
-    print STDERR "reloading the following units: ", join(", ", sort(@reload)), "\n";
-    system("@systemd@/bin/systemctl", "reload", "--", @reload) == 0 or $res = 4;
+if (scalar(keys %unitsToReload) > 0) {
+    print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n";
+    system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4;
     unlink($reloadListFile);
 }
 
diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
index 4b5e84f53c1ac..6153578612c11 100644
--- a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
+++ b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
@@ -24,6 +24,7 @@ in
 
       enable = mkOption {
         default = false;
+        type = types.bool;
         description = ''
           Whether to create symlinks to the system generations under
           <literal>/boot</literal>.  When enabled,
@@ -42,6 +43,7 @@ in
 
       copyKernels = mkOption {
         default = false;
+        type = types.bool;
         description = "
           Whether copy the necessary boot files into /boot, so
           /nix/store is not needed by the boot loader.
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index fd6523c0ece4d..585c8854feecc 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -34,7 +34,7 @@ let
       shell = "${pkgs.stdenv.shell}";
       fullVersion = (builtins.parseDrvName realGrub.name).version;
       grubEfi = f grubEfi;
-      grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f grubEfi.grubTarget else "";
+      grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f (grubEfi.grubTarget or "") else "";
       inherit (efi) efiSysMountPoint canTouchEfiVariables;
       inherit (cfg)
         version extraConfig extraPerEntryConfig extraEntries
@@ -179,6 +179,7 @@ in
       };
 
       splashImage = mkOption {
+        type = types.nullOr types.path;
         example = literalExample "./my-background.png";
         description = ''
           Background image used for GRUB.  It must be a 640x480,
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index 74a934c67931d..2ef1fca19835f 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -448,7 +448,9 @@ sub getDeviceTargets {
 
 # check whether to install GRUB EFI or not
 sub getEfiTarget {
-    if (($grub ne "") && ($grubEfi ne "")) {
+    if ($grubVersion == 1) {
+        return "no"
+    } elsif (($grub ne "") && ($grubEfi ne "")) {
         # EFI can only be installed when target is set;
         # A target is also required then for non-EFI grub
         if (($grubTarget eq "") || ($grubTargetEfi eq "")) { die }
diff --git a/nixos/modules/system/boot/loader/init-script/init-script.nix b/nixos/modules/system/boot/loader/init-script/init-script.nix
index 3b33d42b4ae4e..374d9524ff1ee 100644
--- a/nixos/modules/system/boot/loader/init-script/init-script.nix
+++ b/nixos/modules/system/boot/loader/init-script/init-script.nix
@@ -23,6 +23,7 @@ in
 
       enable = mkOption {
         default = false;
+        type = types.bool;
         description = ''
           Some systems require a /sbin/init script which is started.
           Or having it makes starting NixOS easier.
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
index d3f32418a64c4..1ea3ddd8867c3 100644
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
+++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
@@ -21,6 +21,7 @@ in
 
     boot.loader.raspberryPi.enable = mkOption {
       default = false;
+      type = types.bool;
       description = ''
         Whether to create files with the system generations in
         <literal>/boot</literal>.
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 1e173f5ac7aff..5af644279e5f4 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -177,20 +177,24 @@ fi
 if test -e /sys/power/resume -a -e /sys/power/disk; then
     if test -n "@resumeDevice@"; then
         resumeDev="@resumeDevice@"
+        resumeInfo="$(udevadm info -q property "$resumeDev" )"
     else
         for sd in @resumeDevices@; do
             # Try to detect resume device. According to Ubuntu bug:
             # https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1
             # When there are multiple swap devices, we can't know where will hibernate
             # image reside. We can check all of them for swsuspend blkid.
-            if [ "$(udevadm info -q property "$sd" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then
+            resumeInfo="$(udevadm info -q property "$sd" )"
+            if [ "$(echo "$resumeInfo" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then
                 resumeDev="$sd"
                 break
             fi
         done
     fi
-    if test -n "$resumeDev"; then
-        readlink -f "$resumeDev" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
+    if test -e "$resumeDev"; then
+        resumeMajor="$(echo "$resumeInfo" | sed -n 's/^MAJOR=//p')"
+        resumeMinor="$(echo "$resumeInfo" | sed -n 's/^MINOR=//p')"
+        echo "$resumeMajor:$resumeMinor" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
     fi
 fi
 
@@ -218,6 +222,9 @@ checkFS() {
     # Don't check resilient COWs as they validate the fs structures at mount time
     if [ "$fsType" = btrfs -o "$fsType" = zfs ]; then return 0; fi
 
+    # Skip fsck for inherently readonly filesystems.
+    if [ "$fsType" = squashfs ]; then return 0; fi
+
     # If we couldn't figure out the FS type, then skip fsck.
     if [ "$fsType" = auto ]; then
         echo 'cannot check filesystem with type "auto"!'
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index 356a440b17ac8..173453a17f71f 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -50,8 +50,10 @@ echo "booting system configuration $systemConfig" > /dev/kmsg
 # Make /nix/store a read-only bind mount to enforce immutability of
 # the Nix store.  Note that we can't use "chown root:nixbld" here
 # because users/groups might not exist yet.
-chown 0:30000 /nix/store
-chmod 1775 /nix/store
+# Silence chown/chmod to fail gracefully on a readonly filesystem
+# like squashfs.
+chown -f 0:30000 /nix/store
+chmod -f 1775 /nix/store
 if [ -n "@readOnlyStore@" ]; then
     if ! readonly-mountpoint /nix/store; then
         mount --bind /nix/store /nix/store
diff --git a/nixos/modules/tasks/kbd.nix b/nixos/modules/tasks/kbd.nix
index 03c42404e5d55..8d26998021d33 100644
--- a/nixos/modules/tasks/kbd.nix
+++ b/nixos/modules/tasks/kbd.nix
@@ -22,6 +22,7 @@ in
     # FIXME: still needed?
     boot.extraTTYs = mkOption {
       default = [];
+      type = types.listOf types.string;
       example = ["tty8" "tty9"];
       description = ''
         Tty (virtual console) devices, in addition to the consoles on
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index 70158fc7252b0..8223c5a4941e5 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -35,7 +35,10 @@ in
     assertions = [ {
       assertion = cfg.defaultGatewayWindowSize == null;
       message = "networking.defaultGatewayWindowSize is not supported by networkd.";
-    } ];
+    } ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: {
+      assertion = !rstp;
+      message = "networking.bridges.${n}.rstp is not supported by networkd.";
+    });
 
     systemd.services.dhcpcd.enable = mkDefault false;
 
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index d175bac3074d3..0473c2454e22c 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -7,17 +7,6 @@ in
 {
   imports = [ ../profiles/headless.nix ./ec2-data.nix ];
 
-  options = {
-    ec2 = {
-      hvm = mkOption {
-        default = false;
-        description = ''
-          Whether the EC2 instance is a HVM instance.
-        '';
-      };
-    };
-  };
-
   config = {
     system.build.amazonImage =
       pkgs.vmTools.runInLinuxVM (
@@ -102,6 +91,10 @@ in
     boot.initrd.kernelModules = [ "xen-blkfront" ];
     boot.kernelModules = [ "xen-netfront" ];
 
+    # Prevent the nouveau kernel module from being loaded, as it
+    # interferes with the nvidia/nvidia-uvm modules needed for CUDA.
+    boot.blacklistedKernelModules = [ "nouveau" ];
+
     # Generate a GRUB menu.  Amazon's pv-grub uses this to boot our kernel/initrd.
     boot.loader.grub.version = if cfg.hvm then 2 else 1;
     boot.loader.grub.device = if cfg.hvm then "/dev/xvda" else "nodev";
diff --git a/nixos/modules/virtualisation/amazon-options.nix b/nixos/modules/virtualisation/amazon-options.nix
new file mode 100644
index 0000000000000..34a50dcab16fb
--- /dev/null
+++ b/nixos/modules/virtualisation/amazon-options.nix
@@ -0,0 +1,16 @@
+{ config, lib, pkgs, ... }:
+{
+  options = {
+    ec2 = {
+      hvm = lib.mkOption {
+        default = false;
+        internal = true;
+        description = ''
+          Whether the EC2 instance is a HVM instance.
+        '';
+      };
+    };
+  };
+
+  config = {};
+}
diff --git a/nixos/modules/virtualisation/azure-image.nix b/nixos/modules/virtualisation/azure-image.nix
index ec7e8888c0368..ab5a9c51fa5b5 100644
--- a/nixos/modules/virtualisation/azure-image.nix
+++ b/nixos/modules/virtualisation/azure-image.nix
@@ -24,6 +24,7 @@ in
 
           postVM =
             ''
+              echo Converting
               mkdir -p $out
               ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vpc $diskImage $out/disk.vhd
               rm $diskImage
@@ -62,30 +63,31 @@ in
           echo "copying everything (will take a while)..."
           cp -prd $storePaths /mnt/nix/store/
 
-          # Register the paths in the Nix database.
+          echo Register the paths in the Nix database.
           printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \
-              chroot /mnt ${config.nix.package}/bin/nix-store --load-db
+              chroot /mnt ${config.nix.package}/bin/nix-store --load-db --option build-users-group ""
 
-          # Create the system profile to allow nixos-rebuild to work.
+          echo Create the system profile to allow nixos-rebuild to work.
           chroot /mnt ${config.nix.package}/bin/nix-env \
-              -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel}
+              -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} --option build-users-group ""
 
-          # `nixos-rebuild' requires an /etc/NIXOS.
+          echo nixos-rebuild requires an /etc/NIXOS.
           mkdir -p /mnt/etc
           touch /mnt/etc/NIXOS
 
-          # `switch-to-configuration' requires a /bin/sh
+          echo switch-to-configuration requires a /bin/sh
           mkdir -p /mnt/bin
           ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh
 
-          # Install a configuration.nix.
+          echo Install a configuration.nix.
           mkdir -p /mnt/etc/nixos /mnt/boot/grub
           cp ${./azure-config.nix} /mnt/etc/nixos/configuration.nix
 
-          # Generate the GRUB menu.
+          echo Generate the GRUB menu.
           ln -s vda /dev/sda
           chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot
 
+          echo Almost done
           umount /mnt/proc /mnt/dev /mnt/sys
           umount /mnt
         ''
@@ -119,7 +121,44 @@ in
   # Always include cryptsetup so that NixOps can use it.
   environment.systemPackages = [ pkgs.cryptsetup ];
 
+  systemd.services.fetch-ssh-keys =
+    { description = "Fetch host keys and authorized_keys for root user";
+
+      wantedBy = [ "sshd.service" ];
+      before = [ "sshd.service" ];
+      after = [ "local-fs.target" ];
+
+      path  = [ pkgs.coreutils ];
+      script =
+        ''
+          eval "$(base64 --decode /metadata/CustomData.bin)"
+          if ! [ -z "$ssh_host_ecdsa_key" ]; then
+            echo "downloaded ssh_host_ecdsa_key"
+            echo "$ssh_host_ecdsa_key" > /etc/ssh/ssh_host_ecdsa_key
+            chmod 600 /etc/ssh/ssh_host_ecdsa_key
+          fi
+
+          if ! [ -z "$ssh_host_ecdsa_key_pub" ]; then
+            echo "downloaded ssh_host_ecdsa_key_pub"
+            echo "$ssh_host_ecdsa_key_pub" > /etc/ssh/ssh_host_ecdsa_key.pub
+            chmod 644 /etc/ssh/ssh_host_ecdsa_key.pub
+          fi
+
+          if ! [ -z "$ssh_root_auth_key" ]; then
+            echo "downloaded ssh_root_auth_key"
+            mkdir -m 0700 -p /root/.ssh
+            echo "$ssh_root_auth_key" > /root/.ssh/authorized_keys
+            chmod 600 /root/.ssh/authorized_keys
+          fi
+        '';
+      serviceConfig.Type = "oneshot";
+      serviceConfig.RemainAfterExit = true;
+      serviceConfig.StandardError = "journal+console";
+      serviceConfig.StandardOutput = "journal+console";
+     };
+
   networking.usePredictableInterfaceNames = false;
 
-  users.extraUsers.root.openssh.authorizedKeys.keys = [ (builtins.readFile <ssh-pub-key>) ];
+  #users.extraUsers.root.openssh.authorizedKeys.keys = [ (builtins.readFile <ssh-pub-key>) ];
+
 }
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index c461cf8c00cb8..da39dda853535 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -10,6 +10,7 @@ let
     isExecutable = true;
     src = ./nixos-container.pl;
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
+    su = "${pkgs.shadow.su}/bin/su";
     inherit (pkgs) utillinux;
   };
 
@@ -202,7 +203,7 @@ in
         script =
           ''
             mkdir -p -m 0755 "$root/etc" "$root/var/lib"
-            mkdir -p -m 0700 "$root/var/lib/private" "$root/root"
+            mkdir -p -m 0700 "$root/var/lib/private" "$root/root" /run/containers
             if ! [ -e "$root/etc/os-release" ]; then
               touch "$root/etc/os-release"
             fi
@@ -211,7 +212,7 @@ in
               "/nix/var/nix/profiles/per-container/$INSTANCE" \
               "/nix/var/nix/gcroots/per-container/$INSTANCE"
 
-            cp -f /etc/resolv.conf "$root/etc/resolv.conf"
+            cp --remove-destination /etc/resolv.conf "$root/etc/resolv.conf"
 
             if [ "$PRIVATE_NETWORK" = 1 ]; then
               extraFlags+=" --network-veth"
@@ -260,11 +261,21 @@ in
                 ip route add $LOCAL_ADDRESS dev $ifaceHost
               fi
             fi
+
+            # Get the leader PID so that we can signal it in
+            # preStop. We can't use machinectl there because D-Bus
+            # might be shutting down. FIXME: in systemd 219 we can
+            # just signal systemd-nspawn to do a clean shutdown.
+            machinectl show "$INSTANCE" | sed 's/Leader=\(.*\)/\1/;t;d' > "/run/containers/$INSTANCE.pid"
           '';
 
         preStop =
           ''
-            machinectl poweroff "$INSTANCE" || true
+            pid="$(cat /run/containers/$INSTANCE.pid)"
+            if [ -n "$pid" ]; then
+              kill -RTMIN+4 "$pid"
+            fi
+            rm -f "/run/containers/$INSTANCE.pid"
           '';
 
         restartIfChanged = false;
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index 4d493b3896f24..98985d2d2c57c 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -129,10 +129,10 @@ in
 
       wantedBy = [ "sshd.service" ];
       before = [ "sshd.service" ];
-      after = [ "network-online.target" ];
-      wants = [ "network-online.target" ];
+      after = [ "network-online.target" "ip-up.target" ];
+      wants = [ "network-online.target" "ip-up.target" ];
 
-      script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 6 --waitretry=10"; in
+      script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google'"; in
         ''
           # When dealing with cryptographic keys, we want to keep things private.
           umask 077
@@ -140,7 +140,7 @@ in
           if ! [ -e /root/.ssh/authorized_keys ]; then
                 echo "obtaining SSH key..."
                 mkdir -m 0700 -p /root/.ssh
-                ${wget} -O /root/authorized-keys-metadata http://metadata/0.1/meta-data/authorized-keys
+                ${wget} -O /root/authorized-keys-metadata http://metadata.google.internal/0.1/meta-data/authorized-keys
                 if [ $? -eq 0 -a -e /root/authorized-keys-metadata ]; then
                     cat /root/authorized-keys-metadata | cut -d: -f2- > /root/key.pub
                     if ! grep -q -f /root/key.pub /root/.ssh/authorized_keys; then
@@ -156,7 +156,7 @@ in
           ${flip concatMapStrings config.services.openssh.hostKeys (k :
             let kName = baseNameOf k.path; in ''
               echo "trying to obtain SSH private host key ${kName}"
-              ${wget} -O /root/${kName} http://metadata/0.1/meta-data/attributes/${kName} && :
+              ${wget} -O /root/${kName} http://metadata.google.internal/0.1/meta-data/attributes/${kName} && :
               if [ $? -eq 0 -a -e /root/${kName} ]; then
                   countKeys=$((countKeys+1))
                   mv -f /root/${kName} ${k.path}
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index 2d03f0544b67b..7410609e0642c 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -92,7 +92,7 @@ in
                 ++ optional vswitch.enable "vswitchd.service";
 
         path = [ 
-            pkgs.bridge_utils 
+            pkgs.bridge-utils 
             pkgs.dmidecode 
             pkgs.dnsmasq
             pkgs.ebtables
diff --git a/nixos/modules/virtualisation/lxc.nix b/nixos/modules/virtualisation/lxc.nix
index 10d3a6575fb9b..22da012e4141e 100644
--- a/nixos/modules/virtualisation/lxc.nix
+++ b/nixos/modules/virtualisation/lxc.nix
@@ -32,7 +32,9 @@ in
         default = "";
         description =
           ''
-            This is the system-wide LXC config. See lxc.system.conf(5).
+            This is the system-wide LXC config. See
+            <citerefentry><refentrytitle>lxc.system.conf</refentrytitle>
+            <manvolnum>5</manvolnum></citerefentry>.
           '';
       };
 
@@ -43,7 +45,8 @@ in
         description =
           ''
             Default config (default.conf) for new containers, i.e. for
-            network config. See lxc.container.conf(5).
+            network config. See <citerefentry><refentrytitle>lxc.container.conf
+            </refentrytitle><manvolnum>5</manvolnum></citerefentry>.
           '';
       };
 
@@ -54,7 +57,9 @@ in
         description =
           ''
             This is the config file for managing unprivileged user network
-            administration access in LXC. See lxc-user-net(5).
+            administration access in LXC. See <citerefentry>
+            <refentrytitle>lxc-user-net</refentrytitle><manvolnum>5</manvolnum>
+            </citerefentry>.
           '';
       };
 
diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl
index 94edfb37948a3..1455f7143f131 100644
--- a/nixos/modules/virtualisation/nixos-container.pl
+++ b/nixos/modules/virtualisation/nixos-container.pl
@@ -8,6 +8,7 @@ use Fcntl ':flock';
 use Getopt::Long qw(:config gnu_getopt);
 
 my $nsenter = "@utillinux@/bin/nsenter";
+my $su = "@su@";
 
 # Ensure a consistent umask.
 umask 0022;
@@ -271,14 +272,14 @@ elsif ($action eq "login") {
 }
 
 elsif ($action eq "root-login") {
-    runInContainer("su", "root", "-l");
+    runInContainer("@su@", "root", "-l");
 }
 
 elsif ($action eq "run") {
     shift @ARGV; shift @ARGV;
     # Escape command.
     my $s = join(' ', map { s/'/'\\''/g; "'$_'" } @ARGV);
-    runInContainer("su", "root", "-l", "-c", "exec " . $s);
+    runInContainer("@su@", "root", "-l", "-c", "exec " . $s);
 }
 
 elsif ($action eq "show-ip") {
diff --git a/nixos/modules/virtualisation/nova.nix b/nixos/modules/virtualisation/nova.nix
index 8795b5b52d5a4..21e060cf26636 100644
--- a/nixos/modules/virtualisation/nova.nix
+++ b/nixos/modules/virtualisation/nova.nix
@@ -147,7 +147,7 @@ in
         path =
           [ pkgs.sudo pkgs.vlan pkgs.nettools pkgs.iptables pkgs.qemu_kvm
             pkgs.e2fsprogs pkgs.utillinux pkgs.multipath_tools pkgs.iproute
-            pkgs.bridge_utils
+            pkgs.bridge-utils
           ];
 
         exec = "${nova}/bin/nova-compute --flagfile=${novaConf}";
@@ -163,7 +163,7 @@ in
 
         path =
           [ pkgs.sudo pkgs.vlan pkgs.dnsmasq pkgs.nettools pkgs.iptables
-            pkgs.iproute pkgs.bridge_utils pkgs.radvd
+            pkgs.iproute pkgs.bridge-utils pkgs.radvd
           ];
 
         exec = "${nova}/bin/nova-network --flagfile=${novaConf}";
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 33c64cc890e0c..a5a133dfa5dce 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -36,13 +36,28 @@ let
             ${toString config.virtualisation.diskSize}M || exit 1
       fi
 
-      # Create a directory for exchanging data with the VM.
+      # Create a directory for storing temporary data of the running VM.
       if [ -z "$TMPDIR" -o -z "$USE_TMPDIR" ]; then
           TMPDIR=$(mktemp -d nix-vm.XXXXXXXXXX --tmpdir)
       fi
-      cd $TMPDIR
+      # Create a directory for exchanging data with the VM.
       mkdir -p $TMPDIR/xchg
 
+      ${if cfg.useBootLoader then ''
+        # Create a writable copy/snapshot of the boot disk
+        # A writable boot disk can be booted from automatically
+        ${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 -b ${bootDisk}/disk.img $TMPDIR/disk.img || exit 1
+
+        ${if cfg.useEFIBoot then ''
+          # VM needs a writable flash BIOS
+          cp ${bootDisk}/bios.bin $TMPDIR || exit 1
+          chmod 0644 $TMPDIR/bios.bin || exit 1
+        '' else ''
+        ''}
+      '' else ''
+      ''}
+
+      cd $TMPDIR
       idx=2
       extraDisks=""
       ${flip concatMapStrings cfg.emptyDiskImages (size: ''
@@ -52,7 +67,6 @@ let
       '')}
 
       # Start QEMU.
-      # "-boot menu=on" is there, because I don't know how to make qemu boot from 2nd hd.
       exec ${pkgs.qemu_kvm}/bin/qemu-kvm \
           -name ${vmName} \
           -m ${toString config.virtualisation.memorySize} \
@@ -63,8 +77,11 @@ let
           -virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
           ${if cfg.useBootLoader then ''
             -drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
-            -drive index=1,id=drive2,file=${bootDisk}/disk.img,if=virtio,readonly \
-            -boot menu=on \
+            -drive index=1,id=drive2,file=$TMPDIR/disk.img,media=disk \
+            ${if cfg.useEFIBoot then ''
+              -pflash $TMPDIR/bios.bin \
+            '' else ''
+            ''}
           '' else ''
             -drive file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \
             -kernel ${config.system.build.toplevel}/kernel \
@@ -74,7 +91,8 @@ let
           $extraDisks \
           ${qemuGraphics} \
           ${toString config.virtualisation.qemu.options} \
-          $QEMU_OPTS
+          $QEMU_OPTS \
+          $@
     '';
 
 
@@ -98,23 +116,44 @@ let
             ''
               mkdir $out
               diskImage=$out/disk.img
-              ${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 $diskImage "32M"
+              bootFlash=$out/bios.bin
+              ${pkgs.qemu_kvm}/bin/qemu-img create -f qcow2 $diskImage "40M"
+              ${if cfg.useEFIBoot then ''
+                cp ${pkgs.OVMF-CSM}/FV/OVMF.fd $bootFlash
+                chmod 0644 $bootFlash
+              '' else ''
+              ''}
             '';
           buildInputs = [ pkgs.utillinux ];
+          QEMU_OPTS = if cfg.useEFIBoot
+                      then "-pflash $out/bios.bin -nographic -serial pty"
+                      else "-nographic -serial pty";
         }
         ''
-          # Create a single /boot partition.
-          ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos
-          ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s
-          . /sys/class/block/vda1/uevent
-          mknod /dev/vda1 b $MAJOR $MINOR
+          # Create a /boot EFI partition with 40M
+          ${pkgs.gptfdisk}/sbin/sgdisk -G /dev/vda
+          ${pkgs.gptfdisk}/sbin/sgdisk -a 1 -n 1:34:2047 -c 1:"BIOS Boot Partition" -t 1:ef02 /dev/vda
+          ${pkgs.gptfdisk}/sbin/sgdisk -a 512 -N 2 -c 2:"EFI System" -t 2:ef00 /dev/vda
+          ${pkgs.gptfdisk}/sbin/sgdisk -A 1:set:1 /dev/vda
+          ${pkgs.gptfdisk}/sbin/sgdisk -A 2:set:2 /dev/vda
+          ${pkgs.gptfdisk}/sbin/sgdisk -h 2 /dev/vda
+          ${pkgs.gptfdisk}/sbin/sgdisk -C /dev/vda
+          ${pkgs.utillinux}/bin/sfdisk /dev/vda -A 2
+          . /sys/class/block/vda2/uevent
+          mknod /dev/vda2 b $MAJOR $MINOR
           . /sys/class/block/vda/uevent
-          ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L boot /dev/vda1
-          ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
-
-          # Mount /boot.
+          ${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2
+          export MTOOLS_SKIP_CHECK=1
+          ${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot
+
+          # Mount /boot; load necessary modules first.
+          ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_cp437.ko || true
+          ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_iso8859-1.ko || true
+          ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/fat.ko || true
+          ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/vfat.ko || true
+          ${pkgs.module_init_tools}/sbin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/efivarfs/efivarfs.ko || true
           mkdir /boot
-          mount /dev/vda1 /boot
+          mount /dev/vda2 /boot
 
           # This is needed for GRUB 0.97, which doesn't know about virtio devices.
           mkdir /boot/grub
@@ -287,6 +326,17 @@ in
           '';
       };
 
+    virtualisation.useEFIBoot =
+      mkOption {
+        default = false;
+        description =
+          ''
+            If enabled, the virtual machine will provide a EFI boot
+            manager.
+            useEFIBoot is ignored if useBootLoader == false.
+          '';
+      };
+
   };
 
   config = {
@@ -379,8 +429,8 @@ in
           };
       } // optionalAttrs cfg.useBootLoader
       { "/boot" =
-          { device = "/dev/disk/by-label/boot";
-            fsType = "ext4";
+          { device = "/dev/vdb2";
+            fsType = "vfat";
             options = "ro";
             noCheck = true; # fsck fails on a r/o filesystem
           };
@@ -413,6 +463,7 @@ in
 
     # Wireless won't work in the VM.
     networking.wireless.enable = mkVMOverride false;
+    networking.connman.enable = mkVMOverride false;
 
     # Speed up booting by not waiting for ARP.
     networking.dhcpcd.extraConfig = "noarp";
diff --git a/nixos/modules/virtualisation/xen-dom0.nix b/nixos/modules/virtualisation/xen-dom0.nix
index 566059472c9f2..ea9f61aad6a68 100644
--- a/nixos/modules/virtualisation/xen-dom0.nix
+++ b/nixos/modules/virtualisation/xen-dom0.nix
@@ -5,18 +5,8 @@
 with lib;
 
 let
-
   cfg = config.virtualisation.xen;
-
   xen = pkgs.xen;
-
-  xendConfig = pkgs.writeText "xend-config.sxp"
-    ''
-      (loglevel DEBUG)
-      (network-script network-bridge)
-      (vif-script vif-bridge)
-    '';
-
 in
 
 {
@@ -58,23 +48,62 @@ in
           '';
       };
 
+    virtualisation.xen.bridge =
+      mkOption {
+        default = "xenbr0";
+        description =
+          ''
+            Create a bridge for the Xen domUs to connect to.
+          '';
+      };
+
+    virtualisation.xen.stored =
+      mkOption {
+        type = types.path;
+        description =
+          ''
+            Xen Store daemon to use. Defaults to oxenstored of the xen package.
+          '';
+      };
+
+    virtualisation.xen.trace =
+      mkOption {
+        default = false;
+        description =
+          ''
+            Enable Xen tracing.
+          '';
+      };
   };
 
 
   ###### implementation
 
   config = mkIf cfg.enable {
+    assertions = [ {
+      assertion = pkgs.stdenv.isx86_64;
+      message = "Xen currently not supported on ${pkgs.stdenv.system}";
+    } {
+      assertion = config.boot.loader.grub.enable && (config.boot.loader.grub.efiSupport == false);
+      message = "Xen currently does not support EFI boot";
+    } ];
+
+    virtualisation.xen.stored = mkDefault "${xen}/bin/oxenstored";
 
     environment.systemPackages = [ xen ];
 
-    # Domain 0 requires a pvops-enabled kernel.
-    boot.kernelPackages = pkgs.linuxPackages_3_2_xen;
+    # Make sure Domain 0 gets the required configuration
+    #boot.kernelPackages = pkgs.boot.kernelPackages.override { features={xen_dom0=true;}; };
 
     boot.kernelModules =
-      [ "xen_evtchn" "xen_gntdev" "xen_blkback" "xen_netback" "xen_pciback"
-        "blktap" "tun"
+      [ "xen-evtchn" "xen-gntdev" "xen-gntalloc" "xen-blkback" "xen-netback"
+        "xen-pciback" "evtchn" "gntdev" "netbk" "blkbk" "xen-scsibk"
+        "usbbk" "pciback" "xen-acpi-processor" "blktap2" "tun" "netxen_nic"
+        "xen_wdt" "xen-acpi-processor" "xen-privcmd" "xen-scsiback"
+        "xenfs"
       ];
 
+
     # The radeonfb kernel module causes the screen to go black as soon
     # as it's loaded, so don't load it.
     boot.blacklistedKernelModules = [ "radeonfb" ];
@@ -87,8 +116,8 @@ in
         options loop max_loop=64
       '';
 
-    virtualisation.xen.bootParams =
-      [ "loglvl=all" "guest_loglvl=all" ] ++
+    virtualisation.xen.bootParams = [] ++
+      optionals cfg.trace [ "loglvl=all" "guest_loglvl=all" ] ++
       optional (cfg.domain0MemorySize != 0) "dom0_mem=${toString cfg.domain0MemorySize}M";
 
     system.extraSystemBuilderCmds =
@@ -101,78 +130,162 @@ in
     system.activationScripts.xen =
       ''
         if [ -d /proc/xen ]; then
-            ${pkgs.sysvtools}/bin/mountpoint -q /proc/xen || \
+            ${pkgs.kmod}/bin/modprobe xenfs 2> /dev/null
+            ${pkgs.utillinux}/bin/mountpoint -q /proc/xen || \
                 ${pkgs.utillinux}/bin/mount -t xenfs none /proc/xen
         fi
       '';
 
-    jobs.xend =
-      { description = "Xen Control Daemon";
-
-        startOn = "stopped udevtrigger";
-
-        path =
-          [ pkgs.bridge_utils pkgs.gawk pkgs.iproute pkgs.nettools
-            pkgs.utillinux pkgs.bash xen pkgs.pciutils pkgs.procps
-          ];
-
-        environment.XENCONSOLED_TRACE = "hv";
-
-        preStart =
-          ''
-            mkdir -p /var/log/xen/console -m 0700
-
-            ${xen}/sbin/xend start
-
-            # Wait until Xend is running.
-            for ((i = 0; i < 60; i++)); do echo "waiting for xend..."; ${xen}/sbin/xend status && break; done
-
-            ${xen}/sbin/xend status || exit 1
-          '';
-
-        postStop = "${xen}/sbin/xend stop";
-      };
-
-    jobs.xendomains =
-      { description = "Automatically starts, saves and restores Xen domains on startup/shutdown";
-
-        startOn = "started xend";
-
-        stopOn = "starting shutdown and stopping xend";
-
-        restartIfChanged = false;
-        
-        path = [ pkgs.xen ];
-
-        environment.XENDOM_CONFIG = "${xen}/etc/sysconfig/xendomains";
-
-        preStart =
-          ''
-            mkdir -p /var/lock/subsys -m 755
-            ${xen}/etc/init.d/xendomains start
-          '';
-
-        postStop = "${xen}/etc/init.d/xendomains stop";
-      };
+    # Domain 0 requires a pvops-enabled kernel.
+    system.requiredKernelConfig = with config.lib.kernelConfig;
+      [ (isYes "XEN")
+        (isYes "X86_IO_APIC")
+        (isYes "ACPI")
+        (isYes "XEN_DOM0")
+        (isYes "PCI_XEN")
+        (isYes "XEN_DEV_EVTCHN")
+        (isYes "XENFS")
+        (isYes "XEN_COMPAT_XENFS")
+        (isYes "XEN_SYS_HYPERVISOR")
+        (isYes "XEN_GNTDEV")
+        (isYes "XEN_BACKEND")
+        (isModule "XEN_NETDEV_BACKEND")
+        (isModule "XEN_BLKDEV_BACKEND")
+        (isModule "XEN_PCIDEV_BACKEND")
+        (isYes "XEN_BALLOON")
+        (isYes "XEN_SCRUB_PAGES")
+      ];
 
-    # To prevent a race between dhcpcd and xend's bridge setup script
-    # (which renames eth* to peth* and recreates eth* as a virtual
-    # device), start dhcpcd after xend.
-    jobs.dhcpcd.startOn = mkOverride 50 "started xend";
 
     environment.etc =
-      [ { source = xendConfig;
-          target = "xen/xend-config.sxp";
-        }
-        { source = "${xen}/etc/xen/scripts";
-          target = "xen/scripts";
+      [ { source = "${xen}/etc/xen/xl.conf";
+          target = "xen/xl.conf";
         }
       ];
 
     # Xen provides udev rules.
     services.udev.packages = [ xen ];
 
-    services.udev.path = [ pkgs.bridge_utils pkgs.iproute ];
+    services.udev.path = [ pkgs.bridge-utils pkgs.iproute ];
+
+    systemd.services.xen-store = {
+      description = "Xen Store Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "xen-store.socket" ];
+      requires = [ "xen-store.socket" ];
+      preStart = ''
+        export XENSTORED_ROOTDIR="/var/lib/xenstored"
+        rm -f "$XENSTORED_ROOTDIR"/tdb* &>/dev/null
+
+        mkdir -p /var/run
+        ${optionalString cfg.trace "mkdir -p /var/log/xen"}
+        grep -q control_d /proc/xen/capabilities
+        '';
+      serviceConfig.ExecStart = ''
+        ${cfg.stored}${optionalString cfg.trace " -T /var/log/xen/xenstored-trace.log"} --no-fork
+        '';
+      postStart = ''
+        time=0
+        timeout=30
+        # Wait for xenstored to actually come up, timing out after 30 seconds
+        while [ $time -lt $timeout ] && ! `${pkgs.xen}/bin/xenstore-read -s / >/dev/null 2>&1` ; do
+            time=$(($time+1))
+            sleep 1
+        done
+
+        # Exit if we timed out
+        if ! [ $time -lt $timeout ] ; then
+            echo "Could not start Xenstore Daemon"
+            exit 1
+        fi
+
+        ${pkgs.xen}/bin/xenstore-write "/local/domain/0/name" "Domain-0"
+        ${pkgs.xen}/bin/xenstore-write "/local/domain/0/domid" 0
+        '';
+    };
+
+    systemd.sockets.xen-store = {
+      description = "XenStore Socket for userspace API";
+      wantedBy = [ "sockets.target" ];
+      socketConfig = {
+        ListenStream = [ "/var/run/xenstored/socket" "/var/run/xenstored/socket_ro" ];
+        SocketMode = "0660";
+        SocketUser = "root";
+        SocketGroup = "root";
+      };
+    };
+
+
+    systemd.services.xen-console = {
+      description = "Xen Console Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "xen-store.service" ];
+      preStart = ''
+        mkdir -p /var/run/xen
+        ${optionalString cfg.trace "mkdir -p /var/log/xen"}
+        grep -q control_d /proc/xen/capabilities
+        '';
+      serviceConfig = {
+        ExecStart = ''
+          ${pkgs.xen}/bin/xenconsoled${optionalString cfg.trace " --log=all --log-dir=/var/log/xen"}
+          '';
+      };
+    };
+
+
+    systemd.services.xen-qemu = {
+      description = "Xen Qemu Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "xen-console.service" ];
+      serviceConfig.ExecStart = ''
+        ${pkgs.xen}/lib/xen/bin/qemu-system-i386 -xen-domid 0 -xen-attach -name dom0 -nographic -M xenpv \
+           -monitor /dev/null -serial /dev/null -parallel /dev/null
+        '';
+    };
+
+
+    systemd.services.xen-watchdog = {
+      description = "Xen Watchdog Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "xen-qemu.service" ];
+      serviceConfig.ExecStart = "${pkgs.xen}/bin/xenwatchdogd 30 15";
+      serviceConfig.Type = "forking";
+      serviceConfig.RestartSec = "1";
+      serviceConfig.Restart = "on-failure";
+    };
+
+
+    systemd.services.xen-bridge = {
+      description = "Xen bridge";
+      wantedBy = [ "multi-user.target" ];
+      before = [ "xen-domains.service" ];
+      serviceConfig.RemainAfterExit = "yes";
+      serviceConfig.ExecStart = ''
+        ${pkgs.bridge-utils}/bin/brctl addbr ${cfg.bridge}
+        ${pkgs.inetutils}/bin/ifconfig ${cfg.bridge} up
+        '';
+      serviceConfig.ExecStop = ''
+        ${pkgs.inetutils}/bin/ifconfig ${cfg.bridge} down
+        ${pkgs.bridge-utils}/bin/brctl delbr ${cfg.bridge}
+        '';
+    };
+
+    systemd.services.xen-domains = {
+      description = "Xen domains - automatically starts, saves and restores Xen domains";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "xen-bridge.service" "xen-qemu.service" ];
+      ## To prevent a race between dhcpcd and xend's bridge setup script
+      ## (which renames eth* to peth* and recreates eth* as a virtual
+      ## device), start dhcpcd after xend.
+      before = [ "dhcpd.service" ];
+      restartIfChanged = false;
+      serviceConfig.RemainAfterExit = "yes";
+      path = [ pkgs.xen ];
+      environment.XENDOM_CONFIG = "${pkgs.xen}/etc/sysconfig/xendomains";
+      preStart = "mkdir -p /var/lock/subsys -m 755";
+      serviceConfig.ExecStart = "${pkgs.xen}/etc/init.d/xendomains start";
+      serviceConfig.ExecStop = "${pkgs.xen}/etc/init.d/xendomains stop";
+    };
 
   };
 
diff --git a/nixos/modules/virtualisation/xen-domU.nix b/nixos/modules/virtualisation/xen-domU.nix
index 4835896693456..2db3190ad139d 100644
--- a/nixos/modules/virtualisation/xen-domU.nix
+++ b/nixos/modules/virtualisation/xen-domU.nix
@@ -9,7 +9,10 @@
   boot.loader.grub.device = "nodev";
   boot.loader.grub.extraPerEntryConfig = "root (hd0)";
 
-  boot.initrd.kernelModules = [ "xen-blkfront" ];
+  boot.initrd.kernelModules =
+    [ "xen-blkfront" "xen-tpmfront" "xen-kbdfront" "xen-fbfront"
+      "xen-netfront" "xen-pcifront" "xen-scsifront"
+    ];
 
   # Send syslog messages to the Xen console.
   services.syslogd.tty = "hvc0";
diff --git a/nixos/release.nix b/nixos/release.nix
index 1bd3ec5773189..cc451f7fe15bc 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -244,7 +244,7 @@ in rec {
   tests.blivet = callTest tests/blivet.nix {};
   tests.cadvisor = scrubDrv (import tests/cadvisor.nix { system = "x86_64-linux"; });
   tests.chromium = callTest tests/chromium.nix {};
-  tests.cjdns = callTest tests/cjdns.nix {};
+  #tests.cjdns = callTest tests/cjdns.nix {};
   tests.containers = callTest tests/containers.nix {};
   tests.docker = scrubDrv (import tests/docker.nix { system = "x86_64-linux"; });
   tests.dockerRegistry = scrubDrv (import tests/docker-registry.nix { system = "x86_64-linux"; });
@@ -254,6 +254,7 @@ in rec {
   tests.fleet = scrubDrv (import tests/fleet.nix { system = "x86_64-linux"; });
   #tests.gitlab = callTest tests/gitlab.nix {};
   tests.gnome3 = callTest tests/gnome3.nix {};
+  tests.i3wm = callTest tests/i3wm.nix {};
   tests.installer.grub1 = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).grub1.test);
   tests.installer.lvm = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).lvm.test);
   tests.installer.rebuildCD = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).rebuildCD.test);
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
index efae0ec404591..368d0e43c4657 100644
--- a/nixos/tests/chromium.nix
+++ b/nixos/tests/chromium.nix
@@ -154,7 +154,7 @@ import ./make-test.nix (
 
           my $clipboard = $machine->succeed("${pkgs.xclip}/bin/xclip -o");
           die "sandbox not working properly: $clipboard"
-          unless $clipboard =~ /suid sandbox.*yes/mi
+          unless $clipboard =~ /(?:suid|namespace) sandbox.*yes/mi
               && $clipboard =~ /pid namespaces.*yes/mi
               && $clipboard =~ /network namespaces.*yes/mi
               && $clipboard =~ /seccomp.*sandbox.*yes/mi;
diff --git a/nixos/tests/i3wm.nix b/nixos/tests/i3wm.nix
new file mode 100644
index 0000000000000..0966dba8a3c89
--- /dev/null
+++ b/nixos/tests/i3wm.nix
@@ -0,0 +1,28 @@
+import ./make-test.nix {
+  name = "i3wm";
+
+  machine = { lib, pkgs, ... }: {
+    imports = [ ./common/x11.nix ./common/user-account.nix ];
+    services.xserver.displayManager.auto.user = "alice";
+    services.xserver.windowManager.default = lib.mkForce "i3";
+    services.xserver.windowManager.i3.enable = true;
+  };
+
+  testScript = { nodes, ... }: ''
+    $machine->waitForX;
+    $machine->waitForWindow(qr/first configuration/);
+    $machine->sleep(1);
+    $machine->screenshot("started");
+    $machine->sendKeys("ret");
+    $machine->sleep(1);
+    $machine->sendKeys("alt");
+    $machine->sleep(1);
+    $machine->screenshot("configured");
+    $machine->sendKeys("ret");
+    $machine->sleep(2);
+    $machine->sendKeys("alt-ret");
+    $machine->waitForWindow(qr/machine.*alice/);
+    $machine->sleep(1);
+    $machine->screenshot("terminal");
+  '';
+}