summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/development/development.xml1
-rw-r--r--nixos/doc/manual/development/nixos-tests.xml3
-rw-r--r--nixos/doc/manual/development/running-nixos-tests-interactively.xml43
-rw-r--r--nixos/doc/manual/development/running-nixos-tests.xml40
-rw-r--r--nixos/doc/manual/release-notes/rl-unstable.xml14
-rw-r--r--nixos/modules/config/i18n.nix7
-rw-r--r--nixos/modules/config/system-path.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix6
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh12
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh8
-rw-r--r--nixos/modules/misc/ids.nix14
-rw-r--r--nixos/modules/module-list.nix11
-rw-r--r--nixos/modules/profiles/base.nix6
-rw-r--r--nixos/modules/profiles/docker-container.nix (renamed from nixos/modules/profiles/container.nix)4
-rw-r--r--nixos/modules/profiles/installation-device.nix7
-rw-r--r--nixos/modules/profiles/minimal.nix5
-rw-r--r--nixos/modules/programs/environment.nix1
-rw-r--r--nixos/modules/programs/shadow.nix6
-rw-r--r--nixos/modules/programs/shell.nix2
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/security/grsecurity.nix35
-rw-r--r--nixos/modules/services/audio/alsa.nix27
-rw-r--r--nixos/modules/services/audio/mpd.nix10
-rw-r--r--nixos/modules/services/backup/tarsnap.nix34
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix12
-rw-r--r--nixos/modules/services/desktops/geoclue2.nix2
-rw-r--r--nixos/modules/services/hardware/actkbd.nix130
-rw-r--r--nixos/modules/services/logging/fluentd.nix1
-rw-r--r--nixos/modules/services/misc/etcd.nix2
-rw-r--r--nixos/modules/services/misc/ihaskell.nix76
-rw-r--r--nixos/modules/services/misc/plex.nix87
-rw-r--r--nixos/modules/services/misc/ripple-data-api.nix30
-rw-r--r--nixos/modules/services/misc/rippled.nix32
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix18
-rw-r--r--nixos/modules/services/networking/asterisk.nix223
-rw-r--r--nixos/modules/services/networking/btsync.nix4
-rw-r--r--nixos/modules/services/networking/cjdns.nix21
-rw-r--r--nixos/modules/services/networking/ddclient.nix4
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix11
-rw-r--r--nixos/modules/services/networking/i2p.nix42
-rw-r--r--nixos/modules/services/networking/lambdabot.nix81
-rw-r--r--nixos/modules/services/networking/networkmanager.nix33
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix10
-rw-r--r--nixos/modules/services/networking/sslh.nix2
-rw-r--r--nixos/modules/services/security/hologram.nix102
-rw-r--r--nixos/modules/services/system/dbus.nix2
-rw-r--r--nixos/modules/services/system/nscd.nix6
-rw-r--r--nixos/modules/services/ttys/agetty.nix23
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix3
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/mediawiki.nix5
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/moodle.nix193
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/per-server-options.nix9
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/wordpress.nix209
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix63
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix12
-rw-r--r--nixos/modules/services/x11/xserver.nix42
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl4
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl4
-rw-r--r--nixos/modules/system/boot/networkd.nix670
-rw-r--r--nixos/modules/system/boot/resolved.nix38
-rw-r--r--nixos/modules/system/boot/stage-2.nix1
-rw-r--r--nixos/modules/system/boot/systemd-lib.nix118
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix464
-rw-r--r--nixos/modules/system/boot/systemd.nix351
-rw-r--r--nixos/modules/system/boot/timesyncd.nix40
-rw-r--r--nixos/modules/tasks/filesystems.nix4
-rw-r--r--nixos/modules/tasks/filesystems/cifs.nix2
-rw-r--r--nixos/modules/tasks/filesystems/ntfs.nix11
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix2
-rw-r--r--nixos/modules/virtualisation/container-config.nix3
-rw-r--r--nixos/modules/virtualisation/docker-image.nix2
-rw-r--r--nixos/modules/virtualisation/google-compute-config.nix4
-rw-r--r--nixos/modules/virtualisation/lxc-container.nix2
-rw-r--r--nixos/tests/gnome3_16.nix34
-rw-r--r--nixos/tests/networking.nix125
77 files changed, 2567 insertions, 1109 deletions
diff --git a/nixos/doc/manual/development/development.xml b/nixos/doc/manual/development/development.xml
index 747159c4427..2983c76c770 100644
--- a/nixos/doc/manual/development/development.xml
+++ b/nixos/doc/manual/development/development.xml
@@ -15,6 +15,7 @@ NixOS.</para>
 <xi:include href="writing-modules.xml" />
 <xi:include href="building-parts.xml" />
 <xi:include href="building-nixos.xml" />
+<xi:include href="nixos-tests.xml" />
 <xi:include href="testing-installer.xml" />
 
 </part>
diff --git a/nixos/doc/manual/development/nixos-tests.xml b/nixos/doc/manual/development/nixos-tests.xml
index a98da993330..c09c41ea3bd 100644
--- a/nixos/doc/manual/development/nixos-tests.xml
+++ b/nixos/doc/manual/development/nixos-tests.xml
@@ -15,5 +15,6 @@ required for the test.</para>
 
 <xi:include href="writing-nixos-tests.xml" />
 <xi:include href="running-nixos-tests.xml" />
+<xi:include href="running-nixos-tests-interactively.xml" />
 
-</chapter>
\ No newline at end of file
+</chapter>
diff --git a/nixos/doc/manual/development/running-nixos-tests-interactively.xml b/nixos/doc/manual/development/running-nixos-tests-interactively.xml
new file mode 100644
index 00000000000..e4749077781
--- /dev/null
+++ b/nixos/doc/manual/development/running-nixos-tests-interactively.xml
@@ -0,0 +1,43 @@
+<section 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-running-nixos-tests">
+<title>Running Tests interactively</title>
+
+<para>The test itself can be run interactively.  This is
+particularly useful when developing or debugging a test:
+
+<screen>
+$ nix-build nixos/tests/login.nix -A driver
+$ ./result/bin/nixos-test-driver
+starting VDE switch for network 1
+&gt;
+</screen>
+
+You can then take any Perl statement, e.g.
+
+<screen>
+&gt; startAll
+&gt; testScript
+&gt; $machine->succeed("touch /tmp/foo")
+</screen>
+
+The function <command>testScript</command> executes the entire test
+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>
+
+<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/running-nixos-tests.xml b/nixos/doc/manual/development/running-nixos-tests.xml
index 156dcd205a5..908c0a66a32 100644
--- a/nixos/doc/manual/development/running-nixos-tests.xml
+++ b/nixos/doc/manual/development/running-nixos-tests.xml
@@ -2,7 +2,7 @@
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         version="5.0"
-        xml:id="sec-running-nixos-tests">
+        xml:id="sec-running-nixos-tests-interactively">
 
 <title>Running Tests</title>
 
@@ -38,42 +38,4 @@ $ firefox result/log.html
 </screen>
 
 </para>
-
-<title>Running Tests interactively</title>
-
-<para>The test itself can be run interactively.  This is
-particularly useful when developing or debugging a test:
-
-<screen>
-$ nix-build nixos/tests/login.nix -A driver
-$ ./result/bin/nixos-test-driver
-starting VDE switch for network 1
-&gt;
-</screen>
-
-You can then take any Perl statement, e.g.
-
-<screen>
-&gt; startAll
-&gt; testScript
-&gt; $machine->succeed("touch /tmp/foo")
-</screen>
-
-The function <command>testScript</command> executes the entire test
-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>
-
-<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/release-notes/rl-unstable.xml b/nixos/doc/manual/release-notes/rl-unstable.xml
index 34ffe1d6d32..cdbd074e782 100644
--- a/nixos/doc/manual/release-notes/rl-unstable.xml
+++ b/nixos/doc/manual/release-notes/rl-unstable.xml
@@ -35,6 +35,20 @@ and old <literal>steam</literal> package -- to <literal>steamOriginal</literal>.
 was accordingly renamed to <literal>bomi</literal>
 </para></listitem>
 
+<listitem>
+    <para>
+        The default <literal>NIX_PATH</literal> for NixOS now includes
+        <literal>/nix/var/nix/profiles/per-user/root/channels</literal>, so it's
+        easy to add custom channels.
+    </para>
+    <para>
+        Moreover, whenever a <command>nixos-rebuild &lt;action&gt;
+        --upgrade</command> is issued, every channel that includes a file
+        called <filename>.update-on-nixos-rebuild</filename> will be upgraded
+        alongside of the <literal>nixos</literal> channel.
+    </para>
+</listitem>
+
 </itemizedlist>
 </para>
 
diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix
index d3f24e280c7..f2aacf9b292 100644
--- a/nixos/modules/config/i18n.nix
+++ b/nixos/modules/config/i18n.nix
@@ -74,14 +74,17 @@ in
 
   config = {
 
-    environment.systemPackages = [ glibcLocales ];
+    environment.systemPackages =
+      optional (config.i18n.supportedLocales != []) glibcLocales;
 
     environment.sessionVariables =
       { LANG = config.i18n.defaultLocale;
         LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
       };
 
-    systemd.globalEnvironment.LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive";
+    systemd.globalEnvironment = mkIf (config.i18n.supportedLocales != []) {
+      LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive";
+    };
 
     # ‘/etc/locale.conf’ is used by systemd.
     environment.etc = singleton
diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix
index f3e86bfd201..d22f9ebd1df 100644
--- a/nixos/modules/config/system-path.nix
+++ b/nixos/modules/config/system-path.nix
@@ -23,7 +23,6 @@ let
       pkgs.cpio
       pkgs.curl
       pkgs.diffutils
-      pkgs.eject # HAL depends on it anyway
       pkgs.findutils
       pkgs.gawk
       pkgs.glibc # for ldd, getent
@@ -40,15 +39,12 @@ let
       pkgs.ncurses
       pkgs.netcat
       pkgs.openssh
-      pkgs.pciutils
       pkgs.perl
       pkgs.procps
       pkgs.rsync
       pkgs.strace
-      pkgs.sysvtools
       pkgs.su
       pkgs.time
-      pkgs.usbutils
       pkgs.utillinux
       extraManpages
     ];
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
index 4896eee2908..446d79ce220 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -45,12 +45,6 @@ with lib;
   # Get a console as soon as the initrd loads fbcon on EFI boot.
   boot.initrd.kernelModules = [ "fbcon" ];
 
-  # 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.
   users.extraUsers.root.initialHashedPassword = "";
 }
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index 14ae3daace0..097631eda9c 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -45,7 +45,9 @@ while [ "$#" -gt 0 ]; do
             ;;
         --chroot)
             runChroot=1
-            chrootCommand=("$@")
+            if [[ "$@" != "" ]]; then
+                chrootCommand=("$@")
+            fi
             break
             ;;
         --help)
@@ -254,8 +256,14 @@ NIXOS_INSTALL_GRUB=1 chroot $mountPoint \
 chroot $mountPoint /nix/var/nix/profiles/system/activate
 
 
+# Some systems may not be prepared to use NixOS' paths.
+export PATH=/run/current-system/sw/bin:/run/current-system/sw/sbin:$PATH
+export NIX_PATH=/nix/var/nix/profiles/per-user/root/channels/nixos:nixpkgs=/etc/nixos/nixpkgs
+export NIX_PATH=$NIX_PATH:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels
+
+
 # Ask the user to set a root password.
-if [ "$(chroot $mountPoint nix-instantiate --eval '<nixos>' -A config.users.mutableUsers)" = true ] && [ -t 0 ] ; then
+if [ "$(chroot $mountPoint nix-instantiate --eval '<nixpkgs/nixos>' -A config.users.mutableUsers)" = true ] && [ -t 1 ] ; then
     echo "setting root password..."
     chroot $mountPoint /var/setuid-wrappers/passwd
 fi
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 1d6df8cb3f7..ccafa30856c 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -96,6 +96,14 @@ fi
 # If ‘--upgrade’ is given, run ‘nix-channel --update nixos’.
 if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then
     nix-channel --update nixos
