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-install.xml47
-rw-r--r--nixos/doc/manual/man-nixos-rebuild.xml23
-rw-r--r--nixos/lib/eval-config.nix78
-rw-r--r--nixos/lib/make-iso9660-image.nix13
-rw-r--r--nixos/lib/make-iso9660-image.sh70
-rw-r--r--nixos/lib/test-driver/Machine.pm4
-rw-r--r--nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix6
-rw-r--r--nixos/modules/config/fonts/fontconfig-ultimate.nix4
-rw-r--r--nixos/modules/config/no-x-libs.nix2
-rw-r--r--nixos/modules/config/nsswitch.nix7
-rw-r--r--nixos/modules/config/pulseaudio.nix4
-rw-r--r--nixos/modules/config/sysctl.nix2
-rw-r--r--nixos/modules/config/update-users-groups.pl10
-rw-r--r--nixos/modules/config/users-groups.nix3
-rw-r--r--nixos/modules/hardware/cpu/amd-microcode.nix3
-rw-r--r--nixos/modules/hardware/cpu/intel-microcode.nix3
-rw-r--r--nixos/modules/hardware/ksm.nix18
-rw-r--r--nixos/modules/hardware/video/nvidia.nix11
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix3
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix188
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix2
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl2
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh11
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh11
-rw-r--r--nixos/modules/misc/check-config.nix15
-rw-r--r--nixos/modules/misc/extra-arguments.nix14
-rw-r--r--nixos/modules/misc/ids.nix130
-rw-r--r--nixos/modules/misc/nixpkgs.nix9
-rw-r--r--nixos/modules/module-list.nix20
-rw-r--r--nixos/modules/programs/ibus.nix51
-rw-r--r--nixos/modules/programs/shadow.nix2
-rw-r--r--nixos/modules/programs/ssh.nix31
-rw-r--r--nixos/modules/programs/uim.nix4
-rw-r--r--nixos/modules/rename.nix10
-rw-r--r--nixos/modules/security/apparmor.nix72
-rw-r--r--nixos/modules/security/grsecurity.nix72
-rw-r--r--nixos/modules/security/pam.nix34
-rw-r--r--nixos/modules/security/sudo.nix2
-rw-r--r--nixos/modules/services/audio/icecast.nix130
-rw-r--r--nixos/modules/services/audio/mpd.nix38
-rw-r--r--nixos/modules/services/backup/tarsnap.nix176
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix142
-rw-r--r--nixos/modules/services/cluster/panamax.nix5
-rw-r--r--nixos/modules/services/computing/slurm/slurm.nix130
-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/mysql.nix18
-rw-r--r--nixos/modules/services/games/minecraft-server.nix28
-rw-r--r--nixos/modules/services/games/minetest-server.nix104
-rw-r--r--nixos/modules/services/hardware/tcsd.nix4
-rw-r--r--nixos/modules/services/hardware/udev.nix6
-rw-r--r--nixos/modules/services/logging/fluentd.nix39
-rw-r--r--nixos/modules/services/misc/disnix.nix2
-rw-r--r--nixos/modules/services/misc/mediatomb.nix282
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix9
-rw-r--r--nixos/modules/services/misc/nixos-manual.nix5
-rw-r--r--nixos/modules/services/misc/ripple-data-api.nix168
-rw-r--r--nixos/modules/services/misc/rippled.nix511
-rw-r--r--nixos/modules/services/monitoring/cadvisor.nix10
-rw-r--r--nixos/modules/services/monitoring/munin.nix4
-rw-r--r--nixos/modules/services/monitoring/scollector.nix17
-rw-r--r--nixos/modules/services/monitoring/teamviewer.nix45
-rw-r--r--nixos/modules/services/network-filesystems/drbd.nix2
-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/aiccu.nix195
-rw-r--r--nixos/modules/services/networking/btsync.nix28
-rw-r--r--nixos/modules/services/networking/consul.nix7
-rw-r--r--nixos/modules/services/networking/ddclient.nix97
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix2
-rw-r--r--nixos/modules/services/networking/haproxy.nix43
-rw-r--r--nixos/modules/services/networking/networkmanager.nix42
-rw-r--r--nixos/modules/services/networking/nsd.nix40
-rw-r--r--nixos/modules/services/networking/rdnssd.nix50
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix21
-rw-r--r--nixos/modules/services/printing/cupsd.nix2
-rw-r--r--nixos/modules/services/security/munge.nix61
-rw-r--r--nixos/modules/services/system/dbus.nix3
-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/apache-httpd/owncloud.nix5
-rw-r--r--nixos/modules/services/web-servers/fcgiwrap.nix51
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix13
-rw-r--r--nixos/modules/services/x11/desktop-managers/xbmc.nix31
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix1
-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/hardware/multitouch.nix44
-rw-r--r--nixos/modules/services/x11/unclutter.nix33
-rw-r--r--nixos/modules/services/x11/window-managers/default.nix4
-rw-r--r--nixos/modules/services/x11/window-managers/spectrwm.nix33
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl157
-rw-r--r--nixos/modules/system/boot/loader/generations-dir/generations-dir.nix2
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix1
-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/luksroot.nix28
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh10
-rw-r--r--nixos/modules/system/boot/stage-1.nix79
-rw-r--r--nixos/modules/system/boot/systemd.nix4
-rw-r--r--nixos/modules/tasks/filesystems/btrfs.nix6
-rw-r--r--nixos/modules/tasks/filesystems/cifs.nix2
-rw-r--r--nixos/modules/tasks/filesystems/ext.nix5
-rw-r--r--nixos/modules/tasks/filesystems/f2fs.nix4
-rw-r--r--nixos/modules/tasks/filesystems/jfs.nix2
-rw-r--r--nixos/modules/tasks/filesystems/reiserfs.nix4
-rw-r--r--nixos/modules/tasks/filesystems/unionfs-fuse.nix5
-rw-r--r--nixos/modules/tasks/filesystems/vfat.nix2
-rw-r--r--nixos/modules/tasks/filesystems/xfs.nix2
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix16
-rw-r--r--nixos/modules/tasks/kbd.nix1
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix5
-rw-r--r--nixos/modules/tasks/trackpoint.nix6
-rw-r--r--nixos/modules/virtualisation/amazon-config.nix4
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix2
-rw-r--r--nixos/modules/virtualisation/containers.nix17
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix91
-rw-r--r--nixos/modules/virtualisation/lxc.nix11
-rw-r--r--nixos/modules/virtualisation/nixos-container.pl6
-rw-r--r--nixos/modules/virtualisation/parallels-guest.nix2
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixos/modules/virtualisation/xen-dom0.nix261
-rw-r--r--nixos/modules/virtualisation/xen-domU.nix5
-rw-r--r--nixos/release-combined.nix5
-rw-r--r--nixos/release-small.nix4
-rw-r--r--nixos/release.nix77
-rw-r--r--nixos/tests/boot.nix63
-rw-r--r--nixos/tests/chromium.nix7
-rw-r--r--nixos/tests/cjdns.nix25
-rw-r--r--nixos/tests/i3wm.nix28
-rw-r--r--nixos/tests/installer.nix12
-rw-r--r--nixos/tests/kubernetes.nix17
-rw-r--r--nixos/tests/misc.nix4
-rw-r--r--nixos/tests/nfs.nix2
-rw-r--r--nixos/tests/printing.nix4
-rw-r--r--nixos/tests/virtualbox.nix10
144 files changed, 3768 insertions, 1239 deletions
diff --git a/nixos/doc/manual/administration/declarative-containers.xml b/nixos/doc/manual/administration/declarative-containers.xml
index 177ebdd8db17..228c45b0c1fe 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
+corresponding systemd service, e.g. <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 2a58ff25941c..b613c7f06cc8 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 ceac40b7a1f6..b7e47b8729f3 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-install.xml b/nixos/doc/manual/man-nixos-install.xml
index 06e7b4a98470..7ad1be1ec105 100644
--- a/nixos/doc/manual/man-nixos-install.xml
+++ b/nixos/doc/manual/man-nixos-install.xml
@@ -26,6 +26,22 @@
       <replaceable>root</replaceable>
     </arg>
     <arg>
+      <group choice='req'>
+        <arg choice='plain'><option>--max-jobs</option></arg>
+        <arg choice='plain'><option>-j</option></arg>
+      </group>
+      <replaceable>number</replaceable>
+    </arg>
+    <arg>
+      <option>--cores</option>
+      <replaceable>number</replaceable>
+    </arg>
+    <arg>
+      <option>--option</option>
+      <replaceable>name</replaceable>
+      <replaceable>value</replaceable>
+    </arg>
+    <arg>
       <arg choice='plain'><option>--show-trace</option></arg>
     </arg>
     <arg>
@@ -96,6 +112,37 @@ it.</para>
     </listitem>
   </varlistentry>
 
+  <varlistentry><term><option>--max-jobs</option></term>
+    <term><option>-j</option></term>
+  
+    <listitem><para>Sets the maximum number of build jobs that Nix will
+    perform in parallel to the specified number. The default is <literal>1</literal>.
+    A higher value is useful on SMP systems or to exploit I/O latency.</para></listitem>
+  
+  </varlistentry>
+  
+  
+  <varlistentry><term><option>--cores</option></term>
+  
+    <listitem><para>Sets the value of the <envar>NIX_BUILD_CORES</envar>
+    environment variable in the invocation of builders.  Builders can
+    use this variable at their discretion to control the maximum amount
+    of parallelism.  For instance, in Nixpkgs, if the derivation
+    attribute <varname>enableParallelBuilding</varname> is set to
+    <literal>true</literal>, the builder passes the
+    <option>-j<replaceable>N</replaceable></option> flag to GNU Make.
+    The value <literal>0</literal> means that the builder should use all
+    available CPU cores in the system.</para></listitem>
+  
+  </varlistentry>
+
+  <varlistentry><term><option>--option</option> <replaceable>name</replaceable> <replaceable>value</replaceable></term>
+
+    <listitem><para>Set the Nix configuration option
+    <replaceable>name</replaceable> to <replaceable>value</replaceable>.</para></listitem>
+
+  </varlistentry>
+
   <varlistentry>
     <term><option>--show-trace</option></term>
     <listitem>
diff --git a/nixos/doc/manual/man-nixos-rebuild.xml b/nixos/doc/manual/man-nixos-rebuild.xml
index afc159dbd5d7..c529737c3bf3 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/eval-config.nix b/nixos/lib/eval-config.nix
index 08adcf3a0078..adacbd0863e3 100644
--- a/nixos/lib/eval-config.nix
+++ b/nixos/lib/eval-config.nix
@@ -2,27 +2,51 @@
 # configuration object (`config') from which we can retrieve option
 # values.
 
