summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorCharles Strahan <charles.c.strahan@gmail.com>2014-12-28 14:29:52 -0500
committerCharles Strahan <charles.c.strahan@gmail.com>2014-12-28 14:29:52 -0500
commit145733c479f5e17ef8c8efdd61001fd62940f8a5 (patch)
tree5c231051071eb0661ba6903db086910a4c6aa32d /nixos
parent4ed847d81d1e10da91d5f8bae2f92e7af32dbe80 (diff)
parenta30869a525bd05cefb73bd731db6b9ed12e56c6c (diff)
downloadnixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.tar
nixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.tar.gz
nixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.tar.bz2
nixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.tar.lz
nixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.tar.xz
nixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.tar.zst
nixlib-145733c479f5e17ef8c8efdd61001fd62940f8a5.zip
Merge branch 'master' of github.com:nixos/nixpkgs into pleasant-ruby
Conflicts:
	pkgs/applications/version-management/redmine/default.nix
	pkgs/development/interpreters/ruby/gem.nix
	pkgs/development/interpreters/ruby/generated.nix
	pkgs/development/interpreters/ruby/patches.nix
	pkgs/development/tools/vagrant/default.nix
	pkgs/servers/consul/default.nix
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/administration/network-problems.xml8
-rw-r--r--nixos/doc/manual/configuration/linux-kernel.xml2
-rw-r--r--nixos/doc/manual/configuration/network-manager.xml2
-rw-r--r--nixos/doc/manual/default.nix50
-rw-r--r--nixos/doc/manual/development/running-nixos-tests.xml32
-rw-r--r--nixos/doc/manual/development/sources.xml20
-rw-r--r--nixos/doc/manual/installation/installing.xml19
-rw-r--r--nixos/doc/manual/installation/obtaining.xml11
-rw-r--r--nixos/doc/manual/installation/upgrading.xml14
-rw-r--r--nixos/doc/manual/release-notes/release-notes.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1411.xml22
-rw-r--r--nixos/doc/manual/release-notes/rl-1412.xml167
-rw-r--r--nixos/lib/eval-config.nix9
-rw-r--r--nixos/lib/make-system-tarball.nix5
-rw-r--r--nixos/lib/make-system-tarball.sh4
-rw-r--r--nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix3
-rwxr-xr-xnixos/maintainers/scripts/ec2/create-ebs-amis.py92
-rw-r--r--nixos/modules/config/fonts/fontconfig-ultimate.nix193
-rw-r--r--nixos/modules/config/fonts/fontconfig.nix261
-rw-r--r--nixos/modules/config/fonts/fonts.nix10
-rw-r--r--nixos/modules/config/networking.nix119
-rw-r--r--nixos/modules/config/no-x-libs.nix2
-rw-r--r--nixos/modules/config/nsswitch.nix44
-rw-r--r--nixos/modules/config/timezone.nix8
-rw-r--r--nixos/modules/config/update-users-groups.pl51
-rw-r--r--nixos/modules/config/users-groups.nix78
-rw-r--r--nixos/modules/hardware/all-firmware.nix9
-rw-r--r--nixos/modules/hardware/opengl.nix1
-rw-r--r--nixos/modules/hardware/video/bumblebee.nix2
-rw-r--r--nixos/modules/hardware/video/nvidia.nix5
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix5
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix5
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix1
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt2
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl9
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh11
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh123
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh2
-rw-r--r--nixos/modules/misc/ids.nix30
-rw-r--r--nixos/modules/misc/version.nix2
-rwxr-xr-xnixos/modules/module-list.nix30
-rw-r--r--nixos/modules/profiles/base.nix1
-rw-r--r--nixos/modules/profiles/container.nix56
-rw-r--r--nixos/modules/programs/environment.nix1
-rw-r--r--nixos/modules/programs/light.nix26
-rw-r--r--nixos/modules/programs/ssh.nix14
-rw-r--r--nixos/modules/programs/ssmtp.nix17
-rw-r--r--nixos/modules/programs/virtualbox-host.nix115
-rw-r--r--nixos/modules/programs/virtualbox.nix54
-rw-r--r--nixos/modules/rename.nix8
-rw-r--r--nixos/modules/security/ca.nix1
-rw-r--r--nixos/modules/security/grsecurity.nix4
-rw-r--r--nixos/modules/security/sudo.nix17
-rw-r--r--nixos/modules/services/audio/liquidsoap.nix74
-rw-r--r--nixos/modules/services/audio/mpd.nix4
-rw-r--r--nixos/modules/services/backup/almir.nix1
-rw-r--r--nixos/modules/services/backup/crashplan.nix63
-rw-r--r--nixos/modules/services/backup/rsnapshot.nix11
-rw-r--r--nixos/modules/services/cluster/fleet.nix150
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix462
-rw-r--r--nixos/modules/services/databases/4store-endpoint.nix3
-rw-r--r--nixos/modules/services/databases/4store.nix2
-rw-r--r--nixos/modules/services/databases/hbase.nix133
-rw-r--r--nixos/modules/services/databases/opentsdb.nix100
-rw-r--r--nixos/modules/services/databases/virtuoso.nix2
-rw-r--r--nixos/modules/services/desktops/gnome3/gvfs.nix4
-rw-r--r--nixos/modules/services/desktops/profile-sync-daemon.nix139
-rw-r--r--nixos/modules/services/hardware/80-net-setup-link.rules (renamed from nixos/modules/services/hardware/80-net-name-slot.rules)0
-rw-r--r--nixos/modules/services/hardware/thermald.nix2
-rw-r--r--nixos/modules/services/hardware/udev.nix3
-rw-r--r--nixos/modules/services/logging/logstash.nix14
-rw-r--r--nixos/modules/services/logging/syslog-ng.nix18
-rw-r--r--nixos/modules/services/misc/autofs.nix2
-rw-r--r--nixos/modules/services/misc/defaultUnicornConfig.rb206
-rw-r--r--nixos/modules/services/misc/docker-registry.nix82
-rw-r--r--nixos/modules/services/misc/etcd.nix144
-rw-r--r--nixos/modules/services/misc/gitlab.nix295
-rw-r--r--nixos/modules/services/misc/gitolite.nix27
-rw-r--r--nixos/modules/services/misc/mesos-master.nix21
-rw-r--r--nixos/modules/services/misc/mesos-slave.nix73
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix38
-rw-r--r--nixos/modules/services/misc/synergy.nix41
-rw-r--r--[-rwxr-xr-x]nixos/modules/services/misc/zookeeper.nix0
-rw-r--r--nixos/modules/services/monitoring/bosun.nix136
-rw-r--r--nixos/modules/services/monitoring/graphite.nix20
-rw-r--r--nixos/modules/services/monitoring/munin.nix4
-rw-r--r--nixos/modules/services/monitoring/riemann.nix16
-rw-r--r--nixos/modules/services/monitoring/scollector.nix114
-rw-r--r--nixos/modules/services/monitoring/zabbix-server.nix13
-rw-r--r--nixos/modules/services/network-filesystems/nfsd.nix8
-rw-r--r--nixos/modules/services/network-filesystems/rsyncd.nix133
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix27
-rw-r--r--nixos/modules/services/networking/chrony.nix11
-rw-r--r--nixos/modules/services/networking/cjdns.nix48
-rw-r--r--nixos/modules/services/networking/consul.nix50
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix20
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix134
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix2
-rw-r--r--nixos/modules/services/networking/firewall.nix15
-rw-r--r--nixos/modules/services/networking/git-daemon.nix32
-rw-r--r--nixos/modules/services/networking/gogoclient.nix3
-rw-r--r--nixos/modules/services/networking/i2pd.nix198
-rw-r--r--nixos/modules/services/networking/minidlna.nix2
-rw-r--r--nixos/modules/services/networking/nat.nix6
-rw-r--r--nixos/modules/services/networking/networkmanager.nix7
-rw-r--r--nixos/modules/services/networking/ntpd.nix28
-rw-r--r--nixos/modules/services/networking/openntpd.nix3
-rw-r--r--nixos/modules/services/networking/quassel.nix20
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix21
-rw-r--r--nixos/modules/services/networking/strongswan.nix133
-rw-r--r--nixos/modules/services/networking/tcpcrypt.nix2
-rw-r--r--nixos/modules/services/networking/tox-bootstrapd.nix80
-rw-r--r--nixos/modules/services/networking/unifi.nix44
-rw-r--r--nixos/modules/services/printing/cupsd.nix85
-rw-r--r--nixos/modules/services/scheduling/chronos.nix54
-rw-r--r--nixos/modules/services/scheduling/cron.nix9
-rw-r--r--nixos/modules/services/security/haveged.nix4
-rw-r--r--nixos/modules/services/security/tor.nix420
-rw-r--r--nixos/modules/services/security/torify.nix20
-rw-r--r--nixos/modules/services/security/torsocks.nix118
-rw-r--r--nixos/modules/services/system/cloud-init.nix152
-rw-r--r--nixos/modules/services/system/nscd.nix2
-rw-r--r--nixos/modules/services/torrent/peerflix.nix63
-rw-r--r--nixos/modules/services/torrent/transmission.nix2
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix16
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/mediawiki.nix17
-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/e17.nix30
-rw-r--r--nixos/modules/services/x11/desktop-managers/e18.nix43
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix1
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix24
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix2
-rw-r--r--nixos/modules/services/x11/hardware/synaptics.nix23
-rw-r--r--nixos/modules/services/x11/window-managers/awesome.nix31
-rw-r--r--nixos/modules/services/x11/xserver.nix2
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl8
-rw-r--r--nixos/modules/system/activation/top-level.nix4
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl3
-rw-r--r--nixos/modules/system/boot/loader/grub/ipxe.nix64
-rw-r--r--nixos/modules/system/boot/luksroot.nix2
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh16
-rw-r--r--nixos/modules/system/boot/stage-1.nix45
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh2
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix537
-rw-r--r--nixos/modules/system/boot/systemd.nix270
-rw-r--r--nixos/modules/tasks/bcache.nix11
-rw-r--r--nixos/modules/tasks/filesystems/nfs.nix20
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix220
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix348
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix176
-rw-r--r--nixos/modules/tasks/network-interfaces.nix527
-rw-r--r--nixos/modules/tasks/swraid.nix4
-rw-r--r--nixos/modules/testing/test-instrumentation.nix2
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix5
-rw-r--r--nixos/modules/virtualisation/containers.nix7
-rw-r--r--nixos/modules/virtualisation/docker-image.nix64
-rw-r--r--nixos/modules/virtualisation/docker.nix12
-rw-r--r--nixos/modules/virtualisation/lxc-container.nix26
-rw-r--r--nixos/modules/virtualisation/lxc.nix75
-rw-r--r--nixos/modules/virtualisation/parallels-guest.nix93
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix34
-rw-r--r--nixos/modules/virtualisation/virtualbox-guest.nix4
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix2
-rw-r--r--nixos/release-combined.nix9
-rw-r--r--nixos/release-small.nix1
-rw-r--r--nixos/release.nix35
-rw-r--r--nixos/tests/bittorrent.nix2
-rw-r--r--nixos/tests/blivet.nix12
-rw-r--r--nixos/tests/chromium.nix164
-rw-r--r--nixos/tests/cjdns.nix123
-rw-r--r--nixos/tests/containers.nix9
-rw-r--r--nixos/tests/docker-registry.nix40
-rw-r--r--nixos/tests/docker.nix24
-rw-r--r--nixos/tests/etcd.nix108
-rw-r--r--nixos/tests/fleet.nix73
-rw-r--r--nixos/tests/gitlab.nix21
-rw-r--r--nixos/tests/gnome3.nix2
-rw-r--r--nixos/tests/gnome3_12.nix31
-rw-r--r--nixos/tests/installer.nix15
-rw-r--r--nixos/tests/kde4.nix5
-rw-r--r--nixos/tests/kubernetes.nix178
-rw-r--r--nixos/tests/mesos.nix29
-rw-r--r--nixos/tests/networking-proxy.nix109
-rw-r--r--nixos/tests/networking.nix381
-rw-r--r--nixos/tests/nfs.nix3
-rw-r--r--nixos/tests/peerflix.nix21
-rw-r--r--nixos/tests/printing.nix13
-rw-r--r--nixos/tests/proxy.nix7
-rw-r--r--nixos/tests/quake3.nix4
-rw-r--r--nixos/tests/run-in-machine.nix8
-rw-r--r--nixos/tests/virtualbox.nix401
195 files changed, 9124 insertions, 1647 deletions
diff --git a/nixos/doc/manual/administration/network-problems.xml b/nixos/doc/manual/administration/network-problems.xml
index 5ba1bfd5ac9a..3af9cc59742f 100644
--- a/nixos/doc/manual/administration/network-problems.xml
+++ b/nixos/doc/manual/administration/network-problems.xml
@@ -12,9 +12,9 @@ pre-built binary.  That is, whenever a command like
 <command>nixos-rebuild</command> needs a path in the Nix store, Nix
 will try to download that path from the Internet rather than build it
 from source.  The default binary cache is
-<uri>http://cache.nixos.org/</uri>.  If this cache is unreachable, Nix
-operations may take a long time due to HTTP connection timeouts.  You
-can disable the use of the binary cache by adding <option>--option
+<uri>https://cache.nixos.org/</uri>.  If this cache is unreachable,
+Nix operations may take a long time due to HTTP connection timeouts.
+You can disable the use of the binary cache by adding <option>--option
 use-binary-caches false</option>, e.g.
 
 <screen>
@@ -30,4 +30,4 @@ $ nixos-rebuild switch --option binary-caches http://my-cache.example.org/
 
 </para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/nixos/doc/manual/configuration/linux-kernel.xml b/nixos/doc/manual/configuration/linux-kernel.xml
index 8fe2f5255df3..ffd7b354efe1 100644
--- a/nixos/doc/manual/configuration/linux-kernel.xml
+++ b/nixos/doc/manual/configuration/linux-kernel.xml
@@ -56,7 +56,7 @@ root file system), you can use
 boot.initrd.extraKernelModules = [ "cifs" ];
 </programlisting>
 This causes the specified modules and their dependencies to be added
-to the initial ramdark.</para>
+to the initial ramdisk.</para>
 
 <para>Kernel runtime parameters can be set through
 <option>boot.kernel.sysctl</option>, e.g.
diff --git a/nixos/doc/manual/configuration/network-manager.xml b/nixos/doc/manual/configuration/network-manager.xml
index e65060021b40..ceac40b7a1f6 100644
--- a/nixos/doc/manual/configuration/network-manager.xml
+++ b/nixos/doc/manual/configuration/network-manager.xml
@@ -13,7 +13,7 @@ use NetworkManager. You can enable NetworkManager by setting:
 services.networkmanager.enable = true;
 </programlisting>
 
-Some desktop managers (e.g., GNOME) enable NetworkManager
+some desktop managers (e.g., GNOME) enable NetworkManager
 automatically for you.</para>
 
 <para>All users that should have permission to change network settings
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 68248081af6a..b0a755c6a6fc 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -30,34 +30,13 @@ let
     else
       fn;
 
-  # Convert the list of options into an XML file and a JSON file.  The builtin
-  # unsafeDiscardStringContext is used to prevent the realisation of the store
-  # paths which are used in options definitions.
+  # Convert the list of options into an XML file.  The builtin
+  # unsafeDiscardStringContext is used to prevent the realisation of
+  # the store paths which are used in options definitions.
   optionsXML = builtins.toFile "options.xml" (builtins.unsafeDiscardStringContext (builtins.toXML optionsList'));
-  optionsJSON = builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON optionsList'));
-
-  # Tools-friendly version of the list of NixOS options.
-  options' = stdenv.mkDerivation {
-    name = "options";
-
-    buildCommand = ''
-      # Export list of options in different format.
-      dst=$out/share/doc/nixos
-      mkdir -p $dst
-
-      cp ${optionsJSON} $dst/options.json
-      cp ${optionsXML} $dst/options.xml
-
-      mkdir -p $out/nix-support
-      echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
-      echo "file xml $dst/options.xml" >> $out/nix-support/hydra-build-products
-    ''; # */
-
-    meta.description = "List of NixOS options in various formats.";
-  };
 
   optionsDocBook = runCommand "options-db.xml" {} ''
-    optionsXML=${options'}/share/doc/nixos/options.xml
+    optionsXML=${optionsXML}
     if grep /nixpkgs/nixos/modules $optionsXML; then
       echo "The manual appears to depend on the location of Nixpkgs, which is bad"
       echo "since this prevents sharing via the NixOS channel.  This is typically"
@@ -83,8 +62,25 @@ let
 
 in rec {
 
-  # Tools-friendly version of the list of NixOS options.
-  options = options';
+  # The NixOS options in JSON format.
+  optionsJSON = stdenv.mkDerivation {
+    name = "options-json";
+
+    buildCommand = ''
+      # Export list of options in different format.
+      dst=$out/share/doc/nixos
+      mkdir -p $dst
+
+      cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
+        (listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList'))))
+      } $dst/options.json
+
+      mkdir -p $out/nix-support
+      echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
+    ''; # */
+
+    meta.description = "List of NixOS options in JSON format";
+  };
 
   # Generate the NixOS manual.
   manual = stdenv.mkDerivation {
diff --git a/nixos/doc/manual/development/running-nixos-tests.xml b/nixos/doc/manual/development/running-nixos-tests.xml
index d9be761eb01d..156dcd205a55 100644
--- a/nixos/doc/manual/development/running-nixos-tests.xml
+++ b/nixos/doc/manual/development/running-nixos-tests.xml
@@ -39,24 +39,13 @@ $ firefox result/log.html
 
 </para>
 
-<para>It is also possible to run the test environment interactively,
-allowing you to experiment with the VMs.  For example:
+<title>Running Tests interactively</title>
 
-<screen>
-$ nix-build login.nix -A driver
-$ ./result/bin/nixos-run-vms
-</screen>
-
-The script <command>nixos-run-vms</command> starts the virtual
-machines defined by test.  The root file system of the VMs is created
-on the fly and kept across VM restarts in
-<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
-
-<para>Finally, the test itself can be run interactively.  This is
+<para>The test itself can be run interactively.  This is
 particularly useful when developing or debugging a test:
 
 <screen>
-$ nix-build tests/ -A nfs.driver
+$ nix-build nixos/tests/login.nix -A driver
 $ ./result/bin/nixos-test-driver
 starting VDE switch for network 1
 &gt;
@@ -66,6 +55,7 @@ You can then take any Perl statement, e.g.
 
 <screen>
 &gt; startAll
+&gt; testScript
 &gt; $machine->succeed("touch /tmp/foo")
 </screen>
 
@@ -74,4 +64,16 @@ script and drops you back into the test driver command line upon its
 completion.  This allows you to inspect the state of the VMs after the
 test (e.g. to debug the test script).</para>
 
-</section>
\ No newline at end of file
+<para>To just start and experiment with the VMs, run:
+
+<screen>
+$ nix-build nixos/tests/login.nix -A driver
+$ ./result/bin/nixos-run-vms
+</screen>
+
+The script <command>nixos-run-vms</command> starts the virtual
+machines defined by test.  The root file system of the VMs is created
+on the fly and kept across VM restarts in
+<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
+
+</section>
diff --git a/nixos/doc/manual/development/sources.xml b/nixos/doc/manual/development/sources.xml
index 992a07af9813..3ac07da19f12 100644
--- a/nixos/doc/manual/development/sources.xml
+++ b/nixos/doc/manual/development/sources.xml
@@ -40,20 +40,22 @@ rebuild everything from source. So you may want to create a local
 branch based on your current NixOS version:
 
 <screen>
-$ nixos-version
-14.04.273.ea1952b (Baboon)
-
-$ git checkout -b local ea1952b
+$ <replaceable>/my/sources</replaceable>/nixpkgs/maintainers/scripts/update-channel-branches.sh
+Fetching channels from https://nixos.org/channels:
+ * [new branch]      cbe467e           -> channels/remotes/nixos-unstable
+Fetching channels from nixos-version:
+ * [new branch]      9ff4738           -> channels/current-system
+Fetching channels from ~/.nix-defexpr:
+ * [new branch]      0d4acad           -> channels/root/nixos
+$ git checkout -b local channels/current-system
 </screen>
 
 Or, to base your local branch on the latest version available in the
 NixOS channel:
 
 <screen>
-$ curl -sI http://nixos.org/channels/nixos-unstable/ | grep Location
-Location: http://releases.nixos.org/nixos/unstable/nixos-14.10pre43986.acaf4a6/
-
-$ git checkout -b local acaf4a6
+$ <replaceable>/my/sources</replaceable>/nixpkgs/maintainers/scripts/update-channel-branches.sh
+$ git checkout -b local channels/remotes/nixos-unstable
 </screen>
 
 You can then use <command>git rebase</command> to sync your local
@@ -92,4 +94,4 @@ to <command>nix-env</command>, as it will break after interpreting expressions
 in <filename>nixos/</filename> as packages.</para>
 -->
 
-</chapter>
\ No newline at end of file
+</chapter>
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
index b140c56fbee1..c21759bc9261 100644
--- a/nixos/doc/manual/installation/installing.xml
+++ b/nixos/doc/manual/installation/installing.xml
@@ -11,14 +11,9 @@
   <listitem><para>Boot from the CD.</para></listitem>
 
   <listitem><para>The CD contains a basic NixOS installation.  (It
-  also contains Memtest86+, useful if you want to test new hardware.)
+  also contains Memtest86+, useful if you want to test new hardware).
   When it’s finished booting, it should have detected most of your
-  hardware and brought up networking (check
-  <command>ifconfig</command>).  Networking is necessary for the
-  installer, since it will download lots of stuff (such as source
-  tarballs or Nixpkgs channel binaries).  It’s best if you have a DHCP
-  server on your network.  Otherwise configure networking manually
-  using <command>ifconfig</command>.</para></listitem>
+  hardware.</para></listitem>
 
   <listitem><para>The NixOS manual is available on virtual console 8
   (press Alt+F8 to access).</para></listitem>
@@ -29,6 +24,16 @@
   <listitem><para>If you downloaded the graphical ISO image, you can
   run <command>start display-manager</command> to start KDE.</para></listitem>
 
+  <listitem><para>The boot process should have brought up networking (check
+  <command>ip a</command>).  Networking is necessary for the
+  installer, since it will download lots of stuff (such as source
+  tarballs or Nixpkgs channel binaries).  It’s best if you have a DHCP
+  server on your network. Otherwise configure networking manually
+  using <command>ifconfig</command>.</para>
+  <para>To manually configure the network on the graphical installer,
+  first disable network-manager with
+  <command>systemctl stop network-manager</command>.</para></listitem>
+
   <listitem><para>The NixOS installer doesn’t do any partitioning or
   formatting yet, so you need to that yourself.  Use the following
   commands:
diff --git a/nixos/doc/manual/installation/obtaining.xml b/nixos/doc/manual/installation/obtaining.xml
index ceeeb5c0ac09..540f19c3201d 100644
--- a/nixos/doc/manual/installation/obtaining.xml
+++ b/nixos/doc/manual/installation/obtaining.xml
@@ -8,9 +8,14 @@
 
 <para>NixOS ISO images can be downloaded from the <link
 xlink:href="http://nixos.org/nixos/download.html">NixOS
-homepage</link>.  These can be burned onto a CD.  It is also possible
-to copy them onto a USB stick and install NixOS from there.  For
-details, see the <link
+homepage</link>.  There are a number of installation options.  If
+you happen to have an optical drive and a spare CD, burning the
+image to CD and booting from that is probably the easiest option.
+Most people will need to prepare a USB stick to boot from.
+Unetbootin is recommended and the process is described in brief below.
+Note that systems which use UEFI require some additional manual steps.
+If you run into difficulty a number of alternative methods are presented
+in the <link
 xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS
 Wiki</link>.</para>
 
diff --git a/nixos/doc/manual/installation/upgrading.xml b/nixos/doc/manual/installation/upgrading.xml
index ed71a7e23a30..46d3af56b570 100644
--- a/nixos/doc/manual/installation/upgrading.xml
+++ b/nixos/doc/manual/installation/upgrading.xml
@@ -15,7 +15,7 @@ been built.  These channels are:
 <itemizedlist>
   <listitem>
     <para>Stable channels, such as <literal
-    xlink:href="http://nixos.org/channels/nixos-14.04">nixos-14.04</literal>.
+    xlink:href="https://nixos.org/channels/nixos-14.04">nixos-14.04</literal>.
     These only get conservative bug fixes and package upgrades.  For
     instance, a channel update may cause the Linux kernel on your
     system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but
@@ -26,7 +26,7 @@ been built.  These channels are:
   </listitem>
   <listitem>
     <para>The unstable channel, <literal
-    xlink:href="http://nixos.org/channels/nixos-unstable">nixos-unstable</literal>.
+    xlink:href="https://nixos.org/channels/nixos-unstable">nixos-unstable</literal>.
     This corresponds to NixOS’s main development branch, and may thus
     see radical changes between channel updates.  It’s not recommended
     for production systems.</para>
@@ -34,7 +34,7 @@ been built.  These channels are:
 </itemizedlist>
 
 To see what channels are available, go to <link
-xlink:href="http://nixos.org/channels"/>.  (Note that the URIs of the
+xlink:href="https://nixos.org/channels"/>.  (Note that the URIs of the
 various channels redirect to a directory that contains the channel’s
 latest version and includes ISO images and VirtualBox
 appliances.)</para>
@@ -53,20 +53,20 @@ nixos https://nixos.org/channels/nixos-unstable
 To switch to a different NixOS channel, do
 
 <screen>
-$ nix-channel --add http://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
+$ nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
 </screen>
 
 (Be sure to include the <literal>nixos</literal> parameter at the
 end.)  For instance, to use the NixOS 14.04 stable channel:
 
 <screen>
-$ nix-channel --add http://nixos.org/channels/nixos-14.04 nixos
+$ nix-channel --add https://nixos.org/channels/nixos-14.04 nixos
 </screen>
 
-But it you want to live on the bleeding edge:
+But if you want to live on the bleeding edge:
 
 <screen>
-$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos
+$ nix-channel --add https://nixos.org/channels/nixos-unstable nixos
 </screen>
 
 </para>
diff --git a/nixos/doc/manual/release-notes/release-notes.xml b/nixos/doc/manual/release-notes/release-notes.xml
index 9034dba1fb5a..231a3b4c2e21 100644
--- a/nixos/doc/manual/release-notes/release-notes.xml
+++ b/nixos/doc/manual/release-notes/release-notes.xml
@@ -10,7 +10,7 @@
 <para>This section lists the release notes for each stable version of NixOS.</para>
 </partintro>
 
-<xi:include href="rl-1411.xml" />
+<xi:include href="rl-1412.xml" />
 <xi:include href="rl-1404.xml" />
 <xi:include href="rl-1310.xml" />
 
diff --git a/nixos/doc/manual/release-notes/rl-1411.xml b/nixos/doc/manual/release-notes/rl-1411.xml
deleted file mode 100644
index 74cf8323e692..000000000000
--- a/nixos/doc/manual/release-notes/rl-1411.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-        xmlns:xlink="http://www.w3.org/1999/xlink"
-        xmlns:xi="http://www.w3.org/2001/XInclude"
-        version="5.0"
-        xml:id="sec-release-14.11">
-
-<title>Release 14.11 (“Caterpillar”, 2014/11/??)</title>
-
-<para>When upgrading from a previous release, please be aware of the
-following incompatible changes:
-
-<itemizedlist>
-
-  <listitem><para>The host side of a container virtual Ethernet pair
-  is now called <literal>ve-<replaceable>container-name</replaceable></literal>
-  rather than <literal>c-<replaceable>container-name</replaceable></literal>.</para></listitem>
-
-</itemizedlist>
-
-</para>
-
-</chapter>
diff --git a/nixos/doc/manual/release-notes/rl-1412.xml b/nixos/doc/manual/release-notes/rl-1412.xml
new file mode 100644
index 000000000000..324a3e6bdc2f
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-1412.xml
@@ -0,0 +1,167 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-release-14.12">
+
+<title>Release 14.12 (“Caterpillar”, 2014/12/??)</title>
+
+<para>In addition to numerous new and upgraded packages, this release has the following highlights:
+
+<itemizedlist>
+
+<listitem><para>Systemd has been updated to version 217, which has numerous
+<link xlink:href="http://lists.freedesktop.org/archives/systemd-devel/2014-October/024662.html">improvements
+.</link></para></listitem>
+
+<listitem><para><link xlink:href="http://thread.gmane.org/gmane.linux.distributions.nixos/15165">
+Nix has been updated to 1.8.</link></para></listitem>
+
+<listitem><para>NixOS is now based on Glibc 2.20.</para></listitem>
+
+<listitem><para>KDE has been updated to 4.14.</para></listitem>
+
+<listitem><para>The default Linux kernel has been updated to 3.14.</para></listitem>
+
+<listitem><para><option>users.mutableUsers</option> set to <literal>true</literal> now respect any changes
+made after initial creation of a user or a group.
+</para></listitem>
+
+</itemizedlist></para>
+
+<para>Following new services were added since the last release:
+
+<itemizedlist>
+<listitem><para>parallels-guest</para></listitem>
+<listitem><para>docker</para></listitem>
+<listitem><para>lxc</para></listitem>
+<listitem><para>openvswitch</para></listitem>
+<listitem><para>fluxbox</para></listitem>
+<listitem><para>bspwm</para></listitem>
+<listitem><para>gdm</para></listitem>
+<listitem><para>fcgiwrap</para></listitem>
+<listitem><para>peerflix</para></listitem>
+<listitem><para>fail2ban</para></listitem>
+<listitem><para>chronos</para></listitem>
+<listitem><para>znc</para></listitem>
+<listitem><para>unifi</para></listitem>
+<listitem><para>teamspeak3</para></listitem>
+<listitem><para>strongswan</para></listitem>
+<listitem><para>seeks</para></listitem>
+<listitem><para>radicale</para></listitem>
+<listitem><para>prosody</para></listitem>
+<listitem><para>polipo</para></listitem>
+<listitem><para>openntpd</para></listitem>
+<listitem><para>nsd</para></listitem>
+<listitem><para>mailpile</para></listitem>
+<listitem><para>i2pd</para></listitem>
+<listitem><para>dnscrypt-proxy</para></listitem>
+<listitem><para>consul</para></listitem>
+<listitem><para>atftpd</para></listitem>
+<listitem><para>scollector</para></listitem>
+<listitem><para>collectd</para></listitem>
+<listitem><para>bosun</para></listitem>
+<listitem><para>riemann</para></listitem>
+<listitem><para>zookeeper</para></listitem>
+<listitem><para>uhub</para></listitem>
+<listitem><para>siproxd</para></listitem>
+<listitem><para>redmine</para></listitem>
+<listitem><para>phd</para></listitem>
+<listitem><para>mesos</para></listitem>
+<listitem><para>gitlab</para></listitem>
+<listitem><para>gitolite</para></listitem>
+<listitem><para>etcd</para></listitem>
+<listitem><para>docker-registry</para></listitem>
+<listitem><para>cpuminer-cryptonight</para></listitem>
+<listitem><para>thermald</para></listitem>
+<listitem><para>mlmmj</para></listitem>
+<listitem><para>tcsd</para></listitem>
+<listitem><para>gnome3.seahorse</para></listitem>
+<listitem><para>gnome3.gvfs</para></listitem>
+<listitem><para>gnome3.gnome-online-miners</para></listitem>
+<listitem><para>gnome3.gnome-documents</para></listitem>
+<listitem><para>geoclue2</para></listitem>
+<listitem><para>opentsdb</para></listitem>
+<listitem><para>neo4j</para></listitem>
+<listitem><para>monetdb</para></listitem>
+<listitem><para>influxdb</para></listitem>
+<listitem><para>hbase</para></listitem>
+<listitem><para>torque/mrom</para></listitem>
+<listitem><para>torque/server</para></listitem>
+<listitem><para>kubernetes</para></listitem>
+<listitem><para>fleet</para></listitem>
+<listitem><para>crashplan</para></listitem>
+<listitem><para>mopidy</para></listitem>
+<listitem><para>liquidsoap</para></listitem>
+</itemizedlist>
+</para>
+
+<para>When upgrading from a previous release, please be aware of the
+following incompatible changes:
+
+<itemizedlist>
+
+<listitem><para>The default version of Apache httpd is now 2.4. If
+you use the <option>extraConfig</option> option to pass literal
+Apache configuration text, you may need to update it — see <link
+xlink:href="http://httpd.apache.org/docs/2.4/upgrading.html">Apache’s
+documentation</link> for details. If you wish to continue to use
+httpd 2.2, add the following line to your NixOS configuration:
+
+rogramlisting>
+rvices.httpd.package = pkgs.apacheHttpd_2_2;
+programlisting>
+
+</para></listitem>
+
+<listitem><para>PHP 5.3 has been removed because it is no longer
+supported by the PHP project. A <link
+xlink:href="http://php.net/migration54">migration guide</link> is
+available.</para></listitem>
+
+<listitem><para>The host side of a container virtual Ethernet pair
+is now called <literal>ve-<replaceable>container-name</replaceable></literal>
+rather than <literal>c-<replaceable>container-name</replaceable></literal>.</para></listitem>
+
+<listitem><para>GNOME 3.10 support has been dropped. The default GNOME version is now 3.12.</para></listitem>
+
+<listitem><para>VirtualBox has been upgraded to 4.3.20 release. Users may be required to run
+<command>rm -rf /tmp.vbox*</command>. <literal>imports = [ &lt;nixpkgs/nixos/modules/programs/virtualbox.nix&gt; ]</literal>
+is no longer necessary, use <literal>services.virtualboxHost.enable = true</literal> instead.
+</para>
+<para>Also, hardening mode is now enabled by default, which means that unless you want to use
+USB support, you no longer need to be a member of the <literal>vboxusers</literal> group.
+</para></listitem>
+
+<listitem><para>Chromium has been updated to 39.0.2171.65. <option>enablePepperPDF</option> is now enabled by default.
+<literal>chromium*Wrapper</literal> packages no longer exist, because upstream removed NSAPI support.
+<literal>chromium-stable</literal> has been renamed to <literal>chromium</literal>.
+</para></listitem>
+
+<listitem><para>Python packaging documentation is now part of nixpkgs manual. To override
+the python packages available to a custom python you now use <literal>pkgs.pythonFull.buildEnv.override</literal>
+instead of <literal>pkgs.pythonFull.override</literal>.
+</para></listitem>
+
+<listitem><para><literal>boot.resumeDevice = "8:6"</literal> is no longer supported. Most users will
+want to leave it undefined, which takes the swap partitions automatically. There is an evaluation
+assertion to ensure that the string starts with a slash.
+</para></listitem>
+
+<listitem><para>The system-wide default timezone for NixOS installations
+changed from <literal>CET</literal> to <literal>UTC</literal>. To choose
+a different timezone for your system, configure
+<literal>time.timeZone</literal> in
+<literal>configuration.nix</literal>. A fairly complete list of possible
+values for that setting is available at <link
+xlink:href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"/>.</para></listitem>
+
+<listitem><para>GNU screen has been updated to 4.2.1, which breaks
+the ability to connect to sessions created by older versions of
+screen.</para></listitem>
+
+</itemizedlist>
+
+</para>
+
+</chapter>
diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix
index 0fa00637a93a..08adcf3a0078 100644
--- a/nixos/lib/eval-config.nix
+++ b/nixos/lib/eval-config.nix
@@ -11,15 +11,16 @@
 , prefix ? []
 }:
 
-let extraArgs_ = extraArgs; pkgs_ = pkgs; system_ = system; in
-
-rec {
+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 rec {
 
   # Merge the option definitions in all modules, forming the full
   # system configuration.
   inherit (pkgs.lib.evalModules {
     inherit prefix;
-    modules = modules ++ baseModules;
+    modules = modules ++ extraModules ++ baseModules;
     args = extraArgs;
     check = check && options.environment.checkConfigurationOptions.value;
   }) config options;
diff --git a/nixos/lib/make-system-tarball.nix b/nixos/lib/make-system-tarball.nix
index 3bd891fdbc2b..a2a0340a6bd3 100644
--- a/nixos/lib/make-system-tarball.nix
+++ b/nixos/lib/make-system-tarball.nix
@@ -16,6 +16,9 @@
   # symlink to `object' that will be added to the tarball.
   storeContents ? []
 
+  # Extra commands to be executed before archiving files
+, extraCommands ? ""
+
   # Extra tar arguments
 , extraArgs ? ""
 }:
@@ -25,7 +28,7 @@ stdenv.mkDerivation {
   builder = ./make-system-tarball.sh;
   buildInputs = [perl xz];
 
-  inherit fileName pathsFromGraph extraArgs;
+  inherit fileName pathsFromGraph extraArgs extraCommands;
 
   # !!! should use XML.
   sources = map (x: x.source) contents;
diff --git a/nixos/lib/make-system-tarball.sh b/nixos/lib/make-system-tarball.sh
index 2eb668115a6f..e04455e889b0 100644
--- a/nixos/lib/make-system-tarball.sh
+++ b/nixos/lib/make-system-tarball.sh
@@ -33,7 +33,7 @@ for i in $storePaths; do
 done
 
 
-# TODO tar ruxo 
+# TODO tar ruxo
 # Also include a manifest of the closures in a format suitable for
 # nix-store --load-db.
 printRegistration=1 perl $pathsFromGraph closure-* > nix-path-registration
@@ -48,6 +48,8 @@ for ((n = 0; n < ${#objects[*]}; n++)); do
     fi
 done
 
+$extraCommands
+
 mkdir -p $out/tarball
 
 tar cvJf $out/tarball/$fileName.tar.xz * $extraArgs
diff --git a/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix b/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix
index d9feba164a76..530769cec5b7 100644
--- a/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix
+++ b/nixos/maintainers/scripts/ec2/amazon-hvm-install-config.nix
@@ -19,7 +19,8 @@ in
 {
   imports = [ ./amazon-base-config.nix ];
   ec2.hvm = true;
-  boot.loader.grub.device = lib.mkOverride 0 "nodev";
+  boot.loader.grub.device = lib.mkOverride 0 "/dev/xvdg";
+  boot.kernelParams = [ "console=ttyS0" ];
 
   boot.initrd.extraUtilsCommands = ''
     cp -v ${pkgs.gawk}/bin/gawk $out/bin/gawk
diff --git a/nixos/maintainers/scripts/ec2/create-ebs-amis.py b/nixos/maintainers/scripts/ec2/create-ebs-amis.py
index 14607b9a3678..6c91aa68694d 100755
--- a/nixos/maintainers/scripts/ec2/create-ebs-amis.py
+++ b/nixos/maintainers/scripts/ec2/create-ebs-amis.py
@@ -19,8 +19,17 @@ parser.add_argument('--key', dest='key_name', action='store_true', help='Keypair
 args = parser.parse_args()
 
 instance_type = "m3.medium" if args.hvm else "m1.small"
-ebs_size = 8 if args.hvm else 20
 
+if args.hvm:
+    virtualization_type = "hvm"
+    root_block = "/dev/sda1"
+    image_type = 'hvm'
+else:
+    virtualization_type = "paravirtual"
+    root_block = "/dev/sda"
+    image_type = 'ebs'
+
+ebs_size = 20
 
 # Start a NixOS machine in the given region.
 f = open("ebs-creator-config.nix", "w")
@@ -66,7 +75,7 @@ m.run_command("mount {0} /mnt".format(device))
 m.run_command("touch /mnt/.ebs")
 m.run_command("mkdir -p /mnt/etc/nixos")
 
-m.run_command("nix-channel --add http://nixos.org/channels/nixos-{} nixos".format(args.channel))
+m.run_command("nix-channel --add https://nixos.org/channels/nixos-{} nixos".format(args.channel))
 m.run_command("nix-channel --update")
 
 version = m.run_command("nix-instantiate --eval-only -A lib.nixpkgsVersion '<nixpkgs>'", capture_stdout=True).split(' ')[0].replace('"','').strip()
@@ -76,10 +85,6 @@ if args.hvm:
     m.upload_file("./amazon-hvm-config.nix", "/mnt/etc/nixos/configuration.nix")
     m.upload_file("./amazon-hvm-install-config.nix", "/mnt/etc/nixos/amazon-hvm-install-config.nix")
     m.run_command("NIXOS_CONFIG=/etc/nixos/amazon-hvm-install-config.nix nixos-install")
-    m.run_command('nix-env -iA nixos.pkgs.grub')
-    m.run_command('cp /nix/store/*-grub-0.97*/lib/grub/i386-pc/* /mnt/boot/grub')
-    m.run_command('echo "(hd1) /dev/xvdg" > device.map')
-    m.run_command('echo -e "root (hd1,0)\nsetup (hd1)" | grub --device-map=device.map --batch')
 else:
     m.upload_file("./amazon-base-config.nix", "/mnt/etc/nixos/configuration.nix")
     m.run_command("nixos-install")
@@ -87,7 +92,7 @@ else:
 m.run_command("umount /mnt")
 
 if args.hvm:
-    ami_name = "nixos-{0}-x86_64-ebs-hvm".format(version)
+    ami_name = "nixos-{0}-x86_64-hvm".format(version)
     description = "NixOS {0} (x86_64; EBS root; hvm)".format(version)
 else:
     ami_name = "nixos-{0}-x86_64-ebs".format(version)
@@ -102,58 +107,40 @@ def check():
 
 m.connect()
 volume = m._conn.get_all_volumes([], filters={'attachment.instance-id': m.resource_id, 'attachment.device': "/dev/sdg"})[0]
-if args.hvm:
-    instance = m._conn.run_instances( image_id="ami-5f491f36"
-                                    , instance_type=instance_type
-                                    , key_name=args.key_name
-                                    , placement=m.zone
-                                    , security_groups=["eelco-test"]).instances[0]
-    nixops.util.check_wait(lambda: instance.update() == 'running', max_tries=120)
-    instance.stop()
-    nixops.util.check_wait(lambda: instance.update() == 'stopped', max_tries=120)
-    old_root_volume = m._conn.get_all_volumes([], filters={'attachment.instance-id': instance.id, 'attachment.device': "/dev/sda1"})[0]
-    old_root_volume.detach()
-    volume.detach()
-    nixops.util.check_wait(lambda: volume.update() == 'available', max_tries=120)
-    nixops.util.check_wait(lambda: old_root_volume.update() == 'available', max_tries=120)
-    volume.attach(instance.id, '/dev/sda1')
-    nixops.util.check_wait(lambda: volume.update() == 'in-use', max_tries=120)
-
-    ami_id = m._conn.create_image(instance.id, ami_name, description)
-    time.sleep(5)
-    image = m._conn.get_all_images([ami_id])[0]
-    nixops.util.check_wait(lambda: image.update() == 'available', max_tries=120)
-    instance.terminate()
 
-else:
-    # Create a snapshot.
-    snapshot = volume.create_snapshot(description=description)
-    print >> sys.stderr, "created snapshot {0}".format(snapshot.id)
+# Create a snapshot.
+snapshot = volume.create_snapshot(description=description)
+print >> sys.stderr, "created snapshot {0}".format(snapshot.id)
 
-    nixops.util.check_wait(check, max_tries=120)
+nixops.util.check_wait(check, max_tries=120)
 
-    m._conn.create_tags([snapshot.id], {'Name': ami_name})
+m._conn.create_tags([snapshot.id], {'Name': ami_name})
 
-    if not args.keep: depl.destroy_resources()
+if not args.keep: depl.destroy_resources()
 
-     # Register the image.
-    aki = m._conn.get_all_images(filters={'manifest-location': '*pv-grub-hd0_1.03-x86_64*'})[0]
-    print >> sys.stderr, "using kernel image {0} - {1}".format(aki.id, aki.location)
+# Register the image.
+aki = m._conn.get_all_images(filters={'manifest-location': 'ec2*pv-grub-hd0_1.03-x86_64*'})[0]
+print >> sys.stderr, "using kernel image {0} - {1}".format(aki.id, aki.location)
 
-    block_map = BlockDeviceMapping()
-    block_map['/dev/sda'] = BlockDeviceType(snapshot_id=snapshot.id, delete_on_termination=True)
-    block_map['/dev/sdb'] = BlockDeviceType(ephemeral_name="ephemeral0")
-    block_map['/dev/sdc'] = BlockDeviceType(ephemeral_name="ephemeral1")
-    block_map['/dev/sdd'] = BlockDeviceType(ephemeral_name="ephemeral2")
-    block_map['/dev/sde'] = BlockDeviceType(ephemeral_name="ephemeral3")
+block_map = BlockDeviceMapping()
+block_map[root_block] = BlockDeviceType(snapshot_id=snapshot.id, delete_on_termination=True, size=ebs_size, volume_type="gp2")
+block_map['/dev/sdb'] = BlockDeviceType(ephemeral_name="ephemeral0")
+block_map['/dev/sdc'] = BlockDeviceType(ephemeral_name="ephemeral1")
+block_map['/dev/sdd'] = BlockDeviceType(ephemeral_name="ephemeral2")
+block_map['/dev/sde'] = BlockDeviceType(ephemeral_name="ephemeral3")
 
-    ami_id = m._conn.register_image(
+common_args = dict(
         name=ami_name,
         description=description,
         architecture="x86_64",
-        root_device_name="/dev/sda",
-        kernel_id=aki.id,
-        block_device_map=block_map)
+        root_device_name=root_block,
+        block_device_map=block_map,
+        virtualization_type=virtualization_type,
+        delete_root_volume_on_termination=True
+        )
+if not args.hvm:
+    common_args['kernel_id']=aki.id
+ami_id = m._conn.register_image(**common_args)
 
 print >> sys.stderr, "registered AMI {0}".format(ami_id)
 
@@ -197,17 +184,12 @@ test_depl.nix_exprs = [os.path.abspath("./ebs-test.nix")]
 test_depl.deploy(create_only=True)
 test_depl.machines['machine'].run_command("nixos-version")
 
-if args.hvm:
-    image_type = 'hvm'
-else:
-    image_type = 'ebs'
-
 # Log the AMI ID.
 f = open("{0}.{1}.ami-id".format(args.region, image_type), "w")
 f.write("{0}".format(ami_id))
 f.close()
 
-for dest in [ 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1']:
+for dest in [ 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1']:
     if args.region != dest:
         print >> sys.stderr, "copying image from region {0} to {1}".format(args.region, dest)
         conn = boto.ec2.connect_to_region(dest)
diff --git a/nixos/modules/config/fonts/fontconfig-ultimate.nix b/nixos/modules/config/fonts/fontconfig-ultimate.nix
new file mode 100644
index 000000000000..853f253ff9bc
--- /dev/null
+++ b/nixos/modules/config/fonts/fontconfig-ultimate.nix
@@ -0,0 +1,193 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let fcBool = x: if x then "<bool>true</bool>" else "<bool>false</bool>";
+in
+{
+
+  options = {
+
+    fonts = {
+
+      fontconfig = {
+
+        ultimate = {
+          enable = mkOption {
+            type = types.bool;
+            default = true;
+            description = ''
+              Enable fontconfig-ultimate settings (formerly known as
+              Infinality). Besides the customizable settings in this NixOS
+              module, fontconfig-ultimate also provides many font-specific
+              rendering tweaks.
+            '';
+          };
+
+          allowBitmaps = mkOption {
+            type = types.bool;
+            default = true;
+            description = ''
+              Allow bitmap fonts. Set to <literal>false</literal> to ban all
+              bitmap fonts.
+            '';
+          };
+
+          allowType1 = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''
+              Allow Type-1 fonts. Default is <literal>false</literal> because of
+              poor rendering.
+            '';
+          };
+
+          useEmbeddedBitmaps = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''Use embedded bitmaps in fonts like Calibri.'';
+          };
+
+          forceAutohint = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''
+              Force use of the TrueType Autohinter. Useful for debugging or
+              free-software purists.
+            '';
+          };
+
+          renderMonoTTFAsBitmap = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''Render some monospace TTF fonts as bitmaps.'';
+          };
+
+          substitutions = mkOption {
+            type = types.str // {
+              check = flip elem ["none" "free" "combi" "ms"];
+            };
+            default = "free";
+            description = ''
+              Font substitutions to replace common Type 1 fonts with nicer
+              TrueType fonts. <literal>free</literal> uses free fonts,
+              <literal>ms</literal> uses Microsoft fonts,
+              <literal>combi</literal> uses a combination, and
+              <literal>none</literal> disables the substitutions.
+            '';
+          };
+
+          rendering = mkOption {
+            type = types.attrs;
+            default = pkgs.fontconfig-ultimate.rendering.ultimate;
+            description = ''
+              FreeType rendering settings presets. The default is
+              <literal>pkgs.fontconfig-ultimate.rendering.ultimate</literal>.
+              The other available styles are:
+              <literal>ultimate-lighter</literal>,
+              <literal>ultimate-darker</literal>,
+              <literal>ultimate-lightest</literal>,
+              <literal>ultimate-darkest</literal>,
+              <literal>default</literal> (the original Infinality default),
+              <literal>osx</literal>,
+              <literal>ipad</literal>,
+              <literal>ubuntu</literal>,
+              <literal>linux</literal>,
+              <literal>winxplight</literal>,
+              <literal>win7light</literal>,
+              <literal>winxp</literal>,
+              <literal>win7</literal>,
+              <literal>vanilla</literal>,
+              <literal>classic</literal>,
+              <literal>nudge</literal>,
+              <literal>push</literal>,
+              <literal>shove</literal>,
+              <literal>sharpened</literal>,
+              <literal>infinality</literal>. Any of the presets may be
+              customized by editing the attributes. To disable, set this option
+              to the empty attribute set <literal>{}</literal>.
+            '';
+          };
+        };
+      };
+    };
+
+  };
+
+
+  config =
+    let ultimate = config.fonts.fontconfig.ultimate;
+        fontconfigUltimateConf = ''
+          <?xml version="1.0"?>
+          <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+          <fontconfig>
+
+            ${optionalString (!ultimate.allowBitmaps) ''
+            <!-- Reject bitmap fonts -->
+            <selectfont>
+              <rejectfont>
+                <pattern>
+                  <patelt name="scalable"><bool>false</bool></patelt>
+                </pattern>
+              </rejectfont>
+            </selectfont>
+            ''}
+
+            ${optionalString ultimate.allowType1 ''
+            <!-- Reject Type 1 fonts -->
+            <selectfont>
+              <rejectfont>
+                <pattern>
+                  <patelt name="fontformat">
+                    <string>Type 1</string>
+                  </patelt>
+                </pattern>
+              </rejectfont>
+            </selectfont>
+            ''}
+
+            <!-- Use embedded bitmaps in fonts like Calibri? -->
+            <match target="font">
+              <edit name="embeddedbitmap" mode="assign">
+                ${fcBool ultimate.useEmbeddedBitmaps}
+              </edit>
+            </match>
+
+            <!-- Force autohint always -->
+            <match target="font">
+              <edit name="force_autohint" mode="assign">
+                ${fcBool ultimate.forceAutohint}
+              </edit>
+            </match>
+
+            <!-- Render some monospace TTF fonts as bitmaps -->
+            <match target="pattern">
+              <edit name="bitmap_monospace" mode="assign">
+                ${fcBool ultimate.renderMonoTTFAsBitmap}
+              </edit>
+            </match>
+
+            ${optionalString (ultimate.substitutions != "none") ''
+            <!-- Type 1 font substitutions -->
+            <include ignore_missing="yes">${pkgs.fontconfig-ultimate.confd}/etc/fonts/presets/${ultimate.substitutions}</include>
+            ''}
+
+            <include ignore_missing="yes">${pkgs.fontconfig-ultimate.confd}/etc/fonts/conf.d</include>
+
+          </fontconfig>
+        '';
+    in mkIf (config.fonts.fontconfig.enable && ultimate.enable) {
+
+      environment.etc."fonts/conf.d/52-fontconfig-ultimate.conf" = {
+        text = fontconfigUltimateConf;
+      };
+
+      environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/52-fontconfig-ultimate.conf" = {
+        text = fontconfigUltimateConf;
+      };
+
+      environment.variables = ultimate.rendering;
+
+    };
+
+}
diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix
index 7516d7ddf1a6..793b0a250acd 100644
--- a/nixos/modules/config/fonts/fontconfig.nix
+++ b/nixos/modules/config/fonts/fontconfig.nix
@@ -8,47 +8,250 @@ with lib;
 
     fonts = {
 
-      enableFontConfig = mkOption { # !!! should be enableFontconfig
-        type = types.bool;
-        default = true;
-        description = ''
-          If enabled, a Fontconfig configuration file will be built
-          pointing to a set of default fonts.  If you don't care about
-          running X11 applications or any other program that uses
-          Fontconfig, you can turn this option off and prevent a
-          dependency on all those fonts.
-        '';
+      fontconfig = {
+        enable = mkOption {
+          type = types.bool;
+          default = true;
+          description = ''
+            If enabled, a Fontconfig configuration file will be built
+            pointing to a set of default fonts.  If you don't care about
+            running X11 applications or any other program that uses
+            Fontconfig, you can turn this option off and prevent a
+            dependency on all those fonts.
+          '';
+        };
+
+        antialias = mkOption {
+          type = types.bool;
+          default = true;
+          description = "Enable font antialiasing.";
+        };
+
+        dpi = mkOption {
+          type = types.int;
+          default = 0;
+          description = ''
+            Force DPI setting. Setting to <literal>0</literal> disables DPI
+            forcing; the DPI detected for the display will be used.
+          '';
+        };
+
+        defaultFonts = {
+          monospace = mkOption {
+            type = types.listOf types.str;
+            default = ["DejaVu Sans Mono"];
+            description = ''
+              System-wide default monospace font(s). Multiple fonts may be
+              listed in case multiple languages must be supported.
+            '';
+          };
+
+          sansSerif = mkOption {
+            type = types.listOf types.str;
+            default = ["DejaVu Sans"];
+            description = ''
+              System-wide default sans serif font(s). Multiple fonts may be
+              listed in case multiple languages must be supported.
+            '';
+          };
+
+          serif = mkOption {
+            type = types.listOf types.str;
+            default = ["DejaVu Serif"];
+            description = ''
+              System-wide default serif font(s). Multiple fonts may be listed
+              in case multiple languages must be supported.
+            '';
+          };
+        };
+
+        hinting = {
+          enable = mkOption {
+            type = types.bool;
+            default = true;
+            description = "Enable TrueType hinting.";
+          };
+
+          autohint = mkOption {
+            type = types.bool;
+            default = true;
+            description = ''
+              Enable the autohinter, which provides hinting for otherwise
+              un-hinted fonts. The results are usually lower quality than
+              correctly-hinted fonts.
+            '';
+          };
+
+          style = mkOption {
+            type = types.str // {
+              check = flip elem ["none" "slight" "medium" "full"];
+            };
+            default = "full";
+            description = ''
+              TrueType hinting style, one of <literal>none</literal>,
+              <literal>slight</literal>, <literal>medium</literal>, or
+              <literal>full</literal>.
+            '';
+          };
+        };
+
+        includeUserConf = mkOption {
+          type = types.bool;
+          default = true;
+          description = ''
+            Include the user configuration from
+            <filename>~/.config/fontconfig/fonts.conf</filename> or
+            <filename>~/.config/fontconfig/conf.d</filename>.
+          '';
+        };
+
+        subpixel = {
+
+          rgba = mkOption {
+            type = types.string // {
+              check = flip elem ["rgb" "bgr" "vrgb" "vbgr" "none"];
+            };
+            default = "rgb";
+            description = ''
+              Subpixel order, one of <literal>none</literal>,
+              <literal>rgb</literal>, <literal>bgr</literal>,
+              <literal>vrgb</literal>, or <literal>vbgr</literal>.
+            '';
+          };
+
+          lcdfilter = mkOption {
+            type = types.str // {
+              check = flip elem ["none" "default" "light" "legacy"];
+            };
+            default = "default";
+            description = ''
+              FreeType LCD filter, one of <literal>none</literal>,
+              <literal>default</literal>, <literal>light</literal>, or
+              <literal>legacy</literal>.
+            '';
+          };
+
+        };
+
       };
 
     };
 
   };
 
+  config =
+    let fontconfig = config.fonts.fontconfig;
+        fcBool = x: "<bool>" + (if x then "true" else "false") + "</bool>";
+        nixosConf = ''
+          <?xml version='1.0'?>
+          <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+          <fontconfig>
+
+            <!-- Default rendering settings -->
+            <match target="font">
+              <edit mode="assign" name="hinting">
+                ${fcBool fontconfig.hinting.enable}
+              </edit>
+              <edit mode="assign" name="autohint">
+                ${fcBool fontconfig.hinting.autohint}
+              </edit>
+              <edit mode="assign" name="hintstyle">
+                <const>hint${fontconfig.hinting.style}</const>
+              </edit>
+              <edit mode="assign" name="antialias">
+                ${fcBool fontconfig.antialias}
+              </edit>
+              <edit mode="assign" name="rgba">
+                <const>${fontconfig.subpixel.rgba}</const>
+              </edit>
+              <edit mode="assign" name="lcdfilter">
+                <const>lcd${fontconfig.subpixel.lcdfilter}</const>
+              </edit>
+            </match>
 
-  config = mkIf config.fonts.enableFontConfig {
+            <!-- Default fonts -->
+            ${optionalString (fontconfig.defaultFonts.sansSerif != []) ''
+            <alias>
+              <family>sans-serif</family>
+              <prefer>
+                ${concatStringsSep "\n"
+                  (map (font: "<family>${font}</family>")
+                    fontconfig.defaultFonts.sansSerif)}
+              </prefer>
+            </alias>
+            ''}
+            ${optionalString (fontconfig.defaultFonts.serif != []) ''
+            <alias>
+              <family>serif</family>
+              <prefer>
+                ${concatStringsSep "\n"
+                  (map (font: "<family>${font}</family>")
+                    fontconfig.defaultFonts.serif)}
+              </prefer>
+            </alias>
+            ''}
+            ${optionalString (fontconfig.defaultFonts.monospace != []) ''
+            <alias>
+              <family>monospace</family>
+              <prefer>
+                ${concatStringsSep "\n"
+                  (map (font: "<family>${font}</family>")
+                    fontconfig.defaultFonts.monospace)}
+              </prefer>
+            </alias>
+            ''}
 
-    # Bring in the default (upstream) fontconfig configuration.
-    environment.etc."fonts/fonts.conf".source =
-      pkgs.makeFontsConf { fontDirectories = config.fonts.fonts; };
+            ${optionalString (fontconfig.dpi != 0) ''
+            <match target="pattern">
+              <edit name="dpi" mode="assign">
+                <double>${fontconfig.dpi}</double>
+              </edit>
+            </match>
+            ''}
 
-    environment.etc."fonts/conf.d/00-nixos.conf".text =
-      ''
-        <?xml version='1.0'?>
-        <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
-        <fontconfig>
+          </fontconfig>
+        '';
+    in mkIf fontconfig.enable {
 
-          <!-- Set the default hinting style to "slight". -->
-          <match target="font">
-            <edit mode="assign" name="hintstyle">
-              <const>hintslight</const>
-            </edit>
-          </match>
+      # Fontconfig 2.10 backward compatibility
 
-        </fontconfig>
-      '';
+      # Bring in the default (upstream) fontconfig configuration, only for fontconfig 2.10
+      environment.etc."fonts/fonts.conf".source =
+        pkgs.makeFontsConf { fontconfig = pkgs.fontconfig_210; fontDirectories = config.fonts.fonts; };
 
-    environment.systemPackages = [ pkgs.fontconfig ];
+      environment.etc."fonts/conf.d/98-nixos.conf".text = nixosConf;
 
-  };
+      # Versioned fontconfig > 2.10. Take shared fonts.conf from fontconfig.
+      # Otherwise specify only font directories.
+      environment.etc."fonts/${pkgs.fontconfig.configVersion}/fonts.conf".source =
+        "${pkgs.fontconfig}/etc/fonts/fonts.conf";
+
+      environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/00-nixos.conf".text =
+        ''
+          <?xml version='1.0'?>
+          <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
+          <fontconfig>
+            <!-- Font directories -->
+            ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)}
+          </fontconfig>
+        '';
+
+      environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/98-nixos.conf".text = nixosConf;
+
+      environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/99-user.conf" = {
+        enable = fontconfig.includeUserConf;
+        text = ''
+          <?xml version="1.0"?>
+          <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+          <fontconfig>
+            <include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
+            <include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>
+          </fontconfig>
+        '';
+      };
+
+      environment.systemPackages = [ pkgs.fontconfig ];
+
+    };
 
 }
diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix
index f6060a910a15..a3fa4bd97783 100644
--- a/nixos/modules/config/fonts/fonts.nix
+++ b/nixos/modules/config/fonts/fonts.nix
@@ -13,14 +13,6 @@ with lib;
         type = types.listOf types.path;
         example = literalExample "[ pkgs.dejavu_fonts ]";
         description = "List of primary font paths.";
-        apply = list: list ++
-          [ # - the user's current profile
-            "~/.nix-profile/lib/X11/fonts"
-            "~/.nix-profile/share/fonts"
-            # - the default profile
-            "/nix/var/nix/profiles/default/lib/X11/fonts"
-            "/nix/var/nix/profiles/default/share/fonts"
-          ];
       };
 
     };
@@ -33,7 +25,7 @@ with lib;
       [ pkgs.xorg.fontbhttf
         pkgs.xorg.fontbhlucidatypewriter100dpi
         pkgs.xorg.fontbhlucidatypewriter75dpi
-        pkgs.ttf_bitstream_vera
+        pkgs.dejavu_fonts
         pkgs.freefont_ttf
         pkgs.liberation_ttf
         pkgs.xorg.fontbh100dpi
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index 136a5bda7459..f99cea7d17b1 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -39,6 +39,73 @@ in
       '';
     };
 
+    networking.proxy = {
+
+      default = lib.mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          This option specifies the default value for httpProxy, httpsProxy, ftpProxy and rsyncProxy.
+        '';
+        example = "http://127.0.0.1:3128";
+      };
+
+      httpProxy = lib.mkOption {
+        type = types.nullOr types.str;
+        default = cfg.proxy.default;
+        description = ''
+          This option specifies the http_proxy environment variable.
+        '';
+        example = "http://127.0.0.1:3128";
+      };
+
+      httpsProxy = lib.mkOption {
+        type = types.nullOr types.str;
+        default = cfg.proxy.default;
+        description = ''
+          This option specifies the https_proxy environment variable.
+        '';
+        example = "http://127.0.0.1:3128";
+      };
+
+      ftpProxy = lib.mkOption {
+        type = types.nullOr types.str;
+        default = cfg.proxy.default;
+        description = ''
+          This option specifies the ftp_proxy environment variable.
+        '';
+        example = "http://127.0.0.1:3128";
+      };
+
+      rsyncProxy = lib.mkOption {
+        type = types.nullOr types.str;
+        default = cfg.proxy.default;
+        description = ''
+          This option specifies the rsync_proxy environment variable.
+        '';
+        example = "http://127.0.0.1:3128";
+      };
+
+      noProxy = lib.mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          This option specifies the no_proxy environment variable.
+          If a default proxy is used and noProxy is null,
+          then noProxy will be set to 127.0.0.1,localhost.
+        '';
+        example = "127.0.0.1,localhost,.localdomain";
+      };
+
+      envVars = lib.mkOption {
+        type = types.attrs;
+        internal = true;
+        default = {};
+        description = ''
+          Environment variables used for the network proxy.
+        '';
+      };
+    };
   };
 
   config = {
@@ -73,7 +140,7 @@ in
             '' + optionalString config.services.nscd.enable ''
               # Invalidate the nscd cache whenever resolv.conf is
               # regenerated.
-              libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service'
+              libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null'
             '' + optionalString cfg.dnsSingleRequest ''
               # only send one DNS request at a time
               resolv_conf_options='single-request'
@@ -84,13 +151,59 @@ in
               dnsmasq_conf=/etc/dnsmasq-conf.conf
               dnsmasq_resolv=/etc/dnsmasq-resolv.conf
             '';
-      };
+
+      } // (optionalAttrs config.services.resolved.enable (
+        if dnsmasqResolve then {
+          "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
+        } else {
+          "resolv.conf".source = "/run/systemd/resolve/resolv.conf";
+        }
+      ));
+
+      networking.proxy.envVars =
+        optionalAttrs (cfg.proxy.default != null) {
+          # other options already fallback to proxy.default
+          no_proxy = "127.0.0.1,localhost";
+        } // optionalAttrs (cfg.proxy.httpProxy != null) {
+          http_proxy  = cfg.proxy.httpProxy;
+        } // optionalAttrs (cfg.proxy.httpsProxy != null) {
+          https_proxy = cfg.proxy.httpsProxy;
+        } // optionalAttrs (cfg.proxy.rsyncProxy != null) {
+          rsync_proxy = cfg.proxy.rsyncProxy;
+        } // optionalAttrs (cfg.proxy.ftpProxy != null) {
+          ftp_proxy   = cfg.proxy.ftpProxy;
+        } // optionalAttrs (cfg.proxy.noProxy != null) {
+          no_proxy    = cfg.proxy.noProxy;
+        };
+
+    # Install the proxy environment variables
+    environment.sessionVariables = cfg.proxy.envVars;
 
     # The ‘ip-up’ target is started when we have IP connectivity.  So
     # services that depend on IP connectivity (like ntpd) should be
     # pulled in by this target.
     systemd.targets.ip-up.description = "Services Requiring IP Connectivity";
 
+    # This is needed when /etc/resolv.conf is being overriden by networkd
+    # and other configurations. If the file is destroyed by an environment
+    # activation then it must be rebuilt so that applications which interface
+    # with /etc/resolv.conf directly don't break.
+    system.activationScripts.resolvconf = stringAfter [ "etc" "tmpfs" "var" ]
+      ''
+        # Systemd resolved controls its own resolv.conf
+        rm -f /run/resolvconf/interfaces/systemd
+        ${optionalString config.services.resolved.enable ''
+          rm -rf /run/resolvconf/interfaces
+          mkdir -p /run/resolvconf/interfaces
+          ln -s /run/systemd/resolve/resolv.conf /run/resolvconf/interfaces/systemd
+        ''}
+
+        # Make sure resolv.conf is up to date if not managed by systemd
+        ${optionalString (!config.services.resolved.enable) ''
+          ${pkgs.openresolv}/bin/resolvconf -u
+        ''}
+      '';
+
   };
 
-}
+  }
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix
index f91dbb4cc281..47393c9d3f5c 100644
--- a/nixos/modules/config/no-x-libs.nix
+++ b/nixos/modules/config/no-x-libs.nix
@@ -24,7 +24,7 @@ with lib;
     programs.ssh.setXAuthLocation = false;
     security.pam.services.su.forwardXAuth = lib.mkForce false;
 
-    fonts.enableFontConfig = false;
+    fonts.fontconfig.enable = false;
 
     nixpkgs.config.packageOverrides = pkgs:
       { dbus = pkgs.dbus.override { useX11 = false; }; };
diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix
index 45695d9cb89f..549e731f3b08 100644
--- a/nixos/modules/config/nsswitch.nix
+++ b/nixos/modules/config/nsswitch.nix
@@ -35,29 +35,27 @@ in
 
   config = {
 
-    environment.etc =
-      [ # Name Service Switch configuration file.  Required by the C library.
-        # !!! Factor out the mdns stuff.  The avahi module should define
-        # an option used by this module.
-        { source = pkgs.writeText "nsswitch.conf"
-            ''
-              passwd:    files ldap
-              group:     files ldap
-              shadow:    files ldap
-              hosts:     files ${optionalString nssmdns "mdns_minimal [NOTFOUND=return]"} dns ${optionalString nssmdns "mdns"} ${optionalString nsswins "wins"} myhostname
-              networks:  files dns
-              ethers:    files
-              services:  files
-              protocols: files
-            '';
-          target = "nsswitch.conf";
-        }
-      ];
-
-    # Use nss-myhostname to ensure that our hostname always resolves to
-    # a valid IP address.  It returns all locally configured IP
-    # addresses, or ::1 and 127.0.0.2 as fallbacks.
-    system.nssModules = [ pkgs.systemd ];
+    # Name Service Switch configuration file.  Required by the C
+    # library.  !!! Factor out the mdns stuff.  The avahi module
+    # should define an option used by this module.
+    environment.etc."nsswitch.conf".text =
+      ''
+        passwd:    files ldap
+        group:     files ldap
+        shadow:    files ldap
+        hosts:     files ${optionalString nssmdns "mdns_minimal [NOTFOUND=return]"} dns ${optionalString nssmdns "mdns"} ${optionalString nsswins "wins"} myhostname mymachines
+        networks:  files dns
+        ethers:    files
+        services:  files
+        protocols: files
+      '';
+
+    # Systemd provides nss-myhostname to ensure that our hostname
+    # always resolves to a valid IP address.  It returns all locally
+    # configured IP addresses, or ::1 and 127.0.0.2 as
+    # fallbacks. Systemd also provides nss-mymachines to return IP
+    # addresses of local containers.
+    system.nssModules = [ config.systemd.package ];
 
   };
 }
diff --git a/nixos/modules/config/timezone.nix b/nixos/modules/config/timezone.nix
index c85922840770..068571393116 100644
--- a/nixos/modules/config/timezone.nix
+++ b/nixos/modules/config/timezone.nix
@@ -14,10 +14,14 @@ in
     time = {
 
       timeZone = mkOption {
-        default = "CET";
+        default = "UTC";
         type = types.str;
         example = "America/New_York";
-        description = "The time zone used when displaying times and dates.";
+        description = ''
+          The time zone used when displaying times and dates. See <link
+          xlink:href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"/>
+          for a comprehensive list of possible values for this setting.
+        '';
       };
 
       hardwareClockInLocalTime = mkOption {
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index 197b65e27c4b..d35ecb754bdb 100644
--- a/nixos/modules/config/update-users-groups.pl
+++ b/nixos/modules/config/update-users-groups.pl
@@ -6,6 +6,15 @@ use JSON;
 make_path("/var/lib/nixos", { mode => 0755 });
 
 
+sub hashPassword {
+    my ($password) = @_;
+    my $salt = "";
+    my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
+    $salt .= $chars[rand 64] for (1..8);
+    return crypt($password, '$6$' . $salt . '$');
+}
+
+
 # Functions for allocating free GIDs/UIDs. FIXME: respect ID ranges in
 # /etc/login.defs.
 sub allocId {
@@ -114,7 +123,7 @@ foreach my $g (@{$spec->{groups}}) {
 }
 
 # Update the persistent list of declarative groups.
-write_file($declGroupsFile, join(" ", sort(keys %groupsOut)));
+write_file($declGroupsFile, { binmode => ':utf8' }, join(" ", sort(keys %groupsOut)));
 
 # Merge in the existing /etc/group.
 foreach my $name (keys %groupsCur) {
@@ -131,7 +140,7 @@ foreach my $name (keys %groupsCur) {
 # Rewrite /etc/group. FIXME: acquire lock.
 my @lines = map { join(":", $_->{name}, $_->{password}, $_->{gid}, $_->{members}) . "\n" }
     (sort { $a->{gid} <=> $b->{gid} } values(%groupsOut));
-write_file("/etc/group.tmp", @lines);
+write_file("/etc/group.tmp", { binmode => ':utf8' }, @lines);
 rename("/etc/group.tmp", "/etc/group") or die;
 system("nscd --invalidate group");
 
@@ -160,6 +169,12 @@ foreach my $u (@{$spec->{users}}) {
     } else {
         $u->{uid} = allocUid($u->{isSystemUser}) if !defined $u->{uid};
 
+        if (defined $u->{initialPassword}) {
+            $u->{hashedPassword} = hashPassword($u->{initialPassword});
+        } 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};
@@ -174,6 +189,8 @@ foreach my $u (@{$spec->{users}}) {
         } else {
             warn "warning: password file ‘$u->{passwordFile}’ does not exist\n";
         }
+    } elsif (defined $u->{password}) {
+        $u->{hashedPassword} = hashPassword($u->{password});
     }
 
     $u->{fakePassword} = $existing->{fakePassword} // "x";
@@ -181,7 +198,7 @@ foreach my $u (@{$spec->{users}}) {
 }
 
 # Update the persistent list of declarative users.
-write_file($declUsersFile, join(" ", sort(keys %usersOut)));
+write_file($declUsersFile, { binmode => ':utf8' }, join(" ", sort(keys %usersOut)));
 
 # Merge in the existing /etc/passwd.
 foreach my $name (keys %usersCur) {
@@ -197,7 +214,7 @@ foreach my $name (keys %usersCur) {
 # Rewrite /etc/passwd. FIXME: acquire lock.
 @lines = map { join(":", $_->{name}, $_->{fakePassword}, $_->{uid}, $_->{gid}, $_->{description}, $_->{home}, $_->{shell}) . "\n" }
     (sort { $a->{uid} <=> $b->{uid} } (values %usersOut));
-write_file("/etc/passwd.tmp", @lines);
+write_file("/etc/passwd.tmp", { binmode => ':utf8' }, @lines);
 rename("/etc/passwd.tmp", "/etc/passwd") or die;
 system("nscd --invalidate passwd");
 
@@ -208,32 +225,22 @@ my %shadowSeen;
 
 foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow") : ()) {
     chomp $line;
-    my ($name, $password, @rest) = split(':', $line, -9);
+    my ($name, $hashedPassword, @rest) = split(':', $line, -9);
     my $u = $usersOut{$name};;
     next if !defined $u;
-    $password = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
-    push @shadowNew, join(":", $name, $password, @rest) . "\n";
+    $hashedPassword = "!" if !$spec->{mutableUsers};
+    $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
+    push @shadowNew, join(":", $name, $hashedPassword, @rest) . "\n";
     $shadowSeen{$name} = 1;
 }
 
 foreach my $u (values %usersOut) {
     next if defined $shadowSeen{$u->{name}};
-    my $password = "!";
-    $password = $u->{hashedPassword} if defined $u->{hashedPassword};
+    my $hashedPassword = "!";
+    $hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword};
     # FIXME: set correct value for sp_lstchg.
-    push @shadowNew, join(":", $u->{name}, $password, "1::::::") . "\n";
+    push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::::") . "\n";
 }
 
-write_file("/etc/shadow.tmp", { perms => 0600 }, @shadowNew);
+write_file("/etc/shadow.tmp", { binmode => ':utf8', perms => 0600 }, @shadowNew);
 rename("/etc/shadow.tmp", "/etc/shadow") or die;
-
-
-# Call chpasswd to apply password. FIXME: generate the hashes directly
-# and merge into the /etc/shadow updating above.
-foreach my $u (@{$spec->{users}}) {
-    if (defined $u->{password}) {
-        my $pid = open(PW, "| chpasswd") or die;
-        print PW "$u->{name}:$u->{password}\n";
-        close PW or die "unable to change password of user ‘$u->{name}’: $?\n";
-    }
-}
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 773f9b412afe..256c5888cb94 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -8,19 +8,19 @@ let
   cfg = config.users;
 
   passwordDescription = ''
-    The options <literal>hashedPassword</literal>,
-    <literal>password</literal> and <literal>passwordFile</literal>
+    The options <option>hashedPassword</option>,
+    <option>password</option> and <option>passwordFile</option>
     controls what password is set for the user.
-    <literal>hashedPassword</literal> overrides both
-    <literal>password</literal> and <literal>passwordFile</literal>.
-    <literal>password</literal> overrides <literal>passwordFile</literal>.
+    <option>hashedPassword</option> overrides both
+    <option>password</option> and <option>passwordFile</option>.
+    <option>password</option> overrides <option>passwordFile</option>.
     If none of these three options are set, no password is assigned to
     the user, and the user will not be able to do password logins.
-    If the option <literal>users.mutableUsers</literal> is true, the
+    If the option <option>users.mutableUsers</option> is true, the
     password defined in one of the three options will only be set when
     the user is created for the first time. After that, you are free to
     change the password with the ordinary user management commands. If
-    <literal>users.mutableUsers</literal> is false, you cannot change
+    <option>users.mutableUsers</option> is false, you cannot change
     user passwords, they will always be set according to the password
     options.
   '';
@@ -155,7 +155,7 @@ let
         default = false;
         description = ''
           If true, the user's shell will be set to
-          <literal>cfg.defaultUserShell</literal>.
+          <option>users.defaultUserShell</option>.
         '';
       };
 
@@ -163,7 +163,7 @@ let
         type = with types; uniq (nullOr str);
         default = null;
         description = ''
-          Specifies the (hashed) password for the user.
+          Specifies the hashed password for the user.
           ${passwordDescription}
         '';
       };
@@ -191,6 +191,37 @@ let
           ${passwordDescription}
         '';
       };
+
+      initialHashedPassword = mkOption {
+        type = with types; uniq (nullOr str);
+        default = null;
+        description = ''
+          Specifies the initial hashed password for the user, i.e. the
+          hashed password assigned if the user does not already
+          exist. If <option>users.mutableUsers</option> is true, the
+          password can be changed subsequently using the
+          <command>passwd</command> command. Otherwise, it's
+          equivalent to setting the <option>password</option> option.
+        '';
+      };
+
+      initialPassword = mkOption {
+        type = with types; uniq (nullOr str);
+        default = null;
+        description = ''
+          Specifies the initial password for the user, i.e. the
+          password assigned if the user does not already exist. If
+          <option>users.mutableUsers</option> is true, the password
+          can be changed subsequently using the
+          <command>passwd</command> command. Otherwise, it's
+          equivalent to setting the <option>password</option>
+          option. The same caveat applies: the password specified here
+          is world-readable in the Nix store, so it should only be
+          used for guest accounts or passwords that will be changed
+          promptly.
+        '';
+      };
+
     };
 
     config = mkMerge
@@ -204,6 +235,14 @@ let
           useDefaultShell = mkDefault true;
           isSystemUser = mkDefault false;
         })
+        # If !mutableUsers, setting ‘initialPassword’ is equivalent to
+        # setting ‘password’ (and similarly for hashed passwords).
+        (mkIf (!cfg.mutableUsers && config.initialPassword != null) {
+          password = mkDefault config.initialPassword;
+        })
+        (mkIf (!cfg.mutableUsers && config.initialHashedPassword != null) {
+          hashedPassword = mkDefault config.initialHashedPassword;
+        })
       ];
 
   };
@@ -306,7 +345,8 @@ let
     users = mapAttrsToList (n: u:
       { inherit (u)
           name uid group description home shell createHome isSystemUser
-          password passwordFile hashedPassword;
+          password passwordFile hashedPassword
+          initialPassword initialHashedPassword;
       }) cfg.extraUsers;
     groups = mapAttrsToList (n: g:
       { inherit (g) name gid;
@@ -386,24 +426,12 @@ in {
       options = [ groupOpts ];
     };
 
+    # FIXME: obsolete - will remove.
     security.initialRootPassword = mkOption {
       type = types.str;
       default = "!";
       example = "";
-      description = ''
-        The (hashed) password for the root account set on initial
-        installation. The empty string denotes that root can login
-        locally without a password (but not via remote services such
-        as SSH, or indirectly via <command>su</command> or
-        <command>sudo</command>). The string <literal>!</literal>
-        prevents root from logging in using a password.
-        Note that setting this option sets
-        <literal>users.extraUsers.root.hashedPassword</literal>.
-        Also, if <literal>users.mutableUsers</literal> is false
-        you cannot change the root password manually, so in that case
-        the name of this option is a bit misleading, since it will define
-        the root password beyond the user initialisation phase.
-      '';
+      visible = false;
     };
 
   };
@@ -421,7 +449,7 @@ in {
         shell = mkDefault cfg.defaultUserShell;
         group = "root";
         extraGroups = [ "grsecurity" ];
-        hashedPassword = mkDefault config.security.initialRootPassword;
+        initialHashedPassword = mkDefault config.security.initialRootPassword;
       };
       nobody = {
         uid = ids.uids.nobody;
diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix
index 3820a95b12e2..37a9f4d0d314 100644
--- a/nixos/modules/hardware/all-firmware.nix
+++ b/nixos/modules/hardware/all-firmware.nix
@@ -12,7 +12,8 @@ with lib;
       default = false;
       type = types.bool;
       description = ''
-        Turn on this option if you want to enable all the firmware shipped with Debian/Ubuntu.
+        Turn on this option if you want to enable all the firmware shipped with Debian/Ubuntu
+        and iwlwifi.
       '';
     };
 
@@ -22,7 +23,11 @@ with lib;
   ###### implementation
 
   config = mkIf config.hardware.enableAllFirmware {
-    hardware.firmware = [ "${pkgs.firmwareLinuxNonfree}/lib/firmware" ];
+    hardware.firmware = [
+      "${pkgs.firmwareLinuxNonfree}/lib/firmware"
+      "${pkgs.iwlegacy}/lib/firmware"
+      "${pkgs.iwlwifi}/lib/firmware"
+    ];
   };
 
 }
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index 1777c200dd11..7693bd5bb453 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -16,7 +16,6 @@ let
       [ p.mesa_drivers
         p.mesa_noglu # mainly for libGL
         (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc)
-        p.udev
       ];
   };
 
diff --git a/nixos/modules/hardware/video/bumblebee.nix b/nixos/modules/hardware/video/bumblebee.nix
index 52dea798f87a..7b48d9d1fcf5 100644
--- a/nixos/modules/hardware/video/bumblebee.nix
+++ b/nixos/modules/hardware/video/bumblebee.nix
@@ -30,7 +30,7 @@ with lib;
     boot.kernelModules = [ "bbswitch" ];
     boot.extraModulePackages = [ kernel.bbswitch kernel.nvidia_x11 ];
 
-    environment.systemPackages = [ pkgs.bumblebee ];
+    environment.systemPackages = [ pkgs.bumblebee pkgs.primus ];
 
     systemd.services.bumblebeed = {
       description = "Bumblebee Hybrid Graphics Switcher";
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 2b9221ec5d72..325aa5f093f8 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -11,7 +11,8 @@ let
   # FIXME: should introduce an option like
   # ‘hardware.video.nvidia.package’ for overriding the default NVIDIA
   # driver.
-  enabled = elem "nvidia" drivers || elem "nvidiaLegacy173" drivers || elem "nvidiaLegacy304" drivers;
+  enabled = elem "nvidia" drivers || elem "nvidiaLegacy173" drivers
+    || elem "nvidiaLegacy304" drivers || elem "nvidiaLegacy340" drivers;
 
   nvidia_x11 =
     if elem "nvidia" drivers then
@@ -20,6 +21,8 @@ let
       config.boot.kernelPackages.nvidia_x11_legacy173
     else if elem "nvidiaLegacy304" drivers then
       config.boot.kernelPackages.nvidia_x11_legacy304
+    else if elem "nvidiaLegacy340" drivers then
+      config.boot.kernelPackages.nvidia_x11_legacy340
     else throw "impossible";
 
 in
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
index 0a39e8dde9de..b723a91e4f35 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -45,6 +45,9 @@ with lib;
   # Add support for cow filesystems and their utilities
   boot.supportedFilesystems = [ "zfs" "btrfs" ];
 
+  # Configure host id for ZFS to work
+  networking.hostId = "8425e349";
+
   # Allow the user to log in as root without a password.
-  security.initialRootPassword = "";
+  users.extraUsers.root.initialHashedPassword = "";
 }
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix
index b1e1d16c610d..189cca9e23b9 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix
@@ -14,6 +14,10 @@ with lib;
   # Include gparted for partitioning disks
   environment.systemPackages = [ pkgs.gparted ];
   
+  # Provide networkmanager for easy wireless configuration.
+  networking.networkmanager.enable = true;
+  networking.wireless.enable = mkForce false;
+
   # KDE complains if power management is disabled (to be precise, if
   # there is no power management backend such as upower).
   powerManagement.enable = true;
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 22f31c460802..84de7800c2a9 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -176,7 +176,10 @@ in
     # UUID of the USB stick.  It would be nicer to write
     # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't
     # recognise that.
-    boot.kernelParams = [ "root=LABEL=${config.isoImage.volumeID}" ];
+    boot.kernelParams =
+      [ "root=LABEL=${config.isoImage.volumeID}"
+        "boot.shell_on_fail"
+      ];
 
     fileSystems."/" =
       { fsType = "tmpfs";
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
index 7d3346e4ea1f..bbf0311c04d6 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
+++ b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
@@ -76,7 +76,6 @@ in
       pkgs.ntfsprogs # for resizing NTFS partitions
       pkgs.btrfsProgs
       pkgs.jfsutils
-      pkgs.jfsrec
 
       # Some compression/archiver tools.
       pkgs.unzip
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt b/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt
index 8f0a8d355c6e..84252f292c54 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt
+++ b/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt
@@ -80,7 +80,7 @@ had booted this nixos. Run:
 *  `grep local-cmds run/current-system/init`
 
 Then you can proceed normally subscribing to a nixos channel:
-  nix-channel --add http://nixos.org/channels/nixos-unstable
+  nix-channel --add https://nixos.org/channels/nixos-unstable
   nix-channel --update
 
 Testing:
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index e8f100d64984..43a83e0206de 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -235,7 +235,7 @@ chomp $virt;
 # Check if we're a VirtualBox guest.  If so, enable the guest
 # additions.
 if ($virt eq "oracle") {
-    push @attrs, "services.virtualbox.enable = true;"
+    push @attrs, "services.virtualboxGuest.enable = true;"
 }
 
 
@@ -430,7 +430,7 @@ my $hwConfig = <<EOF;
 # Do not modify this file!  It was generated by ‘nixos-generate-config’
 # and may be overwritten by future invocations.  Please make changes
 # to /etc/nixos/configuration.nix instead.
-{ config, pkgs, ... }:
+{ config, lib, pkgs, ... }:
 
 {
   imports =${\multiLineList("    ", @imports)};
@@ -491,7 +491,7 @@ EOF
 
 $bootLoaderConfig
   # networking.hostName = "nixos"; # Define your hostname.
-  # networking.wireless.enable = true;  # Enables wireless.
+  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.
 
   # Select internationalisation properties.
   # i18n = {
@@ -500,6 +500,9 @@ $bootLoaderConfig
   #   defaultLocale = "en_US.UTF-8";
   # };
 
+  # Set your time zone.
+  # time.timeZone = "Europe/Amsterdam";
+
   # List packages installed in system profile. To search by name, run:
   # \$ nix-env -qaP | grep wget
   # environment.systemPackages = with pkgs; [
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index bd334c2a3cb4..9dfc322b9f74 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -30,8 +30,7 @@ while [ "$#" -gt 0 ]; do
     case "$i" in
         -I)
             given_path="$1"; shift 1
-            absolute_path=$(readlink -m $given_path)
-            extraBuildFlags+=("$i" "/mnt$absolute_path")
+            extraBuildFlags+=("$i" "$given_path")
             ;;
         --root)
             mountPoint="$1"; shift 1
@@ -89,6 +88,12 @@ ln -s /run $mountPoint/var/run
 rm -f $mountPoint/etc/{resolv.conf,hosts}
 cp -Lf /etc/resolv.conf /etc/hosts $mountPoint/etc/
 
+if [ -e "$SSL_CERT_FILE" ]; then
+    cp -Lf "$SSL_CERT_FILE" "$mountPoint/tmp/ca-cert.crt"
+    export SSL_CERT_FILE=/tmp/ca-cert.crt
+    # For Nix 1.7
+    export CURL_CA_BUNDLE=/tmp/ca-cert.crt
+fi
 
 if [ -n "$runChroot" ]; then
     if ! [ -L $mountPoint/nix/var/nix/profiles/system ]; then
@@ -244,7 +249,7 @@ chroot $mountPoint /nix/var/nix/profiles/system/activate
 
 
 # Ask the user to set a root password.
-if [ -t 0 ] ; then
+if [ "$(chroot $mountPoint nix-instantiate --eval '<nixos>' -A config.users.mutableUsers)" = true ] && [ -t 0 ] ; then
     echo "setting root password..."
     chroot $mountPoint /var/setuid-wrappers/passwd
 fi
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
index 96d09c3a6058..17c17d05e288 100644
--- a/nixos/modules/installer/tools/nixos-option.sh
+++ b/nixos/modules/installer/tools/nixos-option.sh
@@ -13,6 +13,7 @@ usage () {
 
 xml=false
 verbose=false
+nixPath=""
 
 option=""
 
@@ -26,6 +27,7 @@ for arg; do
         while test "$sarg" != "-"; do
           case $sarg in
             --*) longarg=$arg; sarg="--";;
+            -I) argfun="include_nixpath";;
             -*) usage;;
           esac
           # remove the first letter option
@@ -53,6 +55,9 @@ for arg; do
         var=$(echo $argfun | sed 's,^set_,,')
         eval $var=$arg
         ;;
+      include_nixpath)
+        nixPath="-I $arg $nixPath"
+        ;;
     esac
     argfun=""
   fi
@@ -69,18 +74,114 @@ fi
 #############################
 
 evalNix(){
-  nix-instantiate - --eval-only "$@"
+  result=$(nix-instantiate ${nixPath:+$nixPath} - --eval-only "$@" 2>&1)
+  if test $? -eq 0; then
+      cat <<EOF
+$result
+EOF
+      return 0;
+  else
+      sed -n '
+  /^error/ { s/, at (string):[0-9]*:[0-9]*//; p; };
+  /^warning: Nix search path/ { p; };
+' <<EOF
+$result
+EOF
+      return 1;
+  fi
+}
+
+header="let
+  nixos = import <nixpkgs/nixos> {};
+  nixpkgs = import <nixpkgs> {};
+in with nixpkgs.lib;
+"
+
+# This function is used for converting the option definition path given by
+# the user into accessors for reaching the definition and the declaration
+# corresponding to this option.
+generateAccessors(){
+  if result=$(evalNix --strict --show-trace <<EOF
+$header
+
+let
+  path = "${option:+$option}";
+  pathList = splitString "." path;
+
+  walkOptions = attrsNames: result:
+    if attrsNames == [] then
+      result
+    else
+      let name = head attrsNames; rest = tail attrsNames; in
+      if isOption result.options then
+        walkOptions rest {
+          options = result.options.type.getSubOptions "";
+          opt = ''(\${result.opt}.type.getSubOptions "")'';
+          cfg = ''\${result.cfg}."\${name}"'';
+        }
+      else
+        walkOptions rest {
+          options = result.options.\${name};
+          opt = ''\${result.opt}."\${name}"'';
+          cfg = ''\${result.cfg}."\${name}"'';
+        }
+    ;
+
+  walkResult = (if path == "" then x: x else walkOptions pathList) {
+    options = nixos.options;
+    opt = ''nixos.options'';
+    cfg = ''nixos.config'';
+  };
+
+in
+  ''let option = \${walkResult.opt}; config = \${walkResult.cfg}; in''
+EOF
+)
+  then
+      echo $result
+  else
+      # In case of error we want to ignore the error message roduced by the
+      # script above, as it is iterating over each attribute, which does not
+      # produce a nice error message.  The following code is a fallback
+      # solution which is cause a nicer error message in the next
+      # evaluation.
+      echo "\"let option = nixos.options${option:+.$option}; config = nixos.config${option:+.$option}; in\""
+  fi
 }
 
+header="$header
+$(eval echo $(generateAccessors))
+"
+
 evalAttr(){
   local prefix="$1"
   local strict="$2"
   local suffix="$3"
-  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" | evalNix ${strict:+--strict}
+
+  # If strict is set, then set it to "true".
+  test -n "$strict" && strict=true
+
+  evalNix ${strict:+--strict} <<EOF
+$header
+
+let
+  value = $prefix${suffix:+.$suffix};
+  strict = ${strict:-false};
+  cleanOutput = x: with nixpkgs.lib;
+    if isDerivation x then x.outPath
+    else if isFunction x then "<CODE>"
+    else if strict then
+      if isAttrs x then mapAttrs (n: cleanOutput) x
+      else if isList x then map cleanOutput x
+      else x
+    else x;
+in
+  cleanOutput value
+EOF
 }
 
 evalOpt(){
-  evalAttr "options" "" "$@"
+  evalAttr "option" "" "$@"
 }
 
 evalCfg(){
@@ -90,8 +191,11 @@ evalCfg(){
 
 findSources(){
   local suffix=$1
-  echo "(import <nixos> {}).options${option:+.$option}.$suffix" |
-    evalNix --strict
+  evalNix --strict <<EOF
+$header
+
+option.$suffix
+EOF
 }
 
 # Given a result from nix-instantiate, recover the list of attributes it
@@ -121,13 +225,12 @@ nixMap() {
 # the output of nixos-option with other tools such as nixos-gui.
 if $xml; then
   evalNix --xml --no-location <<EOF
+$header
+
 let
-  reach = attrs: attrs${option:+.$option};
-  nixos = import <nixos> {};
-  nixpkgs = import <nixpkgs> {};
   sources = builtins.map (f: f.source);
-  opt = reach nixos.options;
-  cfg = reach nixos.config;
+  opt = option;
+  cfg = config;
 in
 
 with nixpkgs.lib;
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 5daa9ff9457c..93f258f54e3e 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -156,7 +156,7 @@ if [ -n "$buildNix" ]; then
                     exit 1
                 fi
                 if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \
-                    --option extra-binary-caches http://cache.nixos.org/; then
+                    --option extra-binary-caches https://cache.nixos.org/; then
                     echo "warning: don't know how to get latest Nix" >&2
                 fi
                 # Older version of nix-store -r don't support --add-root.
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 22997b7a159f..bf8365e34645 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -157,6 +157,23 @@
       redmine = 147;
       seeks = 148;
       prosody = 149;
+      i2pd = 150;
+      dnscrypt-proxy = 151;
+      systemd-network = 152;
+      systemd-resolve = 153;
+      systemd-timesync = 154;
+      liquidsoap = 155;
+      etcd = 156;
+      docker-registry = 157;
+      hbase = 158;
+      opentsdb = 159;
+      scollector = 160;
+      bosun = 161;
+      kubernetes = 162;
+      peerflix = 163;
+      chronos = 164;
+      gitlab = 165;
+      tox-bootstrapd = 166;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -197,6 +214,7 @@
       privoxy = 32;
       disnix = 33;
       osgi = 34;
+      tor = 35;
       ghostOne = 40;
       git = 41;
       fourstore = 42;
@@ -276,11 +294,23 @@
       mlmmj = 135;
       riemann = 137;
       riemanndash = 138;
+      hbase = 139;
+      opentsdb = 140;
       uhub = 142;
       mailpile = 146;
       redmine = 147;
       seeks = 148;
       prosody = 149;
+      i2pd = 150;
+      systemd-network = 152;
+      systemd-resolve = 153;
+      systemd-timesync = 154;
+      liquidsoap = 155;
+      scollector = 156;
+      bosun = 157;
+      kubernetes = 158;
+      fleet = 159;
+      gitlab = 160;
 
       # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399!
 
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index f4271cea853b..5afdcf214f27 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -53,7 +53,7 @@ with lib;
       mkDefault (if pathExists fn then readFile fn else "master");
 
     # Note: code names must only increase in alphabetical order.
-    system.nixosCodeName = "Caterpillar";
+    system.nixosCodeName = "Dingo";
 
     # Generate /etc/os-release.  See
     # http://0pointer.de/public/systemd-man/os-release.html for the
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index d65691c43790..2c52ebb37bcb 100755
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1,6 +1,7 @@
 [
   ./config/fonts/corefonts.nix
   ./config/fonts/fontconfig.nix
+  ./config/fonts/fontconfig-ultimate.nix
   ./config/fonts/fontdir.nix
   ./config/fonts/fonts.nix
   ./config/fonts/ghostscript.nix
@@ -58,6 +59,7 @@
   ./programs/dconf.nix
   ./programs/environment.nix
   ./programs/info.nix
+  ./programs/light.nix
   ./programs/nano.nix
   ./programs/screen.nix
   ./programs/shadow.nix
@@ -66,6 +68,7 @@
   ./programs/ssmtp.nix
   ./programs/uim.nix
   ./programs/venus.nix
+  ./programs/virtualbox-host.nix
   ./programs/wvdial.nix
   ./programs/freetds.nix
   ./programs/zsh/zsh.nix
@@ -88,15 +91,19 @@
   ./services/audio/alsa.nix
   # Disabled as fuppes it does no longer builds.
   # ./services/audio/fuppes.nix
+  ./services/audio/liquidsoap.nix
   ./services/audio/mpd.nix
   ./services/audio/mopidy.nix
   ./services/backup/almir.nix
   ./services/backup/bacula.nix
+  ./services/backup/crashplan.nix
   ./services/backup/mysql-backup.nix
   ./services/backup/postgresql-backup.nix
   ./services/backup/rsnapshot.nix
   ./services/backup/sitecopy-backup.nix
   ./services/backup/tarsnap.nix
+  ./services/cluster/fleet.nix
+  ./services/cluster/kubernetes.nix
   ./services/computing/torque/server.nix
   ./services/computing/torque/mom.nix
   ./services/continuous-integration/jenkins/default.nix
@@ -105,13 +112,15 @@
   ./services/databases/4store.nix
   ./services/databases/couchdb.nix
   ./services/databases/firebird.nix
+  ./services/databases/hbase.nix
   ./services/databases/influxdb.nix
   ./services/databases/memcached.nix
   ./services/databases/monetdb.nix
   ./services/databases/mongodb.nix
   ./services/databases/mysql.nix
-  ./services/databases/neo4j.nix 
+  ./services/databases/neo4j.nix
   ./services/databases/openldap.nix
+  ./services/databases/opentsdb.nix
   ./services/databases/postgresql.nix
   ./services/databases/redis.nix
   ./services/databases/virtuoso.nix
@@ -128,6 +137,7 @@
   ./services/desktops/gnome3/seahorse.nix
   ./services/desktops/gnome3/sushi.nix
   ./services/desktops/gnome3/tracker.nix
+  ./services/desktops/profile-sync-daemon.nix
   ./services/desktops/telepathy.nix
   ./services/games/ghost-one.nix
   ./services/games/minecraft-server.nix
@@ -163,8 +173,11 @@
   ./services/misc/cgminer.nix
   ./services/misc/dictd.nix
   ./services/misc/disnix.nix
+  ./services/misc/docker-registry.nix
+  ./services/misc/etcd.nix
   ./services/misc/felix.nix
   ./services/misc/folding-at-home.nix
+  ./services/misc/gitlab.nix
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
   ./services/misc/mesos-master.nix
@@ -183,6 +196,7 @@
   ./services/misc/uhub.nix
   ./services/misc/zookeeper.nix
   ./services/monitoring/apcupsd.nix
+  ./services/monitoring/bosun.nix
   ./services/monitoring/collectd.nix
   ./services/monitoring/dd-agent.nix
   ./services/monitoring/graphite.nix
@@ -191,6 +205,7 @@
   ./services/monitoring/nagios.nix
   ./services/monitoring/riemann.nix
   ./services/monitoring/riemann-dash.nix
+  ./services/monitoring/scollector.nix
   ./services/monitoring/smartd.nix
   ./services/monitoring/statsd.nix
   ./services/monitoring/systemhealth.nix
@@ -219,6 +234,7 @@
   ./services/networking/ddclient.nix
   ./services/networking/dhcpcd.nix
   ./services/networking/dhcpd.nix
+  ./services/networking/dnscrypt-proxy.nix
   ./services/networking/dnsmasq.nix
   ./services/networking/ejabberd.nix
   ./services/networking/firewall.nix
@@ -230,6 +246,7 @@
   ./services/networking/gvpe.nix
   ./services/networking/haproxy.nix
   ./services/networking/hostapd.nix
+  ./services/networking/i2pd.nix
   ./services/networking/ifplugd.nix
   ./services/networking/iodined.nix
   ./services/networking/ircd-hybrid/default.nix
@@ -263,11 +280,13 @@
   ./services/networking/spiped.nix
   ./services/networking/ssh/lshd.nix
   ./services/networking/ssh/sshd.nix
+  ./services/networking/strongswan.nix
   ./services/networking/supybot.nix
   ./services/networking/syncthing.nix
   ./services/networking/tcpcrypt.nix
   ./services/networking/teamspeak3.nix
   ./services/networking/tftpd.nix
+  ./services/networking/tox-bootstrapd.nix
   ./services/networking/unbound.nix
   ./services/networking/unifi.nix
   ./services/networking/vsftpd.nix
@@ -279,6 +298,7 @@
   ./services/networking/znc.nix
   ./services/printing/cupsd.nix
   ./services/scheduling/atd.nix
+  ./services/scheduling/chronos.nix
   ./services/scheduling/cron.nix
   ./services/scheduling/fcron.nix
   ./services/search/elasticsearch.nix
@@ -291,11 +311,13 @@
   ./services/security/torify.nix
   ./services/security/tor.nix
   ./services/security/torsocks.nix
+  ./services/system/cloud-init.nix
   ./services/system/dbus.nix
   ./services/system/kerberos.nix
   ./services/system/nscd.nix
   ./services/system/uptimed.nix
   ./services/torrent/deluge.nix
+  ./services/torrent/peerflix.nix
   ./services/torrent/transmission.nix
   ./services/ttys/agetty.nix
   ./services/ttys/gpm.nix
@@ -344,6 +366,7 @@
   ./system/boot/loader/efi.nix
   ./system/boot/loader/generations-dir/generations-dir.nix
   ./system/boot/loader/grub/grub.nix
+  ./system/boot/loader/grub/ipxe.nix
   ./system/boot/loader/grub/memtest.nix
   ./system/boot/loader/gummiboot/gummiboot.nix
   ./system/boot/loader/init-script/init-script.nix
@@ -357,6 +380,7 @@
   ./system/boot/tmp.nix
   ./system/etc/etc.nix
   ./system/upstart/upstart.nix
+  ./tasks/bcache.nix
   ./tasks/cpu-freq.nix
   ./tasks/encrypted-devices.nix
   ./tasks/filesystems.nix
@@ -374,6 +398,8 @@
   ./tasks/kbd.nix
   ./tasks/lvm.nix
   ./tasks/network-interfaces.nix
+  ./tasks/network-interfaces-systemd.nix
+  ./tasks/network-interfaces-scripted.nix
   ./tasks/scsi-link-power-management.nix
   ./tasks/swraid.nix
   ./tasks/trackpoint.nix
@@ -382,8 +408,10 @@
   ./virtualisation/containers.nix
   ./virtualisation/docker.nix
   ./virtualisation/libvirtd.nix
+  ./virtualisation/lxc.nix
   #./virtualisation/nova.nix
   ./virtualisation/openvswitch.nix
+  ./virtualisation/parallels-guest.nix
   ./virtualisation/virtualbox-guest.nix
   #./virtualisation/xen-dom0.nix
 ]
diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix
index 7a6f76572058..3d1412b56859 100644
--- a/nixos/modules/profiles/base.nix
+++ b/nixos/modules/profiles/base.nix
@@ -34,7 +34,6 @@
     pkgs.xfsprogs
     pkgs.jfsutils
     pkgs.f2fs-tools
-    #pkgs.jfsrec # disabled because of Boost dependency
 
     # Some compression/archiver tools.
     pkgs.unzip
diff --git a/nixos/modules/profiles/container.nix b/nixos/modules/profiles/container.nix
new file mode 100644
index 000000000000..dd2e6579a932
--- /dev/null
+++ b/nixos/modules/profiles/container.nix
@@ -0,0 +1,56 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
+
+in {
+  # Docker image config.
+  imports = [
+    ../installer/cd-dvd/channel.nix
+    ./minimal.nix
+    ./clone-config.nix
+  ];
+
+  # Create the tarball
+  system.build.tarball = import ../../lib/make-system-tarball.nix {
+    inherit (pkgs) stdenv perl xz pathsFromGraph;
+
+    contents = [];
+    extraArgs = "--owner=0";
+
+    # Add init script to image
+    storeContents = [
+      { object = config.system.build.toplevel + "/init";
+        symlink = "/init";
+      }
+    ] ++ (pkgs2storeContents [ pkgs.stdenv ]);
+
+    # Some container managers like lxc need these
+    extraCommands = "mkdir -p proc sys dev";
+  };
+
+  boot.isContainer = true;
+  boot.postBootCommands =
+    ''
+      # After booting, register the contents of the Nix store in the Nix
+      # database.
+      if [ -f /nix-path-registration ]; then
+        ${config.nix.package}/bin/nix-store --load-db < /nix-path-registration &&
+        rm /nix-path-registration
+      fi
+
+      # nixos-rebuild also requires a "system" profile
+      ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+    '';
+
+  # Disable some features that are not useful in a container.
+  sound.enable = mkDefault false;
+  services.udisks2.enable = mkDefault false;
+
+  # Install new init script
+  system.activationScripts.installInitScript = ''
+    ln -fs $systemConfig/init /init
+  '';
+}
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index d79aff5dc553..a5ec387df647 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -40,7 +40,6 @@ in
     # TODO: move most of these elsewhere
     environment.profileRelativeEnvVars =
       { PATH = [ "/bin" "/sbin" "/lib/kde4/libexec" ];
-        MANPATH = [ "/man" "/share/man" ];
         INFOPATH = [ "/info" "/share/info" ];
         PKG_CONFIG_PATH = [ "/lib/pkgconfig" ];
         TERMINFO_DIRS = [ "/share/terminfo" ];
diff --git a/nixos/modules/programs/light.nix b/nixos/modules/programs/light.nix
new file mode 100644
index 000000000000..09cd1113d9c7
--- /dev/null
+++ b/nixos/modules/programs/light.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.light;
+
+in
+{
+  options = {
+    programs.light = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to install Light backlight control with setuid wrapper.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.light ];
+    security.setuidPrograms = [ "light" ];
+  };
+}
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index ee9cb81a027f..796740ea636a 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -59,6 +59,15 @@ in
         '';
       };
 
+      agentTimeout = mkOption {
+        type = types.nullOr types.string;
+        default = null;
+        example = "1h";
+        description = ''
+          How long to keep the private keys in memory. Use null to keep them forever.
+        '';
+      };
+
       package = mkOption {
         default = pkgs.openssh;
         description = ''
@@ -99,7 +108,10 @@ in
         wantedBy = [ "default.target" ];
         serviceConfig =
           { ExecStartPre = "${pkgs.coreutils}/bin/rm -f %t/ssh-agent";
-            ExecStart = "${cfg.package}/bin/ssh-agent -a %t/ssh-agent";
+            ExecStart =
+                "${cfg.package}/bin/ssh-agent " +
+                optionalString (cfg.agentTimeout != null) ("-t ${cfg.agentTimeout} ") +
+                "-a %t/ssh-agent";
             StandardOutput = "null";
             Type = "forking";
             Restart = "on-failure";
diff --git a/nixos/modules/programs/ssmtp.nix b/nixos/modules/programs/ssmtp.nix
index 34eafd4fa846..7b00efbb4686 100644
--- a/nixos/modules/programs/ssmtp.nix
+++ b/nixos/modules/programs/ssmtp.nix
@@ -20,6 +20,7 @@ in
     networking.defaultMailServer = {
 
       directDelivery = mkOption {
+        type = types.bool;
         default = false;
         example = true;
         description = ''
@@ -35,6 +36,7 @@ in
       };
 
       hostName = mkOption {
+        type = types.str;
         example = "mail.example.org";
         description = ''
           The host name of the default mail server to use to deliver
@@ -42,7 +44,17 @@ in
         '';
       };
 
+      root = mkOption {
+        type = types.str;
+        default = "";
+        example = "root@example.org";
+        description = ''
+          The e-mail to which mail for users with UID &lt; 1000 is forwarded.
+        '';
+      };
+
       domain = mkOption {
+        type = types.str;
         default = "";
         example = "example.org";
         description = ''
@@ -51,6 +63,7 @@ in
       };
 
       useTLS = mkOption {
+        type = types.bool;
         default = false;
         example = true;
         description = ''
@@ -60,6 +73,7 @@ in
       };
 
       useSTARTTLS = mkOption {
+        type = types.bool;
         default = false;
         example = true;
         description = ''
@@ -70,6 +84,7 @@ in
       };
 
       authUser = mkOption {
+        type = types.str;
         default = "";
         example = "foo@example.org";
         description = ''
@@ -78,6 +93,7 @@ in
       };
 
       authPass = mkOption {
+        type = types.str;
         default = "";
         example = "correctHorseBatteryStaple";
         description = ''
@@ -96,6 +112,7 @@ in
       ''
         MailHub=${cfg.hostName}
         FromLineOverride=YES
+        ${if cfg.root != "" then "root=${cfg.root}" else ""}
         ${if cfg.domain != "" then "rewriteDomain=${cfg.domain}" else ""}
         UseTLS=${if cfg.useTLS then "YES" else "NO"}
         UseSTARTTLS=${if cfg.useSTARTTLS then "YES" else "NO"}
diff --git a/nixos/modules/programs/virtualbox-host.nix b/nixos/modules/programs/virtualbox-host.nix
new file mode 100644
index 000000000000..fc113a08a356
--- /dev/null
+++ b/nixos/modules/programs/virtualbox-host.nix
@@ -0,0 +1,115 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.virtualboxHost;
+  virtualbox = config.boot.kernelPackages.virtualbox.override {
+    inherit (cfg) enableHardening;
+  };
+
+in
+
+{
+  options.services.virtualboxHost = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable host-side support for VirtualBox.
+
+        <note><para>
+          In order to pass USB devices from the host to the guests, the user
+          needs to be in the <literal>vboxusers</literal> group.
+        </para></note>
+      '';
+    };
+
+    addNetworkInterface = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Automatically set up a vboxnet0 host-only network interface.
+      '';
+    };
+
+    enableHardening = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Enable hardened VirtualBox, which ensures that only the binaries in the
+        system path get access to the devices exposed by the kernel modules
+        instead of all users in the vboxusers group.
+
+        <important><para>
+          Disabling this can put your system's security at risk, as local users
+          in the vboxusers group can tamper with the VirtualBox device files.
+        </para></important>
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable (mkMerge [{
+    boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ];
+    boot.extraModulePackages = [ virtualbox ];
+    environment.systemPackages = [ virtualbox ];
+
+    security.setuidOwners = let
+      mkSuid = program: {
+        inherit program;
+        source = "${virtualbox}/libexec/virtualbox/${program}";
+        owner = "root";
+        group = "vboxusers";
+        setuid = true;
+      };
+    in mkIf cfg.enableHardening (map mkSuid [
+      "VBoxHeadless"
+      "VBoxNetAdpCtl"
+      "VBoxNetDHCP"
+      "VBoxNetNAT"
+      "VBoxSDL"
+      "VBoxVolInfo"
+      "VirtualBox"
+    ]);
+
+    users.extraGroups.vboxusers.gid = config.ids.gids.vboxusers;
+
+    services.udev.extraRules =
+      ''
+        KERNEL=="vboxdrv",    OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
+        KERNEL=="vboxdrvu",   OWNER="root", GROUP="root",      MODE="0666", TAG+="systemd"
+        KERNEL=="vboxnetctl", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
+        SUBSYSTEM=="usb_device", ACTION=="add", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
+        SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
+        SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
+        SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
+      '';
+
+    # Since we lack the right setuid binaries, set up a host-only network by default.
+  } (mkIf cfg.addNetworkInterface {
+    systemd.services."vboxnet0" =
+      { description = "VirtualBox vboxnet0 Interface";
+        requires = [ "dev-vboxnetctl.device" ];
+        after = [ "dev-vboxnetctl.device" ];
+        wantedBy = [ "network.target" "sys-subsystem-net-devices-vboxnet0.device" ];
+        path = [ virtualbox ];
+        serviceConfig.RemainAfterExit = true;
+        serviceConfig.Type = "oneshot";
+        serviceConfig.PrivateTmp = true;
+        environment.VBOX_USER_HOME = "/tmp";
+        script =
+          ''
+            if ! [ -e /sys/class/net/vboxnet0 ]; then
+              VBoxManage hostonlyif create
+              cat /tmp/VBoxSVC.log >&2
+            fi
+          '';
+        postStop =
+          ''
+            VBoxManage hostonlyif remove vboxnet0
+          '';
+      };
+
+    networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ];
+  })]);
+}
diff --git a/nixos/modules/programs/virtualbox.nix b/nixos/modules/programs/virtualbox.nix
index 1a190573e943..a00b1e5f64d0 100644
--- a/nixos/modules/programs/virtualbox.nix
+++ b/nixos/modules/programs/virtualbox.nix
@@ -1,48 +1,8 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let virtualbox = config.boot.kernelPackages.virtualbox; in
-
-{
-  boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ];
-  boot.extraModulePackages = [ virtualbox ];
-  environment.systemPackages = [ virtualbox ];
-
-  users.extraGroups.vboxusers.gid = config.ids.gids.vboxusers;
-
-  services.udev.extraRules =
-    ''
-      KERNEL=="vboxdrv",    OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
-      KERNEL=="vboxdrvu",   OWNER="root", GROUP="root",      MODE="0666", TAG+="systemd"
-      KERNEL=="vboxnetctl", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
-      SUBSYSTEM=="usb_device", ACTION=="add", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
-      SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
-      SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
-      SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
-    '';
-
-  # Since we lack the right setuid binaries, set up a host-only network by default.
-
-  systemd.services."vboxnet0" =
-    { description = "VirtualBox vboxnet0 Interface";
-      requires = [ "dev-vboxnetctl.device" ];
-      after = [ "dev-vboxnetctl.device" ];
-      wantedBy = [ "network.target" "sys-subsystem-net-devices-vboxnet0.device" ];
-      path = [ virtualbox ];
-      serviceConfig.RemainAfterExit = true;
-      serviceConfig.Type = "oneshot";
-      script =
-        ''
-          if ! [ -e /sys/class/net/vboxnet0 ]; then
-            VBoxManage hostonlyif create
-          fi
-        '';
-      postStop =
-        ''
-          VBoxManage hostonlyif remove vboxnet0
-        '';
-    };
-
-  networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ];
+let
+  msg = "Importing <nixpkgs/nixos/modules/programs/virtualbox.nix> is "
+      + "deprecated, please use `services.virtualboxHost.enable = true' "
+      + "instead.";
+in {
+  config.warnings = [ msg ];
+  config.services.virtualboxHost.enable = true;
 }
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 073a22207652..cb1b92e78d62 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -74,6 +74,7 @@ in zipModules ([]
 ++ obsolete [ "environment" "x11Packages" ] [ "environment" "systemPackages" ]
 ++ obsolete [ "environment" "enableBashCompletion" ] [ "programs" "bash" "enableCompletion" ]
 ++ obsolete [ "environment" "nix" ] [ "nix" "package" ]
+++ obsolete [ "fonts" "enableFontConfig" ] [ "fonts" "fontconfig" "enable" ]
 ++ obsolete [ "fonts" "extraFonts" ] [ "fonts" "fonts" ]
 
 ++ obsolete [ "security" "extraSetuidPrograms" ] [ "security" "setuidPrograms" ]
@@ -107,6 +108,12 @@ in zipModules ([]
 ++ obsolete [ "services" "xserver" "startOpenSSHAgent" ] [ "programs" "ssh" "startAgent" ]
 ++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "xbmc" ]
 
+# VirtualBox
+++ obsolete [ "services" "virtualbox" "enable" ] [ "services" "virtualboxGuest" "enable" ]
+
+# proxy
+++ obsolete [ "nix" "proxy" ] [ "networking" "proxy" "default" ]
+
 # KDE
 ++ deprecated [ "kde" "extraPackages" ] [ "environment" "kdePackages" ]
 # ++ obsolete [ "environment" "kdePackages" ] [ "environment" "systemPackages" ] # !!! doesn't work!
@@ -131,5 +138,6 @@ in zipModules ([]
 ++ obsolete' [ "programs" "bash" "enable" ]
 ++ obsolete' [ "services" "samba" "defaultShare" ]
 ++ obsolete' [ "services" "syslog-ng" "serviceName" ]
+++ obsolete' [ "services" "syslog-ng" "listenToJournal" ]
 
 )
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index 8e653cd42847..f430a5a6339f 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -16,6 +16,7 @@ with lib;
       { SSL_CERT_FILE          = "/etc/ssl/certs/ca-bundle.crt";
         # FIXME: unneeded - remove eventually.
         OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+        # FIXME: unneeded - remove eventually.
         GIT_SSL_CAINFO         = "/etc/ssl/certs/ca-bundle.crt";
       };
 
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index 3773d822b16b..cbad94007088 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -226,8 +226,8 @@ in
       [ { assertion = cfg.stable || cfg.testing;
           message   = ''
             If grsecurity is enabled, you must select either the
-            stable patch (with kernel 3.2), or the testing patch (with
-            kernel 3.13) to continue.
+            stable patch (with kernel 3.14), or the testing patch (with
+            kernel 3.17) to continue.
           '';
         }
         { assertion = (cfg.stable -> !cfg.testing) || (cfg.testing -> !cfg.stable);
diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix
index cbd1628caaec..d42a8c7f7d29 100644
--- a/nixos/modules/security/sudo.nix
+++ b/nixos/modules/security/sudo.nix
@@ -46,6 +46,14 @@ in
           <filename>sudoers</filename> file.
         '';
     };
+
+    security.sudo.extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      description = ''
+        Extra configuration text appended to <filename>sudoers</filename>.
+      '';
+    };
   };
 
 
@@ -55,7 +63,8 @@ in
 
     security.sudo.configFile =
       ''
-        # Don't edit this file. Set the NixOS option ‘security.sudo.configFile’ instead.
+        # Don't edit this file. Set the NixOS options ‘security.sudo.configFile’
+        # or ‘security.sudo.extraConfig’ instead.
 
         # Environment variables to keep for root and %wheel.
         Defaults:root,%wheel env_keep+=TERMINFO_DIRS
@@ -69,6 +78,7 @@ in
 
         # Users in the "wheel" group can do anything.
         %wheel      ALL=(ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL
+        ${cfg.extraConfig}
       '';
 
     security.setuidPrograms = [ "sudo" "sudoedit" ];
@@ -80,11 +90,10 @@ in
     environment.etc = singleton
       { source =
           pkgs.runCommand "sudoers"
-	  {src = pkgs.writeText "sudoers-in" cfg.configFile; }
+          { src = pkgs.writeText "sudoers-in" cfg.configFile; }
           # Make sure that the sudoers file is syntactically valid.
           # (currently disabled - NIXOS-66)
-          "${pkgs.sudo}/sbin/visudo -f $src -c &&
-	      cp $src $out";
+          "${pkgs.sudo}/sbin/visudo -f $src -c && cp $src $out";
         target = "sudoers";
         mode = "0440";
       };
diff --git a/nixos/modules/services/audio/liquidsoap.nix b/nixos/modules/services/audio/liquidsoap.nix
new file mode 100644
index 000000000000..bf67d2399ebb
--- /dev/null
+++ b/nixos/modules/services/audio/liquidsoap.nix
@@ -0,0 +1,74 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  streams = builtins.attrNames config.services.liquidsoap.streams;
+
+  streamService =
+    name:
+    let stream = builtins.getAttr name config.services.liquidsoap.streams; in
+    { inherit name;
+      value = {
+        after = [ "network-online.target" "sound.target" ];
+        description = "${name} liquidsoap stream";
+        wantedBy = [ "multi-user.target" ];
+        path = [ pkgs.wget ];
+        preStart =
+          ''
+            mkdir -p /var/log/liquidsoap
+            chown liquidsoap -R /var/log/liquidsoap
+          '';
+        serviceConfig = {
+          PermissionsStartOnly="true";
+          ExecStart = "${pkgs.liquidsoap}/bin/liquidsoap ${stream}";
+          User = "liquidsoap";
+        };
+      };
+    };
+in
+{
+
+  ##### interface
+
+  options = {
+
+    services.liquidsoap.streams = mkOption {
+
+      description =
+        ''
+          Set of Liquidsoap streams to start,
+          one systemd service per stream.
+        '';
+
+      default = {};
+
+      example = {
+        myStream1 = literalExample "\"/etc/liquidsoap/myStream1.liq\"";
+        myStream2 = literalExample "./myStream2.liq";
+        myStream3 = literalExample "\"out(playlist(\"/srv/music/\"))\"";
+      };
+
+      type = types.attrsOf (types.either types.path types.str);
+    };
+
+  };
+  ##### implementation
+
+  config = mkIf (builtins.length streams != 0) {
+
+    users.extraUsers.liquidsoap = {
+      uid = config.ids.uids.liquidsoap;
+      group = "liquidsoap";
+      extraGroups = [ "audio" ];
+      description = "Liquidsoap streaming user";
+      home = "/var/lib/liquidsoap";
+      createHome = true;
+    };
+
+    users.extraGroups.liquidsoap.gid = config.ids.gids.liquidsoap;
+
+    systemd.services = builtins.listToAttrs ( map streamService streams );
+  };
+
+}
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index e6b525c4b1ba..eab7993387de 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -15,7 +15,6 @@ let
     state_file          "${cfg.dataDir}/state"
     sticker_file        "${cfg.dataDir}/sticker.sql"
     log_file            "syslog"
-    user                "mpd"
     ${if cfg.network.host != "any" then
    "bind_to_address     ${cfg.network.host}" else ""}
     ${if cfg.network.port != 6600 then
@@ -99,6 +98,9 @@ in {
       path = [ pkgs.mpd ];
       preStart = "mkdir -p ${cfg.dataDir} && chown -R mpd:mpd  ${cfg.dataDir}";
       script = "exec mpd --no-daemon ${mpdConf}";
+      serviceConfig = {
+        User = "mpd";
+      };
     };
 
     users.extraUsers.mpd = {
diff --git a/nixos/modules/services/backup/almir.nix b/nixos/modules/services/backup/almir.nix
index 5ce215c5c4b5..ec39a997028a 100644
--- a/nixos/modules/services/backup/almir.nix
+++ b/nixos/modules/services/backup/almir.nix
@@ -109,6 +109,7 @@ in {
       };
 
       sqlalchemy_engine_url = mkOption {
+        default = "postgresql:///bacula";
         example = ''
           postgresql://bacula:bacula@localhost:5432/bacula
           mysql+mysqlconnector://<user>:<password>@<hostname>/<database>'
diff --git a/nixos/modules/services/backup/crashplan.nix b/nixos/modules/services/backup/crashplan.nix
new file mode 100644
index 000000000000..74643d1d4635
--- /dev/null
+++ b/nixos/modules/services/backup/crashplan.nix
@@ -0,0 +1,63 @@
+{ config, pkgs, lib, ... }:
+
+let
+  cfg = config.services.crashplan;
+  crashplan = pkgs.crashplan;
+  varDir = "/var/lib/crashplan";
+in
+
+with lib;
+
+{
+  options = {
+    services.crashplan = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Starts crashplan background service.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ crashplan ];
+
+    systemd.services.crashplan = {
+      description = "CrashPlan Backup Engine";
+
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network.target" ];
+
+      preStart = ''
+        ensureDir() {
+          dir=$1
+          mode=$2
+
+          if ! test -e $dir; then
+            ${pkgs.coreutils}/bin/mkdir -m $mode -p $dir
+          elif [ "$(${pkgs.coreutils}/bin/stat -c %a $dir)" != "$mode" ]; then
+            ${pkgs.coreutils}/bin/chmod $mode $dir
+          fi
+        }
+
+        ensureDir ${crashplan.vardir} 755
+        ensureDir ${crashplan.vardir}/conf 700
+        ensureDir ${crashplan.manifestdir} 700
+        ensureDir ${crashplan.vardir}/cache 700
+        ensureDir ${crashplan.vardir}/backupArchives 700
+        ensureDir ${crashplan.vardir}/log 777
+      '';
+
+      serviceConfig = {
+        Type = "forking";
+        EnvironmentFile = "${crashplan}/bin/run.conf";
+        ExecStart = "${crashplan}/bin/CrashPlanEngine start";
+        ExecStop = "${crashplan}/bin/CrashPlanEngine stop";
+        PIDFile = "${crashplan.vardir}/CrashPlanEngine.pid";
+        WorkingDirectory = crashplan;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/backup/rsnapshot.nix b/nixos/modules/services/backup/rsnapshot.nix
index 091b5cfd4d59..fb25bd9dd1e8 100644
--- a/nixos/modules/services/backup/rsnapshot.nix
+++ b/nixos/modules/services/backup/rsnapshot.nix
@@ -39,11 +39,20 @@ in
           as retain options.
         '';
       };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.rsnapshot;
+        example = literalExample "pkgs.rsnapshotGit";
+        description = ''
+          RSnapshot package to use.
+        '';
+      };
     };
   };
 
   config = mkIf cfg.enable (let
-    myRsnapshot = pkgs.rsnapshot.override { configFile = rsnapshotCfg; };
+    myRsnapshot = cfg.package.override { configFile = rsnapshotCfg; };
     rsnapshotCfg = with pkgs; writeText "gen-rsnapshot.conf" (''
         config_version	1.2
         cmd_cp	${coreutils}/bin/cp
diff --git a/nixos/modules/services/cluster/fleet.nix b/nixos/modules/services/cluster/fleet.nix
new file mode 100644
index 000000000000..04d95fbf186b
--- /dev/null
+++ b/nixos/modules/services/cluster/fleet.nix
@@ -0,0 +1,150 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.fleet;
+
+in {
+
+  ##### Interface
+  options.services.fleet = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable fleet service.
+      '';
+    };
+
+    listen = mkOption {
+      type = types.listOf types.str;
+      default = [ "/var/run/fleet.sock" ];
+      example = [ "/var/run/fleet.sock" "127.0.0.1:49153" ];
+      description = ''
+        Fleet listening addresses.
+      '';
+    };
+
+    etcdServers = mkOption {
+      type = types.listOf types.str;
+      default = [ "http://127.0.0.1:4001" ];
+      description = ''
+        Fleet list of etcd endpoints to use.
+      '';
+    };
+
+    publicIp = mkOption {
+      type = types.nullOr types.str;
+      default = "";
+      description = ''
+        Fleet IP address that should be published with the local Machine's
+        state and any socket information. If not set, fleetd will attempt
+        to detect the IP it should publish based on the machine's IP
+        routing information.
+      '';
+    };
+
+    etcdCafile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Fleet TLS ca file when SSL certificate authentication is enabled
+        in etcd endpoints.
+      '';
+    };
+
+    etcdKeyfile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Fleet TLS key file when SSL certificate authentication is enabled
+        in etcd endpoints.
+      '';
+    };
+
+    etcdCertfile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Fleet TLS cert file when SSL certificate authentication is enabled
+        in etcd endpoints.
+      '';
+    };
+
+    metadata = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      apply = attrs: concatMapStringsSep "," (n: "${n}=${attrs."${n}"}") (attrNames attrs);
+      example = literalExample ''
+        {
+          region = "us-west";
+          az = "us-west-1";
+        }
+      '';
+      description = ''
+        Key/value pairs that are published with the local to the fleet registry.
+        This data can be used directly by a client of fleet to make scheduling decisions.
+      '';
+    };
+
+    extraConfig = mkOption {
+      type = types.attrsOf types.str;
+      apply = mapAttrs' (n: v: nameValuePair ("ETCD_" + n) v);
+      default = {};
+      example = literalExample ''
+        {
+          VERBOSITY = 1;
+          ETCD_REQUEST_TIMEOUT = "2.0";
+          AGENT_TTL = "40s";
+        }
+      '';
+      description = ''
+        Fleet extra config. See
+        <link xlink:href="https://github.com/coreos/fleet/blob/master/Documentation/deployment-and-configuration.md"/>
+        for configuration options.
+      '';
+    };
+
+  };
+
+  ##### Implementation
+  config = mkIf cfg.enable {
+    systemd.services.fleet = {
+      description = "Fleet Init System Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "fleet.socket" "etcd.service" "docker.service" ];
+      requires = [ "fleet.socket" ];
+      environment = {
+        FLEET_ETCD_SERVERS = concatStringsSep "," cfg.etcdServers;
+        FLEET_PUBLIC_IP = cfg.publicIp;
+        FLEET_ETCD_CAFILE = cfg.etcdCafile;
+        FLEET_ETCD_KEYFILE = cfg.etcdKeyfile;
+        FEELT_ETCD_CERTFILE = cfg.etcdCertfile;
+        FLEET_METADATA = cfg.metadata;
+      } // cfg.extraConfig;
+      serviceConfig = {
+        ExecStart = "${pkgs.fleet}/bin/fleetd";
+        Group = "fleet";
+      };
+    };
+
+    systemd.sockets.fleet = {
+      description = "Fleet Socket for the API";
+      wantedBy = [ "sockets.target" ];
+      listenStreams = cfg.listen;
+      socketConfig = {
+        ListenStream = "/var/run/fleet.sock";
+        SocketMode = "0660";
+        SocketUser = "root";
+        SocketGroup = "fleet";
+      };
+    };
+
+    services.etcd.enable = mkDefault true;
+    virtualisation.docker.enable = mkDefault true;
+
+    environment.systemPackages = [ pkgs.fleet ];
+    users.extraGroups.fleet.gid = config.ids.gids.fleet;
+  };
+}
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
new file mode 100644
index 000000000000..7fd2d77aa825
--- /dev/null
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -0,0 +1,462 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.kubernetes;
+
+in {
+
+  ###### interface
+
+  options.services.kubernetes = {
+    package = mkOption {
+      description = "Kubernetes package to use.";
+      type = types.package;
+    };
+
+    verbose = mkOption {
+      description = "Kubernetes enable verbose mode for debugging";
+      default = false;
+      type = types.bool;
+    };
+
+    etcdServers = mkOption {
+      description = "Kubernetes list of etcd servers to watch.";
+      default = [ "127.0.0.1:4001" ];
+      type = types.listOf types.str;
+    };
+
+    roles = mkOption {
+      description = ''
+        Kubernetes role that this machine should take.
+
+        Master role will enable etcd, apiserver, scheduler and controller manager
+        services. Node role will enable etcd, docker, kubelet and proxy services.
+      '';
+      default = [];
+      type = types.listOf (types.enum ["master" "node"]);
+    };
+
+    dataDir = mkOption {
+      description = "Kubernetes root directory for managing kubelet files.";
+      default = "/var/lib/kubernetes";
+      type = types.path;
+    };
+
+    apiserver = {
+      enable = mkOption {
+        description = "Whether to enable kubernetes apiserver.";
+        default = false;
+        type = types.bool;
+      };
+
+      address = mkOption {
+        description = "Kubernetes apiserver listening address.";
+        default = "127.0.0.1";
+        type = types.str;
+      };
+
+      publicAddress = mkOption {
+        description = ''
+          Kubernetes apiserver public listening address used for read only and
+          secure port.
+        '';
+        default = cfg.apiserver.address;
+        type = types.str;
+      };
+
+      port = mkOption {
+        description = "Kubernets apiserver listening port.";
+        default = 8080;
+        type = types.int;
+      };
+
+      readOnlyPort = mkOption {
+        description = "Kubernets apiserver read-only port.";
+        default = 7080;
+        type = types.int;
+      };
+
+      securePort = mkOption {
+        description = "Kubernetes apiserver secure port.";
+        default = 6443;
+        type = types.int;
+      };
+
+      tlsCertFile = mkOption {
+        description = "Kubernetes apiserver certificate file.";
+        default = "";
+        type = types.str;
+      };
+
+      tlsPrivateKeyFile = mkOption {
+        description = "Kubernetes apiserver private key file.";
+        default = "";
+        type = types.str;
+      };
+
+      tokenAuth = mkOption {
+        description = ''
+          Kubernetes apiserver token authentication file. See
+          <link xlink:href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authentication.md"/>
+        '';
+        default = {};
+        example = literalExample ''
+          {
+            alice = "abc123";
+            bob = "xyz987";
+          }
+        '';
+        type = types.attrsOf types.str;
+      };
+
+      authorizationMode = mkOption {
+        description = ''
+          Kubernetes apiserver authorization mode (AlwaysAllow/AlwaysDeny/ABAC). See
+          <link xlink:href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authorization.md"/>
+        '';
+        default = "AlwaysAllow";
+        type = types.enum ["AlwaysAllow" "AlwaysDeny" "ABAC"];
+      };
+
+      authorizationPolicy = mkOption {
+        description = ''
+          Kubernetes apiserver authorization policy file. See
+          <link xlink:href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authorization.md"/>
+        '';
+        default = [];
+        example = literalExample ''
+          [
+            {user = "admin";}
+            {user = "scheduler"; readonly = true; kind= "pods";}
+            {user = "scheduler"; kind = "bindings";}
+            {user = "kubelet";  readonly = true; kind = "bindings";}
+            {user = "kubelet"; kind = "events";}
+            {user= "alice"; ns = "projectCaribou";}
+            {user = "bob"; readonly = true; ns = "projectCaribou";}
+          ]
+        '';
+        type = types.listOf types.attrs;
+      };
+
+      allowPrivileged = mkOption {
+        description = "Whether to allow privileged containers on kubernetes.";
+        default = false;
+        type = types.bool;
+      };
+
+      portalNet = mkOption {
+        description = "Kubernetes CIDR notation IP range from which to assign portal IPs";
+        default = "10.10.10.10/16";
+        type = types.str;
+      };
+
+      extraOpts = mkOption {
+        description = "Kubernetes apiserver extra command line options.";
+        default = "";
+        type = types.str;
+      };
+    };
+
+    scheduler = {
+      enable = mkOption {
+        description = "Whether to enable kubernetes scheduler.";
+        default = false;
+        type = types.bool;
+      };
+
+      address = mkOption {
+        description = "Kubernetes scheduler listening address.";
+        default = "127.0.0.1";
+        type = types.str;
+      };
+
+      port = mkOption {
+        description = "Kubernets scheduler listening port.";
+        default = 10251;
+        type = types.int;
+      };
+
+      master = mkOption {
+        description = "Kubernetes apiserver address";
+        default = "${cfg.apiserver.address}:${toString cfg.apiserver.port}";
+        type = types.str;
+      };
+
+      extraOpts = mkOption {
+        description = "Kubernetes scheduler extra command line options.";
+        default = "";
+        type = types.str;
+      };
+    };
+
+    controllerManager = {
+      enable = mkOption {
+        description = "Whether to enable kubernetes controller manager.";
+        default = false;
+        type = types.bool;
+      };
+
+      address = mkOption {
+        description = "Kubernetes controller manager listening address.";
+        default = "127.0.0.1";
+        type = types.str;
+      };
+
+      port = mkOption {
+        description = "Kubernets controller manager listening port.";
+        default = 10252;
+        type = types.int;
+      };
+
+      master = mkOption {
+        description = "Kubernetes apiserver address";
+        default = "${cfg.apiserver.address}:${toString cfg.apiserver.port}";
+        type = types.str;
+      };
+
+      machines = mkOption {
+        description = "Kubernetes apiserver list of machines to schedule to schedule onto";
+        default = [];
+        type = types.listOf types.str;
+      };
+
+      extraOpts = mkOption {
+        description = "Kubernetes scheduler extra command line options.";
+        default = "";
+        type = types.str;
+      };
+    };
+
+    kubelet = {
+      enable = mkOption {
+        description = "Whether to enable kubernetes kubelet.";
+        default = false;
+        type = types.bool;
+      };
+
+      address = mkOption {
+        description = "Kubernetes kubelet info server listening address.";
+        default = "0.0.0.0";
+        type = types.str;
+      };
+
+      port = mkOption {
+        description = "Kubernets kubelet info server listening port.";
+        default = 10250;
+        type = types.int;
+      };
+
+      hostname = mkOption {
+        description = "Kubernetes kubelet hostname override";
+        default = config.networking.hostName;
+        type = types.str;
+      };
+
+      allowPrivileged = mkOption {
+        description = "Whether to allow kubernetes containers to request privileged mode.";
+        default = false;
+        type = types.bool;
+      };
+
+      extraOpts = mkOption {
+        description = "Kubernetes kubelet extra command line options.";
+        default = "";
+        type = types.str;
+      };
+    };
+
+    proxy = {
+      enable = mkOption {
+        description = "Whether to enable kubernetes proxy.";
+        default = false;
+        type = types.bool;
+      };
+
+      address = mkOption {
+        description = "Kubernetes proxy listening address.";
+        default = "0.0.0.0";
+        type = types.str;
+      };
+
+      extraOpts = mkOption {
+        description = "Kubernetes proxy extra command line options.";
+        default = "";
+        type = types.str;
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkMerge [
+    (mkIf cfg.apiserver.enable {
+      systemd.services.kubernetes-apiserver = {
+        description = "Kubernetes Api Server";
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network-interfaces.target" "etcd.service" ];
+        serviceConfig = {
+          ExecStart = let
+            authorizationPolicyFile =
+              pkgs.writeText "kubernetes-policy"
+                (builtins.toJSON cfg.apiserver.authorizationPolicy);
+            tokenAuthFile =
+              pkgs.writeText "kubernetes-auth"
+                (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"} \
+            ${optionalString (cfg.apiserver.tlsCertFile!="")
+              "-tls_cert_file=${cfg.apiserver.tlsCertFile}"} \
+            ${optionalString (cfg.apiserver.tlsPrivateKeyFile!="")
+              "-tls_private_key_file=${cfg.apiserver.tlsPrivateKeyFile}"} \
+            ${optionalString (cfg.apiserver.tokenAuth!=[])
+              "-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"} \
+            ${cfg.apiserver.extraOpts}
+          '';
+          User = "kubernetes";
+        };
+        postStart = ''
+          until ${pkgs.curl}/bin/curl -s -o /dev/null 'http://${cfg.apiserver.address}:${toString cfg.apiserver.port}/'; do
+            sleep 1;
+          done
+        '';
+      };
+    })
+
+    (mkIf cfg.scheduler.enable {
+      systemd.services.kubernetes-scheduler = {
+        description = "Kubernetes Scheduler Service";
+        wantedBy = [ "multi-user.target" ];
+        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"} \
+            ${cfg.scheduler.extraOpts}
+          '';
+          User = "kubernetes";
+        };
+      };
+    })
+
+    (mkIf cfg.controllerManager.enable {
+      systemd.services.kubernetes-controller-manager = {
+        description = "Kubernetes Controller Manager Service";
+        wantedBy = [ "multi-user.target" ];
+        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"} \
+            ${cfg.controllerManager.extraOpts}
+          '';
+          User = "kubernetes";
+        };
+      };
+    })
+
+    (mkIf cfg.kubelet.enable {
+      systemd.services.kubernetes-kubelet = {
+        description = "Kubernetes Kubelet Service";
+        wantedBy = [ "multi-user.target" ];
+        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"} \
+            ${cfg.kubelet.extraOpts}
+          '';
+          User = "kubernetes";
+          PermissionsStartOnly = true;
+          WorkingDirectory = cfg.dataDir;
+        };
+      };
+    })
+
+    (mkIf cfg.proxy.enable {
+      systemd.services.kubernetes-proxy = {
+        description = "Kubernetes Proxy Service";
+        wantedBy = [ "multi-user.target" ];
+        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"} \
+            ${cfg.proxy.extraOpts}
+          '';
+        };
+      };
+    })
+
+    (mkIf (any (el: el == "master") cfg.roles) {
+      services.kubernetes.apiserver.enable = mkDefault true;
+      services.kubernetes.scheduler.enable = mkDefault true;
+      services.kubernetes.controllerManager.enable = mkDefault true;
+    })
+
+    (mkIf (any (el: el == "node") cfg.roles) {
+      virtualisation.docker.enable = mkDefault true;
+      services.kubernetes.kubelet.enable = mkDefault true;
+      services.kubernetes.proxy.enable = mkDefault true;
+    })
+
+    (mkIf (any (el: el == "node" || el == "master") cfg.roles) {
+      services.etcd.enable = mkDefault true;
+    })
+
+    (mkIf (
+        cfg.apiserver.enable ||
+        cfg.scheduler.enable ||
+        cfg.controllerManager.enable ||
+        cfg.kubelet.enable ||
+        cfg.proxy.enable
+    ) {
+      services.kubernetes.package = mkDefault pkgs.kubernetes;
+
+      environment.systemPackages = [ cfg.package ];
+
+      users.extraUsers = singleton {
+        name = "kubernetes";
+        uid = config.ids.uids.kubernetes;
+        description = "Kubernetes user";
+        extraGroups = [ "docker" ];
+        group = "kubernetes";
+        home = cfg.dataDir;
+        createHome = true;
+      };
+      users.extraGroups.kubernetes.gid = config.ids.gids.kubernetes;
+    })
+
+  ];
+}
diff --git a/nixos/modules/services/databases/4store-endpoint.nix b/nixos/modules/services/databases/4store-endpoint.nix
index f2d64b6891db..a03790433718 100644
--- a/nixos/modules/services/databases/4store-endpoint.nix
+++ b/nixos/modules/services/databases/4store-endpoint.nix
@@ -56,14 +56,13 @@ with lib;
       { name = endpointUser;
         uid = config.ids.uids.fourstorehttp;
         description = "4Store SPARQL endpoint user";
-#        home = stateDir;
       };
 
     services.avahi.enable = true;
 
     jobs.fourStoreEndpoint = {
       name = "4store-endpoint";
-      startOn = "filesystem";
+      startOn = "ip-up";
 
       exec = ''
         ${run} '${pkgs.rdf4store}/bin/4s-httpd -D ${cfg.options} ${if cfg.listenAddress!=null then "-H ${cfg.listenAddress}" else "" } -p ${toString cfg.port} ${cfg.database}'
diff --git a/nixos/modules/services/databases/4store.nix b/nixos/modules/services/databases/4store.nix
index 469fef69c955..807317d27454 100644
--- a/nixos/modules/services/databases/4store.nix
+++ b/nixos/modules/services/databases/4store.nix
@@ -54,7 +54,7 @@ with lib;
 
     jobs.fourStore = {
       name = "4store";
-      startOn = "filesystem";
+      startOn = "ip-up";
 
       preStart = ''
         mkdir -p ${stateDir}/
diff --git a/nixos/modules/services/databases/hbase.nix b/nixos/modules/services/databases/hbase.nix
new file mode 100644
index 000000000000..ccfabc9de0b5
--- /dev/null
+++ b/nixos/modules/services/databases/hbase.nix
@@ -0,0 +1,133 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.hbase;
+
+  configFile = pkgs.writeText "hbase-site.xml" ''
+    <configuration>
+      <property>
+        <name>hbase.rootdir</name>
+        <value>file://${cfg.dataDir}/hbase</value>
+      </property>
+      <property>
+        <name>hbase.zookeeper.property.dataDir</name>
+        <value>${cfg.dataDir}/zookeeper</value>
+      </property>
+    </configuration>
+  '';
+
+  configDir = pkgs.runCommand "hbase-config-dir" {} ''
+    mkdir -p $out
+    cp ${cfg.package}/conf/* $out/
+    rm $out/hbase-site.xml
+    ln -s ${configFile} $out/hbase-site.xml
+  '' ;
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.hbase = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run HBase.
+        '';
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.hbase;
+        example = literalExample "pkgs.hbase";
+        description = ''
+          HBase package to use.
+        '';
+      };
+
+
+      user = mkOption {
+        type = types.string;
+        default = "hbase";
+        description = ''
+          User account under which HBase runs.
+        '';
+      };
+
+      group = mkOption {
+        type = types.string;
+        default = "hbase";
+        description = ''
+          Group account under which HBase runs.
+        '';
+      };
+
+      dataDir = mkOption {
+        type = types.path;
+        default = "/var/lib/hbase";
+        description = ''
+          Specifies location of HBase database files. This location should be
+          writable and readable for the user the HBase service runs as
+          (hbase by default).
+        '';
+      };
+
+      logDir = mkOption {
+        type = types.path;
+        default = "/var/log/hbase";
+        description = ''
+          Specifies the location of HBase log files.
+        '';
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf config.services.hbase.enable {
+
+    systemd.services.hbase = {
+      description = "HBase Server";
+      wantedBy = [ "multi-user.target" ];
+
+      environment = {
+        JAVA_HOME = "${pkgs.jre}";
+        HBASE_LOG_DIR = cfg.logDir;
+      };
+
+      preStart =
+        ''
+        mkdir -p ${cfg.dataDir};
+        mkdir -p ${cfg.logDir};
+
+        if [ "$(id -u)" = 0 ]; then
+          chown ${cfg.user}:${cfg.group} ${cfg.dataDir}
+          chown ${cfg.user}:${cfg.group} ${cfg.logDir}
+        fi
+        '';
+
+      serviceConfig = {
+        PermissionsStartOnly = true;
+        User = cfg.user;
+        Group = cfg.group;
+        ExecStart = "${cfg.package}/bin/hbase --config ${configDir} master start";
+      };
+    };
+
+    users.extraUsers.hbase = {
+      description = "HBase Server user";
+      group = "hbase";
+      uid = config.ids.uids.hbase;
+    };
+
+    users.extraGroups.hbase.gid = config.ids.gids.hbase;
+
+  };
+}
diff --git a/nixos/modules/services/databases/opentsdb.nix b/nixos/modules/services/databases/opentsdb.nix
new file mode 100644
index 000000000000..9c9738570e3f
--- /dev/null
+++ b/nixos/modules/services/databases/opentsdb.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.opentsdb;
+
+  configFile = pkgs.writeText "opentsdb.conf" ''
+    tsd.core.auto_create_metrics = true
+    tsd.http.request.enable_chunked  = true
+  '';
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.opentsdb = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run OpenTSDB.
+        '';
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.opentsdb;
+        example = literalExample "pkgs.opentsdb";
+        description = ''
+          OpenTSDB package to use.
+        '';
+      };
+
+      user = mkOption {
+        type = types.string;
+        default = "opentsdb";
+        description = ''
+          User account under which OpenTSDB runs.
+        '';
+      };
+
+      group = mkOption {
+        type = types.string;
+        default = "opentsdb";
+        description = ''
+          Group account under which OpenTSDB runs.
+        '';
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 4242;
+        description = ''
+          Which port OpenTSDB listens on.
+        '';
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf config.services.opentsdb.enable {
+
+    systemd.services.opentsdb = {
+      description = "OpenTSDB Server";
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "hbase.service" ];
+
+      environment.JAVA_HOME = "${pkgs.jre}";
+      path = [ pkgs.gnuplot ];
+
+      preStart =
+        ''
+        COMPRESSION=NONE HBASE_HOME=${config.services.hbase.package} ${cfg.package}/share/opentsdb/tools/create_table.sh
+        '';
+
+      serviceConfig = {
+        PermissionsStartOnly = true;
+        User = cfg.user;
+        Group = cfg.group;
+        ExecStart = "${cfg.package}/bin/tsdb tsd --staticroot=${cfg.package}/share/opentsdb/static --cachedir=/tmp/opentsdb --port=${toString cfg.port} --config=${configFile}";
+      };
+    };
+
+    users.extraUsers.opentsdb = {
+      description = "OpenTSDB Server user";
+      group = "opentsdb";
+      uid = config.ids.uids.opentsdb;
+    };
+
+    users.extraGroups.opentsdb.gid = config.ids.gids.opentsdb;
+
+  };
+}
diff --git a/nixos/modules/services/databases/virtuoso.nix b/nixos/modules/services/databases/virtuoso.nix
index f955cb74b6ba..8a49e13395c7 100644
--- a/nixos/modules/services/databases/virtuoso.nix
+++ b/nixos/modules/services/databases/virtuoso.nix
@@ -63,7 +63,7 @@ with lib;
 
     jobs.virtuoso = {
       name = "virtuoso";
-      startOn = "filesystem";
+      startOn = "ip-up";
 
       preStart = ''
 	mkdir -p ${stateDir}
diff --git a/nixos/modules/services/desktops/gnome3/gvfs.nix b/nixos/modules/services/desktops/gnome3/gvfs.nix
index 7e1382b161e1..c4f41a6125c7 100644
--- a/nixos/modules/services/desktops/gnome3/gvfs.nix
+++ b/nixos/modules/services/desktops/gnome3/gvfs.nix
@@ -1,6 +1,6 @@
 # gvfs backends
 
-{ config, lib, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
@@ -37,6 +37,8 @@ in
 
     services.dbus.packages = [ gnome3.gvfs ];
 
+    services.udev.packages = [ pkgs.libmtp ];
+
   };
 
 }
diff --git a/nixos/modules/services/desktops/profile-sync-daemon.nix b/nixos/modules/services/desktops/profile-sync-daemon.nix
new file mode 100644
index 000000000000..d66ecef2385a
--- /dev/null
+++ b/nixos/modules/services/desktops/profile-sync-daemon.nix
@@ -0,0 +1,139 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.psd;
+
+  configFile = ''
+    ${optionalString (cfg.users != [ ]) ''
+      USERS="${concatStringsSep " " cfg.users}"
+    ''}
+
+    ${optionalString (cfg.browsers != [ ]) ''
+      BROWSERS="${concatStringsSep " " cfg.browsers}"
+    ''}
+
+    ${optionalString (cfg.volatile != "") "VOLATILE=${cfg.volatile}"}
+    ${optionalString (cfg.daemonFile != "") "DAEMON_FILE=${cfg.daemonFile}"}
+  '';
+
+in {
+
+  options.services.psd = with types; {
+    enable = mkOption {
+      type = bool;
+      default = false;
+      description = ''
+        Whether to enable the Profile Sync daemon.
+      '';
+    };
+
+    users = mkOption {
+      type = listOf str;
+      default = [ ];
+      example = [ "demo" ];
+      description = ''
+        A list of users whose browser profiles should be sync'd to tmpfs.
+      '';
+    };
+
+    browsers = mkOption {
+      type = listOf str;
+      default = [ ];
+      example = [ "chromium" "firefox" ];
+      description = ''
+        A list of browsers to sync. Available choices are:
+
+        chromium chromium-dev conkeror.mozdev.org epiphany firefox
+        firefox-trunk google-chrome google-chrome-beta google-chrome-unstable
+        heftig-aurora icecat luakit midori opera opera-developer opera-beta
+        qupzilla palemoon rekonq seamonkey
+
+        An empty list will enable all browsers.
+      '';
+    };
+
+    resyncTimer = mkOption {
+      type = str;
+      default = "1h";
+      example = "1h 30min";
+      description = ''
+        The amount of time to wait before syncing browser profiles back to the
+        disk.
+
+        Takes a systemd.unit time span. The time unit defaults to seconds if
+        omitted.
+      '';
+    };
+
+    volatile = mkOption {
+      type = str;
+      default = "/run/psd-profiles";
+      description = ''
+        The directory where browser profiles should reside(this should be
+        mounted as a tmpfs). Do not include a trailing backslash.
+      '';
+    };
+
+    daemonFile = mkOption {
+      type = str;
+      default = "/run/psd";
+      description = ''
+        Where the pid and backup configuration files will be stored.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd = {
+      services = {
+        psd = {
+          description = "Profile Sync daemon";
+          wants = [ "psd-resync.service" "local-fs.target" ];
+          wantedBy = [ "multi-user.target" ];
+          preStart = "mkdir -p ${cfg.volatile}";
+
+          path = with pkgs; [ glibc rsync gawk ];
+
+          unitConfig = {
+            RequiresMountsFor = [ "/home/" ];
+          };
+
+          serviceConfig = {
+            Type = "oneshot";
+            RemainAfterExit = "yes";
+            ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon sync";
+            ExecStop = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon unsync";
+          };
+        };
+
+        psd-resync = {
+          description = "Timed profile resync";
+          after = [ "psd.service" ];
+          wants = [ "psd-resync.timer" ];
+          partOf = [ "psd.service" ];
+
+          path = with pkgs; [ glibc rsync gawk ];
+
+          serviceConfig = {
+            Type = "oneshot";
+            ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon resync";
+          };
+        };
+      };
+
+      timers.psd-resync = {
+        description = "Timer for profile sync daemon - ${cfg.resyncTimer}";
+        partOf = [ "psd-resync.service" "psd.service" ];
+
+        timerConfig = {
+          OnUnitActiveSec = "${cfg.resyncTimer}";
+        };
+      };
+    };
+
+    environment.etc."psd.conf".text = configFile;
+
+  };
+}
diff --git a/nixos/modules/services/hardware/80-net-name-slot.rules b/nixos/modules/services/hardware/80-net-setup-link.rules
index 18547f170a3f..18547f170a3f 100644
--- a/nixos/modules/services/hardware/80-net-name-slot.rules
+++ b/nixos/modules/services/hardware/80-net-setup-link.rules
diff --git a/nixos/modules/services/hardware/thermald.nix b/nixos/modules/services/hardware/thermald.nix
index 5233794a20cc..88c3f99aed4e 100644
--- a/nixos/modules/services/hardware/thermald.nix
+++ b/nixos/modules/services/hardware/thermald.nix
@@ -19,6 +19,8 @@ in {
 
   ###### implementation
   config = mkIf cfg.enable {
+    services.dbus.packages = [ pkgs.thermald ];
+
     systemd.services.thermald = {
       description = "Thermal Daemon Service";
       wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 095a97338d52..39180f4d37ec 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -31,6 +31,7 @@ let
     buildCommand = ''
       mkdir -p $out
       shopt -s nullglob
+      set +o pipefail
 
       # Set a reasonable $PATH for programs called by udev rules.
       echo 'ENV{PATH}="${udevPath}/bin:${udevPath}/sbin"' > $out/00-path.rules
@@ -87,7 +88,7 @@ let
       done
 
       ${optionalString config.networking.usePredictableInterfaceNames ''
-        cp ${./80-net-name-slot.rules} $out/80-net-name-slot.rules
+        cp ${./80-net-setup-link.rules} $out/80-net-setup-link.rules
       ''}
 
       # If auto-configuration is disabled, then remove
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index 41f71be2365c..117ee1c900f5 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -7,6 +7,13 @@ let
   pluginPath = lib.concatStringsSep ":" cfg.plugins;
   havePluginPath = lib.length cfg.plugins > 0;
   ops = lib.optionalString;
+  verbosityFlag = {
+    debug = "--debug";
+    info  = "--verbose";
+    warn  = ""; # intentionally empty
+    error = "--quiet";
+    fatal = "--silent";
+  }."${cfg.logLevel}";
 
 in
 
@@ -37,6 +44,12 @@ in
         description = "The paths to find other logstash plugins in.";
       };
 
+      logLevel = mkOption {
+        type = types.enum [ "debug" "info" "warn" "error" "fatal" ];
+        default = "warn";
+        description = "Logging verbosity level.";
+      };
+
       watchdogTimeout = mkOption {
         type = types.int;
         default = 10;
@@ -124,6 +137,7 @@ in
           "${cfg.package}/bin/logstash agent " +
           "-w ${toString cfg.filterWorkers} " +
           ops havePluginPath "--pluginpath ${pluginPath} " +
+          "${verbosityFlag} " +
           "--watchdog-timeout ${toString cfg.watchdogTimeout} " +
           "-f ${writeText "logstash.conf" ''
             input {
diff --git a/nixos/modules/services/logging/syslog-ng.nix b/nixos/modules/services/logging/syslog-ng.nix
index f3991a411ec4..2bf6d1ff7904 100644
--- a/nixos/modules/services/logging/syslog-ng.nix
+++ b/nixos/modules/services/logging/syslog-ng.nix
@@ -43,15 +43,6 @@ in {
           The package providing syslog-ng binaries.
         '';
       };
-      listenToJournal = mkOption {
-        type = types.bool;
-        default = true;
-        description = ''
-          Whether syslog-ng should listen to the syslog socket used
-          by journald, and therefore receive all logs that journald
-          produces.
-        '';
-      };
       extraModulePaths = mkOption {
         type = types.listOf types.str;
         default = [];
@@ -74,7 +65,7 @@ in {
       configHeader = mkOption {
         type = types.lines;
         default = ''
-          @version: 3.5
+          @version: 3.6
           @include "scl.conf"
         '';
         description = ''
@@ -86,18 +77,13 @@ in {
   };
 
   config = mkIf cfg.enable {
-    systemd.sockets.syslog = mkIf cfg.listenToJournal {
-      wantedBy = [ "sockets.target" ];
-      socketConfig.Service = "syslog-ng.service";
-    };
     systemd.services.syslog-ng = {
       description = "syslog-ng daemon";
       preStart = "mkdir -p /{var,run}/syslog-ng";
-      wantedBy = optional (!cfg.listenToJournal) "multi-user.target";
+      wantedBy = [ "multi-user.target" ];
       after = [ "multi-user.target" ]; # makes sure hostname etc is set
       serviceConfig = {
         Type = "notify";
-        Sockets = if cfg.listenToJournal then "syslog.socket" else null;
         StandardOutput = "null";
         Restart = "on-failure";
         ExecStart = "${cfg.package}/sbin/syslog-ng ${concatStringsSep " " syslogngOptions}";
diff --git a/nixos/modules/services/misc/autofs.nix b/nixos/modules/services/misc/autofs.nix
index e645bd25a66d..f4a1059d09f0 100644
--- a/nixos/modules/services/misc/autofs.nix
+++ b/nixos/modules/services/misc/autofs.nix
@@ -84,7 +84,7 @@ in
         startOn = "started network-interfaces";
         stopOn = "stopping network-interfaces";
 
-        path = [ pkgs.nfsUtils pkgs.sshfsFuse ];
+        path = [ pkgs.nfs-utils pkgs.sshfsFuse ];
 
         preStop =
           ''
diff --git a/nixos/modules/services/misc/defaultUnicornConfig.rb b/nixos/modules/services/misc/defaultUnicornConfig.rb
new file mode 100644
index 000000000000..81abaf336dc0
--- /dev/null
+++ b/nixos/modules/services/misc/defaultUnicornConfig.rb
@@ -0,0 +1,206 @@
+# The following was taken from github.com/crohr/syslogger and is BSD
+# licensed.
+require 'syslog'
+require 'logger'
+require 'thread'
+
+class Syslogger
+
+  VERSION = "1.6.0"
+
+  attr_reader :level, :ident, :options, :facility, :max_octets
+  attr_accessor :formatter
+
+  MAPPING = {
+    Logger::DEBUG => Syslog::LOG_DEBUG,
+    Logger::INFO => Syslog::LOG_INFO,
+    Logger::WARN => Syslog::LOG_WARNING,
+    Logger::ERROR => Syslog::LOG_ERR,
+    Logger::FATAL => Syslog::LOG_CRIT,
+    Logger::UNKNOWN => Syslog::LOG_ALERT
+  }
+
+  #
+  # Initializes default options for the logger
+  # <tt>ident</tt>:: the name of your program [default=$0].
+  # <tt>options</tt>::  syslog options [default=<tt>Syslog::LOG_PID | Syslog::LOG_CONS</tt>].
+  #                     Correct values are:
+  #                       LOG_CONS    : writes the message on the console if an error occurs when sending the message;
+  #                       LOG_NDELAY  : no delay before sending the message;
+  #                       LOG_PERROR  : messages will also be written on STDERR;
+  #                       LOG_PID     : adds the process number to the message (just after the program name)
+  # <tt>facility</tt>:: the syslog facility [default=nil] Correct values include:
+  #                       Syslog::LOG_DAEMON
+  #                       Syslog::LOG_USER
+  #                       Syslog::LOG_SYSLOG
+  #                       Syslog::LOG_LOCAL2
+  #                       Syslog::LOG_NEWS
+  #                       etc.
+  #
+  # Usage:
+  #   logger = Syslogger.new("my_app", Syslog::LOG_PID | Syslog::LOG_CONS, Syslog::LOG_LOCAL0)
+  #   logger.level = Logger::INFO # use Logger levels
+  #   logger.warn "warning message"
+  #   logger.debug "debug message"
+  #
+  def initialize(ident = $0, options = Syslog::LOG_PID | Syslog::LOG_CONS, facility = nil)
+    @ident = ident
+    @options = options || (Syslog::LOG_PID | Syslog::LOG_CONS)
+    @facility = facility
+    @level = Logger::INFO
+    @mutex = Mutex.new
+    @formatter = Logger::Formatter.new
+  end
+
+  %w{debug info warn error fatal unknown}.each do |logger_method|
+    # Accepting *args as message could be nil.
+    #  Default params not supported in ruby 1.8.7
+    define_method logger_method.to_sym do |*args, &block|
+      return true if @level > Logger.const_get(logger_method.upcase)
+      message = args.first || block && block.call
+      add(Logger.const_get(logger_method.upcase), message)
+    end
+
+    unless logger_method == 'unknown'
+      define_method "#{logger_method}?".to_sym do
+        @level <= Logger.const_get(logger_method.upcase)
+      end
+    end
+  end
+
+  # Log a message at the Logger::INFO level. Useful for use with Rack::CommonLogger
+  def write(msg)
+    add(Logger::INFO, msg)
+  end
+
+  # Logs a message at the Logger::INFO level.
+  def <<(msg)
+    add(Logger::INFO, msg)
+  end
+
+  # Low level method to add a message.
+  # +severity+::  the level of the message. One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN
+  # +message+:: the message string.
+  #             If nil, the method will call the block and use the result as the message string.
+  #             If both are nil or no block is given, it will use the progname as per the behaviour of both the standard Ruby logger, and the Rails BufferedLogger.
+  # +progname+:: optionally, overwrite the program name that appears in the log message.
+  def add(severity, message = nil, progname = nil, &block)
+    if message.nil? && block.nil? && !progname.nil?
+      message, progname = progname, nil
+    end
+    progname ||= @ident
+
+    @mutex.synchronize do
+      Syslog.open(progname, @options, @facility) do |s|
+        s.mask = Syslog::LOG_UPTO(MAPPING[@level])
+        communication = clean(message || block && block.call)
+        if self.max_octets
+          buffer = "#{tags_text}"
+          communication.bytes do |byte|
+            buffer.concat(byte)
+            # if the last byte we added is potentially part of an escape, we'll go ahead and add another byte
+            if buffer.bytesize >= self.max_octets && !['%'.ord,'\\'.ord].include?(byte)
+              s.log(MAPPING[severity],buffer)
+              buffer = ""
+            end
+          end
+          s.log(MAPPING[severity],buffer) unless buffer.empty?
+        else
+          s.log(MAPPING[severity],"#{tags_text}#{communication}")
+        end
+      end
+    end
+  end
+
+  # Set the max octets of the messages written to the log
+  def max_octets=(max_octets)
+    @max_octets = max_octets
+  end
+
+  # Sets the minimum level for messages to be written in the log.
+  # +level+:: one of <tt>Logger::DEBUG</tt>, <tt>Logger::INFO</tt>, <tt>Logger::WARN</tt>, <tt>Logger::ERROR</tt>, <tt>Logger::FATAL</tt>, <tt>Logger::UNKNOWN</tt>
+  def level=(level)
+    level = Logger.const_get(level.to_s.upcase) if level.is_a?(Symbol)
+
+    unless level.is_a?(Fixnum)
+      raise ArgumentError.new("Invalid logger level `#{level.inspect}`")
+    end
+
+    @level = level
+  end
+
+  # Sets the ident string passed along to Syslog
+  def ident=(ident)
+    @ident = ident
+  end
+
+  # Tagging code borrowed from ActiveSupport gem
+  def tagged(*tags)
+    new_tags = push_tags(*tags)
+    yield self
+  ensure
+    pop_tags(new_tags.size)
+  end
+
+  def push_tags(*tags)
+    tags.flatten.reject{ |i| i.respond_to?(:empty?) ? i.empty? : !i }.tap do |new_tags|
+      current_tags.concat new_tags
+    end
+  end
+
+  def pop_tags(size = 1)
+    current_tags.pop size
+  end
+
+  def clear_tags!
+    current_tags.clear
+  end
+
+  protected
+
+  # Borrowed from SyslogLogger.
+  def clean(message)
+    message = message.to_s.dup
+    message.strip! # remove whitespace
+    message.gsub!(/\n/, '\\n') # escape newlines
+    message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf)
+    message.gsub!(/\e\[[^m]*m/, '') # remove useless ansi color codes
+    message
+  end
+
+  private
+
+  def tags_text
+    tags = current_tags
+    if tags.any?
+      tags.collect { |tag| "[#{tag}] " }.join
+    end
+  end
+
+  def current_tags
+    Thread.current[:syslogger_tagged_logging_tags] ||= []
+  end
+end
+
+worker_processes 2
+working_directory ENV["GITLAB_PATH"]
+pid ENV["UNICORN_PATH"] + "/tmp/pids/unicorn.pid"
+
+listen ENV["UNICORN_PATH"] + "/tmp/sockets/gitlab.socket", :backlog => 1024
+listen "127.0.0.1:8080", :tcp_nopush => true
+
+timeout 60
+
+logger Syslogger.new
+
+preload_app true
+
+GC.respond_to?(:copy_on_write_friendly=) and
+  GC.copy_on_write_friendly = true
+
+check_client_connection false
+
+after_fork do |server, worker|
+  defined?(ActiveRecord::Base) and
+    ActiveRecord::Base.establish_connection
+end
diff --git a/nixos/modules/services/misc/docker-registry.nix b/nixos/modules/services/misc/docker-registry.nix
new file mode 100644
index 000000000000..67580a1c6277
--- /dev/null
+++ b/nixos/modules/services/misc/docker-registry.nix
@@ -0,0 +1,82 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.dockerRegistry;
+
+in {
+  ###### interface
+
+  options.services.dockerRegistry = {
+    enable = mkOption {
+      description = "Whether to enable docker registry server.";
+      default = false;
+      type = types.bool;
+    };
+
+    host = mkOption {
+      description = "Docker registry host or ip to bind to.";
+      default = "127.0.0.1";
+      type = types.str;
+    };
+
+    port = mkOption {
+      description = "Docker registry port to bind to.";
+      default = 5000;
+      type = types.int;
+    };
+
+    storagePath = mkOption {
+      type = types.path;
+      default = "/var/lib/docker/registry";
+      description = "Docker registry strorage path.";
+    };
+
+    extraConfig = mkOption {
+      description = ''
+        Docker extra registry configuration. See
+        <link xlink:href="https://github.com/docker/docker-registry/blob/master/config/config_sample.yml"/>
+      '';
+      default = {};
+      type = types.attrsOf types.str;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.docker-registry = {
+      description = "Docker Container Registry";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      environment = {
+        REGISTRY_HOST = cfg.host;
+        REGISTRY_PORT = toString cfg.port;
+        GUNICORN_OPTS = "[--preload]"; # see https://github.com/docker/docker-registry#sqlalchemy
+        STORAGE_PATH = cfg.storagePath;
+      } // cfg.extraConfig;
+
+      serviceConfig = {
+        ExecStart = "${pkgs.pythonPackages.docker_registry}/bin/docker-registry";
+        User = "docker-registry";
+        Group = "docker";
+        PermissionsStartOnly = true;
+      };
+
+      preStart = ''
+        mkdir -p ${cfg.storagePath}
+        if [ "$(id -u)" = 0 ]; then
+          chown -R docker-registry:docker ${cfg.storagePath}
+        fi
+      '';
+      postStart = ''
+        until ${pkgs.curl}/bin/curl -s -o /dev/null 'http://${cfg.host}:${toString cfg.port}/'; do
+          sleep 1;
+        done
+      '';
+    };
+
+    users.extraGroups.docker.gid = mkDefault config.ids.gids.docker;
+    users.extraUsers.docker-registry.uid = config.ids.uids.docker-registry;
+  };
+}
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
new file mode 100644
index 000000000000..284361a04d9e
--- /dev/null
+++ b/nixos/modules/services/misc/etcd.nix
@@ -0,0 +1,144 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.etcd;
+
+in {
+
+  options.services.etcd = {
+    enable = mkOption {
+      description = "Whether to enable etcd.";
+      default = false;
+      type = types.uniq types.bool;
+    };
+
+    name = mkOption {
+      description = "Etcd unique node name.";
+      default = config.networking.hostName;
+      type = types.str;
+    };
+
+    advertiseClientUrls = mkOption {
+      description = "Etcd list of this member's client URLs to advertise to the rest of the cluster.";
+      default = cfg.listenClientUrls;
+      type = types.listOf types.str;
+    };
+
+    listenClientUrls = mkOption {
+      description = "Etcd list of URLs to listen on for client traffic.";
+      default = ["http://localhost:4001"];
+      type = types.listOf types.str;
+    };
+
+    listenPeerUrls = mkOption {
+      description = "Etcd list of URLs to listen on for peer traffic.";
+      default = ["http://localhost:7001"];
+      type = types.listOf types.str;
+    };
+
+    initialAdvertisePeerUrls = mkOption {
+      description = "Etcd list of this member's peer URLs to advertise to rest of the cluster.";
+      default = cfg.listenPeerUrls;
+      type = types.listOf types.str;
+    };
+
+    initialCluster = mkOption {
+      description = "Etcd initial cluster configuration for bootstrapping.";
+      default = ["${cfg.name}=http://localhost:7001"];
+      type = types.listOf types.str;
+    };
+
+    initialClusterState = mkOption {
+      description = "Etcd initial cluster configuration for bootstrapping.";
+      default = "new";
+      type = types.enum ["new" "existing"];
+    };
+
+    initialClusterToken = mkOption {
+      description = "Etcd initial cluster token for etcd cluster during bootstrap.";
+      default = "etcd-cluster";
+      type = types.str;
+    };
+
+    discovery = mkOption {
+      description = "Etcd discovery url";
+      default = "";
+      type = types.str;
+    };
+
+    extraConf = mkOption {
+      description = ''
+        Etcd extra configuration. See
+        <link xlink:href='https://github.com/coreos/etcd/blob/master/Documentation/configuration.md#environment-variables' />
+      '';
+      type = types.attrsOf types.str;
+      default = {};
+      example = literalExample ''
+        {
+          "CORS": "*",
+          "NAME": "default-name",
+          "MAX_RESULT_BUFFER": "1024",
+          "MAX_CLUSTER_SIZE": "9",
+          "MAX_RETRY_ATTEMPTS": "3"
+        }
+      '';
+    };
+
+    dataDir = mkOption {
+      type = types.path;
+      default = "/var/lib/etcd";
+      description = "Etcd data directory.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.etcd = {
+      description = "Etcd Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+
+      environment = {
+        ETCD_NAME = cfg.name;
+        ETCD_DISCOVERY = cfg.discovery;
+        ETCD_DATA_DIR = cfg.dataDir;
+        ETCD_ADVERTISE_CLIENT_URLS = concatStringsSep "," cfg.advertiseClientUrls;
+        ETCD_LISTEN_CLIENT_URLS = concatStringsSep "," cfg.listenClientUrls;
+        ETCD_LISTEN_PEER_URLS = concatStringsSep "," cfg.listenPeerUrls;
+        ETCD_INITIAL_ADVERTISE_PEER_URLS = concatStringsSep "," cfg.initialAdvertisePeerUrls;
+      } // (optionalAttrs (cfg.discovery == ""){
+        ETCD_INITIAL_CLUSTER = concatStringsSep "," cfg.initialCluster;
+        ETCD_INITIAL_CLUSTER_STATE = cfg.initialClusterState;
+        ETCD_INITIAL_CLUSTER_TOKEN = cfg.initialClusterToken;
+      }) // (mapAttrs' (n: v: nameValuePair "ETCD_${n}" v) cfg.extraConf);
+
+      serviceConfig = {
+        ExecStart = "${pkgs.etcd}/bin/etcd";
+        User = "etcd";
+        PermissionsStartOnly = true;
+      };
+      preStart = ''
+        mkdir -m 0700 -p ${cfg.dataDir}
+        if [ "$(id -u)" = 0 ]; then chown etcd ${cfg.dataDir}; fi
+      '';
+      postStart = ''
+        until ${pkgs.etcdctl}/bin/etcdctl set /nixos/state 'up'; do
+          sleep 1;
+        done
+        until ${pkgs.etcdctl}/bin/etcdctl get /nixos/state | grep up; do
+          sleep 1;
+        done
+      '';
+    };
+
+    environment.systemPackages = [ pkgs.etcdctl ];
+
+    users.extraUsers = singleton {
+      name = "etcd";
+      uid = config.ids.uids.etcd;
+      description = "Etcd daemon user";
+      home = cfg.dataDir;
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
new file mode 100644
index 000000000000..efa139c8dfd2
--- /dev/null
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -0,0 +1,295 @@
+{ config, lib, pkgs, ... }:
+
+# TODO: support non-postgresql
+
+with lib;
+
+let
+  cfg = config.services.gitlab;
+
+  ruby = pkgs.ruby;
+  rubyLibs = pkgs.rubyLibs;
+
+  databaseYml = ''
+    production:
+      adapter: postgresql
+      database: ${cfg.databaseName}
+      host: ${cfg.databaseHost}
+      password: ${cfg.databasePassword}
+      username: ${cfg.databaseUsername}
+      encoding: utf8
+  '';
+  gitlabShellYml = ''
+    user: gitlab
+    gitlab_url: "http://${cfg.host}:${toString cfg.port}/"
+    http_settings:
+      self_signed_cert: false
+    repos_path: "${cfg.stateDir}/repositories"
+    log_file: "${cfg.stateDir}/log/gitlab-shell.log"
+    redis:
+      bin: ${pkgs.redis}/bin/redis-cli
+      host: 127.0.0.1
+      port: 6379
+      database: 0
+      namespace: resque:gitlab
+  '';
+
+  unicornConfig = builtins.readFile ./defaultUnicornConfig.rb;
+
+  gitlab-runner = pkgs.stdenv.mkDerivation rec {
+    name = "gitlab-runner";
+    buildInputs = [ pkgs.gitlab pkgs.rubyLibs.bundler pkgs.makeWrapper ];
+    phases = "installPhase fixupPhase";
+    buildPhase = "";
+    installPhase = ''
+      mkdir -p $out/bin
+      makeWrapper ${rubyLibs.bundler}/bin/bundle $out/bin/gitlab-runner\
+          --set RAKEOPT '"-f ${pkgs.gitlab}/share/gitlab/Rakefile"'\
+          --set UNICORN_PATH "${cfg.stateDir}/"\
+          --set GITLAB_PATH "${pkgs.gitlab}/share/gitlab/"\
+          --set GITLAB_APPLICATION_LOG_PATH "${cfg.stateDir}/log/application.log"\
+          --set GITLAB_SATELLITES_PATH "${cfg.stateDir}/satellites"\
+          --set GITLAB_SHELL_PATH "${pkgs.gitlab-shell}"\
+          --set GITLAB_REPOSITORIES_PATH "${cfg.stateDir}/repositories"\
+          --set GITLAB_SHELL_HOOKS_PATH "${cfg.stateDir}/shell/hooks"\
+          --set BUNDLE_GEMFILE "${pkgs.gitlab}/share/gitlab/Gemfile"\
+          --set GITLAB_EMAIL_FROM "${cfg.emailFrom}"\
+          --set GITLAB_SHELL_CONFIG_PATH "${cfg.stateDir}/shell/config.yml"\
+          --set GITLAB_SHELL_SECRET_PATH "${cfg.stateDir}/config/gitlab_shell_secret"\
+          --set GITLAB_HOST "${cfg.host}"\
+          --set GITLAB_PORT "${toString cfg.port}"\
+          --set GITLAB_BACKUP_PATH"${cfg.backupPath}"\
+          --set RAILS_ENV "production"
+    '';
+  };
+
+in {
+
+  options = {
+    services.gitlab = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the gitlab service.
+        '';
+      };
+
+      satelliteDir = mkOption {
+        type = types.str;
+        default = "/var/gitlab/git-satellites";
+        description = "Gitlab directory to store checked out git trees requires for operation.";
+      };
+
+      stateDir = mkOption {
+        type = types.str;
+        default = "/var/gitlab/state";
+        description = "Gitlab state directory, logs are stored here.";
+      };
+
+      backupPath = mkOption {
+        type = types.str;
+        default = cfg.stateDir + "/backup";
+        description = "Gitlab path for backups.";
+      };
+
+      databaseHost = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        description = "Gitlab database hostname.";
+      };
+
+      databasePassword = mkOption {
+        type = types.str;
+        default = "";
+        description = "Gitlab database user password.";
+      };
+
+      databaseName = mkOption {
+        type = types.str;
+        default = "gitlab";
+        description = "Gitlab database name.";
+      };
+
+      databaseUsername = mkOption {
+        type = types.str;
+        default = "gitlab";
+        description = "Gitlab database user.";
+      };
+
+      emailFrom = mkOption {
+        type = types.str;
+        default = "example@example.org";
+        description = "The source address for emails sent by gitlab.";
+      };
+
+      host = mkOption {
+        type = types.str;
+        default = config.networking.hostName;
+        description = "Gitlab host name. Used e.g. for copy-paste URLs.";
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 8080;
+        description = "Gitlab server listening port.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ gitlab-runner pkgs.gitlab-shell ];
+
+    assertions = [
+      { assertion = cfg.databasePassword != "";
+        message = "databasePassword must be set";
+      }
+    ];
+
+    # Redis is required for the sidekiq queue runner.
+    services.redis.enable = mkDefault true;
+    # We use postgres as the main data store.
+    services.postgresql.enable = mkDefault true;
+    services.postgresql.package = mkDefault pkgs.postgresql;
+    # Use postfix to send out mails.
+    services.postfix.enable = mkDefault true;
+
+    users.extraUsers = [
+      { name = "gitlab";
+        group = "gitlab";
+        home = "${cfg.stateDir}/home";
+        shell = "${pkgs.bash}/bin/bash";
+        uid = config.ids.uids.gitlab;
+      } ];
+
+    users.extraGroups = [
+      { name = "gitlab";
+        gid = config.ids.gids.gitlab;
+      } ];
+
+    systemd.services.gitlab-sidekiq = {
+      after = [ "network.target" "redis.service" ];
+      wantedBy = [ "multi-user.target" ];
+      environment.HOME = "${cfg.stateDir}/home";
+      environment.UNICORN_PATH = "${cfg.stateDir}/";
+      environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/";
+      environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log";
+      environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites";
+      environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}";
+      environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories";
+      environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks";
+      environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile";
+      environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}";
+      environment.GITLAB_SHELL_CONFIG_PATH = "${cfg.stateDir}/shell/config.yml";
+      environment.GITLAB_SHELL_SECRET_PATH = "${cfg.stateDir}/config/gitlab_shell_secret";
+      environment.GITLAB_HOST = "${cfg.host}";
+      environment.GITLAB_PORT = "${toString cfg.port}";
+      environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}";
+      environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}";
+      environment.RAILS_ENV = "production";
+      path = with pkgs; [
+        config.services.postgresql.package
+        gitAndTools.git
+        ruby
+        openssh
+        nodejs
+      ];
+      serviceConfig = {
+        Type = "simple";
+        User = "gitlab";
+        Group = "gitlab";
+        TimeoutSec = "300";
+        WorkingDirectory = "${pkgs.gitlab}/share/gitlab";
+        ExecStart="${rubyLibs.bundler}/bin/bundle exec \"sidekiq -q post_receive -q mailer -q system_hook -q project_web_hook -q gitlab_shell -q common -q default -e production -P ${cfg.stateDir}/tmp/sidekiq.pid\"";
+      };
+    };
+
+    systemd.services.gitlab = {
+      after = [ "network.target" "postgresql.service" "redis.service" ];
+      wantedBy = [ "multi-user.target" ];
+      environment.HOME = "${cfg.stateDir}/home";
+      environment.UNICORN_PATH = "${cfg.stateDir}/";
+      environment.GITLAB_PATH = "${pkgs.gitlab}/share/gitlab/";
+      environment.GITLAB_APPLICATION_LOG_PATH = "${cfg.stateDir}/log/application.log";
+      environment.GITLAB_SATELLITES_PATH = "${cfg.stateDir}/satellites";
+      environment.GITLAB_SHELL_PATH = "${pkgs.gitlab-shell}";
+      environment.GITLAB_REPOSITORIES_PATH = "${cfg.stateDir}/repositories";
+      environment.GITLAB_SHELL_HOOKS_PATH = "${cfg.stateDir}/shell/hooks";
+      environment.BUNDLE_GEMFILE = "${pkgs.gitlab}/share/gitlab/Gemfile";
+      environment.GITLAB_EMAIL_FROM = "${cfg.emailFrom}";
+      environment.GITLAB_HOST = "${cfg.host}";
+      environment.GITLAB_PORT = "${toString cfg.port}";
+      environment.GITLAB_DATABASE_HOST = "${cfg.databaseHost}";
+      environment.GITLAB_DATABASE_PASSWORD = "${cfg.databasePassword}";
+      environment.RAILS_ENV = "production";
+      path = with pkgs; [
+        config.services.postgresql.package
+        gitAndTools.git
+        ruby
+        openssh
+        nodejs
+      ];
+      preStart = ''
+        # TODO: use env vars
+        mkdir -p ${cfg.stateDir}
+        mkdir -p ${cfg.stateDir}/log
+        mkdir -p ${cfg.stateDir}/satellites
+        mkdir -p ${cfg.stateDir}/repositories
+        mkdir -p ${cfg.stateDir}/shell/hooks
+        mkdir -p ${cfg.stateDir}/tmp/pids
+        mkdir -p ${cfg.stateDir}/tmp/sockets
+        rm -rf ${cfg.stateDir}/config
+        mkdir -p ${cfg.stateDir}/config
+        # TODO: What exactly is gitlab-shell doing with the secret?
+        head -c 20 /dev/urandom > ${cfg.stateDir}/config/gitlab_shell_secret
+        mkdir -p ${cfg.stateDir}/home/.ssh
+        touch ${cfg.stateDir}/home/.ssh/authorized_keys
+
+        cp -rf ${pkgs.gitlab}/share/gitlab/config ${cfg.stateDir}/
+        cp ${pkgs.gitlab}/share/gitlab/VERSION ${cfg.stateDir}/VERSION
+
+        ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml
+        ln -fs ${pkgs.writeText "unicorn.rb" unicornConfig} ${cfg.stateDir}/config/unicorn.rb
+
+        chown -R gitlab:gitlab ${cfg.stateDir}/
+        chmod -R 755 ${cfg.stateDir}/
+
+        if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
+          if ! test -e "${cfg.stateDir}/db-created"; then
+            psql postgres -c "CREATE ROLE gitlab WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'"
+            ${config.services.postgresql.package}/bin/createdb --owner gitlab gitlab || true
+            touch "${cfg.stateDir}/db-created"
+
+            # force=yes disables the manual-interaction yes/no prompt
+            # which breaks without an stdin.
+            force=yes ${rubyLibs.bundler}/bin/bundle exec rake -f ${pkgs.gitlab}/share/gitlab/Rakefile gitlab:setup RAILS_ENV=production
+          fi
+        fi
+
+      # Install the shell required to push repositories
+      ln -fs ${pkgs.writeText "config.yml" gitlabShellYml} ${cfg.stateDir}/shell/config.yml
+      export GITLAB_SHELL_CONFIG_PATH=""${cfg.stateDir}/shell/config.yml
+      ${pkgs.gitlab-shell}/bin/install
+
+      # Change permissions in the last step because some of the
+      # intermediary scripts like to create directories as root.
+      chown -R gitlab:gitlab ${cfg.stateDir}/
+      chmod -R 755 ${cfg.stateDir}/
+      '';
+
+      serviceConfig = {
+        PermissionsStartOnly = true; # preStart must be run as root
+        Type = "simple";
+        User = "gitlab";
+        Group = "gitlab";
+        TimeoutSec = "300";
+        WorkingDirectory = "${pkgs.gitlab}/share/gitlab";
+        ExecStart="${rubyLibs.bundler}/bin/bundle exec \"unicorn -c ${cfg.stateDir}/config/unicorn.rb -E production\"";
+      };
+
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/gitolite.nix b/nixos/modules/services/misc/gitolite.nix
index 961af48e0f86..66e19d13d72e 100644
--- a/nixos/modules/services/misc/gitolite.nix
+++ b/nixos/modules/services/misc/gitolite.nix
@@ -15,14 +15,21 @@ in
         default = false;
         description = ''
           Enable gitolite management under the
-          <literal>gitolite</literal> user. The Gitolite home
-          directory is <literal>/var/lib/gitolite</literal>. After
+          <literal>gitolite</literal> user. After
           switching to a configuration with Gitolite enabled, you can
           then run <literal>git clone
           gitolite@host:gitolite-admin.git</literal> to manage it further.
         '';
       };
 
+      dataDir = mkOption {
+        type = types.str;
+        default = "/var/lib/gitolite";
+        description = ''
+          Gitolite home directory (used to store all the repositories).
+        '';
+      };
+
       adminPubkey = mkOption {
         type = types.str;
         description = ''
@@ -39,13 +46,21 @@ in
           A list of custom git hooks that get copied to <literal>~/.gitolite/hooks/common</literal>.
         '';
       };
+
+      user = mkOption {
+        type = types.str;
+        default = "gitolite";
+        description = ''
+          Gitolite user account. This is the username of the gitolite endpoint.
+        '';
+      };
     };
   };
 
   config = mkIf cfg.enable {
-    users.extraUsers.gitolite = {
+    users.extraUsers.${cfg.user} = {
       description     = "Gitolite user";
-      home            = "/var/lib/gitolite";
+      home            = cfg.dataDir;
       createHome      = true;
       uid             = config.ids.uids.gitolite;
       useDefaultShell = true;
@@ -55,13 +70,13 @@ in
       description = "Gitolite initialization";
       wantedBy    = [ "multi-user.target" ];
 
-      serviceConfig.User = "gitolite";
+      serviceConfig.User = "${cfg.user}";
       serviceConfig.Type = "oneshot";
       serviceConfig.RemainAfterExit = true;
 
       path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.openssh ];
       script = ''
-        cd /var/lib/gitolite
+        cd ${cfg.dataDir}
         mkdir -p .gitolite/logs
         if [ ! -d repositories ]; then
           gitolite setup -pk ${pubkeyFile}
diff --git a/nixos/modules/services/misc/mesos-master.nix b/nixos/modules/services/misc/mesos-master.nix
index bdf88d427c5d..5609cf75bb5c 100644
--- a/nixos/modules/services/misc/mesos-master.nix
+++ b/nixos/modules/services/misc/mesos-master.nix
@@ -4,11 +4,11 @@ with lib;
 
 let
   cfg = config.services.mesos.master;
-  
+
 in {
 
   options.services.mesos = {
-    
+
     master = {
       enable = mkOption {
         description = "Whether to enable the Mesos Master.";
@@ -31,36 +31,36 @@ in {
         '';
         type = types.str;
       };
-      
+
       workDir = mkOption {
         description = "The Mesos work directory.";
         default = "/var/lib/mesos/master";
         type = types.str;
       };
-      
+
       extraCmdLineOptions = mkOption {
         description = ''
 	  Extra command line options for Mesos Master.
-	  
+
 	  See https://mesos.apache.org/documentation/latest/configuration/
 	'';
         default = [ "" ];
         type = types.listOf types.string;
         example = [ "--credentials=VALUE" ];
       };
-      
+
       quorum = mkOption {
         description = ''
           The size of the quorum of replicas when using 'replicated_log' based
           registry. It is imperative to set this value to be a majority of
           masters i.e., quorum > (number of masters)/2.
-          
+
           If 0 will fall back to --registry=in_memory.
         '';
         default = 0;
         type = types.int;
       };
-      
+
       logLevel = mkOption {
         description = ''
           The logging level used. Possible values:
@@ -86,11 +86,12 @@ in {
 	  ${pkgs.mesos}/bin/mesos-master \
 	    --port=${toString cfg.port} \
 	    --zk=${cfg.zk} \
-	    ${if cfg.quorum == 0 then "--registry=in_memory" else "--registry=replicated_log --quorum=${cfg.quorum}"} \
+	    ${if cfg.quorum == 0 then "--registry=in_memory" else "--registry=replicated_log --quorum=${toString cfg.quorum}"} \
 	    --work_dir=${cfg.workDir} \
 	    --logging_level=${cfg.logLevel} \
 	    ${toString cfg.extraCmdLineOptions}
 	'';
+	Restart = "on-failure";
 	PermissionsStartOnly = true;
       };
       preStart = ''
@@ -98,6 +99,6 @@ in {
       '';
     };
   };
-  
+
 }
 
diff --git a/nixos/modules/services/misc/mesos-slave.nix b/nixos/modules/services/misc/mesos-slave.nix
index e9a898167161..26fb3fdb00c9 100644
--- a/nixos/modules/services/misc/mesos-slave.nix
+++ b/nixos/modules/services/misc/mesos-slave.nix
@@ -4,7 +4,14 @@ with lib;
 
 let
   cfg = config.services.mesos.slave;
-  
+
+  mkAttributes =
+    attrs: concatStringsSep ";" (mapAttrsToList
+                                   (k: v: "${k}:${v}")
+                                   (filterAttrs (k: v: v != null) attrs));
+  attribsArg = optionalString (cfg.attributes != {})
+                              "--attributes=${mkAttributes cfg.attributes}";
+
 in {
 
   options.services.mesos = {
@@ -29,30 +36,30 @@ in {
         '';
         type = types.str;
       };
-      
+
       withHadoop = mkOption {
-	description = "Add the HADOOP_HOME to the slave.";
-	default = false;
-	type = types.bool;
+        description = "Add the HADOOP_HOME to the slave.";
+        default = false;
+        type = types.bool;
       };
-      
+
       workDir = mkOption {
         description = "The Mesos work directory.";
         default = "/var/lib/mesos/slave";
         type = types.str;
       };
-      
+
       extraCmdLineOptions = mkOption {
         description = ''
-	  Extra command line options for Mesos Slave.
-	  
-	  See https://mesos.apache.org/documentation/latest/configuration/
-	'';
+          Extra command line options for Mesos Slave.
+
+          See https://mesos.apache.org/documentation/latest/configuration/
+        '';
         default = [ "" ];
         type = types.listOf types.string;
         example = [ "--gc_delay=3days" ];
       };
-      
+
       logLevel = mkOption {
         description = ''
           The logging level used. Possible values:
@@ -62,6 +69,19 @@ in {
         type = types.str;
       };
 
+      attributes = mkOption {
+        description = ''
+          Machine attributes for the slave instance.
+
+          Use caution when changing this; you may need to manually reset slave
+          metadata before the slave can re-register.
+        '';
+        default = {};
+        type = types.attrsOf types.str;
+        example = { rack = "aa";
+                    host = "aabc123";
+                    os = "nixos"; };
+      };
     };
 
   };
@@ -72,22 +92,25 @@ in {
       description = "Mesos Slave";
       wantedBy = [ "multi-user.target" ];
       after = [ "network-interfaces.target" ];
+      environment.MESOS_CONTAINERIZERS = "docker,mesos";
       serviceConfig = {
-	ExecStart = ''
-	  ${pkgs.mesos}/bin/mesos-slave \
-	    --port=${toString cfg.port} \
-	    --master=${cfg.master} \
-	    ${optionalString cfg.withHadoop "--hadoop-home=${pkgs.hadoop}"} \
-	    --work_dir=${cfg.workDir} \
-	    --logging_level=${cfg.logLevel} \
-	    ${toString cfg.extraCmdLineOptions}
-	'';
-	PermissionsStartOnly = true;
+        ExecStart = ''
+          ${pkgs.mesos}/bin/mesos-slave \
+            --port=${toString cfg.port} \
+            --master=${cfg.master} \
+            ${optionalString cfg.withHadoop "--hadoop-home=${pkgs.hadoop}"} \
+            ${attribsArg} \
+            --work_dir=${cfg.workDir} \
+            --logging_level=${cfg.logLevel} \
+            --docker=${pkgs.docker}/libexec/docker/docker \
+            ${toString cfg.extraCmdLineOptions}
+        '';
+        PermissionsStartOnly = true;
       };
       preStart = ''
-	mkdir -m 0700 -p ${cfg.workDir}
+        mkdir -m 0700 -p ${cfg.workDir}
       '';
     };
   };
-  
-}
\ No newline at end of file
+
+}
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index c98c0511b566..e9aa10181789 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -36,6 +36,7 @@ let
         # /etc/nixos/configuration.nix.  Do not edit it!
         build-users-group = nixbld
         build-max-jobs = ${toString (cfg.maxJobs)}
+        build-cores = ${toString (cfg.buildCores)}
         build-use-chroot = ${if cfg.useChroot then "true" else "false"}
         build-chroot-dirs = ${toString cfg.chrootDirs} /bin/sh=${sh} $(echo $extraPaths)
         binary-caches = ${toString cfg.binaryCaches}
@@ -74,6 +75,19 @@ in
         ";
       };
 
+      buildCores = mkOption {
+        type = types.int;
+        default = 1;
+        example = 64;
+        description = ''
+          This option defines the maximum number of concurrent tasks during
+          one build. It affects, e.g., -j option for make. The default is 1.
+          Some builds may become non-deterministic with this option; use with
+          care! Packages will only be affected if enableParallelBuilding is
+          set for them.
+        '';
+      };
+
       useChroot = mkOption {
         type = types.bool;
         default = false;
@@ -179,17 +193,6 @@ in
         '';
       };
 
-      proxy = mkOption {
-        type = types.str;
-        default = "";
-        description = ''
-          This option specifies the proxy to use for fetchurl. The real effect
-          is just exporting http_proxy, https_proxy and ftp_proxy with that
-          value.
-        '';
-        example = "http://127.0.0.1:3128";
-      };
-
       # Environment variables for running Nix.
       envVars = mkOption {
         type = types.attrs;
@@ -222,7 +225,7 @@ in
 
       binaryCaches = mkOption {
         type = types.listOf types.str;
-        default = [ http://cache.nixos.org/ ];
+        default = [ https://cache.nixos.org/ ];
         description = ''
           List of binary cache URLs used to obtain pre-built binaries
           of Nix packages.
@@ -278,7 +281,9 @@ in
       { path = [ nix pkgs.openssl pkgs.utillinux pkgs.openssh ]
           ++ optionals cfg.distributedBuilds [ pkgs.gzip ];
 
-        environment = cfg.envVars // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; };
+        environment = cfg.envVars
+          // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; }
+          // config.networking.proxy.envVars;
 
         serviceConfig =
           { Nice = cfg.daemonNiceLevel;
@@ -303,13 +308,6 @@ in
         NIX_BUILD_HOOK = "${nix}/libexec/nix/build-remote.pl";
         NIX_REMOTE_SYSTEMS = "/etc/nix/machines";
         NIX_CURRENT_LOAD = "/run/nix/current-load";
-      }
-
-      # !!! These should not be defined here, but in some general proxy configuration module!
-      // optionalAttrs (cfg.proxy != "") {
-        http_proxy = cfg.proxy;
-        https_proxy = cfg.proxy;
-        ftp_proxy = cfg.proxy;
       };
 
     # Set up the environment variables for running Nix.
diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix
index 5338b25715c8..054df965347d 100644
--- a/nixos/modules/services/misc/synergy.nix
+++ b/nixos/modules/services/misc/synergy.nix
@@ -81,27 +81,26 @@ in
 
   ###### implementation
 
-  config = {
-
-    systemd.services."synergy-client" = {
-      enable = cfgC.enable;
-      after = [ "network.target" ];
-      description = "Synergy client";
-      wantedBy = optional cfgC.autoStart "multi-user.target";
-      path = [ pkgs.synergy ];
-      serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}'';
-    };
-
-    systemd.services."synergy-server" = {
-      enable = cfgS.enable;
-      after = [ "network.target" ];
-      description = "Synergy server";
-      wantedBy = optional cfgS.autoStart "multi-user.target";
-      path = [ pkgs.synergy ];
-      serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} -f ${optionalString (cfgS.address != "") "-a ${cfgS.address}"} ${optionalString (cfgS.screenName != "") "-n ${cfgS.screenName}" }'';
-    };
-
-  };
+  config = mkMerge [
+    (mkIf cfgC.enable {
+      systemd.services."synergy-client" = {
+        after = [ "network.target" ];
+        description = "Synergy client";
+        wantedBy = optional cfgC.autoStart "multi-user.target";
+        path = [ pkgs.synergy ];
+        serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}'';
+      };
+    })
+    (mkIf cfgS.enable {
+      systemd.services."synergy-server" = {
+        after = [ "network.target" ];
+        description = "Synergy server";
+        wantedBy = optional cfgS.autoStart "multi-user.target";
+        path = [ pkgs.synergy ];
+        serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} -f ${optionalString (cfgS.address != "") "-a ${cfgS.address}"} ${optionalString (cfgS.screenName != "") "-n ${cfgS.screenName}" }'';
+      };
+    })
+  ];
 
 }
 
diff --git a/nixos/modules/services/misc/zookeeper.nix b/nixos/modules/services/misc/zookeeper.nix
index 47675b8876cc..47675b8876cc 100755..100644
--- a/nixos/modules/services/misc/zookeeper.nix
+++ b/nixos/modules/services/misc/zookeeper.nix
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
new file mode 100644
index 000000000000..7a53ce174542
--- /dev/null
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -0,0 +1,136 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.bosun;
+
+  configFile = pkgs.writeText "bosun.conf" ''
+    tsdbHost = ${cfg.opentsdbHost}
+    httpListen = ${cfg.listenAddress}
+    stateFile = ${cfg.stateFile}
+    checkFrequency = 5m
+
+    ${cfg.extraConfig}
+  '';
+
+in {
+
+  options = {
+
+    services.bosun = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run bosun.
+        '';
+      };
+
+      package = mkOption {
+        type = types.package;
+        example = literalExample "pkgs.bosun";
+        description = ''
+          bosun binary to use.
+        '';
+      };
+
+      user = mkOption {
+        type = types.string;
+        default = "bosun";
+        description = ''
+          User account under which bosun runs.
+        '';
+      };
+
+      group = mkOption {
+        type = types.string;
+        default = "bosun";
+        description = ''
+          Group account under which bosun runs.
+        '';
+      };
+
+      opentsdbHost = mkOption {
+        type = types.string;
+        default = "localhost:4242";
+        description = ''
+          Host and port of the OpenTSDB database that stores bosun data.
+        '';
+      };
+
+      listenAddress = mkOption {
+        type = types.string;
+        default = ":8070";
+        description = ''
+          The host address and port that bosun's web interface will listen on.
+        '';
+      };
+
+      stateFile = mkOption {
+        type = types.string;
+        default = "/var/lib/bosun/bosun.state";
+        description = ''
+          Path to bosun's state file.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.string;
+        default = "";
+        description = ''
+          Extra configuration options for Bosun. You should describe your
+          desired templates, alerts, macros, etc through this configuration
+          option.
+
+          A detailed description of the supported syntax can be found at-spi2-atk
+          http://bosun.org/configuration.html
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+  
+    services.bosun.package = mkDefault pkgs.bosun; 
+
+    systemd.services.bosun = {
+      description = "bosun metrics collector (part of Bosun)";
+      wantedBy = [ "multi-user.target" ];
+
+      preStart =
+        ''
+        mkdir -p `dirname ${cfg.stateFile}`;
+        touch ${cfg.stateFile}
+        touch ${cfg.stateFile}.tmp
+
+        if [ "$(id -u)" = 0 ]; then
+          chown ${cfg.user}:${cfg.group} ${cfg.stateFile}
+          chown ${cfg.user}:${cfg.group} ${cfg.stateFile}.tmp
+        fi
+        '';
+
+      serviceConfig = {
+        PermissionsStartOnly = true;
+        User = cfg.user;
+        Group = cfg.group;
+        ExecStart = ''
+          ${cfg.package}/bin/bosun -c ${configFile}
+        '';
+      };
+    };
+
+    users.extraUsers.bosun = {
+      description = "bosun user";
+      group = "bosun";
+      uid = config.ids.uids.bosun;
+    };
+
+    users.extraGroups.bosun.gid = config.ids.gids.bosun;
+
+  };
+
+}
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index e21ef167a4ec..bbbbcbccb9be 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -306,7 +306,7 @@ in {
         example = literalExample ''
           {
             GRAPHITE_USERNAME = "user";
-            GRAPHITE_PASSWORD = "pass"; 
+            GRAPHITE_PASSWORD = "pass";
           }
         '';
       };
@@ -344,7 +344,7 @@ in {
               name: Test
         '';
         example = literalExample ''
-          pushbullet_key: pushbullet_api_key 
+          pushbullet_key: pushbullet_api_key
           alerts:
             - target: stats.seatgeek.app.deal_quality.venue_info_cache.hit
               warning: .5
@@ -456,7 +456,7 @@ in {
       environment.systemPackages = [ pkgs.python27Packages.graphite_web ];
     })
 
-    (mkIf cfg.api.enable { 
+    (mkIf cfg.api.enable {
       systemd.services.graphiteApi = {
         description = "Graphite Api Interface";
         wantedBy = [ "multi-user.target" ];
@@ -472,7 +472,7 @@ in {
           ExecStart = ''
             ${pkgs.python27Packages.waitress}/bin/waitress-serve \
             --host=${cfg.api.host} --port=${toString cfg.api.port} \
-            graphite_api.app:app 
+            graphite_api.app:app
           '';
           User = "graphite";
           Group = "graphite";
@@ -501,7 +501,7 @@ in {
           ExecStart = "${pkgs.seyren}/bin/seyren -httpPort ${toString cfg.seyren.port}";
           WorkingDirectory = dataDir;
           User = "graphite";
-          Group = "graphite"; 
+          Group = "graphite";
         };
         preStart = ''
           if ! test -e ${dataDir}/db-created; then
@@ -526,7 +526,7 @@ in {
         serviceConfig = {
           ExecStart = "${pkgs.pythonPackages.graphite_pager}/bin/graphite-pager --config ${pagerConfig}";
           User = "graphite";
-          Group = "graphite"; 
+          Group = "graphite";
         };
       };
 
@@ -535,7 +535,11 @@ in {
       environment.systemPackages = [ pkgs.pythonPackages.graphite_pager ];
     })
 
-    {
+    (mkIf (
+      cfg.carbon.enableCache || cfg.carbon.enableAggregator || cfg.carbon.enableRelay ||
+      cfg.web.enable || cfg.api.enable ||
+      cfg.seyren.enable || cfg.pager.enable
+     ) {
       users.extraUsers = singleton {
         name = "graphite";
         uid = config.ids.uids.graphite;
@@ -543,6 +547,6 @@ in {
         home = dataDir;
       };
       users.extraGroups.graphite.gid = config.ids.gids.graphite;
-    }
+    })
   ];
 }
diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix
index aab1c4b75efb..8558c4ff8e48 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 "/run/current-system/sw/bin:/run/current-system/sw/sbin" \
+          --set PATH "/var/setuid-wrappers:/run/current-system/sw/bin:/run/current-system/sw/sbin" \
           --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="/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/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
       '';
       serviceConfig = {
         ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/";
diff --git a/nixos/modules/services/monitoring/riemann.nix b/nixos/modules/services/monitoring/riemann.nix
index a1935c29a043..ab37d717b86d 100644
--- a/nixos/modules/services/monitoring/riemann.nix
+++ b/nixos/modules/services/monitoring/riemann.nix
@@ -11,11 +11,15 @@ let
     cfg.extraClasspathEntries ++ [ "${riemann}/share/java/riemann.jar" ]
   );
 
+  riemannConfig = concatStringsSep "\n" (
+    [cfg.config] ++ (map (f: ''(load-file "${f}")'') cfg.configFiles)
+  );
+
   launcher = writeScriptBin "riemann" ''
     #!/bin/sh
     exec ${openjdk}/bin/java ${concatStringsSep "\n" cfg.extraJavaOpts} \
       -cp ${classpath} \
-      riemann.bin ${writeText "riemann.config" cfg.config}
+      riemann.bin ${writeText "riemann-config.clj" riemannConfig}
   '';
 
 in {
@@ -36,6 +40,16 @@ in {
           Contents of the Riemann configuration file.
         '';
       };
+      configFiles = mkOption {
+        type = with types; listOf path;
+        default = [];
+        description = ''
+          Extra files containing Riemann configuration. These files will be
+          loaded at runtime by Riemann (with Clojure's
+          <literal>load-file</literal> function) at the end of the
+          configuration.
+        '';
+      };
       extraClasspathEntries = mkOption {
         type = with types; listOf str;
         default = [];
diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix
new file mode 100644
index 000000000000..ce70739abbc4
--- /dev/null
+++ b/nixos/modules/services/monitoring/scollector.nix
@@ -0,0 +1,114 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.scollector;
+
+  collectors = pkgs.runCommand "collectors" {}
+    ''
+    mkdir -p $out
+    ${lib.concatStringsSep
+        "\n"
+        (lib.mapAttrsToList
+          (frequency: binaries:
+            "mkdir -p $out/${frequency}\n" +
+            (lib.concatStringsSep
+              "\n"
+              (map (path: "ln -s ${path} $out/${frequency}/$(basename ${path})")
+                   binaries)))
+          cfg.collectors)}
+    '';
+
+in {
+
+  options = {
+
+    services.scollector = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run scollector.
+        '';
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.scollector;
+        example = literalExample "pkgs.scollector";
+        description = ''
+          scollector binary to use.
+        '';
+      };
+
+      user = mkOption {
+        type = types.string;
+        default = "scollector";
+        description = ''
+          User account under which scollector runs.
+        '';
+      };
+
+      group = mkOption {
+        type = types.string;
+        default = "scollector";
+        description = ''
+          Group account under which scollector runs.
+        '';
+      };
+
+      bosunHost = mkOption {
+        type = types.string;
+        default = "localhost:8070";
+        description = ''
+          Host and port of the bosun server that will store the collected
+          data.
+        '';
+      };
+
+      collectors = mkOption {
+        type = types.attrs;
+        default = {};
+        example = literalExample "{ 0 = [ \"\${postgresStats}/bin/collect-stats\" ]; }";
+        description = ''
+          An attribute set mapping the frequency of collection to a list of
+          binaries that should be executed at that frequency. You can use "0"
+          to run a binary forever.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf config.services.scollector.enable {
+
+    systemd.services.scollector = {
+      description = "scollector metrics collector (part of Bosun)";
+      wantedBy = [ "multi-user.target" ];
+
+      path = [ pkgs.coreutils pkgs.iproute ];
+
+      serviceConfig = {
+        PermissionsStartOnly = true;
+        User = cfg.user;
+        Group = cfg.group;
+        ExecStart = ''
+          ${cfg.package}/bin/scollector -h=${cfg.bosunHost} -c=${collectors}
+        '';
+      };
+    };
+
+    users.extraUsers.scollector = {
+      description = "scollector user";
+      group = "scollector";
+      uid = config.ids.uids.scollector;
+    };
+
+    users.extraGroups.scollector.gid = config.ids.gids.scollector;
+
+  };
+
+}
diff --git a/nixos/modules/services/monitoring/zabbix-server.nix b/nixos/modules/services/monitoring/zabbix-server.nix
index ca283ea2a99f..acd1279ddf47 100644
--- a/nixos/modules/services/monitoring/zabbix-server.nix
+++ b/nixos/modules/services/monitoring/zabbix-server.nix
@@ -32,6 +32,8 @@ let
       ${optionalString (cfg.dbPassword != "") ''
         DBPassword = ${cfg.dbPassword}
       ''}
+
+      ${config.services.zabbixServer.extraConfig}
     '';
 
   useLocalPostgres = cfg.dbServer == "localhost" || cfg.dbServer == "";
@@ -46,6 +48,7 @@ in
 
     services.zabbixServer.enable = mkOption {
       default = false;
+      type = types.bool;
       description = ''
         Whether to run the Zabbix server on this machine.
       '';
@@ -53,6 +56,7 @@ in
 
     services.zabbixServer.dbServer = mkOption {
       default = "localhost";
+      type = types.str;
       description = ''
         Hostname or IP address of the database server.
         Use an empty string ("") to use peer authentication.
@@ -61,9 +65,18 @@ in
 
     services.zabbixServer.dbPassword = mkOption {
       default = "";
+      type = types.str;
       description = "Password used to connect to the database server.";
     };
 
+    services.zabbixServer.extraConfig = mkOption {
+      default = "";
+      type = types.lines;
+      description = ''
+        Configuration that is injected verbatim into the configuration file.
+      '';
+    };
+
   };
 
   ###### implementation
diff --git a/nixos/modules/services/network-filesystems/nfsd.nix b/nixos/modules/services/network-filesystems/nfsd.nix
index 893df51fc1f6..9b317e968849 100644
--- a/nixos/modules/services/network-filesystems/nfsd.nix
+++ b/nixos/modules/services/network-filesystems/nfsd.nix
@@ -86,7 +86,7 @@ in
 
     boot.supportedFilesystems = [ "nfs" ]; # needed for statd and idmapd
 
-    environment.systemPackages = [ pkgs.nfsUtils ];
+    environment.systemPackages = [ pkgs.nfs-utils ];
 
     environment.etc = singleton
       { source = exports;
@@ -104,7 +104,7 @@ in
         after = [ "rpcbind.service" "mountd.service" "idmapd.service" ];
         before = [ "statd.service" ];
 
-        path = [ pkgs.nfsUtils ];
+        path = [ pkgs.nfs-utils ];
 
         script =
           ''
@@ -131,7 +131,7 @@ in
         requires = [ "rpcbind.service" ];
         after = [ "rpcbind.service" ];
 
-        path = [ pkgs.nfsUtils pkgs.sysvtools pkgs.utillinux ];
+        path = [ pkgs.nfs-utils pkgs.sysvtools pkgs.utillinux ];
 
         preStart =
           ''
@@ -157,7 +157,7 @@ in
 
         serviceConfig.Type = "forking";
         serviceConfig.ExecStart = ''
-          @${pkgs.nfsUtils}/sbin/rpc.mountd rpc.mountd \
+          @${pkgs.nfs-utils}/sbin/rpc.mountd rpc.mountd \
               ${if cfg.mountdPort != null then "-p ${toString cfg.mountdPort}" else ""}
         '';
         serviceConfig.Restart = "always";
diff --git a/nixos/modules/services/network-filesystems/rsyncd.nix b/nixos/modules/services/network-filesystems/rsyncd.nix
index 19aa7efd2ff4..2018bfa14a57 100644
--- a/nixos/modules/services/network-filesystems/rsyncd.nix
+++ b/nixos/modules/services/network-filesystems/rsyncd.nix
@@ -6,113 +6,84 @@ let
 
   cfg = config.services.rsyncd;
 
-  motdFile = pkgs.writeText "rsyncd-motd" cfg.motd;
-
-  rsyncdCfg = ""
-    + optionalString (cfg.motd != "") "motd file = ${motdFile}\n"
-    + optionalString (cfg.address != "") "address = ${cfg.address}\n"
-    + optionalString (cfg.port != 873) "port = ${toString cfg.port}\n"
-    + cfg.extraConfig
-    + "\n"
-    + flip concatMapStrings cfg.modules (m: "[${m.name}]\n\tpath = ${m.path}\n"
-      + optionalString (m.comment != "") "\tcomment = ${m.comment}\n"
-      + m.extraConfig
-      + "\n"
-    );
-
-  rsyncdCfgFile = pkgs.writeText "rsyncd.conf" rsyncdCfg;
-
+  motdFile = builtins.toFile "rsyncd-motd" cfg.motd;
+
+  moduleConfig = name:
+    let module = getAttr name cfg.modules; in
+    "[${name}]\n " + (toString (
+       map
+         (key: "${key} = ${toString (getAttr key module)}\n")
+         (attrNames module)
+    ));
+
+  cfgFile = builtins.toFile "rsyncd.conf"
+    ''
+    ${optionalString (cfg.motd != "") "motd file = ${motdFile}"}
+    ${optionalString (cfg.address != "") "address = ${cfg.address}"}
+    ${optionalString (cfg.port != 873) "port = ${toString cfg.port}"}
+    ${cfg.extraConfig}
+    ${toString (map moduleConfig (attrNames cfg.modules))}
+    '';
 in
 
 {
   options = {
-
     services.rsyncd = {
 
       enable = mkOption {
         default = false;
-	description = "Whether to enable the rsync daemon.";
+        description = "Whether to enable the rsync daemon.";
       };
 
       motd = mkOption {
         type = types.string;
         default = "";
-	description = ''
-	  Message of the day to display to clients on each connect.
-	  This usually contains site information and any legal notices.
-	'';
+        description = ''
+          Message of the day to display to clients on each connect.
+          This usually contains site information and any legal notices.
+        '';
       };
 
       port = mkOption {
         default = 873;
-	type = types.int;
-	description = "TCP port the daemon will listen on.";
+        type = types.int;
+        description = "TCP port the daemon will listen on.";
       };
 
       address = mkOption {
         default = "";
-	example = "192.168.1.2";
-	description = ''
-	  IP address the daemon will listen on; rsyncd will listen on
-	  all addresses if this is not specified.
-	'';
+        example = "192.168.1.2";
+        description = ''
+          IP address the daemon will listen on; rsyncd will listen on
+          all addresses if this is not specified.
+        '';
       };
 
       extraConfig = mkOption {
         type = types.lines;
-	default = "";
-	description = ''
-	  Lines of configuration to add to rsyncd globally.
-	  See <literal>man rsyncd.conf</literal> for more options.
-	'';
+        default = "";
+        description = ''
+            Lines of configuration to add to rsyncd globally.
+            See <command>man rsyncd.conf</command> for options.
+          '';
       };
 
       modules = mkOption {
-        default = [ ];
-	example = [ 
-	  { name = "ftp"; 
-	    path = "/home/ftp"; 
-	    comment = "ftp export area";
-	    extraConfig = ''
-	      secrets file = /etc/rsyncd.secrets
-	    '';
-	  }
-	];
-	description = "The list of file paths to export.";
-	type = types.listOf types.optionSet;
-
-	options = {
-
-	  name = mkOption {
-	    example = "ftp";
-	    type = types.string;
-	    description = "Name of export module.";
-	  };
-
-	  comment = mkOption {
-	    default = "";
-	    description = ''
-	      Description string that is displayed next to the module name
-	      when clients obtain a list of available modules.
-	    '';
-	  };
-
-	  path = mkOption {
-	    example = "/home/ftp";
-	    type = types.string;
-	    description = "Directory to make available in this module.";
-   	  };
-
-          extraConfig = mkOption {
-            type = types.lines;
-	    default = "";
-            description = ''
-	      Lines of configuration to add to this module.
-	      See <literal>man rsyncd.conf</literal> for more options.
-	    '';
+        default = {};
+        description = ''
+            A set describing exported directories.
+            See <command>man rsyncd.conf</command> for options.
+          '';
+        type = types.attrsOf (types.attrsOf types.str);
+        example =
+          { srv =
+             { path = "/srv";
+               "read only" = "yes";
+               comment = "Public rsync share.";
+             };
           };
-	};
       };
+
     };
   };
 
@@ -120,20 +91,16 @@ in
 
   config = mkIf cfg.enable {
 
-    environment.etc = singleton
-    { source = rsyncdCfgFile;
+    environment.etc = singleton {
+      source = cfgFile;
       target = "rsyncd.conf";
     };
 
     systemd.services.rsyncd = {
       description = "Rsync daemon";
       wantedBy = [ "multi-user.target" ];
-
-      path = [ pkgs.rsync ];
-
       serviceConfig.ExecStart = "${pkgs.rsync}/bin/rsync --daemon --no-detach";
     };
 
-    networking.firewall.allowedTCPPorts = [ cfg.port ];
   };
 }
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index fd1e83d9f3e7..1199fa316f91 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -27,6 +27,14 @@ let
       mkdir -p ${privateDir}
     '';
 
+  shareConfig = name:
+    let share = getAttr name cfg.shares; in
+    "[${name}]\n " + (toString (
+       map
+         (key: "${key} = ${toString (getAttr key share)}\n")
+         (attrNames share)
+    ));
+
   configFile = pkgs.writeText "smb.conf"
     (if cfg.configText != null then cfg.configText else
     ''
@@ -36,6 +44,8 @@ let
       ${optionalString cfg.syncPasswordsByPam "pam password change = true"}
 
       ${cfg.extraConfig}
+
+      ${toString (map shareConfig (attrNames cfg.shares))}
     '');
 
   # This may include nss_ldap, needed for samba if it has to use ldap.
@@ -159,6 +169,23 @@ in
         '';
       };
 
+      shares = mkOption {
+        default = {};
+        description =
+          ''
+          A set describing shared resources.
+          See <command>man smb.conf</command> for options.
+          '';
+        type = types.attrsOf (types.attrsOf types.str);
+        example =
+          { srv =
+             { path = "/srv";
+               "read only" = "yes";
+                comment = "Public samba share.";
+             };
+          };
+      };
+
     };
 
   };
diff --git a/nixos/modules/services/networking/chrony.nix b/nixos/modules/services/networking/chrony.nix
index d1684dd9f05d..fe062b30e4b7 100644
--- a/nixos/modules/services/networking/chrony.nix
+++ b/nixos/modules/services/networking/chrony.nix
@@ -48,9 +48,10 @@ in
 
       servers = mkOption {
         default = [
-          "0.pool.ntp.org"
-          "1.pool.ntp.org"
-          "2.pool.ntp.org"
+          "0.nixos.pool.ntp.org"
+          "1.nixos.pool.ntp.org"
+          "2.nixos.pool.ntp.org"
+          "3.nixos.pool.ntp.org"
         ];
         description = ''
           The set of NTP servers from which to synchronise.
@@ -99,8 +100,8 @@ in
     jobs.chronyd =
       { description = "chrony daemon";
 
-        wantedBy = [ "ip-up.target" ];
-        partOf = [ "ip-up.target" ];
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
 
         path = [ chrony ];
 
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 9888419309c1..be0acb27324a 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -204,8 +204,29 @@ in
 
     systemd.services.cjdns = {
       description = "encrypted networking for everybody";
-      wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      wantedBy = [ "network.target" ];
+      after = [ "networkSetup.service" "network-interfaces.target" ];
+
+      preStart = if cfg.confFile != "" then "" else ''
+        [ -e /etc/cjdns.keys ] && source /etc/cjdns.keys
+
+        if [ -z "$CJDNS_PRIVATE_KEY" ]; then
+            shopt -s lastpipe
+            ${pkg}/bin/makekeys | { read private ipv6 public; }
+
+            umask 0077
+            echo "CJDNS_PRIVATE_KEY=$private" >> /etc/cjdns.keys
+            echo -e "CJDNS_IPV6=$ipv6\nCJDNS_PUBLIC_KEY=$public" > /etc/cjdns.public
+
+            chmod 600 /etc/cjdns.keys
+            chmod 444 /etc/cjdns.public
+        fi
+
+        if [ -z "$CJDNS_ADMIN_PASSWORD" ]; then
+            echo "CJDNS_ADMIN_PASSWORD=$(${pkgs.coreutils}/bin/head -c 96 /dev/urandom | ${pkgs.coreutils}/bin/tr -dc A-Za-z0-9)" \
+                >> /etc/cjdns.keys
+        fi
+      '';
 
       script = (
         if cfg.confFile != "" then "${pkg}/bin/cjdroute < ${cfg.confFile}" else
@@ -224,27 +245,6 @@ in
       };
     };
 
-    system.activationScripts.cjdns = if (cfg.confFile == "") then "" else ''
-      cjdnsWriteKeys() {
-        private=$1
-        ipv6=$2
-        public=$3
-
-        echo "CJDNS_PRIVATE_KEY=$1" >> /etc/cjdns.keys
-        echo -e "CJDNS_IPV6=$2\nCJDNS_PUBLIC_KEY=$3" > /etc/cjdns.public
-
-        chmod 600 /etc/cjdns.keys
-        chmod 444 /etc/cjdns.public
-      }
-
-      grep -q "CJDNS_PRIVATE_KEY=" /etc/cjdns.keys || \
-          cjdnsWriteKeys $(${pkg}/bin/makekeys)
-
-      grep -q "CJDNS_ADMIN_PASSWORD=" /etc/cjdns.keys || \
-          echo "CJDNS_ADMIN_PASSWORD=$(${pkgs.coreutils}/bin/head -c 96 /dev/urandom | ${pkgs.coreutils}/bin/tr -dc A-Za-z0-9)" \
-          >> /etc/cjdns.keys
-    '';
-
     networking.extraHosts = "${cjdnsHosts}";
 
     assertions = [
@@ -258,4 +258,4 @@ in
 
   };
 
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index ebc836814089..b2d5854fbc0c 100644
--- a/nixos/modules/services/networking/consul.nix
+++ b/nixos/modules/services/networking/consul.nix
@@ -8,7 +8,6 @@ let
 
   configOptions = {
     data_dir = dataDir;
-    rejoin_after_leave = true;
   }
   // (if cfg.webUi then { ui_dir = "${pkgs.consul.ui}"; } else { })
   // cfg.extraConfig;
@@ -41,6 +40,35 @@ in
         '';
       };
 
+      leaveOnStop = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If enabled, causes a leave action to be sent when closing consul.
+          This allows a clean termination of the node, but permanently removes
+          it from the cluster. You probably don't want this option unless you
+          are running a node which going offline in a permanent / semi-permanent
+          fashion.
+        '';
+      };
+
+      joinNodes = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        description = ''
+          A list of addresses of nodes which should be joined at startup if the
+          current node is in a left state.
+        '';
+      };
+
+      joinRetries = mkOption {
+        type = types.int;
+        default = 10;
+        description = ''
+          The number of times to retry connecting to the join nodes.
+        '';
+      };
+
       interface = {
 
         advertise = mkOption {
@@ -119,13 +147,15 @@ in
       serviceConfig = {
         ExecStart = "@${pkgs.consul}/bin/consul consul agent"
           + concatMapStrings (n: " -config-file ${n}") configFiles;
-        ExecStop = "${pkgs.consul}/bin/consul leave";
         ExecReload = "${pkgs.consul}/bin/consul reload";
         PermissionsStartOnly = true;
         User = if cfg.dropPrivileges then "consul" else null;
-      };
+        TimeoutStartSec = "${toString (20 + (3 * cfg.joinRetries))}s";
+      } // (optionalAttrs (cfg.leaveOnStop) {
+        ExecStop = "${pkgs.consul}/bin/consul leave";
+      });
 
-      path = with pkgs; [ iproute gnugrep gawk ];
+      path = with pkgs; [ iproute gnugrep gawk consul ];
       preStart = ''
         mkdir -m 0700 -p ${dataDir}
         chown -R consul ${dataDir}
@@ -160,6 +190,18 @@ in
         echo "    \"\": \"\"" >> /etc/consul-addrs.json
         echo "}" >> /etc/consul-addrs.json
       '';
+      postStart = ''
+        # Issues joins to nodes which we statically connect to
+        ${flip concatMapStrings cfg.joinNodes (addr: ''
+          for i in {0..${toString cfg.joinRetries}}; do
+            # Try to join the other nodes ${toString cfg.joinRetries} times before failing
+            consul join "${addr}" && break
+            sleep 1
+          done &
+        '')}
+        wait
+        exit 0
+      '';
     };
 
   };
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 15dbf80a987e..1ad8cbae15cf 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -8,15 +8,29 @@ let
 
   cfg = config.networking.dhcpcd;
 
+  interfaces = attrValues config.networking.interfaces;
+
+  enableDHCP = config.networking.useDHCP || any (i: i.useDHCP == true) interfaces;
+
   # Don't start dhcpcd on explicitly configured interfaces or on
   # interfaces that are part of a bridge, bond or sit device.
   ignoredInterfaces =
-    map (i: i.name) (filter (i: i.ip4 != [ ] || i.ipAddress != null) (attrValues config.networking.interfaces))
+    map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ip4 != [ ] || i.ipAddress != null) interfaces)
     ++ mapAttrsToList (i: _: i) config.networking.sits
     ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
     ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
     ++ config.networking.dhcpcd.denyInterfaces;
 
+  arrayAppendOrNull = a1: a2: if a1 == null && a2 == null then null
+    else if a1 == null then a2 else if a2 == null then a1
+      else a1 ++ a2;
+
+  # If dhcp is disabled but explicit interfaces are enabled,
+  # we need to provide dhcp just for those interfaces.
+  allowInterfaces = arrayAppendOrNull cfg.allowInterfaces
+    (if !config.networking.useDHCP && enableDHCP then
+      map (i: i.name) (filter (i: i.useDHCP == true) interfaces) else null);
+
   # Config file adapted from the one that ships with dhcpcd.
   dhcpcdConf = pkgs.writeText "dhcpcd.conf"
     ''
@@ -41,7 +55,7 @@ let
       denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* sit*
 
       # Use the list of allowed interfaces if specified
-      ${optionalString (cfg.allowInterfaces != null) "allowinterfaces ${toString cfg.allowInterfaces}"}
+      ${optionalString (allowInterfaces != null) "allowinterfaces ${toString allowInterfaces}"}
 
       ${cfg.extraConfig}
     '';
@@ -132,7 +146,7 @@ in
 
   ###### implementation
 
-  config = mkIf config.networking.useDHCP {
+  config = mkIf enableDHCP {
 
     systemd.services.dhcpcd =
       { description = "DHCP Client";
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
new file mode 100644
index 000000000000..26549bfe6f14
--- /dev/null
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -0,0 +1,134 @@
+{ config, lib, pkgs, ... }:
+with lib;
+
+let
+  apparmorEnabled = config.security.apparmor.enable;
+  dnscrypt-proxy = pkgs.dnscrypt-proxy;
+  cfg = config.services.dnscrypt-proxy;
+  uid = config.ids.uids.dnscrypt-proxy;
+  daemonArgs =
+    [ "--daemonize"
+      "--user=dnscrypt-proxy"
+      "--local-address=${cfg.localAddress}:${toString cfg.port}"
+      (optionalString cfg.tcpOnly "--tcp-only")
+      "--resolvers-list=${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv"
+      "--resolver-name=${cfg.resolverName}"
+    ];
+in
+
+{
+  ##### interface
+
+  options = {
+
+    services.dnscrypt-proxy = {
+
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Enable dnscrypt-proxy.
+          The proxy relays regular DNS queries to a DNSCrypt enabled
+          upstream resolver.
+          The traffic between the client and the upstream resolver is
+          encrypted and authenticated, which may mitigate the risk of MITM
+          attacks and third-party snooping (assuming the upstream is
+          trustworthy).
+        '';
+      };
+
+      localAddress = mkOption {
+        default = "127.0.0.1";
+        type = types.string;
+        description = ''
+          Listen for DNS queries on this address.
+        '';
+      };
+
+      port = mkOption {
+        default = 53;
+        type = types.int;
+        description = ''
+          Listen on this port.
+        '';
+      };
+
+      resolverName = mkOption {
+        default = "opendns";
+        type = types.string;
+        description = ''
+          The name of the upstream DNSCrypt resolver to use.
+          See <literal>${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv</literal>
+          for alternative resolvers (e.g., if you are concerned about logging
+          and/or server location).
+        '';
+      };
+
+      tcpOnly = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Force sending encrypted DNS queries to the upstream resolver
+          over TCP instead of UDP (on port 443).
+          Enabling this option may help circumvent filtering, but should
+          not be used otherwise.
+        '';
+      };
+
+    };
+
+  };
+
+  ##### implementation
+
+  config = mkIf cfg.enable {
+
+    ### AppArmor profile
+
+    security.apparmor.profiles = mkIf apparmorEnabled [
+      (pkgs.writeText "apparmor-dnscrypt-proxy" ''
+
+        ${dnscrypt-proxy}/sbin/dnscrypt-proxy {
+          capability ipc_lock,
+          capability net_bind_service,
+          capability net_admin,
+          capability sys_chroot,
+          capability setgid,
+          capability setuid,
+
+          /dev/null rw,
+          /dev/urandom r,
+
+          ${pkgs.glibc}/lib/*.so mr,
+          ${pkgs.tzdata}/share/zoneinfo/** r,
+
+          ${dnscrypt-proxy}/share/dnscrypt-proxy/** r,
+          ${pkgs.gcc.gcc}/lib/libssp.so.* mr,
+          ${pkgs.libsodium}/lib/libsodium.so.* mr,
+        }
+      '')
+    ];
+
+    ### User
+
+    users.extraUsers = singleton {
+      inherit uid;
+      name = "dnscrypt-proxy";
+      description = "dnscrypt-proxy daemon user";
+    };
+
+    ### Service definition
+
+    systemd.services.dnscrypt-proxy = {
+      description = "dnscrypt-proxy daemon";
+      after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
+      requires = mkIf apparmorEnabled [ "apparmor.service" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = "forking";
+        ExecStart = "${dnscrypt-proxy}/sbin/dnscrypt-proxy ${toString daemonArgs}";
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index 5c68dd89fb12..fbb211911f1c 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" ];
+        after = [ "network.target" "systemd-resolved.conf" ];
         wantedBy = [ "multi-user.target" ];
         path = [ dnsmasq ];
         preStart = ''
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index 68aac3d30de1..1f17661c9f08 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -187,6 +187,12 @@ let
     # Clean up after added ruleset
     ip46tables -D INPUT -j nixos-fw 2>/dev/null || true
 
+    ${optionalString (kernelHasRPFilter && cfg.checkReversePath) ''
+      if ! ip46tables -D PREROUTING -t raw -m rpfilter --invert -j DROP; then
+        echo "<2>failed to stop rpfilter support" >&2
+      fi
+    ''}
+
     ${cfg.extraStopCommands}
   '';
 
@@ -437,7 +443,7 @@ in
 
     networking.firewall.trustedInterfaces = [ "lo" ];
 
-    environment.systemPackages = [ pkgs.iptables ];
+    environment.systemPackages = [ pkgs.iptables pkgs.ipset ];
 
     boot.kernelModules = map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules;
     boot.extraModprobeConfig = optionalString (!cfg.autoLoadConntrackHelpers) ''
@@ -452,10 +458,11 @@ in
 
     systemd.services.firewall = {
       description = "Firewall";
-      wantedBy = [ "network.target" ];
-      after = [ "network-interfaces.target" "systemd-modules-load.service" ];
+      wantedBy = [ "network-pre.target" ];
+      before = [ "network-pre.target" ];
+      after = [ "systemd-modules-load.service" ];
 
-      path = [ pkgs.iptables ];
+      path = [ pkgs.iptables pkgs.ipset ];
 
       # FIXME: this module may also try to load kernel modules, but
       # containers don't have CAP_SYS_MODULE. So the host system had
diff --git a/nixos/modules/services/networking/git-daemon.nix b/nixos/modules/services/networking/git-daemon.nix
index 5864efaca51f..566936a7d0fa 100644
--- a/nixos/modules/services/networking/git-daemon.nix
+++ b/nixos/modules/services/networking/git-daemon.nix
@@ -3,7 +3,6 @@ with lib;
 let
 
   cfg = config.services.gitDaemon;
-  gitUser = "git";
 
 in
 {
@@ -14,6 +13,7 @@ in
     services.gitDaemon = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = ''
           Enable Git daemon, which allows public hosting  of git repositories
@@ -28,6 +28,7 @@ in
       };
 
       basePath = mkOption {
+        type = types.str;
         default = "";
         example = "/srv/git/";
         description = ''
@@ -38,6 +39,7 @@ in
       };
 
       exportAll = mkOption {
+        type = types.bool;
         default = false;
         description = ''
           Publish all directories that look like Git repositories (have the objects
@@ -52,6 +54,7 @@ in
       };
 
       repositories = mkOption {
+        type = types.listOf types.str;
         default = [];
         example = [ "/srv/git" "/home/user/git/repo2" ];
         description = ''
@@ -64,21 +67,36 @@ in
       };
 
       listenAddress = mkOption {
+        type = types.str;
         default = "";
         example = "example.com";
         description = "Listen on a specific IP address or hostname.";
       };
 
       port = mkOption {
+        type = types.int;
         default = 9418;
         description = "Port to listen on.";
       };
 
       options = mkOption {
+        type = types.str;
         default = "";
         description = "Extra configuration options to be passed to Git daemon.";
       };
 
+      user = mkOption {
+        type = types.str;
+        default = "git";
+        description = "User under which Git daemon would be running.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "git";
+        description = "Group under which Git daemon would be running.";
+      };
+
     };
   };
 
@@ -86,14 +104,14 @@ in
 
   config = mkIf cfg.enable {
 
-    users.extraUsers = singleton
-      { name = gitUser;
+    users.extraUsers = if cfg.user != "git" then {} else singleton
+      { name = "git";
         uid = config.ids.uids.git;
         description = "Git daemon user";
       };
 
-    users.extraGroups = singleton
-      { name = gitUser;
+    users.extraGroups = if cfg.group != "git" then {} else singleton
+      { name = "git";
         gid = config.ids.gids.git;
       };
 
@@ -103,8 +121,8 @@ in
       exec = "${pkgs.git}/bin/git daemon --reuseaddr "
         + (optionalString (cfg.basePath != "") "--base-path=${cfg.basePath} ")
         + (optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ")
-        + "--port=${toString cfg.port} --user=${gitUser} --group=${gitUser} ${cfg.options} "
-        + "--verbose " + (optionalString cfg.exportAll "--export-all")  + concatStringsSep " " cfg.repositories;
+        + "--port=${toString cfg.port} --user=${cfg.user} --group=${cfg.group} ${cfg.options} "
+        + "--verbose " + (optionalString cfg.exportAll "--export-all ")  + concatStringsSep " " cfg.repositories;
     };
 
   };
diff --git a/nixos/modules/services/networking/gogoclient.nix b/nixos/modules/services/networking/gogoclient.nix
index 416007941976..9d16f0efb435 100644
--- a/nixos/modules/services/networking/gogoclient.nix
+++ b/nixos/modules/services/networking/gogoclient.nix
@@ -76,8 +76,7 @@ in
         exec ${pkgs.gogoclient}/bin/gogoc -y -f /var/lib/gogoc/gogoc.conf
       '';
     } // optionalAttrs cfg.autorun {
-      wantedBy = [ "ip-up.target" ];
-      partOf = [ "ip-up.target" ];
+      wantedBy = [ "multi-user.target" ];
     };
 
   };
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
new file mode 100644
index 000000000000..d0127fd3f75e
--- /dev/null
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -0,0 +1,198 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.i2pd;
+
+  homeDir = "/var/lib/i2pd";
+
+  extip = "EXTIP=$(${pkgs.curl}/bin/curl -sf "http://jsonip.com" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
+
+  i2pSh = pkgs.writeScriptBin "i2pd" ''
+    #!/bin/sh
+    ${if isNull cfg.extIp then extip else ""}
+    ${pkgs.i2pd}/bin/i2p --log=1 --daemon=0 --service=0 \
+      --v6=${if cfg.enableIPv6 then "1" else "0"} \
+      --unreachable=${if cfg.unreachable then "1" else "0"} \
+      --host=${if isNull cfg.extIp then "$EXTIP" else cfg.extIp} \
+      ${if isNull cfg.port then "" else "--port=${toString cfg.port}"} \
+      --httpproxyport=${toString cfg.proxy.httpPort} \
+      --socksproxyport=${toString cfg.proxy.socksPort} \
+      --ircport=${toString cfg.irc.port} \
+      --ircdest=${cfg.irc.dest} \
+      --irckeys=${cfg.irc.keyFile} \
+      --eepport=${toString cfg.eep.port} \
+      ${if isNull cfg.sam.port then "" else "--samport=${toString cfg.sam.port}"} \
+      --eephost=${cfg.eep.host} \
+      --eepkeys=${cfg.eep.keyFile}
+  '';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.i2pd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enables I2Pd as a running service upon activation.
+        '';
+      };
+
+      extIp = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = ''
+          Your external IP.
+        '';
+      };
+
+      unreachable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If the router is declared to be unreachable and needs introduction nodes.
+        '';
+      };
+
+      port = mkOption {
+        type = with types; nullOr int;
+        default = null;
+        description = ''
+          I2P listen port. If no one is given the router will pick between 9111 and 30777.
+        '';
+      };
+
+      enableIPv6 = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enables IPv6 connectivity. Disabled by default.
+        '';
+      };
+
+      http = {
+        port = mkOption {
+          type = types.int;
+          default = 7070;
+          description = ''
+            HTTP listen port.
+          '';
+        };
+      };
+
+      proxy = {
+        httpPort = mkOption {
+          type = types.int;
+          default = 4446;
+          description = ''
+            HTTP proxy listen port.
+          '';
+        };
+        socksPort = mkOption {
+          type = types.int;
+          default = 4447;
+          description = ''
+            SOCKS proxy listen port.
+          '';
+        };
+      };
+
+      irc = {
+        dest = mkOption {
+          type = types.str;
+          default = "irc.postman.i2p";
+          description = ''
+            Destination I2P tunnel endpoint address of IRC server. irc.postman.i2p by default.
+          '';
+        };
+        port = mkOption {
+          type = types.int;
+          default = 6668;
+          description = ''
+            Local IRC tunnel endoint port to listen on. 6668 by default.
+          '';
+        };
+        keyFile = mkOption {
+          type = types.str;
+          default = "privKeys.dat";
+          description = ''
+            File name containing destination keys. privKeys.dat by default.
+          '';
+        };
+      };
+
+      eep = {
+        host = mkOption {
+          type = types.str;
+          default = "127.0.0.1";
+          description = ''
+            Address to forward incoming traffic to. 127.0.0.1 by default.
+          '';
+        };
+        port = mkOption {
+          type = types.int;
+          default = 80;
+          description = ''
+            Port to forward incoming trafic to. 80 by default.
+          '';
+        };
+        keyFile = mkOption {
+          type = types.str;
+          default = "privKeys.dat";
+          description = ''
+            File name containing destination keys. privKeys.dat by default.
+          '';
+        };
+      };
+
+      sam = {
+        port = mkOption {
+          type = with types; nullOr int;
+          default = null;
+          description = ''
+            Local SAM tunnel endpoint. Usually 7656. SAM is disabled if not specified.
+          '';
+        };
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers.i2pd = {
+      group = "i2pd";
+      description = "I2Pd User";
+      home = homeDir;
+      createHome = true;
+      uid = config.ids.uids.i2pd;
+    };
+
+    users.extraGroups.i2pd.gid = config.ids.gids.i2pd;
+
+    systemd.services.i2pd = {
+      description = "Minimal I2P router";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig =
+      {
+        User = "i2pd";
+        WorkingDirectory = homeDir;
+        Restart = "on-abort";
+        ExecStart = "${i2pSh}/bin/i2pd";
+      };
+    };
+  };
+}
+#
\ No newline at end of file
diff --git a/nixos/modules/services/networking/minidlna.nix b/nixos/modules/services/networking/minidlna.nix
index a519857d6a0b..989ee4d91af9 100644
--- a/nixos/modules/services/networking/minidlna.nix
+++ b/nixos/modules/services/networking/minidlna.nix
@@ -79,7 +79,7 @@ in
       { description = "MiniDLNA Server";
 
         wantedBy = [ "multi-user.target" ];
-        after = [ "network.target" ];
+        after = [ "network.target" "local-fs.target" ];
 
         preStart =
           ''
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index bdb79ce2a901..9d163e60d5ea 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -157,9 +157,9 @@ in
 
     boot = {
       kernelModules = [ "nf_nat_ftp" ];
-      kernel.sysctl = mkOverride 99 {
-        "net.ipv4.conf.all.forwarding" = true;
-        "net.ipv4.conf.default.forwarding" = true;
+      kernel.sysctl = {
+        "net.ipv4.conf.all.forwarding" = mkOverride 99 true;
+        "net.ipv4.conf.default.forwarding" = mkOverride 99 true;
       };
     };
 
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index bc1c95d3fd36..f72c7fb39d6c 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -52,6 +52,7 @@ let
     #!/bin/sh
     if test "$2" = "up"; then
       ${config.systemd.package}/bin/systemctl start ip-up.target
+      ${config.systemd.package}/bin/systemctl start network-online.target
     fi
   '';
 
@@ -177,8 +178,8 @@ in {
     systemd.services."networkmanager-init" = {
       description = "NetworkManager initialisation";
       wantedBy = [ "network.target" ];
-      wants = [ "NetworkManager.service" ];
-      before = [ "NetworkManager.service" ];
+      wants = [ "network-manager.service" ];
+      before = [ "network-manager.service" ];
       script = ''
         mkdir -m 700 -p /etc/NetworkManager/system-connections
         mkdir -m 755 -p ${stateDirs}
@@ -193,7 +194,7 @@ in {
     };
 
     powerManagement.resumeCommands = ''
-      systemctl restart NetworkManager
+      ${config.systemd.package}/bin/systemctl restart network-manager
     '';
 
     security.polkit.extraConfig = polkitConf;
diff --git a/nixos/modules/services/networking/ntpd.nix b/nixos/modules/services/networking/ntpd.nix
index 2f638904406b..1988c7140d34 100644
--- a/nixos/modules/services/networking/ntpd.nix
+++ b/nixos/modules/services/networking/ntpd.nix
@@ -11,19 +11,15 @@ let
   ntpUser = "ntp";
 
   configFile = pkgs.writeText "ntp.conf" ''
-    # Keep the drift file in ${stateDir}/ntp.drift.  However, since we
-    # chroot to ${stateDir}, we have to specify it as /ntp.drift.
-    driftfile /ntp.drift
+    driftfile ${stateDir}/ntp.drift
 
-    restrict default kod nomodify notrap nopeer noquery
-    restrict -6 default kod nomodify notrap nopeer noquery
     restrict 127.0.0.1
     restrict -6 ::1
 
     ${toString (map (server: "server " + server + " iburst\n") config.services.ntp.servers)}
   '';
 
-  ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup -i ${stateDir}";
+  ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup";
 
 in
 
@@ -45,9 +41,10 @@ in
 
       servers = mkOption {
         default = [
-          "0.pool.ntp.org"
-          "1.pool.ntp.org"
-          "2.pool.ntp.org"
+          "0.nixos.pool.ntp.org"
+          "1.nixos.pool.ntp.org"
+          "2.nixos.pool.ntp.org"
+          "3.nixos.pool.ntp.org"
         ];
         description = ''
           The set of NTP servers from which to synchronise.
@@ -63,7 +60,7 @@ in
 
   config = mkIf config.services.ntp.enable {
 
-    # Make tools such as ntpq available in the system path
+    # Make tools such as ntpq available in the system path.
     environment.systemPackages = [ pkgs.ntp ];
 
     users.extraUsers = singleton
@@ -73,13 +70,10 @@ in
         home = stateDir;
       };
 
-    jobs.ntpd =
+    systemd.services.ntpd =
       { description = "NTP Daemon";
 
-        wantedBy = [ "ip-up.target" ];
-        partOf = [ "ip-up.target" ];
-
-        path = [ ntp ];
+        wantedBy = [ "multi-user.target" ];
 
         preStart =
           ''
@@ -87,7 +81,9 @@ in
             chown ${ntpUser} ${stateDir}
           '';
 
-        exec = "ntpd -g -n ${ntpFlags}";
+        serviceConfig = {
+          ExecStart = "@${ntp}/bin/ntpd ntpd -g -n ${ntpFlags}";
+        };
       };
 
   };
diff --git a/nixos/modules/services/networking/openntpd.nix b/nixos/modules/services/networking/openntpd.nix
index bd8a7a04a2af..2f9031481d1d 100644
--- a/nixos/modules/services/networking/openntpd.nix
+++ b/nixos/modules/services/networking/openntpd.nix
@@ -41,8 +41,7 @@ in
 
     systemd.services.openntpd = {
       description = "OpenNTP Server";
-      wantedBy = [ "ip-up.target" ];
-      partOf = [ "ip-up.target" ];
+      wantedBy = [ "multi-user.target" ];
       serviceConfig.ExecStart = "${package}/sbin/ntpd -d -f ${cfgFile}";
     };
   };
diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix
index 749e5dcebb61..579d62884c78 100644
--- a/nixos/modules/services/networking/quassel.nix
+++ b/nixos/modules/services/networking/quassel.nix
@@ -74,21 +74,23 @@ in
         gid = config.ids.gids.quassel;
       }];
 
-    jobs.quassel =
+    systemd.services.quassel =
       { description = "Quassel IRC client daemon";
 
-        startOn = "ip-up";
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
 
         preStart = ''
-            mkdir -p ${cfg.dataDir}
-            chown ${user} ${cfg.dataDir}
+          mkdir -p ${cfg.dataDir}
+          chown ${user} ${cfg.dataDir}
         '';
 
-        exec = ''
-            ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${user} \
-                -c '${quassel}/bin/quasselcore --listen=${cfg.interface}\
-                    --port=${toString cfg.portNumber} --configdir=${cfg.dataDir}'
-        '';
+        serviceConfig =
+        {
+          ExecStart = "${quassel}/bin/quasselcore --listen=${cfg.interface} --port=${toString cfg.portNumber} --configdir=${cfg.dataDir}";
+          User = user;
+          PermissionsStartOnly = true;
+        };
       };
 
   };
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index fee1bace0460..4db8d1e25450 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -17,11 +17,13 @@ let
 
   knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
 
-  knownHostsFile = pkgs.writeText "ssh_known_hosts" (
-    flip concatMapStrings knownHosts (h: ''
-      ${concatStringsSep "," h.hostNames} ${if h.publicKey != null then h.publicKey else readFile h.publicKeyFile}
-    '')
-  );
+  knownHostsFile = pkgs.runCommand "ssh_known_hosts" {} ''
+    touch "$out"
+    ${flip concatMapStrings knownHosts (h: ''
+      pubkeyfile=${builtins.toFile "host.pub" (if h.publicKey == null then readFile h.publicKeyFile else h.publicKey)}
+      ${pkgs.gnused}/bin/sed 's/^/${concatStringsSep "," h.hostNames} /' $pubkeyfile >> "$out"
+    '')}
+  '';
 
   userOptions = {
 
@@ -254,7 +256,10 @@ in
             description = ''
               The public key data for the host. You can fetch a public key
               from a running SSH server with the <command>ssh-keyscan</command>
-              command.
+              command. The public key should not include any host names, only
+              the key type and the key itself. It is allowed to add several
+              lines here, each line will be treated as type/key pair and the
+              host names will be prepended to each line.
             '';
           };
           publicKeyFile = mkOption {
@@ -264,7 +269,9 @@ in
               The path to the public key file for the host. The public
               key file is read at build time and saved in the Nix store.
               You can fetch a public key file from a running SSH server
-              with the <command>ssh-keyscan</command> command.
+              with the <command>ssh-keyscan</command> command. The content
+              of the file should follow the same format as described for
+              the <literal>publicKey</literal> option.
             '';
           };
         };
diff --git a/nixos/modules/services/networking/strongswan.nix b/nixos/modules/services/networking/strongswan.nix
new file mode 100644
index 000000000000..8778b0364f9a
--- /dev/null
+++ b/nixos/modules/services/networking/strongswan.nix
@@ -0,0 +1,133 @@
+{ config, lib, pkgs, ... }:
+
+let
+
+  inherit (builtins) toFile;
+  inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList
+                mkIf mkEnableOption mkOption types;
+
+  cfg = config.services.strongswan;
+
+  ipsecSecrets = secrets: toFile "ipsec.secrets" (
+    concatMapStringsSep "\n" (f: "include ${f}") secrets
+  );
+
+  ipsecConf = {setup, connections, ca}:
+    let
+      # https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf
+      makeSections = type: sections: concatStringsSep "\n\n" (
+        mapAttrsToList (sec: attrs:
+          "${type} ${sec}\n" +
+            (concatStringsSep "\n" ( mapAttrsToList (k: v: "  ${k}=${v}") attrs ))
+        ) sections
+      );
+      setupConf       = makeSections "config" { inherit setup; };
+      connectionsConf = makeSections "conn" connections;
+      caConf          = makeSections "ca" ca;
+
+    in
+    builtins.toFile "ipsec.conf" ''
+      ${setupConf}
+      ${connectionsConf}
+      ${caConf}
+    '';
+
+  strongswanConf = {setup, connections, ca, secrets}: toFile "strongswan.conf" ''
+    charon {
+      plugins {
+        stroke {
+          secrets_file = ${ipsecSecrets secrets}
+        }
+      }
+    }
+
+    starter {
+      config_file = ${ipsecConf { inherit setup connections ca; }}
+    }
+  '';
+
+in
+{
+  options.services.strongswan = {
+    enable = mkEnableOption "strongSwan";
+
+    secrets = mkOption {
+      type = types.listOf types.path;
+      default = [];
+      example = [ "/run/keys/ipsec-foo.secret" ];
+      description = ''
+        A list of paths to IPSec secret files. These
+        files will be included into the main ipsec.secrets file with
+        the <literal>include</literal> directive. It is safer if these
+        paths are absolute.
+      '';
+    };
+
+    setup = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = { cachecrls = "yes"; strictcrlpolicy = "yes"; };
+      description = ''
+        A set of options for the ‘config setup’ section of the
+        <filename>ipsec.conf</filename> file. Defines general
+        configuration parameters.
+      '';
+    };
+
+    connections = mkOption {
+      type = types.attrsOf (types.attrsOf types.str);
+      default = {};
+      example = {
+        "%default" = {
+          keyexchange = "ikev2";
+          keyingtries = "1";
+        };
+        roadwarrior = {
+          auto       = "add";
+          leftcert   = "/run/keys/moonCert.pem";
+          leftid     = "@moon.strongswan.org";
+          leftsubnet = "10.1.0.0/16";
+          right      = "%any";
+        };
+      };
+      description = ''
+        A set of connections and their options for the ‘conn xxx’
+        sections of the <filename>ipsec.conf</filename> file.
+      '';
+    };
+
+    ca = mkOption {
+      type = types.attrsOf (types.attrsOf types.str);
+      default = {};
+      example = {
+        strongswan = {
+          auto   = "add";
+          cacert = "/run/keys/strongswanCert.pem";
+          crluri = "http://crl2.strongswan.org/strongswan.crl";
+        };
+      };
+      description = ''
+        A set of CAs (certification authorities) and their options for
+        the ‘ca xxx’ sections of the <filename>ipsec.conf</filename>
+        file.
+      '';
+    };
+  };
+
+  config = with cfg; mkIf enable {
+    systemd.services.strongswan = {
+      description = "strongSwan IPSec Service";
+      wantedBy = [ "multi-user.target" ];
+      path = with pkgs; [ kmod iproute iptables utillinux ]; # XXX Linux
+      wants = [ "keys.target" ];
+      after = [ "network.target" "keys.target" ];
+      environment = {
+        STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secrets; };
+      };
+      serviceConfig = {
+        ExecStart  = "${pkgs.strongswan}/sbin/ipsec start --nofork";
+      };
+    };
+  };
+}
+
diff --git a/nixos/modules/services/networking/tcpcrypt.nix b/nixos/modules/services/networking/tcpcrypt.nix
index 1359006aef4e..fbd581cc4b4c 100644
--- a/nixos/modules/services/networking/tcpcrypt.nix
+++ b/nixos/modules/services/networking/tcpcrypt.nix
@@ -44,6 +44,8 @@ in
       path = [ pkgs.iptables pkgs.tcpcrypt pkgs.procps ];
 
       preStart = ''
+        mkdir -p /var/run/tcpcryptd
+        chown tcpcryptd /var/run/tcpcryptd
         sysctl -n net.ipv4.tcp_ecn >/run/pre-tcpcrypt-ecn-state
         sysctl -w net.ipv4.tcp_ecn=0
 
diff --git a/nixos/modules/services/networking/tox-bootstrapd.nix b/nixos/modules/services/networking/tox-bootstrapd.nix
new file mode 100644
index 000000000000..65aa87be44cc
--- /dev/null
+++ b/nixos/modules/services/networking/tox-bootstrapd.nix
@@ -0,0 +1,80 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  home = "/var/lib/tox-bootstrapd";
+  PIDFile = "${home}/pid";
+
+  pkg = pkgs.libtoxcore;
+  cfg = config.services.toxBootstrapd;
+  cfgFile = builtins.toFile "tox-bootstrapd.conf"
+    ''
+      port = ${toString cfg.port}
+      keys_file_path = "${home}/keys"
+      pid_file_path = "${PIDFile}"
+      ${cfg.extraConfig}
+    '';
+in
+{
+  options =
+    { services.toxBootstrapd =
+        { enable = mkOption {
+            type = types.bool;
+            default = false;
+            description =
+              ''
+                Whether to enable the Tox DHT boostrap daemon.
+              '';
+          };
+
+          port = mkOption {
+            type = types.int;
+            default = 33445;
+            description = "Listening port (UDP).";
+          };
+
+          keysFile = mkOption {
+            type = types.str;
+            default = "${home}/keys";
+            description = "Node key file.";
+          };
+
+          extraConfig = mkOption {
+            type = types.lines;
+            default = "";
+            description =
+              ''
+                Configuration for boostrap daemon.
+                See <link xlink:href="https://github.com/irungentoo/toxcore/blob/master/other/bootstrap_daemon/tox-bootstrapd.conf"/>
+                and <link xlink:href="http://wiki.tox.im/Nodes"/>.
+             '';
+          };
+      };
+
+    };
+
+  config = mkIf config.services.toxBootstrapd.enable {
+
+    users.extraUsers = singleton
+      { name = "tox-bootstrapd";
+        uid = config.ids.uids.tox-bootstrapd;
+        description = "Tox bootstrap daemon user";
+        inherit home;
+        createHome = true;
+      };
+
+    systemd.services.tox-bootstrapd = {
+      description = "Tox DHT bootstrap daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig =
+        { ExecStart = "${pkg}/bin/tox-bootstrapd ${cfgFile}";
+          Type = "forking";
+          inherit PIDFile;
+          User = "tox-bootstrapd";
+        };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/networking/unifi.nix b/nixos/modules/services/networking/unifi.nix
index 634f760328f7..8905ff1598ba 100644
--- a/nixos/modules/services/networking/unifi.nix
+++ b/nixos/modules/services/networking/unifi.nix
@@ -1,9 +1,24 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, utils, ... }:
 with lib;
 let
   cfg = config.services.unifi;
   stateDir = "/var/lib/unifi";
   cmd = "@${pkgs.icedtea7_jre}/bin/java java -jar ${stateDir}/lib/ace.jar";
+  mountPoints = [
+    {
+      what = "${pkgs.unifi}/dl";
+      where = "${stateDir}/dl";
+    }
+    {
+      what = "${pkgs.unifi}/lib";
+      where = "${stateDir}/lib";
+    }
+    {
+      what = "${pkgs.mongodb}/bin";
+      where = "${stateDir}/bin";
+    }
+  ];
+  systemdMountPoints = map (m: "${utils.escapeSystemdPath m.where}.mount") mountPoints;
 in
 {
 
@@ -32,30 +47,20 @@ in
     # to be used as the working directory.
     systemd.mounts = map ({ what, where }: {
         bindsTo = [ "unifi.service" ];
-        requiredBy = [ "unifi.service" ];
-        before = [ "unifi.service" ];
+        partOf = [ "unifi.service" ];
+        unitConfig.RequiresMountsFor = stateDir;
         options = "bind";
         what = what;
         where = where;
-      }) [
-        {
-          what = "${pkgs.unifi}/dl";
-          where = "${stateDir}/dl";
-        }
-        {
-          what = "${pkgs.unifi}/lib";
-          where = "${stateDir}/lib";
-        }
-        {
-          what = "${pkgs.mongodb}/bin";
-          where = "${stateDir}/bin";
-        }
-      ];
+      }) mountPoints;
 
     systemd.services.unifi = {
       description = "UniFi controller daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" ];
+      after = [ "network.target" ] ++ systemdMountPoints;
+      partOf = systemdMountPoints;
+      bindsTo = systemdMountPoints;
+      unitConfig.RequiresMountsFor = stateDir;
 
       preStart = ''
         # Ensure privacy of state
@@ -63,13 +68,14 @@ in
         chmod 0700 "${stateDir}"
 
         # Create the volatile webapps
+        rm -rf "${stateDir}/webapps"
         mkdir -p "${stateDir}/webapps"
         chown unifi "${stateDir}/webapps"
         ln -s "${pkgs.unifi}/webapps/ROOT.war" "${stateDir}/webapps/ROOT.war"
       '';
 
       postStop = ''
-        rm "${stateDir}/webapps/ROOT.war"
+        rm -rf "${stateDir}/webapps"
       '';
 
       serviceConfig = {
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index 8a8085cad280..bb3bf2519d42 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -11,20 +11,16 @@ let
   additionalBackends = pkgs.runCommand "additional-cups-backends" { }
     ''
       mkdir -p $out
-      if [ ! -e ${pkgs.cups}/lib/cups/backend/smb ]; then
+      if [ ! -e ${cups}/lib/cups/backend/smb ]; then
         mkdir -p $out/lib/cups/backend
         ln -sv ${pkgs.samba}/bin/smbspool $out/lib/cups/backend/smb
       fi
 
       # Provide support for printing via HTTPS.
-      if [ ! -e ${pkgs.cups}/lib/cups/backend/https ]; then
+      if [ ! -e ${cups}/lib/cups/backend/https ]; then
         mkdir -p $out/lib/cups/backend
-        ln -sv ${pkgs.cups}/lib/cups/backend/ipp $out/lib/cups/backend/https
+        ln -sv ${cups}/lib/cups/backend/ipp $out/lib/cups/backend/https
       fi
-
-      # Import filter configuration from Ghostscript.
-      mkdir -p $out/share/cups/mime/
-      ln -v -s "${pkgs.ghostscript}/etc/cups/"* $out/share/cups/mime/
     '';
 
   # Here we can enable additional backends, filters, etc. that are not
@@ -37,6 +33,7 @@ let
     paths = cfg.drivers;
     pathsToLink = [ "/lib/cups" "/share/cups" "/bin" "/etc/cups" ];
     postBuild = cfg.bindirCmds;
+    ignoreCollisions = true;
   };
 
 in
@@ -89,6 +86,29 @@ in
         '';
       };
 
+      cupsFilesConf = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          The contents of the configuration file of the CUPS daemon
+          (<filename>cups-files.conf</filename>).
+        '';
+      };
+
+      extraConf = mkOption {
+        type = types.lines;
+        default = "";
+        example =
+          ''
+            BrowsePoll cups.example.com
+            LogLevel debug
+          '';
+        description = ''
+          Extra contents of the configuration file of the CUPS daemon
+          (<filename>cupsd.conf</filename>).
+        '';
+      };
+
       clientConf = mkOption {
         type = types.lines;
         default = "";
@@ -107,7 +127,7 @@ in
         type = types.listOf types.path;
         example = literalExample "[ pkgs.splix ]";
         description = ''
-          CUPS drivers to use. Drivers provided by CUPS, Ghostscript
+          CUPS drivers to use. Drivers provided by CUPS, cups-filters, Ghostscript
           and Samba are added unconditionally.
         '';
       };
@@ -138,13 +158,9 @@ in
 
     environment.systemPackages = [ cups ];
 
-    environment.variables.CUPS_SERVERROOT = "/etc/cups";
-
-    environment.etc = [
-      { source = pkgs.writeText "client.conf" cfg.clientConf;
-        target = "cups/client.conf";
-      }
-    ];
+    environment.etc."cups/client.conf".text = cfg.clientConf;
+    environment.etc."cups/cups-files.conf".text = cfg.cupsFilesConf;
+    environment.etc."cups/cupsd.conf".text = cfg.cupsdConf;
 
     services.dbus.packages = [ cups ];
 
@@ -171,35 +187,26 @@ in
           '';
 
         serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = "@${cups}/sbin/cupsd cupsd -c ${pkgs.writeText "cupsd.conf" cfg.cupsdConf}";
+        serviceConfig.ExecStart = "@${cups}/sbin/cupsd cupsd";
+
+        restartTriggers =
+          [ config.environment.etc."cups/cups-files.conf".source
+            config.environment.etc."cups/cupsd.conf".source
+          ];
       };
 
     services.printing.drivers =
-      [ pkgs.cups pkgs.cups_pdf_filter pkgs.ghostscript additionalBackends
+      [ cups pkgs.ghostscript pkgs.cups_filters additionalBackends
         pkgs.perl pkgs.coreutils pkgs.gnused pkgs.bc pkgs.gawk pkgs.gnugrep
       ];
 
-    services.printing.cupsdConf =
+    services.printing.cupsFilesConf =
       ''
-        LogLevel info
-
         SystemGroup root wheel
 
-        ${concatMapStrings (addr: ''
-          Listen ${addr}
-        '') cfg.listenAddresses}
-        Listen /var/run/cups/cups.sock
-
-        # Note: we can't use ${cups}/etc/cups as the ServerRoot, since
-        # CUPS will write in the ServerRoot when e.g. adding new printers
-        # through the web interface.
-        ServerRoot /etc/cups
-
         ServerBin ${bindir}/lib/cups
         DataDir ${bindir}/share/cups
 
-        SetEnv PATH ${bindir}/lib/cups/filter:${bindir}/bin:${bindir}/sbin
-
         AccessLog syslog
         ErrorLog syslog
         PageLog syslog
@@ -212,6 +219,18 @@ in
         # these programs to run as `lp' as well.
         User cups
         Group lp
+      '';
+
+    services.printing.cupsdConf =
+      ''
+        LogLevel info
+
+        ${concatMapStrings (addr: ''
+          Listen ${addr}
+        '') cfg.listenAddresses}
+        Listen /var/run/cups/cups.sock
+
+        SetEnv PATH ${bindir}/lib/cups/filter:${bindir}/bin:${bindir}/sbin
 
         Browsing On
         BrowseOrder allow,deny
@@ -257,6 +276,8 @@ in
             Order deny,allow
           </Limit>
         </Policy>
+
+        ${cfg.extraConf}
       '';
 
     security.pam.services.cups = {};
diff --git a/nixos/modules/services/scheduling/chronos.nix b/nixos/modules/services/scheduling/chronos.nix
new file mode 100644
index 000000000000..277cdd632809
--- /dev/null
+++ b/nixos/modules/services/scheduling/chronos.nix
@@ -0,0 +1,54 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.chronos;
+
+in {
+
+  ###### interface
+
+  options.services.chronos = {
+    enable = mkOption {
+      description = "Whether to enable graphite web frontend.";
+      default = false;
+      type = types.uniq types.bool;
+    };
+
+    httpPort = mkOption {
+      description = "Chronos listening port";
+      default = 8080;
+      type = types.int;
+    };
+
+    master = mkOption {
+      description = "Chronos mesos master zookeeper address";
+      default = "zk://${head cfg.zookeeperHosts}/mesos";
+      type = types.str;
+    };
+
+    zookeeperHosts = mkOption {
+      description = "Chronos mesos zookepper addresses";
+      default = [ "localhost:2181" ];
+      type = types.listOf types.str;
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.chronos = {
+      description = "Chronos Service";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" "zookeeper.service" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.chronos}/bin/chronos --master ${cfg.master} --zk_hosts ${concatStringsSep "," cfg.zookeeperHosts} --http_port ${toString cfg.httpPort}";
+        User = "chronos";
+      };
+    };
+
+    users.extraUsers.chronos.uid = config.ids.uids.chronos;
+  };
+}
diff --git a/nixos/modules/services/scheduling/cron.nix b/nixos/modules/services/scheduling/cron.nix
index ded3010ec5ae..1f42086dc1ec 100644
--- a/nixos/modules/services/scheduling/cron.nix
+++ b/nixos/modules/services/scheduling/cron.nix
@@ -97,12 +97,10 @@ in
 
     environment.systemPackages = [ cronNixosPkg ];
 
-    jobs.cron =
+    systemd.services.cron =
       { description = "Cron Daemon";
 
-        startOn = "startup";
-
-        path = [ cronNixosPkg ];
+        wantedBy = [ "multi-user.target" ];
 
         preStart =
           ''
@@ -119,7 +117,8 @@ in
             fi
           '';
 
-        exec = "cron -n";
+        restartTriggers = [ config.environment.etc.localtime.source ];
+        serviceConfig.ExecStart = "${cronNixosPkg}/bin/cron -n";
       };
 
   };
diff --git a/nixos/modules/services/security/haveged.nix b/nixos/modules/services/security/haveged.nix
index 1d52ed55dbda..2aa523bf70a4 100644
--- a/nixos/modules/services/security/haveged.nix
+++ b/nixos/modules/services/security/haveged.nix
@@ -46,7 +46,7 @@ in
   
     systemd.services.haveged =
       { description = "Entropy Harvesting Daemon";
-        unitConfig.documentation = "man:haveged(8)";
+        unitConfig.Documentation = "man:haveged(8)";
         wantedBy = [ "multi-user.target" ];
         
         path = [ pkgs.haveged ];
@@ -60,4 +60,4 @@ in
 
   };
   
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix
index 582dd124c290..47f863b96df2 100644
--- a/nixos/modules/services/security/tor.nix
+++ b/nixos/modules/services/security/tor.nix
@@ -3,120 +3,146 @@
 with lib;
 
 let
-
-  inherit (pkgs) tor privoxy;
-
-  stateDir = "/var/lib/tor";
-  privoxyDir = stateDir+"/privoxy";
-
   cfg = config.services.tor;
-
-  torUser = "tor";
-
-  opt = name: value: if value != "" then "${name} ${value}" else "";
-  optint = name: value: if value != 0 then "${name} ${toString value}" else "";
-
+  torDirectory = "/var/lib/tor";
+
+  opt    = name: value: optionalString (value != null) "${name} ${value}";
+  optint = name: value: optionalString (value != 0)    "${name} ${toString value}";
+
+  torRc = ''
+    User tor
+    DataDirectory ${torDirectory}
+
+    ${optint "ControlPort" cfg.controlPort}
+  ''
+  # Client connection config
+  + optionalString cfg.client.enable  ''
+    SOCKSPort ${cfg.client.socksListenAddress} IsolateDestAddr
+    SOCKSPort ${cfg.client.socksListenAddressFaster}
+    ${opt "SocksPolicy" cfg.client.socksPolicy}
+  ''
+  # Relay config
+  + optionalString cfg.relay.enable ''
+    ORPort ${cfg.relay.portSpec}
+    ${opt "Nickname" cfg.relay.nickname}
+    ${opt "ContactInfo" cfg.relay.contactInfo}
+
+    ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate}
+    ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst}
+    ${opt "AccountingMax" cfg.relay.accountingMax}
+    ${opt "AccountingStart" cfg.relay.accountingStart}
+
+    ${if cfg.relay.isExit then
+        opt "ExitPolicy" cfg.relay.exitPolicy
+      else
+        "ExitPolicy reject *:*"}
+
+    ${optionalString cfg.relay.isBridge ''
+      BridgeRelay 1
+      ServerTransportPlugin obfs2,obfs3 exec ${pkgs.pythonPackages.obfsproxy}/bin/obfsproxy managed
+    ''}
+  ''
+  + cfg.extraConfig;
+
+  torRcFile = pkgs.writeText "torrc" torRc;
 in
-
 {
-
-  ###### interface
-
   options = {
-
     services.tor = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the Tor daemon. By default, the daemon is run without
+          relay, exit, bridge or client connectivity.
+        '';
+      };
 
-      config = mkOption {
+      extraConfig = mkOption {
+        type = types.lines;
         default = "";
         description = ''
           Extra configuration. Contents will be added verbatim to the
-          configuration file.
+          configuration file at the end.
         '';
       };
 
-      client = {
+      controlPort = mkOption {
+        type = types.int;
+        default = 0;
+        example = 9051;
+        description = ''
+          If set, Tor will accept connections on the specified port
+          and allow them to control the tor process.
+        '';
+      };
 
+      client = {
         enable = mkOption {
+          type = types.bool;
           default = false;
           description = ''
-            Whether to enable Tor daemon to route application connections.
-            You might want to disable this if you plan running a dedicated Tor relay.
+            Whether to enable Tor daemon to route application
+            connections.  You might want to disable this if you plan
+            running a dedicated Tor relay.
           '';
         };
 
         socksListenAddress = mkOption {
+          type = types.str;
           default = "127.0.0.1:9050";
           example = "192.168.0.1:9100";
           description = ''
-            Bind to this address to listen for connections from Socks-speaking
-            applications.
+            Bind to this address to listen for connections from
+            Socks-speaking applications. Provides strong circuit
+            isolation, separate circuit per IP address.
           '';
         };
 
         socksListenAddressFaster = mkOption {
+          type = types.str;
           default = "127.0.0.1:9063";
+          example = "192.168.0.1:9101";
           description = ''
-            Same as socksListenAddress but uses weaker circuit isolation to provide
-            performance suitable for a web browser.
-          '';
-        };
+            Bind to this address to listen for connections from
+            Socks-speaking applications. Same as socksListenAddress
+            but uses weaker circuit isolation to provide performance
+            suitable for a web browser.
+           '';
+         };
 
         socksPolicy = mkOption {
-          default = "";
+          type = types.nullOr types.str;
+          default = null;
           example = "accept 192.168.0.0/16, reject *";
           description = ''
-            Entry policies to allow/deny SOCKS requests based on IP address.
-            First entry that matches wins. If no SocksPolicy is set, we accept
-            all (and only) requests from SocksListenAddress.
+            Entry policies to allow/deny SOCKS requests based on IP
+            address.  First entry that matches wins. If no SocksPolicy
+            is set, we accept all (and only) requests from
+            SocksListenAddress.
           '';
         };
 
-        privoxy = {
-
-          enable = mkOption {
-            default = true;
-            description = ''
-              Whether to enable a special instance of privoxy dedicated to Tor.
-              To have anonymity, protocols need to be scrubbed of identifying
-              information.
-              Most people using Tor want to anonymize their web traffic, so by
-              default we enable an special instance of privoxy specifically for
-              Tor.
-              However, if you are only going to use Tor only for other kinds of
-              traffic then you can disable this option.
-            '';
-          };
-
-          listenAddress = mkOption {
-            default = "127.0.0.1:8118";
-            description = ''
-              Address that Tor's instance of privoxy is listening to.
-              *This does not configure the standard NixOS instance of privoxy.*
-              This is for Tor connections only!
-              See services.privoxy.listenAddress to configure the standard NixOS
-              instace of privoxy.
-            '';
-          };
+        privoxy.enable = mkOption {
+          default = true;
+          description = ''
+            Whether to enable and configure the system Privoxy to use Tor's
+            faster port, suitable for HTTP.
 
-          config = mkOption {
-            default = "";
-            description = ''
-              Extra configuration for Tor's instance of privoxy. Contents will be
-              added verbatim to the configuration file.
-              *This does not configure the standard NixOS instance of privoxy.*
-              This is for Tor connections only!
-              See services.privoxy.extraConfig to configure the standard NixOS
-              instace of privoxy.
-            '';
-          };
+            To have anonymity, protocols need to be scrubbed of identifying
+            information, and this can be accomplished for HTTP by Privoxy.
 
+            Privoxy can also be useful for KDE torification. A good setup would be:
+            setting SOCKS proxy to the default Tor port, providing maximum
+            circuit isolation where possible; and setting HTTP proxy to Privoxy
+            to route HTTP traffic over faster, but less isolated port.
+          '';
         };
-
       };
 
       relay = {
-
         enable = mkOption {
+          type = types.bool;
           default = false;
           description = ''
             Whether to enable relaying TOR traffic for others.
@@ -126,16 +152,19 @@ in
         };
 
         isBridge = mkOption {
+          type = types.bool;
           default = false;
           description = ''
-            Bridge relays (or "bridges" ) are Tor relays that aren't listed in the
-            main directory. Since there is no complete public list of them, even if an
-            ISP is filtering connections to all the known Tor relays, they probably
+            Bridge relays (or "bridges") are Tor relays that aren't
+            listed in the main directory. Since there is no complete
+            public list of them, even if an ISP is filtering
+            connections to all the known Tor relays, they probably
             won't be able to block all the bridges.
 
             A bridge relay can't be an exit relay.
 
-            You need to set relay.enable to true for this option to take effect.
+            You need to set relay.enable to true for this option to
+            take effect.
 
             The bridge is set up with an obfuscated transport proxy.
 
@@ -144,25 +173,72 @@ in
         };
 
         isExit = mkOption {
+          type = types.bool;
           default = false;
           description = ''
-            An exit relay allows Tor users to access regular Internet services.
+            An exit relay allows Tor users to access regular Internet
+            services.
 
-            Unlike running a non-exit relay, running an exit relay may expose
-            you to abuse complaints. See https://www.torproject.org/faq.html.en#ExitPolicies for more info.
+            Unlike running a non-exit relay, running an exit relay may
+            expose you to abuse complaints. See
+            https://www.torproject.org/faq.html.en#ExitPolicies for
+            more info.
 
-            You can specify which services Tor users may access via your exit relay using exitPolicy option.
+            You can specify which services Tor users may access via
+            your exit relay using exitPolicy option.
           '';
         };
 
         nickname = mkOption {
+          type = types.str;
           default = "anonymous";
           description = ''
             A unique handle for your TOR relay.
           '';
         };
 
+        contactInfo = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          example = "admin@relay.com";
+          description = ''
+            Contact information for the relay owner (e.g. a mail
+            address and GPG key ID).
+          '';
+        };
+
+        accountingMax = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          example = "450 GBytes";
+          description = ''
+            Specify maximum bandwidth allowed during an accounting
+            period. This allows you to limit overall tor bandwidth
+            over some time period. See the
+            <literal>AccountingMax</literal> option by looking at the
+            tor manual (<literal>man tor</literal>) for more.
+
+            Note this limit applies individually to upload and
+            download; if you specify <literal>"500 GBytes"</literal>
+            here, then you may transfer up to 1 TBytes of overall
+            bandwidth (500 GB upload, 500 GB download).
+          '';
+        };
+
+        accountingStart = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          example = "month 1 1:00";
+          description = ''
+            Specify length of an accounting period. This allows you to
+            limit overall tor bandwidth over some time period. See the
+            <literal>AccountingStart</literal> option by looking at
+            the tor manual (<literal>man tor</literal>) for more.
+          '';
+        };
+
         bandwidthRate = mkOption {
+          type = types.int;
           default = 0;
           example = 100;
           description = ''
@@ -172,6 +248,7 @@ in
         };
 
         bandwidthBurst = mkOption {
+          type = types.int;
           default = cfg.relay.bandwidthRate;
           example = 200;
           description = ''
@@ -181,143 +258,110 @@ in
           '';
         };
 
-        port = mkOption {
-          default = 9001;
-          description = ''
-            What port to advertise for Tor connections.
-          '';
-        };
-
-        listenAddress = mkOption {
-          default = "";
-          example = "0.0.0.0:9090";
+        portSpec = mkOption {
+          type    = types.str;
+          example = "143";
           description = ''
-            Set this if you need to listen on a port other than the one advertised
-            in relayPort (e.g. to advertise 443 but bind to 9090). You'll need to do
-            ipchains or other port forwsarding yourself to make this work.
+            What port to advertise for Tor connections. This corresponds
+            to the <literal>ORPort</literal> section in the Tor manual; see
+            <literal>man tor</literal> for more details.
+
+            At a minimum, you should just specify the port for the
+            relay to listen on; a common one like 143, 22, 80, or 443
+            to help Tor users who may have very restrictive port-based
+            firewalls.
           '';
         };
 
         exitPolicy = mkOption {
-          default = "";
+          type    = types.nullOr types.str;
+          default = null;
           example = "accept *:6660-6667,reject *:*";
           description = ''
-            A comma-separated list of exit policies. They're considered first
-            to last, and the first match wins. If you want to _replace_
-            the default exit policy, end this with either a reject *:* or an
-            accept *:*. Otherwise, you're _augmenting_ (prepending to) the
-            default exit policy. Leave commented to just use the default, which is
-            available in the man page or at https://www.torproject.org/documentation.html
+            A comma-separated list of exit policies. They're
+            considered first to last, and the first match wins. If you
+            want to _replace_ the default exit policy, end this with
+            either a reject *:* or an accept *:*. Otherwise, you're
+            _augmenting_ (prepending to) the default exit
+            policy. Leave commented to just use the default, which is
+            available in the man page or at
+            https://www.torproject.org/documentation.html
 
             Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses
             for issues you might encounter if you use the default exit policy.
 
-            If certain IPs and ports are blocked externally, e.g. by your firewall,
-            you should update your exit policy to reflect this -- otherwise Tor
-            users will be told that those destinations are down.
+            If certain IPs and ports are blocked externally, e.g. by
+            your firewall, you should update your exit policy to
+            reflect this -- otherwise Tor users will be told that
+            those destinations are down.
           '';
         };
-
       };
-
     };
-
   };
 
-
-  ###### implementation
-
-  config = mkIf (cfg.client.enable || cfg.relay.enable) {
-
+  config = mkIf cfg.enable {
     assertions = singleton
-      { assertion = cfg.relay.enable -> !(cfg.relay.isBridge && cfg.relay.isExit);
-        message = "Can't be both an exit and a bridge relay at the same time";
+      { message = "Can't be both an exit and a bridge relay at the same time";
+        assertion =
+          cfg.relay.enable -> !(cfg.relay.isBridge && cfg.relay.isExit);
       };
 
-    users.extraUsers = singleton
-      { name = torUser;
-        uid = config.ids.uids.tor;
-        description = "Tor daemon user";
-        home = stateDir;
+    users.extraGroups.tor.gid = config.ids.gids.tor;
+    users.extraUsers.tor =
+      { description = "Tor Daemon User";
+        createHome  = true;
+        home        = torDirectory;
+        group       = "tor";
+        uid         = config.ids.uids.tor;
       };
 
-    jobs = {
-      tor = { name = "tor";
-
-              startOn = "started network-interfaces";
-              stopOn = "stopping network-interfaces";
-
-              preStart = ''
-                mkdir -m 0755 -p ${stateDir}
-                chown ${torUser} ${stateDir}
-              '';
-              exec = "${tor}/bin/tor -f ${pkgs.writeText "torrc" cfg.config}";
-    }; }
-    // optionalAttrs (cfg.client.privoxy.enable && cfg.client.enable) {
-      torPrivoxy = { name = "tor-privoxy";
-
-                     startOn = "started network-interfaces";
-                     stopOn = "stopping network-interfaces";
-
-                     preStart = ''
-                       mkdir -m 0755 -p ${privoxyDir}
-                       chown ${torUser} ${privoxyDir}
-                     '';
-                     exec = "${privoxy}/sbin/privoxy --no-daemon --user ${torUser} ${pkgs.writeText "torPrivoxy.conf" cfg.client.privoxy.config}";
-    }; };
-
-      services.tor.config = ''
-        DataDirectory ${stateDir}
-        User ${torUser}
-      ''
-      + optionalString cfg.client.enable  ''
-        SOCKSPort ${cfg.client.socksListenAddress} IsolateDestAddr
-        SOCKSPort ${cfg.client.socksListenAddressFaster}
-        ${opt "SocksPolicy" cfg.client.socksPolicy}
-      ''
-      + optionalString cfg.relay.enable ''
-        ORPort ${toString cfg.relay.port}
-        ${opt "ORListenAddress" cfg.relay.listenAddress }
-        ${opt "Nickname" cfg.relay.nickname}
-        ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate}
-        ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst}
-        ${if cfg.relay.isExit then opt "ExitPolicy" cfg.relay.exitPolicy else "ExitPolicy reject *:*"}
-        ${if cfg.relay.isBridge then ''
-          BridgeRelay 1
-          ServerTransportPlugin obfs2,obfs3 exec ${pkgs.pythonPackages.obfsproxy}/bin/obfsproxy managed
-        '' else ""}
-      '';
+    systemd.services.tor =
+      { description = "Tor Daemon";
+        path = [ pkgs.tor ];
+
+        wantedBy = [ "multi-user.target" ];
+        after    = [ "network.target" ];
+        restartTriggers = [ torRcFile ];
+
+        # Translated from the upstream contrib/dist/tor.service.in
+        serviceConfig =
+          { Type         = "simple";
+            ExecStartPre = "${pkgs.tor}/bin/tor -f ${torRcFile} --verify-config";
+            ExecStart    = "${pkgs.tor}/bin/tor -f ${torRcFile} --RunAsDaemon 0";
+            ExecReload   = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+            KillSignal   = "SIGINT";
+            TimeoutSec   = 30;
+            Restart      = "on-failure";
+            LimitNOFILE  = 32768;
+
+            # Hardening
+            # Note: DevicePolicy is set to 'closed', although the
+            # minimal permissions are really:
+            #   DeviceAllow /dev/null rw
+            #   DeviceAllow /dev/urandom r
+            # .. but we can't specify DeviceAllow multiple times. 'closed'
+            # is close enough.
+            PrivateTmp              = "yes";
+            DevicePolicy            = "closed";
+            InaccessibleDirectories = "/home";
+            ReadOnlyDirectories     = "/";
+            ReadWriteDirectories    = torDirectory;
+            NoNewPrivileges         = "yes";
+          };
+      };
 
-      services.tor.client.privoxy.config = ''
-        # Generally, this file goes in /etc/privoxy/config
-        #
-        # Tor listens as a SOCKS4a proxy here:
+    environment.systemPackages = [ pkgs.tor ];
+
+    services.privoxy = mkIf (cfg.client.enable && cfg.client.privoxy.enable) {
+      enable = true;
+      extraConfig = ''
         forward-socks4a / ${cfg.client.socksListenAddressFaster} .
-        confdir ${privoxy}/etc
-        logdir ${privoxyDir}
-        # actionsfile standard  # Internal purpose, recommended
-        actionsfile default.action   # Main actions file
-        actionsfile user.action      # User customizations
-        filterfile default.filter
-
-        # Don't log interesting things, only startup messages, warnings and errors
-        logfile logfile
-        #jarfile jarfile
-        #debug   0    # show each GET/POST/CONNECT request
-        debug   4096 # Startup banner and warnings
-        debug   8192 # Errors - *we highly recommended enabling this*
-
-        user-manual ${privoxy}/doc/privoxy/user-manual
-        listen-address  ${cfg.client.privoxy.listenAddress}
         toggle  1
         enable-remote-toggle 0
         enable-edit-actions 0
         enable-remote-http-toggle 0
-        buffer-limit 4096
-
-        # Extra config goes here
       '';
-
+    };
   };
-
 }
diff --git a/nixos/modules/services/security/torify.nix b/nixos/modules/services/security/torify.nix
index 53f48a714b4b..a81cdbbc172f 100644
--- a/nixos/modules/services/security/torify.nix
+++ b/nixos/modules/services/security/torify.nix
@@ -5,13 +5,13 @@ let
   cfg = config.services.tor;
 
   torify = pkgs.writeTextFile {
-    name = "torify";
+    name = "tsocks";
     text = ''
         #!${pkgs.stdenv.shell}
-        TSOCKS_CONF_FILE=${pkgs.writeText "tsocks.conf" cfg.torify.config} LD_PRELOAD="${pkgs.tsocks}/lib/libtsocks.so $LD_PRELOAD" "$@"
+        TSOCKS_CONF_FILE=${pkgs.writeText "tsocks.conf" cfg.tsocks.config} LD_PRELOAD="${pkgs.tsocks}/lib/libtsocks.so $LD_PRELOAD" "$@"
     '';
     executable = true;
-    destination = "/bin/torify";
+    destination = "/bin/tsocks";
   };
 
 in
@@ -22,12 +22,12 @@ in
   
   options = {
   
-    services.tor.torify = {
+    services.tor.tsocks = {
 
       enable = mkOption {
-        default = cfg.client.enable;
+        default = cfg.enable && cfg.client.enable;
         description = ''
-          Whether to build torify scipt to relay application traffic via TOR.
+          Whether to build tsocks wrapper script to relay application traffic via TOR.
         '';
       };
 
@@ -53,13 +53,13 @@ in
 
   ###### implementation
 
-  config = mkIf cfg.torify.enable {
+  config = mkIf cfg.tsocks.enable {
 
     environment.systemPackages = [ torify ];  # expose it to the users
 
-    services.tor.torify.config = ''
-      server = ${toString(head (splitString ":" cfg.torify.server))}
-      server_port = ${toString(tail (splitString ":" cfg.torify.server))}
+    services.tor.tsocks.config = ''
+      server = ${toString(head (splitString ":" cfg.tsocks.server))}
+      server_port = ${toString(tail (splitString ":" cfg.tsocks.server))}
 
       local = 127.0.0.0/255.128.0.0
       local = 127.128.0.0/255.192.0.0
diff --git a/nixos/modules/services/security/torsocks.nix b/nixos/modules/services/security/torsocks.nix
index ede6c983677a..1b5a05b21e77 100644
--- a/nixos/modules/services/security/torsocks.nix
+++ b/nixos/modules/services/security/torsocks.nix
@@ -1,85 +1,121 @@
 { config, lib, pkgs, ... }:
+
 with lib;
+
 let
+  cfg = config.services.tor.torsocks;
+  optionalNullStr = b: v: optionalString (b != null) v;
 
-  cfg = config.services.tor;
+  configFile = server: ''
+    TorAddress ${toString (head (splitString ":" server))}
+    TorPort    ${toString (tail (splitString ":" server))}
 
-  makeConfig = server: ''
-      server = ${toString(head (splitString ":" server))}
-      server_port = ${toString(tail (splitString ":" server))}
+    OnionAddrRange ${cfg.onionAddrRange}
 
-      local = 127.0.0.0/255.128.0.0
-      local = 127.128.0.0/255.192.0.0
-      local = 169.254.0.0/255.255.0.0
-      local = 172.16.0.0/255.240.0.0
-      local = 192.168.0.0/255.255.0.0
+    ${optionalNullStr cfg.socks5Username
+        "SOCKS5Username ${cfg.socks5Username}"}
+    ${optionalNullStr cfg.socks5Password
+        "SOCKS5Password ${cfg.socks5Password}"}
 
-      ${cfg.torsocks.config}
-    '';
-  makeTorsocks = name: server: pkgs.writeTextFile {
+    AllowInbound ${if cfg.allowInbound then "1" else "0"}
+  '';
+
+  wrapTorsocks = name: server: pkgs.writeTextFile {
     name = name;
     text = ''
         #!${pkgs.stdenv.shell}
-        TORSOCKS_CONF_FILE=${pkgs.writeText "torsocks.conf" (makeConfig server)} LD_PRELOAD="${pkgs.torsocks}/lib/torsocks/libtorsocks.so $LD_PRELOAD" "$@"
+        TORSOCKS_CONF_FILE=${pkgs.writeText "torsocks.conf" (configFile server)} ${pkgs.torsocks}/bin/torsocks "$@"
     '';
     executable = true;
     destination = "/bin/${name}";
   };
 
-  torsocks = makeTorsocks "torsocks" cfg.torsocks.server;
-  torsocksFaster = makeTorsocks "torsocks-faster" cfg.torsocks.serverFaster;
 in
-
 {
-
-  ###### interface
-
   options = {
-
     services.tor.torsocks = {
-
       enable = mkOption {
-        default = cfg.client.enable;
+        type        = types.bool;
+        default     = config.services.tor.enable && config.services.tor.client.enable;
         description = ''
-          Whether to build torsocks scipt to relay application traffic via TOR.
+          Whether to build <literal>/etc/tor/torsocks.conf</literal>
+          containing the specified global torsocks configuration.
         '';
       };
 
       server = mkOption {
-        default = cfg.client.socksListenAddress;
-        example = "192.168.0.20:9050";
+        type    = types.str;
+        default = "127.0.0.1:9050";
+        example = "192.168.0.20:1234";
         description = ''
-          IP address of TOR client to use.
+          IP/Port of the Tor SOCKS server. Currently, hostnames are
+          NOT supported by torsocks.
         '';
       };
 
-      serverFaster = mkOption {
-        default = cfg.client.socksListenAddressFaster;
-        example = "192.168.0.20:9063";
+      fasterServer = mkOption {
+        type    = types.str;
+        default = "127.0.0.1:9063";
+        example = "192.168.0.20:1234";
         description = ''
-          IP address of TOR client to use for applications like web browsers which
-	  need less circuit isolation to achive satisfactory performance.
+          IP/Port of the Tor SOCKS server for torsocks-faster wrapper suitable for HTTP.
+          Currently, hostnames are NOT supported by torsocks.
         '';
       };
 
-      config = mkOption {
-        default = "";
+      onionAddrRange = mkOption {
+        type    = types.str;
+        default = "127.42.42.0/24";
         description = ''
-          Extra configuration. Contents will be added verbatim to torsocks
-          configuration file.
+          Tor hidden sites do not have real IP addresses. This
+          specifies what range of IP addresses will be handed to the
+          application as "cookies" for .onion names.  Of course, you
+          should pick a block of addresses which you aren't going to
+          ever need to actually connect to. This is similar to the
+          MapAddress feature of the main tor daemon.
         '';
       };
 
-    };
+      socks5Username = mkOption {
+        type    = types.nullOr types.str;
+        default = null;
+        example = "bob";
+        description = ''
+          SOCKS5 username. The <literal>TORSOCKS_USERNAME</literal>
+          environment variable overrides this option if it is set.
+        '';
+      };
 
-  };
+      socks5Password = mkOption {
+        type    = types.nullOr types.str;
+        default = null;
+        example = "sekret";
+        description = ''
+          SOCKS5 password. The <literal>TORSOCKS_PASSWORD</literal>
+          environment variable overrides this option if it is set.
+        '';
+      };
 
-  ###### implementation
+      allowInbound = mkOption {
+        type    = types.bool;
+        default = false;
+        description = ''
+          Set Torsocks to accept inbound connections. If set to
+          <literal>true</literal>, listen() and accept() will be
+          allowed to be used with non localhost address.
+        '';
+      };
 
-  config = mkIf cfg.torsocks.enable {
+    };
+  };
 
-    environment.systemPackages = [ torsocks torsocksFaster ];  # expose it to the users
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.torsocks (wrapTorsocks "torsocks-faster" cfg.fasterServer) ];
 
+    environment.etc =
+      [ { source = pkgs.writeText "torsocks.conf" (configFile cfg.server);
+          target = "tor/torsocks.conf";
+        }
+      ];
   };
-
 }
diff --git a/nixos/modules/services/system/cloud-init.nix b/nixos/modules/services/system/cloud-init.nix
new file mode 100644
index 000000000000..0ef31ef8a8b9
--- /dev/null
+++ b/nixos/modules/services/system/cloud-init.nix
@@ -0,0 +1,152 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.cloud-init;
+    path = with pkgs; [ cloud-init nettools utillinux e2fsprogs shadow dmidecode openssh ];
+    configFile = pkgs.writeText "cloud-init.cfg" ''
+users:
+   - root
+
+disable_root: false
+preserve_hostname: false
+
+cloud_init_modules:
+ - migrator
+ - seed_random
+ - bootcmd
+ - write-files
+ - growpart
+ - resizefs
+ - set_hostname
+ - update_hostname
+ - update_etc_hosts
+ - ca-certs
+ - rsyslog
+ - users-groups
+
+cloud_config_modules:
+ - emit_upstart
+ - disk_setup
+ - mounts
+ - ssh-import-id
+ - set-passwords
+ - timezone
+ - disable-ec2-metadata
+ - runcmd
+ - ssh
+
+cloud_final_modules:
+ - rightscale_userdata
+ - scripts-vendor
+ - scripts-per-once
+ - scripts-per-boot
+ - scripts-per-instance
+ - scripts-user
+ - ssh-authkey-fingerprints
+ - keys-to-console
+ - phone-home
+ - final-message
+ - power-state-change
+'';
+in
+{
+  options = {
+
+    services.cloud-init = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the cloud-init service. This services reads
+          configuration metadata in a cloud environment and configures
+          the machine according to this metadata.
+
+          This configuration is not completely compatible with the
+          NixOS way of doing configuration, as configuration done by
+          cloud-init might be overriden by a subsequent nixos-rebuild
+          call. However, some parts of cloud-init fall outside of
+          NixOS's responsibility, like filesystem resizing and ssh
+          public key provisioning, and cloud-init is useful for that
+          parts. Thus, be wary that using cloud-init in NixOS might
+          come as some cost.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.cloud-init-local =
+      { description = "Initial cloud-init job (pre-networking)";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "local-fs.target" ];
+        after = [ "local-fs.target" ];
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} init --local";
+            RemainAfterExit = "yes";
+            TimeoutSec = "0";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.services.cloud-init =
+      { description = "Initial cloud-init job (metadata service crawler)";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "local-fs.target" "cloud-init-local.service" "sshd.service" "sshd-keygen.service" ];
+        after = [ "local-fs.target" "network.target" "cloud-init-local.service" ];
+        before = [ "sshd.service" "sshd-keygen.service" ];
+        requires = [ "network.target "];
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} init";
+            RemainAfterExit = "yes";
+            TimeoutSec = "0";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.services.cloud-config =
+      { description = "Apply the settings specified in cloud-config";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "network.target" ];
+        after = [ "network.target" "syslog.target" "cloud-config.target" ];
+
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} modules --mode=config";
+            RemainAfterExit = "yes";
+            TimeoutSec = "0";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.services.cloud-final =
+      { description = "Execute cloud user/final scripts";
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "network.target" ];
+        after = [ "network.target" "syslog.target" "cloud-config.service" "rc-local.service" ];
+        requires = [ "cloud-config.target" ];
+        path = path;
+        serviceConfig =
+          { Type = "oneshot";
+            ExecStart = "${pkgs.cloud-init}/bin/cloud-init -f ${configFile} modules --mode=final";
+            RemainAfterExit = "yes";
+            TimeoutSec = "0";
+            StandardOutput = "journal+console";
+          };
+      };
+
+    systemd.targets.cloud-config =
+      { description = "Cloud-config availability";
+        requires = [ "cloud-init-local.service" "cloud-init.service" ];
+      };
+  };
+}
diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix
index 5460e962ea2c..0879d9b85bd8 100644
--- a/nixos/modules/services/system/nscd.nix
+++ b/nixos/modules/services/system/nscd.nix
@@ -62,7 +62,7 @@ in
             mkdir -m 0755 -p /var/db/nscd
           '';
 
-        restartTriggers = [ config.environment.etc.hosts.source ];
+        restartTriggers = [ config.environment.etc.hosts.source config.environment.etc."nsswitch.conf".source ];
 
         serviceConfig =
           { ExecStart = "@${pkgs.glibc}/sbin/nscd nscd -f ${cfgFile}";
diff --git a/nixos/modules/services/torrent/peerflix.nix b/nixos/modules/services/torrent/peerflix.nix
new file mode 100644
index 000000000000..0360deac08bb
--- /dev/null
+++ b/nixos/modules/services/torrent/peerflix.nix
@@ -0,0 +1,63 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.peerflix;
+
+  configFile = pkgs.writeText "peerflix-config.json" ''
+    {
+      "connections": 50,
+      "tmp": "${cfg.downloadDir}"
+    }
+  '';
+
+in {
+
+  ###### interface
+
+  options.services.peerflix = {
+    enable = mkOption {
+      description = "Whether to enable peerflix service.";
+      default = false;
+      type = types.uniq types.bool;
+    };
+
+    stateDir = mkOption {
+      description = "Peerflix state directory.";
+      default = "/var/lib/peerflix";
+      type = types.path;
+    };
+
+    downloadDir = mkOption {
+      description = "Peerflix temporary download directory.";
+      default = "${cfg.stateDir}/torrents";
+      type = types.path;
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.peerflix = {
+      description = "Peerflix Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      environment.HOME = cfg.stateDir;
+
+      preStart = ''
+        mkdir -p "${cfg.stateDir}"/{torrents,.config/peerflix-server}
+        if [ "$(id -u)" = 0 ]; then chown -R peerflix "${cfg.stateDir}"; fi
+        ln -fs "${configFile}" "${cfg.stateDir}/.config/peerflix-server/config.json"
+      '';
+
+      serviceConfig = {
+        ExecStart = "${pkgs.nodePackages.peerflix-server}/bin/peerflix-server";
+        PermissionsStartOnly = true;
+        User = "peerflix";
+      };
+    };
+
+    users.extraUsers.peerflix.uid = config.ids.uids.peerflix;
+  };
+}
diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
index 02db4a7a5b2b..1b38ea3b679b 100644
--- a/nixos/modules/services/torrent/transmission.nix
+++ b/nixos/modules/services/torrent/transmission.nix
@@ -88,7 +88,7 @@ in
   config = mkIf cfg.enable {
     systemd.services.transmission = {
       description = "Transmission BitTorrent Service";
-      after = [ "network.target" ] ++ optional apparmor "apparmor.service";
+      after = [ "local-fs.target" "network.target" ] ++ optional apparmor "apparmor.service";
       requires = mkIf apparmor [ "apparmor.service" ];
       wantedBy = [ "multi-user.target" ];
 
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 85458a2ab565..d5a57eddd5e7 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -109,6 +109,11 @@ let
       "mpm_${mainCfg.multiProcessingModule}"
       "authz_core"
       "unixd"
+      "cache" "cache_disk"
+      "slotmem_shm"
+      "socache_shmcb"
+      # For compatibility with old configurations, the new module mod_access_compat is provided.
+      "access_compat"
     ]
     ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
     ++ optional enableSSL "ssl"
@@ -160,9 +165,9 @@ let
 
 
   sslConf = ''
-    SSLSessionCache shm:${mainCfg.stateDir}/ssl_scache(512000)
+    SSLSessionCache ${if version24 then "shmcb" else "shm"}:${mainCfg.stateDir}/ssl_scache(512000)
 
-    SSLMutex posixsem
+    ${if version24 then "Mutex" else "SSLMutex"} posixsem
 
     SSLRandomSeed startup builtin
     SSLRandomSeed connect builtin
@@ -420,8 +425,7 @@ in
 
       package = mkOption {
         type = types.package;
-        default = pkgs.apacheHttpd.override { mpm = mainCfg.multiProcessingModule; };
-        example = literalExample "pkgs.apacheHttpd_2_4";
+        default = pkgs.apacheHttpd;
         description = ''
           Overridable attribute of the Apache HTTP Server package to use.
         '';
@@ -593,11 +597,11 @@ in
   ###### implementation
 
   config = mkIf config.services.httpd.enable {
-  
+
     assertions = [ { assertion = mainCfg.enableSSL == true
                                -> mainCfg.sslServerCert != null
                                     && mainCfg.sslServerKey != null;
-                     message = "SSL is enabled for HTTPD, but sslServerCert and/or sslServerKey haven't been specified."; }
+                     message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; }
                  ];
 
     users.extraUsers = optionalAttrs (mainCfg.user == "wwwrun") (singleton
diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
index d7bdd81b7ebe..c0ed20416397 100644
--- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
@@ -4,6 +4,17 @@ with lib;
 
 let
 
+  httpd = serverInfo.serverConfig.package;
+
+  version24 = !versionOlder httpd.version "2.4";
+
+  allGranted = if version24 then ''
+    Require all granted
+  '' else ''
+    Order allow,deny
+    Allow from all
+  '';
+
   mediawikiConfig = pkgs.writeText "LocalSettings.php"
     ''
       <?php
@@ -121,8 +132,7 @@ in
         Alias ${config.urlPrefix}/images ${config.uploadDir}
 
         <Directory ${config.uploadDir}>
-            Order allow,deny
-            Allow from all
+            ${allGranted}
             Options -Indexes
         </Directory>
       ''}
@@ -142,8 +152,7 @@ in
       ''}
 
       <Directory ${mediawikiRoot}>
-          Order allow,deny
-          Allow from all
+          ${allGranted}
           DirectoryIndex index.php
       </Directory>
 
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 7c2d3a42973a..0af1b58b7cae 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -23,6 +23,7 @@ in
     services.nginx = {
       enable = mkOption {
         default = false;
+        type = types.bool;
         description = "
           Enable the nginx Web Server.
         ";
@@ -70,11 +71,13 @@ in
       };
 
       user = mkOption {
+        type = types.str;
         default = "nginx";
         description = "User account under which nginx runs.";
       };
 
       group = mkOption {
+        type = types.str;
         default = "nginx";
         description = "Group account under which nginx runs.";
       };
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index ebdb2ad06491..bffbb56e6816 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
-    ./e17.nix ./e18.nix ./e19.nix ./gnome3.nix ./xbmc.nix
+    ./e19.nix ./gnome3.nix ./xbmc.nix
   ];
 
   options = {
diff --git a/nixos/modules/services/x11/desktop-managers/e17.nix b/nixos/modules/services/x11/desktop-managers/e17.nix
deleted file mode 100644
index 4cac53c9c75b..000000000000
--- a/nixos/modules/services/x11/desktop-managers/e17.nix
+++ /dev/null
@@ -1,30 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  xcfg = config.services.xserver;
-  cfg = xcfg.desktopManager.e17;
-
-in
-
-{
-  options = {
-
-    services.xserver.desktopManager.e17.enable = mkOption {
-      default = false;
-      example = true;
-      description = "Enable support for the E17 desktop environment.";
-    };
-
-  };
-
-
-  config = mkIf (xcfg.enable && cfg.enable) {
-
-    services.dbus.packages = [ pkgs.e17.ethumb ];
-
-  };
-
-}
diff --git a/nixos/modules/services/x11/desktop-managers/e18.nix b/nixos/modules/services/x11/desktop-managers/e18.nix
deleted file mode 100644
index faafd21b07dd..000000000000
--- a/nixos/modules/services/x11/desktop-managers/e18.nix
+++ /dev/null
@@ -1,43 +0,0 @@
-{ config, pkgs, lib, ... }:
-
-with lib;
-
-let
-
-  xcfg = config.services.xserver;
-  cfg = xcfg.desktopManager.e18;
-  e18_enlightenment = pkgs.e18.enlightenment.override { set_freqset_setuid = true; };
-
-in
-
-{
-  options = {
-
-    services.xserver.desktopManager.e18.enable = mkOption {
-      default = false;
-      example = true;
-      description = "Enable the E18 desktop environment.";
-    };
-
-  };
-
-  config = mkIf (xcfg.enable && cfg.enable) {
-
-    environment.systemPackages = [
-      pkgs.e18.efl pkgs.e18.evas pkgs.e18.emotion pkgs.e18.elementary e18_enlightenment
-      pkgs.e18.terminology pkgs.e18.econnman
-    ];
-
-    services.xserver.desktopManager.session = [
-    { name = "E18";
-      start = ''
-        ${e18_enlightenment}/bin/enlightenment_start
-        waitPID=$!
-      '';
-    }];
-
-    security.setuidPrograms = [ "e18_freqset" ];
-
-  };
-
-}
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 5ac1a9591fdf..c4329cd77550 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -44,9 +44,10 @@ in {
     };
 
     environment.gnome3.packageSet = mkOption {
-      default = pkgs.gnome3;
+      default = null;
       example = literalExample "pkgs.gnome3_12";
-      description = "Which Gnome 3 package set to use.";
+      description = "Which GNOME 3 package set to use.";
+      apply = p: if p == null then pkgs.gnome3 else p;
     };
     
     environment.gnome3.excludePackages = mkOption {
@@ -79,7 +80,6 @@ in {
     services.telepathy.enable = mkDefault true;
     networking.networkmanager.enable = mkDefault true;
     services.upower.enable = config.powerManagement.enable;
-    services.upower.package = gnome3.upower;
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix
index 5c783fdbcedd..16c99862e9e0 100644
--- a/nixos/modules/services/x11/desktop-managers/kde4.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde4.nix
@@ -152,7 +152,9 @@ in
           xorg.xauth # used by kdesu
           pkgs.shared_desktop_ontologies # used by nepomuk
           pkgs.strigi # used by nepomuk
+          pkgs.kde4.akonadi
           pkgs.mysql # used by akonadi
+          pkgs.kde4.kdepim_runtime
         ]
       ++ lib.optional config.hardware.pulseaudio.enable pkgs.kde4.kmix  # Perhaps this should always be enabled
       ++ lib.optional config.hardware.bluetooth.enable pkgs.kde4.bluedevil
@@ -161,6 +163,10 @@ in
 
     environment.pathsToLink = [ "/share" ];
 
+    environment.profileRelativeEnvVars = mkIf (lib.elem "gstreamer" cfg.phononBackends) {
+      GST_PLUGIN_SYSTEM_PATH = [ "/lib/gstreamer-0.10" ];
+    };
+
     environment.etc = singleton
       { source = "${pkgs.xkeyboard_config}/etc/X11/xkb";
         target = "X11/xkb";
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index a31f66176cc9..6a14a163c19a 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -56,6 +56,7 @@ in
         pkgs.xfce.xfce4session
         pkgs.xfce.xfce4settings
         pkgs.xfce.xfce4mixer
+        pkgs.xfce.xfce4volumed
         pkgs.xfce.xfce4screenshooter
         pkgs.xfce.xfconf
         pkgs.xfce.xfdesktop
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 004ea6ef49ac..a1b5daa3336d 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -23,6 +23,17 @@ let
     pathsToLink = [ "/" ];
   };
 
+  fontconfig = config.fonts.fontconfig;
+  xresourcesXft = pkgs.writeText "Xresources-Xft" ''
+    ${optionalString (fontconfig.dpi != 0) ''Xft.dpi: ${fontconfig.dpi}''}
+    Xft.antialias: ${if fontconfig.antialias then "1" else "0"}
+    Xft.rgba: ${fontconfig.subpixel.rgba}
+    Xft.lcdfilter: lcd${fontconfig.subpixel.lcdfilter}
+    Xft.hinting: ${if fontconfig.hinting.enable then "1" else "0"}
+    Xft.autohint: ${if fontconfig.hinting.autohint then "1" else "0"}
+    Xft.hintstyle: hint${fontconfig.hinting.style}
+  '';
+
   # file provided by services.xserver.displayManager.session.script
   xsession = wm: dm: pkgs.writeScript "xsession"
     ''
@@ -68,18 +79,21 @@ let
       # Start PulseAudio if enabled.
       ${optionalString (config.hardware.pulseaudio.enable) ''
         ${optionalString (!config.hardware.pulseaudio.systemWide)
-          "${pkgs.pulseaudio}/bin/pulseaudio --start"
+          "${config.hardware.pulseaudio.package}/bin/pulseaudio --start"
         }
 
         # Publish access credentials in the root window.
-        ${pkgs.pulseaudio}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
+        ${config.hardware.pulseaudio.package}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
 
         # Keep track of devices.  Mostly useful for Phonon/KDE.
-        ${pkgs.pulseaudio}/bin/pactl load-module module-device-manager "do_routing=1"
+        ${config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
       ''}
 
       # Load X defaults.
-      if test -e ~/.Xdefaults; then
+      ${xorg.xrdb}/bin/xrdb -merge ${xresourcesXft}
+      if test -e ~/.Xresources; then
+          ${xorg.xrdb}/bin/xrdb -merge ~/.Xresources
+      elif test -e ~/.Xdefaults; then
           ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults
       fi
 
@@ -175,7 +189,7 @@ in
       xserverArgs = mkOption {
         type = types.listOf types.str;
         default = [];
-        example = [ "-ac" "-logverbose" "-nolisten tcp" ];
+        example = [ "-ac" "-logverbose" "-verbose" "-nolisten tcp" ];
         description = "List of arguments for the X server.";
         apply = toString;
       };
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index 9d14fc2e137c..080588df2472 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -5,8 +5,8 @@ with lib;
 let
 
   cfg = config.services.xserver.displayManager;
-  gdm = pkgs.gnome3_12.gdm; # gdm 3.10 not supported
   gnome3 = config.environment.gnome3.packageSet;
+  gdm = gnome3.gdm;
 
 in
 
diff --git a/nixos/modules/services/x11/hardware/synaptics.nix b/nixos/modules/services/x11/hardware/synaptics.nix
index f5b394b6d98b..9e44ce811c3e 100644
--- a/nixos/modules/services/x11/hardware/synaptics.nix
+++ b/nixos/modules/services/x11/hardware/synaptics.nix
@@ -7,9 +7,9 @@ let cfg = config.services.xserver.synaptics;
     enabledTapConfig = ''
       Option "MaxTapTime" "180"
       Option "MaxTapMove" "220"
-      Option "TapButton1" "${builtins.elemAt cfg.buttonsMap 0}"
-      Option "TapButton2" "${builtins.elemAt cfg.buttonsMap 1}"
-      Option "TapButton3" "${builtins.elemAt cfg.buttonsMap 2}"
+      Option "TapButton1" "${builtins.elemAt cfg.fingersMap 0}"
+      Option "TapButton2" "${builtins.elemAt cfg.fingersMap 1}"
+      Option "TapButton3" "${builtins.elemAt cfg.fingersMap 2}"
     '';
     disabledTapConfig = ''
       Option "MaxTapTime" "0"
@@ -25,12 +25,14 @@ in {
     services.xserver.synaptics = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         example = true;
         description = "Whether to enable touchpad support.";
       };
 
       dev = mkOption {
+        type = types.nullOr types.str;
         default = null;
         example = "/dev/input/event0";
         description =
@@ -59,41 +61,56 @@ in {
       };
 
       twoFingerScroll = mkOption {
+        type = types.bool;
         default = false;
         description = "Whether to enable two-finger drag-scrolling.";
       };
 
       vertEdgeScroll = mkOption {
+        type = types.bool;
         default = ! cfg.twoFingerScroll;
         description = "Whether to enable vertical edge drag-scrolling.";
       };
 
       tapButtons = mkOption {
+        type = types.bool;
         default = true;
         example = false;
         description = "Whether to enable tap buttons.";
       };
 
       buttonsMap = mkOption {
+        type = types.listOf types.int;
         default = [1 2 3];
         example = [1 3 2];
         description = "Remap touchpad buttons.";
         apply = map toString;
       };
 
+      fingersMap = mkOption {
+        type = types.listOf types.int;
+        default = [1 2 3];
+        example = [1 3 2];
+        description = "Remap several-fingers taps.";
+        apply = map toString;
+      };
+
       palmDetect = mkOption {
+        type = types.bool;
         default = false;
         example = true;
         description = "Whether to enable palm detection (hardware support required)";
       };
 
       horizontalScroll = mkOption {
+        type = types.bool;
         default = true;
         example = false;
         description = "Whether to enable horizontal scrolling (on touchpad)";
       };
 
       additionalOptions = mkOption {
+        type = types.str;
         default = "";
         example = ''
           Option "RTCornerButton" "2"
diff --git a/nixos/modules/services/x11/window-managers/awesome.nix b/nixos/modules/services/x11/window-managers/awesome.nix
index 9b2f042a87a6..455b3568499f 100644
--- a/nixos/modules/services/x11/window-managers/awesome.nix
+++ b/nixos/modules/services/x11/window-managers/awesome.nix
@@ -5,6 +5,7 @@ with lib;
 let
 
   cfg = config.services.xserver.windowManager.awesome;
+  awesome = cfg.package;
 
 in
 
@@ -14,9 +15,24 @@ in
 
   options = {
 
-    services.xserver.windowManager.awesome.enable = mkOption {
-      default = false;
-      description = "Enable the Awesome window manager.";
+    services.xserver.windowManager.awesome = {
+
+      enable = mkEnableOption "Awesome window manager";
+
+      luaModules = mkOption {
+        default = [];
+        type = types.listOf types.package;
+        description = "List of lua packages available for being used in the Awesome configuration.";
+        example = literalExample "[ luaPackages.oocairo ]";
+      };
+
+      package = mkOption {
+        default = null;
+        type = types.nullOr types.package;
+        description = "Package to use for running the Awesome WM.";
+        apply = pkg: if pkg == null then pkgs.awesome else pkg;
+      };
+
     };
 
   };
@@ -30,12 +46,17 @@ in
       { name = "awesome";
         start =
           ''
-            ${pkgs.awesome}/bin/awesome &
+            ${concatMapStrings (pkg: ''
+              export LUA_CPATH=$LUA_CPATH''${LUA_CPATH:+;}${pkg}/lib/lua/${awesome.lua.luaversion}/?.so
+              export LUA_PATH=$LUA_PATH''${LUA_PATH:+;}${pkg}/lib/lua/${awesome.lua.luaversion}/?.lua
+            '') cfg.luaModules}
+
+            ${awesome}/bin/awesome &
             waitPID=$!
           '';
       };
 
-    environment.systemPackages = [ pkgs.awesome ];
+    environment.systemPackages = [ awesome ];
 
   };
 
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index f911d3c81f90..64e0d4d8050e 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -483,8 +483,6 @@ in
 
     services.xserver.displayManager.xserverArgs =
       [ "-ac"
-        "-logverbose"
-        "-verbose"
         "-terminate"
         "-logfile" "/var/log/X.${toString cfg.display}.log"
         "-config ${configFile}"
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index 12012698efe3..c814469ae41d 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -181,7 +181,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
             } elsif ($unit =~ /\.mount$/) {
                 # Reload the changed mount unit to force a remount.
                 write_file($reloadListFile, { append => 1 }, "$unit\n");
-            } elsif ($unit =~ /\.socket$/ || $unit =~ /\.path$/) {
+            } elsif ($unit =~ /\.socket$/ || $unit =~ /\.path$/ || $unit =~ /\.slice$/) {
                 # FIXME: do something?
             } else {
                 my $unitInfo = parseUnit($newUnitFile);
@@ -321,6 +321,10 @@ 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", "dbus.service");
+
 # Restart changed services (those that have to be restarted rather
 # than stopped and started).
 my @restart = unique(split('\n', read_file($restartListFile, err_mode => 'quiet') // ""));
@@ -350,8 +354,6 @@ if (scalar @reload > 0) {
     unlink($reloadListFile);
 }
 
-# Signal dbus to reload its configuration.
-system("@systemd@/bin/systemctl", "reload", "dbus.service");
 
 # Print failed and new units.
 my (@failed, @new, @restarting);
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index 62999dceee39..d7a1e205b4d4 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -88,7 +88,7 @@ let
 
   failed = map (x: x.message) (filter (x: !x.assertion) config.assertions);
 
-  showWarnings = res: fold (w: x: builtins.trace "^[[1;31mwarning: ${w}^[[0m" x) res config.warnings;
+  showWarnings = res: fold (w: x: builtins.trace "warning: ${w}" x) res config.warnings;
 
   # Putting it all together.  This builds a store path containing
   # symlinks to the various parts of the built configuration (the
@@ -147,7 +147,7 @@ in
       default = [];
       description = ''
         Additional configurations to build based on the current
-        configuration which is has a lower priority.
+        configuration which then has a lower priority.
       '';
     };
 
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index 981b60c004c2..ffee0271e93b 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -341,8 +341,9 @@ addEntry("NixOS - Default", $defaultConfig);
 
 $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
 
+my $grubBootPath = $grubBoot->path;
 # extraEntries could refer to @bootRoot@, which we have to substitute
-$conf =~ s/\@bootRoot\@/$grubBoot->path/g;
+$conf =~ s/\@bootRoot\@/$grubBootPath/g;
 
 # Emit submenus for all system profiles.
 sub addProfile {
diff --git a/nixos/modules/system/boot/loader/grub/ipxe.nix b/nixos/modules/system/boot/loader/grub/ipxe.nix
new file mode 100644
index 000000000000..9b5097a4cfd9
--- /dev/null
+++ b/nixos/modules/system/boot/loader/grub/ipxe.nix
@@ -0,0 +1,64 @@
+# This module adds a scripted iPXE entry to the GRUB boot menu.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  scripts = builtins.attrNames config.boot.loader.grub.ipxe;
+
+  grubEntry = name:
+    ''
+      menuentry "iPXE - ${name}" {
+        linux16 @bootRoot@/ipxe.lkrn
+        initrd16 @bootRoot@/${name}.ipxe
+      }
+
+    '';
+
+  scriptFile = name:
+    let
+      value = builtins.getAttr name config.boot.loader.grub.ipxe;
+    in
+    if builtins.typeOf value == "path" then value
+    else builtins.toFile "${name}.ipxe" value;
+in
+{
+  options =
+    { boot.loader.grub.ipxe = mkOption {
+        type = types.attrsOf (types.either types.path types.str);
+        description =
+          ''
+            Set of iPXE scripts available for
+            booting from the GRUB boot menu.
+          '';
+        default = { };
+        example = literalExample ''
+          { demo = '''
+              #!ipxe
+              dhcp
+              chain http://boot.ipxe.org/demo/boot.php
+            ''';
+          };
+        '';
+      };
+    };
+
+  config = mkIf (builtins.length scripts != 0) {
+
+    boot.loader.grub.extraEntries =
+      if config.boot.loader.grub.version == 2 then
+        toString (map grubEntry scripts)
+      else
+        throw "iPXE is not supported with GRUB 1.";
+
+    boot.loader.grub.extraFiles =
+      { "ipxe.lkrn" = "${pkgs.ipxe}/ipxe.lkrn"; }
+      //
+      builtins.listToAttrs ( map
+        (name: { name = name+".ipxe"; value = scriptFile name; })
+        scripts
+      );
+  };
+
+}
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 70ff1d588a36..e1e472186e37 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -203,7 +203,7 @@ in
       description = ''
         Unless enabled, encryption keys can be easily recovered by an attacker with physical
         access to any machine with PCMCIA, ExpressCard, ThunderBolt or FireWire port.
-        More information: http://en.wikipedia.org/wiki/DMA_attack
+        More information is available at <link xlink:href="http://en.wikipedia.org/wiki/DMA_attack"/>.
 
         This option blacklists FireWire drivers, but doesn't remove them. You can manually
         load the drivers if you need to use a FireWire device, but don't forget to unload them!
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 5a9beeeafa1d..0b7d4de6d205 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -56,9 +56,10 @@ echo
 
 
 # Mount special file systems.
-mkdir -p /etc
+mkdir -p /etc/udev
 touch /etc/fstab # to shut up mount
 touch /etc/mtab # to shut up mke2fs
+touch /etc/udev/hwdb.bin # to shut up udev
 touch /etc/initrd-release
 mkdir -p /proc
 mount -t proc proc /proc
@@ -122,6 +123,9 @@ for o in $(cat /proc/cmdline); do
     esac
 done
 
+# Set hostid before modules are loaded.
+# This is needed by the spl/zfs modules.
+@setHostId@
 
 # Load the required kernel modules.
 mkdir -p /lib
@@ -184,7 +188,7 @@ if test -e /sys/power/resume -a -e /sys/power/disk; then
         done
     fi
     if test -n "$resumeDev"; then
-        echo "$resumeDev" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
+        readlink -f "$resumeDev" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
     fi
 fi
 
@@ -369,7 +373,11 @@ exec 3>&-
 
 
 # Emit a udev rule for /dev/root to prevent systemd from complaining.
-eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=$targetRoot || true)
+if [ -e /mnt-root/iso ]; then
+    eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=/mnt-root/iso || true)
+else
+    eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=$targetRoot || true)
+fi
 if [ "$ROOT_MAJOR" -a "$ROOT_MINOR" -a "$ROOT_MAJOR" != 0 ]; then
     mkdir -p /run/udev/rules.d
     echo 'ACTION=="add|change", SUBSYSTEM=="block", ENV{MAJOR}=="'$ROOT_MAJOR'", ENV{MINOR}=="'$ROOT_MINOR'", SYMLINK+="root"' > /run/udev/rules.d/61-dev-root-link.rules
@@ -394,7 +402,7 @@ echo /sbin/modprobe > /proc/sys/kernel/modprobe
 # Start stage 2.  `switch_root' deletes all files in the ramfs on the
 # current root.  Note that $stage2Init might be an absolute symlink,
 # in which case "-e" won't work because we're not in the chroot yet.
-if ! test -e "$targetRoot/$stage2Init" -o -L "$targetRoot/$stage2Init"; then
+if ! test -e "$targetRoot/$stage2Init" -o ! -L "$targetRoot/$stage2Init"; then
     echo "stage 2 init script ($targetRoot/$stage2Init) not found"
     fail
 fi
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 6b09559876ca..f0d8b04d0875 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -34,6 +34,8 @@ let
       doublePatchelf = pkgs.stdenv.isArm;
     }
     ''
+      set +o pipefail
+
       mkdir -p $out/bin $out/lib
       ln -s $out/bin $out/sbin
 
@@ -127,7 +129,7 @@ let
       cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
       cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/
       cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
-      cp -v ${pkgs.mdadm}/lib/udev/rules.d/*.rules $out/
+      ${config.boot.initrd.extraUdevRulesCommands}
 
       for i in $out/*.rules; do
           substituteInPlace $i \
@@ -137,7 +139,8 @@ let
             --replace ${pkgs.utillinux}/sbin/blkid ${extraUtils}/bin/blkid \
             --replace /sbin/blkid ${extraUtils}/bin/blkid \
             --replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
-            --replace /sbin/mdadm ${extraUtils}/bin/mdadm
+            --replace /sbin/mdadm ${extraUtils}/bin/mdadm \
+            --replace /bin/sh ${extraUtils}/bin/sh
       done
 
       # Work around a bug in QEMU, which doesn't implement the "READ
@@ -187,6 +190,15 @@ let
     fsInfo =
       let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType fs.options ];
       in pkgs.writeText "initrd-fsinfo" (concatStringsSep "\n" (concatMap f fileSystems));
+
+    setHostId = optionalString (config.networking.hostId != null) ''
+      hi="${config.networking.hostId}"
+      ${if pkgs.stdenv.isBigEndian then ''
+        echo -ne "\x''${hi:0:2}\x''${hi:2:2}\x''${hi:4:2}\x''${hi:6:2}" > /etc/hostid
+      '' else ''
+        echo -ne "\x''${hi:6:2}\x''${hi:4:2}\x''${hi:2:2}\x''${hi:0:2}" > /etc/hostid
+      ''}
+    '';
   };
 
 
@@ -228,8 +240,9 @@ in
       example = "/dev/sda3";
       description = ''
         Device for manual resume attempt during boot. This should be used primarily
-        if you want to resume from file. Specify here the device where the file
-        resides. You should also use <varname>boot.kernelParams</varname> to specify
+        if you want to resume from file. If left empty, the swap partitions are used.
+        Specify here the device where the file resides.
+        You should also use <varname>boot.kernelParams</varname> to specify
         <literal><replaceable>resume_offset</replaceable></literal>.
       '';
     };
@@ -300,9 +313,20 @@ in
       '';
     };
 
+    boot.initrd.extraUdevRulesCommands = mkOption {
+      internal = true;
+      default = "";
+      type = types.lines;
+      description = ''
+        Shell commands to be executed in the builder of the
+        udev-rules derivation.  This can be used to add
+        additional udev rules in the initial ramdisk.
+      '';
+    };
+
     boot.initrd.compressor = mkOption {
       internal = true;
-      default = "gzip -9";
+      default = "gzip -9n";
       type = types.str;
       description = "The compressor to use on the initrd image.";
       example = "xz";
@@ -332,10 +356,17 @@ in
 
   config = mkIf (!config.boot.isContainer) {
 
-    assertions = singleton
+    assertions = [
       { assertion = any (fs: fs.mountPoint == "/") (attrValues config.fileSystems);
         message = "The ‘fileSystems’ option does not specify your root file system.";
-      };
+      }
+      { assertion = let inherit (config.boot) resumeDevice; in
+          resumeDevice == "" || builtins.substring 0 1 resumeDevice == "/";
+        message = "boot.resumeDevice has to be an absolute path."
+          + " Old \"x:y\" style is no longer supported.";
+      }
+    ];
+
 
     system.build.bootStage1 = bootStage1;
     system.build.initialRamdisk = initialRamdisk;
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index 6fff776f8581..3762bda94a5c 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -141,8 +141,6 @@ fi
 # Use /etc/resolv.conf supplied by systemd-nspawn, if applicable.
 if [ -n "@useHostResolvConf@" -a -e /etc/resolv.conf ]; then
     cat /etc/resolv.conf | resolvconf -m 1000 -a host
-else
-    touch /etc/resolv.conf
 fi
 
 
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 07f3cb9e952c..20851c626d75 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -4,15 +4,184 @@ with lib;
 
 let
 
-  checkService = v:
-    let assertValueOneOf = name: values: attr:
-          let val = attr.${name};
-          in optional (attr ? ${name} && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
-        checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"];
-        checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"];
-        errors = concatMap (c: c v) [checkType checkRestart];
-    in if errors == [] then true
-       else builtins.trace (concatStringsSep "\n" errors) false;
+  boolValues = [true false "yes" "no"];
+
+  assertValueOneOf = name: values: group: attr:
+    optional (attr ? ${name} && !elem attr.${name} values)
+      "Systemd ${group} field `${name}' cannot have value `${attr.${name}}'.";
+
+  assertHasField = name: group: attr:
+    optional (!(attr ? ${name}))
+      "Systemd ${group} field `${name}' must exist.";
+
+  assertOnlyFields = fields: group: attr:
+    let badFields = filter (name: ! elem name fields) (attrNames attr); in
+    optional (badFields != [ ])
+      "Systemd ${group} has extra fields [${concatStringsSep " " badFields}].";
+
+  assertRange = name: min: max: group: attr:
+    optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
+      "Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]";
+
+  digits = map toString (range 0 9);
+
+  isByteFormat = s:
+    let
+      l = reverseList (stringToCharacters s);
+      suffix = head l;
+      nums = tail l;
+    in elem suffix (["K" "M" "G" "T"] ++ digits)
+      && all (num: elem num digits) nums;
+
+  assertByteFormat = name: group: attr:
+    optional (attr ? ${name} && ! isByteFormat attr.${name})
+      "Systemd ${group} field `${name}' must be in byte format [0-9]+[KMGT].";
+
+  hexChars = stringToCharacters "0123456789abcdefABCDEF";
+
+  isMacAddress = s: stringLength s == 17
+    && flip all (splitString ":" s) (bytes:
+      all (byte: elem byte hexChars) (stringToCharacters bytes)
+    );
+
+  assertMacAddress = name: group: attr:
+    optional (attr ? ${name} && ! isMacAddress attr.${name})
+      "Systemd ${group} field `${name}' must be a valid mac address.";
+
+  checkUnitConfig = group: checks: v:
+    let errors = concatMap (c: c group v) checks; in
+    if errors == [] then true
+      else builtins.trace (concatStringsSep "\n" errors) false;
+
+  checkService = checkUnitConfig "Service" [
+    (assertValueOneOf "Type" [
+      "simple" "forking" "oneshot" "dbus" "notify" "idle"
+    ])
+    (assertValueOneOf "Restart" [
+      "no" "on-success" "on-failure" "on-abort" "always"
+    ])
+  ];
+
+  checkLink = checkUnitConfig "Link" [
+    (assertOnlyFields [
+      "Description" "Alias" "MACAddressPolicy" "MACAddress" "NamePolicy" "Name"
+      "MTUBytes" "BitsPerSecond" "Duplex" "WakeOnLan"
+    ])
+    (assertValueOneOf "MACAddressPolicy" ["persistent" "random"])
+    (assertMacAddress "MACAddress")
+    (assertValueOneOf "NamePolicy" [
+      "kernel" "database" "onboard" "slot" "path" "mac"
+    ])
+    (assertByteFormat "MTUBytes")
+    (assertByteFormat "BitsPerSecond")
+    (assertValueOneOf "Duplex" ["half" "full"])
+    (assertValueOneOf "WakeOnLan" ["phy" "magic" "off"])
+  ];
+
+  checkNetdev = checkUnitConfig "Netdev" [
+    (assertOnlyFields [
+      "Description" "Name" "Kind" "MTUBytes" "MACAddress"
+    ])
+    (assertHasField "Name")
+    (assertHasField "Kind")
+    (assertValueOneOf "Kind" [
+      "bridge" "bond" "vlan" "macvlan" "vxlan" "ipip"
+      "gre" "sit" "vti" "veth" "tun" "tap" "dummy"
+    ])
+    (assertByteFormat "MTUBytes")
+    (assertMacAddress "MACAddress")
+  ];
+
+  checkVlan = checkUnitConfig "VLAN" [
+    (assertOnlyFields ["Id"])
+    (assertRange "Id" 0 4094)
+  ];
+
+  checkMacvlan = checkUnitConfig "MACVLAN" [
+    (assertOnlyFields ["Mode"])
+    (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"])
+  ];
+
+  checkVxlan = checkUnitConfig "VXLAN" [
+    (assertOnlyFields ["Id" "Group" "TOS" "TTL" "MacLearning"])
+    (assertRange "TTL" 0 255)
+    (assertValueOneOf "MacLearning" boolValues)
+  ];
+
+  checkTunnel = checkUnitConfig "Tunnel" [
+    (assertOnlyFields ["Local" "Remote" "TOS" "TTL" "DiscoverPathMTU"])
+    (assertRange "TTL" 0 255)
+    (assertValueOneOf "DiscoverPathMTU" boolValues)
+  ];
+
+  checkPeer = checkUnitConfig "Peer" [
+    (assertOnlyFields ["Name" "MACAddress"])
+    (assertMacAddress "MACAddress")
+  ];
+
+  tunTapChecks = [
+    (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "User" "Group"])
+    (assertValueOneOf "OneQueue" boolValues)
+    (assertValueOneOf "MultiQueue" boolValues)
+    (assertValueOneOf "PacketInfo" boolValues)
+  ];
+
+  checkTun = checkUnitConfig "Tun" tunTapChecks;
+
+  checkTap = checkUnitConfig "Tap" tunTapChecks;
+
+  checkBond = checkUnitConfig "Bond" [
+    (assertOnlyFields [
+      "Mode" "TransmitHashPolicy" "LACPTransmitRate" "MIIMonitorSec"
+      "UpDelaySec" "DownDelaySec"
+    ])
+    (assertValueOneOf "Mode" [
+      "balance-rr" "active-backup" "balance-xor"
+      "broadcast" "802.3ad" "balance-tlb" "balance-alb"
+    ])
+    (assertValueOneOf "TransmitHashPolicy" [
+      "layer2" "layer3+4" "layer2+3" "encap2+3" "802.3ad" "encap3+4"
+    ])
+    (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
+  ];
+
+  checkNetwork = checkUnitConfig "Network" [
+    (assertOnlyFields [
+      "Description" "DHCP" "DHCPServer" "IPv4LL" "IPv4LLRoute"
+      "LLMNR" "Domains" "Bridge" "Bond"
+    ])
+    (assertValueOneOf "DHCP" ["both" "none" "v4" "v6"])
+    (assertValueOneOf "DHCPServer" boolValues)
+    (assertValueOneOf "IPv4LL" boolValues)
+    (assertValueOneOf "IPv4LLRoute" boolValues)
+    (assertValueOneOf "LLMNR" boolValues)
+  ];
+
+  checkAddress = checkUnitConfig "Address" [
+    (assertOnlyFields ["Address" "Peer" "Broadcast" "Label"])
+    (assertHasField "Address")
+  ];
+
+  checkRoute = checkUnitConfig "Route" [
+    (assertOnlyFields ["Gateway" "Destination" "Metric"])
+    (assertHasField "Gateway")
+  ];
+
+  checkDhcp = checkUnitConfig "DHCP" [
+    (assertOnlyFields [
+      "UseDNS" "UseMTU" "SendHostname" "UseHostname" "UseDomains" "UseRoutes"
+      "CriticalConnections" "VendorClassIdentifier" "RequestBroadcast"
+      "RouteMetric"
+    ])
+    (assertValueOneOf "UseDNS" boolValues)
+    (assertValueOneOf "UseMTU" boolValues)
+    (assertValueOneOf "SendHostname" boolValues)
+    (assertValueOneOf "UseHostname" boolValues)
+    (assertValueOneOf "UseDomains" boolValues)
+    (assertValueOneOf "UseRoutes" boolValues)
+    (assertValueOneOf "CriticalConnections" boolValues)
+    (assertValueOneOf "RequestBroadcast" boolValues)
+  ];
 
   unitOption = mkOptionType {
     name = "systemd option";
@@ -140,6 +309,15 @@ in rec {
       '';
     };
 
+    requisite = mkOption {
+      default = [];
+      type = types.listOf types.str;
+      description = ''
+        Similar to requires. However if the units listed are not started,
+        they will not be started and the transaction will fail.
+      '';
+    };
+
     unitConfig = mkOption {
       default = {};
       example = { RequiresMountsFor = "/data"; };
@@ -441,4 +619,345 @@ in rec {
 
   targetOptions = commonUnitOptions;
 
+  commonNetworkOptions = {
+
+    enable = mkOption {
+      default = true;
+      type = types.bool;
+      description = ''
+        If set to false, this unit will be a symlink to
+        /dev/null.
+      '';
+    };
+
+    matchConfig = mkOption {
+      default = {};
+      example = { Name = "eth0"; };
+      type = types.attrsOf unitOption;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Match]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+        for details.
+      '';
+    };
+
+  };
+
+  linkOptions = commonNetworkOptions // {
+
+    linkConfig = mkOption {
+      default = {};
+      example = { MACAddress = "00:ff:ee:aa:cc:dd"; };
+      type = types.addCheck (types.attrsOf unitOption) checkLink;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Link]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.link</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+  };
+
+  netdevOptions = commonNetworkOptions // {
+
+    netdevConfig = mkOption {
+      default = {};
+      example = { Name = "mybridge"; Kind = "bridge"; };
+      type = types.addCheck (types.attrsOf unitOption) checkNetdev;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Netdev]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    vlanConfig = mkOption {
+      default = {};
+      example = { Id = "4"; };
+      type = types.addCheck (types.attrsOf unitOption) checkVlan;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[VLAN]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    macvlanConfig = mkOption {
+      default = {};
+      example = { Mode = "private"; };
+      type = types.addCheck (types.attrsOf unitOption) checkMacvlan;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[MACVLAN]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    vxlanConfig = mkOption {
+      default = {};
+      example = { Id = "4"; };
+      type = types.addCheck (types.attrsOf unitOption) checkVxlan;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[VXLAN]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    tunnelConfig = mkOption {
+      default = {};
+      example = { Remote = "192.168.1.1"; };
+      type = types.addCheck (types.attrsOf unitOption) checkTunnel;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Tunnel]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    peerConfig = mkOption {
+      default = {};
+      example = { Name = "veth2"; };
+      type = types.addCheck (types.attrsOf unitOption) checkPeer;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Peer]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    tunConfig = mkOption {
+      default = {};
+      example = { User = "openvpn"; };
+      type = types.addCheck (types.attrsOf unitOption) checkTun;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Tun]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    tapConfig = mkOption {
+      default = {};
+      example = { User = "openvpn"; };
+      type = types.addCheck (types.attrsOf unitOption) checkTap;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Tap]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    bondConfig = mkOption {
+      default = {};
+      example = { Mode = "802.3ad"; };
+      type = types.addCheck (types.attrsOf unitOption) checkBond;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Bond]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+  };
+
+  addressOptions = {
+
+    addressConfig = mkOption {
+      default = {};
+      example = { Address = "192.168.0.100/24"; };
+      type = types.addCheck (types.attrsOf unitOption) checkAddress;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Address]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+  };
+
+  routeOptions = {
+
+    routeConfig = mkOption {
+      default = {};
+      example = { Gateway = "192.168.0.1"; };
+      type = types.addCheck (types.attrsOf unitOption) checkRoute;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Route]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+  };
+
+  networkOptions = commonNetworkOptions // {
+
+    networkConfig = mkOption {
+      default = {};
+      example = { Description = "My Network"; };
+      type = types.addCheck (types.attrsOf unitOption) checkNetwork;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[Network]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    dhcpConfig = mkOption {
+      default = {};
+      example = { UseDNS = true; UseRoutes = true; };
+      type = types.addCheck (types.attrsOf unitOption) checkDhcp;
+      description = ''
+        Each attribute in this set specifies an option in the
+        <literal>[DHCP]</literal> section of the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    name = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The name of the network interface to match against.
+      '';
+    };
+
+    DHCP = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        Whether to enable DHCP on the interfaces matched.
+      '';
+    };
+
+    domains = mkOption {
+      type = types.nullOr (types.listOf types.str);
+      default = null;
+      description = ''
+        A list of domains to pass to the network config.
+      '';
+    };
+
+    address = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of addresses to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    gateway = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of gateways to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    dns = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of dns servers to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    ntp = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of ntp servers to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    vlan = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of vlan interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    macvlan = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of macvlan interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    vxlan = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of vxlan interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    tunnel = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of tunnel interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    addresses = mkOption {
+      default = [ ];
+      type = types.listOf types.optionSet;
+      options = [ addressOptions ];
+      description = ''
+        A list of address sections to be added to the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    routes = mkOption {
+      default = [ ];
+      type = types.listOf types.optionSet;
+      options = [ routeOptions ];
+      description = ''
+        A list of route sections to be added to the unit.  See
+        <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+  };
+
 }
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index c1205dc0c447..05f8c8009bfd 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -36,6 +36,7 @@ let
       "graphical.target"
       "multi-user.target"
       "network.target"
+      "network-pre.target"
       "network-online.target"
       "nss-lookup.target"
       "nss-user-lookup.target"
@@ -85,6 +86,7 @@ let
       "systemd-journal-flush.service"
       "systemd-journal-gatewayd.socket"
       "systemd-journal-gatewayd.service"
+      "systemd-journald-dev-log.socket"
       "syslog.socket"
 
       # SysV init compatibility.
@@ -95,6 +97,12 @@ let
       "systemd-modules-load.service"
       "kmod-static-nodes.service"
 
+      # Networking
+      "systemd-networkd.service"
+      "systemd-networkd-wait-online.service"
+      "systemd-resolved.service"
+      "systemd-timesyncd.service"
+
       # Filesystems.
       "systemd-fsck@.service"
       "systemd-fsck-root.service"
@@ -211,6 +219,8 @@ let
           { PartOf = toString config.partOf; }
         // optionalAttrs (config.conflicts != [])
           { Conflicts = toString config.conflicts; }
+        // optionalAttrs (config.requisite != [])
+          { Requisite = toString config.requisite; }
         // optionalAttrs (config.restartTriggers != [])
           { X-Restart-Triggers = toString config.restartTriggers; }
         // optionalAttrs (config.description != "") {
@@ -291,6 +301,19 @@ let
     };
   };
 
+  networkConfig = { name, config, ... }: {
+    config = {
+      matchConfig = optionalAttrs (config.name != null) {
+        Name = config.name;
+      };
+      networkConfig = optionalAttrs (config.DHCP != null) {
+        DHCP = config.DHCP;
+      } // optionalAttrs (config.domains != null) {
+        Domains = concatStringsSep " " config.domains;
+      };
+    };
+  };
+
   toOption = x:
     if x == true then "true"
     else if x == false then "false"
@@ -325,7 +348,8 @@ let
           [Service]
           ${let env = cfg.globalEnvironment // def.environment;
             in concatMapStrings (n:
-              let s = "Environment=\"${n}=${env.${n}}\"\n";
+              let s = optionalString (env."${n}" != null)
+                "Environment=\"${n}=${env.${n}}\"\n";
               in if stringLength s >= 2048 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env)}
           ${if def.reloadIfChanged then ''
             X-ReloadIfChanged=true
@@ -383,6 +407,103 @@ let
         '';
     };
 
+  commonMatchText = def: ''
+      [Match]
+      ${attrsToSection def.matchConfig}
+    '';
+
+  linkToUnit = name: def:
+    { inherit (def) enable;
+      text = commonMatchText def +
+        ''
+          [Link]
+          ${attrsToSection def.linkConfig}
+        '';
+    };
+
+  netdevToUnit = name: def:
+    { inherit (def) enable;
+      text = commonMatchText def +
+        ''
+          [NetDev]
+          ${attrsToSection def.netdevConfig}
+
+          ${optionalString (def.vlanConfig != { }) ''
+            [VLAN]
+            ${attrsToSection def.vlanConfig}
+
+          ''}
+          ${optionalString (def.macvlanConfig != { }) ''
+            [MACVLAN]
+            ${attrsToSection def.macvlanConfig}
+
+          ''}
+          ${optionalString (def.vxlanConfig != { }) ''
+            [VXLAN]
+            ${attrsToSection def.vxlanConfig}
+
+          ''}
+          ${optionalString (def.tunnelConfig != { }) ''
+            [Tunnel]
+            ${attrsToSection def.tunnelConfig}
+
+          ''}
+          ${optionalString (def.peerConfig != { }) ''
+            [Peer]
+            ${attrsToSection def.peerConfig}
+
+          ''}
+          ${optionalString (def.tunConfig != { }) ''
+            [Tun]
+            ${attrsToSection def.tunConfig}
+
+          ''}
+          ${optionalString (def.tapConfig != { }) ''
+            [Tap]
+            ${attrsToSection def.tapConfig}
+
+          ''}
+          ${optionalString (def.bondConfig != { }) ''
+            [Bond]
+            ${attrsToSection def.bondConfig}
+
+          ''}
+        '';
+    };
+
+  networkToUnit = name: def:
+    { inherit (def) enable;
+      text = commonMatchText def +
+        ''
+          [Network]
+          ${attrsToSection def.networkConfig}
+          ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
+          ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
+          ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
+          ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
+          ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
+          ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
+          ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
+          ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
+
+          ${optionalString (def.dhcpConfig != { }) ''
+            [DHCP]
+            ${attrsToSection def.dhcpConfig}
+
+          ''}
+          ${flip concatMapStrings def.addresses (x: ''
+            [Address]
+            ${attrsToSection x.addressConfig}
+
+          '')}
+          ${flip concatMapStrings def.routes (x: ''
+            [Route]
+            ${attrsToSection x.routeConfig}
+
+          '')}
+        '';
+    };
+
   generateUnits = type: units: upstreamUnits: upstreamWants:
     pkgs.runCommand "${type}-units" { preferLocalBuild = true; } ''
       mkdir -p $out
@@ -467,8 +588,9 @@ let
         mkdir -p $out/getty.target.wants/
         ln -s ../autovt@tty1.service $out/getty.target.wants/
 
-        ln -s ../local-fs.target ../remote-fs.target ../network.target ../nss-lookup.target \
-              ../nss-user-lookup.target ../swap.target $out/multi-user.target.wants/
+        ln -s ../local-fs.target ../remote-fs.target ../network.target \
+        ../nss-lookup.target ../nss-user-lookup.target ../swap.target \
+        $out/multi-user.target.wants/
       ''}
     ''; # */
 
@@ -561,6 +683,47 @@ in
       '';
     };
 
+    systemd.network.enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Whether to enable networkd or not.
+      '';
+    };
+
+    systemd.network.links = mkOption {
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = [ linkOptions ];
+      description = "Definiton of systemd network links.";
+    };
+
+    systemd.network.netdevs = mkOption {
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = [ netdevOptions ];
+      description = "Definiton of systemd network devices.";
+    };
+
+    systemd.network.networks = mkOption {
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = [ networkOptions networkConfig ];
+      description = "Definiton of systemd networks.";
+    };
+
+    systemd.network.units = mkOption {
+      description = "Definition of networkd units.";
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = { name, config, ... }:
+        { options = concreteUnitOptions;
+          config = {
+            unit = mkDefault (makeUnit name config);
+          };
+        };
+    };
+
     systemd.defaultUnit = mkOption {
       default = "multi-user.target";
       type = types.str;
@@ -644,6 +807,22 @@ in
       '';
     };
 
+    services.resolved.enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Enables the systemd dns resolver daemon.
+      '';
+    };
+
+    services.timesyncd.enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Enables the systemd ntp client daemon.
+      '';
+    };
+
     systemd.tmpfiles.rules = mkOption {
       type = types.listOf types.str;
       default = [];
@@ -700,7 +879,7 @@ in
 
   ###### implementation
 
-  config = {
+  config = mkMerge [ {
 
     warnings = concatLists (mapAttrsToList (name: service:
       optional (service.serviceConfig.Type or "" == "oneshot" && service.serviceConfig.Restart or "no" != "no")
@@ -713,6 +892,9 @@ in
     environment.etc."systemd/system".source =
       generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants;
 
+    environment.etc."systemd/network".source =
+      generateUnits "network" cfg.network.units [] [];
+
     environment.etc."systemd/user".source =
       generateUnits "user" cfg.user.units upstreamUserUnits [];
 
@@ -765,6 +947,18 @@ in
         unitConfig.X-StopOnReconfiguration = true;
       };
 
+    systemd.targets.network-online.after = [ "ip-up.target" ];
+
+    systemd.targets.network-pre = {
+      wantedBy = [ "network.target" ];
+      before = [ "network.target" ];
+    };
+
+    systemd.targets.remote-fs-pre = {
+      wantedBy = [ "remote-fs.target" ];
+      before = [ "remote-fs.target" ];
+    };
+
     systemd.units =
       mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
       // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
@@ -778,6 +972,11 @@ in
                    (v: let n = escapeSystemdPath v.where;
                        in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
 
+    systemd.network.units =
+      mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.network.links
+      // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.network.netdevs
+      // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.network.networks;
+
     systemd.user.units =
       mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services
       // mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.user.sockets;
@@ -799,6 +998,15 @@ in
     users.extraUsers.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway;
     users.extraGroups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway;
 
+    users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
+    users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network;
+
+    users.extraUsers.systemd-resolve.uid = config.ids.uids.systemd-resolve;
+    users.extraGroups.systemd-resolve.gid = config.ids.gids.systemd-resolve;
+
+    users.extraUsers.systemd-timesync.uid = config.ids.uids.systemd-timesync;
+    users.extraGroups.systemd-timesync.gid = config.ids.gids.systemd-timesync;
+
     # Generate timer units for all services that have a ‘startAt’ value.
     systemd.timers =
       mapAttrs (name: service:
@@ -832,5 +1040,57 @@ in
     systemd.services.systemd-remount-fs.restartIfChanged = false;
     systemd.services.systemd-journal-flush.restartIfChanged = false;
 
-  };
+  }
+  (mkIf config.systemd.network.enable {
+    systemd.services.systemd-networkd = {
+      wantedBy = [ "multi-user.target" ];
+      before = [ "network-interfaces.target" ];
+      restartTriggers = [ config.environment.etc."systemd/network".source ];
+    };
+
+    systemd.services.systemd-networkd-wait-online = {
+      before = [ "network-online.target" "ip-up.target" ];
+      wantedBy = [ "network-online.target" "ip-up.target" ];
+    };
+
+    systemd.services."systemd-network-wait-online@" = {
+      description = "Wait for Network Interface %I to be Configured";
+      conflicts = [ "shutdown.target" ];
+      requisite = [ "systemd-networkd.service" ];
+      after = [ "systemd-networkd.service" ];
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+      };
+    };
+
+    services.resolved.enable = mkDefault true;
+    services.timesyncd.enable = mkDefault config.services.ntp.enable;
+  })
+  (mkIf config.services.resolved.enable {
+    systemd.services.systemd-resolved = {
+      wantedBy = [ "multi-user.target" ];
+      restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ];
+    };
+
+    environment.etc."systemd/resolved.conf".text = ''
+      [Resolve]
+      DNS=${concatStringsSep " " config.networking.nameservers}
+    '';
+  })
+  (mkIf config.services.timesyncd.enable {
+    systemd.services.systemd-timesyncd = {
+      wantedBy = [ "sysinit.target" ];
+      restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ];
+    };
+
+    environment.etc."systemd/timesyncd.conf".text = ''
+      [Time]
+      NTP=${concatStringsSep " " config.services.ntp.servers}
+    '';
+
+    systemd.services.ntpd.enable = false;
+  })
+  ];
 }
diff --git a/nixos/modules/tasks/bcache.nix b/nixos/modules/tasks/bcache.nix
new file mode 100644
index 000000000000..f988ec02af72
--- /dev/null
+++ b/nixos/modules/tasks/bcache.nix
@@ -0,0 +1,11 @@
+{ config, pkgs, ... }:
+
+{
+
+  environment.systemPackages = [ pkgs.bcache-tools ];
+
+  boot.initrd.extraUdevRulesCommands = ''
+    cp -v ${pkgs.bcache-tools}/lib/udev/rules.d/*.rules $out/
+  ''; 
+
+}
diff --git a/nixos/modules/tasks/filesystems/nfs.nix b/nixos/modules/tasks/filesystems/nfs.nix
index 16752ce7e1b5..75c4f93c6917 100644
--- a/nixos/modules/tasks/filesystems/nfs.nix
+++ b/nixos/modules/tasks/filesystems/nfs.nix
@@ -13,7 +13,7 @@ let
   idmapdConfFile = pkgs.writeText "idmapd.conf" ''
     [General]
     Pipefs-Directory = ${rpcMountpoint}
-    ${optionalString (config.networking.domain != "")
+    ${optionalString (config.networking.domain != null)
       "Domain = ${config.networking.domain}"}
 
     [Mapping]
@@ -58,7 +58,7 @@ in
 
     services.rpcbind.enable = true;
 
-    system.fsPackages = [ pkgs.nfsUtils ];
+    system.fsPackages = [ pkgs.nfs-utils ];
 
     boot.extraModprobeConfig = mkIf (cfg.lockdPort != null) ''
       options lockd nlm_udpport=${toString cfg.lockdPort} nlm_tcpport=${toString cfg.lockdPort}
@@ -71,12 +71,12 @@ in
     systemd.services.statd =
       { description = "NFSv3 Network Status Monitor";
 
-        path = [ pkgs.nfsUtils pkgs.sysvtools pkgs.utillinux ];
+        path = [ pkgs.nfs-utils pkgs.sysvtools pkgs.utillinux ];
 
-        wantedBy = [ "network-online.target" "multi-user.target" ];
-        before = [ "network-online.target" ];
+        wantedBy = [ "remote-fs-pre.target" ];
+        before = [ "remote-fs-pre.target" ];
         requires = [ "basic.target" "rpcbind.service" ];
-        after = [ "basic.target" "rpcbind.service" "network.target" ];
+        after = [ "basic.target" "rpcbind.service" ];
 
         unitConfig.DefaultDependencies = false; # don't stop during shutdown
 
@@ -89,7 +89,7 @@ in
 
         serviceConfig.Type = "forking";
         serviceConfig.ExecStart = ''
-          @${pkgs.nfsUtils}/sbin/rpc.statd rpc.statd --no-notify \
+          @${pkgs.nfs-utils}/sbin/rpc.statd rpc.statd --no-notify \
               ${if cfg.statdPort != null then "-p ${toString statdPort}" else ""}
         '';
         serviceConfig.Restart = "always";
@@ -100,8 +100,8 @@ in
 
         path = [ pkgs.sysvtools pkgs.utillinux ];
 
-        wantedBy = [ "network-online.target" "multi-user.target" ];
-        before = [ "network-online.target" ];
+        wantedBy = [ "remote-fs-pre.target" ];
+        before = [ "remote-fs-pre.target" ];
         requires = [ "rpcbind.service" ];
         after = [ "rpcbind.service" ];
 
@@ -117,7 +117,7 @@ in
           '';
 
         serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = "@${pkgs.nfsUtils}/sbin/rpc.idmapd rpc.idmapd -c ${idmapdConfFile}";
+        serviceConfig.ExecStart = "@${pkgs.nfs-utils}/sbin/rpc.idmapd rpc.idmapd -c ${idmapdConfFile}";
         serviceConfig.Restart = "always";
       };
 
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index eb72bfba33c0..ab5942b79453 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -1,11 +1,10 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, utils, ... }:
 #
 # todo:
 #   - crontab for scrubs, etc
 #   - zfs tunables
-#   - /etc/zfs/zpool.cache handling
-
 
+with utils;
 with lib;
 
 let
@@ -31,6 +30,20 @@ let
 
   zfsAutoSnap = "${autosnapPkg}/bin/zfs-auto-snapshot";
 
+  datasetToPool = x: elemAt (splitString "/" x) 0;
+
+  fsToPool = fs: datasetToPool fs.device;
+
+  zfsFilesystems = filter (x: x.fsType == "zfs") (attrValues config.fileSystems);
+
+  isRoot = fs: fs.neededForBoot || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ];
+
+  allPools = unique ((map fsToPool zfsFilesystems) ++ cfgZfs.extraPools);
+
+  rootPools = unique (map fsToPool (filter isRoot zfsFilesystems));
+
+  dataPools = unique (filter (pool: !(elem pool rootPools)) allPools);
+
 in
 
 {
@@ -38,28 +51,73 @@ in
   ###### interface
 
   options = {
-    boot.spl.hostid = mkOption {
-      default = "";
-      example = "0xdeadbeef";
-      description = ''
-        ZFS uses a system's hostid to determine if a storage pool (zpool) is
-        native to this system, and should thus be imported automatically.
-        Unfortunately, this hostid can change under linux from boot to boot (by
-        changing network adapters, for instance). Specify a unique 32 bit hostid in
-        hex here for zfs to prevent getting a random hostid between boots and having to
-        manually import pools.
-      '';
-    };
+    boot.zfs = {
+      useGit = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = ''
+          Use the git version of the SPL and ZFS packages.
+          Note that these are unreleased versions, with less testing, and therefore
+          may be more unstable.
+        '';
+      };
+
+      extraPools = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "tank" "data" ];
+        description = ''
+          Name or GUID of extra ZFS pools that you wish to import during boot.
+
+          Usually this is not necessary. Instead, you should set the mountpoint property
+          of ZFS filesystems to <literal>legacy</literal> and add the ZFS filesystems to
+          NixOS's <option>fileSystems</option> option, which makes NixOS automatically
+          import the associated pool.
+
+          However, in some cases (e.g. if you have many filesystems) it may be preferable
+          to exclusively use ZFS commands to manage filesystems. If so, since NixOS/systemd
+          will not be managing those filesystems, you will need to specify the ZFS pool here
+          so that NixOS automatically imports it on every boot.
+        '';
+      };
 
-    boot.zfs.useGit = mkOption {
-      type = types.bool;
-      default = false;
-      example = true;
-      description = ''
-        Use the git version of the SPL and ZFS packages.
-        Note that these are unreleased versions, with less testing, and therefore
-        may be more unstable.
-      '';
+      forceImportRoot = mkOption {
+        type = types.bool;
+        default = true;
+        example = false;
+        description = ''
+          Forcibly import the ZFS root pool(s) during early boot.
+
+          This is enabled by default for backwards compatibility purposes, but it is highly
+          recommended to disable this option, as it bypasses some of the safeguards ZFS uses
+          to protect your ZFS pools.
+
+          If you set this option to <literal>false</literal> and NixOS subsequently fails to
+          boot because it cannot import the root pool, you should boot with the
+          <literal>zfs_force=1</literal> option as a kernel parameter (e.g. by manually
+          editing the kernel params in grub during boot). You should only need to do this
+          once.
+        '';
+      };
+
+      forceImportAll = mkOption {
+        type = types.bool;
+        default = true;
+        example = false;
+        description = ''
+          Forcibly import all ZFS pool(s).
+
+          This is enabled by default for backwards compatibility purposes, but it is highly
+          recommended to disable this option, as it bypasses some of the safeguards ZFS uses
+          to protect your ZFS pools.
+
+          If you set this option to <literal>false</literal> and NixOS subsequently fails to
+          import your non-root ZFS pool(s), you should manually import each pool with
+          "zpool import -f &lt;pool-name&gt;", and then reboot. You should only need to do
+          this once.
+        '';
+      };
     };
 
     services.zfs.autoSnapshot = {
@@ -124,12 +182,20 @@ in
 
   config = mkMerge [
     (mkIf enableZfs {
+      assertions = [
+        {
+          assertion = config.networking.hostId != null;
+          message = "ZFS requires config.networking.hostId to be set";
+        }
+        {
+          assertion = !cfgZfs.forceImportAll || cfgZfs.forceImportRoot;
+          message = "If you enable boot.zfs.forceImportAll, you must also enable boot.zfs.forceImportRoot";
+        }
+      ];
+
       boot = {
         kernelModules = [ "spl" "zfs" ] ;
         extraModulePackages = [ splPkg zfsPkg ];
-        extraModprobeConfig = mkIf (cfgSpl.hostid != "") ''
-          options spl spl_hostid=${cfgSpl.hostid}
-        '';
       };
 
       boot.initrd = mkIf inInitrd {
@@ -142,50 +208,84 @@ in
             cp -pdv ${zfsPkg}/lib/lib*.so* $out/lib
             cp -pdv ${pkgs.zlib}/lib/lib*.so* $out/lib
           '';
-        postDeviceCommands =
-          ''
-            zpool import -f -a
-          '';
+        postDeviceCommands = concatStringsSep "\n" ([''
+            ZFS_FORCE="${optionalString cfgZfs.forceImportRoot "-f"}"
+
+            for o in $(cat /proc/cmdline); do
+              case $o in
+                zfs_force|zfs_force=1)
+                  ZFS_FORCE="-f"
+                  ;;
+              esac
+            done
+            ''] ++ (map (pool: ''
+            echo "importing root ZFS pool \"${pool}\"..."
+            zpool import -N $ZFS_FORCE "${pool}"
+        '') rootPools));
       };
 
       boot.loader.grub = mkIf inInitrd {
         zfsSupport = true;
       };
 
-      systemd.services."zpool-import" = {
-        description = "Import zpools";
-        after = [ "systemd-udev-settle.service" ];
-        wantedBy = [ "local-fs.target" ];
-        serviceConfig = {
-          Type = "oneshot";
-          RemainAfterExit = true;
-          ExecStart = "${zfsPkg}/sbin/zpool import -f -a";
-        };
-        restartIfChanged = false;
-      };
-
-      systemd.services."zfs-mount" = {
-        description = "Mount ZFS Volumes";
-        after = [ "zpool-import.service" ];
-        wantedBy = [ "local-fs.target" ];
-        serviceConfig = {
-          Type = "oneshot";
-          RemainAfterExit = true;
-          ExecStart = "${zfsPkg}/sbin/zfs mount -a";
-          ExecStop = "${zfsPkg}/sbin/zfs umount -a";
-        };
-        restartIfChanged = false;
-      };
+      environment.etc."zfs/zed.d".source = "${zfsPkg}/etc/zfs/zed.d/*";
 
       system.fsPackages = [ zfsPkg ];                  # XXX: needed? zfs doesn't have (need) a fsck
       environment.systemPackages = [ zfsPkg ];
       services.udev.packages = [ zfsPkg ];             # to hook zvol naming, etc.
+      systemd.packages = [ zfsPkg ];
+
+      systemd.services = let
+        getPoolFilesystems = pool:
+          filter (x: x.fsType == "zfs" && (fsToPool x) == pool) (attrValues config.fileSystems);
+
+        getPoolMounts = pool:
+          let
+            mountPoint = fs: escapeSystemdPath fs.mountPoint;
+          in
+            map (x: "${mountPoint x}.mount") (getPoolFilesystems pool);
+
+        createImportService = pool:
+          nameValuePair "zfs-import-${pool}" {
+            description = "Import ZFS pool \"${pool}\"";
+            requires = [ "systemd-udev-settle.service" ];
+            after = [ "systemd-udev-settle.service" "systemd-modules-load.service" ];
+            wantedBy = (getPoolMounts pool) ++ [ "local-fs.target" ];
+            before = (getPoolMounts pool) ++ [ "local-fs.target" ];
+            unitConfig = {
+              DefaultDependencies = "no";
+            };
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+            };
+            script = ''
+              zpool_cmd="${zfsPkg}/sbin/zpool"
+              ("$zpool_cmd" list "${pool}" >/dev/null) || "$zpool_cmd" import -N ${optionalString cfgZfs.forceImportAll "-f"} "${pool}"
+            '';
+          };
+      in listToAttrs (map createImportService dataPools) // {
+        "zfs-mount" = { after = [ "systemd-modules-load.service" ]; };
+        "zfs-share" = { after = [ "systemd-modules-load.service" ]; };
+        "zed" = { after = [ "systemd-modules-load.service" ]; };
+      };
+
+      systemd.targets."zfs-import" =
+        let
+          services = map (pool: "zfs-import-${pool}.service") dataPools;
+        in
+          {
+            requires = services;
+            after = services;
+          };
+
+      systemd.targets."zfs".wantedBy = [ "multi-user.target" ];
     })
 
     (mkIf enableAutoSnapshots {
       systemd.services."zfs-snapshot-frequent" = {
         description = "ZFS auto-snapshotting every 15 mins";
-        after = [ "zpool-import.service" ];
+        after = [ "zfs-import.target" ];
         serviceConfig = {
           Type = "oneshot";
           ExecStart = "${zfsAutoSnap} frequent ${toString cfgSnapshots.frequent}";
@@ -196,7 +296,7 @@ in
 
       systemd.services."zfs-snapshot-hourly" = {
         description = "ZFS auto-snapshotting every hour";
-        after = [ "zpool-import.service" ];
+        after = [ "zfs-import.target" ];
         serviceConfig = {
           Type = "oneshot";
           ExecStart = "${zfsAutoSnap} hourly ${toString cfgSnapshots.hourly}";
@@ -207,7 +307,7 @@ in
 
       systemd.services."zfs-snapshot-daily" = {
         description = "ZFS auto-snapshotting every day";
-        after = [ "zpool-import.service" ];
+        after = [ "zfs-import.target" ];
         serviceConfig = {
           Type = "oneshot";
           ExecStart = "${zfsAutoSnap} daily ${toString cfgSnapshots.daily}";
@@ -218,7 +318,7 @@ in
 
       systemd.services."zfs-snapshot-weekly" = {
         description = "ZFS auto-snapshotting every week";
-        after = [ "zpool-import.service" ];
+        after = [ "zfs-import.target" ];
         serviceConfig = {
           Type = "oneshot";
           ExecStart = "${zfsAutoSnap} weekly ${toString cfgSnapshots.weekly}";
@@ -229,7 +329,7 @@ in
 
       systemd.services."zfs-snapshot-monthly" = {
         description = "ZFS auto-snapshotting every month";
-        after = [ "zpool-import.service" ];
+        after = [ "zfs-import.target" ];
         serviceConfig = {
           Type = "oneshot";
           ExecStart = "${zfsAutoSnap} monthly ${toString cfgSnapshots.monthly}";
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
new file mode 100644
index 000000000000..9d61a4b05301
--- /dev/null
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -0,0 +1,348 @@
+{ config, lib, pkgs, utils, ... }:
+
+with utils;
+with lib;
+
+let
+
+  cfg = config.networking;
+  interfaces = attrValues cfg.interfaces;
+  hasVirtuals = any (i: i.virtual) interfaces;
+
+  # We must escape interfaces due to the systemd interpretation
+  subsystemDevice = interface:
+    "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
+
+  interfaceIps = i:
+    i.ip4 ++ optionals cfg.enableIPv6 i.ip6
+    ++ optional (i.ipAddress != null) {
+      address = i.ipAddress;
+      prefixLength = i.prefixLength;
+    } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) {
+      address = i.ipv6Address;
+      prefixLength = i.ipv6PrefixLength;
+    };
+
+  destroyBond = i: ''
+    while true; do
+      UPDATED=1
+      SLAVES=$(ip link | grep 'master ${i}' | awk -F: '{print $2}')
+      for I in $SLAVES; do
+        UPDATED=0
+        ip link set "$I" nomaster
+      done
+      [ "$UPDATED" -eq "1" ] && break
+    done
+    ip link set "${i}" down 2>/dev/null || true
+    ip link del "${i}" 2>/dev/null || true
+  '';
+
+in
+
+{
+
+  config = mkIf (!cfg.useNetworkd) {
+
+    systemd.services =
+      let
+
+        networkLocalCommands = {
+          after = [ "network-setup.service" ];
+          bindsTo = [ "network-setup.service" ];
+        };
+
+        networkSetup =
+          { description = "Networking Setup";
+
+            after = [ "network-interfaces.target" "network-pre.target" ];
+            before = [ "network.target" ];
+            wantedBy = [ "network.target" ];
+
+            unitConfig.ConditionCapability = "CAP_NET_ADMIN";
+
+            path = [ pkgs.iproute ];
+
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+
+            script =
+              ''
+                # Set the static DNS configuration, if given.
+                ${pkgs.openresolv}/sbin/resolvconf -m 1 -a static <<EOF
+                ${optionalString (cfg.nameservers != [] && cfg.domain != null) ''
+                  domain ${cfg.domain}
+                ''}
+                ${optionalString (cfg.search != []) ("search " + concatStringsSep " " cfg.search)}
+                ${flip concatMapStrings cfg.nameservers (ns: ''
+                  nameserver ${ns}
+                '')}
+                EOF
+
+                # Set the default gateway.
+                ${optionalString (cfg.defaultGateway != null && cfg.defaultGateway != "") ''
+                  # FIXME: get rid of "|| true" (necessary to make it idempotent).
+                  ip route add default via "${cfg.defaultGateway}" ${
+                    optionalString (cfg.defaultGatewayWindowSize != null)
+                      "window ${cfg.defaultGatewayWindowSize}"} || true
+                ''}
+                ${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6 != "") ''
+                  # FIXME: get rid of "|| true" (necessary to make it idempotent).
+                  ip -6 route add ::/0 via "${cfg.defaultGateway6}" ${
+                    optionalString (cfg.defaultGatewayWindowSize != null)
+                      "window ${cfg.defaultGatewayWindowSize}"} || true
+                ''}
+              '';
+          };
+
+        # For each interface <foo>, create a job ‘network-addresses-<foo>.service"
+        # that performs static address configuration.  It has a "wants"
+        # dependency on ‘<foo>.service’, which is supposed to create
+        # the interface and need not exist (i.e. for hardware
+        # interfaces).  It has a binds-to dependency on the actual
+        # network device, so it only gets started after the interface
+        # has appeared, and it's stopped when the interface
+        # disappears.
+        configureAddrs = i:
+          let
+            ips = interfaceIps i;
+          in
+          nameValuePair "network-addresses-${i.name}"
+          { description = "Addresss configuration of ${i.name}";
+            wantedBy = [ "network-interfaces.target" ];
+            before = [ "network-interfaces.target" ];
+            bindsTo = [ (subsystemDevice i.name) ];
+            after = [ (subsystemDevice i.name) "network-pre.target" ];
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute ];
+            script =
+              ''
+                echo "bringing up interface..."
+                ip link set "${i.name}" up
+
+                restart_network_interfaces=false
+              '' + flip concatMapStrings (ips) (ip:
+                let
+                  address = "${ip.address}/${toString ip.prefixLength}";
+                in
+                ''
+                  echo "checking ip ${address}..."
+                  if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then
+                    echo "added ip ${address}..."
+                    restart_network_setup=true
+                  elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
+                    echo "failed to add ${address}"
+                    exit 1
+                  fi
+                '')
+              + optionalString (ips != [ ])
+                ''
+                  if [ "$restart_network_setup" = "true" ]; then
+                    # Ensure that the default gateway remains set.
+                    # (Flushing this interface may have removed it.)
+                    ${config.systemd.package}/bin/systemctl try-restart --no-block network-setup.service
+                  fi
+                  ${config.systemd.package}/bin/systemctl start ip-up.target
+                '';
+            preStop =
+              ''
+                echo "releasing configured ip's..."
+              '' + flip concatMapStrings (ips) (ip:
+                let
+                  address = "${ip.address}/${toString ip.prefixLength}";
+                in
+                ''
+                  echo -n "Deleting ${address}..."
+                  ip addr del "${address}" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed"
+                  echo ""
+                '');
+          };
+
+        createTunDevice = i: nameValuePair "${i.name}-netdev"
+          { description = "Virtual Network Interface ${i.name}";
+            requires = [ "dev-net-tun.device" ];
+            after = [ "dev-net-tun.device" "network-pre.target" ];
+            wantedBy = [ "network.target" (subsystemDevice i.name) ];
+            before = [ "network-interfaces.target" (subsystemDevice i.name) ];
+            path = [ pkgs.iproute ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+            };
+            script = ''
+              ip tuntap add dev "${i.name}" \
+              ${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \
+              user "${i.virtualOwner}"
+            '';
+            postStop = ''
+              ip link del ${i.name}
+            '';
+          };
+
+        createBridgeDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = map subsystemDevice v.interfaces;
+          in
+          { description = "Bridge Interface ${n}";
+            wantedBy = [ "network.target" (subsystemDevice n) ];
+            bindsTo = deps;
+            after = [ "network-pre.target" ] ++ deps
+              ++ concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) v.interfaces;
+            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute ];
+            script = ''
+              # Remove Dead Interfaces
+              echo "Removing old bridge ${n}..."
+              ip link show "${n}" >/dev/null 2>&1 && ip link del "${n}"
+
+              echo "Adding bridge ${n}..."
+              ip link add name "${n}" type bridge
+
+              # Enslave child interfaces
+              ${flip concatMapStrings v.interfaces (i: ''
+                ip link set "${i}" master "${n}"
+                ip link set "${i}" up
+              '')}
+
+              ip link set "${n}" up
+            '';
+            postStop = ''
+              ip link set "${n}" down || true
+              ip link del "${n}" || true
+            '';
+          });
+
+        createBondDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = map subsystemDevice v.interfaces;
+          in
+          { description = "Bond Interface ${n}";
+            wantedBy = [ "network.target" (subsystemDevice n) ];
+            bindsTo = deps;
+            after = [ "network-pre.target" ] ++ deps
+              ++ concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) v.interfaces;
+            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute pkgs.gawk ];
+            script = ''
+              echo "Destroying old bond ${n}..."
+              ${destroyBond n}
+
+              echo "Creating new bond ${n}..."
+              ip link add name "${n}" type bond \
+                ${optionalString (v.mode != null) "mode ${toString v.mode}"} \
+                ${optionalString (v.miimon != null) "miimon ${toString v.miimon}"} \
+                ${optionalString (v.xmit_hash_policy != null) "xmit_hash_policy ${toString v.xmit_hash_policy}"} \
+                ${optionalString (v.lacp_rate != null) "lacp_rate ${toString v.lacp_rate}"}
+
+              # !!! There must be a better way to wait for the interface
+              while [ ! -d "/sys/class/net/${n}" ]; do sleep 0.1; done;
+
+              # Bring up the bond and enslave the specified interfaces
+              ip link set "${n}" up
+              ${flip concatMapStrings v.interfaces (i: ''
+                ip link set "${i}" down
+                ip link set "${i}" master "${n}"
+              '')}
+            '';
+            postStop = destroyBond n;
+          });
+
+        createMacvlanDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = [ (subsystemDevice v.interface) ];
+          in
+          { description = "Vlan Interface ${n}";
+            wantedBy = [ "network.target" (subsystemDevice n) ];
+            bindsTo = deps;
+            after = [ "network-pre.target" ] ++ deps;
+            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute ];
+            script = ''
+              # Remove Dead Interfaces
+              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
+              ip link add link "${v.interface}" name "${n}" type macvlan \
+                ${optionalString (v.mode != null) "mode ${v.mode}"}
+              ip link set "${n}" up
+            '';
+            postStop = ''
+              ip link delete "${n}"
+            '';
+          });
+
+        createSitDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = optional (v.dev != null) (subsystemDevice v.dev);
+          in
+          { description = "6-to-4 Tunnel Interface ${n}";
+            wantedBy = [ "network.target" (subsystemDevice n) ];
+            bindsTo = deps;
+            after = [ "network-pre.target" ] ++ deps;
+            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute ];
+            script = ''
+              # Remove Dead Interfaces
+              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
+              ip link add name "${n}" type sit \
+                ${optionalString (v.remote != null) "remote \"${v.remote}\""} \
+                ${optionalString (v.local != null) "local \"${v.local}\""} \
+                ${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \
+                ${optionalString (v.dev != null) "dev \"${v.dev}\""}
+              ip link set "${n}" up
+            '';
+            postStop = ''
+              ip link delete "${n}"
+            '';
+          });
+
+        createVlanDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = [ (subsystemDevice v.interface) ];
+          in
+          { description = "Vlan Interface ${n}";
+            wantedBy = [ "network.target" (subsystemDevice n) ];
+            bindsTo = deps;
+            after = [ "network-pre.target" ] ++ deps;
+            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute ];
+            script = ''
+              # Remove Dead Interfaces
+              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
+              ip link add link "${v.interface}" name "${n}" type vlan id "${toString v.id}"
+              ip link set "${n}" up
+            '';
+            postStop = ''
+              ip link delete "${n}"
+            '';
+          });
+
+      in listToAttrs (
+           map configureAddrs interfaces ++
+           map createTunDevice (filter (i: i.virtual) interfaces))
+         // mapAttrs' createBridgeDevice cfg.bridges
+         // mapAttrs' createBondDevice cfg.bonds
+         // mapAttrs' createMacvlanDevice cfg.macvlans
+         // mapAttrs' createSitDevice cfg.sits
+         // mapAttrs' createVlanDevice cfg.vlans
+         // {
+           "network-setup" = networkSetup;
+           "network-local-commands" = networkLocalCommands;
+         };
+
+    services.udev.extraRules =
+      ''
+        KERNEL=="tun", TAG+="systemd"
+      '';
+
+  };
+
+}
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
new file mode 100644
index 000000000000..70158fc7252b
--- /dev/null
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -0,0 +1,176 @@
+{ config, lib, pkgs, utils, ... }:
+
+with utils;
+with lib;
+
+let
+
+  cfg = config.networking;
+  interfaces = attrValues cfg.interfaces;
+
+  interfaceIps = i:
+    i.ip4 ++ optionals cfg.enableIPv6 i.ip6
+    ++ optional (i.ipAddress != null) {
+      address = i.ipAddress;
+      prefixLength = i.prefixLength;
+    } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) {
+      address = i.ipv6Address;
+      prefixLength = i.ipv6PrefixLength;
+    };
+
+  dhcpStr = useDHCP: if useDHCP == true || useDHCP == null then "both" else "none";
+
+  slaves =
+    concatLists (map (bond: bond.interfaces) (attrValues cfg.bonds))
+    ++ concatLists (map (bridge: bridge.interfaces) (attrValues cfg.bridges))
+    ++ map (sit: sit.dev) (attrValues cfg.sits)
+    ++ map (vlan: vlan.interface) (attrValues cfg.vlans);
+
+in
+
+{
+
+  config = mkIf cfg.useNetworkd {
+
+    assertions = [ {
+      assertion = cfg.defaultGatewayWindowSize == null;
+      message = "networking.defaultGatewayWindowSize is not supported by networkd.";
+    } ];
+
+    systemd.services.dhcpcd.enable = mkDefault false;
+
+    systemd.services.network-local-commands = {
+      after = [ "systemd-networkd.service" ];
+      bindsTo = [ "systemd-networkd.service" ];
+    };
+
+    systemd.network =
+      let
+        domains = cfg.search ++ (optional (cfg.domain != null) cfg.domain);
+        genericNetwork = override: {
+          DHCP = override (dhcpStr cfg.useDHCP);
+        } // optionalAttrs (cfg.defaultGateway != null) {
+          gateway = override [ cfg.defaultGateway ];
+        } // optionalAttrs (cfg.defaultGateway6 != null) {
+          gateway = override [ cfg.defaultGateway6 ];
+        } // optionalAttrs (domains != [ ]) {
+          domains = override domains;
+        };
+      in mkMerge [ {
+        enable = true;
+        networks."99-main" = genericNetwork mkDefault;
+      }
+      (mkMerge (flip map interfaces (i: {
+        netdevs = mkIf i.virtual (
+          let
+            devType = if i.virtualType != null then i.virtualType
+              else (if hasPrefix "tun" i.name then "tun" else "tap");
+          in {
+            "40-${i.name}" = {
+              netdevConfig = {
+                Name = i.name;
+                Kind = devType;
+              };
+              "${devType}Config" = optionalAttrs (i.virtualOwner != null) {
+                User = i.virtualOwner;
+              };
+            };
+          });
+        networks."40-${i.name}" = mkMerge [ (genericNetwork mkDefault) {
+          name = mkDefault i.name;
+          DHCP = mkForce (dhcpStr
+            (if i.useDHCP != null then i.useDHCP else cfg.useDHCP && interfaceIps i == [ ]));
+          address = flip map (interfaceIps i)
+            (ip: "${ip.address}/${toString ip.prefixLength}");
+        } ];
+      })))
+      (mkMerge (flip mapAttrsToList cfg.bridges (name: bridge: {
+        netdevs."40-${name}" = {
+          netdevConfig = {
+            Name = name;
+            Kind = "bridge";
+          };
+        };
+        networks = listToAttrs (flip map bridge.interfaces (bi:
+          nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) {
+            DHCP = mkOverride 0 (dhcpStr false);
+            networkConfig.Bridge = name;
+          } ])));
+      })))
+      (mkMerge (flip mapAttrsToList cfg.bonds (name: bond: {
+        netdevs."40-${name}" = {
+          netdevConfig = {
+            Name = name;
+            Kind = "bond";
+          };
+          bondConfig =
+            (optionalAttrs (bond.lacp_rate != null) {
+              LACPTransmitRate = bond.lacp_rate;
+            }) // (optionalAttrs (bond.miimon != null) {
+              MIIMonitorSec = bond.miimon;
+            }) // (optionalAttrs (bond.mode != null) {
+              Mode = bond.mode;
+            }) // (optionalAttrs (bond.xmit_hash_policy != null) {
+              TransmitHashPolicy = bond.xmit_hash_policy;
+            });
+        };
+        networks = listToAttrs (flip map bond.interfaces (bi:
+          nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) {
+            DHCP = mkOverride 0 (dhcpStr false);
+            networkConfig.Bond = name;
+          } ])));
+      })))
+      (mkMerge (flip mapAttrsToList cfg.macvlans (name: macvlan: {
+        netdevs."40-${name}" = {
+          netdevConfig = {
+            Name = name;
+            Kind = "macvlan";
+          };
+          macvlanConfig = optionalAttrs (macvlan.mode != null) { Mode = macvlan.mode; };
+        };
+        networks."40-${macvlan.interface}" = (mkMerge [ (genericNetwork (mkOverride 999)) {
+          macvlan = [ name ];
+        } ]);
+      })))
+      (mkMerge (flip mapAttrsToList cfg.sits (name: sit: {
+        netdevs."40-${name}" = {
+          netdevConfig = {
+            Name = name;
+            Kind = "sit";
+          };
+          tunnelConfig =
+            (optionalAttrs (sit.remote != null) {
+              Remote = sit.remote;
+            }) // (optionalAttrs (sit.local != null) {
+              Local = sit.local;
+            }) // (optionalAttrs (sit.ttl != null) {
+              TTL = sit.ttl;
+            });
+        };
+        networks = mkIf (sit.dev != null) {
+          "40-${sit.dev}" = (mkMerge [ (genericNetwork (mkOverride 999)) {
+            tunnel = [ name ];
+          } ]);
+        };
+      })))
+      (mkMerge (flip mapAttrsToList cfg.vlans (name: vlan: {
+        netdevs."40-${name}" = {
+          netdevConfig = {
+            Name = name;
+            Kind = "vlan";
+          };
+          vlanConfig.Id = vlan.id;
+        };
+        networks."40-${vlan.interface}" = (mkMerge [ (genericNetwork (mkOverride 999)) {
+          vlan = [ name ];
+        } ]);
+      })))
+    ];
+
+    # We need to prefill the slaved devices with networking options
+    # This forces the network interface creator to initialize slaves.
+    networking.interfaces = listToAttrs (map (i: nameValuePair i { }) slaves);
+
+  };
+
+}
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 22b52f77b145..4a272483e549 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -11,6 +11,11 @@ let
   hasSits = cfg.sits != { };
   hasBonds = cfg.bonds != { };
 
+  slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
+    ++ concatMap (i: i.interfaces) (attrValues cfg.bridges);
+
+  slaveIfs = map (i: cfg.interfaces.${i}) (filter (i: cfg.interfaces ? ${i}) slaves);
+
   # We must escape interfaces due to the systemd interpretation
   subsystemDevice = interface:
     "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
@@ -45,6 +50,16 @@ let
         description = "Name of the interface.";
       };
 
+      useDHCP = mkOption {
+        type = types.nullOr types.bool;
+        default = null;
+        description = ''
+          Whether this interface should be configured with dhcp.
+          Null implies the old behavior which depends on whether ip addresses
+          are specified or not.
+        '';
+      };
+
       ip4 = mkOption {
         default = [ ];
         example = [
@@ -189,6 +204,10 @@ let
 
   };
 
+  hexChars = stringToCharacters "0123456789abcdef";
+
+  isHexString = s: all (c: elem c hexChars) (stringToCharacters (toLower s));
+
 in
 
 {
@@ -199,27 +218,57 @@ in
 
     networking.hostName = mkOption {
       default = "nixos";
+      type = types.str;
       description = ''
         The name of the machine.  Leave it empty if you want to obtain
         it from a DHCP server (if using DHCP).
       '';
     };
 
+    networking.hostId = mkOption {
+      default = null;
+      example = "4e98920d";
+      type = types.nullOr types.str;
+      description = ''
+        The 32-bit host ID of the machine, formatted as 8 hexadecimal characters.
+
+        You should try to make this ID unique among your machines. You can
+        generate a random 32-bit ID using the following commands:
+
+        <literal>cksum /etc/machine-id | while read c rest; do printf "%x" $c; done</literal>
+        
+        (this derives it from the machine-id that systemd generates) or
+        
+        <literal>head -c4 /dev/urandom | od -A none -t x4</literal>
+      '';
+    };
+
     networking.enableIPv6 = mkOption {
       default = true;
+      type = types.bool;
       description = ''
         Whether to enable support for IPv6.
       '';
     };
 
     networking.defaultGateway = mkOption {
-      default = "";
+      default = null;
       example = "131.211.84.1";
+      type = types.nullOr types.str;
       description = ''
         The default gateway.  It can be left empty if it is auto-detected through DHCP.
       '';
     };
 
+    networking.defaultGateway6 = mkOption {
+      default = null;
+      example = "2001:4d0:1e04:895::1";
+      type = types.nullOr types.str;
+      description = ''
+        The default ipv6 gateway.  It can be left empty if it is auto-detected through DHCP.
+      '';
+    };
+
     networking.defaultGatewayWindowSize = mkOption {
       default = null;
       example = 524288;
@@ -248,8 +297,9 @@ in
     };
 
     networking.domain = mkOption {
-      default = "";
+      default = null;
       example = "home";
+      type = types.nullOr types.str;
       description = ''
         The domain.  It can be left empty if it is auto-detected through DHCP.
       '';
@@ -396,6 +446,37 @@ in
       };
     };
 
+    networking.macvlans = mkOption {
+      type = types.attrsOf types.optionSet;
+      default = { };
+      example = {
+        wan = {
+          interface = "enp2s0";
+          mode = "vepa";
+        };
+      };
+      description = ''
+        This option allows you to define macvlan interfaces which should
+        be automatically created.
+      '';
+      options = {
+
+        interface = mkOption {
+          example = "enp4s0";
+          type = types.string;
+          description = "The interface the macvlan will transmit packets through.";
+        };
+
+        mode = mkOption {
+          default = null;
+          type = types.nullOr types.str;
+          example = "vepa";
+          description = "The mode of the macvlan device.";
+        };
+
+      };
+    };
+
     networking.sits = mkOption {
       type = types.attrsOf types.optionSet;
       default = { };
@@ -505,6 +586,16 @@ in
       '';
     };
 
+    networking.useNetworkd = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Whether we should use networkd as the network configuration backend or
+        the legacy script based system. Note that this option is experimental,
+        enable at your own risk.
+      '';
+    };
+
   };
 
 
@@ -513,10 +604,18 @@ in
   config = {
 
     assertions =
-      flip map interfaces (i: {
+      (flip map interfaces (i: {
         assertion = i.subnetMask == null;
         message = "The networking.interfaces.${i.name}.subnetMask option is defunct. Use prefixLength instead.";
-      });
+      })) ++ (flip map slaveIfs (i: {
+        assertion = i.ip4 == [ ] && i.ipAddress == null && i.ip6 == [ ] && i.ipv6Address == null;
+        message = "The networking.interfaces.${i.name} must not have any defined ips when it is a slave.";
+      })) ++ [
+        {
+          assertion = cfg.hostId == null || (stringLength cfg.hostId == 8 && isHexString cfg.hostId);
+          message = "Invalid value given to the networking.hostId option.";
+        }
+      ];
 
     boot.kernelModules = [ ]
       ++ optional cfg.enableIPv6 "ipv6"
@@ -529,6 +628,45 @@ in
       # from being created.
       optionalString hasBonds "options bonding max_bonds=0";
 
+    boot.kernel.sysctl = {
+      "net.net.ipv4.conf.all.promote_secondaries" = true;
+      "net.ipv6.conf.all.disable_ipv6" = mkDefault (!cfg.enableIPv6);
+      "net.ipv6.conf.default.disable_ipv6" = mkDefault (!cfg.enableIPv6);
+      "net.ipv4.conf.all_forwarding" = mkDefault (any (i: i.proxyARP) interfaces);
+      "net.ipv6.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces);
+    } // listToAttrs (concatLists (flip map (filter (i: i.proxyARP) interfaces)
+        (i: flip map [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${i.name}.proxy_arp" true))
+      ));
+
+    security.setuidPrograms = [ "ping" "ping6" ];
+
+    # Set the host and domain names in the activation script.  Don't
+    # clear it if it's not configured in the NixOS configuration,
+    # since it may have been set by dhcpcd in the meantime.
+    system.activationScripts.hostname =
+      optionalString (cfg.hostName != "") ''
+        hostname "${cfg.hostName}"
+      '';
+    system.activationScripts.domain =
+      optionalString (cfg.domain != null) ''
+        domainname "${cfg.domain}"
+      '';
+
+    environment.etc = mkIf (cfg.hostId != null)
+      [
+        {
+          target = "hostid";
+          source = pkgs.runCommand "gen-hostid" {} ''
+            hi="${cfg.hostId}"
+            ${if pkgs.stdenv.isBigEndian then ''
+              echo -ne "\x''${hi:0:2}\x''${hi:2:2}\x''${hi:4:2}\x''${hi:6:2}" > $out
+            '' else ''
+              echo -ne "\x''${hi:6:2}\x''${hi:4:2}\x''${hi:2:2}\x''${hi:0:2}" > $out
+            ''}
+          '';
+        }
+      ];
+
     environment.systemPackages =
       [ pkgs.host
         pkgs.iproute
@@ -538,353 +676,54 @@ in
         pkgs.iw
         pkgs.rfkill
         pkgs.openresolv
-      ]
-      ++ optional (cfg.bridges != {}) pkgs.bridge_utils
-      ++ optional hasVirtuals pkgs.tunctl
-      ++ optional cfg.enableIPv6 pkgs.ndisc6;
-
-    security.setuidPrograms = [ "ping" "ping6" ];
+      ];
 
     systemd.targets."network-interfaces" =
       { description = "All Network Interfaces";
         wantedBy = [ "network.target" ];
+        before = [ "network.target" ];
+        after = [ "network-pre.target" ];
         unitConfig.X-StopOnReconfiguration = true;
       };
 
-    systemd.services =
-      let
-
-        networkSetup =
-          { description = "Networking Setup";
-
-            after = [ "network-interfaces.target" ];
-            before = [ "network.target" ];
-            wantedBy = [ "network.target" ];
-
-            unitConfig.ConditionCapability = "CAP_NET_ADMIN";
-
-            path = [ pkgs.iproute ];
-
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
-
-            script =
-              ''
-                # Set the static DNS configuration, if given.
-                ${pkgs.openresolv}/sbin/resolvconf -m 1 -a static <<EOF
-                ${optionalString (cfg.nameservers != [] && cfg.domain != "") ''
-                  domain ${cfg.domain}
-                ''}
-                ${optionalString (cfg.search != []) ("search " + concatStringsSep " " cfg.search)}
-                ${flip concatMapStrings cfg.nameservers (ns: ''
-                  nameserver ${ns}
-                '')}
-                EOF
-
-                # Disable or enable IPv6.
-                ${optionalString (!config.boot.isContainer) ''
-                  if [ -e /proc/sys/net/ipv6/conf/all/disable_ipv6 ]; then
-                    echo ${if cfg.enableIPv6 then "0" else "1"} > /proc/sys/net/ipv6/conf/all/disable_ipv6
-                  fi
-                ''}
-
-                # Set the default gateway.
-                ${optionalString (cfg.defaultGateway != "") ''
-                  # FIXME: get rid of "|| true" (necessary to make it idempotent).
-                  ip route add default via "${cfg.defaultGateway}" ${
-                    optionalString (cfg.defaultGatewayWindowSize != null)
-                      "window ${cfg.defaultGatewayWindowSize}"} || true
-                ''}
-
-                # Turn on forwarding if any interface has enabled proxy_arp.
-                ${optionalString (any (i: i.proxyARP) interfaces) ''
-                  echo 1 > /proc/sys/net/ipv4/ip_forward
-                ''}
-
-                # Run any user-specified commands.
-                ${cfg.localCommands}
-              '';
-          };
-
-        # For each interface <foo>, create a job ‘<foo>-cfg.service"
-        # that performs static configuration.  It has a "wants"
-        # dependency on ‘<foo>.service’, which is supposed to create
-        # the interface and need not exist (i.e. for hardware
-        # interfaces).  It has a binds-to dependency on the actual
-        # network device, so it only gets started after the interface
-        # has appeared, and it's stopped when the interface
-        # disappears.
-        configureInterface = i:
-          let
-            ips = i.ip4 ++ optionals cfg.enableIPv6 i.ip6
-              ++ optional (i.ipAddress != null) {
-                address = i.ipAddress;
-                prefixLength = i.prefixLength;
-              } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) {
-                address = i.ipv6Address;
-                prefixLength = i.ipv6PrefixLength;
-              };
-          in
-          nameValuePair "${i.name}-cfg"
-          { description = "Configuration of ${i.name}";
-            wantedBy = [ "network-interfaces.target" ];
-            bindsTo = [ (subsystemDevice i.name) ];
-            after = [ (subsystemDevice i.name) ];
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
-            path = [ pkgs.iproute pkgs.gawk ];
-            script =
-              ''
-                echo "bringing up interface..."
-                ip link set "${i.name}" up
-              ''
-              + optionalString (i.macAddress != null)
-                ''
-                  echo "setting MAC address to ${i.macAddress}..."
-                  ip link set "${i.name}" address "${i.macAddress}"
-                ''
-              + optionalString (i.mtu != null)
-                ''
-                  echo "setting MTU to ${toString i.mtu}..."
-                  ip link set "${i.name}" mtu "${toString i.mtu}"
-                ''
-
-              # Ip Setup
-              +
-                ''
-                  curIps=$(ip -o a show dev "${i.name}" | awk '{print $4}')
-                  # Only do an add if it's necessary.  This is
-                  # useful when the Nix store is accessed via this
-                  # interface (e.g. in a QEMU VM test).
-                ''
-              + flip concatMapStrings (ips) (ip:
-                let
-                  address = "${ip.address}/${toString ip.prefixLength}";
-                in
-                ''
-                  echo "checking ip ${address}..."
-                  if ! echo "$curIps" | grep "${address}" >/dev/null 2>&1; then
-                    if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then
-                      echo "added ip ${address}..."
-                      restart_network_setup=true
-                    elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
-                      echo "failed to add ${address}"
-                      exit 1
-                    fi
-                  fi
-                '')
-              + optionalString (ips != [ ])
-                ''
-                  if [ restart_network_setup = true ]; then
-                    # Ensure that the default gateway remains set.
-                    # (Flushing this interface may have removed it.)
-                    ${config.systemd.package}/bin/systemctl try-restart --no-block network-setup.service
-                  fi
-                  ${config.systemd.package}/bin/systemctl start ip-up.target
-                ''
-              + optionalString i.proxyARP
-                ''
-                  echo 1 > /proc/sys/net/ipv4/conf/${i.name}/proxy_arp
-                ''
-              + optionalString (i.proxyARP && cfg.enableIPv6)
-                ''
-                  echo 1 > /proc/sys/net/ipv6/conf/${i.name}/proxy_ndp
-                '';
-            preStop =
-              ''
-                echo "releasing configured ip's..."
-              ''
-              + flip concatMapStrings (ips) (ip:
-                let
-                  address = "${ip.address}/${toString ip.prefixLength}";
-                in
-                ''
-                  echo -n "Deleting ${address}..."
-                  ip addr del "${address}" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed"
-                  echo ""
-                '');
-          };
-
-        createTunDevice = i: nameValuePair "${i.name}-netdev"
-          { description = "Virtual Network Interface ${i.name}";
-            requires = [ "dev-net-tun.device" ];
-            after = [ "dev-net-tun.device" ];
-            wantedBy = [ "network.target" (subsystemDevice i.name) ];
-            path = [ pkgs.iproute ];
-            serviceConfig = {
-              Type = "oneshot";
-              RemainAfterExit = true;
-            };
-            script = ''
-              ip tuntap add dev "${i.name}" \
-              ${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \
-              user "${i.virtualOwner}"
-            '';
-            postStop = ''
-              ip link del ${i.name}
-            '';
-          };
-
-        createBridgeDevice = n: v: nameValuePair "${n}-netdev"
-          (let
-            deps = map subsystemDevice v.interfaces;
-          in
-          { description = "Bridge Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
-            bindsTo = deps;
-            after = deps;
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
-            path = [ pkgs.bridge_utils pkgs.iproute ];
-            script =
-              ''
-                # Remove Dead Interfaces
-                ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
-
-                brctl addbr "${n}"
-
-                # Set bridge's hello time to 0 to avoid startup delays.
-                brctl setfd "${n}" 0
-
-                ${flip concatMapStrings v.interfaces (i: ''
-                  brctl addif "${n}" "${i}"
-                  ip link set "${i}" up
-                  ip addr flush dev "${i}"
-
-                  echo "bringing up network device ${n}..."
-                  ip link set "${n}" up
-                '')}
-
-                # !!! Should delete (brctl delif) any interfaces that
-                # no longer belong to the bridge.
-              '';
-            postStop =
-              ''
-                ip link set "${n}" down
-                brctl delbr "${n}"
-              '';
-          });
-
-        createBondDevice = n: v: nameValuePair "${n}-netdev"
-          (let
-            deps = map subsystemDevice v.interfaces;
-          in
-          { description = "Bond Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
-            bindsTo = deps;
-            after = deps;
-            before = [ "${n}-cfg.service" ];
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
-            path = [ pkgs.ifenslave pkgs.iproute ];
-            script = ''
-              ip link add name "${n}" type bond
-
-              # !!! There must be a better way to wait for the interface
-              while [ ! -d /sys/class/net/${n} ]; do sleep 0.1; done;
-
-              # Ensure the link is down so that we can set options
-              ip link set "${n}" down
-
-              # Set the miimon and mode options
-              ${optionalString (v.miimon != null)
-                "echo \"${toString v.miimon}\" >/sys/class/net/${n}/bonding/miimon"}
-              ${optionalString (v.mode != null)
-                "echo \"${v.mode}\" >/sys/class/net/${n}/bonding/mode"}
-              ${optionalString (v.lacp_rate != null)
-                "echo \"${v.lacp_rate}\" >/sys/class/net/${n}/bonding/lacp_rate"}
-              ${optionalString (v.xmit_hash_policy != null)
-                "echo \"${v.xmit_hash_policy}\" >/sys/class/net/${n}/bonding/xmit_hash_policy"}
-
-              # Bring up the bond and enslave the specified interfaces
-              ip link set "${n}" up
-              ${flip concatMapStrings v.interfaces (i: ''
-                ifenslave "${n}" "${i}"
-              '')}
-            '';
-            postStop = ''
-              ${flip concatMapStrings v.interfaces (i: ''
-                ifenslave -d "${n}" "${i}" >/dev/null 2>&1 || true
-              '')}
-              ip link set "${n}" down >/dev/null 2>&1 || true
-              ip link del "${n}" >/dev/null 2>&1 || true
-            '';
-          });
-
-        createSitDevice = n: v: nameValuePair "${n}-netdev"
-          (let
-            deps = optional (v.dev != null) (subsystemDevice v.dev);
-          in
-          { description = "6-to-4 Tunnel Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
-            bindsTo = deps;
-            after = deps;
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
-            path = [ pkgs.iproute ];
-            script = ''
-              # Remove Dead Interfaces
-              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
-              ip link add name "${n}" type sit \
-                ${optionalString (v.remote != null) "remote \"${v.remote}\""} \
-                ${optionalString (v.local != null) "local \"${v.local}\""} \
-                ${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \
-                ${optionalString (v.dev != null) "dev \"${v.dev}\""}
-              ip link set "${n}" up
-            '';
-            postStop = ''
-              ip link delete "${n}"
-            '';
-          });
-
-        createVlanDevice = n: v: nameValuePair "${n}-netdev"
-          (let
-            deps = [ (subsystemDevice v.interface) ];
-          in
-          { description = "Vlan Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
-            bindsTo = deps;
-            after = deps;
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
-            path = [ pkgs.iproute ];
-            script = ''
-              # Remove Dead Interfaces
-              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
-              ip link add link "${v.interface}" name "${n}" type vlan id "${toString v.id}"
-              ip link set "${n}" up
-            '';
-            postStop = ''
-              ip link delete "${n}"
-            '';
-          });
-
-      in listToAttrs (
-           map configureInterface interfaces ++
-           map createTunDevice (filter (i: i.virtual) interfaces))
-         // mapAttrs' createBridgeDevice cfg.bridges
-         // mapAttrs' createBondDevice cfg.bonds
-         // mapAttrs' createSitDevice cfg.sits
-         // mapAttrs' createVlanDevice cfg.vlans
-         // { "network-setup" = networkSetup; };
-
-    # Set the host and domain names in the activation script.  Don't
-    # clear it if it's not configured in the NixOS configuration,
-    # since it may have been set by dhcpcd in the meantime.
-    system.activationScripts.hostname =
-      optionalString (config.networking.hostName != "") ''
-        hostname "${config.networking.hostName}"
-      '';
-    system.activationScripts.domain =
-      optionalString (config.networking.domain != "") ''
-        domainname "${config.networking.domain}"
-      '';
-
-    services.udev.extraRules =
-      ''
-        KERNEL=="tun", TAG+="systemd"
-      '';
-
+    systemd.services = {
+      network-local-commands = {
+        description = "Extra networking commands.";
+        before = [ "network.target" ];
+        wantedBy = [ "network.target" ];
+        after = [ "network-pre.target" ];
+        unitConfig.ConditionCapability = "CAP_NET_ADMIN";
+        path = [ pkgs.iproute ];
+        serviceConfig.Type = "oneshot";
+        serviceConfig.RemainAfterExit = true;
+        script = ''
+          # Run any user-specified commands.
+          ${cfg.localCommands}
+        '';
+      };
+    } // (listToAttrs (flip map interfaces (i:
+      nameValuePair "network-link-${i.name}"
+      { description = "Link configuration of ${i.name}";
+        wantedBy = [ "network-interfaces.target" ];
+        before = [ "network-interfaces.target" ];
+        bindsTo = [ (subsystemDevice i.name) ];
+        after = [ (subsystemDevice i.name) "network-pre.target" ];
+        path = [ pkgs.iproute ];
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = true;
+        };
+        script =
+          ''
+            echo "Configuring link..."
+          '' + optionalString (i.macAddress != null) ''
+            echo "setting MAC address to ${i.macAddress}..."
+            ip link set "${i.name}" address "${i.macAddress}"
+          '' + optionalString (i.mtu != null) ''
+            echo "setting MTU to ${toString i.mtu}..."
+            ip link set "${i.name}" mtu "${toString i.mtu}"
+          '';
+      })));
   };
 
 }
diff --git a/nixos/modules/tasks/swraid.nix b/nixos/modules/tasks/swraid.nix
index 3b4aa9875f26..8e9728919718 100644
--- a/nixos/modules/tasks/swraid.nix
+++ b/nixos/modules/tasks/swraid.nix
@@ -8,4 +8,8 @@
 
   boot.initrd.availableKernelModules = [ "md_mod" "raid0" "raid1" "raid456" ];
 
+  boot.initrd.extraUdevRulesCommands = ''
+    cp -v ${pkgs.mdadm}/lib/udev/rules.d/*.rules $out/
+  '';
+
 }
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index 54a376c9560e..4b4284d85319 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -98,7 +98,7 @@ let kernel = config.boot.kernelPackages.kernel; in
     networking.usePredictableInterfaceNames = false;
 
     # Make it easy to log in as root when running the test interactively.
-    security.initialRootPassword = mkDefault "";
+    users.extraUsers.root.initialHashedPassword = mkOverride 150 "";
 
   };
 
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index 552d787b4478..d175bac3074d 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -191,10 +191,5 @@ in
     environment.systemPackages = [ pkgs.cryptsetup ];
 
     boot.initrd.supportedFilesystems = [ "unionfs-fuse" ];
-
-    # Prevent logging in as root without a password.  This doesn't really matter,
-    # since the only PAM services that allow logging in with a null
-    # password are local ones that are inaccessible on EC2 machines.
-    security.initialRootPassword = mkDefault "!";
   };
 }
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 35e37257838e..994a00fb028f 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -271,9 +271,12 @@ in
 
           NotifyAccess = "all";
 
-          # Note that on reboot, systemd-nspawn returns 10, so this
+          # Note that on reboot, systemd-nspawn returns 133, so this
           # unit will be restarted. On poweroff, it returns 0, so the
           # unit won't be restarted.
+          RestartForceExitStatus = "133";
+          SuccessExitStatus = "133";
+
           Restart = "on-failure";
 
           # Hack: we don't want to kill systemd-nspawn, since we call
@@ -305,8 +308,6 @@ in
           '';
       }) config.containers;
 
-    # FIXME: auto-start containers.
-
     # Generate /etc/hosts entries for the containers.
     networking.extraHosts = concatStrings (mapAttrsToList (name: cfg: optionalString (cfg.localAddress != null)
       ''
diff --git a/nixos/modules/virtualisation/docker-image.nix b/nixos/modules/virtualisation/docker-image.nix
index 13b861dc9884..0195ca5c6dce 100644
--- a/nixos/modules/virtualisation/docker-image.nix
+++ b/nixos/modules/virtualisation/docker-image.nix
@@ -1,67 +1,19 @@
-{ config, lib, pkgs, ... }:
+{ config, pkgs, ... }:
 
-with lib;
-
-let
- pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
-
-in {
-  # Create the tarball
-  system.build.dockerImage = import ../../lib/make-system-tarball.nix {
-    inherit (pkgs) stdenv perl xz pathsFromGraph;
-
-    contents = [];
-    extraArgs = "--owner=0";
-    storeContents = [
-      { object = config.system.build.toplevel + "/init";
-        symlink = "/bin/init";
-      }
-    ] ++ (pkgs2storeContents [ pkgs.stdenv ]);
-  };
+{
+  imports = [
+    ../profiles/container.nix
+  ];
 
   boot.postBootCommands =
     ''
-      # After booting, register the contents of the Nix store in the Nix
-      # database.
-      if [ -f /nix-path-registration ]; then
-        ${config.nix.package}/bin/nix-store --load-db < /nix-path-registration &&
-        rm /nix-path-registration
-      fi
-
-      # nixos-rebuild also requires a "system" profile and an
-      # /etc/NIXOS tag.
-      touch /etc/NIXOS
-      ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
-
       # Set virtualisation to docker
-      echo "docker" > /run/systemd/container 
+      echo "docker" > /run/systemd/container
     '';
 
-
-  # docker image config
-  require = [
-    ../installer/cd-dvd/channel.nix
-    ../profiles/minimal.nix
-    ../profiles/clone-config.nix
-  ];
-
-  boot.isContainer = true;
-
-  # Iptables do not work in docker
+  # Iptables do not work in Docker.
   networking.firewall.enable = false;
 
-  services.openssh.enable = true;
-
-  # Socket activated ssh presents problem in docker
+  # Socket activated ssh presents problem in Docker.
   services.openssh.startWhenNeeded = false;
-
-  # Allow the user to login as root without password
-  security.initialRootPassword = "";
-
-  # Some more help text.
-  services.mingetty.helpLine =
-    ''
-
-      Log in as "root" with an empty password.
-    '';
 }
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index 1ce066cdc73d..5be76b2682f5 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -7,6 +7,8 @@ with lib;
 let
 
   cfg = config.virtualisation.docker;
+  pro = config.networking.proxy.default;
+  proxy_env = optionalAttrs (pro != null) { Environment = "\"http_proxy=${pro}\""; };
 
 in
 
@@ -73,7 +75,7 @@ in
           #  goes in config bundled with docker itself
           LimitNOFILE = 1048576;
           LimitNPROC = 1048576;
-        };
+        } // proxy_env;
       };
 
       systemd.sockets.docker = {
@@ -99,7 +101,13 @@ in
           #  goes in config bundled with docker itself
           LimitNOFILE = 1048576;
           LimitNPROC = 1048576;
-        };
+        } // proxy_env;
+
+        postStart = ''
+          while ! [ -e /var/run/docker.sock ]; do
+            sleep 0.1
+          done
+        '';
 
         # Presumably some containers are running we don't want to interrupt
         restartIfChanged = false;
diff --git a/nixos/modules/virtualisation/lxc-container.nix b/nixos/modules/virtualisation/lxc-container.nix
new file mode 100644
index 000000000000..2fa749d542ea
--- /dev/null
+++ b/nixos/modules/virtualisation/lxc-container.nix
@@ -0,0 +1,26 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+  imports = [
+    ../profiles/container.nix
+  ];
+
+  # Allow the user to login as root without password.
+  users.extraUsers.root.initialHashedPassword = mkOverride 150 "";
+
+  # Some more help text.
+  services.mingetty.helpLine =
+    ''
+
+      Log in as "root" with an empty password.
+    '';
+
+  # Containers should be light-weight, so start sshd on demand.
+  services.openssh.enable = mkDefault true;
+  services.openssh.startWhenNeeded = mkDefault true;
+
+  # Allow ssh connections
+  networking.firewall.allowedTCPPorts = [ 22 ];
+}
diff --git a/nixos/modules/virtualisation/lxc.nix b/nixos/modules/virtualisation/lxc.nix
new file mode 100644
index 000000000000..10d3a6575fb9
--- /dev/null
+++ b/nixos/modules/virtualisation/lxc.nix
@@ -0,0 +1,75 @@
+# LXC Configuration
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.virtualisation.lxc;
+
+in
+
+{
+  ###### interface
+
+  options.virtualisation.lxc = {
+    enable =
+      mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            This enables Linux Containers (LXC), which provides tools
+            for creating and managing system or application containers
+            on Linux.
+          '';
+      };
+
+    systemConfig =
+      mkOption {
+        type = types.lines;
+        default = "";
+        description =
+          ''
+            This is the system-wide LXC config. See lxc.system.conf(5).
+          '';
+      };
+
+    defaultConfig =
+      mkOption {
+        type = types.lines;
+        default = "";
+        description =
+          ''
+            Default config (default.conf) for new containers, i.e. for
+            network config. See lxc.container.conf(5).
+          '';
+      };
+
+    usernetConfig =
+      mkOption {
+        type = types.lines;
+        default = "";
+        description =
+          ''
+            This is the config file for managing unprivileged user network
+            administration access in LXC. See lxc-user-net(5).
+          '';
+      };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.lxc ];
+
+    environment.etc."lxc/lxc.conf".text = cfg.systemConfig;
+    environment.etc."lxc/lxc-usernet".text = cfg.usernetConfig;
+    environment.etc."lxc/default.conf".text = cfg.defaultConfig;
+
+  };
+
+}
diff --git a/nixos/modules/virtualisation/parallels-guest.nix b/nixos/modules/virtualisation/parallels-guest.nix
new file mode 100644
index 000000000000..141e70974058
--- /dev/null
+++ b/nixos/modules/virtualisation/parallels-guest.nix
@@ -0,0 +1,93 @@
+{ config, lib, pkgs, pkgs_i686, ... }:
+
+with lib;
+
+let
+
+  prl-tools = config.boot.kernelPackages.prl-tools;
+
+in
+
+{
+
+  options = {
+    hardware.parallels = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          This enables Parallel Tools for Linux guests, along with provided
+          video, mouse and other hardware drivers.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf config.hardware.parallels.enable {
+
+    services.xserver = {
+      drivers = singleton
+        { name = "prlvideo"; modules = [ prl-tools ]; libPath = [ prl-tools ]; };
+
+      screenSection = ''
+        Option "NoMTRR"
+      '';
+
+      config = ''
+        Section "InputClass"
+          Identifier "prlmouse"
+          MatchIsPointer "on"
+          MatchTag "prlmouse"
+          Driver "prlmouse"
+        EndSection
+      '';
+    };
+
+    hardware.opengl.package = prl-tools;
+    hardware.opengl.package32 = pkgs_i686.linuxPackages.prl-tools.override { libsOnly = true; kernel = null; };
+
+    services.udev.packages = [ prl-tools ];
+
+    environment.systemPackages = [ prl-tools ];
+
+    boot.extraModulePackages = [ prl-tools ];
+
+    boot.kernelModules = [ "prl_tg" "prl_eth" "prl_fs" "prl_fs_freeze" "acpi_memhotplug" ];
+
+    services.ntp.enable = false;
+
+    systemd.services.prltoolsd = {
+      description = "Parallels Tools' service";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${prl-tools}/bin/prltoolsd -f";
+        PIDFile = "/var/run/prltoolsd.pid";
+      };
+    };
+
+    systemd.services.prlfsmountd = {
+      description = "Parallels Shared Folders Daemon";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = rec {
+        ExecStart = "${prl-tools}/sbin/prlfsmountd ${PIDFile}";
+        ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /media";
+        ExecStopPost = "${prl-tools}/sbin/prlfsmountd -u";
+        PIDFile = "/run/prlfsmountd.pid";
+      };
+    };
+
+    systemd.services.prlshprint = {
+      description = "Parallels Shared Printer Tool";
+      wantedBy = [ "multi-user.target" ];
+      bindsTo = [ "cupsd.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 a7610b3e11a0..42986aa3e033 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -57,8 +57,7 @@ let
           -name ${vmName} \
           -m ${toString config.virtualisation.memorySize} \
           ${optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"} \
-          -net nic,vlan=0,model=virtio \
-          -net user,vlan=0''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \
+          ${concatStringsSep " " config.virtualisation.qemu.networkingOptions} \
           -virtfs local,path=/nix/store,security_model=none,mount_tag=store \
           -virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
           -virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
@@ -248,12 +247,31 @@ in
         description = "Primary IP address used in /etc/hosts.";
       };
 
-    virtualisation.qemu.options =
-      mkOption {
-        default = [];
-        example = [ "-vga std" ];
-        description = "Options passed to QEMU.";
-      };
+    virtualisation.qemu = {
+      options =
+        mkOption {
+          default = [];
+          example = [ "-vga std" ];
+          description = "Options passed to QEMU.";
+        };
+
+      networkingOptions =
+        mkOption {
+          default = [
+            "-net nic,vlan=0,model=virtio"
+            "-net user,vlan=0\${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}"
+          ];
+          type = types.listOf types.str;
+          description = ''
+            Networking-related command-line options that should be passed to qemu.
+            The default is to use userspace networking (slirp).
+
+            If you override this option, be adviced to keep
+            ''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} (as seen in the default)
+            to keep the default runtime behaviour.
+          '';
+        };
+    };
 
     virtualisation.useBootLoader =
       mkOption {
diff --git a/nixos/modules/virtualisation/virtualbox-guest.nix b/nixos/modules/virtualisation/virtualbox-guest.nix
index a5a4db797877..a0e4bd558e05 100644
--- a/nixos/modules/virtualisation/virtualbox-guest.nix
+++ b/nixos/modules/virtualisation/virtualbox-guest.nix
@@ -6,7 +6,7 @@ with lib;
 
 let
 
-  cfg = config.services.virtualbox;
+  cfg = config.services.virtualboxGuest;
   kernel = config.boot.kernelPackages;
 
 in
@@ -17,7 +17,7 @@ in
 
   options = {
 
-    services.virtualbox = {
+    services.virtualboxGuest = {
 
       enable = mkOption {
         default = false;
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index 106b269d9e1f..8232f6e50dfc 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -128,6 +128,6 @@ in {
     boot.loader.grub.version = 2;
     boot.loader.grub.device = "/dev/sda";
   
-    services.virtualbox.enable = true;
+    services.virtualboxGuest.enable = true;
   };
 }
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index 5173c33cab71..f2f68a11a288 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -48,6 +48,7 @@ in rec {
         (all nixos.ova)
 
         #(all nixos.tests.containers)
+        (all nixos.tests.chromium)
         (all nixos.tests.firefox)
         (all nixos.tests.firewall)
         (all nixos.tests.gnome3)
@@ -66,6 +67,14 @@ in rec {
         (all nixos.tests.misc)
         (all nixos.tests.nat.firewall)
         (all nixos.tests.nat.standalone)
+        (all nixos.tests.networking.scripted.static)
+        (all nixos.tests.networking.scripted.dhcpSimple)
+        (all nixos.tests.networking.scripted.dhcpOneIf)
+        (all nixos.tests.networking.scripted.bond)
+        (all nixos.tests.networking.scripted.bridge)
+        (all nixos.tests.networking.scripted.macvlan)
+        (all nixos.tests.networking.scripted.sit)
+        (all nixos.tests.networking.scripted.vlan)
         (all nixos.tests.nfs3)
         (all nixos.tests.openssh)
         (all nixos.tests.printing)
diff --git a/nixos/release-small.nix b/nixos/release-small.nix
index 4099d9147422..07cd672843ea 100644
--- a/nixos/release-small.nix
+++ b/nixos/release-small.nix
@@ -65,6 +65,7 @@ in rec {
       mysql51
       mysql55
       nginx
+      nodejs
       openjdk
       openssh
       php
diff --git a/nixos/release.nix b/nixos/release.nix
index cb79dd3a226b..04b8fd9bf675 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -130,6 +130,7 @@ in rec {
   manual = buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.manual.manual);
   manualPDF = (buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.manual.manualPDF)).x86_64-linux;
   manpages = buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.manual.manpages);
+  options = (buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.manual.optionsJSON)).x86_64-linux;
 
 
   # Build the initial ramdisk so Hydra can keep track of its size over time.
@@ -212,6 +213,12 @@ in rec {
     inherit system;
   });
 
+  # Provide container tarball for lxc, libvirt-lxc, docker-lxc, ...
+  containerTarball = forAllSystems (system: makeSystemTarball {
+    module = ./modules/virtualisation/lxc-container.nix;
+    inherit system;
+  });
+
   /*
   system_tarball_fuloong2f =
     assert builtins.currentSystem == "mips64-linux";
@@ -235,9 +242,16 @@ in rec {
   tests.avahi = callTest tests/avahi.nix {};
   tests.bittorrent = callTest tests/bittorrent.nix {};
   tests.blivet = callTest tests/blivet.nix {};
+  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.firefox = callTest tests/firefox.nix {};
   tests.firewall = callTest tests/firewall.nix {};
+  tests.fleet = scrubDrv (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);
@@ -253,6 +267,7 @@ in rec {
   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.latestKernel.login = callTest tests/login.nix { latestKernel = true; };
   tests.login = callTest tests/login.nix {};
   #tests.logstash = callTest tests/logstash.nix {};
@@ -263,9 +278,28 @@ in rec {
   tests.mysqlReplication = callTest tests/mysql-replication.nix {};
   tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; };
   tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; };
+  tests.networking.networkd.static = callTest tests/networking.nix { networkd = true; test = "static"; };
+  tests.networking.networkd.dhcpSimple = callTest tests/networking.nix { networkd = true; test = "dhcpSimple"; };
+  tests.networking.networkd.dhcpOneIf = callTest tests/networking.nix { networkd = true; test = "dhcpOneIf"; };
+  tests.networking.networkd.bond = callTest tests/networking.nix { networkd = true; test = "bond"; };
+  tests.networking.networkd.bridge = callTest tests/networking.nix { networkd = true; test = "bridge"; };
+  tests.networking.networkd.macvlan = callTest tests/networking.nix { networkd = true; test = "macvlan"; };
+  tests.networking.networkd.sit = callTest tests/networking.nix { networkd = true; test = "sit"; };
+  tests.networking.networkd.vlan = callTest tests/networking.nix { networkd = true; test = "vlan"; };
+  tests.networking.scripted.static = callTest tests/networking.nix { networkd = false; test = "static"; };
+  tests.networking.scripted.dhcpSimple = callTest tests/networking.nix { networkd = false; test = "dhcpSimple"; };
+  tests.networking.scripted.dhcpOneIf = callTest tests/networking.nix { networkd = false; test = "dhcpOneIf"; };
+  tests.networking.scripted.bond = callTest tests/networking.nix { networkd = false; test = "bond"; };
+  tests.networking.scripted.bridge = callTest tests/networking.nix { networkd = false; test = "bridge"; };
+  tests.networking.scripted.macvlan = callTest tests/networking.nix { networkd = false; test = "macvlan"; };
+  tests.networking.scripted.sit = callTest tests/networking.nix { networkd = false; test = "sit"; };
+  tests.networking.scripted.vlan = callTest tests/networking.nix { networkd = false; test = "vlan"; };
+  # 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.nsd = callTest tests/nsd.nix {};
   tests.openssh = callTest tests/openssh.nix {};
+  tests.peerflix = callTest tests/peerflix.nix {};
   tests.printing = callTest tests/printing.nix {};
   tests.proxy = callTest tests/proxy.nix {};
   tests.quake3 = callTest tests/quake3.nix {};
@@ -273,6 +307,7 @@ 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.xfce = callTest tests/xfce.nix {};
 
 
diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix
index 3500ad8ccc31..0d0f00212a02 100644
--- a/nixos/tests/bittorrent.nix
+++ b/nixos/tests/bittorrent.nix
@@ -81,7 +81,7 @@ in
       # Create the torrent.
       $tracker->succeed("mkdir /tmp/data");
       $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2");
-      $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ip4).address}:6969/announce -o /tmp/test.torrent");
+      $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -p -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ip4).address}:6969/announce -o /tmp/test.torrent");
       $tracker->succeed("chmod 644 /tmp/test.torrent");
 
       # Start the tracker.  !!! use a less crappy tracker
diff --git a/nixos/tests/blivet.nix b/nixos/tests/blivet.nix
index acaf4fec614f..72c2a33f87eb 100644
--- a/nixos/tests/blivet.nix
+++ b/nixos/tests/blivet.nix
@@ -43,11 +43,6 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.pythonPackages; rec {
     TMPDIR=/tmp/xchg/bigtmp
     export TMPDIR
 
-    mkPythonPath() {
-      nix-store -qR "$@" \
-        | sed -e 's|$|/lib/${pkgs.python.libPrefix}/site-packages|'
-    }
-
     cp -Rd "${blivet.src}/tests" .
 
     # Skip SELinux tests
@@ -73,8 +68,11 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.pythonPackages; rec {
       -e 's|_STORE_FILE_PATH = .*|_STORE_FILE_PATH = tempfile.gettempdir()|' \
       tests/loopbackedtestcase.py
 
-    PYTHONPATH=".:$(mkPythonPath "${blivet}" "${mock}" | paste -sd :)" \
-      python "${pythonTestRunner}"
+    PYTHONPATH=".:$(< "${pkgs.stdenv.mkDerivation {
+      name = "blivet-pythonpath";
+      buildInputs = [ blivet mock ];
+      buildCommand = "echo \"$PYTHONPATH\" > \"$out\"";
+    }}")" python "${pythonTestRunner}"
   '';
 
   testScript = ''
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
new file mode 100644
index 000000000000..d571a4358164
--- /dev/null
+++ b/nixos/tests/chromium.nix
@@ -0,0 +1,164 @@
+import ./make-test.nix (
+{ pkgs
+, channelMap ? {
+    stable = pkgs.chromium;
+    beta   = pkgs.chromiumBeta;
+    dev    = pkgs.chromiumDev;
+  }
+, ...
+}: rec {
+  name = "chromium";
+
+  machine.imports = [ ./common/x11.nix ];
+
+  startupHTML = pkgs.writeText "chromium-startup.html" ''
+    <!DOCTYPE html>
+    <html>
+    <head>
+    <meta charset="UTF-8">
+    <title>Chromium startup notifier</title>
+    </head>
+    <body onload="javascript:document.title='startup done'">
+      <img src="file://${pkgs.fetchurl {
+        url = "http://nixos.org/logo/nixos.svg";
+        sha256 = "0p2iaqcx2cj24xqycfw1pi4i5461gnn0034lafpi99ph435x6z68";
+      }}" />
+    </body>
+    </html>
+  '';
+
+  testScript = let
+    xdo = name: text: let
+      xdoScript = pkgs.writeText "${name}.xdo" text;
+    in "${pkgs.xdotool}/bin/xdotool '${xdoScript}'";
+  in ''
+    sub createNewWin {
+      $machine->nest("creating a new Chromium window", sub {
+        $machine->execute("${xdo "new-window" ''
+          search --onlyvisible --name "startup done"
+          windowfocus --sync
+          windowactivate --sync
+          key Ctrl+n
+        ''}");
+      });
+    }
+
+    sub closeWin {
+      Machine::retry sub {
+        $machine->execute("${xdo "close-window" ''
+          search --onlyvisible --name "new tab"
+          windowfocus --sync
+          windowactivate --sync
+          key Ctrl+w
+        ''}");
+        for (1..20) {
+          my ($status, $out) = $machine->execute("${xdo "wait-for-close" ''
+            search --onlyvisible --name "new tab"
+          ''}");
+          return 1 if $status != 0;
+          $machine->sleep(1);
+        }
+      }
+    }
+
+    sub waitForNewWin {
+      my $ret = 0;
+      $machine->nest("waiting for new Chromium window to appear", sub {
+        for (1..20) {
+          my ($status, $out) = $machine->execute("${xdo "wait-for-window" ''
+            search --onlyvisible --name "new tab"
+            windowfocus --sync
+            windowactivate --sync
+          ''}");
+          if ($status == 0) {
+            $ret = 1;
+            last;
+          }
+          $machine->sleep(1);
+        }
+      });
+      return $ret;
+    }
+
+    sub createAndWaitForNewWin {
+      for (1..3) {
+        createNewWin;
+        return 1 if waitForNewWin;
+      }
+      die "new window didn't appear within 60 seconds";
+    }
+
+    sub testNewWin {
+      my ($desc, $code) = @_;
+      createAndWaitForNewWin;
+      subtest($desc, $code);
+      closeWin;
+    }
+
+    sub chromiumTest {
+      my ($channel, $pkg, $code) = @_;
+      $machine->waitForX;
+
+      my $url = "file://${startupHTML}";
+      my $args = "--user-data-dir=/tmp/chromium-$channel";
+      $machine->execute(
+        "ulimit -c unlimited; ".
+        "$pkg/bin/chromium $args \"$url\" & disown"
+      );
+      $machine->waitUntilSucceeds("${xdo "check-startup" ''
+        search --sync --onlyvisible --name "startup done"
+        # close first start help popup
+        key Escape
+        windowfocus --sync
+        windowactivate --sync
+      ''}");
+
+      createAndWaitForNewWin;
+      $machine->screenshot($channel."_emptywin");
+      closeWin;
+
+      $machine->screenshot($channel."_startup_done");
+
+      subtest("Chromium $channel", $code);
+
+      $machine->shutdown;
+    }
+
+    for (${let
+      mkArray = name: pkg: "[\"${name}\", \"${pkg}\"]";
+      chanArrays = pkgs.lib.mapAttrsToList mkArray channelMap;
+    in pkgs.lib.concatStringsSep ", " chanArrays}) {
+      my ($channel, $pkg) = @$_;
+      chromiumTest $channel, $pkg, sub {
+        testNewWin "check sandbox", sub {
+          $machine->succeed("${xdo "type-url" ''
+            search --sync --onlyvisible --name "new tab"
+            windowfocus --sync
+            type --delay 1000 "chrome://sandbox"
+          ''}");
+
+          $machine->succeed("${xdo "submit-url" ''
+            search --sync --onlyvisible --name "new tab"
+            windowfocus --sync
+            key --delay 1000 Return
+          ''}");
+
+          $machine->screenshot($channel."_sandbox");
+
+          $machine->succeed("${xdo "submit-url" ''
+            search --sync --onlyvisible --name "sandbox status"
+            windowfocus --sync
+            key --delay 1000 Ctrl+a Ctrl+c
+          ''}");
+
+          my $clipboard = $machine->succeed("${pkgs.xclip}/bin/xclip -o");
+          die "sandbox not working properly: $clipboard"
+          unless $clipboard =~ /suid sandbox.*yes/mi
+              && $clipboard =~ /pid namespaces.*yes/mi
+              && $clipboard =~ /network namespaces.*yes/mi
+              && $clipboard =~ /seccomp.*sandbox.*yes/mi;
+        };
+      };
+    }
+  '';
+})
diff --git a/nixos/tests/cjdns.nix b/nixos/tests/cjdns.nix
new file mode 100644
index 000000000000..7bb3863c683f
--- /dev/null
+++ b/nixos/tests/cjdns.nix
@@ -0,0 +1,123 @@
+let
+  carolKey = "2d2a338b46f8e4a8c462f0c385b481292a05f678e19a2b82755258cf0f0af7e2";
+  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";
+      #networking.firewall.enable = true;
+      networking.firewall.allowPing = true;
+      #networking.firewall.rejectPackets = true;
+    };
+
+in
+
+import ./make-test.nix {
+  name = "cjdns";
+
+  nodes = rec
+    { # Alice finds peers over over ETHInterface.
+      alice =
+        { config, ... }:
+        { imports = [ basicConfig ];
+
+          services.cjdns.ETHInterface.bind = "eth1";
+
+          services.httpd.enable = true;
+          services.httpd.adminAddr = "foo@example.org";
+          networking.firewall.allowedTCPPorts = [ 80 ];
+        };
+
+      # 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;
+                      publicKey = carolPubKey;
+                    };
+                };
+            };
+        };
+
+      # Carol listens on ETHInterface and UDPInterface,
+      # but knows neither Alice or Bob.
+      carol =
+        { config, lib, nodes, ... }:
+          let
+            carolIp4 = (lib.mkForce nodes.carol.config.networking.interfaces.eth1);
+          in
+          { imports = [ basicConfig ];
+
+          environment.etc."cjdns.keys".text = ''
+            CJDNS_PRIVATE_KEY=${carolKey}
+            CJDNS_ADMIN_PASSWORD=FOOBAR
+          '';
+
+          networking.interfaces.eth1.ipAddress = "192.168.0.1";
+                    
+          services.cjdns =
+            { authorizedPasswords = [ carolPassword ];
+              ETHInterface.bind = "eth1";
+              UDPInterface.bind = "192.168.0.1:1024";
+            };
+          networking.firewall.allowedUDPPorts = [ 1024 ];
+        };
+
+    };
+
+  testScript =
+    ''
+      startAll;
+
+      $alice->waitForUnit("cjdns.service");
+      $bob->waitForUnit("cjdns.service");
+      $carol->waitForUnit("cjdns.service");
+
+      sub cjdnsIp {
+          my ($machine) = @_;
+          my $ip = (split /[ \/]+/, $machine->succeed("ip -o -6 addr show dev tun0"))[3];
+          $machine->log("has ip $ip");
+          return $ip;
+      }
+
+      my $aliceIp6 = cjdnsIp $alice;
+      my $bobIp6   = cjdnsIp $bob;
+      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");
+
+      $carol->succeed("ping6 -c 4 $aliceIp6");
+      $carol->succeed("ping6 -c 4 $bobIp6");
+      
+      $alice->succeed("ping6 -c 4 $bobIp6");
+      $bob->succeed("ping6 -c 4 $aliceIp6");
+
+      $alice->waitForUnit("httpd.service");
+
+      $bob->succeed("curl --fail -g http://[$aliceIp6]");
+    '';
+}
diff --git a/nixos/tests/containers.nix b/nixos/tests/containers.nix
index 331324139a1a..e40a8100a06c 100644
--- a/nixos/tests/containers.nix
+++ b/nixos/tests/containers.nix
@@ -43,7 +43,7 @@ import ./make-test.nix {
       $machine->fail("curl --fail --connect-timeout 2 http://$ip/ > /dev/null");
 
       # Make sure we have a NixOS tree (required by ‘nixos-container create’).
-      $machine->succeed("nix-env -qa -A nixos.pkgs.hello >&2");
+      $machine->succeed("PAGER=cat nix-env -qa -A nixos.pkgs.hello >&2");
 
       # Create some containers imperatively.
       my $id1 = $machine->succeed("nixos-container create foo --ensure-unique-name");
@@ -91,6 +91,13 @@ import ./make-test.nix {
       # Execute commands via the root shell.
       $machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
 
+      # Stop and start (regression test for #4989)
+      $machine->succeed("nixos-container stop $id1");
+      $machine->succeed("nixos-container start $id1");
+
+      # Execute commands via the root shell.
+      $machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
+
       # Destroy the containers.
       $machine->succeed("nixos-container destroy $id1");
       $machine->succeed("nixos-container destroy $id2");
diff --git a/nixos/tests/docker-registry.nix b/nixos/tests/docker-registry.nix
new file mode 100644
index 000000000000..cc3c47746800
--- /dev/null
+++ b/nixos/tests/docker-registry.nix
@@ -0,0 +1,40 @@
+# This test runs docker-registry and check if it works
+
+import ./make-test.nix {
+  name = "docker-registry";
+
+  nodes = {
+    registry = { config, pkgs, ... }: {
+      services.dockerRegistry.enable = true;
+      services.dockerRegistry.port = 8080;
+      services.dockerRegistry.host = "0.0.0.0";
+      networking.firewall.allowedTCPPorts = [ 8080 ];
+    };
+
+    client1 = { config, pkgs, ...}: {
+      virtualisation.docker.enable = true;
+      virtualisation.docker.extraOptions = "--insecure-registry registry:8080";
+    };
+
+    client2 = { config, pkgs, ...}: {
+      virtualisation.docker.enable = true;
+      virtualisation.docker.extraOptions = "--insecure-registry registry:8080";
+    };
+  };
+
+  testScript = ''
+    $client1->start();
+    $client1->waitForUnit("docker.service");
+    $client1->succeed("tar cv --files-from /dev/null | docker import - scratch");
+    $client1->succeed("docker tag scratch registry:8080/scratch");
+
+    $registry->start();
+    $registry->waitForUnit("docker-registry.service");
+    $client1->succeed("docker push registry:8080/scratch");
+
+    $client2->start();
+    $client2->waitForUnit("docker.service");
+    $client2->succeed("docker pull registry:8080/scratch");
+    $client2->succeed("docker images | grep scratch");
+  '';
+}
diff --git a/nixos/tests/docker.nix b/nixos/tests/docker.nix
new file mode 100644
index 000000000000..63c909ff294c
--- /dev/null
+++ b/nixos/tests/docker.nix
@@ -0,0 +1,24 @@
+# This test runs docker and checks if simple container starts
+
+import ./make-test.nix {
+  name = "docker";
+
+  nodes = {
+    docker =
+      { config, pkgs, ... }:
+        {
+          virtualisation.docker.enable = true;
+        };
+    };
+
+  testScript = ''
+    startAll;
+
+    $docker->waitForUnit("docker.service");
+    $docker->succeed("tar cv --files-from /dev/null | docker import - scratch");
+    $docker->succeed("docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratch /bin/sleep 10");
+    $docker->succeed("docker ps | grep sleeping");
+    $docker->succeed("docker stop sleeping");
+  '';
+
+}
diff --git a/nixos/tests/etcd.nix b/nixos/tests/etcd.nix
new file mode 100644
index 000000000000..ace5e05b170a
--- /dev/null
+++ b/nixos/tests/etcd.nix
@@ -0,0 +1,108 @@
+# This test runs etcd as single node, multy node and using discovery
+
+import ./make-test.nix {
+  name = "etcd";
+
+  nodes = {
+    simple =
+      { config, pkgs, nodes, ... }:
+        {
+          services.etcd.enable = true;
+          services.etcd.listenClientUrls = ["http://0.0.0.0:4001"];
+          environment.systemPackages = [ pkgs.curl ];
+          networking.firewall.allowedTCPPorts = [ 4001 ];
+        };
+
+
+    node1 =
+      { config, pkgs, nodes, ... }:
+        {
+          services = {
+            etcd = {
+              enable = true;
+              listenPeerUrls = ["http://0.0.0.0:7001"];
+              initialAdvertisePeerUrls = ["http://node1:7001"];
+              initialCluster = ["node1=http://node1:7001" "node2=http://node2:7001"];
+            };
+          };
+
+          networking.firewall.allowedTCPPorts = [ 7001 ];
+        };
+
+    node2 =
+      { config, pkgs, ... }:
+        {
+          services = {
+            etcd = {
+              enable = true;
+              listenPeerUrls = ["http://0.0.0.0:7001"];
+              initialAdvertisePeerUrls = ["http://node2:7001"];
+              initialCluster = ["node1=http://node1:7001" "node2=http://node2:7001"];
+            };
+          };
+
+          networking.firewall.allowedTCPPorts = [ 7001 ];
+        };
+
+    discovery1 =
+      { config, pkgs, nodes, ... }:
+        {
+          services = {
+            etcd = {
+              enable = true;
+              listenPeerUrls = ["http://0.0.0.0:7001"];
+              initialAdvertisePeerUrls = ["http://discovery1:7001"];
+              discovery = "http://simple:4001/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/";
+            };
+          };
+
+          networking.firewall.allowedTCPPorts = [ 7001 ];
+        };
+
+    discovery2 =
+      { config, pkgs, ... }:
+        {
+          services = {
+            etcd = {
+              enable = true;
+              listenPeerUrls = ["http://0.0.0.0:7001"];
+              initialAdvertisePeerUrls = ["http://discovery2:7001"];
+              discovery = "http://simple:4001/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/";
+            };
+          };
+
+          networking.firewall.allowedTCPPorts = [ 7001 ];
+        };
+    };
+
+  testScript = ''
+    subtest "single node", sub {
+      $simple->start();
+      $simple->waitForUnit("etcd.service");
+      $simple->succeed("etcdctl set /foo/bar 'Hello world'");
+      $simple->waitUntilSucceeds("etcdctl get /foo/bar | grep 'Hello world'");
+    };
+
+    subtest "multy node", sub {
+      $node1->start();
+      $node2->start();
+      $node1->waitForUnit("etcd.service");
+      $node2->waitForUnit("etcd.service");
+      $node1->succeed("etcdctl set /foo/bar 'Hello world'");
+      $node2->waitUntilSucceeds("etcdctl get /foo/bar | grep 'Hello world'");
+      $node1->shutdown();
+      $node2->shutdown();
+    };
+
+    subtest "discovery", sub {
+      $simple->succeed("curl -X PUT http://localhost:4001/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=2");
+
+      $discovery1->start();
+      $discovery2->start();
+      $discovery1->waitForUnit("etcd.service");
+      $discovery2->waitForUnit("etcd.service");
+      $discovery1->succeed("etcdctl set /foo/bar 'Hello world'");
+      $discovery2->waitUntilSucceeds("etcdctl get /foo/bar | grep 'Hello world'");
+    };
+  '';
+}
diff --git a/nixos/tests/fleet.nix b/nixos/tests/fleet.nix
new file mode 100644
index 000000000000..c60f596b6f50
--- /dev/null
+++ b/nixos/tests/fleet.nix
@@ -0,0 +1,73 @@
+import ./make-test.nix rec {
+  name = "simple";
+
+  nodes = {
+    node1 =
+      { config, pkgs, ... }:
+        {
+          services = {
+            etcd = {
+              enable = true;
+              listenPeerUrls = ["http://0.0.0.0:7001"];
+              initialAdvertisePeerUrls = ["http://node1:7001"];
+              initialCluster = ["node1=http://node1:7001" "node2=http://node2:7001"];
+            };
+         };
+
+          services.fleet = {
+            enable = true;
+            metadata.name = "node1";
+          };
+
+          networking.firewall.allowedTCPPorts = [ 7001 ];
+        };
+
+    node2 =
+      { config, pkgs, ... }:
+        {
+          services = {
+            etcd = {
+              enable = true;
+              listenPeerUrls = ["http://0.0.0.0:7001"];
+              initialAdvertisePeerUrls = ["http://node2:7001"];
+              initialCluster = ["node1=http://node1:7001" "node2=http://node2:7001"];
+            };
+           };
+
+          services.fleet = {
+            enable = true;
+            metadata.name = "node2";
+          };
+
+          networking.firewall.allowedTCPPorts = [ 7001 ];
+        };
+  };
+
+  service = builtins.toFile "hello.service" ''
+    [Unit]
+    Description=Hello World
+
+    [Service]
+    ExecStart=/bin/sh -c "while true; do echo \"Hello, world\"; /var/run/current-system/sw/bin/sleep 1; done"
+
+    [X-Fleet]
+    MachineMetadata=name=node2
+  '';
+
+  testScript =
+    ''
+      startAll;
+      $node1->waitForUnit("fleet.service");
+      $node2->waitForUnit("fleet.service");
+
+      $node2->waitUntilSucceeds("fleetctl list-machines | grep node1");
+      $node1->waitUntilSucceeds("fleetctl list-machines | grep node2");
+
+      $node1->succeed("cp ${service} hello.service && fleetctl submit hello.service");
+      $node1->succeed("fleetctl list-unit-files | grep hello");
+      $node1->succeed("fleetctl start hello.service");
+      $node1->waitUntilSucceeds("fleetctl list-units | grep running");
+      $node1->succeed("fleetctl stop hello.service");
+      $node1->succeed("fleetctl destroy hello.service");
+    '';
+}
diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix
new file mode 100644
index 000000000000..27c65fe47e8d
--- /dev/null
+++ b/nixos/tests/gitlab.nix
@@ -0,0 +1,21 @@
+# This test runs gitlab and checks if it works
+
+import ./make-test.nix {
+  name = "gitlab";
+
+  nodes = {
+    gitlab = { config, pkgs, ... }: {
+      virtualisation.memorySize = 768;
+      services.gitlab.enable = true;
+      services.gitlab.databasePassword = "gitlab";
+      systemd.services.gitlab.serviceConfig.TimeoutStartSec = "10min";
+    };
+  };
+
+  testScript = ''
+    $gitlab->start();
+    $gitlab->waitForUnit("gitlab.service");
+    $gitlab->waitForUnit("gitlab-sidekiq.service");
+    $gitlab->waitUntilSucceeds("curl http://localhost:8080/users/sign_in");
+  '';
+}
diff --git a/nixos/tests/gnome3.nix b/nixos/tests/gnome3.nix
index df30283e3155..6f2925e52fa4 100644
--- a/nixos/tests/gnome3.nix
+++ b/nixos/tests/gnome3.nix
@@ -11,6 +11,8 @@ import ./make-test.nix {
       services.xserver.displayManager.auto.enable = true;
       services.xserver.displayManager.auto.user = "alice";
       services.xserver.desktopManager.gnome3.enable = true;
+
+      virtualisation.memorySize = 512;
     };
 
   testScript =
diff --git a/nixos/tests/gnome3_12.nix b/nixos/tests/gnome3_12.nix
deleted file mode 100644
index 723d1bc45229..000000000000
--- a/nixos/tests/gnome3_12.nix
+++ /dev/null
@@ -1,31 +0,0 @@
-import ./make-test.nix {
-  name = "gnome3_12";
-
-  machine =
-    { config, pkgs, ... }:
-
-    { imports = [ ./common/user-account.nix ];
-
-      services.xserver.enable = true;
-
-      services.xserver.displayManager.auto.enable = true;
-      services.xserver.displayManager.auto.user = "alice";
-      services.xserver.desktopManager.gnome3.enable = true;
-      environment.gnome3.packageSet = pkgs.gnome3_12;
-    };
-
-  testScript =
-    ''
-      $machine->waitForX;
-      $machine->sleep(15);
-
-      # Check that logging in has given the user ownership of devices.
-      $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
-
-      $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'");
-      $machine->waitForWindow(qr/Terminal/);
-      $machine->sleep(20);
-      $machine->screenshot("screen");
-    '';
-
-}
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 4ee0e064c100..641ff924e14e 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -29,6 +29,10 @@ let
                 pkgs.unionfs-fuse
                 pkgs.gummiboot
               ];
+
+            # Don't use https://cache.nixos.org since the fake
+            # cache.nixos.org doesn't do https.
+            nix.binaryCaches = [ http://cache.nixos.org/ ];
           }
         ];
     }).config.system.build.isoImage;
@@ -38,7 +42,7 @@ let
   makeConfig = { testChannel, grubVersion, grubDevice, grubIdentifier
     , readOnly ? true, forceGrubReinstallCount ? 0 }:
     pkgs.writeText "configuration.nix" ''
-      { config, pkgs, modulesPath, ... }:
+      { config, lib, pkgs, modulesPath, ... }:
 
       { imports =
           [ ./hardware-configuration.nix
@@ -59,6 +63,8 @@ let
         ${optionalString (!readOnly) "nix.readOnlyStore = false;"}
 
         environment.systemPackages = [ ${optionalString testChannel "pkgs.rlwrap"} ];
+
+        nix.binaryCaches = [ http://cache.nixos.org/ ];
       }
     '';
 
@@ -66,7 +72,7 @@ let
   # Configuration of a web server that simulates the Nixpkgs channel
   # distribution server.
   webserver =
-    { config, pkgs, ... }:
+    { config, lib, pkgs, ... }:
 
     { services.httpd.enable = true;
       services.httpd.adminAddr = "foo@example.org";
@@ -185,8 +191,9 @@ let
       $machine->succeed("test -e /boot/grub");
 
       # Did the swap device get activated?
-      $machine->waitForUnit("swap.target");
-      $machine->succeed("cat /proc/swaps | grep -q /dev");
+      # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved
+      #$machine->waitForUnit("swap.target");
+      $machine->waitUntilSucceeds("cat /proc/swaps | grep -q /dev");
 
       # Check whether the channel works.
       $machine->succeed("nix-env -i coreutils >&2");
diff --git a/nixos/tests/kde4.nix b/nixos/tests/kde4.nix
index fcc5101feb3d..dd2574fd02a0 100644
--- a/nixos/tests/kde4.nix
+++ b/nixos/tests/kde4.nix
@@ -41,8 +41,7 @@ import ./make-test.nix ({ pkgs, ... }: {
         ];
     };
 
-  testScript =
-    ''
+  testScript = '' 
       $machine->waitUntilSucceeds("pgrep plasma-desktop");
       $machine->waitForWindow(qr/plasma-desktop/);
 
@@ -60,7 +59,7 @@ import ./make-test.nix ({ pkgs, ... }: {
 
       $machine->sleep(10);
 
-      $machine->screenshot("screen");
+      $machine->screenshot("screen"); 
     '';
 
 })
diff --git a/nixos/tests/kubernetes.nix b/nixos/tests/kubernetes.nix
new file mode 100644
index 000000000000..8bc7c8d618ad
--- /dev/null
+++ b/nixos/tests/kubernetes.nix
@@ -0,0 +1,178 @@
+# This test runs two node kubernetes cluster and checks if simple redis pod works
+
+import ./make-test.nix rec {
+  name = "kubernetes";
+
+  redisMaster = builtins.toFile "redis-master-pod.yaml" ''
+      id: redis-master-pod
+      kind: Pod
+      apiVersion: v1beta1
+      desiredState:
+        manifest:
+          version: v1beta1
+          id: redis-master-pod
+          containers:
+            - name: master
+              image: master:5000/scratch
+              cpu: 100
+              ports:
+                - name: redis-server
+                  containerPort: 6379
+                  hostPort: 6379
+              volumeMounts:
+                - name: nix-store
+                  mountPath: /nix/store
+                  readOnly: true
+              volumeMounts:
+                - name: system-profile
+                  mountPath: /bin
+                  readOnly: true
+              command:
+                - /bin/redis-server
+          volumes:
+            - name: nix-store
+              source:
+                hostDir:
+                  path: /nix/store
+            - name: system-profile
+              source:
+                hostDir:
+                  path: /run/current-system/sw/bin
+      labels:
+        name: redis
+        role: master
+  '';
+
+  nodes = {
+    master =
+      { config, pkgs, lib, nodes, ... }:
+        {
+          virtualisation.memorySize = 768;
+          services.kubernetes = {
+            roles = ["master" "node"];
+            controllerManager.machines = ["master" "node"];
+            kubelet.extraOpts = "-network_container_image=master:5000/pause";
+            apiserver.address = "0.0.0.0";
+            verbose = true;
+          };
+          virtualisation.docker.extraOptions = "--iptables=false --ip-masq=false -b cbr0 --insecure-registry master:5000";
+
+          services.etcd = {
+            listenPeerUrls = ["http://0.0.0.0:7001"];
+            initialAdvertisePeerUrls = ["http://master:7001"];
+            initialCluster = ["master=http://master:7001" "node=http://node:7001"];
+          };
+          services.dockerRegistry.enable = true;
+          services.dockerRegistry.host = "0.0.0.0";
+          services.dockerRegistry.port = 5000;
+
+          virtualisation.vlans = [ 1 2 ];
+          networking.bridges = {
+            cbr0.interfaces = [ "eth2" ];
+          };
+          networking.interfaces = {
+            cbr0 = {
+              ipAddress = "10.10.0.1";
+              prefixLength = 24;
+            };
+            eth2.ip4 = lib.mkOverride 0 [ ];
+          };
+          networking.localCommands = ''
+            ip route add 10.10.0.0/16 dev cbr0
+            ip route flush cache
+          '';
+          networking.extraHosts = "127.0.0.1 master";
+
+          networking.firewall.enable = false;
+          #networking.firewall.allowedTCPPorts = [ 4001 7001 ];
+
+          environment.systemPackages = [ pkgs.redis ];
+        };
+
+    node =
+      { config, pkgs, lib, nodes, ... }:
+        {
+          services.kubernetes = {
+            roles = ["node"];
+            kubelet.extraOpts = "-network_container_image=master:5000/pause";
+            verbose = true;
+          };
+          virtualisation.docker.extraOptions = "--iptables=false --ip-masq=false -b cbr0 --insecure-registry master:5000";
+          services.etcd = {
+            listenPeerUrls = ["http://0.0.0.0:7001"];
+            initialAdvertisePeerUrls = ["http://node:7001"];
+            initialCluster = ["master=http://master:7001" "node=http://node:7001"];
+          };
+
+          virtualisation.vlans = [ 1 2 ];
+          networking.bridges = {
+            cbr0.interfaces = [ "eth2" ];
+          };
+          networking.interfaces = {
+            cbr0 = {
+              ipAddress = "10.10.1.1";
+              prefixLength = 24;
+            };
+            eth2.ip4 = lib.mkOverride 0 [ ];
+          };
+          networking.localCommands = ''
+            ip route add 10.10.0.0/16 dev cbr0
+            ip route flush cache
+          '';
+          networking.extraHosts = "127.0.0.1 node";
+
+          networking.firewall.enable = false;
+          #networking.firewall.allowedTCPPorts = [ 4001 7001 ];
+
+          environment.systemPackages = [ pkgs.redis ];
+        };
+
+    client =
+      { config, pkgs, nodes, ... }:
+        {
+          virtualisation.docker.enable = true;
+          virtualisation.docker.extraOptions = "--insecure-registry master:5000";
+          environment.systemPackages = [ pkgs.kubernetes ];
+          environment.etc."test/redis-master-pod.yaml".source = redisMaster;
+          environment.etc."test/pause".source = "${pkgs.kubernetes}/bin/kube-pause";
+          environment.etc."test/Dockerfile".source = pkgs.writeText "Dockerfile" ''
+            FROM scratch
+            ADD pause /
+            ENTRYPOINT ["/pause"]
+          '';
+        };
+  };
+
+  testScript = ''
+    startAll;
+
+    $master->waitForUnit("kubernetes-apiserver.service");
+    $master->waitForUnit("kubernetes-scheduler.service");
+    $master->waitForUnit("kubernetes-controller-manager.service");
+    $master->waitForUnit("kubernetes-kubelet.service");
+    $master->waitForUnit("kubernetes-proxy.service");
+
+    $node->waitForUnit("kubernetes-kubelet.service");
+    $node->waitForUnit("kubernetes-proxy.service");
+
+    $master->waitUntilSucceeds("kubecfg list minions | grep master");
+    $master->waitUntilSucceeds("kubecfg list 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");
+    $master->waitForUnit("docker-registry.service");
+    $client->succeed("docker push master:5000/scratch");
+    $client->succeed("mkdir -p /root/pause");
+    $client->succeed("cp /etc/test/pause /root/pause/");
+    $client->succeed("cp /etc/test/Dockerfile /root/pause/");
+    $client->succeed("cd /root/pause && docker build -t master:5000/pause .");
+    $client->succeed("docker push master:5000/pause");
+
+    subtest "simple pod", sub {
+      $client->succeed("kubectl create -f ${redisMaster} -s http://master:8080");
+      $client->waitUntilSucceeds("kubectl get pods -s http://master:8080 | grep redis-master | grep -i running");
+    }
+
+  '';
+}
diff --git a/nixos/tests/mesos.nix b/nixos/tests/mesos.nix
new file mode 100644
index 000000000000..040f613c5966
--- /dev/null
+++ b/nixos/tests/mesos.nix
@@ -0,0 +1,29 @@
+import ./make-test.nix {
+  name = "simple";
+
+  machine = { config, pkgs, ... }: {
+    services.zookeeper.enable = true;
+    virtualisation.docker.enable = true;
+    services.mesos = {
+      slave = {
+        enable = true;
+        master = "zk://localhost:2181/mesos";
+        attributes = {
+          tag1 = "foo";
+          tag2 = "bar";
+        };
+      };
+      master = {
+        enable = true;
+        zk = "zk://localhost:2181/mesos";
+      };
+    };
+  };
+
+  testScript =
+    ''
+      startAll;
+      $machine->waitForUnit("mesos-master.service");
+      $machine->waitForUnit("mesos-slave.service");
+    '';
+}
diff --git a/nixos/tests/networking-proxy.nix b/nixos/tests/networking-proxy.nix
new file mode 100644
index 000000000000..30844805ebf8
--- /dev/null
+++ b/nixos/tests/networking-proxy.nix
@@ -0,0 +1,109 @@
+# Test whether `networking.proxy' work as expected.
+
+# TODO: use a real proxy node and put this test into networking.nix
+# TODO: test whether nix tools work as expected behind a proxy
+
+let default-config = {
+        imports = [ ./common/user-account.nix ];
+
+        services.xserver.enable = false;
+
+        virtualisation.memorySize = 128;
+      };
+in import ./make-test.nix {
+  name = "networking-proxy";
+
+  nodes = {
+    # no proxy
+    machine =
+      { config, pkgs, ... }:
+
+      default-config;
+
+    # proxy default
+    machine2 =
+      { config, pkgs, ... }:
+
+      default-config // {
+        networking.proxy.default = "http://user:pass@host:port";
+      };
+
+    # specific proxy options
+    machine3 =
+      { config, pkgs, ... }:
+
+      default-config //
+      {
+        networking.proxy = {
+          # useless because overriden by the next options
+          default = "http://user:pass@host:port";
+          # advanced proxy setup
+          httpProxy = "123-http://user:pass@http-host:port";
+          httpsProxy = "456-http://user:pass@https-host:port";
+          rsyncProxy = "789-http://user:pass@rsync-host:port";
+          ftpProxy = "101112-http://user:pass@ftp-host:port";
+          noProxy = "131415-127.0.0.1,localhost,.localdomain";
+        };
+      };
+
+    # mix default + proxy options
+    machine4 =
+      { config, pkgs, ... }:
+
+      default-config // {
+        networking.proxy = {
+          # open for all *_proxy env var
+          default = "000-http://user:pass@default-host:port";
+          # except for those 2
+          rsyncProxy = "123-http://user:pass@http-host:port";
+          noProxy = "131415-127.0.0.1,localhost,.localdomain";
+        };
+      };
+    };
+
+  testScript =
+    ''
+      startAll;
+
+      # no proxy at all
+      print $machine->execute("env | grep -i proxy");
+      print $machine->execute("su - alice -c 'env | grep -i proxy'");
+      $machine->mustFail("env | grep -i proxy");
+      $machine->mustFail("su - alice -c 'env | grep -i proxy'");
+
+      # Use a default proxy option
+      print $machine2->execute("env | grep -i proxy");
+      print $machine2->execute("su - alice -c 'env | grep -i proxy'");
+      $machine2->mustSucceed("env | grep -i proxy");
+      $machine2->mustSucceed("su - alice -c 'env | grep -i proxy'");
+
+      # explicitly set each proxy option
+      print $machine3->execute("env | grep -i proxy");
+      print $machine3->execute("su - alice -c 'env | grep -i proxy'");
+      $machine3->mustSucceed("env | grep -i http_proxy | grep 123");
+      $machine3->mustSucceed("env | grep -i https_proxy | grep 456");
+      $machine3->mustSucceed("env | grep -i rsync_proxy | grep 789");
+      $machine3->mustSucceed("env | grep -i ftp_proxy | grep 101112");
+      $machine3->mustSucceed("env | grep -i no_proxy | grep 131415");
+      $machine3->mustSucceed("su - alice -c 'env | grep -i http_proxy | grep 123'");
+      $machine3->mustSucceed("su - alice -c 'env | grep -i https_proxy | grep 456'");
+      $machine3->mustSucceed("su - alice -c 'env | grep -i rsync_proxy | grep 789'");
+      $machine3->mustSucceed("su - alice -c 'env | grep -i ftp_proxy | grep 101112'");
+      $machine3->mustSucceed("su - alice -c 'env | grep -i no_proxy | grep 131415'");
+
+      # set default proxy option + some other specifics
+      print $machine4->execute("env | grep -i proxy");
+      print $machine4->execute("su - alice -c 'env | grep -i proxy'");
+      $machine4->mustSucceed("env | grep -i http_proxy | grep 000");
+      $machine4->mustSucceed("env | grep -i https_proxy | grep 000");
+      $machine4->mustSucceed("env | grep -i rsync_proxy | grep 123");
+      $machine4->mustSucceed("env | grep -i ftp_proxy | grep 000");
+      $machine4->mustSucceed("env | grep -i no_proxy | grep 131415");
+      $machine4->mustSucceed("su - alice -c 'env | grep -i http_proxy | grep 000'");
+      $machine4->mustSucceed("su - alice -c 'env | grep -i https_proxy | grep 000'");
+      $machine4->mustSucceed("su - alice -c 'env | grep -i rsync_proxy | grep 123'");
+      $machine4->mustSucceed("su - alice -c 'env | grep -i ftp_proxy | grep 000'");
+      $machine4->mustSucceed("su - alice -c 'env | grep -i no_proxy | grep 131415'");
+    '';
+
+}
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
new file mode 100644
index 000000000000..46d0422f9c66
--- /dev/null
+++ b/nixos/tests/networking.nix
@@ -0,0 +1,381 @@
+import ./make-test.nix ({ networkd, test, ... }:
+  let
+    router = { config, pkgs, ... }:
+      with pkgs.lib;
+      let
+        vlanIfs = range 1 (length config.virtualisation.vlans);
+      in {
+        virtualisation.vlans = [ 1 2 3 ];
+        networking = {
+          useDHCP = false;
+          useNetworkd = networkd;
+          firewall.allowPing = true;
+          interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
+            nameValuePair "eth${toString n}" {
+              ipAddress = "192.168.${toString n}.1";
+              prefixLength = 24;
+            })));
+        };
+        services.dhcpd = {
+          enable = true;
+          interfaces = map (n: "eth${toString n}") vlanIfs;
+          extraConfig = ''
+            option subnet-mask 255.255.255.0;
+          '' + flip concatMapStrings vlanIfs (n: ''
+            subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
+              option broadcast-address 192.168.${toString n}.255;
+              option routers 192.168.${toString n}.1;
+              range 192.168.${toString n}.2 192.168.${toString n}.254;
+            }
+          '');
+        };
+      };
+    testCases = {
+      static = {
+        name = "Static";
+        nodes.router = router;
+        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 2 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = false;
+            defaultGateway = "192.168.1.1";
+            interfaces.eth1.ip4 = mkOverride 0 [
+              { address = "192.168.1.2"; prefixLength = 24; }
+              { address = "192.168.1.3"; prefixLength = 32; }
+              { address = "192.168.1.10"; prefixLength = 32; }
+            ];
+            interfaces.eth2.ip4 = mkOverride 0 [
+              { address = "192.168.2.2"; prefixLength = 24; }
+            ];
+          };
+        };
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client->waitForUnit("network-interfaces.target");
+            $client->waitForUnit("network.target");
+            $router->waitForUnit("network-interfaces.target");
+            $router->waitForUnit("network.target");
+
+            # Make sure dhcpcd is not started
+            $client->fail("systemctl status dhcpcd.service");
+
+            # Test vlan 1
+            $client->succeed("ping -c 1 192.168.1.1");
+            $client->succeed("ping -c 1 192.168.1.2");
+            $client->succeed("ping -c 1 192.168.1.3");
+            $client->succeed("ping -c 1 192.168.1.10");
+
+            $router->succeed("ping -c 1 192.168.1.1");
+            $router->succeed("ping -c 1 192.168.1.2");
+            $router->succeed("ping -c 1 192.168.1.3");
+            $router->succeed("ping -c 1 192.168.1.10");
+
+            # Test vlan 2
+            $client->succeed("ping -c 1 192.168.2.1");
+            $client->succeed("ping -c 1 192.168.2.2");
+
+            $router->succeed("ping -c 1 192.168.2.1");
+            $router->succeed("ping -c 1 192.168.2.2");
+
+            # Test default gateway
+            $router->succeed("ping -c 1 192.168.3.1");
+            $client->succeed("ping -c 1 192.168.3.1");
+          '';
+      };
+      dhcpSimple = {
+        name = "SimpleDHCP";
+        nodes.router = router;
+        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 2 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = true;
+            interfaces.eth1.ip4 = mkOverride 0 [ ];
+            interfaces.eth2.ip4 = mkOverride 0 [ ];
+          };
+        };
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client->waitForUnit("network-interfaces.target");
+            $client->waitForUnit("network.target");
+            $router->waitForUnit("network-interfaces.target");
+            $router->waitForUnit("network.target");
+
+            # Wait until we have an ip address on each interface
+            $client->succeed("while ! ip addr show dev eth1 | grep '192.168.1'; do true; done");
+            $client->succeed("while ! ip addr show dev eth2 | grep '192.168.2'; do true; done");
+
+            # Test vlan 1
+            $client->succeed("ping -c 1 192.168.1.1");
+            $client->succeed("ping -c 1 192.168.1.2");
+
+            $router->succeed("ping -c 1 192.168.1.1");
+            $router->succeed("ping -c 1 192.168.1.2");
+
+            # Test vlan 2
+            $client->succeed("ping -c 1 192.168.2.1");
+            $client->succeed("ping -c 1 192.168.2.2");
+
+            $router->succeed("ping -c 1 192.168.2.1");
+            $router->succeed("ping -c 1 192.168.2.2");
+          '';
+      };
+      dhcpOneIf = {
+        name = "OneInterfaceDHCP";
+        nodes.router = router;
+        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 2 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = false;
+            interfaces.eth1 = {
+              ip4 = mkOverride 0 [ ];
+              useDHCP = true;
+            };
+            interfaces.eth2.ip4 = mkOverride 0 [ ];
+          };
+        };
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client->waitForUnit("network-interfaces.target");
+            $client->waitForUnit("network.target");
+            $router->waitForUnit("network-interfaces.target");
+            $router->waitForUnit("network.target");
+
+            # Wait until we have an ip address on each interface
+            $client->succeed("while ! ip addr show dev eth1 | grep '192.168.1'; do true; done");
+
+            # Test vlan 1
+            $client->succeed("ping -c 1 192.168.1.1");
+            $client->succeed("ping -c 1 192.168.1.2");
+
+            $router->succeed("ping -c 1 192.168.1.1");
+            $router->succeed("ping -c 1 192.168.1.2");
+
+            # Test vlan 2
+            $client->succeed("ping -c 1 192.168.2.1");
+            $client->fail("ping -c 1 192.168.2.2");
+
+            $router->succeed("ping -c 1 192.168.2.1");
+            $router->fail("ping -c 1 192.168.2.2");
+          '';
+      };
+      bond = let
+        node = address: { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 2 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = false;
+            bonds.bond = {
+              mode = "balance-rr";
+              interfaces = [ "eth1" "eth2" ];
+            };
+            interfaces.eth1.ip4 = mkOverride 0 [ ];
+            interfaces.eth2.ip4 = mkOverride 0 [ ];
+            interfaces.bond.ip4 = mkOverride 0
+              [ { inherit address; prefixLength = 30; } ];
+          };
+        };
+      in {
+        name = "Bond";
+        nodes.client1 = node "192.168.1.1";
+        nodes.client2 = node "192.168.1.2";
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client1->waitForUnit("network-interfaces.target");
+            $client1->waitForUnit("network.target");
+            $client2->waitForUnit("network-interfaces.target");
+            $client2->waitForUnit("network.target");
+
+            # Test bonding
+            $client1->succeed("ping -c 2 192.168.1.1");
+            $client1->succeed("ping -c 2 192.168.1.2");
+
+            $client2->succeed("ping -c 2 192.168.1.1");
+            $client2->succeed("ping -c 2 192.168.1.2");
+          '';
+      };
+      bridge = let
+        node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ vlan ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = false;
+            interfaces.eth1.ip4 = mkOverride 0
+              [ { inherit address; prefixLength = 24; } ];
+          };
+        };
+      in {
+        name = "Bridge";
+        nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
+        nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
+        nodes.router = { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 2 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = false;
+            bridges.bridge.interfaces = [ "eth1" "eth2" ];
+            interfaces.eth1.ip4 = mkOverride 0 [ ];
+            interfaces.eth2.ip4 = mkOverride 0 [ ];
+            interfaces.bridge.ip4 = mkOverride 0
+              [ { address = "192.168.1.1"; prefixLength = 24; } ];
+          };
+        };
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client1->waitForUnit("network-interfaces.target");
+            $client1->waitForUnit("network.target");
+            $client2->waitForUnit("network-interfaces.target");
+            $client2->waitForUnit("network.target");
+            $router->waitForUnit("network-interfaces.target");
+            $router->waitForUnit("network.target");
+
+            # Test bridging
+            $client1->succeed("ping -c 1 192.168.1.1");
+            $client1->succeed("ping -c 1 192.168.1.2");
+            $client1->succeed("ping -c 1 192.168.1.3");
+
+            $client2->succeed("ping -c 1 192.168.1.1");
+            $client2->succeed("ping -c 1 192.168.1.2");
+            $client2->succeed("ping -c 1 192.168.1.3");
+
+            $router->succeed("ping -c 1 192.168.1.1");
+            $router->succeed("ping -c 1 192.168.1.2");
+            $router->succeed("ping -c 1 192.168.1.3");
+          '';
+      };
+      macvlan = {
+        name = "MACVLAN";
+        nodes.router = router;
+        nodes.client = { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = true;
+            macvlans.macvlan.interface = "eth1";
+            interfaces.eth1.ip4 = mkOverride 0 [ ];
+          };
+        };
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client->waitForUnit("network-interfaces.target");
+            $client->waitForUnit("network.target");
+            $router->waitForUnit("network-interfaces.target");
+            $router->waitForUnit("network.target");
+
+            # Wait until we have an ip address on each interface
+            $client->succeed("while ! ip addr show dev eth1 | grep '192.168.1'; do true; done");
+            $client->succeed("while ! ip addr show dev macvlan | grep '192.168.1'; do true; done");
+
+            # Test macvlan
+            $client->succeed("ping -c 1 192.168.1.1");
+            $client->succeed("ping -c 1 192.168.1.2");
+            $client->succeed("ping -c 1 192.168.1.3");
+
+            $router->succeed("ping -c 1 192.168.1.1");
+            $router->succeed("ping -c 1 192.168.1.2");
+            $router->succeed("ping -c 1 192.168.1.3");
+          '';
+      };
+      sit = let
+        node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; {
+          virtualisation.vlans = [ 1 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.enable = false;
+            useDHCP = false;
+            sits.sit = {
+              inherit remote;
+              local = address4;
+              dev = "eth1";
+            };
+            interfaces.eth1.ip4 = mkOverride 0
+              [ { address = address4; prefixLength = 24; } ];
+            interfaces.sit.ip6 = mkOverride 0
+              [ { address = address6; prefixLength = 64; } ];
+          };
+        };
+      in {
+        name = "Sit";
+        nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
+        nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client1->waitForUnit("network-interfaces.target");
+            $client1->waitForUnit("network.target");
+            $client2->waitForUnit("network-interfaces.target");
+            $client2->waitForUnit("network.target");
+
+            $client1->succeed("ip addr >&2");
+            $client2->succeed("ip addr >&2");
+
+            # Test ipv6
+            $client1->succeed("ping6 -c 1 fc00::1");
+            $client1->succeed("ping6 -c 1 fc00::2");
+
+            $client2->succeed("ping6 -c 1 fc00::1");
+            $client2->succeed("ping6 -c 1 fc00::2");
+          '';
+      };
+      vlan = let
+        node = address: { config, pkgs, ... }: with pkgs.lib; {
+          #virtualisation.vlans = [ 1 ];
+          networking = {
+            useNetworkd = networkd;
+            firewall.allowPing = true;
+            useDHCP = false;
+            vlans.vlan = {
+              id = 1;
+              interface = "eth0";
+            };
+            interfaces.eth0.ip4 = mkOverride 0 [ ];
+            interfaces.eth1.ip4 = mkOverride 0 [ ];
+            interfaces.vlan.ip4 = mkOverride 0
+              [ { inherit address; prefixLength = 24; } ];
+          };
+        };
+      in {
+        name = "vlan";
+        nodes.client1 = node "192.168.1.1";
+        nodes.client2 = node "192.168.1.2";
+        testScript = { nodes, ... }:
+          ''
+            startAll;
+
+            $client1->waitForUnit("network-interfaces.target");
+            $client1->waitForUnit("network.target");
+            $client2->waitForUnit("network-interfaces.target");
+            $client2->waitForUnit("network.target");
+
+            # Test vlan is setup
+            $client1->succeed("ip addr show dev vlan >&2");
+            $client2->succeed("ip addr show dev vlan >&2");
+          '';
+      };
+    };
+    case = testCases.${test};
+  in case // {
+    name = "${case.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
+  })
diff --git a/nixos/tests/nfs.nix b/nixos/tests/nfs.nix
index 61b2431c04c7..5ed805a16952 100644
--- a/nixos/tests/nfs.nix
+++ b/nixos/tests/nfs.nix
@@ -38,7 +38,8 @@ in
   testScript =
     ''
       $server->waitForUnit("nfsd");
-      $server->waitForUnit("network.target");
+      $server->succeed("systemctl start network-online.target");
+      $server->waitForUnit("network-online.target");
 
       startAll;
 
diff --git a/nixos/tests/peerflix.nix b/nixos/tests/peerflix.nix
new file mode 100644
index 000000000000..739936a10b23
--- /dev/null
+++ b/nixos/tests/peerflix.nix
@@ -0,0 +1,21 @@
+# This test runs peerflix and checks if peerflix starts
+
+import ./make-test.nix {
+  name = "peerflix";
+
+  nodes = {
+    peerflix =
+      { config, pkgs, ... }:
+        {
+          services.peerflix.enable = true;
+        };
+    };
+
+  testScript = ''
+    startAll;
+
+    $peerflix->waitForUnit("peerflix.service");
+    $peerflix->waitUntilSucceeds("curl localhost:9000");
+  '';
+
+}
diff --git a/nixos/tests/printing.nix b/nixos/tests/printing.nix
index a55e077c2696..79f4db3257aa 100644
--- a/nixos/tests/printing.nix
+++ b/nixos/tests/printing.nix
@@ -9,7 +9,7 @@ import ./make-test.nix ({pkgs, ... }: {
       { config, pkgs, ... }:
       { services.printing.enable = true;
         services.printing.listenAddresses = [ "*:631" ];
-        services.printing.cupsdConf =
+        services.printing.extraConf =
           ''
             <Location />
               Order allow,deny
@@ -40,10 +40,10 @@ import ./make-test.nix ({pkgs, ... }: {
       $server->fail("curl --fail --connect-timeout 2  http://client:631/");
 
       # Add a HP Deskjet printer connected via USB to the server.
-      $server->succeed("lpadmin -p DeskjetLocal -v usb://HP/Deskjet%205400%20series?serial=TH93I152S123XY -m 'drv:///sample.drv/deskjet.ppd' -E");
+      $server->succeed("lpadmin -p DeskjetLocal -E -v usb://foobar/printers/foobar");
 
       # Add it to the client as well via IPP.
-      $client->succeed("lpadmin -p DeskjetRemote -v ipp://server/printers/DeskjetLocal -m 'drv:///sample.drv/deskjet.ppd' -E");
+      $client->succeed("lpadmin -p DeskjetRemote -E -v ipp://server/printers/DeskjetLocal");
       $client->succeed("lpadmin -d DeskjetRemote");
 
       # Do some status checks.
@@ -55,7 +55,7 @@ import ./make-test.nix ({pkgs, ... }: {
       $client->succeed("lpq") =~ /DeskjetRemote is ready.*no entries/s or die;
 
       # Test printing various file types.
-      foreach my $file ("${pkgs.groff}/share/doc/*/examples/mom/typesetting.pdf",
+      foreach my $file ("${pkgs.groff}/share/doc/*/examples/mom/penguin.pdf",
                         "${pkgs.groff}/share/doc/*/meref.ps",
                         "${pkgs.cups}/share/doc/cups/images/cups.png",
                         "${pkgs.xz}/share/doc/xz/faq.txt")
@@ -72,9 +72,8 @@ import ./make-test.nix ({pkgs, ... }: {
               # (showing that the right filters have been applied).  Of
               # course, since there is no actual USB printer attached, the
               # file will stay in the queue forever.
-              $server->waitForFile("/var/spool/cups/d*-*");
-              $server->succeed("lpq -a") =~ /remroot.*$fn/ or die;
-              $server->succeed("hexdump -C -n2 /var/spool/cups/d*-*") =~ /1b 45/ or die; # 1b 45 = printer reset
+              $server->waitForFile("/var/spool/cups/d00001-001");
+              $server->succeed("lpq -a") =~ /$fn/ or die;
 
               # Delete the job on the client.  It should disappear on the
               # server as well.
diff --git a/nixos/tests/proxy.nix b/nixos/tests/proxy.nix
index 01f0f3fe17a3..8350bc5c6a4b 100644
--- a/nixos/tests/proxy.nix
+++ b/nixos/tests/proxy.nix
@@ -22,20 +22,19 @@ in
 
         { services.httpd.enable = true;
           services.httpd.adminAddr = "bar@example.org";
-          services.httpd.extraModules = ["proxy_balancer"];
+          services.httpd.extraModules = [ "proxy_balancer" "lbmethod_byrequests" ];
 
           services.httpd.extraConfig =
             ''
               ExtendedStatus on
 
               <Location /server-status>
-                Order deny,allow
-                Allow from all
+                Require all granted
                 SetHandler server-status
               </Location>
 
               <Proxy balancer://cluster>
-                Allow from all
+                Require all granted
                 BalancerMember http://${nodes.backend1.config.networking.hostName} retry=0
                 BalancerMember http://${nodes.backend2.config.networking.hostName} retry=0
               </Proxy>
diff --git a/nixos/tests/quake3.nix b/nixos/tests/quake3.nix
index b16cb179982a..e0e6d6eaadbf 100644
--- a/nixos/tests/quake3.nix
+++ b/nixos/tests/quake3.nix
@@ -15,14 +15,14 @@ in
 rec {
   name = "quake3";
 
-  makeCoverageReport = true;
+  # TODO: lcov doesn't work atm
+  #makeCoverageReport = true;
 
   client =
     { config, pkgs, ... }:
 
     { imports = [ ./common/x11.nix ];
       hardware.opengl.driSupport = true;
-      services.xserver.defaultDepth = pkgs.lib.mkOverride 0 16;
       environment.systemPackages = [ pkgs.quake3demo ];
       nixpkgs.config.packageOverrides = overrides;
     };
diff --git a/nixos/tests/run-in-machine.nix b/nixos/tests/run-in-machine.nix
index 7f6e6a6dc573..d1102f8d4073 100644
--- a/nixos/tests/run-in-machine.nix
+++ b/nixos/tests/run-in-machine.nix
@@ -2,9 +2,7 @@
 
 with import ../lib/testing.nix { inherit system; };
 
-{
-  test = runInMachine {
-    drv = pkgs.hello;
-    machine = { config, pkgs, ... }: { /* services.sshd.enable = true; */ };
-  };
+runInMachine {
+  drv = pkgs.hello;
+  machine = { config, pkgs, ... }: { /* services.sshd.enable = true; */ };
 }
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
new file mode 100644
index 000000000000..b2b1ec877798
--- /dev/null
+++ b/nixos/tests/virtualbox.nix
@@ -0,0 +1,401 @@
+import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
+
+  debug = false;
+
+  testVMConfig = vmName: attrs: { config, pkgs, ... }: {
+    boot.kernelParams = let
+      miniInit = ''
+        #!${pkgs.stdenv.shell} -xe
+        export PATH="${pkgs.coreutils}/bin:${pkgs.utillinux}/bin"
+
+        ${pkgs.linuxPackages.virtualboxGuestAdditions}/sbin/VBoxService
+        ${(attrs.vmScript or (const "")) pkgs}
+
+        i=0
+        while [ ! -e /mnt-root/shutdown ]; do
+          sleep 10
+          i=$(($i + 10))
+          [ $i -le 120 ] || fail
+        done
+
+        rm -f /mnt-root/boot-done /mnt-root/shutdown
+      '';
+    in [
+      "console=tty0" "console=ttyS0" "ignore_loglevel"
+      "boot.trace" "panic=1" "boot.panic_on_fail"
+      "init=${pkgs.writeScript "mini-init.sh" miniInit}"
+    ];
+
+    fileSystems."/" = {
+      device = "vboxshare";
+      fsType = "vboxsf";
+    };
+
+    services.virtualboxGuest.enable = true;
+
+    boot.initrd.kernelModules = [
+      "af_packet" "vboxsf"
+      "virtio" "virtio_pci" "virtio_ring" "virtio_net" "vboxguest"
+    ];
+
+    boot.initrd.extraUtilsCommands = ''
+      cp -av -t "$out/bin/" \
+        "${pkgs.linuxPackages.virtualboxGuestAdditions}/sbin/mount.vboxsf" \
+        "${pkgs.utillinux}/bin/unshare"
+      ${(attrs.extraUtilsCommands or (const "")) pkgs}
+    '';
+
+    boot.initrd.postMountCommands = ''
+      touch /mnt-root/boot-done
+      hostname "${vmName}"
+      mkdir -p /nix/store
+      unshare -m "@shell@" -c '
+        mount -t vboxsf nixstore /nix/store
+        exec "$stage2Init"
+      '
+      poweroff -f
+    '';
+
+    system.requiredKernelConfig = with config.lib.kernelConfig; [
+      (isYes "SERIAL_8250_CONSOLE")
+      (isYes "SERIAL_8250")
+    ];
+  };
+
+  mkLog = logfile: tag: let
+    rotated = map (i: "${logfile}.${toString i}") (range 1 9);
+    all = concatMapStringsSep " " (f: "\"${f}\"") ([logfile] ++ rotated);
+    logcmd = "tail -F ${all} 2> /dev/null | logger -t \"${tag}\"";
+  in optionalString debug "$machine->execute(ru '${logcmd} & disown');";
+
+  testVM = vmName: vmScript: let
+    cfg = (import ../lib/eval-config.nix {
+      system = "i686-linux";
+      modules = [
+        ../modules/profiles/minimal.nix
+        (testVMConfig vmName vmScript)
+      ];
+    }).config;
+  in pkgs.vmTools.runInLinuxVM (pkgs.runCommand "virtualbox-image" {
+    preVM = ''
+      mkdir -p "$out"
+      diskImage="$(pwd)/qimage"
+      ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw "$diskImage" 100M
+    '';
+
+    postVM = ''
+      echo "creating VirtualBox disk image..."
+      ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vdi \
+        "$diskImage" "$out/disk.vdi"
+    '';
+
+    buildInputs = [ pkgs.utillinux pkgs.perl ];
+  } ''
+    ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos
+    ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s
+    . /sys/class/block/vda1/uevent
+    mknod /dev/vda1 b $MAJOR $MINOR
+
+    ${pkgs.e2fsprogs}/sbin/mkfs.ext4 /dev/vda1
+    ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
+    mkdir /mnt
+    mount /dev/vda1 /mnt
+    cp "${cfg.system.build.kernel}/bzImage" /mnt/linux
+    cp "${cfg.system.build.initialRamdisk}/initrd" /mnt/initrd
+
+    ${pkgs.grub2}/bin/grub-install --boot-directory=/mnt /dev/vda
+
+    cat > /mnt/grub/grub.cfg <<GRUB
+    set root=hd0,1
+    linux /linux ${concatStringsSep " " cfg.boot.kernelParams}
+    initrd /initrd
+    boot
+    GRUB
+    umount /mnt
+  '');
+
+  createVM = name: attrs: let
+    mkFlags = concatStringsSep " ";
+
+    sharePath = "/home/alice/vboxshare-${name}";
+
+    createFlags = mkFlags [
+      "--ostype Linux26"
+      "--register"
+    ];
+
+    vmFlags = mkFlags ([
+      "--uart1 0x3F8 4"
+      "--uartmode1 client /run/virtualbox-log-${name}.sock"
+    ] ++ (attrs.vmFlags or []));
+
+    controllerFlags = mkFlags [
+      "--name SATA"
+      "--add sata"
+      "--bootable on"
+      "--hostiocache on"
+    ];
+
+    diskFlags = mkFlags [
+      "--storagectl SATA"
+      "--port 0"
+      "--device 0"
+      "--type hdd"
+      "--mtype immutable"
+      "--medium ${testVM name attrs}/disk.vdi"
+    ];
+
+    sharedFlags = mkFlags [
+      "--name vboxshare"
+      "--hostpath ${sharePath}"
+    ];
+
+    nixstoreFlags = mkFlags [
+      "--name nixstore"
+      "--hostpath /nix/store"
+      "--readonly"
+    ];
+  in {
+    machine = {
+      systemd.sockets = listToAttrs (singleton {
+        name = "vboxtestlog-${name}";
+        value = {
+          description = "VirtualBox Test Machine Log Socket";
+          wantedBy = [ "sockets.target" ];
+          before = [ "multi-user.target" ];
+          socketConfig.ListenStream = "/run/virtualbox-log-${name}.sock";
+          socketConfig.Accept = true;
+        };
+      });
+
+      systemd.services = listToAttrs (singleton {
+        name = "vboxtestlog-${name}@";
+        value = {
+          description = "VirtualBox Test Machine Log";
+          serviceConfig.StandardInput = "socket";
+          serviceConfig.StandardOutput = "syslog";
+          serviceConfig.SyslogIdentifier = "GUEST-${name}";
+          serviceConfig.ExecStart = "${pkgs.coreutils}/bin/cat";
+        };
+      });
+    };
+
+    testSubs = ''
+      sub checkRunning_${name} {
+        my $cmd = 'VBoxManage list runningvms | grep -q "^\"${name}\""';
+        my ($status, $out) = $machine->execute(ru $cmd);
+        return $status == 0;
+      }
+
+      sub cleanup_${name} {
+        $machine->execute(ru "VBoxManage controlvm ${name} poweroff")
+          if checkRunning_${name};
+        $machine->succeed("rm -rf ${sharePath}");
+        $machine->succeed("mkdir -p ${sharePath}");
+        $machine->succeed("chown alice.users ${sharePath}");
+      }
+
+      sub createVM_${name} {
+        vbm("createvm --name ${name} ${createFlags}");
+        vbm("modifyvm ${name} ${vmFlags}");
+        vbm("setextradata ${name} VBoxInternal/PDM/HaltOnReset 1");
+        vbm("storagectl ${name} ${controllerFlags}");
+        vbm("storageattach ${name} ${diskFlags}");
+        vbm("sharedfolder add ${name} ${sharedFlags}");
+        vbm("sharedfolder add ${name} ${nixstoreFlags}");
+        cleanup_${name};
+
+        ${mkLog "$HOME/VirtualBox VMs/${name}/Logs/VBox.log" "HOST-${name}"}
+      }
+
+      sub destroyVM_${name} {
+        cleanup_${name};
+        vbm("unregistervm ${name} --delete");
+      }
+
+      sub waitForVMBoot_${name} {
+        $machine->execute(ru(
+          'set -e; i=0; '.
+          'while ! test -e ${sharePath}/boot-done; do '.
+          'sleep 10; i=$(($i + 10)); [ $i -le 3600 ]; '.
+          'VBoxManage list runningvms | grep -q "^\"${name}\""; '.
+          'done'
+        ));
+      }
+
+      sub waitForIP_${name} ($) {
+        my $property = "/VirtualBox/GuestInfo/Net/$_[0]/V4/IP";
+        my $getip = "VBoxManage guestproperty get ${name} $property | ".
+                    "sed -n -e 's/^Value: //p'";
+        my $ip = $machine->succeed(ru(
+          'for i in $(seq 1000); do '.
+          'if ipaddr="$('.$getip.')" && [ -n "$ipaddr" ]; then '.
+          'echo "$ipaddr"; exit 0; '.
+          'fi; '.
+          'sleep 1; '.
+          'done; '.
+          'echo "Could not get IPv4 address for ${name}!" >&2; '.
+          'exit 1'
+        ));
+        chomp $ip;
+        return $ip;
+      }
+
+      sub waitForStartup_${name} {
+        for (my $i = 0; $i <= 120; $i += 10) {
+          $machine->sleep(10);
+          return if checkRunning_${name};
+        }
+        die "VirtualBox VM didn't start up within 2 minutes";
+      }
+
+      sub waitForShutdown_${name} {
+        for (my $i = 0; $i <= 120; $i += 10) {
+          $machine->sleep(10);
+          return unless checkRunning_${name};
+        }
+        die "VirtualBox VM didn't shut down within 2 minutes";
+      }
+
+      sub shutdownVM_${name} {
+        $machine->succeed(ru "touch ${sharePath}/shutdown");
+        $machine->waitUntilSucceeds(
+          "test ! -e ${sharePath}/shutdown ".
+          "  -a ! -e ${sharePath}/boot-done"
+        );
+        waitForShutdown_${name};
+      }
+    '';
+  };
+
+  hostonlyVMFlags = [
+    "--nictype1 virtio"
+    "--nictype2 virtio"
+    "--nic2 hostonly"
+    "--hostonlyadapter2 vboxnet0"
+  ];
+
+  dhcpScript = pkgs: ''
+    ${pkgs.dhcp}/bin/dhclient \
+      -lf /run/dhcp.leases \
+      -pf /run/dhclient.pid \
+      -v eth0 eth1
+
+    otherIP="$(${pkgs.netcat}/bin/netcat -clp 1234 || :)"
+    ${pkgs.iputils}/bin/ping -I eth1 -c1 "$otherIP"
+    echo "$otherIP reachable" | ${pkgs.netcat}/bin/netcat -clp 5678 || :
+  '';
+
+  vboxVMs = mapAttrs createVM {
+    simple = {};
+
+    test1.vmFlags = hostonlyVMFlags;
+    test1.vmScript = dhcpScript;
+
+    test2.vmFlags = hostonlyVMFlags;
+    test2.vmScript = dhcpScript;
+  };
+
+in {
+  name = "virtualbox";
+
+  machine = { pkgs, lib, config, ... }: {
+    imports = let
+      mkVMConf = name: val: val.machine // { key = "${name}-config"; };
+      vmConfigs = mapAttrsToList mkVMConf vboxVMs;
+    in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs;
+    virtualisation.memorySize = 768;
+    services.virtualboxHost.enable = true;
+    users.extraUsers.alice.extraGroups = let
+      inherit (config.services.virtualboxHost) enableHardening;
+    in lib.mkIf enableHardening (lib.singleton "vboxusers");
+  };
+
+  testScript = ''
+    sub ru ($) {
+      my $esc = $_[0] =~ s/'/'\\${"'"}'/gr;
+      return "su - alice -c '$esc'";
+    }
+
+    sub vbm {
+      $machine->succeed(ru("VBoxManage ".$_[0]));
+    };
+
+    ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)}
+
+    $machine->waitForX;
+
+    ${mkLog "$HOME/.config/VirtualBox/VBoxSVC.log" "HOST-SVC"}
+
+    createVM_simple;
+
+    subtest "simple-gui", sub {
+      $machine->succeed(ru "VirtualBox &");
+      $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/);
+      $machine->sleep(5);
+      $machine->screenshot("gui_manager_started");
+      $machine->sendKeys("ret");
+      $machine->screenshot("gui_manager_sent_startup");
+      waitForStartup_simple;
+      $machine->screenshot("gui_started");
+      waitForVMBoot_simple;
+      $machine->screenshot("gui_booted");
+      shutdownVM_simple;
+      $machine->sleep(5);
+      $machine->screenshot("gui_stopped");
+      $machine->sendKeys("ctrl-q");
+      $machine->sleep(5);
+      $machine->screenshot("gui_manager_stopped");
+    };
+
+    cleanup_simple;
+
+    subtest "simple-cli", sub {
+      vbm("startvm simple");
+      waitForStartup_simple;
+      $machine->screenshot("cli_started");
+      waitForVMBoot_simple;
+      $machine->screenshot("cli_booted");
+      shutdownVM_simple;
+    };
+
+    subtest "privilege-escalation", sub {
+      $machine->fail("test -e '/root/VirtualBox VMs'");
+      $machine->fail("test -e '/root/.config/VirtualBox'");
+      $machine->succeed("test -e '/home/alice/VirtualBox VMs'");
+    };
+
+    destroyVM_simple;
+
+    subtest "net-hostonlyif", sub {
+      createVM_test1;
+      createVM_test2;
+
+      vbm("startvm test1");
+      waitForStartup_test1;
+
+      vbm("startvm test2");
+      waitForStartup_test2;
+
+      waitForVMBoot_test1;
+      waitForVMBoot_test2;
+
+      $machine->screenshot("net_booted");
+
+      my $test1IP = waitForIP_test1 1;
+      my $test2IP = waitForIP_test2 1;
+
+      $machine->succeed("echo '$test2IP' | netcat -c '$test1IP' 1234");
+      $machine->succeed("echo '$test1IP' | netcat -c '$test2IP' 1234");
+
+      $machine->waitUntilSucceeds("netcat -c '$test1IP' 5678 >&2");
+      $machine->waitUntilSucceeds("netcat -c '$test2IP' 5678 >&2");
+
+      shutdownVM_test1;
+      shutdownVM_test2;
+
+      destroyVM_test1;
+      destroyVM_test2;
+    };
+  '';
+})