+
+    # If there are other channels that contain a file called
+    # ".update-on-nixos-rebuild", update them as well.
+    for channelpath in /nix/var/nix/profiles/per-user/root/channels/*; do
+        if [ -e "$channelpath/.update-on-nixos-rebuild" ]; then
+            nix-channel --update "$(basename "$channelpath")"
+        fi
+    done
 fi
 
 # Make sure that we use the Nix package we depend on, not something
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index c2523a3cc32..0319c5688fb 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -203,17 +203,20 @@
       sddm = 175;
       tss = 176;
       memcached = 177;
-      nscd = 178;
       ntp = 179;
       zabbix = 180;
       redis = 181;
-      sshd = 182;
       unifi = 183;
       uptimed = 184;
       zope2 = 185;
       ripple-data-api = 186;
       mediatomb = 187;
       rdnssd = 188;
+      ihaskell = 189;
+      i2p = 190;
+      lambdabot = 191;
+      asterisk = 192;
+      plex = 193;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -394,17 +397,20 @@
       sddm = 175;
       tss = 176;
       #memcached = 177; # unused
-      #nscd = 178; # unused
       #ntp = 179; # unused
       #zabbix = 180; # unused
       #redis = 181; # unused
-      #sshd = 182; # unused
       #unifi = 183; # unused
       #uptimed = 184; # unused
       #zope2 = 185; # unused
       #ripple-data-api = 186; #unused
       mediatomb = 187;
       #rdnssd = 188; # unused
+      ihaskell = 189;
+      i2p = 190;
+      lambdabot = 191;
+      #asterisk = 192; # unused
+      plex = 193;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 17717c5988d..61cc551f435 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -149,6 +149,7 @@
   ./services/games/minecraft-server.nix
   ./services/games/minetest-server.nix
   ./services/hardware/acpid.nix
+  ./services/hardware/actkbd.nix
   ./services/hardware/amd-hybrid-graphics.nix
   ./services/hardware/bluetooth.nix
   ./services/hardware/freefall.nix
@@ -193,6 +194,7 @@
   ./services/misc/gitlab.nix
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
+  ./services/misc/ihaskell.nix
   ./services/misc/mediatomb.nix
   ./services/misc/mesos-master.nix
   ./services/misc/mesos-slave.nix
@@ -202,6 +204,7 @@
   ./services/misc/nix-ssh-serve.nix
   ./services/misc/parsoid.nix
   ./services/misc/phd.nix
+  ./services/misc/plex.nix
   ./services/misc/redmine.nix
   ./services/misc/rippled.nix
   ./services/misc/ripple-data-api.nix
@@ -241,6 +244,7 @@
   ./services/network-filesystems/yandex-disk.nix
   ./services/networking/aiccu.nix
   ./services/networking/amuled.nix
+  ./services/networking/asterisk.nix
   ./services/networking/atftpd.nix
   ./services/networking/avahi-daemon.nix
   ./services/networking/bind.nix
@@ -268,10 +272,12 @@
   ./services/networking/haproxy.nix
   ./services/networking/hostapd.nix
   ./services/networking/i2pd.nix
+  ./services/networking/i2p.nix
   ./services/networking/ifplugd.nix
   ./services/networking/iodined.nix
   ./services/networking/ircd-hybrid/default.nix
   ./services/networking/kippo.nix
+  ./services/networking/lambdabot.nix
   ./services/networking/mailpile.nix
   ./services/networking/minidlna.nix
   ./services/networking/mstpd.nix
@@ -336,6 +342,7 @@
   ./services/security/fprot.nix
   ./services/security/frandom.nix
   ./services/security/haveged.nix
+  ./services/security/hologram.nix
   ./services/security/munge.nix
   ./services/security/torify.nix
   ./services/security/tor.nix
@@ -410,6 +417,9 @@
   ./system/boot/stage-1.nix
   ./system/boot/stage-2.nix
   ./system/boot/systemd.nix
+  ./system/boot/networkd.nix
+  ./system/boot/resolved.nix
+  ./system/boot/timesyncd.nix
   ./system/boot/tmp.nix
   ./system/etc/etc.nix
   ./system/upstart/upstart.nix
@@ -423,6 +433,7 @@
   ./tasks/filesystems/f2fs.nix
   ./tasks/filesystems/jfs.nix
   ./tasks/filesystems/nfs.nix
+  ./tasks/filesystems/ntfs.nix
   ./tasks/filesystems/reiserfs.nix
   ./tasks/filesystems/unionfs-fuse.nix
   ./tasks/filesystems/vfat.nix
diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix
index 5211b905002..f6676fc3793 100644
--- a/nixos/modules/profiles/base.nix
+++ b/nixos/modules/profiles/base.nix
@@ -29,6 +29,8 @@
     pkgs.hdparm
     pkgs.dmraid
     pkgs.smartmontools # for diagnosing hard disks
+    pkgs.pciutils
+    pkgs.usbutils
 
     # Tools to create / manipulate filesystems.
     pkgs.ntfsprogs # for resizing NTFS partitions
@@ -50,6 +52,8 @@
   ];
 
   # Include support for various filesystems.
-  boot.supportedFilesystems = [ "btrfs" "reiserfs" "vfat" "f2fs" ];
+  boot.supportedFilesystems = [ "btrfs" "reiserfs" "vfat" "f2fs" "zfs" "ntfs" "cifs" ];
 
+  # Configure host id for ZFS to work
+  networking.hostId = "8425e349";
 }
diff --git a/nixos/modules/profiles/container.nix b/nixos/modules/profiles/docker-container.nix
index dd2e6579a93..df762b7ac58 100644
--- a/nixos/modules/profiles/container.nix
+++ b/nixos/modules/profiles/docker-container.nix
@@ -45,10 +45,6 @@ in {
       ${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/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix
index 5aab2a2954e..a41d17e5182 100644
--- a/nixos/modules/profiles/installation-device.nix
+++ b/nixos/modules/profiles/installation-device.nix
@@ -26,15 +26,14 @@ with lib;
     # Disable some other stuff we don't need.
     security.sudo.enable = false;
 
-    # Include only the en_US locale.  This saves 75 MiB or so compared to
-    # the full glibcLocales package.
-    i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"];
+    # Automatically log in at the virtual consoles.
+    services.mingetty.autologinUser = "root";
 
     # Some more help text.
     services.mingetty.helpLine =
       ''
 
-        Log in as "root" with an empty password.  ${
+        The "root" account has an empty password.  ${
           optionalString config.services.xserver.enable
             "Type `start display-manager' to\nstart the graphical user interface."}
       '';
diff --git a/nixos/modules/profiles/minimal.nix b/nixos/modules/profiles/minimal.nix
index 5067622aaf1..69729923e03 100644
--- a/nixos/modules/profiles/minimal.nix
+++ b/nixos/modules/profiles/minimal.nix
@@ -3,6 +3,9 @@
 
 { config, lib, pkgs, ... }:
 
+with lib;
+
 {
-  environment.noXlibs = true;
+  environment.noXlibs = mkDefault true;
+  i18n.supportedLocales = [ config.i18n.defaultLocale ];
 }
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index e0379a2c02a..dce757ceb62 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -28,6 +28,7 @@ in
           [ "/nix/var/nix/profiles/per-user/root/channels/nixos"
             "nixpkgs=/etc/nixos/nixpkgs"
             "nixos-config=/etc/nixos/configuration.nix"
+            "/nix/var/nix/profiles/per-user/root/channels"
           ];
       };
 
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 895ecb122cb..566398d839f 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -100,8 +100,10 @@ in
         chgpasswd = { rootOK = true; };
       };
 
-    security.setuidPrograms = [ "passwd" "chfn" "su" "sg" "newgrp"
-      "newuidmap" "newgidmap"  # new in shadow 4.2.x
+    security.setuidPrograms = [ "su" "chfn" ]
+      ++ lib.optionals config.users.mutableUsers
+      [ "passwd" "sg" "newgrp"
+        "newuidmap" "newgidmap" # new in shadow 4.2.x
       ];
 
   };
diff --git a/nixos/modules/programs/shell.nix b/nixos/modules/programs/shell.nix
index 80d40a7c708..d8845fd8f44 100644
--- a/nixos/modules/programs/shell.nix
+++ b/nixos/modules/programs/shell.nix
@@ -53,7 +53,7 @@ in
           # Set up a default Nix expression from which to install stuff.
           if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then
               rm -f $HOME/.nix-defexpr
-              mkdir $HOME/.nix-defexpr
+              mkdir -p $HOME/.nix-defexpr
               if [ "$USER" != root ]; then
                   ln -s /nix/var/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root
               fi
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index d90cffbd967..fc83e7ed590 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -135,7 +135,7 @@ in zipModules ([]
 
 ++ obsolete [ "services" "mysql55" ] [ "services" "mysql" ]
 
-++ obsolete [ "environment" "checkConfigurationOptions" ] [ "_module" "check" ]
+++ alias    [ "environment" "checkConfigurationOptions" ] [ "_module" "check" ]
 
 # XBMC
 ++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index 35974f6890e..b116d8bfef2 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -112,9 +112,6 @@ in
             <literal>kernel.grsecurity.grsec_lock</literal> to
             non-zero as soon as all sysctl options are set. *THIS IS
             EXTREMELY IMPORTANT*!
-
-            If disabled, this also turns off the
-            <literal>systemd-sysctl</literal> service.
           '';
         };
 
@@ -229,11 +226,8 @@ in
             kernel 3.19) to continue.
           '';
         }
-        { assertion = (cfg.stable -> !cfg.testing) || (cfg.testing -> !cfg.stable);
-          message   = ''
-            You must select either the stable or testing patch, not
-            both.
-          '';
+        { assertion = !(cfg.stable && cfg.testing);
+          message   = "Select either one of the stable or testing patch";
         }
         { assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) ||
                       (cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc);
@@ -282,22 +276,21 @@ in
 #     };
 #   };
 
-    system.activationScripts.grsec =
-      ''
-        mkdir -p /etc/grsec
-        if [ ! -f /etc/grsec/learn_config ]; then
-          cp ${pkgs.gradm}/etc/grsec/learn_config /etc/grsec
-        fi
-        if [ ! -f /etc/grsec/policy ]; then
-          cp ${pkgs.gradm}/etc/grsec/policy /etc/grsec
-        fi
-        chmod -R 0600 /etc/grsec
-      '';
+    system.activationScripts = lib.optionalAttrs (!cfg.config.disableRBAC) { grsec = ''
+      mkdir -p /etc/grsec
+      if [ ! -f /etc/grsec/learn_config ]; then
+        cp ${pkgs.gradm}/etc/grsec/learn_config /etc/grsec
+      fi
+      if [ ! -f /etc/grsec/policy ]; then
+        cp ${pkgs.gradm}/etc/grsec/policy /etc/grsec
+      fi
+      chmod -R 0600 /etc/grsec
+    ''; };
 
     # Enable AppArmor, gradm udev rules, and utilities
     security.apparmor.enable   = true;
     boot.kernelPackages        = customGrsecPkg;
-    services.udev.packages     = [ pkgs.gradm ];
-    environment.systemPackages = [ pkgs.gradm pkgs.paxctl pkgs.pax-utils ];
+    services.udev.packages     = lib.optional (!cfg.config.disableRBAC) pkgs.gradm;
+    environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils ] ++ lib.optional (!cfg.config.disableRBAC) pkgs.gradm;
   };
 }
diff --git a/nixos/modules/services/audio/alsa.nix b/nixos/modules/services/audio/alsa.nix
index 653c0ed5d70..c63f4dc8d7f 100644
--- a/nixos/modules/services/audio/alsa.nix
+++ b/nixos/modules/services/audio/alsa.nix
@@ -33,6 +33,16 @@ in
         '';
       };
 
+      enableMediaKeys = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable volume and capture control with keyboard media keys.
+
+          Enabling this will turn on <option>services.actkbd</option>.
+        '';
+      };
+
       extraConfig = mkOption {
         type = types.lines;
         default = "";
@@ -80,6 +90,23 @@ in
         };
       };
 
+    services.actkbd = mkIf config.sound.enableMediaKeys {
+      enable = true;
+      bindings = [
+        # "Mute" media key
+        { keys = [ 113 ]; events = [ "key" ];       command = "${alsaUtils}/bin/amixer -q set Master toggle"; }
+
+        # "Lower Volume" media key
+        { keys = [ 114 ]; events = [ "key" "rep" ]; command = "${alsaUtils}/bin/amixer -q set Master 1- unmute"; }
+
+        # "Raise Volume" media key
+        { keys = [ 115 ]; events = [ "key" "rep" ]; command = "${alsaUtils}/bin/amixer -q set Master 1+ unmute"; }
+
+        # "Mic Mute" media key
+        { keys = [ 190 ]; events = [ "key" ];       command = "${alsaUtils}/bin/amixer -q set Capture toggle"; }
+      ];
+    };
+
   };
 
 }
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index d9b5bf7b5e6..06ba4b9b5ac 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -11,7 +11,7 @@ let
   mpdConf = pkgs.writeText "mpd.conf" ''
     music_directory     "${cfg.musicDirectory}"
     playlist_directory  "${cfg.dataDir}/playlists"
-    db_file             "${cfg.dataDir}/tag_cache"
+    db_file             "${cfg.dbFile}"
     state_file          "${cfg.dataDir}/state"
     sticker_file        "${cfg.dataDir}/sticker.sql"
     log_file            "syslog"
@@ -93,6 +93,14 @@ in {
         };
 
       };
+
+      dbFile = mkOption {
+        type = types.str;
+        default = "${cfg.dataDir}/tag_cache";
+        description = ''
+          The path to MPD's database.
+        '';
+      };
     };
 
   };
diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix
index 155161945cd..f8eeb437844 100644
--- a/nixos/modules/services/backup/tarsnap.nix
+++ b/nixos/modules/services/backup/tarsnap.nix
@@ -5,20 +5,21 @@ with lib;
 let
   cfg = config.services.tarsnap;
 
-  optionalNullStr = e: v: if e == null then "" else v;
-
   configFile = cfg: ''
     cachedir ${config.services.tarsnap.cachedir}
     keyfile  ${config.services.tarsnap.keyfile}
     ${optionalString cfg.nodump "nodump"}
     ${optionalString cfg.printStats "print-stats"}
     ${optionalString cfg.printStats "humanize-numbers"}
-    ${optionalNullStr cfg.checkpointBytes "checkpoint-bytes "+cfg.checkpointBytes}
+    ${optionalString (cfg.checkpointBytes != null) ("checkpoint-bytes "+cfg.checkpointBytes)}
     ${optionalString cfg.aggressiveNetworking "aggressive-networking"}
     ${concatStringsSep "\n" (map (v: "exclude "+v) cfg.excludes)}
     ${concatStringsSep "\n" (map (v: "include "+v) cfg.includes)}
     ${optionalString cfg.lowmem "lowmem"}
     ${optionalString cfg.verylowmem "verylowmem"}
+    ${optionalString (cfg.maxbw != null) ("maxbw "+toString cfg.maxbw)}
+    ${optionalString (cfg.maxbwRateUp != null) ("maxbw-rate-up "+toString cfg.maxbwRateUp)}
+    ${optionalString (cfg.maxbwRateDown != null) ("maxbw-rate-down "+toString cfg.maxbwRateDown)}
   '';
 in
 {
@@ -166,6 +167,33 @@ in
                   slowing down the archiving process.
                 '';
               };
+
+              maxbw = mkOption {
+                type = types.nullOr types.int;
+                default = null;
+                description = ''
+                  Abort archival if upstream bandwidth usage in bytes
+                  exceeds this threshold.
+                '';
+              };
+
+              maxbwRateUp = mkOption {
+                type = types.nullOr types.int;
+                default = null;
+                example = literalExample "25 * 1000";
+                description = ''
+                  Upload bandwidth rate limit in bytes.
+                '';
+              };
+
+              maxbwRateDown = mkOption {
+                type = types.nullOr types.int;
+                default = null;
+                example = literalExample "50 * 1000";
+                description = ''
+                  Download bandwidth rate limit in bytes.
+                '';
+              };
             };
           }
         ));
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index d9ae0454ba5..6a775bb159f 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -224,7 +224,7 @@ in {
 
       machines = mkOption {
         description = "Kubernetes controller list of machines to schedule to schedule onto";
-        default = [];
+        default = [config.networking.hostName];
         type = types.listOf types.str;
       };
 
@@ -310,6 +310,12 @@ in {
         type = types.str;
       };
 
+      master = mkOption {
+        description = "Kubernetes apiserver address";
+        default = "${cfg.apiserver.address}:${toString cfg.apiserver.port}";
+        type = types.str;
+      };
+
       extraOpts = mkOption {
         description = "Kubernetes proxy extra command line options.";
         default = "";
@@ -355,6 +361,7 @@ in {
             --secure_port=${toString cfg.apiserver.securePort} \
             --portal_net=${cfg.apiserver.portalNet} \
             --logtostderr=true \
+            --runtime_config=api/v1beta3 \
             ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
             ${cfg.apiserver.extraOpts}
           '';
@@ -416,7 +423,6 @@ in {
         script = ''
           export PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH"
           exec ${cfg.package}/bin/kubelet \
-            --etcd_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.etcdServers} \
             --api_servers=${concatMapStringsSep "," (f: "http://${f}") cfg.kubelet.apiServers}  \
             --address=${cfg.kubelet.address} \
             --port=${toString cfg.kubelet.port} \
@@ -443,7 +449,7 @@ in {
         after = [ "network-interfaces.target" "etcd.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-proxy \
-            --etcd_servers=${concatMapStringsSep "," (s: "http://${s}") cfg.etcdServers} \
+            --master=${cfg.proxy.master} \
             --bind_address=${cfg.proxy.address} \
             --logtostderr=true \
             ${optionalString cfg.verbose "--v=6 --log_flush_frequency=1s"} \
diff --git a/nixos/modules/services/desktops/geoclue2.nix b/nixos/modules/services/desktops/geoclue2.nix
index 6bdd5edff1f..0e041fdbfbc 100644
--- a/nixos/modules/services/desktops/geoclue2.nix
+++ b/nixos/modules/services/desktops/geoclue2.nix
@@ -34,6 +34,8 @@ with lib;
 
     services.dbus.packages = [ pkgs.geoclue2 ];
 
+    systemd.packages = [ pkgs.geoclue2 ];
+
   };
 
 }
diff --git a/nixos/modules/services/hardware/actkbd.nix b/nixos/modules/services/hardware/actkbd.nix
new file mode 100644
index 00000000000..82de362c371
--- /dev/null
+++ b/nixos/modules/services/hardware/actkbd.nix
@@ -0,0 +1,130 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.actkbd;
+
+  configFile = pkgs.writeText "actkbd.conf" ''
+    ${concatMapStringsSep "\n"
+      ({ keys, events, attributes, command, ... }:
+        ''${concatMapStringsSep "+" toString keys}:${concatStringsSep "," events}:${concatStringsSep "," attributes}:${command}''
+      )
+      cfg.bindings}
+    ${cfg.extraConfig}
+  '';
+
+  bindingCfg = { config, ... }: {
+    options = {
+
+      keys = mkOption {
+        type = types.listOf types.int;
+        description = "List of keycodes to match.";
+      };
+
+      events = mkOption {
+        type = types.listOf (types.enum ["key" "rep" "rel"]);
+        default = [ "key" ];
+        description = "List of events to match.";
+      };
+
+      attributes = mkOption {
+        type = types.listOf types.str;
+        default = [ "exec" ];
+        description = "List of attributes.";
+      };
+
+      command = mkOption {
+        type = types.str;
+        default = "";
+        description = "What to run.";
+      };
+
+    };
+  };
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.actkbd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable the <command>actkbd</command> key mapping daemon.
+
+          Turning this on will start an <command>actkbd</command>
+          instance for every evdev input that has at least one key
+          (which is okay even for systems with tiny memory footprint,
+          since actkbd normally uses &lt;100 bytes of memory per
+          instance).
+
+          This allows binding keys globally without the need for e.g.
+          X11.
+        '';
+      };
+
+      bindings = mkOption {
+        type = types.listOf (types.submodule bindingCfg);
+        default = [];
+        example = lib.literalExample ''
+          [ { keys = [ 113 ]; events = [ "key" ]; command = "''${pkgs.alsaUtils}/bin/amixer -q set Master toggle"; }
+          ]
+        '';
+        description = ''
+          Key bindings for <command>actkbd</command>.
+
+          See <command>actkbd</command> <filename>README</filename> for documentation.
+
+          The example shows a piece of what <option>sound.enableMediaKeys</option> does when enabled.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Literal contents to append to the end of actkbd configuration file.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    services.udev.packages = lib.singleton (pkgs.writeTextFile {
+      name = "actkbd-udev-rules";
+      destination = "/etc/udev/rules.d/61-actkbd.rules";
+      text = ''
+        ACTION=="add", SUBSYSTEM=="input", KERNEL=="event[0-9]*", ENV{ID_INPUT_KEY}=="1", TAG+="systemd", ENV{SYSTEMD_WANTS}+="actkbd@$env{DEVNAME}.service"
+      '';
+    });
+
+    systemd.services."actkbd@" = {
+      enable = true;
+      restartIfChanged = true;
+      unitConfig = {
+        Description = "actkbd on %I";
+        ConditionPathExists = "%I";
+      };
+      serviceConfig = {
+        Type = "forking";
+        ExecStart = "${pkgs.actkbd}/bin/actkbd -D -c ${configFile} -d %I";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/logging/fluentd.nix b/nixos/modules/services/logging/fluentd.nix
index 61eeec504e0..3aa27a15266 100644
--- a/nixos/modules/services/logging/fluentd.nix
+++ b/nixos/modules/services/logging/fluentd.nix
@@ -33,6 +33,7 @@ in {
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
         ExecStart = "${pkgs.fluentd}/bin/fluentd -c ${pkgs.writeText "fluentd.conf" cfg.config}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
       };
     };
   };
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index 284361a04d9..26d2753879d 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -11,7 +11,7 @@ in {
     enable = mkOption {
       description = "Whether to enable etcd.";
       default = false;
-      type = types.uniq types.bool;
+      type = types.bool;
     };
 
     name = mkOption {
diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix
new file mode 100644
index 00000000000..7f7f981de49
--- /dev/null
+++ b/nixos/modules/services/misc/ihaskell.nix
@@ -0,0 +1,76 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.ihaskell;
+  ihaskell = pkgs.ihaskell.override {
+    inherit (cfg.haskellPackages) ihaskell ghcWithPackages;
+    packages = self: cfg.extraPackages self;
+  };
+
+in
+
+{
+  options = {
+    services.ihaskell = {
+      enable = mkOption {
+        default = false;
+        example = true;
+        description = "Autostart an IHaskell notebook service.";
+      };
+
+      haskellPackages = mkOption {
+        default = pkgs.haskellngPackages;
+        defaultText = "pkgs.haskellngPackages";
+        example = literalExample "pkgs.haskell-ng.packages.ghc784";
+        description = ''
+          haskellPackages used to build IHaskell and other packages.
+          This can be used to change the GHC version used to build
+          IHaskell and the packages listed in
+          <varname>extraPackages</varname>.
+        '';
+      };
+
+      extraPackages = mkOption {
+        default = self: [];
+        example = literalExample ''
+          haskellPackages: [
+            haskellPackages.wreq
+            haskellPackages.lens
+          ]
+        '';
+        description = ''
+          Extra packages available to ghc when running ihaskell. The
+          value must be a function which receives the attrset defined
+          in <varname>haskellPackages</varname> as the sole argument.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers.ihaskell = {
+      group = config.users.extraGroups.ihaskell.name;
+      description = "IHaskell user";
+      home = "/var/lib/ihaskell";
+      createHome = true;
+      uid = config.ids.uids.ihaskell;
+    };
+
+    users.extraGroups.ihaskell.gid = config.ids.gids.ihaskell;
+
+    systemd.services.ihaskell = {
+      description = "IHaskell notebook instance";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        User = config.users.extraUsers.ihaskell.name;
+        Group = config.users.extraGroups.ihaskell.name;
+        ExecStart = "${pkgs.stdenv.shell} -c \"cd $HOME;${ihaskell}/bin/ihaskell-notebook\"";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix
new file mode 100644
index 00000000000..f4642b5157e
--- /dev/null
+++ b/nixos/modules/services/misc/plex.nix
@@ -0,0 +1,87 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.plex;
+  plex = pkgs.plex;
+in
+{
+  options = {
+    services.plex = {
+      enable = mkEnableOption "Enable Plex Media Server";
+
+      # FIXME: In order for this config option to work, symlinks in the Plex
+      # package in the Nix store have to be changed to point to this directory.
+      dataDir = mkOption {
+        type = types.str;
+        default = "/var/lib/plex";
+        description = "The directory where Plex stores its data files.";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "plex";
+        description = "User account under which Plex runs.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "plex";
+        description = "Group under which Plex runs.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    # Most of this is just copied from the RPM package's systemd service file.
+    systemd.services.plex = {
+      description = "Plex Media Server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        test -d "${cfg.dataDir}" || {
+          echo "Creating initial Plex data directory in \"${cfg.dataDir}\"."
+          mkdir -p "${cfg.dataDir}"
+          chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}"
+        }
+        # Copy the database skeleton files to /var/lib/plex/.skeleton
+        test -d "${cfg.dataDir}/.skeleton" || mkdir "${cfg.dataDir}/.skeleton"
+        for db in "com.plexapp.plugins.library.db"; do
+            cp "${plex}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db"
+            chmod u+w "${cfg.dataDir}/.skeleton/$db"
+            chown ${cfg.user}:${cfg.group} "${cfg.dataDir}/.skeleton/$db"
+        done
+     '';
+      serviceConfig = {
+        Type = "simple";
+        User = cfg.user;
+        Group = cfg.group;
+        PermissionsStartOnly = "true";
+        ExecStart = "/bin/sh -c '${plex}/usr/lib/plexmediaserver/Plex\\ Media\\ Server'";
+      };
+      environment = {
+        PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=cfg.dataDir;
+        PLEX_MEDIA_SERVER_HOME="${plex}/usr/lib/plexmediaserver";
+        PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="6";
+        PLEX_MEDIA_SERVER_TMPDIR="/tmp";
+        LD_LIBRARY_PATH="${plex}/usr/lib/plexmediaserver";
+        LC_ALL="en_US.UTF-8";
+        LANG="en_US.UTF-8";
+      };
+    };
+
+    users.extraUsers = mkIf (cfg.user == "plex") {
+      plex = {
+        group = cfg.group;
+        uid = config.ids.uids.plex;
+      };
+    };
+
+    users.extraGroups = mkIf (cfg.group == "plex") {
+      plex = {
+        gid = config.ids.gids.plex;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/ripple-data-api.nix b/nixos/modules/services/misc/ripple-data-api.nix
index 6e5ac7ab00b..3b281449a25 100644
--- a/nixos/modules/services/misc/ripple-data-api.nix
+++ b/nixos/modules/services/misc/ripple-data-api.nix
@@ -43,6 +43,24 @@ in {
         type = types.int;
       };
 
+      importMode = mkOption {
+        description = "Ripple data api import mode.";
+        default = "liveOnly";
+        type = types.enum ["live" "liveOnly"];
+      };
+
+      minLedger = mkOption {
+        description = "Ripple data api minimal ledger to fetch.";
+        default = null;
+        type = types.nullOr types.int;
+      };
+
+      maxLedger = mkOption {
+        description = "Ripple data api maximal ledger to fetch.";
+        default = null;
+        type = types.nullOr types.int;
+      };
+
       redis = {
         enable = mkOption {
           description = "Whether to enable caching of ripple data to redis.";
@@ -129,6 +147,7 @@ in {
 
       serviceConfig = {
         ExecStart = "${pkgs.ripple-data-api}/bin/api";
+        Restart = "always";
         User = "ripple-data-api";
       };
     };
@@ -145,8 +164,15 @@ in {
         LOG_FILE = "/dev/null";
       };
 
-      serviceConfig = {
-        ExecStart = "${pkgs.ripple-data-api}/bin/importer live debug2";
+      serviceConfig = let
+        importMode =
+          if cfg.minLedger != null && cfg.maxLedger != null then
+            "${toString cfg.minLedger} ${toString cfg.maxLedger}"
+          else
+            cfg.importMode;
+      in {
+        ExecStart = "${pkgs.ripple-data-api}/bin/importer ${importMode} debug";
+        Restart = "always";
         User = "ripple-data-api";
       };
 
diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix
index 85a1ed8ae9e..03fcc003a40 100644
--- a/nixos/modules/services/misc/rippled.nix
+++ b/nixos/modules/services/misc/rippled.nix
@@ -12,7 +12,7 @@ let
     path=${db.path}
     ${optionalString (db.compression != null) ("compression=${b2i db.compression}") }
     ${optionalString (db.onlineDelete != null) ("online_delete=${toString db.onlineDelete}")}
-    ${optionalString (db.advisoryDelete != null) ("advisory_delete=${toString db.advisoryDelete}")}
+    ${optionalString (db.advisoryDelete != null) ("advisory_delete=${b2i db.advisoryDelete}")}
     ${db.extraOpts}
   '';
 
@@ -71,6 +71,13 @@ let
     [sntp_servers]
     ${concatStringsSep "\n" cfg.sntpServers}
 
+    ${optionalString cfg.statsd.enable ''
+    [insight]
+    server=statsd
+    address=${cfg.statsd.address}
+    prefix=${cfg.statsd.prefix}
+    ''}
+
     [rpc_startup]
     { "command": "log_level", "severity": "${cfg.logLevel}" }
   '' + cfg.extraConfig;
@@ -142,7 +149,6 @@ let
 	  default = null;
 	  type = types.nullOr types.path;
 	};
-
       };
     };
   };
@@ -150,7 +156,7 @@ let
   dbOptions = {
     type = mkOption {
       description = "Rippled database type.";
-      type = types.enum ["rocksdb" "nudb" "sqlite"];
+      type = types.enum ["rocksdb" "nudb" "sqlite" "hyperleveldb"];
       default = "rocksdb";
     };
 
@@ -317,7 +323,7 @@ in
 	  Path to the ripple database.
 	'';
 	type = types.path;
-	default = "/var/lib/rippled/db";
+	default = "/var/lib/rippled";
       };
 
       validationQuorum = mkOption {
@@ -366,6 +372,22 @@ in
 	default = "error";
       };
 
+      statsd = {
+        enable = mkEnableOption "Whether enable statsd monitoring for rippled";
+
+        address = mkOption {
+          description = "The UDP address and port of the listening StatsD server.";
+          default = "127.0.0.1:8125";
+          type = types.str;
+        };
+
+        prefix = mkOption {
+          description = "A string prepended to each collected metric.";
+          default = "";
+          type = types.str;
+        };
+      };
+
       extraConfig = mkOption {
         default = "";
 	description = ''
@@ -400,6 +422,8 @@ in
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/rippled --fg --conf ${cfg.config}";
         User = "rippled";
+	Restart = "on-failure";
+	LimitNOFILE=10000;
       };
     };
 
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index d6babb8e9a5..8b3741bca0a 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -4,6 +4,10 @@ with lib;
 
 let
 
+  smbToString = x: if builtins.typeOf x == "bool"
+                   then (if x then "true" else "false")
+                   else toString x;
+
   cfg = config.services.samba;
 
   samba = cfg.package;
@@ -15,9 +19,9 @@ let
 
   shareConfig = name:
     let share = getAttr name cfg.shares; in
-    "[${name}]\n " + (toString (
+    "[${name}]\n " + (smbToString (
        map
-         (key: "${key} = ${toString (getAttr key share)}\n")
+         (key: "${key} = ${smbToString (getAttr key share)}\n")
          (attrNames share)
     ));
 
@@ -27,12 +31,12 @@ let
       [ global ]
       security = ${cfg.securityType}
       passwd program = /var/setuid-wrappers/passwd %u
-      pam password change = ${if cfg.syncPasswordsByPam then "yes" else "no"}
-      invalid users = ${toString cfg.invalidUsers}
+      pam password change = ${smbToString cfg.syncPasswordsByPam}
+      invalid users = ${smbToString cfg.invalidUsers}
 
       ${cfg.extraConfig}
 
-      ${toString (map shareConfig (attrNames cfg.shares))}
+      ${smbToString (map shareConfig (attrNames cfg.shares))}
     '');
 
   # This may include nss_ldap, needed for samba if it has to use ldap.
@@ -151,7 +155,7 @@ in
         example =
           { srv =
              { path = "/srv";
-               "read only" = "yes";
+               "read only" = true;
                 comment = "Public samba share.";
              };
           };
@@ -193,7 +197,7 @@ in
             "samba-setup" = {
               description = "Samba Setup Task";
               script = setupScript;
-              unitConfig.RequiresMountsFor = "/var/samba /var/log/samba";
+              unitConfig.RequiresMountsFor = "/var/lib/samba";
             };
           };
         };
diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix
new file mode 100644
index 00000000000..b079cb22730
--- /dev/null
+++ b/nixos/modules/services/networking/asterisk.nix
@@ -0,0 +1,223 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.asterisk;
+
+  asteriskUser = "asterisk";
+
+  varlibdir = "/var/lib/asterisk";
+  spooldir = "/var/spool/asterisk";
+  logdir = "/var/log/asterisk";
+
+  asteriskEtc = pkgs.stdenv.mkDerivation
+  ((mapAttrs' (name: value: nameValuePair
+        # Fudge the names to make bash happy
+        ((replaceChars ["."] ["_"] name) + "_")
+        (value)
+      ) cfg.confFiles) //
+  {
+    confFilesString = concatStringsSep " " (
+      attrNames cfg.confFiles
+    );
+
+    name = "asterisk.etc";
+
+    # Default asterisk.conf file
+    # (Notice that astetcdir will be set to the path of this derivation)
+    asteriskConf = ''
+      [directories]
+      astetcdir => @out@
+      astmoddir => ${pkgs.asterisk}/lib/asterisk/modules
+      astvarlibdir => /var/lib/asterisk
+      astdbdir => /var/lib/asterisk
+      astkeydir => /var/lib/asterisk
+      astdatadir => /var/lib/asterisk
+      astagidir => /var/lib/asterisk/agi-bin
+      astspooldir => /var/spool/asterisk
+      astrundir => /var/run/asterisk
+      astlogdir => /var/log/asterisk
+      astsbindir => ${pkgs.asterisk}/sbin
+    '';
+    extraConf = cfg.extraConfig;
+
+    # Loading all modules by default is considered sensible by the authors of
+    # "Asterisk: The Definitive Guide". Secure sites will likely want to
+    # specify their own "modules.conf" in the confFiles option.
+    modulesConf = ''
+      [modules]
+      autoload=yes
+    '';
+
+    # Use syslog for logging so logs can be viewed with journalctl
+    loggerConf = ''
+      [general]
+
+      [logfiles]
+      syslog.local0 => notice,warning,error
+    '';
+
+    buildCommand = ''
+      mkdir -p "$out"
+
+      # Create asterisk.conf, pointing astetcdir to the path of this derivation
+      echo "$asteriskConf" | sed "s|@out@|$out|g" > "$out"/asterisk.conf
+      echo "$extraConf" >> "$out"/asterisk.conf
+
+      echo "$modulesConf" > "$out"/modules.conf
+
+      echo "$loggerConf" > "$out"/logger.conf
+
+      # Config files specified in confFiles option override all other files
+      for i in $confFilesString; do
+        conf=$(echo "$i"_ | sed 's/\./_/g')
+        echo "''${!conf}" > "$out"/"$i"
+      done
+    '';
+  });
+in
+
+{
+  options = {
+    services.asterisk = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable the Asterisk PBX server.
+        '';
+      };
+
+      extraConfig = mkOption {
+        default = "";
+        type = types.lines;
+        example = ''
+          [options]
+          verbose=3
+          debug=3
+        '';
+        description = ''
+          Extra configuration options appended to the default
+          <literal>asterisk.conf</literal> file.
+        '';
+      };
+
+      confFiles = mkOption {
+        default = {};
+        type = types.attrsOf types.str;
+        example = literalExample
+          ''
+            {
+              "extensions.conf" = '''
+                [tests]
+                ; Dial 100 for "hello, world"
+                exten => 100,1,Answer()
+                same  =>     n,Wait(1)
+                same  =>     n,Playback(hello-world)
+                same  =>     n,Hangup()
+
+                [softphones]
+                include => tests
+
+                [unauthorized]
+              ''';
+              "sip.conf" = '''
+                [general]
+                allowguest=no              ; Require authentication
+                context=unauthorized       ; Send unauthorized users to /dev/null
+                srvlookup=no               ; Don't do DNS lookup
+                udpbindaddr=0.0.0.0        ; Listen on all interfaces
+                nat=force_rport,comedia    ; Assume device is behind NAT
+
+                [softphone](!)
+                type=friend                ; Match on username first, IP second
+                context=softphones         ; Send to softphones context in
+                                           ; extensions.conf file
+                host=dynamic               ; Device will register with asterisk
+                disallow=all               ; Manually specify codecs to allow
+                allow=g722
+                allow=ulaw
+                allow=alaw
+
+                [myphone](softphone)
+                secret=GhoshevFew          ; Change this password!
+              ''';
+              "logger.conf" = '''
+                [general]
+
+                [logfiles]
+                ; Add debug output to log
+                syslog.local0 => notice,warning,error,debug
+              ''';
+            }
+        '';
+        description = ''
+          Sets the content of config files (typically ending with
+          <literal>.conf</literal>) in the Asterisk configuration directory.
+
+          Note that if you want to change <literal>asterisk.conf</literal>, it
+          is preferable to use the <option>services.asterisk.extraConfig</option>
+          option over this option. If <literal>"asterisk.conf"</literal> is
+          specified with the <option>confFiles</option> option (not recommended),
+          you must be prepared to set your own <literal>astetcdir</literal>
+          path.
+
+          See
+          <link xlink:href="http://www.asterisk.org/community/documentation"/>
+          for more examples of what is possible here.
+        '';
+      };
+
+      extraArguments = mkOption {
+        default = [];
+        type = types.listOf types.str;
+        example =
+          [ "-vvvddd" "-e" "1024" ];
+        description = ''
+          Additional command line arguments to pass to Asterisk.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers = singleton
+    { name = asteriskUser;
+      uid = config.ids.uids.asterisk;
+      description = "Asterisk daemon user";
+      home = varlibdir;
+    };
+
+    systemd.services.asterisk = {
+      description = ''
+        Asterisk PBX server
+      '';
+
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = ''
+        # Copy skeleton directory tree to /var
+        for d in '${varlibdir}' '${spooldir}' '${logdir}'; do
+          # TODO: Make exceptions for /var directories that likely should be updated
+          if [ ! -e "$d" ]; then
+            cp --recursive ${pkgs.asterisk}/"$d" "$d"
+            chown --recursive ${asteriskUser} "$d"
+            find "$d" -type d | xargs chmod 0755
+          fi
+        done
+      '';
+
+      serviceConfig = {
+        ExecStart =
+          let
+            # FIXME: This doesn't account for arguments with spaces
+            argString = concatStringsSep " " cfg.extraArguments;
+          in
+          "${pkgs.asterisk}/bin/asterisk -U ${asteriskUser} -C ${asteriskEtc}/asterisk.conf ${argString} -F";
+        Type = "forking";
+        PIDFile = "/var/run/asterisk/asterisk.pid";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix
index 8b90f295ed4..d0123b79e3f 100644
--- a/nixos/modules/services/networking/btsync.nix
+++ b/nixos/modules/services/networking/btsync.nix
@@ -293,7 +293,7 @@ in
     systemd.services.btsync = with pkgs; {
       description = "Bittorrent Sync Service";
       wantedBy    = [ "multi-user.target" ];
-      after       = [ "network.target" ];
+      after       = [ "network.target" "local-fs.target" ];
       serviceConfig = {
         Restart   = "on-abort";
         UMask     = "0002";
@@ -305,7 +305,7 @@ in
 
     systemd.services."btsync@" = with pkgs; {
       description = "Bittorrent Sync Service for %i";
-      after       = [ "network.target" ];
+      after       = [ "network.target" "local-fs.target" ];
       serviceConfig = {
         Restart   = "on-abort";
         User      = "%i";
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index be0acb27324..f4063a3406f 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -44,6 +44,9 @@ let
       })
     else "";
 
+  parseModules = x:
+    x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; };
+
   # would be nice to  merge 'cfg' with a //,
   # but the json nesting is wacky.
   cjdrouteConf = builtins.toJSON ( {
@@ -53,8 +56,8 @@ let
     };
     authorizedPasswords = map (p: { password = p; }) cfg.authorizedPasswords;
     interfaces = {
-      ETHInterface = if (cfg.ETHInterface.bind != "") then [ cfg.ETHInterface ] else [ ];
-      UDPInterface = if (cfg.UDPInterface.bind != "") then [ cfg.UDPInterface ] else [ ];
+      ETHInterface = if (cfg.ETHInterface.bind != "") then [ (parseModules cfg.ETHInterface) ] else [ ];
+      UDPInterface = if (cfg.UDPInterface.bind != "") then [ (parseModules cfg.UDPInterface) ] else [ ];
     };
 
     privateKey = "@CJDNS_PRIVATE_KEY@";
@@ -151,12 +154,14 @@ in
 
       ETHInterface = {
         bind = mkOption {
-        default = "";
-        example = "eth0";
-        description = ''
-          Bind to this device for native ethernet operation.
-        '';
-      };
+          default = "";
+          example = "eth0";
+          description =
+            ''
+              Bind to this device for native ethernet operation.
+              <literal>all</literal> is a pseudo-name which will try to connect to all devices.
+            '';
+        };
 
         beacon = mkOption {
           type = types.int;
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index f01deb6ee7c..92f6396b358 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -127,8 +127,8 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
       serviceConfig = {
-        # This may change back to forking if too many problems occur:
-        type = "simple";
+        # Uncomment this if too many problems occur:
+        # Type = "forking";
         User = ddclientUser;
         Group = "nogroup"; #TODO get this to work
         PermissionsStartOnly = "true";
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index 7ddabf73106..18086154b6b 100644
--- a/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixos/modules/services/networking/dnsmasq.nix
@@ -28,6 +28,7 @@ in
     services.dnsmasq = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = ''
           Whether to run dnsmasq.
@@ -35,14 +36,16 @@ in
       };
 
       resolveLocalQueries = mkOption {
+        type = types.bool;
         default = true;
         description = ''
           Whether dnsmasq should resolve local queries (i.e. add 127.0.0.1 to
-          /etc/resolv.conf)
+          /etc/resolv.conf).
         '';
       };
 
       servers = mkOption {
+        type = types.listOf types.string;
         default = [];
         example = [ "8.8.8.8" "8.8.4.4" ];
         description = ''
@@ -51,11 +54,11 @@ in
       };
 
       extraConfig = mkOption {
-        type = types.string;
+        type = types.lines;
         default = "";
         description = ''
           Extra configuration directives that should be added to
-          <literal>dnsmasq.conf</literal>
+          <literal>dnsmasq.conf</literal>.
         '';
       };
 
@@ -81,7 +84,7 @@ in
       };
 
     systemd.services.dnsmasq = {
-        description = "dnsmasq daemon";
+        description = "Dnsmasq Daemon";
         after = [ "network.target" "systemd-resolved.service" ];
         wantedBy = [ "multi-user.target" ];
         path = [ dnsmasq ];
diff --git a/nixos/modules/services/networking/i2p.nix b/nixos/modules/services/networking/i2p.nix
new file mode 100644
index 00000000000..bad22c79138
--- /dev/null
+++ b/nixos/modules/services/networking/i2p.nix
@@ -0,0 +1,42 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.i2p;
+  homeDir = "/var/lib/i2p";
+in {
+  ###### interface
+  options.services.i2p = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enables i2p as a running service upon activation.
+        '';
+      };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    users.extraUsers.i2p = {
+      group = "i2p";
+      description = "i2p User";
+      home = homeDir;
+      createHome = true;
+      uid = config.ids.uids.i2p;
+    };
+    users.extraGroups.i2p.gid = config.ids.gids.i2p;
+    systemd.services.i2p = {
+      description = "I2P router with administration interface for hidden services";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        User = "i2p";
+        WorkingDirectory = homeDir;
+        Restart = "on-abort";
+        ExecStart = "${pkgs.i2p}/bin/i2prouter-plain";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/lambdabot.nix b/nixos/modules/services/networking/lambdabot.nix
new file mode 100644
index 00000000000..4ef7c7c9ab6
--- /dev/null
+++ b/nixos/modules/services/networking/lambdabot.nix
@@ -0,0 +1,81 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.lambdabot;
+
+  rc = builtins.toFile "script.rc" cfg.script;
+
+in
+
+{
+
+  ### configuration
+
+  options = {
+
+    services.lambdabot = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable the Lambdabot IRC bot";
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.lambdabot;
+        description = "Used lambdabot package";
+      };
+
+      script = mkOption {
+        type = types.str;
+        default = "";
+        description = "Lambdabot script";
+      };
+
+    };
+
+  };
+
+  ### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.lambdabot = {
+      description = "Lambdabot daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      # Workaround for https://github.com/lambdabot/lambdabot/issues/117
+      script = ''
+        mkdir -p ~/.lambdabot
+        cd ~/.lambdabot
+        mkfifo /run/lambdabot/offline
+        (
+          echo 'rc ${rc}'
+          while true; do
+            cat /run/lambdabot/offline
+          done
+        ) | ${cfg.package}/bin/lambdabot
+      '';
+      serviceConfig = {
+        User = "lambdabot";
+        RuntimeDirectory = [ "lambdabot" ];
+      };
+    };
+
+    users.extraUsers.lambdabot = {
+      group = "lambdabot";
+      description = "Lambdabot daemon user";
+      home = "/var/lib/lambdabot";
+      createHome = true;
+      uid = config.ids.uids.lambdabot;
+    };
+
+    users.extraGroups.lambdabot.gid = config.ids.gids.lambdabot;
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index f00c5d1f701..60f380f024b 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -98,13 +98,23 @@ in {
         '';
       };
 
+      # Ugly hack for using the correct gnome3 packageSet
+      basePackages = mkOption {
+        type = types.attrsOf types.path;
+        default = { inherit networkmanager modemmanager wpa_supplicant
+                            networkmanager_openvpn networkmanager_vpnc
+                            networkmanager_openconnect
+                            networkmanager_pptp networkmanager_l2tp; };
+        internal = true;
+      };
+
       packages = mkOption {
         type = types.listOf types.path;
         default = [ ];
         description = ''
           Extra packages that provide NetworkManager plugins.
         '';
-        apply = list: [ networkmanager modemmanager wpa_supplicant ] ++ list;
+        apply = list: (attrValues cfg.basePackages) ++ list;
       };
 
       appendNameservers = mkOption {
@@ -164,7 +174,7 @@ in {
 
     boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections.
 
-    environment.etc = [
+    environment.etc = with cfg.basePackages; [
       { source = ipUpScript;
         target = "NetworkManager/dispatcher.d/01nixos-ip-up";
       }
@@ -195,14 +205,7 @@ in {
         target = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}";
       }) cfg.dispatcherScripts;
 
-    environment.systemPackages = cfg.packages ++ [
-        networkmanager_openvpn
-        networkmanager_vpnc
-        networkmanager_openconnect
-        networkmanager_pptp
-        networkmanager_l2tp
-        modemmanager
-        ];
+    environment.systemPackages = cfg.packages;
 
     users.extraGroups = singleton {
       name = "networkmanager";
@@ -238,15 +241,7 @@ in {
 
     security.polkit.extraConfig = polkitConf;
 
-    # openvpn plugin has only dbus interface
-    services.dbus.packages = cfg.packages ++ [
-        networkmanager_openvpn
-        networkmanager_vpnc
-        networkmanager_openconnect
-        networkmanager_pptp
-        networkmanager_l2tp
-        modemmanager
-        ];
+    services.dbus.packages = cfg.packages;
 
     services.udev.packages = cfg.packages;
   };
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index b2740bd33b7..c25532511a0 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -281,10 +281,8 @@ in
 
   config = mkIf cfg.enable {
 
-    users.extraUsers = singleton
-      { name = "sshd";
-        uid = config.ids.uids.sshd;
-        description = "SSH privilege separation user";
+    users.extraUsers.sshd =
+      { description = "SSH privilege separation user";
         home = "/var/empty";
       };
 
@@ -379,7 +377,7 @@ in
           Port ${toString port}
         '') cfg.ports}
 
-        ${concatMapStrings ({ port, addr }: ''
+        ${concatMapStrings ({ port, addr, ... }: ''
           ListenAddress ${addr}${if port != null then ":" + toString port else ""}
         '') cfg.listenAddresses}
 
@@ -418,7 +416,7 @@ in
                     (data.publicKey != null && data.publicKeyFile == null);
         message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
       })
-      ++ flip map cfg.listenAddresses ({ addr, port }: {
+      ++ flip map cfg.listenAddresses ({ addr, port, ... }: {
         assertion = addr != null;
         message = "addr must be specified in each listenAddresses entry";
       });
diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix
index e251571dca3..c87fe914df8 100644
--- a/nixos/modules/services/networking/sslh.nix
+++ b/nixos/modules/services/networking/sslh.nix
@@ -81,7 +81,7 @@ in
       description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      serviceConfig.ExecStart = "${pkgs.sslh}/bin/sslh -F ${configFile}";
+      serviceConfig.ExecStart = "${pkgs.sslh}/bin/sslh -F${configFile}";
       serviceConfig.KillMode = "process";
       serviceConfig.PIDFile = "${cfg.pidfile}";
     };
diff --git a/nixos/modules/services/security/hologram.nix b/nixos/modules/services/security/hologram.nix
new file mode 100644
index 00000000000..f9abf38942f
--- /dev/null
+++ b/nixos/modules/services/security/hologram.nix
@@ -0,0 +1,102 @@
+{pkgs, config, lib, ...}:
+
+with lib;
+
+let
+  cfg = config.services.hologram-server;
+
+  cfgFile = pkgs.writeText "hologram-server.json" (builtins.toJSON {
+    ldap = {
+      host = cfg.ldapHost;
+      bind = {
+        dn       = cfg.ldapBindDN;
+        password = cfg.ldapBindPassword;
+      };
+      insecureldap = cfg.ldapInsecure;
+      userattr     = cfg.ldapUserAttr;
+      baseDN       = cfg.ldapBaseDN;
+    };
+    aws = {
+      account     = cfg.awsAccount;
+      defaultrole = cfg.awsDefaultRole;
+    };
+    stats  = cfg.statsAddress;
+    listen = cfg.listenAddress;
+  });
+in {
+  options = {
+    services.hologram-server = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the Hologram server for AWS instance credentials";
+      };
+
+      listenAddress = mkOption {
+        type        = types.str;
+        default     = "0.0.0.0:3100";
+        description = "Address and port to listen on";
+      };
+
+      ldapHost = mkOption {
+        type        = types.str;
+        description = "Address of the LDAP server to use";
+      };
+
+      ldapInsecure = mkOption {
+        type        = types.bool;
+        default     = false;
+        description = "Whether to connect to LDAP over SSL or not";
+      };
+
+      ldapUserAttr = mkOption {
+        type        = types.str;
+        default     = "cn";
+        description = "The LDAP attribute for usernames";
+      };
+
+      ldapBaseDN = mkOption {
+        type        = types.str;
+        description = "The base DN for your Hologram users";
+      };
+
+      ldapBindDN = mkOption {
+        type        = types.str;
+        description = "DN of account to use to query the LDAP server";
+      };
+
+      ldapBindPassword = mkOption {
+        type        = types.str;
+        description = "Password of account to use to query the LDAP server";
+      };
+
+      awsAccount = mkOption {
+        type        = types.str;
+        description = "AWS account number";
+      };
+
+      awsDefaultRole = mkOption {
+        type        = types.str;
+        description = "AWS default role";
+      };
+
+      statsAddress = mkOption {
+        type        = types.str;
+        default     = "";
+        description = "Address of statsd server";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.hologram-server = {
+      description = "Provide EC2 instance credentials to machines outside of EC2";
+      after       = [ "network.target" ];
+      wantedBy    = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.goPackages.hologram}/bin/hologram-server --debug --conf ${cfgFile}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index d40f7d6d05d..853b458cf58 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -133,6 +133,8 @@ in
     # Don't restart dbus-daemon. Bad things tend to happen if we do.
     systemd.services.dbus.reloadIfChanged = true;
 
+    systemd.services.dbus.restartTriggers = [ configDir ];
+
     environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ];
 
   };
diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix
index 0879d9b85bd..caedc2e4217 100644
--- a/nixos/modules/services/system/nscd.nix
+++ b/nixos/modules/services/system/nscd.nix
@@ -42,11 +42,7 @@ in
 
   config = mkIf cfg.enable {
 
-    users.extraUsers = singleton
-      { name = "nscd";
-        uid = config.ids.uids.nscd;
-        description = "Name service cache daemon user";
-      };
+    users.extraUsers.nscd.description = "Name service cache daemon user";
 
     systemd.services.nscd =
       { description = "Name Service Cache Daemon";
diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix
index 3958be33df2..85ee23c1a3d 100644
--- a/nixos/modules/services/ttys/agetty.nix
+++ b/nixos/modules/services/ttys/agetty.nix
@@ -10,6 +10,15 @@ with lib;
 
     services.mingetty = {
 
+      autologinUser = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          Username of the account that will be automatically logged in at the console.
+          If unspecified, a login prompt is shown as usual.
+        '';
+      };
+
       greetingLine = mkOption {
         type = types.str;
         default = ''<<< Welcome to NixOS ${config.system.nixosVersion} (\m) - \l >>>'';
@@ -46,28 +55,30 @@ with lib;
 
   ###### implementation
 
-  config = {
-
+  config = let
+    autologinArg = optionalString (config.services.mingetty.autologinUser != null) "--autologin ${config.services.mingetty.autologinUser}";
+    gettyCmd = extraArgs: "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login ${autologinArg} ${extraArgs}";
+  in {
     systemd.services."getty@" =
-      { serviceConfig.ExecStart = "@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login --keep-baud %I 115200,38400,9600 $TERM";
+      { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud %I 115200,38400,9600 $TERM";
         restartIfChanged = false;
       };
 
     systemd.services."serial-getty@" =
       { serviceConfig.ExecStart =
           let speeds = concatStringsSep "," (map toString config.services.mingetty.serialSpeed);
-          in "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login %I ${speeds} $TERM";
+          in gettyCmd "%I ${speeds} $TERM";
         restartIfChanged = false;
       };
 
     systemd.services."container-getty@" =
       { unitConfig.ConditionPathExists = "/dev/pts/%I"; # Work around being respawned when "machinectl login" exits.
-        serviceConfig.ExecStart = "@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login --keep-baud pts/%I 115200,38400,9600 $TERM";
+        serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM";
         restartIfChanged = false;
       };
 
     systemd.services."console-getty" =
-      { serviceConfig.ExecStart = "@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login --keep-baud console 115200,38400,9600 $TERM";
+      { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM";
         serviceConfig.Restart = "always";
         restartIfChanged = false;
 	enable = mkDefault config.boot.isContainer;
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 2b5cba68d45..2885fd39652 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -231,6 +231,9 @@ let
     ${if cfg.sslServerCert != null then ''
       SSLCertificateFile ${cfg.sslServerCert}
       SSLCertificateKeyFile ${cfg.sslServerKey}
+      ${if cfg.sslServerChain != null then ''
+        SSLCertificateChainFile ${cfg.sslServerChain}
+      '' else ""}
     '' else ""}
 
     ${if cfg.enableSSL then ''
diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
index c0ed2041639..52d8c89baff 100644
--- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
@@ -83,11 +83,11 @@ let
 
   # Unpack Mediawiki and put the config file in its root directory.
   mediawikiRoot = pkgs.stdenv.mkDerivation rec {
-    name= "mediawiki-1.23.3";
+    name= "mediawiki-1.23.9";
 
     src = pkgs.fetchurl {
       url = "http://download.wikimedia.org/mediawiki/1.23/${name}.tar.gz";
-      sha256 = "0l6798jwjwk2khfnm84mgc65ij53a8pnv30wdnn15ys4ivia4bpf";
+      sha256 = "1l7k4g0pgz92yvrfr52w26x740s4362v0gc95pk0i30vn2sp5bql";
     };
 
     skins = config.skins;
@@ -142,6 +142,7 @@ in
         RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
         RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
         ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedDirs}
+        ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedFiles}
         RewriteRule ${if config.enableUploads
           then "!^/images"
           else "^.*\$"
diff --git a/nixos/modules/services/web-servers/apache-httpd/moodle.nix b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
new file mode 100644
index 00000000000..84c8281ecd8
--- /dev/null
+++ b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
@@ -0,0 +1,193 @@
+{ config, lib, pkgs, serverInfo, php, ... }:
+
+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
+  '';
+
+  moodleConfig = pkgs.writeText "config.php"
+    ''
+      <?php
+      unset($CFG);
+      global $CFG;
+      $CFG = new stdClass();
+      $CFG->dbtype    = '${config.dbType}';
+      $CFG->dblibrary = 'native';
+      $CFG->dbhost    = '${config.dbHost}';
+      $CFG->dbname    = '${config.dbName}';
+      $CFG->dbuser    = '${config.dbUser}';
+      $CFG->dbpass    = '${config.dbPassword}';
+      $CFG->prefix    = '${config.dbPrefix}';
+      $CFG->dboptions = array(
+          'dbpersist' => false,
+          'dbsocket'  => false,
+          'dbport'    => "${config.dbPort}",
+      );
+      $CFG->wwwroot   = '${config.wwwRoot}';
+      $CFG->dataroot  = '${config.dataRoot}';
+      $CFG->directorypermissions = 02777;
+      $CFG->admin = 'admin';
+      ${optionalString (config.debug.noEmailEver == true) ''
+        $CFG->noemailever = true;
+      ''}
+
+      ${config.extraConfig}
+      require_once(dirname(__FILE__) . '/lib/setup.php'); // Do not edit
+    '';
+  # Unpack Moodle and put the config file in its root directory.
+  moodleRoot = pkgs.stdenv.mkDerivation rec {
+    name= "moodle-2.8.5";
+
+    src = pkgs.fetchurl {
+      url = "https://download.moodle.org/stable28/${name}.tgz";
+      sha256 = "1a159a193010cddedce10ee009184502e6f732e4d7c85167d8597fe5dff9e190";
+    };
+
+    buildPhase =
+      ''
+      ''; 
+
+    installPhase =
+      ''
+        mkdir -p $out
+        cp -r * $out
+        cp ${moodleConfig} $out/config.php
+      '';
+  };
+
+in
+
+{
+
+  extraConfig =
+  ''
+    # this should be config.urlPrefix instead of /
+    Alias / ${moodleRoot}/
+    <Directory ${moodleRoot}>
+      DirectoryIndex index.php
+    </Directory>
+  '';
+
+  documentRoot = moodleRoot; # TODO: fix this, should be config.urlPrefix
+
+  enablePHP = true;
+
+  options = {
+
+    id = mkOption {
+      default = "main";
+      description = ''
+        A unique identifier necessary to keep multiple Moodle server
+        instances on the same machine apart.
+      '';
+    };
+
+    dbType = mkOption {
+      default = "postgres";
+      example = "mysql";
+      description = "Database type.";
+    };
+
+    dbName = mkOption {
+      default = "moodle";
+      description = "Name of the database that holds the Moodle data.";
+    };
+
+    dbHost = mkOption {
+      default = "localhost";
+      example = "10.0.2.2";
+      description = ''
+        The location of the database server.
+      '';
+    };
+
+    dbPort = mkOption {
+      default = ""; # use the default port
+      example = "12345";
+      description = ''
+        The port that is used to connect to the database server.
+      '';
+    };
+
+    dbUser = mkOption {
+      default = "moodle";
+      description = "The user name for accessing the database.";
+    };
+
+    dbPassword = mkOption {
+      default = "";
+      example = "password";
+      description = ''
+        The password of the database user.  Warning: this is stored in
+        cleartext in the Nix store!
+      '';
+    };
+    
+    dbPrefix = mkOption {
+      default = "mdl_";
+      example = "my_other_mdl_";
+      description = ''
+        A prefix for each table, if multiple moodles should run in a single database.
+      '';
+    };
+
+    wwwRoot = mkOption {
+      type = types.string;
+      example = "http://my.machine.com/my-moodle";
+      description = ''
+        The full web address where moodle has been installed.
+      '';
+    };
+
+    dataRoot = mkOption {
+      default = "/var/lib/moodledata";
+      example = "/var/lib/moodledata";
+      description = ''
+        The data directory for moodle. Needs to be writable!
+      '';
+      type = types.path;
+      };
+
+    
+    extraConfig = mkOption {
+      default = "";
+      example =
+        ''
+        '';
+      description = ''
+        Any additional text to be appended to Moodle's
+        configuration file.  This is a PHP script.
+      '';
+    };
+
+    debug = {
+      noEmailEver = mkOption {
+        default = false;
+	example = "true";
+	description = ''
+	  Set this to true to prevent Moodle from ever sending any email.
+	'';
+	};
+    };
+  };
+
+  startupScript = pkgs.writeScript "moodle_startup.sh" ''
+  echo "Checking for existence of ${config.dataRoot}"
+  if [ ! -e "${config.dataRoot}" ]
+  then
+    mkdir -p "${config.dataRoot}"
+    chown ${serverInfo.serverConfig.user}.${serverInfo.serverConfig.group} "${config.dataRoot}"
+  fi
+  '';
+
+}
diff --git a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix b/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix
index 76f55a63e32..5abcc5e7490 100644
--- a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix
@@ -56,6 +56,13 @@ with lib;
     description = "Path to server SSL certificate key.";
   };
 
+  sslServerChain = mkOption {
+    type = types.nullOr types.path;
+    default = null;
+    example = "/var/ca.pem";
+    description = "Path to server SSL chain file.";
+  };
+
   adminAddr = mkOption ({
     type = types.nullOr types.str;
     example = "admin@example.org";
@@ -90,7 +97,7 @@ with lib;
     default = [];
     example = [
       { urlPath = "/foo/bar.png";
-        dir = "/home/eelco/some-file.png";
+        files = "/home/eelco/some-file.png";
       }
     ];
     description = ''
diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
new file mode 100644
index 00000000000..01b6cfc62af
--- /dev/null
+++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
@@ -0,0 +1,209 @@
+{ config, lib, pkgs, serverInfo, php, ... }:
+
+with lib;
+
+let
+  # https://wordpress.org/plugins/postgresql-for-wordpress/
+  # Wordpress plugin 'postgresql-for-wordpress' installation example
+  postgresqlForWordpressPlugin = pkgs.stdenv.mkDerivation {
+    name = "postgresql-for-wordpress-plugin";
+    # Download the theme from the wordpress site
+    src = pkgs.fetchurl {
+      url = https://downloads.wordpress.org/plugin/postgresql-for-wordpress.1.3.1.zip;
+      sha256 = "f11a5d76af884c7bec2bc653ed5bd29d3ede9a8657bd67ab7824e329e5d809e8";
+    };
+    # We need unzip to build this package
+    buildInputs = [ pkgs.unzip ];
+    # Installing simply means copying all files to the output directory
+    installPhase = "mkdir -p $out; cp -R * $out/";
+  };
+
+  # Our bare-bones wp-config.php file using the above settings
+  wordpressConfig = pkgs.writeText "wp-config.php" ''
+    <?php
+    define('DB_NAME',     '${config.dbName}');
+    define('DB_USER',     '${config.dbUser}');
+    define('DB_PASSWORD', '${config.dbPassword}');
+    define('DB_HOST',     '${config.dbHost}');
+    define('DB_CHARSET',  'utf8');
+    $table_prefix  = '${config.tablePrefix}';
+    if ( !defined('ABSPATH') )
+    	define('ABSPATH', dirname(__FILE__) . '/');
+    require_once(ABSPATH . 'wp-settings.php');
+    ${config.extraConfig}
+  '';
+
+  # .htaccess to support pretty URLs
+  htaccess = pkgs.writeText "htaccess" ''
+    <IfModule mod_rewrite.c>
+    RewriteEngine On
+    RewriteBase /
+    RewriteCond %{REQUEST_FILENAME} !-f
+    RewriteCond %{REQUEST_FILENAME} !-d
+    RewriteRule . /index.php [L]
+    </IfModule>
+  '';
+
+  # The wordpress package itself
+  wordpressRoot = pkgs.stdenv.mkDerivation rec {
+    name = "wordpress";
+    # Fetch directly from the wordpress site, want to upgrade?
+    # Just change the version URL and update the hash
+    src = pkgs.fetchurl {
+      url = http://wordpress.org/wordpress-4.1.1.tar.gz;
+      sha256 = "1s9y0i9ms3m6dswb9gqrr95plnx6imahc07fyhvrp5g35f6c12k1";
+    };
+    installPhase = ''
+      mkdir -p $out
+      # Copy all the wordpress files we downloaded
+      cp -R * $out/
+      # We'll symlink the wordpress config
+      ln -s ${wordpressConfig} $out/wp-config.php
+      # As well as our custom .htaccess
+      ln -s ${htaccess} $out/.htaccess
+      # And the uploads directory
+      ln -s ${config.wordpressUploads} $out/wp-content/uploads
+      # And the theme(s)
+      ${concatMapStrings (theme: "ln -s ${theme} $out/wp-content/themes/${theme.name}\n") config.themes}
+      # And the plugin(s)
+      # remove bundled plugin(s) coming with wordpress
+      rm -Rf $out/wp-content/plugins/akismet
+      # install plugins
+      ${concatMapStrings (plugin: "ln -s ${plugin} $out/wp-content/plugins/${plugin.name}\n") (config.plugins ++ [ postgresqlForWordpressPlugin]) }
+    '';
+  };
+
+in
+
+{
+
+  # And some httpd extraConfig to make things work nicely
+  extraConfig = ''
+    <Directory ${wordpressRoot}>
+      DirectoryIndex index.php
+      Allow from *
+      Options FollowSymLinks
+      AllowOverride All
+    </Directory>
+  '';
+
+  enablePHP = true;
+
+  options = {
+    dbHost = mkOption {
+      default = "localhost";
+      description = "The location of the database server.";  
+      example = "localhost";
+    };
+    dbName = mkOption {
+      default = "wordpress";
+      description = "Name of the database that holds the Wordpress data.";
+      example = "localhost";
+    };
+    dbUser = mkOption {
+      default = "wordpress";
+      description = "The dbUser, read the username, for the database.";
+      example = "wordpress";
+    };
+    dbPassword = mkOption {
+      default = "wordpress";
+      description = "The password to the respective dbUser.";
+      example = "wordpress";
+    };
+    tablePrefix = mkOption {
+      default = "wp_";
+      description = ''
+        The $table_prefix is the value placed in the front of your database tables. Change the value if you want to use something other than wp_ for your database prefix. Typically this is changed if you are installing multiple WordPress blogs in the same database. See <link xlink:href='http://codex.wordpress.org/Editing_wp-config.php#table_prefix'/>.
+      '';
+    };
+    wordpressUploads = mkOption {
+    default = "/data/uploads";
+      description = ''
+        This directory is used for uploads of pictures and must be accessible (read: owned) by the httpd running user. The directory passed here is automatically created and permissions are given to the httpd running user.
+      '';
+    };
+    plugins = mkOption {
+      default = [];
+      type = types.listOf types.path;
+      description =
+        ''
+          List of path(s) to respective plugin(s) which are symlinked from the 'plugins' directory. Note: These plugins need to be packaged before use.
+        '';
+      example = ''
+        # Wordpress plugin 'akismet' installation example
+        akismetPlugin = pkgs.stdenv.mkDerivation {
+          name = "akismet-plugin";
+          # Download the theme from the wordpress site
+          src = pkgs.fetchurl {
+            url = https://downloads.wordpress.org/plugin/akismet.3.1.zip;
+            sha256 = "1i4k7qyzna08822ncaz5l00wwxkwcdg4j9h3z2g0ay23q640pclg";
+          };
+          # We need unzip to build this package
+          buildInputs = [ pkgs.unzip ];
+          # Installing simply means copying all files to the output directory
+          installPhase = "mkdir -p $out; cp -R * $out/";
+        };
+
+        And then pass this theme to the themes list like this:
+          plugins = [ akismetPlugin ];
+      '';
+    };
+    themes = mkOption {
+      default = [];
+      type = types.listOf types.path;
+      description =
+        ''
+          List of path(s) to respective theme(s) which are symlinked from the 'theme' directory. Note: These themes need to be packaged before use.
+        '';
+      example = ''
+        # For shits and giggles, let's package the responsive theme
+        responsiveTheme = pkgs.stdenv.mkDerivation {
+          name = "responsive-theme";
+          # Download the theme from the wordpress site
+          src = pkgs.fetchurl {
+            url = http://wordpress.org/themes/download/responsive.1.9.7.6.zip;
+            sha256 = "06i26xlc5kdnx903b1gfvnysx49fb4kh4pixn89qii3a30fgd8r8";
+          };
+          # We need unzip to build this package
+          buildInputs = [ pkgs.unzip ];
+          # Installing simply means copying all files to the output directory
+          installPhase = "mkdir -p $out; cp -R * $out/";
+        };
+
+        And then pass this theme to the themes list like this:
+          themes = [ responsiveTheme ];
+      '';
+    };
+    extraConfig = mkOption {
+      default = "";
+      example =
+        ''
+          define( 'AUTOSAVE_INTERVAL', 60 ); // Seconds
+        '';
+      description = ''
+        Any additional text to be appended to Wordpress's wp-config.php
+        configuration file.  This is a PHP script.  For configuration
+        settings, see <link xlink:href='http://codex.wordpress.org/Editing_wp-config.php'/>.
+      '';
+    };
+  }; 
+
+  documentRoot = wordpressRoot;
+
+  startupScript = pkgs.writeScript "init-wordpress.sh" ''
+    #!/bin/sh
+    mkdir -p ${config.wordpressUploads}
+    chown ${serverInfo.serverConfig.user} ${config.wordpressUploads}
+
+    # we should use systemd dependencies here
+    #waitForUnit("network-interfaces.target");
+    if [ ! -d ${serverInfo.fullConfig.services.mysql.dataDir}/${config.dbName} ]; then
+      # Wait until MySQL is up
+      while [ ! -e /var/run/mysql/mysqld.pid ]; do
+        sleep 1
+      done
+      ${pkgs.mysql}/bin/mysql -e 'CREATE DATABASE ${config.dbName};'
+      ${pkgs.mysql}/bin/mysql -e 'GRANT ALL ON ${config.dbName}.* TO ${config.dbUser}@localhost IDENTIFIED BY "${config.dbPassword}";'
+    fi
+  '';
+}
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 0f21ef01263..fe50c182bfe 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -102,6 +102,7 @@ in
         '';
       serviceConfig = {
         ExecStart = "${nginx}/bin/nginx -c ${configFile} -p ${cfg.stateDir}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         Restart = "on-failure";
         RestartSec = "10s";
         StartLimitInterval = "1min";
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 6398a15bfcc..d53f119c955 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -21,7 +21,7 @@ let
     destination = "/share/applications/mimeapps.list";
     text = ''
       [Default Applications]
-      inode/directory=nautilus.desktop
+      inode/directory=nautilus.desktop;org.gnome.Nautilus.desktop
     '';
   };
 
@@ -80,6 +80,7 @@ in {
     services.telepathy.enable = mkDefault true;
     networking.networkmanager.enable = mkDefault true;
     services.upower.enable = config.powerManagement.enable;
+    hardware.bluetooth.enable = mkDefault true;
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ];
 
@@ -108,7 +109,7 @@ in {
           # Override default mimeapps
           export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${mimeAppsList}/share
 
-          # Let gnome-control-center find gnome-shell search providers
+          # Let gnome-control-center find gnome-shell search providers. GNOME 3.12 compatibility.
           export GNOME_SEARCH_PROVIDERS_DIR=${config.system.path}/share/gnome-shell/search-providers/
 
           # Let nautilus find extensions
@@ -120,6 +121,9 @@ in {
           # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
           ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
 
+          # Find the mouse
+          export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons
+
           ${gnome3.gnome_session}/bin/gnome-session&
           waitPID=$!
         '';
@@ -128,52 +132,15 @@ in {
     environment.variables.GIO_EXTRA_MODULES = [ "${gnome3.dconf}/lib/gio/modules"
                                                 "${gnome3.glib_networking}/lib/gio/modules"
                                                 "${gnome3.gvfs}/lib/gio/modules" ];
-    environment.systemPackages =
-      [ pkgs.desktop_file_utils
-        gnome3.glib_networking
-        gnome3.gtk3 # for gtk-update-icon-cache
-        pkgs.ibus
-        pkgs.shared_mime_info # for update-mime-database
-        gnome3.gvfs
-        gnome3.dconf
-        gnome3.gnome-backgrounds
-        gnome3.gnome_control_center
-        gnome3.gnome_icon_theme
-        gnome3.gnome-menus
-        gnome3.gnome_settings_daemon
-        gnome3.gnome_shell
-        gnome3.gnome_themes_standard
-      ] ++ cfg.sessionPath ++ (removePackagesByName [
-        gnome3.baobab
-        gnome3.empathy
-        gnome3.eog
-        gnome3.epiphany
-        gnome3.evince
-        gnome3.gucharmap
-        gnome3.nautilus
-        gnome3.totem
-        gnome3.vino
-        gnome3.yelp
-        gnome3.gnome-calculator
-        gnome3.gnome-contacts
-        gnome3.gnome-font-viewer
-        gnome3.gnome-screenshot
-        gnome3.gnome-shell-extensions
-        gnome3.gnome-system-log
-        gnome3.gnome-system-monitor
-        gnome3.gnome_terminal
-        gnome3.gnome-user-docs
-
-        gnome3.bijiben
-        gnome3.evolution
-        gnome3.file-roller
-        gnome3.gedit
-        gnome3.gnome-clocks
-        gnome3.gnome-music
-        gnome3.gnome-tweak-tool
-        gnome3.gnome-photos
-        gnome3.nautilus-sendto
-      ] config.environment.gnome3.excludePackages);
+    environment.systemPackages = gnome3.corePackages ++ cfg.sessionPath
+      ++ (removePackagesByName gnome3.optionalPackages config.environment.gnome3.excludePackages);
+
+    # Use the correct gnome3 packageSet
+    networking.networkmanager.basePackages =
+      { inherit (pkgs) networkmanager modemmanager wpa_supplicant;
+        inherit (gnome3) networkmanager_openvpn networkmanager_vpnc
+                         networkmanager_openconnect networkmanager_pptp
+                         networkmanager_l2tp; };
 
     # Needed for themes and backgrounds
     environment.pathsToLink = [ "/share" ];
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index a7ebafa28b3..6c3c5273086 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -58,14 +58,14 @@ in
           # Find the mouse
           XCURSOR_PATH = "~/.icons:${config.system.path}/share/icons";
         };
-        execCmd = "exec ${gdm}/sbin/gdm";
+        execCmd = "exec ${gdm}/bin/gdm";
       };
 
     # Because sd_login_monitor_new requires /run/systemd/machines
     systemd.services.display-manager.wants = [ "systemd-machined.service" ];
     systemd.services.display-manager.after = [ "systemd-machined.service" ];
 
-    systemd.services.display-manager.path = [ gnome3.gnome_shell gnome3.caribou ];
+    systemd.services.display-manager.path = [ gnome3.gnome_shell gnome3.caribou pkgs.xlibs.xhost pkgs.dbus_tools ];
 
     services.dbus.packages = [ gdm ];
 
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 6a7b810261d..4aeaed8cd32 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -19,7 +19,7 @@ let
     '';
 
   theme = pkgs.gnome3.gnome_themes_standard;
-  icons = pkgs.gnome3.gnome_icon_theme;
+  icons = pkgs.gnome3.defaultIconTheme;
 
   # The default greeter provided with this expression is the GTK greeter.
   # Again, we need a few things in the environment for the greeter to run with
@@ -69,6 +69,7 @@ let
       xserver-command = ${xserverWrapper}
       session-wrapper = ${dmcfg.session.script}
       greeter-session = ${cfg.greeter.name}
+      ${cfg.extraSeatDefaults}
     '';
 
   gtkGreeterConf = writeText "lightdm-gtk-greeter.conf"
@@ -109,6 +110,15 @@ in
         '';
       };
 
+      extraSeatDefaults = mkOption {
+        type = types.lines;
+        default = "";
+        example = ''
+          greeter-show-manual-login=true
+        '';
+        description = "Extra lines to append to SeatDefaults section.";
+      };
+
     };
   };
 
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 64e0d4d8050..5198864ef6e 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -41,16 +41,24 @@ let
     };
   in imap mkHead cfg.xrandrHeads;
 
-  xrandrDeviceSection = flip concatMapStrings xrandrHeads (h: ''
-    Option "monitor-${h.output}" "${h.name}"
-  '');
+  xrandrDeviceSection = let
+    monitors = flip map xrandrHeads (h: ''
+      Option "monitor-${h.output}" "${h.name}"
+    '');
+    # First option is indented through the space in the config but any
+    # subsequent options aren't so we need to apply indentation to
+    # them here
+    monitorsIndented = if length monitors > 1
+      then singleton (head monitors) ++ map (m: "  " + m) (tail monitors)
+      else monitors;
+  in concatStrings monitorsIndented;
 
   # Here we chain every monitor from the left to right, so we have:
   # m4 right of m3 right of m2 right of m1   .----.----.----.----.
   # Which will end up in reverse ----------> | m1 | m2 | m3 | m4 |
   #                                          `----^----^----^----'
   xrandrMonitorSections = let
-    mkMonitor = previous: current: previous ++ singleton {
+    mkMonitor = previous: current: singleton {
       inherit (current) name;
       value = ''
         Section "Monitor"
@@ -60,8 +68,8 @@ let
           ''}
         EndSection
       '';
-    };
-    monitors = foldl mkMonitor [] xrandrHeads;
+    } ++ previous;
+    monitors = reverseList (foldl mkMonitor [] xrandrHeads);
   in concatMapStrings (getAttr "value") monitors;
 
   configFile = pkgs.stdenv.mkDerivation {
@@ -147,6 +155,19 @@ in
         '';
       };
 
+      inputClassSections = mkOption {
+        type = types.listOf types.lines;
+        default = [];
+        example = [ ''
+           Identifier      "Trackpoint Wheel Emulation"
+           MatchProduct    "ThinkPad USB Keyboard with TrackPoint"
+           Option          "EmulateWheel"          "true
+           Option          "EmulateWheelButton"    "2"
+           Option          "Emulate3Buttons"       "false"
+          '' ];
+        description = "Content of additional InputClass sections of the X server configuration file.";
+      };
+
       modules = mkOption {
         type = types.listOf types.path;
         default = [];
@@ -522,6 +543,14 @@ in
           Option "XkbVariant" "${cfg.xkbVariant}"
         EndSection
 
+        # Additional "InputClass" sections
+        ${flip concatMapStrings cfg.inputClassSections (inputClassSection: ''
+        Section "InputClass"
+          ${inputClassSection}
+        EndSection
+        '')}
+
+
         Section "ServerLayout"
           Identifier "Layout[all]"
           ${cfg.serverLayoutSection}
@@ -593,4 +622,3 @@ in
   };
 
 }
-
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index 7aa4b12a654..4289740322a 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -322,7 +322,9 @@ foreach my $device (keys %$prevSwaps) {
 
 
 # Should we have systemd re-exec itself?
-my $restartSystemd = abs_path("/proc/1/exe") ne abs_path("@systemd@/lib/systemd/systemd");
+my $prevSystemd = abs_path("/proc/1/exe") or die;
+my $newSystemd = abs_path("@systemd@/lib/systemd/systemd") or die;
+my $restartSystemd = $prevSystemd ne $newSystemd;
 
 
 sub filterUnits {
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index 2ef1fca1983..81009e9fb82 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -468,8 +468,8 @@ sub getEfiTarget {
         if ($grubTargetEfi eq "") { die }
         else {return "only" }
     } else {
-        # at least one grub target has to be given
-        die
+        # prevent an installation if neither grub nor grubEfi is given
+        return "neither"
     }
 }
 
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
new file mode 100644
index 00000000000..0221374ab83
--- /dev/null
+++ b/nixos/modules/system/boot/networkd.nix
@@ -0,0 +1,670 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with import ./systemd-unit-options.nix { inherit config lib; };
+with import ./systemd-lib.nix { inherit config lib pkgs; };
+
+let
+
+  cfg = config.systemd.network;
+
+  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)
+  ];
+
+  commonNetworkOptions = {
+
+    enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Whether to manage network configuration using <command>systemd-network</command>.
+      '';
+    };
+
+    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.
+      '';
+    };
+
+  };
+
+  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;
+      };
+    };
+  };
+
+  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}
+
+          '')}
+        '';
+    };
+
+in
+
+{
+
+  options = {
+
+    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 = "Definition of systemd network links.";
+    };
+
+    systemd.network.netdevs = mkOption {
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = [ netdevOptions ];
+      description = "Definition of systemd network devices.";
+    };
+
+    systemd.network.networks = mkOption {
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = [ networkOptions networkConfig ];
+      description = "Definition 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);
+          };
+        };
+    };
+
+  };
+
+  config = mkIf config.systemd.network.enable {
+
+    systemd.additionalUpstreamSystemUnits =
+      [ "systemd-networkd.service" "systemd-networkd-wait-online.service" ];
+
+    systemd.network.units =
+      mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
+      // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
+      // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
+
+    environment.etc."systemd/network".source =
+      generateUnits "network" cfg.units [] [];
+
+    users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
+    users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network;
+
+    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;
+
+  };
+
+}
diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix
new file mode 100644
index 00000000000..ecd547322d3
--- /dev/null
+++ b/nixos/modules/system/boot/resolved.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  options = {
+
+    services.resolved.enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Whether to enable the systemd DNS resolver daemon.
+      '';
+    };
+
+  };
+
+  config = mkIf config.services.resolved.enable {
+
+    systemd.additionalUpstreamSystemUnits = [ "systemd-resolved.service" ];
+
+    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}
+    '';
+
+    users.extraUsers.systemd-resolve.uid = config.ids.uids.systemd-resolve;
+    users.extraGroups.systemd-resolve.gid = config.ids.gids.systemd-resolve;
+
+  };
+
+}
diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix
index 6155bb37cc5..c0ef4e02d1f 100644
--- a/nixos/modules/system/boot/stage-2.nix
+++ b/nixos/modules/system/boot/stage-2.nix
@@ -24,7 +24,6 @@ let
     path =
       [ pkgs.coreutils
         pkgs.utillinux
-        pkgs.sysvtools
         pkgs.openresolv
       ] ++ optional config.nix.readOnlyStore readonlyMountpoint;
     postBootCommands = pkgs.writeText "local-cmds"
diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix
new file mode 100644
index 00000000000..e8cfd3395cb
--- /dev/null
+++ b/nixos/modules/system/boot/systemd-lib.nix
@@ -0,0 +1,118 @@
+{ config, lib, pkgs }:
+
+with lib;
+
+let cfg = config.systemd; in
+
+rec {
+
+  shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s);
+
+  makeUnit = name: unit:
+    let
+      pathSafeName = lib.replaceChars ["@" ":" "\\"] ["-" "-" "-"] name;
+    in
+    if unit.enable then
+      pkgs.runCommand "unit-${pathSafeName}" { preferLocalBuild = true; inherit (unit) text; }
+        ''
+          mkdir -p $out
+          echo -n "$text" > $out/${shellEscape name}
+        ''
+    else
+      pkgs.runCommand "unit-${pathSafeName}-disabled" { preferLocalBuild = true; }
+        ''
+          mkdir -p $out
+          ln -s /dev/null $out/${shellEscape name}
+        '';
+
+  generateUnits = type: units: upstreamUnits: upstreamWants:
+    pkgs.runCommand "${type}-units" { preferLocalBuild = true; } ''
+      mkdir -p $out
+
+      # Copy the upstream systemd units we're interested in.
+      for i in ${toString upstreamUnits}; do
+        fn=${cfg.package}/example/systemd/${type}/$i
+        if ! [ -e $fn ]; then echo "missing $fn"; false; fi
+        if [ -L $fn ]; then
+          target="$(readlink "$fn")"
+          if [ ''${target:0:3} = ../ ]; then
+            ln -s "$(readlink -f "$fn")" $out/
+          else
+            cp -pd $fn $out/
+          fi
+        else
+          ln -s $fn $out/
+        fi
+      done
+
+      # Copy .wants links, but only those that point to units that
+      # we're interested in.
+      for i in ${toString upstreamWants}; do
+        fn=${cfg.package}/example/systemd/${type}/$i
+        if ! [ -e $fn ]; then echo "missing $fn"; false; fi
+        x=$out/$(basename $fn)
+        mkdir $x
+        for i in $fn/*; do
+          y=$x/$(basename $i)
+          cp -pd $i $y
+          if ! [ -e $y ]; then rm $y; fi
+        done
+      done
+
+      # Symlink all units provided listed in systemd.packages.
+      for i in ${toString cfg.packages}; do
+        for fn in $i/etc/systemd/${type}/* $i/lib/systemd/${type}/*; do
+          if ! [[ "$fn" =~ .wants$ ]]; then
+            ln -s $fn $out/
+          fi
+        done
+      done
+
+      # Symlink all units defined by systemd.units. If these are also
+      # provided by systemd or systemd.packages, then add them as
+      # <unit-name>.d/overrides.conf, which makes them extend the
+      # upstream unit.
+      for i in ${toString (mapAttrsToList (n: v: v.unit) units)}; do
+        fn=$(basename $i/*)
+        if [ -e $out/$fn ]; then
+          if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
+            ln -sfn /dev/null $out/$fn
+          else
+            mkdir $out/$fn.d
+            ln -s $i/$fn $out/$fn.d/overrides.conf
+          fi
+       else
+          ln -fs $i/$fn $out/
+        fi
+      done
+
+      # Created .wants and .requires symlinks from the wantedBy and
+      # requiredBy options.
+      ${concatStrings (mapAttrsToList (name: unit:
+          concatMapStrings (name2: ''
+            mkdir -p $out/'${name2}.wants'
+            ln -sfn '../${name}' $out/'${name2}.wants'/
+          '') unit.wantedBy) units)}
+
+      ${concatStrings (mapAttrsToList (name: unit:
+          concatMapStrings (name2: ''
+            mkdir -p $out/'${name2}.requires'
+            ln -sfn '../${name}' $out/'${name2}.requires'/
+          '') unit.requiredBy) units)}
+
+      ${optionalString (type == "system") ''
+        # Stupid misc. symlinks.
+        ln -s ${cfg.defaultUnit} $out/default.target
+
+        ln -s rescue.target $out/kbrequest.target
+
+        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/
+      ''}
+    ''; # */
+
+}
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 2f4786c7896..785634cbf66 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -62,126 +62,7 @@ let
     ])
   ];
 