-{ system ? builtins.currentSystem
-, pkgs ? null
-, baseModules ? import ../modules/module-list.nix
-, extraArgs ? {}
+# !!! Please think twice before adding to this argument list!
+# Ideally eval-config.nix would be an extremely thin wrapper
+# around lib.evalModules, so that modular systems that have nixos configs
+# as subcomponents (e.g. the container feature, or nixops if network
+# expressions are ever made modular at the top level) can just use
+# types.submodule instead of using eval-config.nix
+{ # !!! system can be set modularly, would be nice to remove
+  system ? builtins.currentSystem
+, # !!! is this argument needed any more? The pkgs argument can
+  # be set modularly anyway.
+  pkgs ? null
+, # !!! what do we gain by making this configurable?
+  baseModules ? import ../modules/module-list.nix
+, # !!! See comment about args in lib/modules.nix
+  extraArgs ? {}
 , modules
-, check ? true
+, # !!! See comment about check in lib/modules.nix
+  check ? true
 , prefix ? []
+, lib ? import ../../lib
 }:
 
 let extraArgs_ = extraArgs; pkgs_ = pkgs; system_ = system;
     extraModules = let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
                    in if e == "" then [] else [(import (builtins.toPath e))];
+in
+
+let
+  pkgsModule = rec {
+    _file = ./eval-config.nix;
+    key = _file;
+    config = {
+      nixpkgs.system = lib.mkDefault system_;
+      _module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
+    };
+  };
+
 in rec {
 
   # Merge the option definitions in all modules, forming the full
   # system configuration.
-  inherit (pkgs.lib.evalModules {
-    inherit prefix;
-    modules = modules ++ extraModules ++ baseModules;
+  inherit (lib.evalModules {
+    inherit prefix check;
+    modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ];
     args = extraArgs;
-    check = check && options.environment.checkConfigurationOptions.value;
   }) config options;
 
   # These are the extra arguments passed to every module.  In
@@ -33,40 +57,8 @@ in rec {
   # the 64-bit package anyway. However, it would be cleaner to respect
   # nixpkgs.config here.
   extraArgs = extraArgs_ // {
-    inherit pkgs modules baseModules;
-    modulesPath = ../modules;
-    pkgs_i686 = import ./nixpkgs.nix { system = "i686-linux"; config.allowUnfree = true; };
-    utils = import ./utils.nix pkgs;
+    inherit modules baseModules;
   };
 
-  # Import Nixpkgs, allowing the NixOS option nixpkgs.config to
-  # specify the Nixpkgs configuration (e.g., to set package options
-  # such as firefox.enableGeckoMediaPlayer, or to apply global
-  # overrides such as changing GCC throughout the system), and the
-  # option nixpkgs.system to override the platform type.  This is
-  # tricky, because we have to prevent an infinite recursion: "pkgs"
-  # is passed as an argument to NixOS modules, but the value of "pkgs"
-  # depends on config.nixpkgs.config, which we get from the modules.
-  # So we call ourselves here with "pkgs" explicitly set to an
-  # instance that doesn't depend on nixpkgs.config.
-  pkgs =
-    if pkgs_ != null
-    then pkgs_
-    else import ./nixpkgs.nix (
-      let
-        system = if nixpkgsOptions.system != "" then nixpkgsOptions.system else system_;
-        nixpkgsOptions = (import ./eval-config.nix {
-          inherit system extraArgs modules prefix;
-          # For efficiency, leave out most NixOS modules; they don't
-          # define nixpkgs.config, so it's pointless to evaluate them.
-          baseModules = [ ../modules/misc/nixpkgs.nix ../modules/config/no-x-libs.nix ];
-          pkgs = import ./nixpkgs.nix { system = system_; config = {}; };
-          check = false;
-        }).config.nixpkgs;
-      in
-      {
-        inherit system;
-        inherit (nixpkgsOptions) config;
-      });
-
+  inherit (config._module.args) pkgs;
 }
diff --git a/nixos/lib/make-iso9660-image.nix b/nixos/lib/make-iso9660-image.nix
index 5ad546e9534d..b2409c6006bc 100644
--- a/nixos/lib/make-iso9660-image.nix
+++ b/nixos/lib/make-iso9660-image.nix
@@ -1,4 +1,4 @@
-{ stdenv, perl, cdrkit, pathsFromGraph
+{ stdenv, perl, pathsFromGraph, xorriso, syslinux
 
 , # The file name of the resulting ISO image.
   isoName ? "cd.iso"
@@ -22,12 +22,18 @@
 , # Whether this should be an efi-bootable El-Torito CD.
   efiBootable ? false
 
+, # Wheter this should be an hybrid CD (bootable from USB as well as CD).
+  usbBootable ? false
+
 , # The path (in the ISO file system) of the boot image.
   bootImage ? ""
 
 , # The path (in the ISO file system) of the efi boot image.
   efiBootImage ? ""
 
+, # The path (outside the ISO file system) of the isohybrid-mbr image.
+  isohybridMbrImage ? ""
+
 , # Whether to compress the resulting ISO image with bzip2.
   compressImage ? false
 
@@ -38,13 +44,14 @@
 
 assert bootable -> bootImage != "";
 assert efiBootable -> efiBootImage != "";
+assert usbBootable -> isohybridMbrImage != "";
 
 stdenv.mkDerivation {
   name = "iso9660-image";
   builder = ./make-iso9660-image.sh;
-  buildInputs = [perl cdrkit];
+  buildInputs = [perl xorriso syslinux];
 
-  inherit isoName bootable bootImage compressImage volumeID pathsFromGraph efiBootImage efiBootable;
+  inherit isoName bootable bootImage compressImage volumeID pathsFromGraph efiBootImage efiBootable isohybridMbrImage usbBootable;
 
   # !!! should use XML.
   sources = map (x: x.source) contents;
diff --git a/nixos/lib/make-iso9660-image.sh b/nixos/lib/make-iso9660-image.sh
index 675b5bb35148..c9a373794692 100644
--- a/nixos/lib/make-iso9660-image.sh
+++ b/nixos/lib/make-iso9660-image.sh
@@ -13,6 +13,20 @@ stripSlash() {
     if test "${res:0:1}" = /; then res=${res:1}; fi
 }
 
+# Escape potential equal signs (=) with backslash (\=)
+escapeEquals() {
+    echo "$1" | sed -e 's/\\/\\\\/g' -e 's/=/\\=/g'
+}
+
+# Queues an file/directory to be placed on the ISO.
+# An entry consists of a local source path (2) and
+# a destination path on the ISO (1).
+addPath() {
+    target="$1"
+    source="$2"
+    echo "$(escapeEquals "$target")=$(escapeEquals "$source")" >> pathlist
+}
+
 stripSlash "$bootImage"; bootImage="$res"
 
 
@@ -31,11 +45,20 @@ if test -n "$bootable"; then
         fi
     done
 
-    bootFlags="-b $bootImage -c .boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table"
+    isoBootFlags="-eltorito-boot ${bootImage}
+                  -eltorito-catalog .boot.cat
+                  -no-emul-boot -boot-load-size 4 -boot-info-table"
+fi
+
+if test -n "$usbBootable"; then
+    usbBootFlags="-isohybrid-mbr ${isohybridMbrImage}"
 fi
 
 if test -n "$efiBootable"; then
-    bootFlags="$bootFlags -eltorito-alt-boot -e $efiBootImage -no-emul-boot"
+    efiBootFlags="-eltorito-alt-boot
+                  -e $efiBootImage
+                  -no-emul-boot
+                  -isohybrid-gpt-basdat"
 fi
 
 touch pathlist
@@ -44,14 +67,14 @@ touch pathlist
 # Add the individual files.
 for ((i = 0; i < ${#targets_[@]}; i++)); do
     stripSlash "${targets_[$i]}"
-    echo "$res=${sources_[$i]}" >> pathlist
+    addPath "$res" "${sources_[$i]}"
 done
 
 
 # Add the closures of the top-level store objects.
 storePaths=$(perl $pathsFromGraph closure-*)
 for i in $storePaths; do
-    echo "${i:1}=$i" >> pathlist
+    addPath "${i:1}" "$i"
 done
 
 
@@ -59,7 +82,7 @@ done
 # nix-store --load-db.
 if [ -n "$object" ]; then
     printRegistration=1 perl $pathsFromGraph closure-* > nix-path-registration
-    echo "nix-path-registration=nix-path-registration" >> pathlist
+    addPath "nix-path-registration" "nix-path-registration"
 fi
 
 
@@ -70,22 +93,39 @@ for ((n = 0; n < ${#objects[*]}; n++)); do
     if test "$symlink" != "none"; then
         mkdir -p $(dirname ./$symlink)
         ln -s $object ./$symlink
-        echo "$symlink=./$symlink" >> pathlist
+        addPath "$symlink" "./$symlink"
     fi
 done
 
-# !!! what does this do?
-cat pathlist | sed -e 's/=\(.*\)=\(.*\)=/\\=\1=\2\\=/' | tee pathlist.safer
-
-
 mkdir -p $out/iso
-genCommand="genisoimage -iso-level 4 -r -J $bootFlags -hide-rr-moved -graft-points -path-list pathlist.safer ${volumeID:+-V $volumeID}"
-if test -z "$compressImage"; then
-    $genCommand -o $out/iso/$isoName
-else
-    $genCommand | bzip2 > $out/iso/$isoName.bz2
+
+xorriso="xorriso
+ -as mkisofs
+ -iso-level 3
+ -volid ${volumeID}
+ -appid nixos
+ -publisher nixos
+ -graft-points
+ -full-iso9660-filenames
+ ${isoBootFlags}
+ ${usbBootFlags}
+ ${efiBootFlags}
+ -r
+ -path-list pathlist
+ --sort-weight 0 /
+ --sort-weight 1 /isolinux" # Make sure isolinux is near the beginning of the ISO
+
+$xorriso -output $out/iso/$isoName
+
+if test -n "$usbBootable"; then
+    echo "Making image hybrid..."
+    isohybrid --uefi $out/iso/$isoName
 fi
 
+if test -n "$compressImage"; then
+    echo "Compressing image..."
+    bzip2 $out/iso/$isoName
+fi
 
 mkdir -p $out/nix-support
 echo $system > $out/nix-support/system
diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm
index 85c2bfa88e1a..e0791692d3ef 100644
--- a/nixos/lib/test-driver/Machine.pm
+++ b/nixos/lib/test-driver/Machine.pm
@@ -37,6 +37,10 @@ sub new {
             if defined $args->{hda};
         $startCommand .= "-cdrom $args->{cdrom} "
             if defined $args->{cdrom};
+        $startCommand .= "-device piix3-usb-uhci -drive id=usbdisk,file=$args->{usb},if=none,readonly -device usb-storage,drive=usbdisk "
+            if defined $args->{usb};
+        $startCommand .= "-bios $args->{bios} "
+            if defined $args->{bios};
         $startCommand .= $args->{qemuFlags} || "";
     } else {
         $startCommand = Cwd::abs_path $startCommand;
diff --git a/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix b/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix
index 530769cec5b7..c0ec38bf489a 100644
--- a/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix
+++ b/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix
@@ -23,9 +23,9 @@ in
   boot.kernelParams = [ "console=ttyS0" ];
 
   boot.initrd.extraUtilsCommands = ''
-    cp -v ${pkgs.gawk}/bin/gawk $out/bin/gawk
-    cp -v ${pkgs.gnused}/bin/sed $out/bin/gnused
-    cp -v ${pkgs.utillinux}/sbin/sfdisk $out/bin/sfdisk
+    copy_bin_and_libs ${pkgs.gawk}/bin/gawk
+    copy_bin_and_libs ${pkgs.gnused}/bin/sed
+    copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk
     cp -v ${growpart} $out/bin/growpart
   '';
   boot.initrd.postDeviceCommands = ''
diff --git a/nixos/modules/config/fonts/fontconfig-ultimate.nix b/nixos/modules/config/fonts/fontconfig-ultimate.nix
index 853f253ff9bc..02568f9de51e 100644
--- a/nixos/modules/config/fonts/fontconfig-ultimate.nix
+++ b/nixos/modules/config/fonts/fontconfig-ultimate.nix
@@ -1,6 +1,6 @@
-{ config, pkgs, ... }:
+{ config, pkgs, lib, ... }:
 
-with pkgs.lib;
+with lib;
 
 let fcBool = x: if x then "<bool>true</bool>" else "<bool>false</bool>";
 in
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix
index 47393c9d3f5c..13477337bda5 100644
--- a/nixos/modules/config/no-x-libs.nix
+++ b/nixos/modules/config/no-x-libs.nix
@@ -27,6 +27,6 @@ with lib;
     fonts.fontconfig.enable = false;
 
     nixpkgs.config.packageOverrides = pkgs:
-      { dbus = pkgs.dbus.override { useX11 = false; }; };
+      { dbus = pkgs.dbus.override { x11Support = false; }; };
   };
 }
diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix
index 549e731f3b08..a39c2895bf84 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/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix
index 8b38489a8c19..c41e4ea604d5 100644
--- a/nixos/modules/config/pulseaudio.nix
+++ b/nixos/modules/config/pulseaudio.nix
@@ -124,9 +124,7 @@ in {
     }
 
     (mkIf cfg.enable {
-      environment.systemPackages = [
-        cfg.package
-      ] ++ lib.optionals enable32BitAlsaPlugins [ pkgs_i686.pulseaudio ];
+      environment.systemPackages = [ cfg.package ];
 
       environment.etc = singleton {
         target = "asound.conf";
diff --git a/nixos/modules/config/sysctl.nix b/nixos/modules/config/sysctl.nix
index 3b6ccd380c75..e83562a8356e 100644
--- a/nixos/modules/config/sysctl.nix
+++ b/nixos/modules/config/sysctl.nix
@@ -64,6 +64,6 @@ in
     #
     # Removed under grsecurity.
     boot.kernel.sysctl."kernel.kptr_restrict" =
-      if config.security.grsecurity.enable then null else 1;
+      if (config.boot.kernelPackages.kernel.features.grsecurity or false) then null else 1;
   };
 }
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index d35ecb754bdb..de73de91629b 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 f585a2774799..9d48edf2f26c 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -110,7 +110,7 @@ let
 
       shell = mkOption {
         type = types.str;
-        default = "/run/current-system/sw/sbin/nologin";
+        default = "/run/current-system/sw/bin/nologin";
         description = "The path to the user's shell.";
       };
 
@@ -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/cpu/amd-microcode.nix b/nixos/modules/hardware/cpu/amd-microcode.nix
index 86a3df5da21d..d44f01a49590 100644
--- a/nixos/modules/hardware/cpu/amd-microcode.nix
+++ b/nixos/modules/hardware/cpu/amd-microcode.nix
@@ -22,8 +22,7 @@ with lib;
   ###### implementation
 
   config = mkIf config.hardware.cpu.amd.updateMicrocode {
-    hardware.firmware = [ "${pkgs.amdUcode}/lib/firmware" ];
-    boot.kernelModules = [ "microcode" ];
+    boot.initrd.prepend = [ "${pkgs.microcodeAmd}/amd-ucode.img" ];
   };
 
 }
diff --git a/nixos/modules/hardware/cpu/intel-microcode.nix b/nixos/modules/hardware/cpu/intel-microcode.nix
index 800c391b293a..89ae4f45806c 100644
--- a/nixos/modules/hardware/cpu/intel-microcode.nix
+++ b/nixos/modules/hardware/cpu/intel-microcode.nix
@@ -22,8 +22,7 @@ with lib;
   ###### implementation
 
   config = mkIf config.hardware.cpu.intel.updateMicrocode {
-    hardware.firmware = [ "${pkgs.microcodeIntel}/lib/firmware" ];
-    boot.kernelModules = [ "microcode" ];
+    boot.initrd.prepend = [ "${pkgs.microcodeIntel}/intel-ucode.img" ];
   };
 
 }
diff --git a/nixos/modules/hardware/ksm.nix b/nixos/modules/hardware/ksm.nix
new file mode 100644
index 000000000000..d6ac69b5d65e
--- /dev/null
+++ b/nixos/modules/hardware/ksm.nix
@@ -0,0 +1,18 @@
+{ config, lib, ... }:
+
+{
+  options.hardware.enableKSM = lib.mkEnableOption "Kernel Same-Page Merging";
+
+  config = lib.mkIf config.hardware.enableKSM {
+    systemd.services.enable-ksm = {
+      description = "Enable Kernel Same-Page Merging";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "systemd-udev-settle.service" ];
+      script = ''
+        if [ -e /sys/kernel/mm/ksm ]; then
+          echo 1 > /sys/kernel/mm/ksm/run
+        fi
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 2b20dc7395af..711576982ec3 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -13,7 +13,7 @@ let
   # driver.
   nvidiaForKernel = kernelPackages:
     if elem "nvidia" drivers then
-      kernelPackages.nvidia_x11
+        kernelPackages.nvidia_x11
     else if elem "nvidiaLegacy173" drivers then
       kernelPackages.nvidia_x11_legacy173
     else if elem "nvidiaLegacy304" drivers then
@@ -47,6 +47,15 @@ in
 
     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/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
index b723a91e4f35..4896eee29084 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -36,6 +36,9 @@ with lib;
   # EFI booting
   isoImage.makeEfiBootable = true;
 
+  # USB booting
+  isoImage.makeUsbBootable = true;
+
   # Add Memtest86+ to the CD.
   boot.loader.grub.memtest86.enable = true;
 
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 39db7d9b8f72..d9d7254aba25 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -7,66 +7,89 @@
 with lib;
 
 let
-
-  # The Grub image.
-  grubImage = pkgs.runCommand "grub_eltorito" {}
+  # Timeout in syslinux is in units of 1/10 of a second.
+  # 0 is used to disable timeouts.
+  syslinuxTimeout = if config.boot.loader.timeout == null then
+      0
+    else
+      max (config.boot.loader.timeout * 10) 1;
+
+
+  max = x: y: if x > y then x else y;
+
+  # The configuration file for syslinux.
+
+  # Notes on syslinux configuration and UNetbootin compatiblity:
+  #   * Do not use '/syslinux/syslinux.cfg' as the path for this
+  #     configuration. UNetbootin will not parse the file and use it as-is.
+  #     This results in a broken configuration if the partition label does
+  #     not match the specified config.isoImage.volumeID. For this reason
+  #     we're using '/isolinux/isolinux.cfg'.
+  #   * Use APPEND instead of adding command-line arguments directly after
+  #     the LINUX entries.
+  #   * COM32 entries (chainload, reboot, poweroff) are not recognized. They
+  #     result in incorrect boot entries.
+
+  baseIsolinuxCfg =
     ''
-      ${pkgs.grub2}/bin/grub-mkimage -p /boot/grub -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
-      cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out
-    ''; # */
-
-
-  # The configuration file for Grub.
-  grubCfg =
-    ''
-      set default=${builtins.toString config.boot.loader.grub.default}
-      set timeout=${builtins.toString config.boot.loader.grub.timeout}
-
-      if loadfont /boot/grub/unicode.pf2; then
-        set gfxmode=640x480
-        insmod gfxterm
-        insmod vbe
-        terminal_output gfxterm
-
-        insmod png
-        if background_image /boot/grub/splash.png; then
-          set color_normal=white/black
-          set color_highlight=black/white
-        else
-          set menu_color_normal=cyan/blue
-          set menu_color_highlight=white/blue
-        fi
-
-      fi
-
-      ${config.boot.loader.grub.extraEntries}
+    SERIAL 0 38400
+    TIMEOUT ${builtins.toString syslinuxTimeout}
+    UI vesamenu.c32
+    MENU TITLE NixOS
+    MENU BACKGROUND /isolinux/background.png
+    DEFAULT boot
+
+    LABEL boot
+    MENU LABEL NixOS ${config.system.nixosVersion} Installer
+    LINUX /boot/bzImage
+    APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+    INITRD /boot/initrd
     '';
 
+  isolinuxMemtest86Entry = ''
+    LABEL memtest
+    MENU LABEL Memtest86+
+    LINUX /boot/memtest.bin
+    APPEND ${toString config.boot.loader.grub.memtest86.params}
+  '';
+
+  isolinuxCfg = baseIsolinuxCfg + (optionalString config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
 
   # The efi boot image
   efiDir = pkgs.runCommand "efi-directory" {} ''
-    mkdir -p $out/efi/boot
-    cp -v ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi $out/efi/boot/boot${targetArch}.efi
+    mkdir -p $out/EFI/boot
+    cp -v ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi $out/EFI/boot/boot${targetArch}.efi
     mkdir -p $out/loader/entries
     echo "title NixOS LiveCD" > $out/loader/entries/nixos-livecd.conf
     echo "linux /boot/bzImage" >> $out/loader/entries/nixos-livecd.conf
     echo "initrd /boot/initrd" >> $out/loader/entries/nixos-livecd.conf
     echo "options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" >> $out/loader/entries/nixos-livecd.conf
     echo "default nixos-livecd" > $out/loader/loader.conf
-    echo "timeout 5" >> $out/loader/loader.conf
+    echo "timeout ${builtins.toString config.boot.loader.gummiboot.timeout}" >> $out/loader/loader.conf
   '';
 
-  efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools ]; }
+  efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools pkgs.libfaketime ]; }
+    # Be careful about determinism: du --apparent-size,
+    #   dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
     ''
-      #Let's hope 15M is enough
-      dd bs=2048 count=7680 if=/dev/zero of="$out"
-      ${pkgs.dosfstools}/sbin/mkfs.vfat "$out"
-      mcopy -svi "$out" ${efiDir}/* ::
-      mmd -i "$out" boot
-      mcopy -v -i "$out" \
-        ${config.boot.kernelPackages.kernel}/bzImage ::boot/bzImage
-      mcopy -v -i "$out" \
-        ${config.system.build.initialRamdisk}/initrd ::boot/initrd
+      mkdir ./contents && cd ./contents
+      cp -rp "${efiDir}"/* .
+      mkdir ./boot
+      cp -p "${config.boot.kernelPackages.kernel}/bzImage" \
+        "${config.system.build.initialRamdisk}/initrd" ./boot/
+      touch --date=@0 ./*
+
+      usage_size=$(du -sb --apparent-size . | tr -cd '[:digit:]')
+      # Make the image 110% as big as the files need to make up for FAT overhead
+      image_size=$(( ($usage_size * 110) / 100 ))
+      # Make the image fit blocks of 1M
+      block_size=$((1024*1024))
+      image_size=$(( ($image_size / $block_size + 1) * $block_size ))
+      echo "Usage size: $usage_size"
+      echo "Image size: $image_size"
+      truncate --size=$image_size "$out"
+      ${pkgs.libfaketime}/bin/faketime "2000-01-01 00:00:00" ${pkgs.dosfstools}/sbin/mkfs.vfat -i 12345678 -n EFIBOOT "$out"
+      mcopy -bpsvm -i "$out" ./* ::
     ''; # */
 
   targetArch = if pkgs.stdenv.isi686 then
@@ -152,9 +175,24 @@ in
       '';
     };
 
+    isoImage.makeUsbBootable = mkOption {
+      default = false;
+      description = ''
+        Whether the ISO image should be bootable from CD as well as USB.
+      '';
+    };
 
-  };
+    isoImage.splashImage = mkOption {
+      default = pkgs.fetchurl {
+          url = https://raw.githubusercontent.com/NixOS/nixos-artwork/5729ab16c6a5793c10a2913b5a1b3f59b91c36ee/ideas/grub-splash/grub-nixos-1.png;
+          sha256 = "43fd8ad5decf6c23c87e9026170a13588c2eba249d9013cb9f888da5e2002217";
+        };
+      description = ''
+        The splash image to use in the bootloader.
+      '';
+    };
 
+  };
 
   config = {
 
@@ -166,7 +204,7 @@ in
 
     # !!! Hack - attributes expected by other modules.
     system.boot.loader.kernelFile = "bzImage";
-    environment.systemPackages = [ pkgs.grub2 ];
+    environment.systemPackages = [ pkgs.grub2 pkgs.syslinux ];
 
     # In stage 1 of the boot, mount the CD as the root FS by label so
     # that we don't need to know its device.  We pass the label of the
@@ -216,7 +254,7 @@ in
         options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro";
       };
 
-    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" ];
+    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" ];
 
     boot.initrd.kernelModules = [ "loop" ];
 
@@ -236,15 +274,12 @@ in
     # Individual files to be included on the CD, outside of the Nix
     # store on the CD.
     isoImage.contents =
-      [ { source = grubImage;
-          target = "/boot/grub/grub_eltorito";
-        }
-        { source = pkgs.substituteAll  {
-            name = "grub.cfg";
-            src = pkgs.writeText "grub.cfg-in" grubCfg;
+      [ { source = pkgs.substituteAll  {
+            name = "isolinux.cfg";
+            src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
             bootRoot = "/boot";
           };
-          target = "/boot/grub/grub.cfg";
+          target = "/isolinux/isolinux.cfg";
         }
         { source = config.boot.kernelPackages.kernel + "/bzImage";
           target = "/boot/bzImage";
@@ -252,51 +287,44 @@ in
         { source = config.system.build.initialRamdisk + "/initrd";
           target = "/boot/initrd";
         }
-        { source = "${pkgs.grub2}/share/grub/unicode.pf2";
-          target = "/boot/grub/unicode.pf2";
-        }
-        { source = config.boot.loader.grub.splashImage;
-          target = "/boot/grub/splash.png";
-        }
         { source = config.system.build.squashfsStore;
           target = "/nix-store.squashfs";
         }
+        { source = "${pkgs.syslinux}/share/syslinux";
+          target = "/isolinux";
+        }
+        { source = config.isoImage.splashImage;
+          target = "/isolinux/background.png";
+        }
       ] ++ optionals config.isoImage.makeEfiBootable [
         { source = efiImg;
           target = "/boot/efi.img";
         }
-        { source = "${efiDir}/efi";
-          target = "/efi";
+        { source = "${efiDir}/EFI";
+          target = "/EFI";
         }
         { source = "${efiDir}/loader";
           target = "/loader";
         }
-      ] ++ mapAttrsToList (n: v: { source = v; target = "/boot/${n}"; }) config.boot.loader.grub.extraFiles;
-
-    # The Grub menu.
-    boot.loader.grub.extraEntries =
-      ''
-        menuentry "NixOS ${config.system.nixosVersion} Installer" {
-          linux /boot/bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
-          initrd /boot/initrd
-        }
-
-        menuentry "Boot from hard disk" {
-          set root=(hd0)
-          chainloader +1
+      ] ++ optionals config.boot.loader.grub.memtest86.enable [
+        { source = "${pkgs.memtest86plus}/memtest.bin";
+          target = "/boot/memtest.bin";
         }
-      '';
+      ];
 
-    boot.loader.grub.timeout = 10;
+    boot.loader.timeout = 10;
 
     # Create the ISO image.
     system.build.isoImage = import ../../../lib/make-iso9660-image.nix ({
-      inherit (pkgs) stdenv perl cdrkit pathsFromGraph;
+      inherit (pkgs) stdenv perl pathsFromGraph xorriso syslinux;
 
       inherit (config.isoImage) isoName compressImage volumeID contents;
 
       bootable = true;
-      bootImage = "/boot/grub/grub_eltorito";
+      bootImage = "/isolinux/isolinux.bin";
+    } // optionalAttrs config.isoImage.makeUsbBootable {
+      usbBootable = true;
+      isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
     } // optionalAttrs config.isoImage.makeEfiBootable {
       efiBootable = true;
       efiBootImage = "boot/efi.img";
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
index 4ce7582c166a..46dc1c705022 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
+++ b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
@@ -98,7 +98,7 @@ in
 
   boot.initrd.extraUtilsCommands =
     ''
-      cp ${pkgs.utillinux}/sbin/hwclock $out/bin
+      copy_bin_and_libs ${pkgs.utillinux}/sbin/hwclock
     '';
 
   boot.initrd.postDeviceCommands =
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 43a83e0206de..eadaae6715b4 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -148,7 +148,7 @@ sub pciCheck {
          $device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1"
         ) )
      {
-        push @modulePackages, "config.boot.kernelPackages.broadcom_sta";
+        push @modulePackages, "\${config.boot.kernelPackages.broadcom_sta}";
         push @kernelModules, "wl";
      }
 
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index bfb42d40b06e..14ae3daace0b 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -28,9 +28,14 @@ chrootCommand=(/run/current-system/sw/bin/bash)
 while [ "$#" -gt 0 ]; do
     i="$1"; shift 1
     case "$i" in
-        -I)
-            given_path="$1"; shift 1
-            extraBuildFlags+=("$i" "$given_path")
+        --max-jobs|-j|--cores|-I)
+            j="$1"; shift 1
+            extraBuildFlags+=("$i" "$j")
+            ;;
+        --option)
+            j="$1"; shift 1
+            k="$1"; shift 1
+            extraBuildFlags+=("$i" "$j" "$k")
             ;;
         --root)
             mountPoint="$1"; shift 1
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 8157f8fc7da5..1d6df8cb3f71 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/misc/check-config.nix b/nixos/modules/misc/check-config.nix
deleted file mode 100644
index e9803de21961..000000000000
--- a/nixos/modules/misc/check-config.nix
+++ /dev/null
@@ -1,15 +0,0 @@
-{ lib, ... }:
-
-with lib;
-
-{
-  options = {
-    environment.checkConfigurationOptions = mkOption {
-      type = types.bool;
-      default = true;
-      description = ''
-        Whether to check the validity of the entire configuration.
-      '';
-    };
-  };
-}
diff --git a/nixos/modules/misc/extra-arguments.nix b/nixos/modules/misc/extra-arguments.nix
new file mode 100644
index 000000000000..c2c8903546d5
--- /dev/null
+++ b/nixos/modules/misc/extra-arguments.nix
@@ -0,0 +1,14 @@
+{ lib, pkgs, config, ... }:
+
+{
+  _module.args = {
+    modulesPath = ../.;
+
+    pkgs_i686 = import ../../lib/nixpkgs.nix {
+      system = "i686-linux";
+      config.allowUnfree = true;
+    };
+
+    utils = import ../../lib/utils.nix pkgs;
+  };
+}
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 0c863ec8de1c..c2523a3cc329 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -27,28 +27,38 @@
 
     ids.uids = {
       root = 0;
-      nscd = 1;
-      sshd = 2;
-      ntp = 3;
+      #wheel = 1; # unused
+      #kmem = 2; # unused
+      #tty = 3; # unused
       messagebus = 4; # D-Bus
       haldaemon = 5;
-      nagios = 6;
+      #disk = 6; # unused
       vsftpd = 7;
       ftp = 8;
       bitlbee = 9;
       avahi = 10;
+      nagios = 11;
       atd = 12;
-      zabbix = 13;
-      postfix = 14;
+      postfix = 13;
+      #postdrop = 14; # unused
       dovecot = 15;
       tomcat = 16;
+      #audio = 17; # unused
+      #floppy = 18; # unused
+      #uucp = 19; # unused
+      #lp = 20; # unused
       pulseaudio = 22; # must match `pulseaudio' GID
       gpsd = 23;
+      #cdrom = 24; # unused
+      #tape = 25; # unused
+      #video = 26; # unused
+      #dialout = 27; # unused
       polkituser = 28;
-      uptimed = 29;
+      #utmp = 29; # unused
       ddclient = 30;
       davfs2 = 31;
       privoxy = 32;
+      #disnix = 33; # unused
       osgi = 34;
       tor = 35;
       cups = 36;
@@ -70,18 +80,25 @@
       fprot = 52;
       bind = 53;
       wwwrun = 54;
+      #adm = 55; # unused
       spamd = 56;
+      #networkmanager = 57; # unused
       nslcd = 58;
+      #scanner = 59; # unused
       nginx = 60;
       chrony = 61;
+      #systemd-journal = 62; # unused
       smtpd = 63;
       smtpq = 64;
       supybot = 65;
       iodined = 66;
+      #libvirtd = 67; # unused
       graphite = 68;
       statsd = 69;
       transmission = 70;
       postgres = 71;
+      #vboxusers = 72; # unused
+      #vboxsf = 73; # unused
       smbguest = 74;  # unused
       varnish = 75;
       datadog = 76;
@@ -102,13 +119,13 @@
       minidlna = 91;
       elasticsearch = 92;
       tcpcryptd = 93; # tcpcryptd uses a hard-coded uid. We patch it in Nixpkgs to match this choice.
-      zope2 = 94;
+      #connman = 94; # unused
       firebird = 95;
-      redis = 96;
+      #keys = 96; # unused
       haproxy = 97;
       mongodb = 98;
       openldap = 99;
-      memcached = 100;
+      #users = 100; # unused
       cgminer = 101;
       munin = 102;
       logcheck = 103;
@@ -129,6 +146,7 @@
       foundationdb = 118;
       newrelic = 119;
       starbound = 120;
+      #grsecurity = 121; # unused
       hydra = 122;
       spiped = 123;
       teamspeak = 124;
@@ -138,7 +156,7 @@
       znc = 128;
       polipo = 129;
       mopidy = 130;
-      unifi = 131;
+      #docker = 131; # unused
       gdm = 132;
       dhcpd = 133;
       siproxd = 134;
@@ -180,6 +198,22 @@
       panamax = 170;
       marathon = 171;
       exim = 172;
+      #fleet = 173; # unused
+      #input = 174; # unused
+      sddm = 175;
+      tss = 176;
+      memcached = 177;
+      nscd = 178;
+      ntp = 179;
+      zabbix = 180;
+      redis = 181;
+      sshd = 182;
+      unifi = 183;
+      uptimed = 184;
+      zope2 = 185;
+      ripple-data-api = 186;
+      mediatomb = 187;
+      rdnssd = 188;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -199,15 +233,16 @@
       ftp = 8;
       bitlbee = 9;
       avahi = 10;
+      #nagios = 11; # unused
       atd = 12;
       postfix = 13;
       postdrop = 14;
       dovecot = 15;
+      tomcat = 16;
       audio = 17;
       floppy = 18;
       uucp = 19;
       lp = 20;
-      tomcat = 21;
       pulseaudio = 22; # must match `pulseaudio' UID
       gpsd = 23;
       cdrom = 24;
@@ -216,21 +251,30 @@
       dialout = 27;
       #polkituser = 28; # currently unused, polkitd doesn't need a group
       utmp = 29;
+      #ddclient = 30; # unused
       davfs2 = 31;
       privoxy = 32;
       disnix = 33;
       osgi = 34;
       tor = 35;
-      ghostOne = 40;
+      #cups = 36; # unused
+      #foldingathome = 37; # unused
+      #sabnzd = 38; # unused
+      #kdm = 39; # unused
+      ghostone = 40;
       git = 41;
       fourstore = 42;
-      fourstorehttpd = 43;
+      fourstorehttp = 43;
       virtuoso = 44;
+      #rtkit = 45; # unused
       dovecot2 = 46;
+      #dovenull = 47; # unused
+      #unbound = 48; # unused
       prayer = 49;
       mpd = 50;
       clamav = 51;
       fprot = 52;
+      #bind = 53; # unused
       wwwrun = 54;
       adm = 55;
       spamd = 56;
@@ -238,6 +282,7 @@
       nslcd = 58;
       scanner = 59;
       nginx = 60;
+      #chrony = 61; # unused
       systemd-journal = 62;
       smtpd = 63;
       smtpq = 64;
@@ -245,6 +290,7 @@
       iodined = 66;
       libvirtd = 67;
       graphite = 68;
+      #statsd = 69; # unused
       transmission = 70;
       postgres = 71;
       vboxusers = 72;
@@ -267,11 +313,17 @@
       quassel = 89;
       amule = 90;
       minidlna = 91;
-      haproxy = 92;
-      openldap = 93;
+      #elasticsearch = 92; # unused
+      #tcpcryptd = 93; # unused
       connman = 94;
-      munin = 95;
+      firebird = 95;
       keys = 96;
+      haproxy = 97;
+      #mongodb = 98; # unused
+      openldap = 99;
+      munin = 102;
+      #logcheck = 103; # unused
+      #nix-ssh = 104; # unused
       dictd = 105;
       couchdb = 106;
       searx = 107;
@@ -279,8 +331,12 @@
       jenkins = 109;
       systemd-journal-gateway = 110;
       notbit = 111;
+      #ngircd = 112; # unused
       btsync = 113;
+      #minecraft = 114; # unused
       monetdb = 115;
+      #ripped = 116; # unused
+      #murmur = 117; # unused
       foundationdb = 118;
       newrelic = 119;
       starbound = 120;
@@ -290,37 +346,65 @@
       teamspeak = 124;
       influxdb = 125;
       nsd = 126;
-      firebird = 127;
+      #gitolite = 127; # unused
       znc = 128;
       polipo = 129;
       mopidy = 130;
       docker = 131;
       gdm = 132;
-      tss = 133;
+      #dhcpcd = 133; # unused
       siproxd = 134;
       mlmmj = 135;
+      #neo4j = 136; # unused
       riemann = 137;
       riemanndash = 138;
-      hbase = 139;
-      opentsdb = 140;
+      #radvd = 139; # unused
+      #zookeeper = 140; # unused
+      #dnsmasq = 141; # unused
       uhub = 142;
+      #yandexdisk = 143; # unused
+      #collectd = 144; # unused
+      #consul = 145; # unused
       mailpile = 146;
       redmine = 147;
       seeks = 148;
       prosody = 149;
       i2pd = 150;
+      #dnscrypt-proxy = 151; # unused
       systemd-network = 152;
       systemd-resolve = 153;
       systemd-timesync = 154;
       liquidsoap = 155;
-      fleet = 159;
+      #etcd = 156; # unused
+      #docker-registry = 157; # unused
+      hbase = 158;
+      opentsdb = 159;
       scollector = 160;
       bosun = 161;
       kubernetes = 162;
+      #peerflix = 163; # unused
+      #chronos = 164; # unused
       gitlab = 165;
-      nylon = 166;
+      nylon = 168;
       panamax = 170;
+      #marathon = 171; # unused
       exim = 172;
+      fleet = 173;
+      input = 174;
+      sddm = 175;
+      tss = 176;
+      #memcached = 177; # unused
+      #nscd = 178; # unused
+      #ntp = 179; # unused
+      #zabbix = 180; # unused
+      #redis = 181; # unused
+      #sshd = 182; # unused
+      #unifi = 183; # unused
+      #uptimed = 184; # unused
+      #zope2 = 185; # unused
+      #ripple-data-api = 186; #unused
+      mediatomb = 187;
+      #rdnssd = 188; # unused
 
       # 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/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix
index f41c8817ba4a..114feb2562db 100644
--- a/nixos/modules/misc/nixpkgs.nix
+++ b/nixos/modules/misc/nixpkgs.nix
@@ -59,7 +59,8 @@ in
     };
 
     nixpkgs.system = mkOption {
-      type = types.str;
+      type = types.uniq types.str;
+      example = "i686-linux";
       description = ''
         Specifies the Nix platform type for which NixOS should be built.
         If unset, it defaults to the platform type of your host system.
@@ -71,6 +72,10 @@ in
   };
 
   config = {
-    nixpkgs.system = mkDefault pkgs.stdenv.system;
+    _module.args.pkgs = import ../../lib/nixpkgs.nix {
+      system = config.nixpkgs.system;
+
+      inherit (config.nixpkgs) config;
+    };
   };
 }
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index c41ae69c1ace..17717c5988dc 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -29,6 +29,7 @@
   ./hardware/all-firmware.nix
   ./hardware/cpu/amd-microcode.nix
   ./hardware/cpu/intel-microcode.nix
+  ./hardware/ksm.nix
   ./hardware/network/b43.nix
   ./hardware/network/intel-2100bg.nix
   ./hardware/network/intel-2200bg.nix
@@ -43,8 +44,8 @@
   ./installer/tools/nixos-checkout.nix
   ./installer/tools/tools.nix
   ./misc/assertions.nix
-  ./misc/check-config.nix
   ./misc/crashdump.nix
+  ./misc/extra-arguments.nix
   ./misc/ids.nix
   ./misc/lib.nix
   ./misc/locate.nix
@@ -60,6 +61,7 @@
   ./programs/dconf.nix
   ./programs/environment.nix
   ./programs/info.nix
+  ./programs/ibus.nix
   ./programs/light.nix
   ./programs/nano.nix
   ./programs/screen.nix
@@ -90,8 +92,9 @@
   ./services/amqp/activemq/default.nix
   ./services/amqp/rabbitmq.nix
   ./services/audio/alsa.nix
-  # Disabled as fuppes it does no longer builds.
+  # Disabled as fuppes no longer builds.
   # ./services/audio/fuppes.nix
+  ./services/audio/icecast.nix
   ./services/audio/liquidsoap.nix
   ./services/audio/mpd.nix
   ./services/audio/mopidy.nix
@@ -108,6 +111,7 @@
   ./services/cluster/panamax.nix
   ./services/computing/torque/server.nix
   ./services/computing/torque/mom.nix
+  ./services/computing/slurm/slurm.nix
   ./services/continuous-integration/jenkins/default.nix
   ./services/continuous-integration/jenkins/slave.nix
   ./services/databases/4store-endpoint.nix
@@ -143,6 +147,7 @@
   ./services/desktops/telepathy.nix
   ./services/games/ghost-one.nix
   ./services/games/minecraft-server.nix
+  ./services/games/minetest-server.nix
   ./services/hardware/acpid.nix
   ./services/hardware/amd-hybrid-graphics.nix
   ./services/hardware/bluetooth.nix
@@ -158,6 +163,7 @@
   ./services/hardware/udisks2.nix
   ./services/hardware/upower.nix
   ./services/hardware/thermald.nix
+  ./services/logging/fluentd.nix
   ./services/logging/klogd.nix
   ./services/logging/logcheck.nix
   ./services/logging/logrotate.nix
@@ -187,6 +193,7 @@
   ./services/misc/gitlab.nix
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
+  ./services/misc/mediatomb.nix
   ./services/misc/mesos-master.nix
   ./services/misc/mesos-slave.nix
   ./services/misc/nix-daemon.nix
@@ -197,6 +204,7 @@
   ./services/misc/phd.nix
   ./services/misc/redmine.nix
   ./services/misc/rippled.nix
+  ./services/misc/ripple-data-api.nix
   ./services/misc/rogue.nix
   ./services/misc/siproxd.nix
   ./services/misc/svnserve.nix
@@ -218,6 +226,7 @@
   ./services/monitoring/smartd.nix
   ./services/monitoring/statsd.nix
   ./services/monitoring/systemhealth.nix
+  ./services/monitoring/teamviewer.nix
   ./services/monitoring/ups.nix
   ./services/monitoring/uptime.nix
   ./services/monitoring/zabbix-agent.nix
@@ -228,7 +237,9 @@
   ./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/aiccu.nix
   ./services/networking/amuled.nix
   ./services/networking/atftpd.nix
   ./services/networking/avahi-daemon.nix
@@ -325,6 +336,7 @@
   ./services/security/fprot.nix
   ./services/security/frandom.nix
   ./services/security/haveged.nix
+  ./services/security/munge.nix
   ./services/security/torify.nix
   ./services/security/tor.nix
   ./services/security/torsocks.nix
@@ -352,12 +364,14 @@
   ./services/web-servers/varnish/default.nix
   ./services/web-servers/winstone.nix
   ./services/web-servers/zope2.nix
+  ./services/x11/unclutter.nix
   ./services/x11/desktop-managers/default.nix
   ./services/x11/display-managers/auto.nix
   ./services/x11/display-managers/default.nix
   ./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
@@ -432,5 +446,5 @@
   ./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/ibus.nix b/nixos/modules/programs/ibus.nix
new file mode 100644
index 000000000000..b8702a743d8a
--- /dev/null
+++ b/nixos/modules/programs/ibus.nix
@@ -0,0 +1,51 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.ibus;
+in
+{
+  options = {
+
+    programs.ibus = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "Enable IBus input method";
+      };
+      plugins = mkOption {
+        type = lib.types.listOf lib.types.path;
+        default = [];
+        description = ''
+          IBus plugin packages
+        '';
+      };
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.ibus ];
+
+    gtkPlugins = [ pkgs.ibus ];
+    qtPlugins = [ pkgs.ibus-qt ];
+
+    environment.variables =
+      let
+        env = pkgs.buildEnv {
+          name = "ibus-env";
+          paths = [ pkgs.ibus ] ++ cfg.plugins;
+        };
+      in {
+        GTK_IM_MODULE = "ibus";
+        QT_IM_MODULE = "ibus";
+        XMODIFIERS = "@im=ibus";
+
+        IBUS_COMPONENT_PATH = "${env}/share/ibus/component";
+      };
+
+    services.xserver.displayManager.sessionCommands = "${pkgs.ibus}/bin/ibus-daemon --daemonize --xim --cache=none";
+  };
+}
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 5c2ea07c5549..895ecb122cb6 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -100,7 +100,7 @@ in
         chgpasswd = { rootOK = true; };
       };
 
-    security.setuidPrograms = [ "passwd" "chfn" "su" "newgrp"
+    security.setuidPrograms = [ "passwd" "chfn" "su" "sg" "newgrp"
       "newuidmap" "newgidmap"  # new in shadow 4.2.x
       ];
 
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 796740ea636a..6ca73eea5f6f 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 = cfg.askPassword;
+
+  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
 {
@@ -15,6 +26,12 @@ in
 
     programs.ssh = {
 
+      askPassword = mkOption {
+        type = types.string;
+        default = "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
+        description = ''Program used by SSH to ask for passwords.'';
+      };
+
       forwardX11 = mkOption {
         type = types.bool;
         default = false;
@@ -117,6 +134,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 +148,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 fc25ba6f9694..4bf2f9a17571 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/rename.nix b/nixos/modules/rename.nix
index 1efc278aeb22..d90cffbd967f 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -107,11 +107,13 @@ in zipModules ([]
 ++ obsolete [ "services" "sshd" "permitRootLogin" ] [ "services" "openssh" "permitRootLogin" ]
 ++ obsolete [ "services" "xserver" "startSSHAgent" ] [ "services" "xserver" "startOpenSSHAgent" ]
 ++ obsolete [ "services" "xserver" "startOpenSSHAgent" ] [ "programs" "ssh" "startAgent" ]
-++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "xbmc" ]
 
 # VirtualBox
 ++ obsolete [ "services" "virtualbox" "enable" ] [ "services" "virtualboxGuest" "enable" ]
 
+# Tarsnap
+++ obsolete [ "services" "tarsnap" "config" ] [ "services" "tarsnap" "archives" ]
+
 # proxy
 ++ obsolete [ "nix" "proxy" ] [ "networking" "proxy" "default" ]
 
@@ -133,6 +135,12 @@ in zipModules ([]
 
 ++ obsolete [ "services" "mysql55" ] [ "services" "mysql" ]
 
+++ obsolete [ "environment" "checkConfigurationOptions" ] [ "_module" "check" ]
+
+# XBMC
+++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
+++ obsolete [ "services" "xserver" "desktopManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
+
 # Options that are obsolete and have no replacement.
 ++ obsolete' [ "boot" "loader" "grub" "bootDevice" ]
 ++ obsolete' [ "boot" "initrd" "luks" "enable" ]
diff --git a/nixos/modules/security/apparmor.nix b/nixos/modules/security/apparmor.nix
index f29e7a5ad818..4fef62cbffd7 100644
--- a/nixos/modules/security/apparmor.nix
+++ b/nixos/modules/security/apparmor.nix
@@ -1,43 +1,49 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit (lib) mkIf mkOption types concatMapStrings;
   cfg = config.security.apparmor;
 in
+
 {
-  options = {
-    security.apparmor = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Enable the AppArmor Mandatory Access Control system.";
-      };
+   options = {
+     security.apparmor = {
+       enable = mkOption {
+         type = types.bool;
+         default = false;
+         description = "Enable the AppArmor Mandatory Access Control system.";
+       };
+       profiles = mkOption {
+         type = types.listOf types.path;
+         default = [];
+         description = "List of files containing AppArmor profiles.";
+       };
+     };
+   };
 
-      profiles = mkOption {
-        type = types.listOf types.path;
-        default = [];
-        description = "List of files containing AppArmor profiles.";
-      };
-    };
-  };
+   config = mkIf cfg.enable {
+     environment.systemPackages = [ pkgs.apparmor-utils ];
 
-  config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.apparmor ];
-    systemd.services.apparmor = {
-      wantedBy = [ "local-fs.target" ];
-      path     = [ pkgs.apparmor ];
+     systemd.services.apparmor = {
+       wantedBy = [ "local-fs.target" ];
+       serviceConfig = {
+         Type = "oneshot";
+         RemainAfterExit = "yes";
+         ExecStart = concatMapStrings (p:
+           ''${pkgs.apparmor-parser}/bin/apparmor_parser -rKv -I ${pkgs.apparmor-profiles}/etc/apparmor.d "${p}" ; ''
+         ) cfg.profiles;
+         ExecStop = concatMapStrings (p:
+           ''${pkgs.apparmor-parser}/bin/apparmor_parser -Rv "${p}" ; ''
+         ) cfg.profiles;
+       };
+     };
 
-      serviceConfig = {
-        Type = "oneshot";
-        RemainAfterExit = "yes";
-        ExecStart = concatMapStrings (profile:
-          ''${pkgs.apparmor}/sbin/apparmor_parser -rKv -I ${pkgs.apparmor}/etc/apparmor.d/ "${profile}" ; ''
-        ) cfg.profiles;
-        ExecStop = concatMapStrings (profile:
-          ''${pkgs.apparmor}/sbin/apparmor_parser -Rv -I ${pkgs.apparmor}/etc/apparmor.d/ "${profile}" ; ''
-        ) cfg.profiles;
-      };
-    };
-  };
+     security.pam.services.apparmor.text = ''
+       ## AppArmor changes hats according to `order`: first try user, then
+       ## group, and finally fall back to a hat called "DEFAULT"
+       ##
+       ## For now, enable debugging as this is an experimental feature.
+       session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug
+     '';
+   };
 }
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index d0c7fa6ec288..35974f6890e6 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -38,59 +38,47 @@ in
         type = types.bool;
         default = false;
         description = ''
-          Enable the testing grsecurity patch, based on Linux 3.18.
+          Enable the testing grsecurity patch, based on Linux 3.19.
         '';
       };
 
       config = {
         mode = mkOption {
-          type = types.str;
+          type = types.enum [ "auto" "custom" ];
           default = "auto";
-          example = "custom";
           description = ''
             grsecurity configuration mode. This specifies whether
             grsecurity is auto-configured or otherwise completely
-            manually configured. Can either be
-            <literal>custom</literal> or <literal>auto</literal>.
-
-            <literal>auto</literal> is recommended.
+            manually configured.
           '';
         };
 
         priority = mkOption {
-          type = types.str;
+          type = types.enum [ "security" "performance" ];
           default = "security";
-          example = "performance";
           description = ''
             grsecurity configuration priority. This specifies whether
             the kernel configuration should emphasize speed or
-            security. Can either be <literal>security</literal> or
-            <literal>performance</literal>.
+            security.
           '';
         };
 
         system = mkOption {
-          type = types.str;
-          default = "";
-          example = "desktop";
+          type = types.enum [ "desktop" "server" ];
+          default = "desktop";
           description = ''
-            grsecurity system configuration. This specifies whether
-            the kernel configuration should be suitable for a Desktop
-            or a Server. Can either be <literal>server</literal> or
-            <literal>desktop</literal>.
+            grsecurity system configuration.
           '';
         };
 
         virtualisationConfig = mkOption {
-          type = types.str;
-          default = "none";
-          example = "host";
+          type = types.nullOr (types.enum [ "host" "guest" ]);
+          default = null;
           description = ''
             grsecurity virtualisation configuration. This specifies
             the virtualisation role of the machine - that is, whether
             it will be a virtual machine guest, a virtual machine
-            host, or neither. Can be one of <literal>none</literal>,
-            <literal>host</literal>, or <literal>guest</literal>.
+            host, or neither.
           '';
         };
 
@@ -106,17 +94,10 @@ in
         };
 
         virtualisationSoftware = mkOption {
-          type = types.str;
-          default = "";
-          example = "kvm";
+          type = types.nullOr (types.enum [ "kvm" "xen" "vmware" "virtualbox" ]);
+          default = null;
           description = ''
-            grsecurity virtualisation software. Set this to the
-            specified virtual machine technology if the machine is
-            running as a guest, or a host.
-
-            Can be one of <literal>kvm</literal>,
-            <literal>xen</literal>, <literal>vmware</literal> or
-            <literal>virtualbox</literal>.
+            Configure grsecurity for use with this virtualisation software.
           '';
         };
 
@@ -245,7 +226,7 @@ in
           message   = ''
             If grsecurity is enabled, you must select either the
             stable patch (with kernel 3.14), or the testing patch (with
-            kernel 3.18) to continue.
+            kernel 3.19) to continue.
           '';
         }
         { assertion = (cfg.stable -> !cfg.testing) || (cfg.testing -> !cfg.stable);
@@ -262,34 +243,23 @@ in
                    && config.boot.kernelPackages.kernel.features.grsecurity;
           message = "grsecurity enabled, but kernel doesn't have grsec support";
         }