-  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)
-  ];
+in rec {
 
   unitOption = mkOptionType {
     name = "systemd option";
@@ -195,8 +76,6 @@ let
         else mergeOneOption loc defs';
   };
 
-in rec {
-
   sharedOptions = {
 
     enable = mkOption {
@@ -619,345 +498,4 @@ 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 29c449d4d0b..78aac7fe96f 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -3,6 +3,7 @@
 with utils;
 with lib;
 with import ./systemd-unit-options.nix { inherit config lib; };
+with import ./systemd-lib.nix { inherit config lib pkgs; };
 
 let
 
@@ -10,24 +11,6 @@ let
 
   systemd = cfg.package;
 
-
-  makeUnit = name: unit:
-    let
-      pathSafeName = lib.replaceChars ["@" ":" "\\"] ["-" "-" "-"] name;
-    in
-    if unit.enable then
-      pkgs.runCommand "unit-${pathSafeName}" { preferLocalBuild = true; inherit (unit) text; }
-        ''
-          mkdir -p $out
-          echo -n "$text" > $out/${shellEscape name}
-        ''
-    else
-      pkgs.runCommand "unit-${pathSafeName}-disabled" { preferLocalBuild = true; }
-        ''
-          mkdir -p $out
-          ln -s /dev/null $out/${shellEscape name}
-        '';
-
   upstreamSystemUnits =
     [ # Targets.
       "basic.target"
@@ -97,12 +80,6 @@ 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"
@@ -196,8 +173,6 @@ let
       "timers.target"
     ];
 
-  shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s);
-
   makeJobScript = name: text:
     let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${shellEscape name}"; inherit text; };
     in "${x}/bin/${shellEscape name}";
@@ -301,19 +276,6 @@ 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"
@@ -412,188 +374,6 @@ let
       ${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
-
-      # Copy the upstream systemd units we're interested in.
-      for i in ${toString upstreamUnits}; do
-        fn=${systemd}/example/systemd/${type}/$i
-        if ! [ -e $fn ]; then echo "missing $fn"; false; fi
-        if [ -L $fn ]; then
-          target="$(readlink "$fn")"
-          if [ ''${target:0:3} = ../ ]; then
-            ln -s "$(readlink -f "$fn")" $out/
-          else
-            cp -pd $fn $out/
-          fi
-        else
-          ln -s $fn $out/
-        fi
-      done
-
-      # Copy .wants links, but only those that point to units that
-      # we're interested in.
-      for i in ${toString upstreamWants}; do
-        fn=${systemd}/example/systemd/${type}/$i
-        if ! [ -e $fn ]; then echo "missing $fn"; false; fi
-        x=$out/$(basename $fn)
-        mkdir $x
-        for i in $fn/*; do
-          y=$x/$(basename $i)
-          cp -pd $i $y
-          if ! [ -e $y ]; then rm $y; fi
-        done
-      done
-
-      # Symlink all units provided listed in systemd.packages.
-      for i in ${toString cfg.packages}; do
-        for fn in $i/etc/systemd/${type}/* $i/lib/systemd/${type}/*; do
-          if ! [[ "$fn" =~ .wants$ ]]; then
-            ln -s $fn $out/
-          fi
-        done
-      done
-
-      # Symlink all units defined by systemd.units. If these are also
-      # provided by systemd or systemd.packages, then add them as
-      # <unit-name>.d/overrides.conf, which makes them extend the
-      # upstream unit.
-      for i in ${toString (mapAttrsToList (n: v: v.unit) units)}; do
-        fn=$(basename $i/*)
-        if [ -e $out/$fn ]; then
-          if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
-            ln -sfn /dev/null $out/$fn
-          else
-            mkdir $out/$fn.d
-            ln -s $i/$fn $out/$fn.d/overrides.conf
-          fi
-       else
-          ln -fs $i/$fn $out/
-        fi
-      done
-
-      # Created .wants and .requires symlinks from the wantedBy and
-      # requiredBy options.
-      ${concatStrings (mapAttrsToList (name: unit:
-          concatMapStrings (name2: ''
-            mkdir -p $out/'${name2}.wants'
-            ln -sfn '../${name}' $out/'${name2}.wants'/
-          '') unit.wantedBy) units)}
-
-      ${concatStrings (mapAttrsToList (name: unit:
-          concatMapStrings (name2: ''
-            mkdir -p $out/'${name2}.requires'
-            ln -sfn '../${name}' $out/'${name2}.requires'/
-          '') unit.requiredBy) units)}
-
-      ${optionalString (type == "system") ''
-        # Stupid misc. symlinks.
-        ln -s ${cfg.defaultUnit} $out/default.target
-
-        ln -s rescue.target $out/kbrequest.target
-
-        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/
-      ''}
-    ''; # */
-
 in
 
 {
@@ -683,47 +463,6 @@ 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 = "Definition of systemd network links.";
-    };
-
-    systemd.network.netdevs = mkOption {
-      default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ netdevOptions ];
-      description = "Definition of systemd network devices.";
-    };
-
-    systemd.network.networks = mkOption {
-      default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ networkOptions networkConfig ];
-      description = "Definition 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;
@@ -807,22 +546,6 @@ 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 = [];
@@ -886,7 +609,7 @@ in
 
   ###### implementation
 
-  config = mkMerge [ {
+  config = {
 
     warnings = concatLists (mapAttrsToList (name: service:
       optional (service.serviceConfig.Type or "" == "oneshot" && service.serviceConfig.Restart or "no" != "no")
@@ -899,9 +622,6 @@ 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 [];
 
@@ -979,11 +699,6 @@ 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
@@ -1006,15 +721,6 @@ 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:
@@ -1053,57 +759,6 @@ 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/system/boot/timesyncd.nix b/nixos/modules/system/boot/timesyncd.nix
new file mode 100644
index 00000000000..cba965b1cd2
--- /dev/null
+++ b/nixos/modules/system/boot/timesyncd.nix
@@ -0,0 +1,40 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  options = {
+
+    services.timesyncd.enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Enables the systemd NTP client daemon.
+      '';
+    };
+
+  };
+
+  config = mkIf config.services.timesyncd.enable {
+
+    systemd.additionalUpstreamSystemUnits = [ "systemd-timesyncd.service" ];
+
+    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;
+
+    users.extraUsers.systemd-timesync.uid = config.ids.uids.systemd-timesync;
+    users.extraGroups.systemd-timesync.gid = config.ids.gids.systemd-timesync;
+
+  };
+
+}
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index c6f2f072352..ce8d6079faa 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -137,9 +137,7 @@ in
     # Add the mount helpers to the system path so that `mount' can find them.
     system.fsPackages = [ pkgs.dosfstools ];
 
-    environment.systemPackages =
-      [ pkgs.ntfs3g pkgs.fuse ]
-      ++ config.system.fsPackages;
+    environment.systemPackages = [ pkgs.fuse ] ++ config.system.fsPackages;
 
     environment.etc.fstab.text =
       let
diff --git a/nixos/modules/tasks/filesystems/cifs.nix b/nixos/modules/tasks/filesystems/cifs.nix
index 3932b5c9acf..a928fcae415 100644
--- a/nixos/modules/tasks/filesystems/cifs.nix
+++ b/nixos/modules/tasks/filesystems/cifs.nix
@@ -11,7 +11,7 @@ in
 {
   config = {
 
-    system.fsPackages = [ pkgs.cifs_utils ];
+    system.fsPackages = mkIf (any (fs: fs == "cifs") config.boot.supportedFilesystems) [ pkgs.cifs_utils ];
 
     boot.initrd.availableKernelModules = mkIf inInitrd
       [ "cifs" "nls_utf8" "hmac" "md4" "ecb" "des_generic" "sha256" ];
diff --git a/nixos/modules/tasks/filesystems/ntfs.nix b/nixos/modules/tasks/filesystems/ntfs.nix
new file mode 100644
index 00000000000..c40d2a1a80b
--- /dev/null
+++ b/nixos/modules/tasks/filesystems/ntfs.nix
@@ -0,0 +1,11 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  config = mkIf (any (fs: fs == "ntfs" || fs == "ntfs-3g") config.boot.supportedFilesystems) {
+
+    system.fsPackages = [ pkgs.ntfs3g ];
+
+  };
+}
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index fd545a723e7..328d94cbb05 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -107,7 +107,7 @@ in
             ips = interfaceIps i;
           in
           nameValuePair "network-addresses-${i.name}"
-          { description = "Addresss configuration of ${i.name}";
+          { description = "Address configuration of ${i.name}";
             wantedBy = [ "network-interfaces.target" ];
             before = [ "network-interfaces.target" ];
             bindsTo = [ (subsystemDevice i.name) ];
diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix
index a7e8953827a..67047541102 100644
--- a/nixos/modules/virtualisation/container-config.nix
+++ b/nixos/modules/virtualisation/container-config.nix
@@ -9,6 +9,7 @@ with lib;
     # Disable some features that are not useful in a container.
     sound.enable = mkDefault false;
     services.udisks2.enable = mkDefault false;
+    powerManagement.enable = mkDefault false;
 
     networking.useHostResolvConf = true;
 
@@ -20,6 +21,8 @@ with lib;
 
     systemd.services.systemd-remount-fs.enable = false;
 
+    systemd.services.systemd-random-seed.enable = false;
+
   };
 
 }
diff --git a/nixos/modules/virtualisation/docker-image.nix b/nixos/modules/virtualisation/docker-image.nix
index 0195ca5c6dc..9535e3e0d67 100644
--- a/nixos/modules/virtualisation/docker-image.nix
+++ b/nixos/modules/virtualisation/docker-image.nix
@@ -2,7 +2,7 @@
 
 {
   imports = [
-    ../profiles/container.nix
+    ../profiles/docker-container.nix # FIXME, shouldn't include something from profiles/
   ];
 
   boot.postBootCommands =
diff --git a/nixos/modules/virtualisation/google-compute-config.nix b/nixos/modules/virtualisation/google-compute-config.nix
index 9e6be93b6d9..f6bca1aa857 100644
--- a/nixos/modules/virtualisation/google-compute-config.nix
+++ b/nixos/modules/virtualisation/google-compute-config.nix
@@ -1,5 +1,5 @@
-{ config, pkgs, modulesPath, ... }:
+{ config, pkgs, ... }:
 
 {
-  imports = [ "${modulesPath}/virtualisation/google-compute-image.nix" ];
+  imports = [ <nixpkgs/nixos/modules/virtualisation/google-compute-image.nix> ];
 }
diff --git a/nixos/modules/virtualisation/lxc-container.nix b/nixos/modules/virtualisation/lxc-container.nix
index 2fa749d542e..0208787e779 100644
--- a/nixos/modules/virtualisation/lxc-container.nix
+++ b/nixos/modules/virtualisation/lxc-container.nix
@@ -4,7 +4,7 @@ with lib;
 
 {
   imports = [
-    ../profiles/container.nix
+    ../profiles/docker-container.nix # FIXME, shouldn't include something from profiles/
   ];
 
   # Allow the user to login as root without password.
diff --git a/nixos/tests/gnome3_16.nix b/nixos/tests/gnome3_16.nix
new file mode 100644
index 00000000000..23a66aba50c
--- /dev/null
+++ b/nixos/tests/gnome3_16.nix
@@ -0,0 +1,34 @@
+import ./make-test.nix {
+  name = "gnome3";
+
+  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_16;
+
+      virtualisation.memorySize = 512;
+    };
+
+  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/networking.nix b/nixos/tests/networking.nix
index 46d0422f9c6..2ea96ecb7ca 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -64,26 +64,26 @@ import ./make-test.nix ({ networkd, test, ... }:
             $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");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
+            $client->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
+            $router->waitUntilSucceeds("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");
+            $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
+            $client->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
+            $router->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.3.1");
+            $client->waitUntilSucceeds("ping -c 1 192.168.3.1");
           '';
       };
       dhcpSimple = {
@@ -109,22 +109,22 @@ import ./make-test.nix ({ networkd, test, ... }:
             $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");
+            $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
+            $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'");
 
             # Test vlan 1
-            $client->succeed("ping -c 1 192.168.1.1");
-            $client->succeed("ping -c 1 192.168.1.2");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $client->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $router->waitUntilSucceeds("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");
+            $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
+            $client->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
+            $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
           '';
       };
       dhcpOneIf = {
@@ -147,26 +147,27 @@ import ./make-test.nix ({ networkd, test, ... }:
           ''
             startAll;
 
+            # Wait for networking to come up
             $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->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
 
             # Test vlan 1
-            $client->succeed("ping -c 1 192.168.1.1");
-            $client->succeed("ping -c 1 192.168.1.2");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $client->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
 
             # Test vlan 2
-            $client->succeed("ping -c 1 192.168.2.1");
+            $client->waitUntilSucceeds("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->waitUntilSucceeds("ping -c 1 192.168.2.1");
             $router->fail("ping -c 1 192.168.2.2");
           '';
       };
@@ -195,17 +196,18 @@ import ./make-test.nix ({ networkd, test, ... }:
           ''
             startAll;
 
+            # Wait for networking to come up
             $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");
+            $client1->waitUntilSucceeds("ping -c 2 192.168.1.1");
+            $client1->waitUntilSucceeds("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");
+            $client2->waitUntilSucceeds("ping -c 2 192.168.1.1");
+            $client2->waitUntilSucceeds("ping -c 2 192.168.1.2");
           '';
       };
       bridge = let
@@ -240,6 +242,7 @@ import ./make-test.nix ({ networkd, test, ... }:
           ''
             startAll;
 
+            # Wait for networking to come up
             $client1->waitForUnit("network-interfaces.target");
             $client1->waitForUnit("network.target");
             $client2->waitForUnit("network-interfaces.target");
@@ -248,17 +251,17 @@ import ./make-test.nix ({ networkd, test, ... }:
             $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");
+            $client1->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $client1->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $client1->waitUntilSucceeds("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");
+            $client2->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $client2->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $client2->waitUntilSucceeds("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");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
           '';
       };
       macvlan = {
@@ -278,23 +281,28 @@ import ./make-test.nix ({ networkd, test, ... }:
           ''
             startAll;
 
+            # Wait for networking to come up
             $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");
+            $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
+            $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'");
 
-            # 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");
+            # Print diagnosting information
+            $router->succeed("ip addr >&2");
+            $client->succeed("ip addr >&2");
 
-            $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");
+            # Test macvlan creates routable ips
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
+
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
+            $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
           '';
       };
       sit = let
@@ -323,20 +331,22 @@ import ./make-test.nix ({ networkd, test, ... }:
           ''
             startAll;
 
+            # Wait for networking to be configured
             $client1->waitForUnit("network-interfaces.target");
             $client1->waitForUnit("network.target");
             $client2->waitForUnit("network-interfaces.target");
             $client2->waitForUnit("network.target");
 
+            # Print diagnostic information
             $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");
+            $client1->waitUntilSucceeds("ping6 -c 1 fc00::1");
+            $client1->waitUntilSucceeds("ping6 -c 1 fc00::2");
 
-            $client2->succeed("ping6 -c 1 fc00::1");
-            $client2->succeed("ping6 -c 1 fc00::2");
+            $client2->waitUntilSucceeds("ping6 -c 1 fc00::1");
+            $client2->waitUntilSucceeds("ping6 -c 1 fc00::2");
           '';
       };
       vlan = let
@@ -364,6 +374,7 @@ import ./make-test.nix ({ networkd, test, ... }:
           ''
             startAll;
 
+            # Wait for networking to be configured
             $client1->waitForUnit("network-interfaces.target");
             $client1->waitForUnit("network.target");
             $client2->waitForUnit("network-interfaces.target");