-        { assertion = elem cfg.config.mode [ "auto" "custom" ];
-          message = "grsecurity mode must either be 'auto' or 'custom'.";
-        }
-        { assertion = cfg.config.mode == "auto" -> elem cfg.config.system [ "desktop" "server" ];
-          message = "when using auto grsec mode, system must be either 'desktop' or 'server'";
-        }
-        { assertion = cfg.config.mode == "auto" -> elem cfg.config.priority [ "performance" "security" ];
-          message = "when using auto grsec mode, priority must be 'performance' or 'security'.";
-        }
-        { assertion = cfg.config.mode == "auto" -> elem cfg.config.virtualisationConfig [ "host" "guest" "none" ];
-          message = "when using auto grsec mode, 'virt' must be 'host', 'guest' or 'none'.";
-        }
-        { assertion = (cfg.config.mode == "auto" && (elem cfg.config.virtualisationConfig [ "host" "guest" ])) ->
+        { assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) ->
               cfg.config.hardwareVirtualisation != null;
           message   = "when using auto grsec mode with virtualisation, you must specify if your hardware has virtualisation extensions";
         }
-        { assertion = (cfg.config.mode == "auto" && (elem cfg.config.virtualisationConfig [ "host" "guest" ])) ->
-              elem cfg.config.virtualisationSoftware [ "kvm" "xen" "virtualbox" "vmware" ];
-          message   = "virtualisation software must be 'kvm', 'xen', 'vmware' or 'virtualbox'";
+        { assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) ->
+              cfg.config.virtualisationSoftware != null;
+         message   = "grsecurity configured for virtualisation but no virtualisation software specified";
         }
       ];
 
     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 dcb2d5494754..631e8317cb4c 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -6,8 +6,9 @@
 with lib;
 
 let
+  parentConfig = config;
 
-  pamOpts = args: {
+  pamOpts = { config, name, ... }: let cfg = config; in let config = parentConfig; in {
 
     options = {
 
@@ -180,8 +181,8 @@ let
 
     };
 
-    config = let cfg = args.config; in {
-      name = mkDefault args.name;
+    config = {
+      name = mkDefault name;
       setLoginUid = mkDefault cfg.startSession;
       limits = mkDefault config.security.pam.loginLimits;
 
@@ -211,11 +212,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
+              "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 ''
@@ -223,9 +226,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"}
@@ -245,6 +250,8 @@ 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
@@ -252,7 +259,7 @@ let
           ${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
+              "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
@@ -357,6 +364,13 @@ in
       '';
     };
 
+    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.";
@@ -377,7 +391,11 @@ in
       ++ 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.enableOATH [ pkgs.oathToolkit ];
+      ++ 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/security/sudo.nix b/nixos/modules/security/sudo.nix
index d42a8c7f7d29..bced2a6ed757 100644
--- a/nixos/modules/security/sudo.nix
+++ b/nixos/modules/security/sudo.nix
@@ -77,7 +77,7 @@ in
         root        ALL=(ALL) SETENV: ALL
 
         # Users in the "wheel" group can do anything.
-        %wheel      ALL=(ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL
+        %wheel      ALL=(ALL:ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL
         ${cfg.extraConfig}
       '';
 
diff --git a/nixos/modules/services/audio/icecast.nix b/nixos/modules/services/audio/icecast.nix
new file mode 100644
index 000000000000..6a8a0f9975b3
--- /dev/null
+++ b/nixos/modules/services/audio/icecast.nix
@@ -0,0 +1,130 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.icecast;
+  configFile = pkgs.writeText "icecast.xml" ''
+    <icecast>
+      <hostname>${cfg.hostname}</hostname>
+
+      <authentication>
+        <admin-user>${cfg.admin.user}</admin-user>
+        <admin-password>${cfg.admin.password}</admin-password>
+      </authentication>
+
+      <paths>
+        <logdir>${cfg.logDir}</logdir>
+        <adminroot>${pkgs.icecast}/share/icecast/admin</adminroot>
+        <webroot>${pkgs.icecast}/share/icecast/web</webroot>
+        <alias source="/" dest="/status.xsl"/>
+      </paths>
+
+      <listen-socket>
+        <port>${toString cfg.listen.port}</port>
+        <bind-address>${cfg.listen.address}</bind-address>
+      </listen-socket>   
+
+      <security>
+        <chroot>0</chroot>
+        <changeowner>
+            <user>${cfg.user}</user>
+            <group>${cfg.group}</group>
+        </changeowner>
+      </security>
+
+      ${cfg.extraConf}
+    </icecast>
+  '';
+in {
+
+  ###### interface
+
+  options = {
+
+    services.icecast = {
+
+      enable = mkEnableOption "Icecast server";
+
+      hostname = mkOption {
+        type = types.str;
+        description = "DNS name or IP address that will be used for the stream directory lookups or possibily the playlist generation if a Host header is not provided.";
+        default = config.networking.domain;
+      };
+
+      admin = {
+        user = mkOption {
+          type = types.str;
+          description = "Username used for all administration functions.";
+          default = "admin";
+        };
+
+        password = mkOption {
+          type = types.str;
+          description = "Password used for all administration functions.";
+        };
+      };
+
+      logDir = mkOption {
+        type = types.path;
+        description = "Base directory used for logging.";
+        default = "/var/log/icecast";
+      };
+      
+      listen = {
+        port = mkOption {
+          type = types.int;
+          description = "TCP port that will be used to accept client connections.";
+          default = 8000;
+        };
+
+        address = mkOption {
+          type = types.str;
+          description = "Address Icecast will listen on.";
+          default = "::";
+        };
+      };
+
+      user = mkOption {
+        type = types.str;
+        description = "User privileges for the server.";
+        default = "nobody";
+      };
+
+      group = mkOption {
+        type = types.str;
+        description = "Group privileges for the server.";
+        default = "nogroup";
+      };
+
+      extraConf = mkOption {
+        type = types.lines;
+        description = "icecast.xml content.";
+        default = "";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.icecast = {
+      after = [ "network.target" ];
+      description = "Icecast Network Audio Streaming Server";
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = "mkdir -p ${cfg.logDir} && chown ${cfg.user}:${cfg.group} ${cfg.logDir}";
+      serviceConfig = {
+        Type = "simple";
+        ExecStart = "${pkgs.icecast}/bin/icecast -c ${configFile}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index b79052337597..d9b5bf7b5e6f 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -15,10 +15,12 @@ let
     state_file          "${cfg.dataDir}/state"
     sticker_file        "${cfg.dataDir}/sticker.sql"
     log_file            "syslog"
-    ${if cfg.network.host != "any" then
-   "bind_to_address     ${cfg.network.host}" else ""}
-    ${if cfg.network.port != 6600 then
-   "port                ${toString cfg.network.port}" else ""}
+    user                "${cfg.user}"
+    group               "${cfg.group}"
+
+    ${optionalString (cfg.network.host != "any") ''bind_to_address "${cfg.network.host}"''}
+    ${optionalString (cfg.network.port != 6600)  ''port "${toString cfg.network.port}"''}
+
     ${cfg.extraConfig}
   '';
 
@@ -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,19 @@ 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 {
+      name = "mpd";
+      gid = gid;
+    });
   };
 
 }
diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix
index 1b0bcadca151..155161945cd9 100644
--- a/nixos/modules/services/backup/tarsnap.nix
+++ b/nixos/modules/services/backup/tarsnap.nix
@@ -12,6 +12,7 @@ let
     keyfile  ${config.services.tarsnap.keyfile}
     ${optionalString cfg.nodump "nodump"}
     ${optionalString cfg.printStats "print-stats"}
+    ${optionalString cfg.printStats "humanize-numbers"}
     ${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
     ${optionalString cfg.aggressiveNetworking "aggressive-networking"}
     ${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)}
@@ -27,46 +28,39 @@ in
         type = types.bool;
         default = false;
         description = ''
-          If enabled, NixOS will periodically create backups of the
-          specified directories using the <literal>tarsnap</literal>
-          backup service. This installs a <literal>systemd</literal>
-          service called <literal>tarsnap-backup</literal> which is
-          periodically run by cron, or you may run it on-demand.
-
-          See the Tarsnap <link
-          xlink:href='http://www.tarsnap.com/gettingstarted.html'>Getting
-          Started</link> page.
+          Enable periodic tarsnap backups.
         '';
       };
 
       keyfile = mkOption {
-        type = types.path;
+        type = types.str;
         default = "/root/tarsnap.key";
         description = ''
-          Path to the keyfile which identifies the machine
-          associated with your Tarsnap account. This file can
-          be created using the
-          <literal>tarsnap-keygen</literal> utility, and
-          providing your Tarsnap login credentials.
+          The keyfile which associates this machine with your tarsnap
+          account.
+          Create the keyfile with <command>tarsnap-keygen</command>.
+
+          The keyfile name should be given as a string and not a path, to
+          avoid the key being copied into the Nix store.
         '';
       };
 
       cachedir = mkOption {
-        type    = types.path;
+        type    = types.nullOr types.path;
         default = "/var/cache/tarsnap";
         description = ''
-          Tarsnap operations use a "cache directory" which
-          allows Tarsnap to identify which blocks of data have
-          been previously stored; this directory is specified
-          via the <literal>cachedir</literal> option. If the
-          cache directory is lost or out of date, tarsnap
-          creation/deletion operations will exit with an error
-          message instructing you to run <literal>tarsnap
-          --fsck</literal> to regenerate the cache directory.
+          The cache allows tarsnap to identify previously stored data
+          blocks, reducing archival time and bandwidth usage.
+
+          Should the cache become desynchronized or corrupted, tarsnap
+          will refuse to run until you manually rebuild the cache with
+          <command>tarsnap --fsck</command>.
+
+          Set to <literal>null</literal> to disable caching.
         '';
       };
 
-      config = mkOption {
+      archives = mkOption {
         type = types.attrsOf (types.submodule (
           {
             options = {
@@ -74,41 +68,44 @@ in
                 type = types.bool;
                 default = true;
                 description = ''
-                  If set to <literal>true</literal>, then don't
-                  archive files which have the
-                  <literal>nodump</literal> flag set.
+                  Exclude files with the <literal>nodump</literal> flag.
                 '';
               };
 
               printStats = mkOption {
                 type = types.bool;
                 default = true;
-                description = "Print statistics when creating archives.";
+                description = ''
+                  Print global archive statistics upon completion.
+                  The output is available via
+                  <command>systemctl status tarsnap@archive-name</command>.
+                '';
               };
 
               checkpointBytes = mkOption {
                 type = types.nullOr types.str;
-                default = "1G";
+                default = "1GB";
                 description = ''
-                  Create a checkpoint per a particular amount of
-                  uploaded data. By default, Tarsnap will create
-                  checkpoints once per GB of data uploaded. At
-                  minimum, <literal>checkpointBytes</literal> must be
-                  1GB.
-
-                  Can also be set to <literal>null</literal> to
-                  disable checkpointing.
+                  Create a checkpoint every <literal>checkpointBytes</literal>
+                  of uploaded data (optionally specified using an SI prefix).
+
+                  1GB is the minimum value. A higher value is recommended,
+                  as checkpointing is expensive.
+
+                  Set to <literal>null</literal> to disable checkpointing.
                 '';
               };
 
               period = mkOption {
                 type = types.str;
-                default = "15 01 * * *";
+                default = "01:15";
+                example = "hourly";
                 description = ''
-                  This option defines (in the format used by cron)
-                  when tarsnap is run for backups. The default is to
-                  backup the specified paths at 01:15 at night every
-                  day.
+                  Create archive at this interval.
+
+                  The format is described in
+                  <citerefentry><refentrytitle>systemd.time</refentrytitle>
+                  <manvolnum>7</manvolnum></citerefentry>.
                 '';
               };
 
@@ -116,11 +113,11 @@ in
                 type = types.bool;
                 default = false;
                 description = ''
-                  Aggressive network behaviour: Use multiple TCP
-                  connections when writing archives.  Use of this
-                  option is recommended only in cases where TCP
-                  congestion control is known to be the limiting
-                  factor in upload performance.
+                  Upload data over multiple TCP connections, potentially
+                  increasing tarsnap's bandwidth utilisation at the cost
+                  of slowing down all other network traffic. Not
+                  recommended unless TCP congestion is the dominant
+                  limiting factor.
                 '';
               };
 
@@ -134,8 +131,7 @@ in
                 type = types.listOf types.str;
                 default = [];
                 description = ''
-                  Exclude files and directories matching the specified
-                  patterns.
+                  Exclude files and directories matching these patterns.
                 '';
               };
 
@@ -143,12 +139,10 @@ in
                 type = types.listOf types.str;
                 default = [];
                 description = ''
-                  Include only files and directories matching the
-                  specified patterns.
+                  Include only files and directories matching these
+                  patterns (the empty list includes everything).
 
-                  Note that exclusions specified via
-                  <literal>excludes</literal> take precedence over
-                  inclusions.
+                  Exclusions have precedence over inclusions.
                 '';
               };
 
@@ -156,10 +150,10 @@ in
                 type = types.bool;
                 default = false;
                 description = ''
-                  Attempt to reduce tarsnap memory consumption.  This
-                  option will slow down the process of creating
-                  archives, but may help on systems where the average
-                  size of files being backed up is less than 1 MB.
+                  Reduce memory consumption by not caching small files.
+                  Possibly beneficial if the average file size is smaller
+                  than 1 MB and the number of files is lower than the
+                  total amount of RAM in KB.
                 '';
               };
 
@@ -167,11 +161,9 @@ in
                 type = types.bool;
                 default = false;
                 description = ''
-                  Try even harder to reduce tarsnap memory
-                  consumption.  This can significantly slow down
-                  tarsnap, but reduces its memory usage by an
-                  additional factor of 2 beyond what the
-                  <literal>lowmem</literal> option does.
+                  Reduce memory consumption by a factor of 2 beyond what
+                  <literal>lowmem</literal> does, at the cost of significantly
+                  slowing down the archiving process.
                 '';
               };
             };
@@ -188,25 +180,22 @@ in
 
             gamedata =
               { directories = [ "/var/lib/minecraft "];
-                period      = "*/30 * * * *";
+                period      = "*:30";
               };
           }
         '';
 
         description = ''
-          Configuration of a Tarsnap archive. In the example, your
-          machine will have two tarsnap archives:
-          <literal>gamedata</literal> (backed up every 30 minutes) and
-          <literal>nixos</literal> (backed up at 1:15 AM every night by
-          default). You can control individual archive backups using
-          <literal>systemctl</literal>, using the
-          <literal>tarsnap@nixos</literal> or
-          <literal>tarsnap@gamedata</literal> units. For example,
-          <literal>systemctl start tarsnap@nixos</literal> will
-          immediately create a new NixOS archive. By default, archives
-          are suffixed with the timestamp of when they were started,
-          down to second resolution. This means you can use GNU
-          <literal>sort</literal> to sort output easily.
+          Tarsnap archive configurations. Each attribute names an archive
+          to be created at a given time interval, according to the options
+          associated with it. When uploading to the tarsnap server,
+          archive names are suffixed by a 1 second resolution timestamp.
+
+          For each member of the set is created a timer which triggers the
+          instanced <literal>tarsnap@</literal> service unit. You may use
+          <command>systemctl start tarsnap@archive-name</command> to
+          manually trigger creation of <literal>archive-name</literal> at
+          any time.
         '';
       };
     };
@@ -216,38 +205,45 @@ in
     assertions =
       (mapAttrsToList (name: cfg:
         { assertion = cfg.directories != [];
-          message = "Must specify directories for Tarsnap to back up";
-        }) cfg.config) ++
+          message = "Must specify paths for tarsnap to back up";
+        }) cfg.archives) ++
       (mapAttrsToList (name: cfg:
-        { assertion = cfg.lowmem -> !cfg.verylowmem && (cfg.verylowmem -> !cfg.lowmem);
+        { assertion = !(cfg.lowmem && cfg.verylowmem);
           message = "You cannot set both lowmem and verylowmem";
-        }) cfg.config);
+        }) cfg.archives);
 
     systemd.services."tarsnap@" = {
-      description = "Tarsnap Backup of '%i'";
+      description = "Tarsnap archive '%i'";
       requires    = [ "network.target" ];
 
       path = [ pkgs.tarsnap pkgs.coreutils ];
       scriptArgs = "%i";
       script = ''
-        mkdir -p -m 0755 $(dirname ${cfg.cachedir})
-        mkdir -p -m 0600 ${cfg.cachedir}
+        mkdir -p -m 0755 ${dirOf cfg.cachedir}
+        mkdir -p -m 0700 ${cfg.cachedir}
         DIRS=`cat /etc/tarsnap/$1.dirs`
         exec tarsnap --configfile /etc/tarsnap/$1.conf -c -f $1-$(date +"%Y%m%d%H%M%S") $DIRS
       '';
+
+      serviceConfig = {
+        IOSchedulingClass = "idle";
+        NoNewPrivileges = "true";
+        CapabilityBoundingSet = "CAP_DAC_READ_SEARCH";
+      };
     };
 
-    services.cron.systemCronJobs = mapAttrsToList (name: cfg:
-      "${cfg.period} root ${config.systemd.package}/bin/systemctl start tarsnap@${name}"
-    ) cfg.config;
+    systemd.timers = mapAttrs' (name: cfg: nameValuePair "tarsnap@${name}"
+      { timerConfig.OnCalendar = cfg.period;
+        wantedBy = [ "timers.target" ];
+      }) cfg.archives;
 
     environment.etc =
       (mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.conf"
         { text = configFile cfg;
-        }) cfg.config) //
+        }) cfg.archives) //
       (mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.dirs"
         { text = concatStringsSep " " cfg.directories;
-        }) cfg.config);
+        }) cfg.archives);
 
     environment.systemPackages = [ pkgs.tarsnap ];
   };
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index 7fd2d77aa825..d9ae0454ba5e 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -44,6 +44,12 @@ in {
       type = types.path;
     };
 
+    dockerCfg = mkOption {
+      description = "Kubernetes contents of dockercfg file.";
+      default = "";
+      type = types.lines;
+    };
+
     apiserver = {
       enable = mkOption {
         description = "Whether to enable kubernetes apiserver.";
@@ -217,13 +223,13 @@ in {
       };
 
       machines = mkOption {
-        description = "Kubernetes apiserver list of machines to schedule to schedule onto";
+        description = "Kubernetes controller list of machines to schedule to schedule onto";
         default = [];
         type = types.listOf types.str;
       };
 
       extraOpts = mkOption {
-        description = "Kubernetes scheduler extra command line options.";
+        description = "Kubernetes controller extra command line options.";
         default = "";
         type = types.str;
       };
@@ -260,6 +266,30 @@ in {
         type = types.bool;
       };
 
+      apiServers = mkOption {
+        description = "Kubernetes kubelet list of Kubernetes API servers for publishing events, and reading pods and services.";
+        default = ["${cfg.apiserver.address}:${toString cfg.apiserver.port}"];
+        type = types.listOf types.str;
+      };
+
+      cadvisorPort = mkOption {
+        description = "Kubernetes kubelet local cadvisor port.";
+        default = config.services.cadvisor.port;
+        type = types.int;
+      };
+
+      clusterDns = mkOption {
+        description = "Use alternative dns.";
+        default = "";
+        type = types.str;
+      };
+
+      clusterDomain = mkOption {
+        description = "Use alternative domain.";
+        default = "";
+        type = types.str;
+      };
+
       extraOpts = mkOption {
         description = "Kubernetes kubelet extra command line options.";
         default = "";
@@ -295,6 +325,7 @@ in {
       systemd.services.kubernetes-apiserver = {
         description = "Kubernetes Api Server";
         wantedBy = [ "multi-user.target" ];
+        requires = ["kubernetes-setup.service"];
         after = [ "network-interfaces.target" "etcd.service" ];
         serviceConfig = {
           ExecStart = let
@@ -306,26 +337,25 @@ in {
                 (concatImapStringsSep "\n" (i: v: v + "," + (toString i))
                     (mapAttrsToList (name: token: token + "," + name) cfg.apiserver.tokenAuth));
           in ''${cfg.package}/bin/kube-apiserver \
-            -etcd_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.etcdServers} \
-            -address=${cfg.apiserver.address} \
-            -port=${toString cfg.apiserver.port} \
-            -read_only_port=${toString cfg.apiserver.readOnlyPort} \
-            -public_address_override=${cfg.apiserver.publicAddress} \
-            -allow_privileged=${if cfg.apiserver.allowPrivileged then "true" else "false"} \
+            --etcd_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.etcdServers} \
+            --address=${cfg.apiserver.address} \
+            --port=${toString cfg.apiserver.port} \
+            --read_only_port=${toString cfg.apiserver.readOnlyPort} \
+            --public_address_override=${cfg.apiserver.publicAddress} \
+            --allow_privileged=${if cfg.apiserver.allowPrivileged then "true" else "false"} \
             ${optionalString (cfg.apiserver.tlsCertFile!="")
-              "-tls_cert_file=${cfg.apiserver.tlsCertFile}"} \
+              "--tls_cert_file=${cfg.apiserver.tlsCertFile}"} \
             ${optionalString (cfg.apiserver.tlsPrivateKeyFile!="")
-              "-tls_private_key_file=${cfg.apiserver.tlsPrivateKeyFile}"} \
+              "--tls_private_key_file=${cfg.apiserver.tlsPrivateKeyFile}"} \
             ${optionalString (cfg.apiserver.tokenAuth!=[])
-              "-token_auth_file=${tokenAuthFile}"} \
-            -authorization_mode=${cfg.apiserver.authorizationMode} \
+              "--token_auth_file=${tokenAuthFile}"} \
+            --authorization_mode=${cfg.apiserver.authorizationMode} \
             ${optionalString (cfg.apiserver.authorizationMode == "ABAC")
-              "-authorization_policy_file=${authorizationPolicyFile}"} \
-            ${optionalString (cfg.apiserver.tlsCertFile!="" && cfg.apiserver.tlsCertFile!="")
-              "-secure_port=${toString cfg.apiserver.securePort}"} \
-            -portal_net=${cfg.apiserver.portalNet} \
-            -logtostderr=true \
-            ${optionalString cfg.verbose "-v=6 -log_flush_frequency=1s"} \
+              "--authorization_policy_file=${authorizationPolicyFile}"} \
+            --secure_port=${toString cfg.apiserver.securePort} \
+            --portal_net=${cfg.apiserver.portalNet} \
+            --logtostderr=true \
+            ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
             ${cfg.apiserver.extraOpts}
           '';
           User = "kubernetes";
@@ -345,11 +375,11 @@ in {
         after = [ "network-interfaces.target" "kubernetes-apiserver.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-scheduler \
-            -address=${cfg.scheduler.address} \
-            -port=${toString cfg.scheduler.port} \
-            -master=${cfg.scheduler.master} \
-            -logtostderr=true \
-            ${optionalString cfg.verbose "-v=6 -log_flush_frequency=1s"} \
+            --address=${cfg.scheduler.address} \
+            --port=${toString cfg.scheduler.port} \
+            --master=${cfg.scheduler.master} \
+            --logtostderr=true \
+            ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
             ${cfg.scheduler.extraOpts}
           '';
           User = "kubernetes";
@@ -364,13 +394,12 @@ in {
         after = [ "network-interfaces.target" "kubernetes-apiserver.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-controller-manager \
-            -address=${cfg.controllerManager.address} \
-            -port=${toString cfg.controllerManager.port} \
-            -master=${cfg.controllerManager.master} \
-            ${optionalString (cfg.controllerManager.machines != [])
-                "-machines=${concatStringsSep "," cfg.controllerManager.machines}"} \
-            -logtostderr=true \
-            ${optionalString cfg.verbose "-v=6 -log_flush_frequency=1s"} \
+            --address=${cfg.controllerManager.address} \
+            --port=${toString cfg.controllerManager.port} \
+            --master=${cfg.controllerManager.master} \
+            --machines=${concatStringsSep "," cfg.controllerManager.machines} \
+            --logtostderr=true \
+            ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
             ${cfg.controllerManager.extraOpts}
           '';
           User = "kubernetes";
@@ -382,23 +411,28 @@ in {
       systemd.services.kubernetes-kubelet = {
         description = "Kubernetes Kubelet Service";
         wantedBy = [ "multi-user.target" ];
+        requires = ["kubernetes-setup.service"];
         after = [ "network-interfaces.target" "etcd.service" "docker.service" ];
-        serviceConfig = {
-          ExecStart = ''${cfg.package}/bin/kubelet \
-            -etcd_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.etcdServers} \
-            -address=${cfg.kubelet.address} \
-            -port=${toString cfg.kubelet.port} \
-            -hostname_override=${cfg.kubelet.hostname} \
-            -allow_privileged=${if cfg.kubelet.allowPrivileged then "true" else "false"} \
-            -root_dir=${cfg.dataDir} \
-            -logtostderr=true \
-            ${optionalString cfg.verbose "-v=6 -log_flush_frequency=1s"} \
+        script = ''
+          export PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH"
+          exec ${cfg.package}/bin/kubelet \
+            --etcd_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.etcdServers} \
+            --api_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.kubelet.apiServers}  \
+            --address=${cfg.kubelet.address} \
+            --port=${toString cfg.kubelet.port} \
+            --hostname_override=${cfg.kubelet.hostname} \
+            --allow_privileged=${if cfg.kubelet.allowPrivileged then "true" else "false"} \
+            --root_dir=${cfg.dataDir} \
+            --cadvisor_port=${toString cfg.kubelet.cadvisorPort} \
+            ${optionalString (cfg.kubelet.clusterDns != "")
+                ''--cluster_dns=${cfg.kubelet.clusterDns}''} \
+            ${optionalString (cfg.kubelet.clusterDomain != "")
+                ''--cluster_domain=${cfg.kubelet.clusterDomain}''} \
+            --logtostderr=true \
+            ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
             ${cfg.kubelet.extraOpts}
           '';
-          User = "kubernetes";
-          PermissionsStartOnly = true;
-          WorkingDirectory = cfg.dataDir;
-        };
+        serviceConfig.WorkingDirectory = cfg.dataDir;
       };
     })
 
@@ -409,10 +443,10 @@ in {
         after = [ "network-interfaces.target" "etcd.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-proxy \
-            -etcd_servers=${concatMapStringsSep "," (s: "http://${s}") cfg.etcdServers} \
-            -bind_address=${cfg.proxy.address} \
-            -logtostderr=true \
-            ${optionalString cfg.verbose "-v=6 -log_flush_frequency=1s"} \
+            --etcd_servers=${concatMapStringsSep "," (s: "http://${s}") cfg.etcdServers} \
+            --bind_address=${cfg.proxy.address} \
+            --logtostderr=true \
+            ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
             ${cfg.proxy.extraOpts}
           '';
         };
@@ -427,6 +461,8 @@ in {
 
     (mkIf (any (el: el == "node") cfg.roles) {
       virtualisation.docker.enable = mkDefault true;
+      services.cadvisor.enable = mkDefault true;
+      services.cadvisor.port = mkDefault 4194;
       services.kubernetes.kubelet.enable = mkDefault true;
       services.kubernetes.proxy.enable = mkDefault true;
     })
@@ -442,6 +478,16 @@ in {
         cfg.kubelet.enable ||
         cfg.proxy.enable
     ) {
+      systemd.services.kubernetes-setup = {
+        description = "Kubernetes setup.";
+        serviceConfig.Type = "oneshot";
+        script = ''
+          mkdir -p /var/run/kubernetes
+          chown kubernetes /var/run/kubernetes
+          ln -fs ${pkgs.writeText "kubernetes-dockercfg" cfg.dockerCfg} /var/run/kubernetes/.dockercfg
+        '';
+      };
+
       services.kubernetes.package = mkDefault pkgs.kubernetes;
 
       environment.systemPackages = [ cfg.package ];
diff --git a/nixos/modules/services/cluster/panamax.nix b/nixos/modules/services/cluster/panamax.nix
index a7233f23c913..b47ff744fc27 100644
--- a/nixos/modules/services/cluster/panamax.nix
+++ b/nixos/modules/services/cluster/panamax.nix
@@ -124,14 +124,15 @@ in {
       };
 
       preStart = ''
-        rm -rf ${cfg.dataDir}/state/tmp
         mkdir -p ${cfg.dataDir}/ui/state/{log,tmp}
+        chown -R panamax:panamax ${cfg.dataDir}
       '';
 
       serviceConfig = {
         ExecStart = "${panamax_ui}/bin/bundle exec rails server --binding 127.0.0.1 --port ${toString cfg.UIPort}";
         User = "panamax";
         Group = "panamax";
+        PermissionsStartOnly = true;
       };
     };
 
@@ -145,6 +146,8 @@ in {
 
     services.journald.enableHttpGateway = mkDefault true;
     services.fleet.enable = mkDefault true;
+    services.cadvisor.enable = mkDefault true;
+    services.cadvisor.port = mkDefault 3002;
     virtualisation.docker.enable = mkDefault true;
 
     environment.systemPackages = [ panamax_api panamax_ui ];
diff --git a/nixos/modules/services/computing/slurm/slurm.nix b/nixos/modules/services/computing/slurm/slurm.nix
new file mode 100644
index 000000000000..019d7fbb16cd
--- /dev/null
+++ b/nixos/modules/services/computing/slurm/slurm.nix
@@ -0,0 +1,130 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.slurm;
+  # configuration file can be generated by http://slurm.schedmd.com/configurator.html
+  configFile = pkgs.writeText "slurm.conf" 
+    ''
+      ${optionalString (cfg.controlMachine != null) ''controlMachine=${cfg.controlMachine}''}
+      ${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
+      ${optionalString (cfg.nodeName != null) ''nodeName=${cfg.nodeName}''}
+      ${optionalString (cfg.partitionName != null) ''partitionName=${cfg.partitionName}''}
+      ${cfg.extraConfig}
+    '';
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.slurm = {
+
+      server = {
+        enable = mkEnableOption "slurm control daemon";
+
+      };
+      
+      client = {
+        enable = mkEnableOption "slurm rlient daemon";
+
+      };
+
+      controlMachine = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = null;
+        description = ''
+          The short hostname of the machine where SLURM control functions are
+          executed (i.e. the name returned by the command "hostname -s", use "tux001"
+          rather than "tux001.my.com").
+        '';
+      };
+
+      controlAddr = mkOption {
+        type = types.nullOr types.str;
+        default = cfg.controlMachine;
+        example = null;
+        description = ''
+          Name that ControlMachine should be referred to in establishing a
+          communications path.
+        '';
+      };
+
+      nodeName = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "linux[1-32] CPUs=1 State=UNKNOWN";
+        description = ''
+          Name that SLURM uses to refer to a node (or base partition for BlueGene
+          systems). Typically this would be the string that "/bin/hostname -s"
+          returns. Note that now you have to write node's parameters after the name.
+        '';
+      };
+
+      partitionName = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP";
+        description = ''
+          Name by which the partition may be referenced. Note that now you have
+          to write patrition's parameters after the name.
+        '';
+      };
+
+      extraConfig = mkOption {
+        default = ""; 
+        type = types.lines;
+        description = ''
+          Extra configuration options that will be added verbatim at
+          the end of the slurm configuration file.
+        '';
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf (cfg.client.enable || cfg.server.enable) {
+
+    environment.systemPackages = [ pkgs.slurm-llnl ];
+
+    systemd.services.slurmd = mkIf (cfg.client.enable) {
+      path = with pkgs; [ slurm-llnl coreutils ];
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "systemd-tmpfiles-clean.service" ];
+
+      serviceConfig = {
+        Type = "forking";
+        ExecStart = "${pkgs.slurm-llnl}/bin/slurmd -f ${configFile}";
+        PIDFile = "/run/slurmd.pid";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+    };
+
+    systemd.services.slurmctld = mkIf (cfg.server.enable) {
+      path = with pkgs; [ slurm-llnl munge coreutils ];
+      
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "auditd.service" "munged.service" "slurmdbd.service" ];
+      requires = [ "munged.service" ];
+
+      serviceConfig = {
+        Type = "forking";
+        ExecStart = "${pkgs.slurm-llnl}/bin/slurmctld";
+        PIDFile = "/run/slurmctld.pid";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+      environment = { SLURM_CONF = "${configFile}"; };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/databases/couchdb.nix b/nixos/modules/services/databases/couchdb.nix
index e1fe6be6f6a3..2b1d07c355ef 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 02e44ad88704..14ffdad9217d 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/mysql.nix b/nixos/modules/services/databases/mysql.nix
index b94a3fbf3de7..05b13492052a 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -8,9 +8,7 @@ let
 
   mysql = cfg.package;
 
-  is55 = mysql.mysqlVersion == "5.5";
-
-  mysqldDir = if is55 then "${mysql}/bin" else "${mysql}/libexec";
+  atLeast55 = versionAtLeast mysql.mysqlVersion "5.5";
 
   pidFile = "${cfg.pidDir}/mysqld.pid";
 
@@ -24,7 +22,7 @@ let
     port = ${toString cfg.port}
     ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") "log-bin=mysql-bin"}
     ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") "server-id = ${toString cfg.replication.serverId}"}
-    ${optionalString (cfg.replication.role == "slave" && !is55)
+    ${optionalString (cfg.replication.role == "slave" && !atLeast55)
     ''
       master-host = ${cfg.replication.masterHost}
       master-user = ${cfg.replication.masterUser}
@@ -75,7 +73,7 @@ in
       };
 
       pidDir = mkOption {
-        default = "/var/run/mysql";
+        default = "/run/mysqld";
         description = "Location of the file which stores the PID of the MySQL server";
       };
 
@@ -180,15 +178,19 @@ in
 
             mkdir -m 0700 -p ${cfg.pidDir}
             chown -R ${cfg.user} ${cfg.pidDir}
+
+            # Make the socket directory
+            mkdir -m 0700 -p /run/mysqld
+            chown -R ${cfg.user} /run/mysqld
           '';
 
-        serviceConfig.ExecStart = "${mysqldDir}/mysqld --defaults-extra-file=${myCnf} ${mysqldOptions}";
+        serviceConfig.ExecStart = "${mysql}/bin/mysqld --defaults-extra-file=${myCnf} ${mysqldOptions}";
 
         postStart =
           ''
             # Wait until the MySQL server is available for use
             count=0
-            while [ ! -e /tmp/mysql.sock ]
+            while [ ! -e /run/mysqld/mysqld.sock ]
             do
                 if [ $count -eq 30 ]
                 then
@@ -222,7 +224,7 @@ in
                     fi
                   '') cfg.initialDatabases}
 
-                ${optionalString (cfg.replication.role == "slave" && is55)
+                ${optionalString (cfg.replication.role == "slave" && atLeast55)
                   ''
                     # Set up the replication master
 
diff --git a/nixos/modules/services/games/minecraft-server.nix b/nixos/modules/services/games/minecraft-server.nix
index 4c734aefa469..d2c8af6de0c5 100644
--- a/nixos/modules/services/games/minecraft-server.nix
+++ b/nixos/modules/services/games/minecraft-server.nix
@@ -8,6 +8,7 @@ in
 {
   options = {
     services.minecraft-server = {
+
       enable = mkOption {
         type = types.bool;
         default = false;
@@ -15,7 +16,23 @@ in
           If enabled, start a Minecraft Server. The listening port for
           the server is always <literal>25565</literal>. The server
           data will be loaded from and saved to
-          <literal>/var/lib/minecraft</literal>.
+          <literal>${cfg.dataDir}</literal>.
+        '';
+      };
+
+      dataDir = mkOption {
+        type = types.path;
+        default = "/var/lib/minecraft";
+        description = ''
+          Directory to store minecraft database and other state/data files.
+        '';
+      };
+
+      openFirewall = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to open ports in the firewall (if enabled) for the server.
         '';
       };
 
@@ -30,7 +47,7 @@ in
   config = mkIf cfg.enable {
     users.extraUsers.minecraft = {
       description     = "Minecraft Server Service user";
-      home            = "/var/lib/minecraft";
+      home            = cfg.dataDir;
       createHome      = true;
       uid             = config.ids.uids.minecraft;
     };
@@ -43,9 +60,14 @@ in
       serviceConfig.Restart = "always";
       serviceConfig.User    = "minecraft";
       script = ''
-        cd /var/lib/minecraft
+        cd ${cfg.dataDir}
         exec ${pkgs.minecraft-server}/bin/minecraft-server ${cfg.jvmOpts}
       '';
     };
+
+    networking.firewall = mkIf cfg.openFirewall {
+      allowedUDPPorts = [ 25565 ];
+      allowedTCPPorts = [ 25565 ];
+    };
   };
 }
diff --git a/nixos/modules/services/games/minetest-server.nix b/nixos/modules/services/games/minetest-server.nix
new file mode 100644
index 000000000000..996e313386fe
--- /dev/null
+++ b/nixos/modules/services/games/minetest-server.nix
@@ -0,0 +1,104 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg   = config.services.minetest-server;
+  flag  = val: name: if val != null then "--${name} ${val} " else "";
+  flags = [ 
+    (flag cfg.gameId "gameid") 
+    (flag cfg.world "world") 
+    (flag cfg.configPath "config") 
+    (flag cfg.logPath "logfile") 
+    (flag cfg.port "port") 
+  ];
+in
+{
+  options = {
+    services.minetest-server = {
+      enable = mkOption {
+        type        = types.bool;
+        default     = false;
+        description = "If enabled, starts a Minetest Server.";
+      };
+
+      gameId = mkOption {
+        type        = types.nullOr types.str;
+        default     = null;
+        description = ''
+          Id of the game to use. To list available games run 
+          `minetestserver --gameid list`.
+
+          If only one game exists, this option can be null.
+        '';
+      };
+
+      world = mkOption {
+        type        = types.nullOr types.path;
+        default     = null;
+        description = ''
+          Name of the world to use. To list available worlds run
+          `minetestserver --world list`.
+
+          If only one world exists, this option can be null.
+        '';
+      };
+
+      configPath = mkOption {
+        type        = types.nullOr types.path;
+        default     = null;
+        description = ''
+          Path to the config to use.
+
+          If set to null, the config of the running user will be used:
+          `~/.minetest/minetest.conf`.
+        '';
+      };
+
+      logPath = mkOption {
+        type        = types.nullOr types.path;
+        default     = null;
+        description = ''
+          Path to logfile for logging. 
+
+          If set to null, logging will be output to stdout which means
+          all output will be catched by systemd.
+        '';
+      };
+
+      port = mkOption {
+        type        = types.nullOr types.int;
+        default     = null;
+        description = ''
+          Port number to bind to.
+
+          If set to null, the default 30000 will be used.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers.minetest = {
+      description     = "Minetest Server Service user";
+      home            = "/var/lib/minetest";
+      createHome      = true;
+      uid             = config.ids.uids.minetest;
+    };
+
+    systemd.services.minetest-server = {
+      description   = "Minetest Server Service";
+      wantedBy      = [ "multi-user.target" ];
+      after         = [ "network.target" ];
+
+      serviceConfig.Restart = "always";
+      serviceConfig.User    = "minetest";
+
+      script = ''
+        cd /var/lib/minetest
+
+        exec ${pkgs.minetest}/bin/minetestserver ${concatStrings flags}
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/services/hardware/tcsd.nix b/nixos/modules/services/hardware/tcsd.nix
index d7f6c188feb8..220b154bd97a 100644
--- a/nixos/modules/services/hardware/tcsd.nix
+++ b/nixos/modules/services/hardware/tcsd.nix
@@ -128,12 +128,12 @@ in
     users.extraUsers = optionalAttrs (cfg.user == "tss") (singleton
       { name = "tss";
         group = "tss";
-        uid = config.ids.uids.nginx;
+        uid = config.ids.uids.tss;
       });
 
     users.extraGroups = optionalAttrs (cfg.group == "tss") (singleton
       { name = "tss";
-        gid = config.ids.gids.nginx;
+        gid = config.ids.gids.tss;
       });
   };
 }
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 39180f4d37ec..50588e449587 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -28,6 +28,7 @@ let
   # Perform substitutions in all udev rules files.
   udevRules = stdenv.mkDerivation {
     name = "udev-rules";
+    preferLocalBuild = true;
     buildCommand = ''
       mkdir -p $out
       shopt -s nullglob
@@ -236,7 +237,10 @@ in
 
     system.activationScripts.udevd =
       ''
-        echo "" > /proc/sys/kernel/hotplug
+        # The deprecated hotplug uevent helper is not used anymore
+        if [ -e /proc/sys/kernel/hotplug ]; then
+          echo "" > /proc/sys/kernel/hotplug
+        fi
 
         # Regenerate the hardware database /var/lib/udev/hwdb.bin
         # whenever systemd changes.
diff --git a/nixos/modules/services/logging/fluentd.nix b/nixos/modules/services/logging/fluentd.nix
new file mode 100644
index 000000000000..61eeec504e0d
--- /dev/null
+++ b/nixos/modules/services/logging/fluentd.nix
@@ -0,0 +1,39 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.fluentd;
+in {
+  ###### interface
+
+  options = {
+
+    services.fluentd = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable fluentd.";
+      };
+
+      config = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Fluentd config.";
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.fluentd = with pkgs; {
+      description = "Fluentd Daemon";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.fluentd}/bin/fluentd -c ${pkgs.writeText "fluentd.conf" cfg.config}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix
index 219c7ed95874..48bb9e4293e7 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/mediatomb.nix b/nixos/modules/services/misc/mediatomb.nix
new file mode 100644
index 000000000000..23227548039c
--- /dev/null
+++ b/nixos/modules/services/misc/mediatomb.nix
@@ -0,0 +1,282 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  uid = config.ids.uids.mediatomb;
+  gid = config.ids.gids.mediatomb;
+  cfg = config.services.mediatomb;
+
+  mtConf = pkgs.writeText "config.xml" ''
+  <?xml version="1.0" encoding="UTF-8"?>
+  <config version="2" xmlns="http://mediatomb.cc/config/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mediatomb.cc/config/2 http://mediatomb.cc/config/2.xsd">
+    <server>
+      <ui enabled="yes" show-tooltips="yes">
+        <accounts enabled="no" session-timeout="30">
+          <account user="mediatomb" password="mediatomb"/>
+        </accounts>
+      </ui>
+      <name>${cfg.serverName}</name>
+      <udn>uuid:${cfg.uuid}</udn>
+      <home>${cfg.dataDir}</home>
+      <webroot>${pkgs.mediatomb}/share/mediatomb/web</webroot>
+      <storage>
+        <sqlite3 enabled="yes">
+          <database-file>mediatomb.db</database-file>
+        </sqlite3>
+      </storage>
+      <protocolInfo extend="${if cfg.ps3Support then "yes" else "no"}"/>
+      ${if cfg.dsmSupport then ''
+      <custom-http-headers>
+        <add header="X-User-Agent: redsonic"/>
+      </custom-http-headers>
+
+      <manufacturerURL>redsonic.com</manufacturerURL>
+      <modelNumber>105</modelNumber>
+      '' else ""}
+      ${if cfg.tg100Support then ''
+      <upnp-string-limit>101</upnp-string-limit>
+      '' else ""}
+      <extended-runtime-options>
+        <mark-played-items enabled="yes" suppress-cds-updates="yes">
+          <string mode="prepend">*</string>
+          <mark>
+            <content>video</content>
+          </mark>
+        </mark-played-items>
+      </extended-runtime-options>
+    </server>
+    <import hidden-files="no">
+      <scripting script-charset="UTF-8">
+        <common-script>/nix/store/cngbzn39vidd6jm4wgzxfafqll74ybfa-mediatomb-0.12.1/share/mediatomb/js/common.js</common-script>
+        <playlist-script>/nix/store/cngbzn39vidd6jm4wgzxfafqll74ybfa-mediatomb-0.12.1/share/mediatomb/js/playlists.js</playlist-script>
+        <virtual-layout type="builtin">
+          <import-script>/nix/store/cngbzn39vidd6jm4wgzxfafqll74ybfa-mediatomb-0.12.1/share/mediatomb/js/import.js</import-script>
+        </virtual-layout>
+      </scripting>
+      <mappings>
+        <extension-mimetype ignore-unknown="no">
+          <map from="mp3" to="audio/mpeg"/>
+          <map from="ogx" to="application/ogg"/>
+          <map from="ogv" to="video/ogg"/>
+          <map from="oga" to="audio/ogg"/>
+          <map from="ogg" to="audio/ogg"/>
+          <map from="ogm" to="video/ogg"/>
+          <map from="asf" to="video/x-ms-asf"/>
+          <map from="asx" to="video/x-ms-asf"/>
+          <map from="wma" to="audio/x-ms-wma"/>
+          <map from="wax" to="audio/x-ms-wax"/>
+          <map from="wmv" to="video/x-ms-wmv"/>
+          <map from="wvx" to="video/x-ms-wvx"/>
+          <map from="wm" to="video/x-ms-wm"/>
+          <map from="wmx" to="video/x-ms-wmx"/>
+          <map from="m3u" to="audio/x-mpegurl"/>
+          <map from="pls" to="audio/x-scpls"/>
+          <map from="flv" to="video/x-flv"/>
+          <map from="mkv" to="video/x-matroska"/>
+          <map from="mka" to="audio/x-matroska"/>
+          ${if cfg.ps3Support then ''
+          <map from="avi" to="video/divx"/>
+          '' else ""}
+          ${if cfg.dsmSupport then ''
+          <map from="avi" to="video/avi"/>
+          '' else ""}
+        </extension-mimetype>
+        <mimetype-upnpclass>
+          <map from="audio/*" to="object.item.audioItem.musicTrack"/>
+          <map from="video/*" to="object.item.videoItem"/>
+          <map from="image/*" to="object.item.imageItem"/>
+        </mimetype-upnpclass>
+        <mimetype-contenttype>
+          <treat mimetype="audio/mpeg" as="mp3"/>
+          <treat mimetype="application/ogg" as="ogg"/>
+          <treat mimetype="audio/ogg" as="ogg"/>
+          <treat mimetype="audio/x-flac" as="flac"/>
+          <treat mimetype="audio/x-ms-wma" as="wma"/>
+          <treat mimetype="audio/x-wavpack" as="wv"/>
+          <treat mimetype="image/jpeg" as="jpg"/>
+          <treat mimetype="audio/x-mpegurl" as="playlist"/>
+          <treat mimetype="audio/x-scpls" as="playlist"/>
+          <treat mimetype="audio/x-wav" as="pcm"/>
+          <treat mimetype="audio/L16" as="pcm"/>
+          <treat mimetype="video/x-msvideo" as="avi"/>
+          <treat mimetype="video/mp4" as="mp4"/>
+          <treat mimetype="audio/mp4" as="mp4"/>
+          <treat mimetype="application/x-iso9660" as="dvd"/>
+          <treat mimetype="application/x-iso9660-image" as="dvd"/>
+        </mimetype-contenttype>
+      </mappings>
+      <online-content>
+        <YouTube enabled="no" refresh="28800" update-at-start="no" purge-after="604800" racy-content="exclude" format="mp4" hd="no">
+          <favorites user="mediatomb"/>
+          <standardfeed feed="most_viewed" time-range="today"/>
+          <playlists user="mediatomb"/>
+          <uploads user="mediatomb"/>
+          <standardfeed feed="recently_featured" time-range="today"/>
+        </YouTube>
+      </online-content>
+    </import>
+    <transcoding enabled="${if cfg.transcoding then "yes" else "no"}">
+      <mimetype-profile-mappings>
+        <transcode mimetype="video/x-flv" using="vlcmpeg"/>
+        <transcode mimetype="application/ogg" using="vlcmpeg"/>
+        <transcode mimetype="application/ogg" using="oggflac2raw"/>
+        <transcode mimetype="audio/x-flac" using="oggflac2raw"/>
+      </mimetype-profile-mappings>
+      <profiles>
+        <profile name="oggflac2raw" enabled="no" type="external">
+          <mimetype>audio/L16</mimetype>
+          <accept-url>no</accept-url>
+          <first-resource>yes</first-resource>
+          <accept-ogg-theora>no</accept-ogg-theora>
+          <agent command="ogg123" arguments="-d raw -o byteorder:big -f %out %in"/>
+          <buffer size="1048576" chunk-size="131072" fill-size="262144"/>
+        </profile>
+        <profile name="vlcmpeg" enabled="no" type="external">
+          <mimetype>video/mpeg</mimetype>
+          <accept-url>yes</accept-url>
+          <first-resource>yes</first-resource>
+          <accept-ogg-theora>yes</accept-ogg-theora>
+          <agent command="vlc" arguments="-I dummy %in --sout #transcode{venc=ffmpeg,vcodec=mp2v,vb=4096,fps=25,aenc=ffmpeg,acodec=mpga,ab=192,samplerate=44100,channels=2}:standard{access=file,mux=ps,dst=%out} vlc:quit"/>
+          <buffer size="14400000" chunk-size="512000" fill-size="120000"/>
+        </profile>
+      </profiles>
+    </transcoding>
+  </config>
+  '';
+
+in {
+
+
+  ###### interface
+
+  options = {
+
+    services.mediatomb = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable the mediatomb DLNA server.
+        '';
+      };
+
+      serverName = mkOption {
+        type = types.string;
+        default = "mediatomb";
+        description = ''
+          How to identify the server on the network.
+        '';
+      };
+
+      ps3Support = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable ps3 specific tweaks.
+          WARNING: incompatible with DSM 320 support.
+        '';
+      };
+
+      dsmSupport = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable D-Link DSM 320 specific tweaks.
+          WARNING: incompatible with ps3 support.
+        '';
+      };
+
+      tg100Support = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable Telegent TG100 specific tweaks.
+        '';
+      };
+
+      transcoding = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable transcoding.
+        '';
+      };
+
+      dataDir = mkOption {
+        type = types.path;
+        default = "/var/lib/mediatomb";
+        description = ''
+          The directory where mediatomb stores its state, data, etc.
+        '';
+      };
+
+      user = mkOption {
+        default = "mediatomb";
+        description = "User account under which mediatomb runs.";
+      };
+
+      group = mkOption {
+        default = "mediatomb";
+        description = "Group account under which mediatomb runs.";
+      };
+
+      port = mkOption {
+        default = 49152;
+        description = ''
+          The network port to listen on.
+        '';
+      };
+
+      uuid = mkOption {
+        default = "fdfc8a4e-a3ad-4c1d-b43d-a2eedb03a687";
+        description = ''
+          A unique (on your network) to identify the server by.
+        '';
+      };
+
+      customCfg = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Allow mediatomb to create and use its own config file inside ${cfg.dataDir}.
+        '';
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.mediatomb = {
+      description = "MediaTomb media Server";
+      after = [ "local-fs.target" "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.mediatomb ];
+      serviceConfig.ExecStart = "${pkgs.mediatomb}/bin/mediatomb -p ${toString cfg.port} ${if cfg.customCfg then "" else "-c ${mtConf}"} -m ${cfg.dataDir}";
+      serviceConfig.User = "${cfg.user}";
+    };
+
+    users.extraGroups = optionalAttrs (cfg.group == "mediatomb") (singleton {
+      name = "mediatomb";
+      gid = gid;
+    });
+
+    users.extraUsers = optionalAttrs (cfg.user == "mediatomb") (singleton {
+      name = "mediatomb";
+      isSystemUser = true;
+      group = cfg.group;
+      home = "${cfg.dataDir}";
+      createHome = true;
+      description = "Mediatomb DLNA Server User";
+    });
+
+    networking.firewall = {
+      allowedUDPPorts = [ 1900 cfg.port ];
+      allowedTCPPorts = [ cfg.port ];
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index f231998d8f47..6d25fef45768 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
@@ -357,7 +359,9 @@ in
 
     nix.nrBuildUsers = mkDefault (lib.max 10 cfg.maxJobs);
 
-    users.extraUsers = map makeNixBuildUser (range 1 cfg.nrBuildUsers);
+    users.extraUsers = nixbldUsers;
+
+    services.xserver.displayManager.hiddenUsers = map ({ name, ... }: name) nixbldUsers;
 
     system.activationScripts.nix = stringAfter [ "etc" "users" ]
       ''
@@ -375,9 +379,6 @@ in
           /nix/var/nix/gcroots/per-user \
           /nix/var/nix/profiles/per-user \
           /nix/var/nix/gcroots/tmp
-
-        ln -sf /nix/var/nix/profiles /nix/var/nix/gcroots/
-        ln -sf /nix/var/nix/manifests /nix/var/nix/gcroots/
       '';
 
   };
diff --git a/nixos/modules/services/misc/nixos-manual.nix b/nixos/modules/services/misc/nixos-manual.nix
index c0d7885280a5..c570a01fb3b2 100644
--- a/nixos/modules/services/misc/nixos-manual.nix
+++ b/nixos/modules/services/misc/nixos-manual.nix
@@ -3,7 +3,7 @@
 # of the virtual consoles.  The latter is useful for the installation
 # CD.
 
-{ config, lib, pkgs, baseModules, ... } @ extraArgs:
+{ config, lib, pkgs, baseModules, ... }:
 
 with lib;
 
@@ -14,11 +14,12 @@ let
   versionModule =
     { system.nixosVersionSuffix = config.system.nixosVersionSuffix;
       system.nixosRevision = config.system.nixosRevision;
+      nixpkgs.system = config.nixpkgs.system;
     };
 
   eval = evalModules {
     modules = [ versionModule ] ++ baseModules;
-    args = (removeAttrs extraArgs ["config" "options"]) // { modules = [ ]; };
+    args = (config._module.args) // { modules = [ ]; };
   };
 
   manual = import ../../../doc/manual {
diff --git a/nixos/modules/services/misc/ripple-data-api.nix b/nixos/modules/services/misc/ripple-data-api.nix
new file mode 100644
index 000000000000..6e5ac7ab00bd
--- /dev/null
+++ b/nixos/modules/services/misc/ripple-data-api.nix
@@ -0,0 +1,168 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.rippleDataApi;
+
+  deployment_env_config = builtins.toJSON {
+    production = {
+      port = toString cfg.port;
+      maxSockets = 150;
+      batchSize = 100;
+      startIndex = 32570;
+      rippleds = cfg.rippleds;
+      redis = {
+        enable = cfg.redis.enable;
+        host = cfg.redis.host;
+        port = cfg.redis.port;
+        options.auth_pass = null;
+      };
+    };
+  };
+
+  db_config = builtins.toJSON {
+    production = {
+      username = optional (cfg.couchdb.pass != "") cfg.couchdb.user;
+      password = optional (cfg.couchdb.pass != "") cfg.couchdb.pass;
+      host = cfg.couchdb.host;
+      port = cfg.couchdb.port;
+      database = cfg.couchdb.db;
+      protocol = "http";
+    };
+  };
+
+in {
+  options = {
+    services.rippleDataApi = {
+      enable = mkEnableOption "Whether to enable ripple data api.";
+
+      port = mkOption {
+        description = "Ripple data api port";
+        default = 5993;
+        type = types.int;
+      };
+
+      redis = {
+        enable = mkOption {
+          description = "Whether to enable caching of ripple data to redis.";
+          default = true;
+          type = types.bool;
+        };
+
+        host = mkOption {
+          description = "Ripple data api redis host.";
+          default = "localhost";
+          type = types.str;
+        };
+
+        port = mkOption {
+          description = "Ripple data api redis port.";
+          default = 5984;
+          type = types.int;
+        };
+      };
+
+      couchdb = {
+        host = mkOption {
+          description = "Ripple data api couchdb host.";
+          default = "localhost";
+          type = types.str;
+        };
+
+        port = mkOption {
+          description = "Ripple data api couchdb port.";
+          default = 5984;
+          type = types.int;
+        };
+
+        db = mkOption {
+          description = "Ripple data api couchdb database.";
+          default = "rippled";
+          type = types.str;
+        };
+
+        user = mkOption {
+          description = "Ripple data api couchdb username.";
+          default = "rippled";
+          type = types.str;
+        };
+
+        pass = mkOption {
+          description = "Ripple data api couchdb password.";
+          default = "";
+          type = types.str;
+        };
+
+        create = mkOption {
+          description = "Whether to create couchdb database needed by ripple data api.";
+          type = types.bool;
+          default = true;
+        };
+      };
+
+      rippleds = mkOption {
+        description = "List of rippleds to be used by ripple data api.";
+        default = [
+          "http://s_east.ripple.com:51234"
+          "http://s_west.ripple.com:51234"
+        ];
+        type = types.listOf types.str;
+      };
+    };
+  };
+
+  config = mkIf (cfg.enable) {
+    services.couchdb.enable = mkDefault true;
+    services.couchdb.bindAddress = mkDefault "0.0.0.0";
+    services.redis.enable = mkDefault true;
+
+    systemd.services.ripple-data-api = {
+      after = [ "couchdb.service" "redis.service" "ripple-data-api-importer.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+      environment = {
+        NODE_ENV = "production";
+        DEPLOYMENT_ENVS_CONFIG = pkgs.writeText "deployment.environment.json" deployment_env_config;
+        DB_CONFIG = pkgs.writeText "db.config.json" db_config;
+      };
+
+      serviceConfig = {
+        ExecStart = "${pkgs.ripple-data-api}/bin/api";
+        User = "ripple-data-api";
+      };
+    };
+
+    systemd.services.ripple-data-importer = {
+      after = [ "couchdb.service" ];
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.curl ];
+
+      environment = {
+        NODE_ENV = "production";
+        DEPLOYMENT_ENVS_CONFIG = pkgs.writeText "deployment.environment.json" deployment_env_config;
+        DB_CONFIG = pkgs.writeText "db.config.json" db_config;
+        LOG_FILE = "/dev/null";
+      };
+
+      serviceConfig = {
+        ExecStart = "${pkgs.ripple-data-api}/bin/importer live debug2";
+        User = "ripple-data-api";
+      };
+
+      preStart = mkMerge [
+        (mkIf (cfg.couchdb.create) ''
+          HOST="http://${optionalString (cfg.couchdb.pass != "") "${cfg.couchdb.user}:${cfg.couchdb.pass}@"}${cfg.couchdb.host}:${toString cfg.couchdb.port}"
+          curl -X PUT $HOST/${cfg.couchdb.db} || true
+        '')
+        "${pkgs.ripple-data-api}/bin/update-views"
+      ];
+    };
+
+    users.extraUsers = singleton
+      { name = "ripple-data-api";
+        description = "Ripple data api user";
+        uid = config.ids.uids.ripple-data-api;
+      };
+  };
+}
diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix
index 2c1fec9f6d7c..85a1ed8ae9e3 100644
--- a/nixos/modules/services/misc/rippled.nix
+++ b/nixos/modules/services/misc/rippled.nix
@@ -1,5 +1,3 @@
-# configuration building is commented out until better tested.
-
 { config, lib, pkgs, ... }:
 
 with lib;
@@ -7,266 +5,366 @@ with lib;
 let
   cfg = config.services.rippled;
 
-  rippledStateCfgFile = "/var/lib/rippled/rippled.cfg";
+  b2i = val: if val then "1" else "0";
+
+  dbCfg = db: ''
+    type=${db.type}
+    path=${db.path}
+    ${optionalString (db.compression != null) ("compression=${b2i db.compression}") }
+    ${optionalString (db.onlineDelete != null) ("online_delete=${toString db.onlineDelete}")}
+    ${optionalString (db.advisoryDelete != null) ("advisory_delete=${toString db.advisoryDelete}")}
+    ${db.extraOpts}
+  '';
 
   rippledCfg = ''
+    [server]
+    ${concatMapStringsSep "\n" (n: "port_${n}") (attrNames cfg.ports)}
+
+    ${concatMapStrings (p: ''
+    [port_${p.name}]
+    ip=${p.ip}
+    port=${toString p.port}
+    protocol=${concatStringsSep "," p.protocol}
+    ${optionalString (p.user != "") "user=${p.user}"}
+    ${optionalString (p.password != "") "user=${p.password}"}
+    admin=${if p.admin then "allow" else "no"}
+    ${optionalString (p.ssl.key != null) "ssl_key=${p.ssl.key}"}
+    ${optionalString (p.ssl.cert != null) "ssl_cert=${p.ssl.cert}"}
+    ${optionalString (p.ssl.chain != null) "ssl_chain=${p.ssl.chain}"}
+    '') (attrValues cfg.ports)}
+
+    [database_path]
+    ${cfg.databasePath}
+
     [node_db]
-    type=HyperLevelDB
-    path=/var/lib/rippled/db/hyperldb
+    ${dbCfg cfg.nodeDb}
 
-    [debug_logfile]
-    /var/log/rippled/debug.log
+    ${optionalString (cfg.tempDb != null) ''
+    [temp_db]
+    ${dbCfg cfg.tempDb}''}
 
-  ''
-  + optionalString (cfg.peerIp != null) ''
-    [peer_ip]
-    ${cfg.peerIp}
+    ${optionalString (cfg.importDb != null) ''
+    [import_db]
+    ${dbCfg cfg.importDb}''}
 
-    [peer_port]
-    ${toString cfg.peerPort}
+    [ips]
+    ${concatStringsSep "\n" cfg.ips}
 
-  ''
-  + cfg.extraConfig;
+    [ips_fixed]
+    ${concatStringsSep "\n" cfg.ipsFixed}
 
-  rippledCfgFile = pkgs.writeText "rippled.cfg" rippledCfg;
-    
-in
+    [validators]
+    ${concatStringsSep "\n" cfg.validators}
 
-{
+    [node_size]
+    ${cfg.nodeSize}
 
-  ###### interface
+    [ledger_history]
+    ${toString cfg.ledgerHistory}
 
-  options = {
+    [fetch_depth]
+    ${toString cfg.fetchDepth}
 
-    services.rippled = {
+    [validation_quorum]
+    ${toString cfg.validationQuorum}
 
-      enable = mkOption {
-        default = false;
-	description = "Whether to enable rippled";
-      };
+    [sntp_servers]
+    ${concatStringsSep "\n" cfg.sntpServers}
 
-      #
-      # Rippled has a simple configuration file layout that is easy to 
-      # build with nix. Many of the options are defined here but are 
-      # commented out until the code to append them to the config above
-      # is written and they are tested.
-      #
-      # If you find a yourself implementing more options, please submit a 
-      # pull request.
-      #
-
-      /*
-      ips = mkOption {
-        default = [ "r.ripple.com 51235" ];
-	example = [ "192.168.0.1" "192.168.0.1 3939" "r.ripple.com 51235" ];
-	description = ''
-	  List of hostnames or ips where the Ripple protocol is served.
-	  For a starter list, you can either copy entries from: 
-	  https://ripple.com/ripple.txt or if you prefer you can let it
-	   default to r.ripple.com 51235
+    [rpc_startup]
+    { "command": "log_level", "severity": "${cfg.logLevel}" }
+  '' + cfg.extraConfig;
 
-	  A port may optionally be specified after adding a space to the 
-	  address. By convention, if known, IPs are listed in from most 
-	  to least trusted.
-	'';
+  portOptions = { name, ...}: {
+    options = {
+      name = mkOption {
+	internal = true;
+	default = name;
       };
 
-      ipsFixed = mkOption {
-        default = null;
-	example = [ "192.168.0.1" "192.168.0.1 3939" "r.ripple.com 51235" ];
-	description = ''
-	  List of IP addresses or hostnames to which rippled should always 
-	  attempt to maintain peer connections with. This is useful for 
-	  manually forming private networks, for example to configure a 
-	  validation server that connects to the Ripple network through a 
-	  public-facing server, or for building a set of cluster peers.
+      ip = mkOption {
+	default = "127.0.0.1";
+	description = "Ip where rippled listens.";
+	type = types.str;
+      };
 
-	  A port may optionally be specified after adding a space to the address
-	'';
+      port = mkOption {
+	description = "Port where rippled listens.";
+	type = types.int;
       };
-      */
 
-      peerIp = mkOption {
-        default = null;
-	example = "0.0.0.0";
-	description = ''
-	  IP address or domain to bind to allow external connections from peers.
-	  Defaults to not binding, which disallows external connections from peers.
-        '';
+      protocol = mkOption {
+	description = "Protocols expose by rippled.";
+	type = types.listOf (types.enum ["http" "https" "ws" "wss" "peer"]);
       };
 
-      peerPort = mkOption {
-	default = 51235;
-	description = ''
-	  If peerIp is supplied, corresponding port to bind to for peer connections.
-	'';
+      user = mkOption {
+	description = "When set, these credentials will be required on HTTP/S requests.";
+	type = types.str;
+	default = "";
       };
 
-      /*
-      peerPortProxy = mkOption {
-        type = types.int;
-	example = 51236;
-	description = ''
-	  An optional, additional listening port number for peers. Incoming
-	  connections on this port will be required to provide a PROXY Protocol
-	  handshake, described in this document (external link):
+      password = mkOption {
+	description = "When set, these credentials will be required on HTTP/S requests.";
+	type = types.str;
+	default = "";
+      };
 
-	    http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
+      admin = mkOption {
+	description = "Controls whether or not administrative commands are allowed.";
+	type = types.bool;
+	default = false;
+      };
 
-	  The PROXY Protocol is a popular method used by elastic load balancing
-	  service providers such as Amazon, to identify the true IP address and
-	  port number of external incoming connections.
+      ssl = {
+	key = mkOption {
+	  description = ''
+	    Specifies the filename holding the SSL key in PEM format.
+	  '';
+	  default = null;
+	  type = types.nullOr types.path;
+	};
+
+	cert = mkOption {
+	  description = ''
+	    Specifies the path to the SSL certificate file in PEM format.
+	    This is not needed if the chain includes it.
+	  '';
+	  default = null;
+	  type = types.nullOr types.path;
+	};
+
+	chain = mkOption {
+	  description = ''
+	    If you need a certificate chain, specify the path to the
+	    certificate chain here. The chain may include the end certificate.
+	  '';
+	  default = null;
+	  type = types.nullOr types.path;
+	};
 
-	  In addition to enabling this setting, it will also be required to
-	  use your provider-specific control panel or administrative web page
-	  to configure your server instance to receive PROXY Protocol handshakes,
-	  and also to restrict access to your instance to the Elastic Load Balancer.
-	'';
       };
-
-      peerPrivate = mkOption {
-        default = null;
-	example = 0;
-	description = ''
-	 0: Request peers to broadcast your address. Normal outbound peer connections [default]
-	 1: Request peers not broadcast your address. Only connect to configured peers.
-       '';
-     };
-
-     peerSslCipherList = mkOption {
-       default = null;
-       example = "ALL:!LOW:!EXP:!MD5:@STRENGTH";
-       description = ''
-         A colon delimited string with the allowed SSL cipher modes for peer. The
-	 choices for for ciphers are defined by the OpenSSL API function
-	 SSL_CTX_set_cipher_list, documented here (external link):
-
-	  http://pic.dhe.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_ssl_ctx_set_cipher_list.html
-
-	The default setting of "ALL:!LOW:!EXP:!MD5:@STRENGTH", which allows
-	non-authenticated peer connections (they are, however, secure).
-      '';
     };
+  };
 
-    nodeSeed = mkOption {
-      default = null;
-      example = "RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE";
-      description = ''
-        This is used for clustering. To force a particular node seed or key, the
-	key can be set here.  The format is the same as the validation_seed field.
-	To obtain a validation seed, use the rippled validation_create command.
-      '';
+  dbOptions = {
+    type = mkOption {
+      description = "Rippled database type.";
+      type = types.enum ["rocksdb" "nudb" "sqlite"];
+      default = "rocksdb";
     };
 
-    clusterNodes = mkOption {
-      default = null;
-      example = [ "n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5" ];
-      description = ''
-        To extend full trust to other nodes, place their node public keys here.
-	Generally, you should only do this for nodes under common administration.
-	Node public keys start with an 'n'. To give a node a name for identification
-	place a space after the public key and then the name.
-      '';
+    path = mkOption {
+      description = "Location to store the database.";
+      type = types.path;
+      default = cfg.databasePath;
     };
 
-    sntpServers = mkOption {
+    compression = mkOption {
+      description = "Whether to enable snappy compression.";
+      type = types.nullOr types.bool;
       default = null;
-      example = [ "time.nist.gov" "pool.ntp.org" ];
-      description = ''
-        IP address or domain of NTP servers to use for time synchronization.
-      '';
     };
 
-    # TODO: websocket options
-
-    rpcAllowRemote = mkOption {
-      default = false;
-      description = ''
-        false: Allow RPC connections only from 127.0.0.1. [default]
-	true:  Allow RPC connections from any IP.
-      '';
+    onlineDelete = mkOption {
+      description = "Enable automatic purging of older ledger information.";
+      type = types.addCheck (types.nullOr types.int) (v: v > 256);
+      default = cfg.ledgerHistory;
     };
 
-    rpcAdminAllow = mkOption {
-      example = [ "10.0.0.4" ];
+    advisoryDelete = mkOption {
       description = ''
-        List of IP addresses allowed to have admin access.
+	If set, then require administrative RPC call "can_delete"
+	to enable online deletion of ledger records.
       '';
+      type = types.nullOr types.bool;
+      default = null;
     };
 
-    rpcAdminUser = mkOption {
-      type = types.str;
-      description = ''
-        As a server, require this as the admin user to be specified.  Also, require
-	rpc_admin_user and rpc_admin_password to be checked for RPC admin functions.
-	The request must specify these as the admin_user and admin_password in the
-	request object.
-      '';
+    extraOpts = mkOption {
+      description = "Extra database options.";
+      type = types.lines;
+      default = "";
     };
+  };
 
-    rpcAdminPassword = mkOption {
-      type = types.str;
-      description = ''
-        As a server, require this as the admin pasword to be specified.  Also,
-	require rpc_admin_user and rpc_admin_password to be checked for RPC admin
-	functions.  The request must specify these as the admin_user and
-	admin_password in the request object.
-      '';
-    };
+in
+
+{
+
+  ###### interface
+
+  options = {
+    services.rippled = {
+      enable = mkEnableOption "Whether to enable rippled";
+
+      package = mkOption {
+	description = "Which rippled package to use.";
+	type = types.package;
+	default = pkgs.rippled;
+      };
+
+      ports = mkOption {
+	description = "Ports exposed by rippled";
+	type = types.attrsOf types.optionSet;
+	options = [portOptions];
+	default = {
+	  rpc = {
+	    port = 5005;
+	    admin = true;
+	    protocol = ["http"];
+	  };
+
+	  peer = {
+	    port = 51235;
+	    ip = "0.0.0.0";
+	    protocol = ["peer"];
+	  };
+
+	  ws_public = {
+	    port = 5006;
+	    ip = "0.0.0.0";
+	    protocol = ["ws" "wss"];
+	  };
+	};
+      };
 
-      rpcIp = mkOption {
-        type = types.str;
+      nodeDb = mkOption {
+	description = "Rippled main database options.";
+	type = types.nullOr types.optionSet;
+	options = [dbOptions];
+	default = {
+	  type = "rocksdb";
+	  extraOpts = ''
+	    open_files=2000
+	    filter_bits=12
+	    cache_mb=256
+	    file_size_pb=8
+	    file_size_mult=2;
+	  '';
+	};
+      };
+
+      tempDb = mkOption {
+	description = "Rippled temporary database options.";
+	type = types.nullOr types.optionSet;
+	options = [dbOptions];
+	default = null;
+      };
+
+      importDb = mkOption {
+	description = "Settings for performing a one-time import.";
+	type = types.nullOr types.optionSet;
+	options = [dbOptions];
+	default = null;
+      };
+
+      nodeSize = mkOption {
 	description = ''
-	  IP address or domain to bind to allow insecure RPC connections.
-	  Defaults to not binding, which disallows RPC connections.
+	  Rippled size of the node you are running.
+	  "tiny", "small", "medium", "large", and "huge"
 	'';
+	type = types.enum ["tiny" "small" "medium" "large" "huge"];
+	default = "small";
       };
 
-      rpcPort = mkOption {
-        type = types.int;
-        description = ''
-          If rpcIp is supplied, corresponding port to bind to for peer connections.
-        '';
+      ips = mkOption {
+	description = ''
+	  List of hostnames or ips where the Ripple protocol is served.
+	  For a starter list, you can either copy entries from:
+	  https://ripple.com/ripple.txt or if you prefer you can let it
+	   default to r.ripple.com 51235
+
+	  A port may optionally be specified after adding a space to the
+	  address. By convention, if known, IPs are listed in from most
+	  to least trusted.
+	'';
+	type = types.listOf types.str;
+	default = ["r.ripple.com 51235"];
+      };
+
+      ipsFixed = mkOption {
+	description = ''
+	  List of IP addresses or hostnames to which rippled should always
+	  attempt to maintain peer connections with. This is useful for
+	  manually forming private networks, for example to configure a
+	  validation server that connects to the Ripple network through a
+	  public-facing server, or for building a set of cluster peers.
+
+	  A port may optionally be specified after adding a space to the address
+	'';
+	type = types.listOf types.str;
+	default = [];
+      };
+
+      validators = mkOption {
+	description = ''
+	  List of nodes to always accept as validators. Nodes are specified by domain
+	  or public key.
+	'';
+	type = types.listOf types.str;
+	default = [
+	  "n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7  RL1"
+	  "n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj  RL2"
+	  "n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C  RL3"
+	  "n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS  RL4"
+	  "n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA  RL5"
+	];
       };
 
-      rpcUser = mkOption {
-        type = types.str;
+      databasePath = mkOption {
 	description = ''
-	  Require a this user to specified and require rpcPassword to
-	  be checked for RPC access via the rpcIp and rpcPort. The user and password
-	  must be specified via HTTP's basic authentication method.
-	  As a client, supply this to the server via HTTP's basic authentication
-	  method.
+	  Path to the ripple database.
 	'';
+	type = types.path;
+	default = "/var/lib/rippled/db";
       };
 
-      rpcPassword = mkOption {
-        type = types.str;
+      validationQuorum = mkOption {
 	description = ''
-	  Require a this password to specified and require rpc_user to
-	  be checked for RPC access via the rpcIp and rpcPort. The user and password
-	  must be specified via HTTP's basic authentication method.
-	  As a client, supply this to the server via HTTP's basic authentication
-	  method.
+	  The minimum number of trusted validations a ledger must have before
+	  the server considers it fully validated.
 	'';
+	type = types.int;
+	default = 3;
       };
 
-      rpcStartup = mkOption {
-        example = [ ''"command" : "log_level"'' ''"partition" : "ripplecalc"'' ''"severity" : "trace"'' ];
-	description = "List of RPC commands to run at startup.";
+      ledgerHistory = mkOption {
+	description = ''
+	  The number of past ledgers to acquire on server startup and the minimum
+	  to maintain while running.
+	'';
+	type = types.either types.int (types.enum ["full"]);
+	default = 1296000; # 1 month
       };
 
-      rpcSecure = mkOption {
-        default = false;
+      fetchDepth = mkOption {
 	description = ''
-	  false: Server certificates are not provided for RPC clients using SSL [default]
-	  true:  Client RPC connections wil be provided with SSL certificates.
+	  The number of past ledgers to serve to other peers that request historical
+	  ledger data (or "full" for no limit).
+	'';
+	type = types.either types.int (types.enum ["full"]);
+	default = "full";
+      };
 
-	  Note that if rpc_secure is enabled, it will also be necessasry to configure the
-	  certificate file settings located in rpcSslCert, rpcSslChain, and rpcSslKey
+      sntpServers = mkOption {
+	description = ''
+	  IP address or domain of NTP servers to use for time synchronization.;
 	'';
+	type = types.listOf types.str;
+	default = [
+	  "time.windows.com"
+	  "time.apple.com"
+	  "time.nist.gov"
+	  "pool.ntp.org"
+	];
+      };
+
+      logLevel = mkOption {
+        description = "Logging verbosity.";
+	type = types.enum ["debug" "error" "info"];
+	default = "error";
       };
-      */
 
       extraConfig = mkOption {
         default = "";
@@ -275,8 +373,11 @@ in
 	'';
       };
 
+      config = mkOption {
+	internal = true;
+	default = pkgs.writeText "rippled.conf" rippledCfg;
+      };
     };
-
   };
 
 
@@ -288,27 +389,21 @@ in
       { name = "rippled";
         description = "Ripple server user";
         uid = config.ids.uids.rippled;
-	home = "/var/lib/rippled";
+	home = cfg.databasePath;
+	createHome = true;
       };
 
     systemd.services.rippled = {
-      path = [ pkgs.rippled ];
-
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
       serviceConfig = {
-        ExecStart = "${pkgs.rippled}/bin/rippled --fg -q --conf ${rippledStateCfgFile}";
-	WorkingDirectory = "/var/lib/rippled";
+        ExecStart = "${cfg.package}/bin/rippled --fg --conf ${cfg.config}";
+        User = "rippled";
       };
     };
 
-    networking.firewall.allowedTCPPorts = mkIf (cfg.peerIp != null) [ cfg.peerPort ];
+    environment.systemPackages = [ cfg.package ];
 
-    system.activationScripts.rippled = ''
-      mkdir -p /var/{lib,log}/rippled
-      chown -R rippled /var/{lib,log}/rippled
-      ln -sf ${rippledCfgFile} ${rippledStateCfgFile}
-    '';
   };
 }
diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix
index 0a06291da2a4..b6cf397f35c0 100644
--- a/nixos/modules/services/monitoring/cadvisor.nix
+++ b/nixos/modules/services/monitoring/cadvisor.nix
@@ -90,17 +90,9 @@ in {
             ${optionalString cfg.storageDriverSecure "-storage_driver_secure"}
           ''}
         '';
-        User = "cadvisor";
       };
     };
 
-    virtualisation.docker.enable = true;
-
-    users.extraUsers = singleton {
-      name = "cadvisor";
-      uid = config.ids.uids.cadvisor;
-      description = "Cadvisor user";
-      extraGroups = [ "docker" ];
-    };
+    virtualisation.docker.enable = mkDefault true;
   };
 }
diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix
index 8558c4ff8e48..31afa859e256 100644
--- a/nixos/modules/services/monitoring/munin.nix
+++ b/nixos/modules/services/monitoring/munin.nix
@@ -34,7 +34,7 @@ let
         cap=$(sed -nr 's/.*#%#\s+capabilities\s*=\s*(.+)/\1/p' $file)
 
         wrapProgram $file \
-          --set PATH "/var/setuid-wrappers:/run/current-system/sw/bin:/run/current-system/sw/sbin" \
+          --set PATH "/var/setuid-wrappers:/run/current-system/sw/bin:/run/current-system/sw/bin" \
           --set MUNIN_LIBDIR "${pkgs.munin}/lib" \
           --set MUNIN_PLUGSTATE "/var/run/munin"
 
@@ -194,7 +194,7 @@ in
 
         mkdir -p /etc/munin/plugins
         rm -rf /etc/munin/plugins/*
-        PATH="/var/setuid-wrappers:/run/current-system/sw/bin:/run/current-system/sw/sbin" ${pkgs.munin}/sbin/munin-node-configure --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${muninPlugins} --servicedir=/etc/munin/plugins 2>/dev/null | ${pkgs.bash}/bin/bash
+        PATH="/var/setuid-wrappers:/run/current-system/sw/bin:/run/current-system/sw/bin" ${pkgs.munin}/sbin/munin-node-configure --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${muninPlugins} --servicedir=/etc/munin/plugins 2>/dev/null | ${pkgs.bash}/bin/bash
       '';
       serviceConfig = {
         ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/";
diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix
index ce70739abbc4..0143d2e327bd 100644
--- a/nixos/modules/services/monitoring/scollector.nix
+++ b/nixos/modules/services/monitoring/scollector.nix
@@ -20,6 +20,10 @@ let
           cfg.collectors)}
     '';
 
+  cmdLineOpts = concatStringsSep " " (
+    [ "-h=${cfg.bosunHost}" "-c=${collectors}" ] ++ cfg.extraOpts
+  );
+
 in {
 
   options = {
@@ -79,6 +83,15 @@ in {
         '';
       };
 
+      extraOpts = mkOption {
+        type = with types; listOf str;
+        default = [];
+        example = [ "-d" ];
+        description = ''
+          Extra scollector command line options
+        '';
+      };
+
     };
 
   };
@@ -95,9 +108,7 @@ in {
         PermissionsStartOnly = true;
         User = cfg.user;
         Group = cfg.group;
-        ExecStart = ''
-          ${cfg.package}/bin/scollector -h=${cfg.bosunHost} -c=${collectors}
-        '';
+        ExecStart = "${cfg.package}/bin/scollector ${cmdLineOpts}";
       };
     };
 
diff --git a/nixos/modules/services/monitoring/teamviewer.nix b/nixos/modules/services/monitoring/teamviewer.nix
new file mode 100644
index 000000000000..beba5dcd1b06
--- /dev/null
+++ b/nixos/modules/services/monitoring/teamviewer.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.teamviewer;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.teamviewer.enable = mkEnableOption "teamviewer daemon";
+      
+  };
+
+  ###### implementation
+
+  config = mkIf (cfg.enable) {
+
+    environment.systemPackages = [ pkgs.teamviewer ];
+
+    systemd.services.teamviewerd = {
+      description = "TeamViewer remote control daemon";
+
+      wantedBy = [ "graphical.target" ];
+      after = [ "NetworkManager-wait-online.service" "network.target" ];
+
+      serviceConfig = {
+        Type = "forking";
+        ExecStart = "${pkgs.teamviewer}/bin/teamviewerd -d";
+        PIDFile = "/run/teamviewerd.pid";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        Restart = "on-abort";
+        StartLimitInterval = "60";
+        StartLimitBurst = "10";
+      };
+    };
+  };
+
+}
diff --git a/nixos/modules/services/network-filesystems/drbd.nix b/nixos/modules/services/network-filesystems/drbd.nix
index b914724abfe2..1bd67206444e 100644
--- a/nixos/modules/services/network-filesystems/drbd.nix
+++ b/nixos/modules/services/network-filesystems/drbd.nix
@@ -44,7 +44,7 @@ let cfg = config.services.drbd; in
 
     boot.extraModprobeConfig =
       ''
-        options drbd usermode_helper=/run/current-system/sw/sbin/drbdadm
+        options drbd usermode_helper=/run/current-system/sw/bin/drbdadm
       '';
 
     environment.etc = singleton
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 8c79bf663d15..d6babb8e9a51 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 000000000000..648097274641
--- /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/aiccu.nix b/nixos/modules/services/networking/aiccu.nix
new file mode 100644
index 000000000000..4301da288814
--- /dev/null
+++ b/nixos/modules/services/networking/aiccu.nix
@@ -0,0 +1,195 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.aiccu;
+  showBool = b: if b then "true" else "false";
+  notNull = a: ! isNull a;
+  configFile = pkgs.writeText "aiccu.conf" ''
+    ${if notNull cfg.username then "username " + cfg.username else ""}
+    ${if notNull cfg.password then "password " + cfg.password else ""}
+    protocol ${cfg.protocol}
+    server ${cfg.server}
+    ipv6_interface ${cfg.interfaceName}
+    verbose ${showBool cfg.verbose}
+    daemonize true
+    automatic ${showBool cfg.automatic}
+    requiretls ${showBool cfg.requireTLS}
+    pidfile ${cfg.pidFile}
+    defaultroute ${showBool cfg.defaultRoute}
+    ${if notNull cfg.setupScript then cfg.setupScript else ""}
+    makebeats ${showBool cfg.makeHeartBeats}
+    noconfigure ${showBool cfg.noConfigure}
+    behindnat ${showBool cfg.behindNAT}
+    ${if cfg.localIPv4Override then "local_ipv4_override" else ""}
+  '';
+
+in {
+
+  options = {
+
+    services.aiccu = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "Enable aiccu IPv6 over IPv4 SiXXs tunnel";
+      };
+
+      username = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        example = "FAB5-SIXXS";
+        description = "Login credential";
+      };
+
+      password = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        example = "TmAkRbBEr0";
+        description = "Login credential";
+      };
+
+      protocol = mkOption {
+        type = types.str;
+        default = "tic";
+        example = "tic|tsp|l2tp";
+        description = "Protocol to use for setting up the tunnel";
+      };
+
+      server = mkOption {
+        type = types.str;
+        default = "tic.sixxs.net";
+        example = "enabled.ipv6server.net";
+        description = "Server to use for setting up the tunnel";
+      };
+
+      interfaceName = mkOption {
+        type = types.str;
+        default = "aiccu";
+        example = "sixxs";
+        description = ''
+          The name of the interface that will be used as a tunnel interface.
+          On *BSD the ipv6_interface should be set to gifX (eg gif0) for proto-41 tunnels
+          or tunX (eg tun0) for AYIYA tunnels.
+        '';
+      };
+
+      tunnelID = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        example = "T12345";
+        description = "The tunnel id to use, only required when there are multiple tunnels in the list";
+      };
+
+      verbose = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "Be verbose?";
+      };
+
+      automatic = mkOption {
+        type = types.bool;
+        default = true;
+        example = false;
+        description = "Automatic Login and Tunnel activation";
+      };
+
+      requireTLS = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = ''
+          When set to true, if TLS is not supported on the server
+          the TIC transaction will fail.
+          When set to false, it will try a starttls, when that is
+          not supported it will continue.
+          In any case if AICCU is build with TLS support it will
+          try to do a 'starttls' to the TIC server to see if that
+          is supported.
+        '';
+      };
+
+      pidFile = mkOption {
+        type = types.path;
+        default = "/run/aiccu.pid";
+        example = "/var/lib/aiccu/aiccu.pid";
+        description = "Location of PID File";
+      };
+
+      defaultRoute = mkOption {
+        type = types.bool;
+        default = true;
+        example = false;
+        description = "Add a default route";
+      };
+
+      setupScript = mkOption {
+        type = with types; nullOr path;
+        default = null;
+        example = "/var/lib/aiccu/fix-subnets.sh";
+        description = "Script to run after setting up the interfaces";
+      };
+
+      makeHeartBeats = mkOption {
+        type = types.bool;
+        default = true;
+        example = false;
+        description = ''
+          In general you don't want to turn this off
+          Of course only applies to AYIYA and heartbeat tunnels not to static ones
+        '';
+      };
+
+      noConfigure = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "Don't configure anything";
+      };
+
+      behindNAT = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "Notify the user that a NAT-kind network is detected";
+      };
+
+      localIPv4Override = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = ''
+          Overrides the IPv4 parameter received from TIC
+          This allows one to configure a NAT into "DMZ" mode and then
+          forwarding the proto-41 packets to an internal host.
+
+          This is only needed for static proto-41 tunnels!
+          AYIYA and heartbeat tunnels don't require this.
+        '';
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.aiccu = {
+      description = "Automatic IPv6 Connectivity Client Utility";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.aiccu}/bin/aiccu start ${configFile}";
+        ExecStop = "${pkgs.aiccu}/bin/aiccu stop";
+        Type = "forking";
+        PIDFile = cfg.pidFile;
+        Restart = "no"; # aiccu startup errors are serious, do not pound the tic server or be banned.
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix
index 34bddf908731..8b90f295ed46 100644
--- a/nixos/modules/services/networking/btsync.nix
+++ b/nixos/modules/services/networking/btsync.nix
@@ -4,6 +4,9 @@ with lib;
 
 let
   cfg = config.services.btsync;
+
+  bittorrentSync = cfg.package;
+
   listenAddr = cfg.httpListenAddr + ":" + (toString cfg.httpListenPort);
 
   boolStr = x: if x then "true" else "false";
@@ -57,7 +60,7 @@ let
     ''
       {
         "device_name":     "${cfg.deviceName}",
-        "storage_path":    "/var/lib/btsync/",
+        "storage_path":    "${cfg.storagePath}",
         "listening_port":  ${toString cfg.listeningPort},
         "use_gui":         false,
 
@@ -195,6 +198,23 @@ in
           '';
       };
 
+      package = mkOption {
+        type = types.package;
+        example = literalExample "pkgs.bittorrentSync20";
+        description = ''
+          Branch of bittorrent sync to use.
+        '';
+      };
+
+      storagePath = mkOption {
+        type = types.path;
+        default = "/var/lib/btsync";
+        example = "/var/lib/btsync";
+        description = ''
+          Where to store the bittorrent sync files.
+        '';
+      };
+
       apiKey = mkOption {
         type = types.str;
         default = "";
@@ -256,9 +276,11 @@ in
         }
       ];
 
+    services.btsync.package = mkOptionDefault pkgs.bittorrentSync14;
+
     users.extraUsers.btsync = {
       description     = "Bittorrent Sync Service user";
-      home            = "/var/lib/btsync";
+      home            = cfg.storagePath;
       createHome      = true;
       uid             = config.ids.uids.btsync;
       group           = "btsync";
@@ -292,6 +314,6 @@ in
       };
     };
 
-    environment.systemPackages = [ pkgs.bittorrentSync ];
+    environment.systemPackages = [ cfg.package ];
   };
 }
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index 3ae010e81070..5308fd995085 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/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index bb94a8dacfa2..f01deb6ee7c8 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -3,24 +3,22 @@
 let
 
   inherit (lib) mkOption mkIf singleton;
-
   inherit (pkgs) ddclient;
 
   stateDir = "/var/spool/ddclient";
-
   ddclientUser = "ddclient";
-
-  ddclientFlags = "-foreground -file ${ddclientCfg}";
-
+  ddclientFlags = "-foreground -verbose -noquiet -file ${ddclientCfg}";
+  ddclientPIDFile = "${stateDir}/ddclient.pid";
   ddclientCfg = pkgs.writeText "ddclient.conf" ''
     daemon=600
     cache=${stateDir}/ddclient.cache
-    pid=${stateDir}/ddclient.pid
-    use=${config.services.ddclient.web}
+    pid=${ddclientPIDFile}
+    use=${config.services.ddclient.use}
     login=${config.services.ddclient.username}
     password=${config.services.ddclient.password}
     protocol=${config.services.ddclient.protocol}
     server=${config.services.ddclient.server}
+    ssl=${if config.services.ddclient.ssl then "yes" else "yes"}
     wildcard=YES
     ${config.services.ddclient.domain}
     ${config.services.ddclient.extraConfig}
@@ -34,10 +32,11 @@ in
 
   options = {
 
-    services.ddclient = {
+    services.ddclient = with lib.types; {
 
       enable = mkOption {
         default = false;
+        type = bool;
         description = ''
           Whether to synchronise your machine's IP address with a dynamic DNS provider (e.g. dyndns.org).
         '';
@@ -45,6 +44,7 @@ in
 
       domain = mkOption {
         default = "";
+        type = str;
         description = ''
           Domain name to synchronize.
         '';
@@ -52,76 +52,93 @@ in
 
       username = mkOption {
         default = "";
+        type = str;
         description = ''
           Username.
         '';
       };
 
       password = mkOption {
-        default = "" ;
+        default = "";
+        type = str;
         description = ''
           Password.
         '';
       };
 
       protocol = mkOption {
-        default = "dyndns2" ;
+        default = "dyndns2";
+        type = str;
         description = ''
-          Protocol to use with dynamic DNS provider. (see also, http://sourceforge.net/apps/trac/ddclient/wiki/Protocols)
+          Protocol to use with dynamic DNS provider (see http://sourceforge.net/apps/trac/ddclient/wiki/Protocols).
         '';
       };
 
       server = mkOption {
-        default = "members.dyndns.org" ;
+        default = "";
+        type = str;
         description = ''
-          Server
+          Server address.
+        '';
+      };
+
+      ssl = mkOption {
+        default = true;
+        type = bool;
+        description = ''
+          Whether to use to use SSL/TLS to connect to dynamic DNS provider.
         '';
       };
 
       extraConfig = mkOption {
-        default = "" ;
+        default = "";
+        type = str;
         description = ''
           Extra configuration. Contents will be added verbatim to the configuration file.
         '';
       };
 
-      web = mkOption {
-        default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '" ;
-        description = "";
+      use = mkOption {
+        default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '";
+        type = str;
+        description = ''
+          Method to determine the IP address to send to the dymanic DNS provider.
+        '';
       };
-
     };
-
   };
 
 
   ###### implementation
 
   config = mkIf config.services.ddclient.enable {
-  
-    environment.systemPackages = [ ddclient ];
-
-    users.extraUsers = singleton
-      { name = ddclientUser;
-        uid = config.ids.uids.ddclient;
-        description = "ddclient daemon user";
-        home = stateDir;
-      };
-
-    jobs.ddclient =
-      { name = "ddclient";
 
-        startOn = "startup";
+    environment.systemPackages = [ ddclient ];
 
-        preStart =
-          ''
-            mkdir -m 0755 -p ${stateDir}
-            chown ${ddclientUser} ${stateDir}
-          '';
+    users.extraUsers = singleton {
+      name = ddclientUser;
+      uid = config.ids.uids.ddclient;
+      description = "ddclient daemon user";
+      home = stateDir;
+    };
 
-        exec = "${ddclient}/bin/ddclient ${ddclientFlags}";
+    systemd.services.ddclient = {
+      description = "Dynamic DNS Client";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        # This may change back to forking if too many problems occur:
+        type = "simple";
+        User = ddclientUser;
+        Group = "nogroup"; #TODO get this to work
+        PermissionsStartOnly = "true";
+        PIDFile = ddclientPIDFile;
+        ExecStartPre = ''
+          ${pkgs.stdenv.shell} -c "${pkgs.coreutils}/bin/mkdir -m 0755 -p ${stateDir} && ${pkgs.coreutils}/bin/chown ${ddclientUser} ${stateDir}"
+        '';
+        ExecStart = "${ddclient}/bin/ddclient ${ddclientFlags}";
+        #ExecStartPost = "${pkgs.coreutils}/bin/rm -r ${stateDir}"; # Should we have this?
       };
-
+    };
   };
-
 }
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index fbb211911f1c..7ddabf73106e 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 887ea79c34b1..09e48ec4bff0 100644
--- a/nixos/modules/services/networking/haproxy.nix
+++ b/nixos/modules/services/networking/haproxy.nix
@@ -18,42 +18,8 @@ with lib;
       };
 
       config = mkOption {
-        type = types.lines;
-        default =
-          ''
-          global
-            log 127.0.0.1 local6
-            maxconn  24000
-            daemon
-            nbproc 1
-
-          defaults
-            mode http
-            option httpclose
-
-            # Remove requests from the queue if people press stop button
-            option abortonclose
-
-            # Try to connect this many times on failure
-            retries 3
-
-            # If a client is bound to a particular backend but it goes down,
-            # send them to a different one
-            option redispatch
-
-            monitor-uri /haproxy-ping
-
-            timeout connect 7s
-            timeout queue   300s
-            timeout client  300s
-            timeout server  300s
-
-            # Enable status page at this URL, on the port HAProxy is bound to
-            stats enable
-            stats uri /haproxy-status
-            stats refresh 5s
-            stats realm Haproxy statistics
-          '';
+        type = types.nullOr types.lines;
+        default = null;
         description = ''
           Contents of the HAProxy configuration file,
           <filename>haproxy.conf</filename>.
@@ -66,6 +32,11 @@ with lib;
 
   config = mkIf cfg.enable {
 
+    assertions = [{
+      assertion = cfg.config != null;
+      message = "You must provide services.haproxy.config.";
+    }];
+
     systemd.services.haproxy = {
       description = "HAProxy";
       after = [ "network.target" ];
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index f72c7fb39d6c..f00c5d1f701d 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.
+        '';
+      };
     };
   };
 
@@ -152,16 +183,24 @@ in {
       { source = "${networkmanager_pptp}/etc/NetworkManager/VPN/nm-pptp-service.name";
         target = "NetworkManager/VPN/nm-pptp-service.name";
       }
+      { source = "${networkmanager_l2tp}/etc/NetworkManager/VPN/nm-l2tp-service.name";
+        target = "NetworkManager/VPN/nm-l2tp-service.name";
+      }
     ] ++ 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
         networkmanager_vpnc
         networkmanager_openconnect
         networkmanager_pptp
+        networkmanager_l2tp
         modemmanager
         ];
 
@@ -205,6 +244,7 @@ in {
         networkmanager_vpnc
         networkmanager_openconnect
         networkmanager_pptp
+        networkmanager_l2tp
         modemmanager
         ];
 
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index 140b7ed2da37..36d9f5d2f166 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -9,6 +9,14 @@ let
   stateDir = "/var/lib/nsd";
   pidFile  = stateDir + "/var/nsd.pid";
 
+  nsdPkg = pkgs.nsd.override {
+    bind8Stats = cfg.bind8Stats;
+    ipv6       = cfg.ipv6;
+    ratelimit  = cfg.ratelimit.enable;
+    rootServer = cfg.rootServer;
+    zoneStats  = length (collect (x: (x.zoneStats or null) != null) cfg.zones) > 0;
+  };
+
   zoneFiles = pkgs.stdenv.mkDerivation {
     preferLocalBuild = true;
     name = "nsd-env";
@@ -107,6 +115,7 @@ let
     zone:
       name:         "${name}"
       zonefile:     "${stateDir}/zones/${name}"
+      ${maybeString "zonestats: "          zone.zoneStats}
       ${maybeString "outgoing-interface: " zone.outgoingInterface}
     ${forEach     "  rrl-whitelist: "      zone.rrlWhitelist}
 
@@ -270,6 +279,19 @@ let
           Use imports or pkgs.lib.readFile if you don't want this data in your config file.
         '';
       };
+
+      zoneStats = mkOption {
+        type        = types.nullOr types.str;
+        default     = null;
+        example     = "%s";
+        description = ''
+          When set to something distinct to null NSD is able to collect
+          statistics per zone. All statistics of this zone(s) will be added
+          to the group specified by this given name. Use "%s" to use the zones
+          name as the group. The groups are output from nsd-control stats
+          and stats_noreset.
+        '';
+      };
     };
   };
 
@@ -286,6 +308,15 @@ in
         '';
       };
 
+      bind8Stats = mkOption {
+        type        = types.bool;
+        default     = false;
+        example     = true;
+        description = ''
+          Wheter to enable BIND8 like statisics.
+        '';
+      };
+
       rootServer = mkOption {
         type        = types.bool;
         default     = false;
@@ -659,13 +690,6 @@ in
 
   config = mkIf cfg.enable {
 
-    # this is not working :(
-    nixpkgs.config.nsd = {
-      ipv6       = cfg.ipv6;
-      ratelimit  = cfg.ratelimit.enable;
-      rootServer = cfg.rootServer;
-    };
-
     users.extraGroups = singleton {
       name = username;
       gid  = config.ids.gids.nsd;
@@ -688,7 +712,7 @@ in
       serviceConfig = {
         PIDFile   = pidFile;
         Restart   = "always";
-        ExecStart = "${pkgs.nsd}/sbin/nsd -d -c ${configFile}";
+        ExecStart = "${nsdPkg}/sbin/nsd -d -c ${configFile}";
       };
 
       preStart = ''
diff --git a/nixos/modules/services/networking/rdnssd.nix b/nixos/modules/services/networking/rdnssd.nix
index 4c1891816e3e..95833d31e99d 100644
--- a/nixos/modules/services/networking/rdnssd.nix
+++ b/nixos/modules/services/networking/rdnssd.nix
@@ -4,7 +4,12 @@
 { config, lib, pkgs, ... }:
 
 with lib;
-
+let
+  mergeHook = pkgs.writeScript "rdnssd-merge-hook" ''
+    #! ${pkgs.stdenv.shell} -e
+    ${pkgs.openresolv}/bin/resolvconf -u
+  '';
+in
 {
 
   ###### interface
@@ -30,18 +35,39 @@ with lib;
 
   config = mkIf config.services.rdnssd.enable {
 
-    jobs.rdnssd =
-      { description = "RDNSS daemon";
-
-        # Start before the network interfaces are brought up so that
-        # the daemon receives RDNSS advertisements from the kernel.
-        startOn = "starting network-interfaces";
-
-        # !!! Should write to /var/run/rdnssd/resolv.conf and run the daemon under another uid.
-        exec = "${pkgs.ndisc6}/sbin/rdnssd --resolv-file /etc/resolv.conf -u root";
-
-        daemonType = "fork";
+    systemd.services.rdnssd = {
+      description = "RDNSS daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = ''
+        # Create the proper run directory
+        mkdir -p /run/rdnssd
+        touch /run/rdnssd/resolv.conf
+        chown -R rdnssd /run/rdnssd
+
+        # Link the resolvconf interfaces to rdnssd
+        rm -f /run/resolvconf/interfaces/rdnssd
+        ln -s /run/rdnssd/resolv.conf /run/resolvconf/interfaces/rdnssd
+        ${mergeHook}
+      '';
+
+      postStop = ''
+        rm -f /run/resolvconf/interfaces/rdnssd
+        ${mergeHook}
+      '';
+
+      serviceConfig = {
+        ExecStart = "@${pkgs.ndisc6}/bin/rdnssd rdnssd -p /run/rdnssd/rdnssd.pid -r /run/rdnssd/resolv.conf -u rdnssd -H ${mergeHook}";
+        Type = "forking";
+        PIDFile = "/run/rdnssd/rdnssd.pid";
       };
+    };
+
+    users.extraUsers.rdnssd = {
+      description = "RDNSSD Daemon User";
+      uid = config.ids.uids.rdnssd;
+    };
 
   };
 
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index c0ad9e17c413..b2740bd33b7f 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -9,12 +9,6 @@ let
 
   nssModulesPath = config.system.nssModules.path;
 
-  permitRootLoginCheck = v:
-    v == "yes" ||
-    v == "without-password" ||
-    v == "forced-commands-only" ||
-    v == "no";
-
   knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
 
   knownHostsText = flip (concatMapStringsSep "\n") knownHosts
@@ -116,12 +110,9 @@ in
 
       permitRootLogin = mkOption {
         default = "without-password";
-        type = types.addCheck types.str permitRootLoginCheck;
+        type = types.enum ["yes" "without-password" "forced-commands-only" "no"];
         description = ''
-          Whether the root user can login using ssh. Valid values are
-          <literal>yes</literal>, <literal>without-password</literal>,
-          <literal>forced-commands-only</literal> or
-          <literal>no</literal>.
+          Whether the root user can login using ssh.
         '';
       };
 
@@ -195,12 +186,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 +316,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 +372,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/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index 679aa81a13da..b573a356b351 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -183,7 +183,7 @@ in
     # gets loaded, and then cups cannot access the printers.
     boot.blacklistedKernelModules = [ "usblp" ];
 
-    systemd.services.cupsd =
+    systemd.services.cups =
       { description = "CUPS Printing Daemon";
 
         wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/security/munge.nix b/nixos/modules/services/security/munge.nix
new file mode 100644
index 000000000000..919c2c2b0e15
--- /dev/null
+++ b/nixos/modules/services/security/munge.nix
@@ -0,0 +1,61 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.munge;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.munge = {
+      enable = mkEnableOption "munge service";
+
+      password = mkOption {
+        default = "/etc/munge/munge.key";
+        type = types.string;
+        description = ''
+          The path to a daemon's secret key.
+        '';
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.munge ];
+
+    systemd.services.munged = { 
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      path = [ pkgs.munge pkgs.coreutils ];
+
+      preStart = ''
+        chmod 0700 ${cfg.password}
+        mkdir -p /var/lib/munge -m 0711
+        mkdir -p /var/log/munge -m 0700
+        mkdir -p /run/munge -m 0755
+      '';
+
+      serviceConfig = {
+        ExecStart = "${pkgs.munge}/bin/munged --syslog --key-file ${cfg.password}";
+        PIDFile = "/run/munge/munged.pid";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index 928f16c94489..d40f7d6d05d9 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -130,6 +130,9 @@ in
         config.system.path
       ];
 
+    # Don't restart dbus-daemon. Bad things tend to happen if we do.
+    systemd.services.dbus.reloadIfChanged = true;
+
     environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ];
 
   };
diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
index 1b38ea3b679b..135113b3ceb1 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 6a830827fd78..2b5cba68d457 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/apache-httpd/owncloud.nix b/nixos/modules/services/web-servers/apache-httpd/owncloud.nix
index 3bea3c3ee1dd..a5e539bc9ba7 100644
--- a/nixos/modules/services/web-servers/apache-httpd/owncloud.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/owncloud.nix
@@ -384,8 +384,7 @@ rec {
     };
 
     adminPassword = mkOption {
-      description = "The admin password for accessing owncloud.
-        Warning: this is stored in cleartext in the Nix store!";
+      description = "The admin password for accessing owncloud.";
     };
 
     dbType = mkOption {
@@ -571,7 +570,7 @@ rec {
 
     chown wwwrun:wwwrun ${config.dataDir}/owncloud.log || true
 
-    QUERY="INSERT INTO groups (gid) values('admin'); INSERT INTO users (uid,password) values('${config.adminUser}','`echo -n "${config.adminPassword}" | ${pkgs.openssl}/bin/openssl dgst -sha1 | ${pkgs.gawk}/bin/awk '{print $2}'`'); INSERT INTO group_user (gid,uid) values('admin','${config.adminUser}');"
+    QUERY="INSERT INTO groups (gid) values('admin'); INSERT INTO users (uid,password) values('${config.adminUser}','${builtins.hashString "sha1" config.adminPassword}'); INSERT INTO group_user (gid,uid) values('admin','${config.adminUser}');"
     ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/psql -h "/tmp" -U postgres -d ${config.dbName} -Atw -c "$QUERY" || true
   '';
 }
diff --git a/nixos/modules/services/web-servers/fcgiwrap.nix b/nixos/modules/services/web-servers/fcgiwrap.nix
index 7e91e7b60eef..2c5e433003c8 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/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 0af1b58b7cae..0f21ef012639 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -102,6 +102,9 @@ in
         '';
       serviceConfig = {
         ExecStart = "${nginx}/bin/nginx -c ${configFile} -p ${cfg.stateDir}";
+        Restart = "on-failure";
+        RestartSec = "10s";
+        StartLimitInterval = "1min";
       };
     };
 
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 9165658a7be7..998bcd354c53 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -19,7 +19,7 @@ in
   # E.g., if KDE is enabled, it supersedes xterm.
   imports = [
     ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix ./kde5.nix
-    ./e19.nix ./gnome3.nix ./xbmc.nix ./kodi.nix
+    ./e19.nix ./gnome3.nix ./kodi.nix
   ];
 
   options = {
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index 9c3c65dcfaa7..02e51577e3e2 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -88,7 +88,9 @@ in
     };
 
     environment.systemPackages =
-      [
+      filter isDerivation (builtins.attrValues plasma5)
+      ++ filter isDerivation (builtins.attrValues kf5)
+      ++ [
         pkgs.qt4 # qtconfig is the only way to set Qt 4 theme
 
         kdeApps.kde-baseapps
@@ -97,13 +99,12 @@ in
         kdeApps.konsole
         kdeApps.oxygen-icons
 
+        kdeApps.kde-runtime
+
         pkgs.hicolor_icon_theme
 
         pkgs.orion # GTK theme, nearly identical to Breeze
-      ]
-      ++ filter isDerivation (builtins.attrValues plasma5)
-      ++ filter isDerivation (builtins.attrValues kf5)
-      ++ phononBackendPackages;
+      ] ++ phononBackendPackages;
 
     environment.pathsToLink = [ "/share" ];
 
@@ -121,6 +122,8 @@ in
 
     fonts.fonts = [ plasma5.oxygen-fonts ];
 
+    programs.ssh.askPassword = "${plasma5.ksshaskpass}/bin/ksshaskpass";
+
     # Enable helpful DBus services.
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
diff --git a/nixos/modules/services/x11/desktop-managers/xbmc.nix b/nixos/modules/services/x11/desktop-managers/xbmc.nix
deleted file mode 100644
index 97e966ca0197..000000000000
--- a/nixos/modules/services/x11/desktop-managers/xbmc.nix
+++ /dev/null
@@ -1,31 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.services.xserver.desktopManager.xbmc;
-in
-
-{
-  options = {
-    services.xserver.desktopManager.xbmc = {
-      enable = mkOption {
-        default = false;
-        example = true;
-        description = "Enable the xbmc multimedia center.";
-      };
-    };
-  };
-
-  config = mkIf cfg.enable {
-    services.xserver.desktopManager.session = [{
-      name = "xbmc";
-      start = ''
-        ${pkgs.xbmc}/bin/xbmc --lircdev /var/run/lirc/lircd --standalone &
-        waitPID=$!
-      '';
-    }];
-    
-    environment.systemPackages = [ pkgs.xbmc ];
-  };
-}
\ No newline at end of file
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 6a14a163c19a..fce5bf11f053 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -46,7 +46,6 @@ in
         pkgs.which # Needed by the xfce's xinitrc script.
         pkgs.xfce.exo
         pkgs.xfce.gtk_xfce_engine
-        pkgs.xfce.libxfcegui4 # For the icons.
         pkgs.xfce.mousepad
         pkgs.xfce.ristretto
         pkgs.xfce.terminal
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 601971d27b69..c5012dbb5e30 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 b3da0cda04a3..a7ebafa28b38 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 42eaacfe84af..d0b69c5452c2 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 98e3fd6d6a5d..6a7b810261da 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/bin/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 000000000000..c44383cc6117
--- /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/bin/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/hardware/multitouch.nix b/nixos/modules/services/x11/hardware/multitouch.nix
index 6e6e88e67218..f8386b5e333b 100644
--- a/nixos/modules/services/x11/hardware/multitouch.nix
+++ b/nixos/modules/services/x11/hardware/multitouch.nix
@@ -2,9 +2,15 @@
 
 with lib;
 
-let cfg = config.services.xserver.multitouch; in
-
-{
+let cfg = config.services.xserver.multitouch;
+    disabledTapConfig = ''
+      Option "MaxTapTime" "0"
+      Option "MaxTapMove" "0"
+      Option "TapButton1" "0"
+      Option "TapButton2" "0"
+      Option "TapButton3" "0"
+    '';
+in {
 
   options = {
 
@@ -30,6 +36,33 @@ let cfg = config.services.xserver.multitouch; in
         description = "Whether to ignore touches detected as being the palm (i.e when typing)";
       };
 
+      tapButtons = mkOption {
+        type = types.bool;
+        default = true;
+        example = false;
+        description = "Whether to enable tap buttons.";
+      };
+
+      buttonsMap = mkOption {
+        type = types.listOf types.int;
+        default = [3 2 0];
+        example = [1 3 2];
+        description = "Remap touchpad buttons.";
+        apply = map toString;
+      };
+
+      additionalOptions = mkOption {
+        type = types.str;
+        default = "";
+        example = ''
+          Option "ScaleDistance" "50"
+          Option "RotateDistance" "60"
+        '';
+        description = ''
+          Additional options for mtrack touchpad driver.
+        '';
+      };
+
     };
 
   };
@@ -46,12 +79,17 @@ let cfg = config.services.xserver.multitouch; in
           Identifier "Touchpads"
           Driver "mtrack"
           Option "IgnorePalm" "${if cfg.ignorePalm then "true" else "false"}"
+          Option "ClickFinger1" "${builtins.elemAt cfg.buttonsMap 0}"
+          Option "ClickFinger2" "${builtins.elemAt cfg.buttonsMap 1}"
+          Option "ClickFinger3" "${builtins.elemAt cfg.buttonsMap 2}"
+          ${optionalString (!cfg.tapButtons) disabledTapConfig}
           ${optionalString cfg.invertScroll ''
             Option "ScrollUpButton" "5"
             Option "ScrollDownButton" "4"
             Option "ScrollLeftButton" "7"
             Option "ScrollRightButton" "6"
           ''}
+          ${cfg.additionalOptions}
         EndSection
       '';
 
diff --git a/nixos/modules/services/x11/unclutter.nix b/nixos/modules/services/x11/unclutter.nix
new file mode 100644
index 000000000000..556d9e187fdd
--- /dev/null
+++ b/nixos/modules/services/x11/unclutter.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let cfg = config.services.unclutter;
+in {
+  options = {
+    services.unclutter.enable = mkOption {
+      type = types.bool;
+      default = false;
+      example = true;
+      description = "Enable unclutter to hide your mouse cursor when inactive";
+    };
+
+    services.unclutter.arguments = mkOption {
+      description = "Arguments to pass to unclutter command";
+      default = "-idle 1";
+      type = types.uniq types.string;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.unclutter = {
+      description = "unclutter";
+      requires = [ "display-manager.service" ];
+      after = [ "display-manager.service" ];
+      wantedBy = [ "graphical.target" ];
+      serviceConfig.ExecStart = ''
+        ${pkgs.unclutter}/bin/unclutter ${cfg.arguments}
+      '';
+      environment = { DISPLAY = ":0"; };
+      serviceConfig.Restart = "always";
+    };
+  };
+}
diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix
index 628d475c9684..097e4fe70d58 100644
--- a/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixos/modules/services/x11/window-managers/default.nix
@@ -8,14 +8,18 @@ in
 
 {
   imports = [
+    ./afterstep.nix
     ./bspwm.nix
     ./compiz.nix
+    ./fluxbox.nix
     ./herbstluftwm.nix
     ./i3.nix
     ./metacity.nix
     ./openbox.nix
+    ./ratpoison.nix
     ./sawfish.nix
     ./stumpwm.nix
+    ./spectrwm.nix
     ./twm.nix
     ./windowmaker.nix
     ./wmii.nix
diff --git a/nixos/modules/services/x11/window-managers/spectrwm.nix b/nixos/modules/services/x11/window-managers/spectrwm.nix
new file mode 100644
index 000000000000..5db6b41ba8fd
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/spectrwm.nix
@@ -0,0 +1,33 @@
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.spectrwm;
+in
+
+{
+  options = {
+    services.xserver.windowManager.spectrwm = {
+      enable = mkOption {
+        default = false;
+        example = true;
+        description = "Enable the spectrwm window manager.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.xserver.windowManager = {
+      session = [{
+        name = "spectrwm";
+        start = ''
+          ${pkgs.spectrwm}/bin/spectrwm &
+          waitPID=$!
+        '';
+      }];
+    };
+    environment.systemPackages = [ pkgs.spectrwm ];
+  };
+}
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index dbe13c022f09..7aa4b12a6543 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;
 }
 
-print STDERR "NOT restarting the following units: ", join(", ", sort(@unitsToSkip)), "\n"
-    if scalar @unitsToSkip > 0;
+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 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;
 }
@@ -321,16 +384,19 @@ system("@systemd@/bin/systemctl", "reset-failed");
 # Make systemd reload its units.
 system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3;
 
-# Signal dbus to reload its configuration before starting other units.
-# Other units may rely on newly installed policy files under /etc/dbus-1
-system("@systemd@/bin/systemctl", "reload-or-restart", "dbus.service");
+# Reload units that need it. This includes remounting changed mount
+# units.
+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);
+}
 
 # 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,20 +406,11 @@ 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;
-    unlink($reloadListFile);
-}
-
 
 # Print failed and new units.
 my (@failed, @new, @restarting);
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 4b5e84f53c1a..6153578612c1 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 a166709d39a3..585c8854feec 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -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/init-script/init-script.nix b/nixos/modules/system/boot/loader/init-script/init-script.nix
index 3b33d42b4ae4..374d9524ff1e 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 d3f32418a64c..1ea3ddd8867c 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/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index e1e472186e37..20eee8e06e07 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -405,29 +405,19 @@ in
 
     # copy the cryptsetup binary and it's dependencies
     boot.initrd.extraUtilsCommands = ''
-      cp -pdv ${pkgs.cryptsetup}/sbin/cryptsetup $out/bin
-
-      cp -pdv ${pkgs.libgcrypt}/lib/libgcrypt*.so.* $out/lib
-      cp -pdv ${pkgs.libgpgerror}/lib/libgpg-error*.so.* $out/lib
-      cp -pdv ${pkgs.cryptsetup}/lib/libcryptsetup*.so.* $out/lib
-      cp -pdv ${pkgs.popt}/lib/libpopt*.so.* $out/lib
+      copy_bin_and_libs ${pkgs.cryptsetup}/bin/cryptsetup
 
       ${optionalString luks.yubikeySupport ''
-      cp -pdv ${pkgs.ykpers}/bin/ykchalresp $out/bin
-      cp -pdv ${pkgs.ykpers}/bin/ykinfo $out/bin
-      cp -pdv ${pkgs.openssl}/bin/openssl $out/bin
-
-      cc -O3 -I${pkgs.openssl}/include -L${pkgs.openssl}/lib ${./pbkdf2-sha512.c} -o $out/bin/pbkdf2-sha512 -lcrypto
-      strip -s $out/bin/pbkdf2-sha512
+        copy_bin_and_libs ${pkgs.ykpers}/bin/ykchalresp
+        copy_bin_and_libs ${pkgs.ykpers}/bin/ykinfo
+        copy_bin_and_libs ${pkgs.openssl}/bin/openssl
 
-      cp -pdv ${pkgs.libusb1}/lib/libusb*.so.* $out/lib
-      cp -pdv ${pkgs.ykpers}/lib/libykpers*.so.* $out/lib
-      cp -pdv ${pkgs.libyubikey}/lib/libyubikey*.so.* $out/lib
-      cp -pdv ${pkgs.openssl}/lib/libssl*.so.* $out/lib
-      cp -pdv ${pkgs.openssl}/lib/libcrypto*.so.* $out/lib
+        cc -O3 -I${pkgs.openssl}/include -L${pkgs.openssl}/lib ${./pbkdf2-sha512.c} -o pbkdf2-sha512 -lcrypto
+        strip -s pbkdf2-sha512
+        copy_bin_and_libs pbkdf2-sha512
 
-      mkdir -p $out/etc/ssl
-      cp -pdv ${pkgs.openssl}/etc/ssl/openssl.cnf $out/etc/ssl
+        mkdir -p $out/etc/ssl
+        cp -pdv ${pkgs.openssl}/etc/ssl/openssl.cnf $out/etc/ssl
 
       cat > $out/bin/openssl-wrap <<EOF
 #!$out/bin/sh
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index a34a13602650..5af644279e5f 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
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 16bebe03740a..8b58eccdcec7 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -39,46 +39,60 @@ let
       mkdir -p $out/bin $out/lib
       ln -s $out/bin $out/sbin
 
-      # Copy what we need from Glibc.
-      cp -pv ${pkgs.glibc}/lib/ld*.so.? $out/lib
-      cp -pv ${pkgs.glibc}/lib/libc.so.* $out/lib
-      cp -pv ${pkgs.glibc}/lib/libm.so.* $out/lib
-      cp -pv ${pkgs.glibc}/lib/libpthread.so.* $out/lib
-      cp -pv ${pkgs.glibc}/lib/librt.so.* $out/lib
-      cp -pv ${pkgs.glibc}/lib/libdl.so.* $out/lib
-      cp -pv ${pkgs.gcc.cc}/lib*/libgcc_s.so.* $out/lib
+      copy_bin_and_libs () {
+        [ -f "$out/bin/$(basename $1)" ] && rm "$out/bin/$(basename $1)"
+        cp -pdv $1 $out/bin
+      }
 
       # Copy BusyBox.
-      cp -pvd ${pkgs.busybox}/bin/* ${pkgs.busybox}/sbin/* $out/bin/
+      for BIN in ${pkgs.busybox}/{s,}bin/*; do
+        copy_bin_and_libs $BIN
+      done
 
       # Copy some utillinux stuff.
-      cp -vf --remove-destination ${pkgs.utillinux}/sbin/blkid $out/bin
-      cp -pdv ${pkgs.utillinux}/lib/libblkid*.so.* $out/lib
-      cp -pdv ${pkgs.utillinux}/lib/libuuid*.so.* $out/lib
+      copy_bin_and_libs ${pkgs.utillinux}/sbin/blkid
 
       # Copy dmsetup and lvm.
-      cp -v ${pkgs.lvm2}/sbin/dmsetup $out/bin/dmsetup
-      cp -v ${pkgs.lvm2}/sbin/lvm $out/bin/lvm
-      cp -v ${pkgs.lvm2}/lib/libdevmapper.so.*.* $out/lib
-      cp -v ${pkgs.systemd}/lib/libsystemd.so.* $out/lib
+      copy_bin_and_libs ${pkgs.lvm2}/sbin/dmsetup
+      copy_bin_and_libs ${pkgs.lvm2}/sbin/lvm
 
       # Add RAID mdadm tool.
-      cp -v ${pkgs.mdadm}/sbin/mdadm $out/bin/mdadm
+      copy_bin_and_libs ${pkgs.mdadm}/sbin/mdadm
 
       # Copy udev.
-      cp -v ${udev}/lib/systemd/systemd-udevd ${udev}/bin/udevadm $out/bin
-      cp -v ${udev}/lib/udev/*_id $out/bin
-      cp -pdv ${udev}/lib/libudev.so.* $out/lib
-      cp -v ${pkgs.kmod}/lib/libkmod.so.* $out/lib
-      cp -v ${pkgs.acl}/lib/libacl.so.* $out/lib
-      cp -v ${pkgs.attr}/lib/libattr.so.* $out/lib
+      copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
+      copy_bin_and_libs ${udev}/bin/udevadm
+      for BIN in ${udev}/lib/udev/*_id; do
+        copy_bin_and_libs $BIN
+      done
 
       # Copy modprobe.
-      cp -v ${pkgs.kmod}/bin/kmod $out/bin/
+      copy_bin_and_libs ${pkgs.kmod}/bin/kmod
       ln -sf kmod $out/bin/modprobe
 
       ${config.boot.initrd.extraUtilsCommands}
 
+      # Copy ld manually since it isn't detected correctly
+      cp -pv ${pkgs.glibc}/lib/ld*.so.? $out/lib
+
+      # Copy all of the needed libraries for the binaries
+      for BIN in $(find $out/{bin,sbin} -type f); do
+        echo "Copying libs for bin $BIN"
+        LDD="$(ldd $BIN)" || continue
+        LIBS="$(echo "$LDD" | awk '{print $3}' | sed '/^$/d')"
+        for LIB in $LIBS; do
+          [ ! -f "$out/lib/$(basename $LIB)" ] && cp -pdv $LIB $out/lib
+          while [ "$(readlink $LIB)" != "" ]; do
+            LINK="$(readlink $LIB)"
+            if [ "${LINK:0:1}" != "/" ]; then
+              LINK="$(dirname $LIB)/$LINK"
+            fi
+            LIB="$LINK"
+            [ ! -f "$out/lib/$(basename $LIB)" ] && cp -pdv $LIB $out/lib
+          done
+        done
+      done
+
       # Strip binaries further than normal.
       chmod -R u+w $out
       stripDirs "lib bin" "-s"
@@ -100,10 +114,11 @@ let
       echo "testing patched programs..."
       $out/bin/ash -c 'echo hello world' | grep "hello world"
       export LD_LIBRARY_PATH=$out/lib
-      $out/bin/mount --help 2>&1 | grep "BusyBox"
+      $out/bin/mount --help 2>&1 | grep -q "BusyBox"
+      $out/bin/blkid --help 2>&1 | grep -q 'libblkid'
       $out/bin/udevadm --version
-      $out/bin/dmsetup --version 2>&1 | tee -a log | grep "version:"
-      LVM_SYSTEM_DIR=$out $out/bin/lvm version 2>&1 | tee -a log | grep "LVM"
+      $out/bin/dmsetup --version 2>&1 | tee -a log | grep -q "version:"
+      LVM_SYSTEM_DIR=$out $out/bin/lvm version 2>&1 | tee -a log | grep -q "LVM"
       $out/bin/mdadm --version
 
       ${config.boot.initrd.extraUtilsCommandsTest}
@@ -205,7 +220,7 @@ let
   # The closure of the init script of boot stage 1 is what we put in
   # the initial RAM disk.
   initialRamdisk = pkgs.makeInitrd {
-    inherit (config.boot.initrd) compressor;
+    inherit (config.boot.initrd) compressor prepend;
 
     contents =
       [ { object = bootStage1;
@@ -247,6 +262,14 @@ in
       '';
     };
 
+    boot.initrd.prepend = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        Other initrd files to prepend to the final initrd we are building.
+      '';
+    };
+
     boot.initrd.checkJournalingFS = mkOption {
       default = true;
       type = types.bool;
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index f853a8f6775c..29c449d4d0be 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -1,7 +1,7 @@
 { config, lib, pkgs, utils, ... }:
 
-with lib;
 with utils;
+with lib;
 with import ./systemd-unit-options.nix { inherit config lib; };
 
 let
@@ -13,7 +13,7 @@ let
 
   makeUnit = name: unit:
     let
-      pathSafeName = lib.replaceChars ["@" "\\"] ["-" "-"] name;
+      pathSafeName = lib.replaceChars ["@" ":" "\\"] ["-" "-" "-"] name;
     in
     if unit.enable then
       pkgs.runCommand "unit-${pathSafeName}" { preferLocalBuild = true; inherit (unit) text; }
diff --git a/nixos/modules/tasks/filesystems/btrfs.nix b/nixos/modules/tasks/filesystems/btrfs.nix
index d0a2ac645e0b..049f7708d739 100644
--- a/nixos/modules/tasks/filesystems/btrfs.nix
+++ b/nixos/modules/tasks/filesystems/btrfs.nix
@@ -17,13 +17,9 @@ in
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
-        mkdir -p $out/bin
-        cp -v ${pkgs.btrfsProgs}/bin/btrfs $out/bin
+        copy_bin_and_libs ${pkgs.btrfsProgs}/bin/btrfs
         ln -sv btrfs $out/bin/btrfsck
         ln -sv btrfsck $out/bin/fsck.btrfs
-        # !!! Increases uncompressed initrd by 240k
-        cp -pv ${pkgs.zlib}/lib/libz.so* $out/lib
-        cp -pv ${pkgs.lzo}/lib/liblzo2.so* $out/lib
       '';
 
     boot.initrd.extraUtilsCommandsTest = mkIf inInitrd
diff --git a/nixos/modules/tasks/filesystems/cifs.nix b/nixos/modules/tasks/filesystems/cifs.nix
index c60f175db841..3932b5c9acf9 100644
--- a/nixos/modules/tasks/filesystems/cifs.nix
+++ b/nixos/modules/tasks/filesystems/cifs.nix
@@ -18,7 +18,7 @@ in
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
-        cp -v ${pkgs.cifs_utils}/sbin/mount.cifs $out/bin
+        copy_bin_and_libs ${pkgs.cifs_utils}/sbin/mount.cifs
       '';
 
   };
diff --git a/nixos/modules/tasks/filesystems/ext.nix b/nixos/modules/tasks/filesystems/ext.nix
index 24592e9d5882..cc9d0ef37d59 100644
--- a/nixos/modules/tasks/filesystems/ext.nix
+++ b/nixos/modules/tasks/filesystems/ext.nix
@@ -10,12 +10,11 @@
     boot.initrd.extraUtilsCommands =
       ''
         # Copy e2fsck and friends.
-        cp -v ${pkgs.e2fsprogs}/sbin/e2fsck $out/bin
-        cp -v ${pkgs.e2fsprogs}/sbin/tune2fs $out/bin
+        copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/e2fsck
+        copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/tune2fs
         ln -sv e2fsck $out/bin/fsck.ext2
         ln -sv e2fsck $out/bin/fsck.ext3
         ln -sv e2fsck $out/bin/fsck.ext4
-        cp -pdv ${pkgs.e2fsprogs}/lib/lib*.so.* $out/lib
       '';
 
   };
diff --git a/nixos/modules/tasks/filesystems/f2fs.nix b/nixos/modules/tasks/filesystems/f2fs.nix
index 1ed7b1b6a62e..430ac630a885 100644
--- a/nixos/modules/tasks/filesystems/f2fs.nix
+++ b/nixos/modules/tasks/filesystems/f2fs.nix
@@ -13,9 +13,7 @@ in
     boot.initrd.availableKernelModules = mkIf inInitrd [ "f2fs" ];
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd ''
-      mkdir -p $out/bin $out/lib
-      cp -v   ${pkgs.f2fs-tools}/sbin/fsck.f2fs $out/bin
-      cp -pdv ${pkgs.f2fs-tools}/lib/lib*.so.* $out/lib
+      copy_bin_and_libs ${pkgs.f2fs-tools}/sbin/fsck.f2fs
     '';
   };
 }
diff --git a/nixos/modules/tasks/filesystems/jfs.nix b/nixos/modules/tasks/filesystems/jfs.nix
index b7091ce9b184..fc3905c7dc20 100644
--- a/nixos/modules/tasks/filesystems/jfs.nix
+++ b/nixos/modules/tasks/filesystems/jfs.nix
@@ -13,7 +13,7 @@ in
     boot.initrd.kernelModules = mkIf inInitrd [ "jfs" ];
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd ''
-      cp -v ${pkgs.jfsutils}/sbin/fsck.jfs "$out/bin/"
+      copy_bin_and_libs ${pkgs.jfsutils}/sbin/fsck.jfs
     '';
   };
 }
diff --git a/nixos/modules/tasks/filesystems/reiserfs.nix b/nixos/modules/tasks/filesystems/reiserfs.nix
index a3bfb3fed8ef..ab4c43e2ab82 100644
--- a/nixos/modules/tasks/filesystems/reiserfs.nix
+++ b/nixos/modules/tasks/filesystems/reiserfs.nix
@@ -17,8 +17,8 @@ in
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
-        cp -v ${pkgs.reiserfsprogs}/sbin/reiserfsck $out/bin
-        ln -sv reiserfsck $out/bin/fsck.reiserfs
+        copy_bin_and_libs ${pkgs.reiserfsprogs}/sbin/reiserfsck
+        ln -s reiserfsck $out/bin/fsck.reiserfs
       '';
 
   };
diff --git a/nixos/modules/tasks/filesystems/unionfs-fuse.nix b/nixos/modules/tasks/filesystems/unionfs-fuse.nix
index fe195e0db0b6..3e38bffa3ba2 100644
--- a/nixos/modules/tasks/filesystems/unionfs-fuse.nix
+++ b/nixos/modules/tasks/filesystems/unionfs-fuse.nix
@@ -7,9 +7,8 @@
       boot.initrd.kernelModules = [ "fuse" ];
 
       boot.initrd.extraUtilsCommands = ''
-        cp -v ${pkgs.fuse}/lib/libfuse* $out/lib
-        cp -v ${pkgs.fuse}/sbin/mount.fuse $out/bin
-        cp -v ${pkgs.unionfs-fuse}/bin/unionfs $out/bin
+        copy_bin_and_libs ${pkgs.fuse}/sbin/mount.fuse
+        copy_bin_and_libs ${pkgs.unionfs-fuse}/bin/unionfs
         substitute ${pkgs.unionfs-fuse}/sbin/mount.unionfs-fuse $out/bin/mount.unionfs-fuse \
           --replace '${pkgs.bash}/bin/bash' /bin/sh \
           --replace '${pkgs.fuse}/sbin' /bin \
diff --git a/nixos/modules/tasks/filesystems/vfat.nix b/nixos/modules/tasks/filesystems/vfat.nix
index 4cfe6e208f7e..958e27ae8a32 100644
--- a/nixos/modules/tasks/filesystems/vfat.nix
+++ b/nixos/modules/tasks/filesystems/vfat.nix
@@ -17,7 +17,7 @@ in
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
-        cp -v ${pkgs.dosfstools}/sbin/dosfsck $out/bin
+        copy_bin_and_libs ${pkgs.dosfstools}/sbin/dosfsck
         ln -sv dosfsck $out/bin/fsck.vfat
       '';
 
diff --git a/nixos/modules/tasks/filesystems/xfs.nix b/nixos/modules/tasks/filesystems/xfs.nix
index 5225b62a88c5..d7c3930f4a3c 100644
--- a/nixos/modules/tasks/filesystems/xfs.nix
+++ b/nixos/modules/tasks/filesystems/xfs.nix
@@ -17,7 +17,7 @@ in
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
-        cp -v ${pkgs.xfsprogs}/sbin/fsck.xfs $out/bin
+        copy_bin_and_libs ${pkgs.xfsprogs}/sbin/fsck.xfs
       '';
 
     # Trick just to set 'sh' after the extraUtils nuke-refs.
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 93782ffa4d58..d4b10e9ed09e 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -55,8 +55,7 @@ in
     boot.zfs = {
       useGit = mkOption {
         type = types.bool;
-        # TODO(wkennington): Revert when 0.6.4 is out
-        default = versionAtLeast config.boot.kernelPackages.kernel.version "3.19";
+        default = false;
         example = true;
         description = ''
           Use the git version of the SPL and ZFS packages.
@@ -204,11 +203,14 @@ in
         kernelModules = [ "spl" "zfs" ];
         extraUtilsCommands =
           ''
-            cp -v ${zfsUserPkg}/sbin/zfs $out/bin
-            cp -v ${zfsUserPkg}/sbin/zdb $out/bin
-            cp -v ${zfsUserPkg}/sbin/zpool $out/bin
-            cp -pdv ${zfsUserPkg}/lib/lib*.so* $out/lib
-            cp -pdv ${pkgs.zlib}/lib/lib*.so* $out/lib
+            copy_bin_and_libs ${zfsUserPkg}/sbin/zfs
+            copy_bin_and_libs ${zfsUserPkg}/sbin/zdb
+            copy_bin_and_libs ${zfsUserPkg}/sbin/zpool
+          '';
+        extraUtilsCommandsTest = mkIf inInitrd
+          ''
+            $out/bin/zfs --help >/dev/null 2>&1
+            $out/bin/zpool --help >/dev/null 2>&1
           '';
         postDeviceCommands = concatStringsSep "\n" ([''
             ZFS_FORCE="${optionalString cfgZfs.forceImportRoot "-f"}"
diff --git a/nixos/modules/tasks/kbd.nix b/nixos/modules/tasks/kbd.nix
index 03c42404e5d5..8d26998021d3 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 70158fc7252b..8223c5a4941e 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/tasks/trackpoint.nix b/nixos/modules/tasks/trackpoint.nix
index 5d1bb631b54f..778cdc5d30dd 100644
--- a/nixos/modules/tasks/trackpoint.nix
+++ b/nixos/modules/tasks/trackpoint.nix
@@ -16,7 +16,7 @@ with lib;
           Enable sensitivity and speed configuration for trackpoints.
         '';
       };
-  
+
       sensitivity = mkOption {
         default = 128;
         example = 255;
@@ -44,7 +44,7 @@ with lib;
           Enable scrolling while holding the middle mouse button.
         '';
       };
-      
+
     };
 
   };
@@ -70,7 +70,7 @@ with lib;
         ''
           Section "InputClass"
             Identifier "Trackpoint Wheel Emulation"
-            MatchProduct "TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB Trackpoint pointing device|Composite TouchPad / TrackPoint"
+            MatchProduct "Elantech PS/2 TrackPoint|TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB Trackpoint pointing device|Composite TouchPad / TrackPoint"
             MatchDevicePath "/dev/input/event*"
             Option "EmulateWheel" "true"
             Option "EmulateWheelButton" "2"
diff --git a/nixos/modules/virtualisation/amazon-config.nix b/nixos/modules/virtualisation/amazon-config.nix
index e816ed2d183a..a27e52a8e68c 100644
--- a/nixos/modules/virtualisation/amazon-config.nix
+++ b/nixos/modules/virtualisation/amazon-config.nix
@@ -1,5 +1,3 @@
-{ config, pkgs, modulesPath, ... }:
-
 {
-  imports = [ "${modulesPath}/virtualisation/amazon-image.nix" ];
+  imports = [ ./amazon-image.nix ];
 }
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index 0473c2454e22..600a29f31bc5 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -165,7 +165,7 @@ in
     boot.initrd.extraUtilsCommands =
       ''
         # We need swapon in the initrd.
-        cp --remove-destination ${pkgs.utillinux}/sbin/swapon $out/bin
+        copy_bin_and_libs ${pkgs.utillinux}/sbin/swapon
       '';
 
     # Don't put old configurations in the GRUB menu.  The user has no
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index c461cf8c00cb..da39dda85353 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 4d493b3896f2..ee5485071a35 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -7,6 +7,9 @@ in
 {
   imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ];
 
+  # https://cloud.google.com/compute/docs/tutorials/building-images
+  networking.firewall.enable = mkDefault false;
+
   system.build.googleComputeImage =
     pkgs.vmTools.runInLinuxVM (
       pkgs.runCommand "google-compute-image"
@@ -95,6 +98,7 @@ in
 
   boot.kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ];
   boot.initrd.kernelModules = [ "virtio_scsi" ];
+  boot.kernelModules = [ "virtio_pci" "virtio_net" ];
 
   # Generate a GRUB menu.  Amazon's pv-grub uses this to boot our kernel/initrd.
   boot.loader.grub.device = "/dev/sda";
@@ -108,6 +112,7 @@ in
   # at instance creation time.
   services.openssh.enable = true;
   services.openssh.permitRootLogin = "without-password";
+  services.openssh.passwordAuthentication = mkDefault false;
 
   # Force getting the hostname from Google Compute.
   networking.hostName = mkDefault "";
@@ -129,10 +134,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 +145,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 +161,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}
@@ -178,5 +183,79 @@ in
       serviceConfig.RemainAfterExit = true;
       serviceConfig.StandardError = "journal+console";
       serviceConfig.StandardOutput = "journal+console";
-     };
+    };
+
+  # Setings taken from https://cloud.google.com/compute/docs/tutorials/building-images#providedkernel
+  boot.kernel.sysctl = {
+    # enables syn flood protection
+    "net.ipv4.tcp_syncookies" = mkDefault "1";
+
+    # ignores source-routed packets
+    "net.ipv4.conf.all.accept_source_route" = mkDefault "0";
+
+    # ignores source-routed packets
+    "net.ipv4.conf.default.accept_source_route" = mkDefault "0";
+
+    # ignores ICMP redirects
+    "net.ipv4.conf.all.accept_redirects" = mkDefault "0";
+
+    # ignores ICMP redirects
+    "net.ipv4.conf.default.accept_redirects" = mkDefault "0";
+
+    # ignores ICMP redirects from non-GW hosts
+    "net.ipv4.conf.all.secure_redirects" = mkDefault "1";
+
+    # ignores ICMP redirects from non-GW hosts
+    "net.ipv4.conf.default.secure_redirects" = mkDefault "1";
+
+    # don't allow traffic between networks or act as a router
+    "net.ipv4.ip_forward" = mkDefault "0";
+
+    # don't allow traffic between networks or act as a router
+    "net.ipv4.conf.all.send_redirects" = mkDefault "0";
+
+    # don't allow traffic between networks or act as a router
+    "net.ipv4.conf.default.send_redirects" = mkDefault "0";
+
+    # reverse path filtering - IP spoofing protection
+    "net.ipv4.conf.all.rp_filter" = mkDefault "1";
+
+    # reverse path filtering - IP spoofing protection
+    "net.ipv4.conf.default.rp_filter" = mkDefault "1";
+
+    # ignores ICMP broadcasts to avoid participating in Smurf attacks
+    "net.ipv4.icmp_echo_ignore_broadcasts" = mkDefault "1";
+
+    # ignores bad ICMP errors
+    "net.ipv4.icmp_ignore_bogus_error_responses" = mkDefault "1";
+
+    # logs spoofed, source-routed, and redirect packets
+    "net.ipv4.conf.all.log_martians" = mkDefault "1";
+
+    # log spoofed, source-routed, and redirect packets
+    "net.ipv4.conf.default.log_martians" = mkDefault "1";
+
+    # implements RFC 1337 fix
+    "net.ipv4.tcp_rfc1337" = mkDefault "1";
+
+    # randomizes addresses of mmap base, heap, stack and VDSO page
+    "kernel.randomize_va_space" = mkDefault "2";
+
+    # provides protection from ToCToU races
+    "fs.protected_hardlinks" = mkDefault "1";
+
+    # provides protection from ToCToU races
+    "fs.protected_symlinks" = mkDefault "1";
+
+    # makes locating kernel addresses more difficult
+    "kernel.kptr_restrict" = mkDefault "1";
+
+    # set ptrace protections
+    "kernel.yama.ptrace_scope" = mkDefault "1";
+
+    # set perf only available to root
+    "kernel.perf_event_paranoid" = mkDefault "2";
+
+  };
+
 }
diff --git a/nixos/modules/virtualisation/lxc.nix b/nixos/modules/virtualisation/lxc.nix
index 10d3a6575fb9..22da012e4141 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 94edfb37948a..f1d9e64ee38f 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;
@@ -22,6 +23,7 @@ Usage: nixos-container list
        nixos-container start <container-name>
        nixos-container stop <container-name>
        nixos-container status <container-name>
+       nixos-container update <container-name> [--config <string>]
        nixos-container login <container-name>
        nixos-container root-login <container-name>
        nixos-container run <container-name> -- args...
@@ -271,14 +273,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/parallels-guest.nix b/nixos/modules/virtualisation/parallels-guest.nix
index 141e70974058..2f40283b3e1d 100644
--- a/nixos/modules/virtualisation/parallels-guest.nix
+++ b/nixos/modules/virtualisation/parallels-guest.nix
@@ -82,7 +82,7 @@ in
     systemd.services.prlshprint = {
       description = "Parallels Shared Printer Tool";
       wantedBy = [ "multi-user.target" ];
-      bindsTo = [ "cupsd.service" ];
+      bindsTo = [ "cups.service" ];
       serviceConfig = {
         Type = "forking";
         ExecStart = "${prl-tools}/bin/prlshprint";
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index a5a133dfa5dc..8c7e840910de 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -346,7 +346,7 @@ in
     boot.initrd.extraUtilsCommands =
       ''
         # We need mke2fs in the initrd.
-        cp -vf --remove-destination ${pkgs.e2fsprogs}/sbin/mke2fs $out/bin
+        copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/mke2fs
       '';
 
     boot.initrd.postDeviceCommands =
diff --git a/nixos/modules/virtualisation/xen-dom0.nix b/nixos/modules/virtualisation/xen-dom0.nix
index f3a24c5cf25b..ea9f61aad6a6 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,71 +130,36 @@ 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";
         }
       ];
 
@@ -174,6 +168,125 @@ in
 
     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 483589669345..2db3190ad139 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-combined.nix b/nixos/release-combined.nix
index 2381132bb45e..cb1c200ab475 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -31,7 +31,7 @@ in rec {
     nixpkgs = nixpkgsSrc;
   })) [ "unstable" ];
 
-  tested = pkgs.releaseTools.aggregate {
+  tested = pkgs.lib.hydraJob (pkgs.releaseTools.aggregate {
     name = "nixos-${nixos.channel.version}";
     meta = {
       description = "Release-critical builds for the NixOS channel";
@@ -57,6 +57,7 @@ in rec {
         (all nixos.tests.installer.simple)
         (all nixos.tests.installer.simpleLabels)
         (all nixos.tests.installer.simpleProvided)
+        (all nixos.tests.installer.swraid)
         (all nixos.tests.installer.btrfsSimple)
         (all nixos.tests.installer.btrfsSubvols)
         (all nixos.tests.installer.btrfsSubvolDefault)
@@ -85,6 +86,6 @@ in rec {
         nixpkgs.tarball
         (all nixpkgs.emacs)
       ];
-  };
+  });
 
 }
diff --git a/nixos/release-small.nix b/nixos/release-small.nix
index 7f53a101bdfc..11155c853696 100644
--- a/nixos/release-small.nix
+++ b/nixos/release-small.nix
@@ -79,7 +79,7 @@ in rec {
       vim;
   };
 
-  tested = pkgs.releaseTools.aggregate {
+  tested = lib.hydraJob (pkgs.releaseTools.aggregate {
     name = "nixos-${nixos.channel.version}";
     meta = {
       description = "Release-critical builds for the NixOS channel";
@@ -88,6 +88,6 @@ in rec {
     constituents =
       let all = x: map (system: x.${system}) supportedSystems; in
       [ nixpkgs.tarball ] ++ lib.collect lib.isDerivation nixos;
-  };
+  });
 
 }
diff --git a/nixos/release.nix b/nixos/release.nix
index 1bd3ec577318..375b65d040e6 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -3,22 +3,20 @@
 , supportedSystems ? [ "x86_64-linux" "i686-linux" ]
 }:
 
+with import ../lib;
+
 let
 
   version = builtins.readFile ../.version;
   versionSuffix =
     (if stableBranch then "." else "pre") + "${toString nixpkgs.revCount}.${nixpkgs.shortRev}";
 
-  forAllSystems = pkgs.lib.genAttrs supportedSystems;
-
-  scrubDrv = drv: let res = { inherit (drv) drvPath outPath type name system meta; outputName = "out"; out = res; }; in res;
+  forAllSystems = genAttrs supportedSystems;
 
-  callTest = fn: args: forAllSystems (system: scrubDrv (import fn ({ inherit system; } // args)));
+  callTest = fn: args: forAllSystems (system: hydraJob (import fn ({ inherit system; } // args)));
 
   pkgs = import nixpkgs { system = "x86_64-linux"; };
 
-  lib = pkgs.lib;
-
 
   versionModule =
     { system.nixosVersionSuffix = versionSuffix;
@@ -42,10 +40,10 @@ let
 
     in
       # Declare the ISO as a build product so that it shows up in Hydra.
-      scrubDrv (runCommand "nixos-iso-${config.system.nixosVersion}"
+      hydraJob (runCommand "nixos-iso-${config.system.nixosVersion}"
         { meta = {
             description = "NixOS installation CD (${description}) - ISO image for ${system}";
-            maintainers = map (x: lib.getAttr x lib.maintainers) maintainers;
+            maintainers = map (x: lib.maintainers.${x}) maintainers;
           };
           inherit iso;
           passthru = { inherit config; };
@@ -74,7 +72,7 @@ let
       tarball //
         { meta = {
             description = "NixOS system tarball for ${system} - ${stdenv.platform.name}";
-            maintainers = map (x: lib.getAttr x lib.maintainers) maintainers;
+            maintainers = map (x: lib.maintainers.${x}) maintainers;
           };
           inherit config;
         };
@@ -83,12 +81,12 @@ let
   makeClosure = module: buildFromConfig module (config: config.system.build.toplevel);
 
 
-  buildFromConfig = module: sel: forAllSystems (system: scrubDrv (sel (import ./lib/eval-config.nix {
+  buildFromConfig = module: sel: forAllSystems (system: hydraJob (sel (import ./lib/eval-config.nix {
     inherit system;
-    modules = [ module versionModule ] ++ lib.singleton
+    modules = [ module versionModule ] ++ singleton
       ({ config, lib, ... }:
-      { fileSystems."/".device  = lib.mkDefault "/dev/sda1";
-        boot.loader.grub.device = lib.mkDefault "/dev/sda";
+      { fileSystems."/".device  = mkDefault "/dev/sda1";
+        boot.loader.grub.device = mkDefault "/dev/sda";
       });
   }).config));
 
@@ -175,10 +173,10 @@ in rec {
 
     in
       # Declare the OVA as a build product so that it shows up in Hydra.
-      scrubDrv (runCommand "nixos-ova-${config.system.nixosVersion}-${system}"
+      hydraJob (runCommand "nixos-ova-${config.system.nixosVersion}-${system}"
         { meta = {
             description = "NixOS VirtualBox appliance (${system})";
-            maintainers = lib.maintainers.eelco;
+            maintainers = maintainers.eelco;
           };
           ova = config.system.build.virtualBoxOVA;
         }
@@ -195,9 +193,9 @@ in rec {
   dummy = forAllSystems (system: pkgs.runCommand "dummy"
     { toplevel = (import lib/eval-config.nix {
         inherit system;
-        modules = lib.singleton ({ config, pkgs, ... }:
-          { fileSystems."/".device  = lib.mkDefault "/dev/sda1";
-            boot.loader.grub.device = lib.mkDefault "/dev/sda";
+        modules = singleton ({ config, pkgs, ... }:
+          { fileSystems."/".device  = mkDefault "/dev/sda1";
+            boot.loader.grub.device = mkDefault "/dev/sda";
           });
       }).config.system.build.toplevel;
     }
@@ -242,33 +240,35 @@ in rec {
   tests.avahi = callTest tests/avahi.nix {};
   tests.bittorrent = callTest tests/bittorrent.nix {};
   tests.blivet = callTest tests/blivet.nix {};
-  tests.cadvisor = scrubDrv (import tests/cadvisor.nix { system = "x86_64-linux"; });
+  tests.cadvisor = hydraJob (import tests/cadvisor.nix { system = "x86_64-linux"; });
   tests.chromium = callTest tests/chromium.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"; });
-  tests.etcd = scrubDrv (import tests/etcd.nix { system = "x86_64-linux"; });
+  tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; });
+  tests.dockerRegistry = hydraJob (import tests/docker-registry.nix { system = "x86_64-linux"; });
+  tests.etcd = hydraJob (import tests/etcd.nix { system = "x86_64-linux"; });
   tests.firefox = callTest tests/firefox.nix {};
   tests.firewall = callTest tests/firewall.nix {};
-  tests.fleet = scrubDrv (import tests/fleet.nix { system = "x86_64-linux"; });
+  tests.fleet = hydraJob (import tests/fleet.nix { system = "x86_64-linux"; });
   #tests.gitlab = callTest tests/gitlab.nix {};
   tests.gnome3 = callTest tests/gnome3.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);
-  tests.installer.separateBoot = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).separateBoot.test);
-  tests.installer.simple = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).simple.test);
-  tests.installer.simpleLabels = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).simpleLabels.test);
-  tests.installer.simpleProvided = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).simpleProvided.test);
-  tests.installer.btrfsSimple = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).btrfsSimple.test);
-  tests.installer.btrfsSubvols = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).btrfsSubvols.test);
-  tests.installer.btrfsSubvolDefault = forAllSystems (system: scrubDrv (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test);
+  tests.i3wm = callTest tests/i3wm.nix {};
+  tests.installer.grub1 = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).grub1.test);
+  tests.installer.lvm = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).lvm.test);
+  tests.installer.rebuildCD = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).rebuildCD.test);
+  tests.installer.separateBoot = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).separateBoot.test);
+  tests.installer.simple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simple.test);
+  tests.installer.simpleLabels = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleLabels.test);
+  tests.installer.simpleProvided = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).simpleProvided.test);
+  tests.installer.swraid = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).swraid.test);
+  tests.installer.btrfsSimple = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSimple.test);
+  tests.installer.btrfsSubvols = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSubvols.test);
+  tests.installer.btrfsSubvolDefault = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test);
   tests.influxdb = callTest tests/influxdb.nix {};
   tests.ipv6 = callTest tests/ipv6.nix {};
   tests.jenkins = callTest tests/jenkins.nix {};
   tests.kde4 = callTest tests/kde4.nix {};
-  tests.kubernetes = scrubDrv (import tests/kubernetes.nix { system = "x86_64-linux"; });
+  tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; });
   tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; };
   tests.login = callTest tests/login.nix {};
   #tests.logstash = callTest tests/logstash.nix {};
@@ -298,9 +298,10 @@ in rec {
   # TODO: put in networking.nix after the test becomes more complete
   tests.networkingProxy = callTest tests/networking-proxy.nix {};
   tests.nfs3 = callTest tests/nfs.nix { version = 3; };
+  tests.nfs4 = callTest tests/nfs.nix { version = 4; };
   tests.nsd = callTest tests/nsd.nix {};
   tests.openssh = callTest tests/openssh.nix {};
-  tests.panamax = scrubDrv (import tests/panamax.nix { system = "x86_64-linux"; });
+  tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
   tests.peerflix = callTest tests/peerflix.nix {};
   tests.printing = callTest tests/printing.nix {};
   tests.proxy = callTest tests/proxy.nix {};
@@ -309,8 +310,12 @@ in rec {
   tests.simple = callTest tests/simple.nix {};
   tests.tomcat = callTest tests/tomcat.nix {};
   tests.udisks2 = callTest tests/udisks2.nix {};
-  tests.virtualbox = callTest tests/virtualbox.nix {};
+  tests.virtualbox = hydraJob (import tests/virtualbox.nix { system = "x86_64-linux"; });
   tests.xfce = callTest tests/xfce.nix {};
+  tests.bootBiosCdrom = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootBiosCdrom);
+  tests.bootBiosUsb = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootBiosUsb);
+  tests.bootUefiCdrom = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootUefiCdrom);
+  tests.bootUefiUsb = forAllSystems (system: hydraJob (import tests/boot.nix { inherit system; }).bootUefiUsb);
 
 
   /* Build a bunch of typical closures so that Hydra can keep track of
diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix
new file mode 100644
index 000000000000..2fdbb0c00b85
--- /dev/null
+++ b/nixos/tests/boot.nix
@@ -0,0 +1,63 @@
+{ system ? builtins.currentSystem }:
+
+with import ../lib/testing.nix { inherit system; };
+with import ../lib/qemu-flags.nix;
+with pkgs.lib;
+
+let
+
+  iso =
+    (import ../lib/eval-config.nix {
+      inherit system;
+      modules =
+        [ ../modules/installer/cd-dvd/installation-cd-minimal.nix
+          ../modules/testing/test-instrumentation.nix
+          { key = "serial";
+            boot.loader.grub.timeout = mkOverride 0 0;
+
+            # The test cannot access the network, so any sources we
+            # need must be included in the ISO.
+            isoImage.storeContents =
+              [ pkgs.glibcLocales
+                pkgs.sudo
+                pkgs.docbook5
+                pkgs.docbook5_xsl
+                pkgs.grub
+                pkgs.perlPackages.XMLLibXML
+                pkgs.unionfs-fuse
+                pkgs.gummiboot
+              ];
+          }
+        ];
+    }).config.system.build.isoImage;
+
+  makeBootTest = name: machineConfig:
+    makeTest {
+      inherit iso;
+      name = "boot-" + name;
+      nodes = { };
+      testScript =
+        ''
+          my $machine = createMachine({ ${machineConfig}, qemuFlags => '-m 768' });
+          $machine->start;
+          $machine->waitForUnit("multi-user.target");
+          $machine->shutdown;
+        '';
+    };
+in {
+    bootBiosCdrom = makeBootTest "bios-cdrom" ''
+        cdrom => glob("${iso}/iso/*.iso")
+      '';
+    bootBiosUsb = makeBootTest "bios-usb" ''
+        usb => glob("${iso}/iso/*.iso")
+      '';
+    bootUefiCdrom = makeBootTest "uefi-cdrom" ''
+        cdrom => glob("${iso}/iso/*.iso"),
+        bios => '${pkgs.OVMF}/FV/OVMF.fd'
+      '';
+    bootUefiUsb = makeBootTest "uefi-usb" ''
+        usb => glob("${iso}/iso/*.iso"),
+        bios => '${pkgs.OVMF}/FV/OVMF.fd'
+      '';
+  }
+
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
index 368d0e43c465..026433fc7ee9 100644
--- a/nixos/tests/chromium.nix
+++ b/nixos/tests/chromium.nix
@@ -109,7 +109,12 @@ import ./make-test.nix (
       $machine->waitUntilSucceeds("${xdo "check-startup" ''
         search --sync --onlyvisible --name "startup done"
         # close first start help popup
-        key Escape
+        key -delay 1000 Escape
+        # XXX: This is to make sure the popup is closed, but we better do
+        # screenshots to detect visual changes.
+        key -delay 2000 Escape
+        key -delay 3000 Escape
+        key -delay 4000 Escape
         windowfocus --sync
         windowactivate --sync
       ''}");
diff --git a/nixos/tests/cjdns.nix b/nixos/tests/cjdns.nix
index 7bb3863c683f..45164234b1bd 100644
--- a/nixos/tests/cjdns.nix
+++ b/nixos/tests/cjdns.nix
@@ -3,15 +3,15 @@ let
   carolPubKey = "n932l3pjvmhtxxcdrqq2qpw5zc58f01vvjx01h4dtd1bb0nnu2h0.k";
   carolPassword = "678287829ce4c67bc8b227e56d94422ee1b85fa11618157b2f591de6c6322b52";
   carolIp4 = "192.168.0.9";
-  
+
   basicConfig =
     { config, pkgs, ... }:
     { services.cjdns.enable = true;
-    
+
       # Turning off DHCP isn't very realistic but makes
       # the sequence of address assignment less stochastic.
       networking.useDHCP = false;
-      
+
       networking.interfaces.eth1.prefixLength = 24;
       # CJDNS output is incompatible with the XML log.
       systemd.services.cjdns.serviceConfig.StandardOutput = "null";
@@ -41,19 +41,18 @@ import ./make-test.nix {
       # Bob explicitly connects to Carol over UDPInterface.
       bob =
         { config, lib, nodes, ... }:
-        
+
         let carolIp4 = lib.mkForce nodes.carol.config.networking.interfaces.eth1; in
-        
+
           { imports = [ basicConfig ];
-          
+
           networking.interfaces.eth1.ipAddress = "192.168.0.2";
-          
+
           services.cjdns =
             { UDPInterface =
                 { bind = "0.0.0.0:1024";
                   connectTo."192.168.0.1:1024}" =
-                    { hostname = "carol.hype";
-                      password = carolPassword;
+                    { password = carolPassword;
                       publicKey = carolPubKey;
                     };
                 };
@@ -75,7 +74,7 @@ import ./make-test.nix {
           '';
 
           networking.interfaces.eth1.ipAddress = "192.168.0.1";
-                    
+
           services.cjdns =
             { authorizedPasswords = [ carolPassword ];
               ETHInterface.bind = "eth1";
@@ -106,13 +105,13 @@ import ./make-test.nix {
       my $carolIp6 = cjdnsIp $carol;
 
       # ping a few times each to let the routing table establish itself
-      
+
       $alice->succeed("ping6 -c 4 $carolIp6");
-      $bob->succeed("ping6 -c 4 carol.hype");
+      $bob->succeed("ping6 -c 4 $carolIp6");
 
       $carol->succeed("ping6 -c 4 $aliceIp6");
       $carol->succeed("ping6 -c 4 $bobIp6");
-      
+
       $alice->succeed("ping6 -c 4 $bobIp6");
       $bob->succeed("ping6 -c 4 $aliceIp6");
 
diff --git a/nixos/tests/i3wm.nix b/nixos/tests/i3wm.nix
new file mode 100644
index 000000000000..0966dba8a3c8
--- /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");
+  '';
+}
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index c7815bde3f5c..af87705b9279 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -327,12 +327,12 @@ in {
           $machine->succeed(
               "parted /dev/vda --"
               . " mklabel msdos"
-              . " mkpart primary ext2 1M 30MB" # /boot
-              . " mkpart extended 30M -1s"
-              . " mkpart logical 31M 1531M" # md0 (root), first device
-              . " mkpart logical 1540M 3040M" # md0 (root), second device
-              . " mkpart logical 3050M 3306M" # md1 (swap), first device
-              . " mkpart logical 3320M 3576M", # md1 (swap), second device
+              . " mkpart primary ext2 1M 100MB" # /boot
+              . " mkpart extended 100M -1s"
+              . " mkpart logical 102M 1602M" # md0 (root), first device
+              . " mkpart logical 1603M 3103M" # md0 (root), second device
+              . " mkpart logical 3104M 3360M" # md1 (swap), first device
+              . " mkpart logical 3361M 3617M", # md1 (swap), second device
               "udevadm settle",
               "ls -l /dev/vda* >&2",
               "cat /proc/partitions >&2",
diff --git a/nixos/tests/kubernetes.nix b/nixos/tests/kubernetes.nix
index 8bc7c8d618ad..0a9eda930bad 100644
--- a/nixos/tests/kubernetes.nix
+++ b/nixos/tests/kubernetes.nix
@@ -13,7 +13,7 @@ import ./make-test.nix rec {
           id: redis-master-pod
           containers:
             - name: master
-              image: master:5000/scratch
+              image: master:5000/nix
               cpu: 100
               ports:
                 - name: redis-server
@@ -50,8 +50,8 @@ import ./make-test.nix rec {
           virtualisation.memorySize = 768;
           services.kubernetes = {
             roles = ["master" "node"];
+            dockerCfg = ''{"master:5000":{}}'';
             controllerManager.machines = ["master" "node"];
-            kubelet.extraOpts = "-network_container_image=master:5000/pause";
             apiserver.address = "0.0.0.0";
             verbose = true;
           };
@@ -94,7 +94,8 @@ import ./make-test.nix rec {
         {
           services.kubernetes = {
             roles = ["node"];
-            kubelet.extraOpts = "-network_container_image=master:5000/pause";
+            dockerCfg = ''{"master:5000":{}}'';
+            kubelet.apiServers = ["master:8080"];
             verbose = true;
           };
           virtualisation.docker.extraOptions = "--iptables=false --ip-masq=false -b cbr0 --insecure-registry master:5000";
@@ -155,14 +156,14 @@ import ./make-test.nix rec {
     $node->waitForUnit("kubernetes-kubelet.service");
     $node->waitForUnit("kubernetes-proxy.service");
 
-    $master->waitUntilSucceeds("kubecfg list minions | grep master");
-    $master->waitUntilSucceeds("kubecfg list minions | grep node");
+    $master->waitUntilSucceeds("kubectl get minions | grep master");
+    $master->waitUntilSucceeds("kubectl get minions | grep node");
 
     $client->waitForUnit("docker.service");
-    $client->succeed("tar cv --files-from /dev/null | docker import - scratch");
-    $client->succeed("docker tag scratch master:5000/scratch");
+    $client->succeed("tar cv --files-from /dev/null | docker import - nix");
+    $client->succeed("docker tag nix master:5000/nix");
     $master->waitForUnit("docker-registry.service");
-    $client->succeed("docker push master:5000/scratch");
+    $client->succeed("docker push master:5000/nix");
     $client->succeed("mkdir -p /root/pause");
     $client->succeed("cp /etc/test/pause /root/pause/");
     $client->succeed("cp /etc/test/Dockerfile /root/pause/");
diff --git a/nixos/tests/misc.nix b/nixos/tests/misc.nix
index e1830d95b41f..b44af5316bea 100644
--- a/nixos/tests/misc.nix
+++ b/nixos/tests/misc.nix
@@ -102,6 +102,10 @@ import ./make-test.nix {
       subtest "shell-vars", sub {
           $machine->succeed('[ -n "$NIX_PATH" ]');
       };
+
+      subtest "nix-db", sub {
+          $machine->succeed("nix-store -qR /run/current-system | grep nixos-");
+      };
     '';
 
 }
diff --git a/nixos/tests/nfs.nix b/nixos/tests/nfs.nix
index 5ed805a16952..216fea7784a7 100644
--- a/nixos/tests/nfs.nix
+++ b/nixos/tests/nfs.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ version, ... }:
+import ./make-test.nix ({ version ? 4, ... }:
 
 let
 
diff --git a/nixos/tests/printing.nix b/nixos/tests/printing.nix
index 3e5ee680c7a6..ba10f23582d7 100644
--- a/nixos/tests/printing.nix
+++ b/nixos/tests/printing.nix
@@ -31,8 +31,8 @@ import ./make-test.nix ({pkgs, ... }: {
       startAll;
 
       # Make sure that cups is up on both sides.
-      $server->waitForUnit("cupsd.service");
-      $client->waitForUnit("cupsd.service");
+      $server->waitForUnit("cups.service");
+      $client->waitForUnit("cups.service");
       $client->succeed("lpstat -r") =~ /scheduler is running/ or die;
       $client->succeed("lpstat -H") =~ "/var/run/cups/cups.sock" or die;
       $client->succeed("curl --fail http://localhost:631/");
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index b2b1ec877798..827481879a3e 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -39,9 +39,8 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
     ];
 
     boot.initrd.extraUtilsCommands = ''
-      cp -av -t "$out/bin/" \
-        "${pkgs.linuxPackages.virtualboxGuestAdditions}/sbin/mount.vboxsf" \
-        "${pkgs.utillinux}/bin/unshare"
+      copy_bin_and_libs "${pkgs.linuxPackages.virtualboxGuestAdditions}/sbin/mount.vboxsf"
+      copy_bin_and_libs "${pkgs.utillinux}/bin/unshare"
       ${(attrs.extraUtilsCommands or (const "")) pkgs}
     '';
 
@@ -245,6 +244,7 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
         for (my $i = 0; $i <= 120; $i += 10) {
           $machine->sleep(10);
           return if checkRunning_${name};
+          eval { $_[0]->() } if defined $_[0];
         }
         die "VirtualBox VM didn't start up within 2 minutes";
       }
@@ -336,7 +336,9 @@ in {
       $machine->screenshot("gui_manager_started");
       $machine->sendKeys("ret");
       $machine->screenshot("gui_manager_sent_startup");
-      waitForStartup_simple;
+      waitForStartup_simple (sub {
+        $machine->sendKeys("ret");
+      });
       $machine->screenshot("gui_started");
       waitForVMBoot_simple;
       $machine->screenshot("gui_booted");