summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/config-examples/basic.nix21
-rw-r--r--nixos/doc/config-examples/closed-install-configuration.nix32
-rw-r--r--nixos/doc/config-examples/root-on-lvm.nix27
-rw-r--r--nixos/doc/config-examples/svn-server.nix36
-rw-r--r--nixos/doc/config-examples/x86_64-usbstick.nix20
-rw-r--r--nixos/doc/manual/administration/boot-problems.xml65
-rw-r--r--nixos/doc/manual/administration/cleaning-store.xml62
-rw-r--r--nixos/doc/manual/administration/container-networking.xml50
-rw-r--r--nixos/doc/manual/administration/containers.xml34
-rw-r--r--nixos/doc/manual/administration/control-groups.xml75
-rw-r--r--nixos/doc/manual/administration/declarative-containers.xml52
-rw-r--r--nixos/doc/manual/administration/imperative-containers.xml124
-rw-r--r--nixos/doc/manual/administration/logging.xml52
-rw-r--r--nixos/doc/manual/administration/maintenance-mode.xml18
-rw-r--r--nixos/doc/manual/administration/network-problems.xml33
-rw-r--r--nixos/doc/manual/administration/rebooting.xml44
-rw-r--r--nixos/doc/manual/administration/rollback.xml48
-rw-r--r--nixos/doc/manual/administration/running.xml24
-rw-r--r--nixos/doc/manual/administration/service-mgmt.xml83
-rw-r--r--nixos/doc/manual/administration/store-corruption.xml37
-rw-r--r--nixos/doc/manual/administration/troubleshooting.xml18
-rw-r--r--nixos/doc/manual/administration/user-sessions.xml53
-rw-r--r--nixos/doc/manual/configuration.xml1557
-rw-r--r--nixos/doc/manual/configuration/abstractions.xml166
-rw-r--r--nixos/doc/manual/configuration/ad-hoc-network-config.xml24
-rw-r--r--nixos/doc/manual/configuration/ad-hoc-packages.xml63
-rw-r--r--nixos/doc/manual/configuration/adding-custom-packages.xml84
-rw-r--r--nixos/doc/manual/configuration/config-file.xml213
-rw-r--r--nixos/doc/manual/configuration/config-syntax.xml27
-rw-r--r--nixos/doc/manual/configuration/configuration.xml32
-rw-r--r--nixos/doc/manual/configuration/customizing-packages.xml92
-rw-r--r--nixos/doc/manual/configuration/declarative-packages.xml43
-rw-r--r--nixos/doc/manual/configuration/file-systems.xml40
-rw-r--r--nixos/doc/manual/configuration/firewall.xml38
-rw-r--r--nixos/doc/manual/configuration/ipv4-config.xml44
-rw-r--r--nixos/doc/manual/configuration/ipv6-config.xml19
-rw-r--r--nixos/doc/manual/configuration/linux-kernel.xml69
-rw-r--r--nixos/doc/manual/configuration/luks-file-systems.xml42
-rw-r--r--nixos/doc/manual/configuration/modularity.xml143
-rw-r--r--nixos/doc/manual/configuration/network-manager.xml27
-rw-r--r--nixos/doc/manual/configuration/networking.xml22
-rw-r--r--nixos/doc/manual/configuration/package-mgmt.xml34
-rw-r--r--nixos/doc/manual/configuration/ssh.xml32
-rw-r--r--nixos/doc/manual/configuration/summary.xml191
-rw-r--r--nixos/doc/manual/configuration/user-mgmt.xml95
-rw-r--r--nixos/doc/manual/configuration/wireless.xml41
-rw-r--r--nixos/doc/manual/configuration/x-windows.xml94
-rw-r--r--nixos/doc/manual/containers.xml242
-rw-r--r--nixos/doc/manual/default.nix56
-rw-r--r--nixos/doc/manual/development.xml1119
-rw-r--r--nixos/doc/manual/development/building-nixos.xml32
-rw-r--r--nixos/doc/manual/development/building-parts.xml113
-rw-r--r--nixos/doc/manual/development/development.xml20
-rw-r--r--nixos/doc/manual/development/nixos-tests.xml19
-rw-r--r--nixos/doc/manual/development/option-declarations.xml141
-rw-r--r--nixos/doc/manual/development/option-def.xml112
-rw-r--r--nixos/doc/manual/development/running-nixos-tests.xml77
-rw-r--r--nixos/doc/manual/development/sources.xml95
-rw-r--r--nixos/doc/manual/development/testing-installer.xml27
-rw-r--r--nixos/doc/manual/development/writing-modules.xml175
-rw-r--r--nixos/doc/manual/development/writing-nixos-tests.xml251
-rw-r--r--nixos/doc/manual/installation.xml570
-rw-r--r--nixos/doc/manual/installation/changing-config.xml90
-rw-r--r--nixos/doc/manual/installation/installation.xml21
-rw-r--r--nixos/doc/manual/installation/installing-uefi.xml51
-rw-r--r--nixos/doc/manual/installation/installing-usb.xml30
-rw-r--r--nixos/doc/manual/installation/installing.xml264
-rw-r--r--nixos/doc/manual/installation/obtaining.xml44
-rw-r--r--nixos/doc/manual/installation/upgrading.xml90
-rw-r--r--nixos/doc/manual/man-nixos-option.xml66
-rw-r--r--nixos/doc/manual/manual.xml24
-rw-r--r--nixos/doc/manual/release-notes/release-notes.xml17
-rw-r--r--nixos/doc/manual/release-notes/rl-1310.xml11
-rw-r--r--nixos/doc/manual/release-notes/rl-1404.xml (renamed from nixos/doc/manual/release-notes.xml)50
-rw-r--r--nixos/doc/manual/release-notes/rl-1410.xml22
-rw-r--r--nixos/doc/manual/running.xml369
-rw-r--r--nixos/doc/manual/style.css7
-rw-r--r--nixos/doc/manual/troubleshooting.xml199
-rw-r--r--nixos/lib/build-vms.nix11
-rw-r--r--nixos/lib/make-system-tarball.nix5
-rw-r--r--nixos/lib/make-system-tarball.sh2
-rw-r--r--nixos/lib/utils.nix3
-rwxr-xr-xnixos/maintainers/scripts/gce/create-gce.sh7
-rw-r--r--nixos/modules/config/fonts/fonts.nix2
-rw-r--r--nixos/modules/config/gtk-exe-env.nix41
-rw-r--r--nixos/modules/config/networking.nix8
-rw-r--r--nixos/modules/config/power-management.nix8
-rw-r--r--nixos/modules/config/pulseaudio.nix16
-rw-r--r--nixos/modules/config/qt-plugin-env.nix37
-rw-r--r--nixos/modules/config/shells-environment.nix4
-rw-r--r--nixos/modules/config/system-path.nix2
-rw-r--r--nixos/modules/config/users-groups.nix93
-rw-r--r--nixos/modules/config/vpnc.nix41
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix9
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball.nix7
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl45
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh8
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh74
-rw-r--r--nixos/modules/installer/tools/tools.nix1
-rw-r--r--nixos/modules/installer/virtualbox-demo.nix3
-rw-r--r--nixos/modules/misc/crashdump.nix2
-rw-r--r--nixos/modules/misc/ids.nix15
-rw-r--r--nixos/modules/misc/meta.nix63
-rwxr-xr-x[-rw-r--r--]nixos/modules/module-list.nix23
-rw-r--r--nixos/modules/profiles/all-hardware.nix4
-rw-r--r--nixos/modules/programs/environment.nix2
-rw-r--r--nixos/modules/programs/freetds.nix61
-rw-r--r--nixos/modules/programs/shadow.nix6
-rw-r--r--nixos/modules/programs/uim.nix29
-rw-r--r--nixos/modules/programs/virtualbox.nix2
-rw-r--r--nixos/modules/security/pam.nix20
-rw-r--r--nixos/modules/security/setuid-wrappers.nix4
-rw-r--r--nixos/modules/services/audio/mopidy.nix2
-rw-r--r--nixos/modules/services/backup/rsnapshot.nix2
-rw-r--r--nixos/modules/services/databases/neo4j.nix143
-rw-r--r--nixos/modules/services/databases/postgresql.xml77
-rw-r--r--nixos/modules/services/hardware/tcsd.nix4
-rw-r--r--nixos/modules/services/hardware/thermald.nix28
-rw-r--r--nixos/modules/services/logging/syslog-ng.nix4
-rw-r--r--nixos/modules/services/mail/mlmmj.nix128
-rw-r--r--nixos/modules/services/misc/mesos-master.nix103
-rw-r--r--nixos/modules/services/misc/mesos-slave.nix93
-rw-r--r--nixos/modules/services/misc/nixos-manual.nix2
-rw-r--r--nixos/modules/services/misc/phd.nix52
-rw-r--r--nixos/modules/services/misc/siproxd.nix180
-rw-r--r--nixos/modules/services/misc/uhub.nix186
-rwxr-xr-xnixos/modules/services/misc/zookeeper.nix145
-rw-r--r--nixos/modules/services/monitoring/riemann-dash.nix79
-rw-r--r--nixos/modules/services/monitoring/riemann.nix77
-rw-r--r--nixos/modules/services/monitoring/smartd.nix2
-rw-r--r--nixos/modules/services/network-filesystems/diod.nix159
-rw-r--r--nixos/modules/services/network-filesystems/nfsd.nix13
-rw-r--r--nixos/modules/services/network-filesystems/yandex-disk.nix104
-rw-r--r--nixos/modules/services/networking/atftpd.nix51
-rw-r--r--nixos/modules/services/networking/cjdns.nix316
-rw-r--r--nixos/modules/services/networking/copy-com.nix53
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix41
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix50
-rw-r--r--nixos/modules/services/networking/ircd-hybrid/default.nix4
-rw-r--r--nixos/modules/services/networking/nat.nix33
-rw-r--r--nixos/modules/services/networking/nsd.nix241
-rw-r--r--nixos/modules/services/networking/openntpd.nix49
-rw-r--r--nixos/modules/services/networking/privoxy.nix76
-rw-r--r--nixos/modules/services/networking/radvd.nix32
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix38
-rw-r--r--nixos/modules/services/networking/unbound.nix32
-rw-r--r--nixos/modules/services/networking/znc.nix192
-rw-r--r--nixos/modules/services/printing/cupsd.nix24
-rw-r--r--nixos/modules/services/security/clamav.nix4
-rw-r--r--nixos/modules/services/ttys/agetty.nix7
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix8
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/mediawiki.nix1
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/phabricator.nix61
-rw-r--r--nixos/modules/services/web-servers/tomcat.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix4
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix6
-rw-r--r--nixos/modules/services/x11/display-managers/slim.nix10
-rw-r--r--nixos/modules/services/x11/window-managers/fluxbox.nix28
-rw-r--r--nixos/modules/services/x11/xserver.nix4
-rw-r--r--nixos/modules/system/boot/kernel.nix1
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix37
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl146
-rw-r--r--nixos/modules/system/boot/loader/gummiboot/gummiboot.nix2
-rw-r--r--nixos/modules/system/boot/luksroot.nix67
-rw-r--r--nixos/modules/system/boot/modprobe.nix5
-rw-r--r--nixos/modules/system/boot/stage-1.nix12
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh4
-rw-r--r--nixos/modules/system/boot/systemd.nix2
-rw-r--r--nixos/modules/tasks/cpu-freq.nix4
-rw-r--r--nixos/modules/tasks/filesystems/nfs.nix37
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix6
-rw-r--r--nixos/modules/tasks/network-interfaces.nix318
-rw-r--r--nixos/modules/tasks/trackpoint.nix44
-rw-r--r--nixos/modules/virtualisation/container-config.nix71
-rw-r--r--nixos/modules/virtualisation/containers.nix91
-rw-r--r--nixos/modules/virtualisation/docker-image.nix67
-rw-r--r--nixos/modules/virtualisation/docker.nix1
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix35
-rw-r--r--nixos/modules/virtualisation/nixos-container.pl90
-rw-r--r--nixos/modules/virtualisation/openvswitch.nix117
-rw-r--r--nixos/release-combined.nix5
-rw-r--r--nixos/release.nix57
-rw-r--r--nixos/tests/bittorrent.nix6
-rw-r--r--nixos/tests/installer.nix114
-rw-r--r--nixos/tests/nat.nix2
-rw-r--r--nixos/tests/phabricator.nix7
187 files changed, 8363 insertions, 5239 deletions
diff --git a/nixos/doc/config-examples/basic.nix b/nixos/doc/config-examples/basic.nix
deleted file mode 100644
index da37cfb8c28..00000000000
--- a/nixos/doc/config-examples/basic.nix
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  boot = {
-    loader.grub.device = "/dev/sda";
-  };
-
-  fileSystems = [
-    { mountPoint = "/";
-      device = "/dev/sda1";
-    }
-  ];
-
-  swapDevices = [
-    { device = "/dev/sdb1"; }
-  ];
-
-  services = {
-    openssh = {
-      enable = true;
-    };
-  };
-}
diff --git a/nixos/doc/config-examples/closed-install-configuration.nix b/nixos/doc/config-examples/closed-install-configuration.nix
deleted file mode 100644
index 0cebacdb0cc..00000000000
--- a/nixos/doc/config-examples/closed-install-configuration.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  boot = {
-    loader.grub.device = "/dev/sda";
-    copyKernels = true;
-    bootMount = "(hd0,0)";
-  };
-
-  fileSystems = [
-    { mountPoint = "/";
-      device = "/dev/sda3";
-    }
-    { mountPoint = "/boot";
-      device = "/dev/sda1";
-      neededForBoot = true;
-    }
-  ];
-
-  swapDevices = [
-    { device = "/dev/sda2"; }
-  ];
-
-  services = {
-    sshd = {
-      enable = true;
-    };
-  };
-
-  fonts = {
-    enableFontConfig = false;
-  };
-
-}
diff --git a/nixos/doc/config-examples/root-on-lvm.nix b/nixos/doc/config-examples/root-on-lvm.nix
deleted file mode 100644
index 2ea1e547921..00000000000
--- a/nixos/doc/config-examples/root-on-lvm.nix
+++ /dev/null
@@ -1,27 +0,0 @@
-# This configuration has / on a LVM volume.  Since Grub
-# doesn't know about LVM, a separate /boot is therefore
-# needed.
-#
-# In this example, labels are used for file systems and
-# swap devices: "boot" might be /dev/sda1, "root" might be
-# /dev/my-volume-group/root, and "swap" might be /dev/sda2.
-# In particular there is no specific reference to the fact
-# that / is on LVM; that's figured out automatically.
-
-{
-  boot.loader.grub.device = "/dev/sda";
-  boot.initrd.kernelModules = ["ata_piix"];
-
-  fileSystems = [
-    { mountPoint = "/";
-      label = "root";
-    }
-    { mountPoint = "/boot";
-      label = "boot";
-    }
-  ];
-
-  swapDevices = [
-    { label = "swap"; }
-  ];
-}
diff --git a/nixos/doc/config-examples/svn-server.nix b/nixos/doc/config-examples/svn-server.nix
deleted file mode 100644
index e727007117b..00000000000
--- a/nixos/doc/config-examples/svn-server.nix
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-  boot = {
-    loader.grub.device = "/dev/sda";
-  };
-
-  fileSystems = [
-    { mountPoint = "/";
-      device = "/dev/sda1";
-    }
-  ];
-
-  services = {
-
-    sshd = {
-      enable = true;
-    };
-
-    httpd = {
-      enable = true;
-      adminAddr = "admin@example.org";
-
-      subservices = {
-
-        subversion = {
-          enable = true;
-          dataDir = "/data/subversion";
-          notificationSender = "svn@example.org";
-        };
-
-      };
-
-    };
-
-  };
-
-}
diff --git a/nixos/doc/config-examples/x86_64-usbstick.nix b/nixos/doc/config-examples/x86_64-usbstick.nix
deleted file mode 100644
index 374d3ba3bc7..00000000000
--- a/nixos/doc/config-examples/x86_64-usbstick.nix
+++ /dev/null
@@ -1,20 +0,0 @@
-# Configuration file used to install NixOS-x86_64 on a USB stick.
-
-{
-  boot = {
-    loader.grub.device = "/dev/sda";
-    initrd = {
-      kernelModules = ["usb_storage" "ehci_hcd" "ohci_hcd"];
-    };
-  };
-
-  fileSystems = [
-    { mountPoint = "/";
-      label = "nixos-usb";
-    }
-  ];
-
-  fonts = {
-    enableFontConfig = false;
-  };
-}
diff --git a/nixos/doc/manual/administration/boot-problems.xml b/nixos/doc/manual/administration/boot-problems.xml
new file mode 100644
index 00000000000..be6ff3aac0f
--- /dev/null
+++ b/nixos/doc/manual/administration/boot-problems.xml
@@ -0,0 +1,65 @@
+<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-boot-problems">
+
+<title>Boot Problems</title>
+
+<para>If NixOS fails to boot, there are a number of kernel command
+line parameters that may help you to identify or fix the issue.  You
+can add these parameters in the GRUB boot menu by pressing “e” to
+modify the selected boot entry and editing the line starting with
+<literal>linux</literal>.  The following are some useful kernel command
+line parameters that are recognised by the NixOS boot scripts or by
+systemd:
+
+<variablelist>
+
+  <varlistentry><term><literal>boot.shell_on_fail</literal></term>
+    <listitem><para>Start a root shell if something goes wrong in
+    stage 1 of the boot process (the initial ramdisk).  This is
+    disabled by default because there is no authentication for the
+    root shell.</para></listitem>
+  </varlistentry>
+
+  <varlistentry><term><literal>boot.debug1</literal></term>
+    <listitem><para>Start an interactive shell in stage 1 before
+    anything useful has been done.  That is, no modules have been
+    loaded and no file systems have been mounted, except for
+    <filename>/proc</filename> and
+    <filename>/sys</filename>.</para></listitem>
+  </varlistentry>
+
+  <varlistentry><term><literal>boot.trace</literal></term>
+    <listitem><para>Print every shell command executed by the stage 1
+    and 2 boot scripts.</para></listitem>
+  </varlistentry>
+
+  <varlistentry><term><literal>single</literal></term>
+    <listitem><para>Boot into rescue mode (a.k.a. single user mode).
+    This will cause systemd to start nothing but the unit
+    <literal>rescue.target</literal>, which runs
+    <command>sulogin</command> to prompt for the root password and
+    start a root login shell.  Exiting the shell causes the system to
+    continue with the normal boot process.</para></listitem>
+  </varlistentry>
+
+  <varlistentry><term><literal>systemd.log_level=debug systemd.log_target=console</literal></term>
+    <listitem><para>Make systemd very verbose and send log messages to
+    the console instead of the journal.</para></listitem>
+  </varlistentry>
+
+</variablelist>
+
+For more parameters recognised by systemd, see
+<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
+
+<para>If no login prompts or X11 login screens appear (e.g. due to
+hanging dependencies), you can press Alt+ArrowUp.  If you’re lucky,
+this will start rescue mode (described above).  (Also note that since
+most units have a 90-second timeout before systemd gives up on them,
+the <command>agetty</command> login prompts should appear eventually
+unless something is very wrong.)</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/cleaning-store.xml b/nixos/doc/manual/administration/cleaning-store.xml
new file mode 100644
index 00000000000..41dc65795b6
--- /dev/null
+++ b/nixos/doc/manual/administration/cleaning-store.xml
@@ -0,0 +1,62 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-nix-gc">
+
+<title>Cleaning the Nix Store</title>
+
+<para>Nix has a purely functional model, meaning that packages are
+never upgraded in place.  Instead new versions of packages end up in a
+different location in the Nix store (<filename>/nix/store</filename>).
+You should periodically run Nix’s <emphasis>garbage
+collector</emphasis> to remove old, unreferenced packages.  This is
+easy:
+
+<screen>
+$ nix-collect-garbage
+</screen>
+
+Alternatively, you can use a systemd unit that does the same in the
+background:
+
+<screen>
+$ systemctl start nix-gc.service
+</screen>
+
+You can tell NixOS in <filename>configuration.nix</filename> to run
+this unit automatically at certain points in time, for instance, every
+night at 03:15:
+
+<programlisting>
+nix.gc.automatic = true;
+nix.gc.dates = "03:15";
+</programlisting>
+
+</para>
+
+<para>The commands above do not remove garbage collector roots, such
+as old system configurations.  Thus they do not remove the ability to
+roll back to previous configurations.  The following command deletes
+old roots, removing the ability to roll back to them:
+<screen>
+$ nix-collect-garbage -d
+</screen>
+You can also do this for specific profiles, e.g.
+<screen>
+$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old
+</screen>
+Note that NixOS system configurations are stored in the profile
+<filename>/nix/var/nix/profiles/system</filename>.</para>
+
+<para>Another way to reclaim disk space (often as much as 40% of the
+size of the Nix store) is to run Nix’s store optimiser, which seeks
+out identical files in the store and replaces them with hard links to
+a single copy.
+<screen>
+$ nix-store --optimise
+</screen>
+Since this command needs to read the entire Nix store, it can take
+quite a while to finish.</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/container-networking.xml b/nixos/doc/manual/administration/container-networking.xml
new file mode 100644
index 00000000000..adea3e69840
--- /dev/null
+++ b/nixos/doc/manual/administration/container-networking.xml
@@ -0,0 +1,50 @@
+<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-container-networking">
+
+
+<title>Container Networking</title>
+
+<para>When you create a container using <literal>nixos-container
+create</literal>, it gets it own private IPv4 address in the range
+<literal>10.233.0.0/16</literal>. You can get the container’s IPv4
+address as follows:
+
+<screen>
+$ nixos-container show-ip foo
+10.233.4.2
+
+$ ping -c1 10.233.4.2
+64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms
+</screen>
+
+</para>
+
+<para>Networking is implemented using a pair of virtual Ethernet
+devices. The network interface in the container is called
+<literal>eth0</literal>, while the matching interface in the host is
+called <literal>ve-<replaceable>container-name</replaceable></literal>
+(e.g., <literal>ve-foo</literal>).  The container has its own network
+namespace and the <literal>CAP_NET_ADMIN</literal> capability, so it
+can perform arbitrary network configuration such as setting up
+firewall rules, without affecting or having access to the host’s
+network.</para>
+
+<para>By default, containers cannot talk to the outside network. If
+you want that, you should set up Network Address Translation (NAT)
+rules on the host to rewrite container traffic to use your external
+IP address. This can be accomplished using the following configuration
+on the host:
+
+<programlisting>
+networking.nat.enable = true;
+networking.nat.internalInterfaces = ["ve-+"];
+networking.nat.externalInterface = "eth0";
+</programlisting>
+where <literal>eth0</literal> should be replaced with the desired
+external interface. Note that <literal>ve-+</literal> is a wildcard
+that matches all container interfaces.</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/containers.xml b/nixos/doc/manual/administration/containers.xml
new file mode 100644
index 00000000000..4cd2c8ae556
--- /dev/null
+++ b/nixos/doc/manual/administration/containers.xml
@@ -0,0 +1,34 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="ch-containers">
+
+<title>Container Management</title>
+
+<para>NixOS allows you to easily run other NixOS instances as
+<emphasis>containers</emphasis>. Containers are a light-weight
+approach to virtualisation that runs software in the container at the
+same speed as in the host system. NixOS containers share the Nix store
+of the host, making container creation very efficient.</para>
+
+<warning><para>Currently, NixOS containers are not perfectly isolated
+from the host system. This means that a user with root access to the
+container can do things that affect the host. So you should not give
+container root access to untrusted users.</para></warning>
+
+<para>NixOS containers can be created in two ways: imperatively, using
+the command <command>nixos-container</command>, and declaratively, by
+specifying them in your <filename>configuration.nix</filename>. The
+declarative approach implies that containers get upgraded along with
+your host system when you run <command>nixos-rebuild</command>, which
+is often not what you want. By contrast, in the imperative approach,
+containers are configured and updated independently from the host
+system.</para>
+
+<xi:include href="imperative-containers.xml" />
+<xi:include href="declarative-containers.xml" />
+<xi:include href="container-networking.xml" />
+
+</chapter>
+
diff --git a/nixos/doc/manual/administration/control-groups.xml b/nixos/doc/manual/administration/control-groups.xml
new file mode 100644
index 00000000000..86c684cdfe5
--- /dev/null
+++ b/nixos/doc/manual/administration/control-groups.xml
@@ -0,0 +1,75 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-cgroups">
+
+<title>Control Groups</title>
+
+<para>To keep track of the processes in a running system, systemd uses
+<emphasis>control groups</emphasis> (cgroups).  A control group is a
+set of processes used to allocate resources such as CPU, memory or I/O
+bandwidth.  There can be multiple control group hierarchies, allowing
+each kind of resource to be managed independently.</para>
+
+<para>The command <command>systemd-cgls</command> lists all control
+groups in the <literal>systemd</literal> hierarchy, which is what
+systemd uses to keep track of the processes belonging to each service
+or user session:
+
+<screen>
+$ systemd-cgls
+├─user
+│ └─eelco
+│   └─c1
+│     ├─ 2567 -:0
+│     ├─ 2682 kdeinit4: kdeinit4 Running...
+│     ├─ <replaceable>...</replaceable>
+│     └─10851 sh -c less -R
+└─system
+  ├─httpd.service
+  │ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH
+  │ └─<replaceable>...</replaceable>
+  ├─dhcpcd.service
+  │ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf
+  └─ <replaceable>...</replaceable>
+</screen>
+
+Similarly, <command>systemd-cgls cpu</command> shows the cgroups in
+the CPU hierarchy, which allows per-cgroup CPU scheduling priorities.
+By default, every systemd service gets its own CPU cgroup, while all
+user sessions are in the top-level CPU cgroup.  This ensures, for
+instance, that a thousand run-away processes in the
+<literal>httpd.service</literal> cgroup cannot starve the CPU for one
+process in the <literal>postgresql.service</literal> cgroup.  (By
+contrast, it they were in the same cgroup, then the PostgreSQL process
+would get 1/1001 of the cgroup’s CPU time.)  You can limit a service’s
+CPU share in <filename>configuration.nix</filename>:
+
+<programlisting>
+systemd.services.httpd.serviceConfig.CPUShares = 512;
+</programlisting>
+
+By default, every cgroup has 1024 CPU shares, so this will halve the
+CPU allocation of the <literal>httpd.service</literal> cgroup.</para>
+
+<para>There also is a <literal>memory</literal> hierarchy that
+controls memory allocation limits; by default, all processes are in
+the top-level cgroup, so any service or session can exhaust all
+available memory.  Per-cgroup memory limits can be specified in
+<filename>configuration.nix</filename>; for instance, to limit
+<literal>httpd.service</literal> to 512 MiB of RAM (excluding swap)
+and 640 MiB of RAM (including swap):
+
+<programlisting>
+systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
+systemd.services.httpd.serviceConfig.ControlGroupAttribute = [ "memory.memsw.limit_in_bytes 640M" ];
+</programlisting>
+
+</para>
+
+<para>The command <command>systemd-cgtop</command> shows a
+continuously updated list of all cgroups with their CPU and memory
+usage.</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/declarative-containers.xml b/nixos/doc/manual/administration/declarative-containers.xml
new file mode 100644
index 00000000000..177ebdd8db1
--- /dev/null
+++ b/nixos/doc/manual/administration/declarative-containers.xml
@@ -0,0 +1,52 @@
+<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-declarative-containers">
+
+<title>Declarative Container Specification</title>
+
+<para>You can also specify containers and their configuration in the
+host’s <filename>configuration.nix</filename>.  For example, the
+following specifies that there shall be a container named
+<literal>database</literal> running PostgreSQL:
+
+<programlisting>
+containers.database =
+  { config =
+      { config, pkgs, ... }:
+      { services.postgresql.enable = true;
+        services.postgresql.package = pkgs.postgresql92;
+      };
+  };
+</programlisting>
+
+If you run <literal>nixos-rebuild switch</literal>, the container will
+be built and started. If the container was already running, it will be
+updated in place, without rebooting.</para>
+
+<para>By default, declarative containers share the network namespace
+of the host, meaning that they can listen on (privileged)
+ports. However, they cannot change the network configuration. You can
+give a container its own network as follows:
+
+<programlisting>
+containers.database =
+  { privateNetwork = true;
+    hostAddress = "192.168.100.10";
+    localAddress = "192.168.100.11";
+  };
+</programlisting>
+
+This gives the container a private virtual Ethernet interface with IP
+address <literal>192.168.100.11</literal>, which is hooked up to a
+virtual Ethernet interface on the host with IP address
+<literal>192.168.100.10</literal>.  (See the next section for details
+on container networking.)</para>
+
+<para>To disable the container, just remove it from
+<filename>configuration.nix</filename> and run <literal>nixos-rebuild
+switch</literal>. Note that this will not delete the root directory of
+the container in <literal>/var/lib/containers</literal>.</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/imperative-containers.xml b/nixos/doc/manual/administration/imperative-containers.xml
new file mode 100644
index 00000000000..6131d4e04ea
--- /dev/null
+++ b/nixos/doc/manual/administration/imperative-containers.xml
@@ -0,0 +1,124 @@
+<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-imperative-containers">
+
+<title>Imperative Container Management</title>
+
+<para>We’ll cover imperative container management using
+<command>nixos-container</command> first. You create a container with
+identifier <literal>foo</literal> as follows:
+
+<screen>
+$ nixos-container create foo
+</screen>
+
+This creates the container’s root directory in
+<filename>/var/lib/containers/foo</filename> and a small configuration
+file in <filename>/etc/containers/foo.conf</filename>. It also builds
+the container’s initial system configuration and stores it in
+<filename>/nix/var/nix/profiles/per-container/foo/system</filename>. You
+can modify the initial configuration of the container on the command
+line. For instance, to create a container that has
+<command>sshd</command> running, with the given public key for
+<literal>root</literal>:
+
+<screen>
+$ nixos-container create foo --config 'services.openssh.enable = true; \
+  users.extraUsers.root.openssh.authorizedKeys.keys = ["ssh-dss AAAAB3N…"];'
+</screen>
+
+</para>
+
+<para>Creating a container does not start it. To start the container,
+run:
+
+<screen>
+$ nixos-container start foo
+</screen>
+
+This command will return as soon as the container has booted and has
+reached <literal>multi-user.target</literal>. On the host, the
+container runs within a systemd unit called
+<literal>container@<replaceable>container-name</replaceable>.service</literal>.
+Thus, if something went wrong, you can get status info using
+<command>systemctl</command>:
+
+<screen>
+$ systemctl status container@foo
+</screen>
+
+</para>
+
+<para>If the container has started succesfully, you can log in as
+root using the <command>root-login</command> operation:
+
+<screen>
+$ nixos-container root-login foo
+[root@foo:~]#
+</screen>
+
+Note that only root on the host can do this (since there is no
+authentication).  You can also get a regular login prompt using the
+<command>login</command> operation, which is available to all users on
+the host:
+
+<screen>
+$ nixos-container login foo
+foo login: alice
+Password: ***
+</screen>
+
+With <command>nixos-container run</command>, you can execute arbitrary
+commands in the container:
+
+<screen>
+$ nixos-container run foo -- uname -a
+Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
+</screen>
+
+</para>
+
+<para>There are several ways to change the configuration of the
+container. First, on the host, you can edit
+<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>,
+and run
+
+<screen>
+$ nixos-container update foo
+</screen>
+
+This will build and activate the new configuration. You can also
+specify a new configuration on the command line:
+
+<screen>
+$ nixos-container update foo --config 'services.httpd.enable = true; \
+  services.httpd.adminAddr = "foo@example.org";'
+
+$ curl http://$(nixos-container show-ip foo)/
+&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">…
+</screen>
+
+However, note that this will overwrite the container’s
+<filename>/etc/nixos/configuration.nix</filename>.</para>
+
+<para>Alternatively, you can change the configuration from within the
+container itself by running <command>nixos-rebuild switch</command>
+inside the container. Note that the container by default does not have
+a copy of the NixOS channel, so you should run <command>nix-channel
+--update</command> first.</para>
+
+<para>Containers can be stopped and started using
+<literal>nixos-container stop</literal> and <literal>nixos-container
+start</literal>, respectively, or by using
+<command>systemctl</command> on the container’s service unit. To
+destroy a container, including its file system, do
+
+<screen>
+$ nixos-container destroy foo
+</screen>
+
+</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/logging.xml b/nixos/doc/manual/administration/logging.xml
new file mode 100644
index 00000000000..1d5df7770e2
--- /dev/null
+++ b/nixos/doc/manual/administration/logging.xml
@@ -0,0 +1,52 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-logging">
+
+<title>Logging</title>
+
+<para>System-wide logging is provided by systemd’s
+<emphasis>journal</emphasis>, which subsumes traditional logging
+daemons such as syslogd and klogd.  Log entries are kept in binary
+files in <filename>/var/log/journal/</filename>.  The command
+<literal>journalctl</literal> allows you to see the contents of the
+journal.  For example,
+
+<screen>
+$ journalctl -b
+</screen>
+
+shows all journal entries since the last reboot.  (The output of
+<command>journalctl</command> is piped into <command>less</command> by
+default.)  You can use various options and match operators to restrict
+output to messages of interest.  For instance, to get all messages
+from PostgreSQL:
+
+<screen>
+$ journalctl -u postgresql.service
+-- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. --
+...
+Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG:  database system is shut down
+-- Reboot --
+Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG:  database system was shut down at 2013-01-07 15:44:14 CET
+Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG:  database system is ready to accept connections
+</screen>
+
+Or to get all messages since the last reboot that have at least a
+“critical” severity level:
+
+<screen>
+$ journalctl -b -p crit
+Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice]
+Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1)
+</screen>
+
+</para>
+
+<para>The system journal is readable by root and by users in the
+<literal>wheel</literal> and <literal>systemd-journal</literal>
+groups.  All users have a private journal that can be read using
+<command>journalctl</command>.</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/maintenance-mode.xml b/nixos/doc/manual/administration/maintenance-mode.xml
new file mode 100644
index 00000000000..15c1f902da7
--- /dev/null
+++ b/nixos/doc/manual/administration/maintenance-mode.xml
@@ -0,0 +1,18 @@
+<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-maintenance-mode">
+
+<title>Maintenance Mode</title>
+
+<para>You can enter rescue mode by running:
+
+<screen>
+$ systemctl rescue</screen>
+
+This will eventually give you a single-user root shell.  Systemd will
+stop (almost) all system services.  To get out of maintenance mode,
+just exit from the rescue shell.</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/network-problems.xml b/nixos/doc/manual/administration/network-problems.xml
new file mode 100644
index 00000000000..5ba1bfd5ac9
--- /dev/null
+++ b/nixos/doc/manual/administration/network-problems.xml
@@ -0,0 +1,33 @@
+<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-nix-network-issues">
+
+<title>Network Problems</title>
+
+<para>Nix uses a so-called <emphasis>binary cache</emphasis> to
+optimise building a package from source into downloading it as a
+pre-built binary.  That is, whenever a command like
+<command>nixos-rebuild</command> needs a path in the Nix store, Nix
+will try to download that path from the Internet rather than build it
+from source.  The default binary cache is
+<uri>http://cache.nixos.org/</uri>.  If this cache is unreachable, Nix
+operations may take a long time due to HTTP connection timeouts.  You
+can disable the use of the binary cache by adding <option>--option
+use-binary-caches false</option>, e.g.
+
+<screen>
+$ nixos-rebuild switch --option use-binary-caches false
+</screen>
+
+If you have an alternative binary cache at your disposal, you can use
+it instead:
+
+<screen>
+$ nixos-rebuild switch --option binary-caches http://my-cache.example.org/
+</screen>
+
+</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/rebooting.xml b/nixos/doc/manual/administration/rebooting.xml
new file mode 100644
index 00000000000..d1db7b141cf
--- /dev/null
+++ b/nixos/doc/manual/administration/rebooting.xml
@@ -0,0 +1,44 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-rebooting">
+
+<title>Rebooting and Shutting Down</title>
+
+<para>The system can be shut down (and automatically powered off) by
+doing:
+
+<screen>
+$ shutdown
+</screen>
+
+This is equivalent to running <command>systemctl
+poweroff</command>.</para>
+
+<para>To reboot the system, run
+
+<screen>
+$ reboot
+</screen>
+
+which is equivalent to <command>systemctl reboot</command>.
+Alternatively, you can quickly reboot the system using
+<literal>kexec</literal>, which bypasses the BIOS by directly loading
+the new kernel into memory:
+
+<screen>
+$ systemctl kexec
+</screen>
+
+</para>
+
+<para>The machine can be suspended to RAM (if supported) using
+<command>systemctl suspend</command>, and suspended to disk using
+<command>systemctl hibernate</command>.</para>
+
+<para>These commands can be run by any user who is logged in locally,
+i.e. on a virtual console or in X11; otherwise, the user is asked for
+authentication.</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/rollback.xml b/nixos/doc/manual/administration/rollback.xml
new file mode 100644
index 00000000000..23a3ece7c07
--- /dev/null
+++ b/nixos/doc/manual/administration/rollback.xml
@@ -0,0 +1,48 @@
+<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-rollback">
+
+<title>Rolling Back Configuration Changes</title>
+
+<para>After running <command>nixos-rebuild</command> to switch to a
+new configuration, you may find that the new configuration doesn’t
+work very well.  In that case, there are several ways to return to a
+previous configuration.</para>
+
+<para>First, the GRUB boot manager allows you to boot into any
+previous configuration that hasn’t been garbage-collected.  These
+configurations can be found under the GRUB submenu “NixOS - All
+configurations”.  This is especially useful if the new configuration
+fails to boot.  After the system has booted, you can make the selected
+configuration the default for subsequent boots:
+
+<screen>
+$ /run/current-system/bin/switch-to-configuration boot</screen>
+
+</para>
+
+<para>Second, you can switch to the previous configuration in a running
+system:
+
+<screen>
+$ nixos-rebuild switch --rollback</screen>
+
+This is equivalent to running:
+
+<screen>
+$ /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen>
+
+where <replaceable>N</replaceable> is the number of the NixOS system
+configuration.  To get a list of the available configurations, do:
+
+<screen>
+$ ls -l /nix/var/nix/profiles/system-*-link
+<replaceable>...</replaceable>
+lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055
+</screen>
+
+</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/running.xml b/nixos/doc/manual/administration/running.xml
new file mode 100644
index 00000000000..9091511ed52
--- /dev/null
+++ b/nixos/doc/manual/administration/running.xml
@@ -0,0 +1,24 @@
+<part 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="ch-running">
+
+<title>Administration</title>
+
+<partintro>
+<para>This chapter describes various aspects of managing a running
+NixOS system, such as how to use the <command>systemd</command>
+service manager.</para>
+</partintro>
+
+<xi:include href="service-mgmt.xml" />
+<xi:include href="rebooting.xml" />
+<xi:include href="user-sessions.xml" />
+<xi:include href="control-groups.xml" />
+<xi:include href="logging.xml" />
+<xi:include href="cleaning-store.xml" />
+<xi:include href="containers.xml" />
+<xi:include href="troubleshooting.xml" />
+
+</part>
diff --git a/nixos/doc/manual/administration/service-mgmt.xml b/nixos/doc/manual/administration/service-mgmt.xml
new file mode 100644
index 00000000000..c0940a42f30
--- /dev/null
+++ b/nixos/doc/manual/administration/service-mgmt.xml
@@ -0,0 +1,83 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-systemctl">
+
+<title>Service Management</title>
+
+<para>In NixOS, all system services are started and monitored using
+the systemd program.  Systemd is the “init” process of the system
+(i.e. PID 1), the parent of all other processes.  It manages a set of
+so-called “units”, which can be things like system services
+(programs), but also mount points, swap files, devices, targets
+(groups of units) and more.  Units can have complex dependencies; for
+instance, one unit can require that another unit must be successfully
+started before the first unit can be started.  When the system boots,
+it starts a unit named <literal>default.target</literal>; the
+dependencies of this unit cause all system services to be started,
+file systems to be mounted, swap files to be activated, and so
+on.</para>
+
+<para>The command <command>systemctl</command> is the main way to
+interact with <command>systemd</command>.  Without any arguments, it
+shows the status of active units:
+
+<screen>
+$ systemctl
+-.mount          loaded active mounted   /
+swapfile.swap    loaded active active    /swapfile
+sshd.service     loaded active running   SSH Daemon
+graphical.target loaded active active    Graphical Interface
+<replaceable>...</replaceable>
+</screen>
+
+</para>
+
+<para>You can ask for detailed status information about a unit, for
+instance, the PostgreSQL database service:
+
+<screen>
+$ systemctl status postgresql.service
+postgresql.service - PostgreSQL Server
+          Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service)
+          Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago
+        Main PID: 2390 (postgres)
+          CGroup: name=systemd:/system/postgresql.service
+                  ├─2390 postgres
+                  ├─2418 postgres: writer process
+                  ├─2419 postgres: wal writer process
+                  ├─2420 postgres: autovacuum launcher process
+                  ├─2421 postgres: stats collector process
+                  └─2498 postgres: zabbix zabbix [local] idle
+
+Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG:  database system was shut down at 2013-01-07 15:55:05 CET
+Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG:  database system is ready to accept connections
+Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG:  autovacuum launcher started
+Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
+</screen>
+
+Note that this shows the status of the unit (active and running), all
+the processes belonging to the service, as well as the most recent log
+messages from the service.
+
+</para>
+
+<para>Units can be stopped, started or restarted:
+
+<screen>
+$ systemctl stop postgresql.service
+$ systemctl start postgresql.service
+$ systemctl restart postgresql.service
+</screen>
+
+These operations are synchronous: they wait until the service has
+finished starting or stopping (or has failed).  Starting a unit will
+cause the dependencies of that unit to be started as well (if
+necessary).</para>
+
+<!-- - cgroups: each service and user session is a cgroup
+
+- cgroup resource management -->
+
+</chapter>
diff --git a/nixos/doc/manual/administration/store-corruption.xml b/nixos/doc/manual/administration/store-corruption.xml
new file mode 100644
index 00000000000..0160cb45358
--- /dev/null
+++ b/nixos/doc/manual/administration/store-corruption.xml
@@ -0,0 +1,37 @@
+<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-nix-store-corruption">
+
+<title>Nix Store Corruption</title>
+
+<para>After a system crash, it’s possible for files in the Nix store
+to become corrupted.  (For instance, the Ext4 file system has the
+tendency to replace un-synced files with zero bytes.)  NixOS tries
+hard to prevent this from happening: it performs a
+<command>sync</command> before switching to a new configuration, and
+Nix’s database is fully transactional.  If corruption still occurs,
+you may be able to fix it automatically.</para>
+
+<para>If the corruption is in a path in the closure of the NixOS
+system configuration, you can fix it by doing
+
+<screen>
+$ nixos-rebuild switch --repair
+</screen>
+
+This will cause Nix to check every path in the closure, and if its
+cryptographic hash differs from the hash recorded in Nix’s database,
+the path is rebuilt or redownloaded.</para>
+
+<para>You can also scan the entire Nix store for corrupt paths:
+
+<screen>
+$ nix-store --verify --check-contents --repair
+</screen>
+
+Any corrupt paths will be redownloaded if they’re available in a
+binary cache; otherwise, they cannot be repaired.</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/administration/troubleshooting.xml b/nixos/doc/manual/administration/troubleshooting.xml
new file mode 100644
index 00000000000..351fb188331
--- /dev/null
+++ b/nixos/doc/manual/administration/troubleshooting.xml
@@ -0,0 +1,18 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="ch-troubleshooting">
+
+<title>Troubleshooting</title>
+
+<para>This chapter describes solutions to common problems you might
+encounter when you manage your NixOS system.</para>
+
+<xi:include href="boot-problems.xml" />
+<xi:include href="maintenance-mode.xml" />
+<xi:include href="rollback.xml" />
+<xi:include href="store-corruption.xml" />
+<xi:include href="network-problems.xml" />
+
+</chapter>
diff --git a/nixos/doc/manual/administration/user-sessions.xml b/nixos/doc/manual/administration/user-sessions.xml
new file mode 100644
index 00000000000..05e2c1a9b29
--- /dev/null
+++ b/nixos/doc/manual/administration/user-sessions.xml
@@ -0,0 +1,53 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-user-sessions">
+
+<title>User Sessions</title>
+
+<para>Systemd keeps track of all users who are logged into the system
+(e.g. on a virtual console or remotely via SSH).  The command
+<command>loginctl</command> allows querying and manipulating user
+sessions.  For instance, to list all user sessions:
+
+<screen>
+$ loginctl
+   SESSION        UID USER             SEAT
+        c1        500 eelco            seat0
+        c3          0 root             seat0
+        c4        500 alice
+</screen>
+
+This shows that two users are logged in locally, while another is
+logged in remotely.  (“Seats” are essentially the combinations of
+displays and input devices attached to the system; usually, there is
+only one seat.)  To get information about a session:
+
+<screen>
+$ loginctl session-status c3
+c3 - root (0)
+           Since: Tue, 2013-01-08 01:17:56 CET; 4min 42s ago
+          Leader: 2536 (login)
+            Seat: seat0; vc3
+             TTY: /dev/tty3
+         Service: login; type tty; class user
+           State: online
+          CGroup: name=systemd:/user/root/c3
+                  ├─ 2536 /nix/store/10mn4xip9n7y9bxqwnsx7xwx2v2g34xn-shadow-4.1.5.1/bin/login --
+                  ├─10339 -bash
+                  └─10355 w3m nixos.org
+</screen>
+
+This shows that the user is logged in on virtual console 3.  It also
+lists the processes belonging to this session.  Since systemd keeps
+track of this, you can terminate a session in a way that ensures that
+all the session’s processes are gone:
+
+<screen>
+$ loginctl terminate-session c3
+</screen>
+
+</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/configuration.xml b/nixos/doc/manual/configuration.xml
deleted file mode 100644
index d35a5fff4aa..00000000000
--- a/nixos/doc/manual/configuration.xml
+++ /dev/null
@@ -1,1557 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-         xmlns:xlink="http://www.w3.org/1999/xlink"
-         xml:id="ch-configuration">
-
-<title>Configuring NixOS</title>
-
-<para>This chapter describes how to configure various aspects of a
-NixOS machine through the configuration file
-<filename>/etc/nixos/configuration.nix</filename>.  As described in
-<xref linkend="sec-changing-config" />, changes to this file only take
-effect after you run <command>nixos-rebuild</command>.</para>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-configuration-syntax"><title>Configuration syntax</title>
-
-<section><title>The basics</title>
-
-<para>The NixOS configuration file
-<filename>/etc/nixos/configuration.nix</filename> is actually a
-<emphasis>Nix expression</emphasis>, which is the Nix package
-manager’s purely functional language for describing how to build
-packages and configurations.  This means you have all the expressive
-power of that language at your disposal, including the ability to
-abstract over common patterns, which is very useful when managing
-complex systems.  The syntax and semantics of the Nix language are
-fully described in the <link
-xlink:href="http://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
-manual</link>, but here we give a short overview of the most important
-constructs useful in NixOS configuration files.</para>
-
-<para>The NixOS configuration file generally looks like this:
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ <replaceable>option definitions</replaceable>
-}
-</programlisting>
-
-The first line (<literal>{ config, pkgs, ... }:</literal>) denotes
-that this is actually a function that takes at least the two arguments
- <varname>config</varname> and <varname>pkgs</varname>.  (These are
-explained later.)  The function returns a <emphasis>set</emphasis> of
-option definitions (<literal>{ <replaceable>...</replaceable> }</literal>).  These definitions have the
-form <literal><replaceable>name</replaceable> =
-<replaceable>value</replaceable></literal>, where
-<replaceable>name</replaceable> is the name of an option and
-<replaceable>value</replaceable> is its value.  For example,
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ services.httpd.enable = true;
-  services.httpd.adminAddr = "alice@example.org";
-  services.httpd.documentRoot = "/webroot";
-}
-</programlisting>
-
-defines a configuration with three option definitions that together
-enable the Apache HTTP Server with <filename>/webroot</filename> as
-the document root.</para>
-
-<para>Sets can be nested, and in fact dots in option names are
-shorthand for defining a set containing another set.  For instance,
-<option>services.httpd.enable</option> defines a set named
-<varname>services</varname> that contains a set named
-<varname>httpd</varname>, which in turn contains an option definition
-named <varname>enable</varname> with value <literal>true</literal>.
-This means that the example above can also be written as:
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ services = {
-    httpd = {
-      enable = true;
-      adminAddr = "alice@example.org";
-      documentRoot = "/webroot";
-    };
-  };
-}
-</programlisting>
-
-which may be more convenient if you have lots of option definitions
-that share the same prefix (such as
-<literal>services.httpd</literal>).</para>
-
-<para>NixOS checks your option definitions for correctness.  For
-instance, if you try to define an option that doesn’t exist (that is,
-doesn’t have a corresponding <emphasis>option declaration</emphasis>),
-<command>nixos-rebuild</command> will give an error like:
-<screen>
-The option `services.httpd.enabl' defined in `/etc/nixos/configuration.nix' does not exist.
-</screen>
-Likewise, values in option definitions must have a correct type.  For
-instance, <option>services.httpd.enable</option> must be a Boolean
-(<literal>true</literal> or <literal>false</literal>).  Trying to give
-it a value of another type, such as a string, will cause an error:
-<screen>
-The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
-</screen>
-
-</para>
-
-<para>Options have various types of values.  The most important are:
-
-<variablelist>
-  <varlistentry>
-    <term>Strings</term>
-    <listitem>
-      <para>Strings are enclosed in double quotes, e.g.
-
-<programlisting>
-networking.hostName = "dexter";
-</programlisting>
-
-      Special characters can be escaped by prefixing them with a
-      backslash (e.g. <literal>\"</literal>).</para>
-
-      <para>Multi-line strings can be enclosed in <emphasis>double
-      single quotes</emphasis>, e.g.
-
-<programlisting>
-networking.extraHosts =
-  ''
-    127.0.0.2 other-localhost
-    10.0.0.1 server
-  '';
-</programlisting>
-
-      The main difference is that preceding whitespace is
-      automatically stripped from each line, and that characters like
-      <literal>"</literal> and <literal>\</literal> are not special
-      (making it more convenient for including things like shell
-      code).</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>Booleans</term>
-    <listitem>
-      <para>These can be <literal>true</literal> or
-      <literal>false</literal>, e.g.
-
-<programlisting>
-networking.firewall.enable = true;
-networking.firewall.allowPing = false;
-</programlisting>
-      </para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>Integers</term>
-    <listitem>
-      <para>For example,
-
-<programlisting>
-boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
-</programlisting>
-
-      (Note that here the attribute name
-      <literal>net.ipv4.tcp_keepalive_time</literal> is enclosed in
-      quotes to prevent it from being interpreted as a set named
-      <literal>net</literal> containing a set named
-      <literal>ipv4</literal>, and so on.  This is because it’s not a
-      NixOS option but the literal name of a Linux kernel
-      setting.)</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>Sets</term>
-    <listitem>
-      <para>Sets were introduced above.  They are name/value pairs
-      enclosed in braces, as in the option definition
-
-<programlisting>
-fileSystems."/boot" =
-  { device = "/dev/sda1";
-    fsType = "ext4";
-    options = "rw,data=ordered,relatime";
-  };
-</programlisting>
-      </para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>Lists</term>
-    <listitem>
-      <para>The important thing to note about lists is that list
-      elements are separated by whitespace, like this:
-
-<programlisting>
-boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
-</programlisting>
-
-      List elements can be any other type, e.g. sets:
-
-<programlisting>
-swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
-</programlisting>
-      </para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>Packages</term>
-    <listitem>
-      <para>Usually, the packages you need are already part of the Nix
-      Packages collection, which is a set that can be accessed through
-      the function argument <varname>pkgs</varname>.  Typical uses:
-
-<programlisting>
-environment.systemPackages =
-  [ pkgs.thunderbird
-    pkgs.emacs
-  ];
-
-postgresql.package = pkgs.postgresql90;
-</programlisting>
-
-      The latter option definition changes the default PostgreSQL
-      package used by NixOS’s PostgreSQL service to 9.0.  For more
-      information on packages, including how to add new ones, see
-      <xref linkend="sec-custom-packages"/>.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-</para>
-
-</section>
-
-
-<section xml:id="sec-module-abstractions"><title>Abstractions</title>
-
-<para>If you find yourself repeating yourself over and over, it’s time
-to abstract.  Take, for instance, this Apache HTTP Server configuration:
-
-<programlisting>
-{
-  services.httpd.virtualHosts =
-    [ { hostName = "example.org";
-        documentRoot = "/webroot";
-        adminAddr = "alice@example.org";
-        enableUserDir = true;
-      }
-      { hostName = "example.org";
-        documentRoot = "/webroot";
-        adminAddr = "alice@example.org";
-        enableUserDir = true;
-        enableSSL = true;
-        sslServerCert = "/root/ssl-example-org.crt";
-        sslServerKey = "/root/ssl-example-org.key";
-      }
-    ];
-}
-</programlisting>
-
-It defines two virtual hosts with nearly identical configuration; the
-only difference is that the second one has SSL enabled.  To prevent
-this duplication, we can use a <literal>let</literal>:
-
-<programlisting>
-let
-  exampleOrgCommon =
-    { hostName = "example.org";
-      documentRoot = "/webroot";
-      adminAddr = "alice@example.org";
-      enableUserDir = true;
-    };
-in
-{
-  services.httpd.virtualHosts =
-    [ exampleOrgCommon
-      (exampleOrgCommon // {
-        enableSSL = true;
-        sslServerCert = "/root/ssl-example-org.crt";
-        sslServerKey = "/root/ssl-example-org.key";
-      })
-    ];
-}
-</programlisting>
-
-The <literal>let exampleOrgCommon =
-<replaceable>...</replaceable></literal> defines a variable named
-<literal>exampleOrgCommon</literal>.  The <literal>//</literal>
-operator merges two attribute sets, so the configuration of the second
-virtual host is the set <literal>exampleOrgCommon</literal> extended
-with the SSL options.</para>
-
-<para>You can write a <literal>let</literal> wherever an expression is
-allowed.  Thus, you also could have written:
-
-<programlisting>
-{
-  services.httpd.virtualHosts =
-    let exampleOrgCommon = <replaceable>...</replaceable>; in
-    [ exampleOrgCommon
-      (exampleOrgCommon // { <replaceable>...</replaceable> })
-    ];
-}
-</programlisting>
-
-but not <literal>{ let exampleOrgCommon =
-<replaceable>...</replaceable>; in <replaceable>...</replaceable>;
-}</literal> since attributes (as opposed to attribute values) are not
-expressions.</para>
-
-<para><emphasis>Functions</emphasis> provide another method of
-abstraction.  For instance, suppose that we want to generate lots of
-different virtual hosts, all with identical configuration except for
-the host name.  This can be done as follows:
-
-<programlisting>
-{
-  services.httpd.virtualHosts =
-    let
-      makeVirtualHost = name:
-        { hostName = name;
-          documentRoot = "/webroot";
-          adminAddr = "alice@example.org";
-        };
-    in
-      [ (makeVirtualHost "example.org")
-        (makeVirtualHost "example.com")
-        (makeVirtualHost "example.gov")
-        (makeVirtualHost "example.nl")
-      ];
-}
-</programlisting>
-
-Here, <varname>makeVirtualHost</varname> is a function that takes a
-single argument <literal>name</literal> and returns the configuration
-for a virtual host.  That function is then called for several names to
-produce the list of virtual host configurations.</para>
-
-<para>We can further improve on this by using the function
-<varname>map</varname>, which applies another function to every
-element in a list:
-
-<programlisting>
-{
-  services.httpd.virtualHosts =
-    let
-      makeVirtualHost = <replaceable>...</replaceable>;
-    in map makeVirtualHost
-      [ "example.org" "example.com" "example.gov" "example.nl" ];
-}
-</programlisting>
-
-(The function <literal>map</literal> is called a
-<emphasis>higher-order function</emphasis> because it takes another
-function as an argument.)</para>
-
-<para>What if you need more than one argument, for instance, if we
-want to use a different <literal>documentRoot</literal> for each
-virtual host?  Then we can make <varname>makeVirtualHost</varname> a
-function that takes a <emphasis>set</emphasis> as its argument, like this:
-
-<programlisting>
-{
-  services.httpd.virtualHosts =
-    let
-      makeVirtualHost = { name, root }:
-        { hostName = name;
-          documentRoot = root;
-          adminAddr = "alice@example.org";
-        };
-    in map makeVirtualHost
-      [ { name = "example.org"; root = "/sites/example.org"; }
-        { name = "example.com"; root = "/sites/example.com"; }
-        { name = "example.gov"; root = "/sites/example.gov"; }
-        { name = "example.nl"; root = "/sites/example.nl"; }
-      ];
-}
-</programlisting>
-
-But in this case (where every root is a subdirectory of
-<filename>/sites</filename> named after the virtual host), it would
-have been shorter to define <varname>makeVirtualHost</varname> as
-<programlisting>
-makeVirtualHost = name:
-  { hostName = name;
-    documentRoot = "/sites/${name}";
-    adminAddr = "alice@example.org";
-  };
-</programlisting>
-
-Here, the construct
-<literal>${<replaceable>...</replaceable>}</literal> allows the result
-of an expression to be spliced into a string.</para>
-
-</section>
-
-
-<section xml:id="sec-modularity"><title>Modularity</title>
-
-<para>The NixOS configuration mechanism is modular.  If your
-<filename>configuration.nix</filename> becomes too big, you can split
-it into multiple files.  Likewise, if you have multiple NixOS
-configurations (e.g. for different computers) with some commonality,
-you can move the common configuration into a shared file.</para>
-
-<para>Modules have exactly the same syntax as
-<filename>configuration.nix</filename>.  In fact,
-<filename>configuration.nix</filename> is itself a module.  You can
-use other modules by including them from
-<filename>configuration.nix</filename>, e.g.:
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ imports = [ ./vpn.nix ./kde.nix ];
-  services.httpd.enable = true;
-  environment.systemPackages = [ pkgs.emacs ];
-  <replaceable>...</replaceable>
-}
-</programlisting>
-
-Here, we include two modules from the same directory,
-<filename>vpn.nix</filename> and <filename>kde.nix</filename>.  The
-latter might look like this:
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ services.xserver.enable = true;
-  services.xserver.displayManager.kdm.enable = true;
-  services.xserver.desktopManager.kde4.enable = true;
-  environment.systemPackages = [ pkgs.kde4.kscreensaver ];
-}
-</programlisting>
-
-Note that both <filename>configuration.nix</filename> and
-<filename>kde.nix</filename> define the option
-<option>environment.systemPackages</option>.  When multiple modules
-define an option, NixOS will try to <emphasis>merge</emphasis> the
-definitions.  In the case of
-<option>environment.systemPackages</option>, that’s easy: the lists of
-packages can simply be concatenated.  The value in
-<filename>configuration.nix</filename> is merged last, so for
-list-type options, it will appear at the end of the merged list. If
-you want it to appear first, you can use <varname>mkBefore</varname>:
-
-<programlisting>
-boot.kernelModules = mkBefore [ "kvm-intel" ];
-</programlisting>
-
-This causes the <literal>kvm-intel</literal> kernel module to be
-loaded before any other kernel modules.</para>
-
-<para>For other types of options, a merge may not be possible. For
-instance, if two modules define
-<option>services.httpd.adminAddr</option>,
-<command>nixos-rebuild</command> will give an error:
-
-<screen>
-The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
-</screen>
-
-When that happens, it’s possible to force one definition take
-precedence over the others:
-
-<programlisting>
-services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
-</programlisting>
-
-</para>
-
-<para>When using multiple modules, you may need to access
-configuration values defined in other modules.  This is what the
-<varname>config</varname> function argument is for: it contains the
-complete, merged system configuration.  That is,
-<varname>config</varname> is the result of combining the
-configurations returned by every module<footnote><para>If you’re
-wondering how it’s possible that the (indirect)
-<emphasis>result</emphasis> of a function is passed as an
-<emphasis>input</emphasis> to that same function: that’s because Nix
-is a “lazy” language — it only computes values when they are needed.
-This works as long as no individual configuration value depends on
-itself.</para></footnote>.  For example, here is a module that adds
-some packages to <option>environment.systemPackages</option> only if
-<option>services.xserver.enable</option> is set to
-<literal>true</literal> somewhere else:
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ environment.systemPackages =
-    if config.services.xserver.enable then
-      [ pkgs.firefox
-        pkgs.thunderbird
-      ]
-    else
-      [ ];
-}
-</programlisting>
-
-</para>
-
-<para>With multiple modules, it may not be obvious what the final
-value of a configuration option is.  The command
-<option>nixos-option</option> allows you to find out:
-
-<screen>
-$ nixos-option services.xserver.enable
-true
-
-$ nixos-option boot.kernelModules
-[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
-</screen>
-
-Interactive exploration of the configuration is possible using
-<command
-xlink:href="https://github.com/edolstra/nix-repl">nix-repl</command>,
-a read-eval-print loop for Nix expressions.  It’s not installed by
-default; run <literal>nix-env -i nix-repl</literal> to get it.  A
-typical use:
-
-<screen>
-$ nix-repl '&lt;nixos>'
-
-nix-repl> config.networking.hostName
-"mandark"
-
-nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
-[ "example.org" "example.gov" ]
-</screen>
-
-</para>
-
-</section>
-
-
-<section xml:id="sec-nix-syntax-summary"><title>Syntax summary</title>
-
-<para>Below is a summary of the most important syntactic constructs in
-the Nix expression language.  It’s not complete.  In particular, there
-are many other built-in functions.  See the <link
-xlink:href="http://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
-manual</link> for the rest.</para>
-
-<informaltable frame='none'>
-  <tgroup cols='2'>
-    <colspec colname='c1' rowsep='1' colsep='1' />
-    <colspec colname='c2' rowsep='1' />
-    <thead>
-      <row>
-        <entry>Example</entry>
-        <entry>Description</entry>
-      </row>
-    </thead>
-    <tbody>
-
-      <row>
-        <entry namest="c1" nameend="c2"><emphasis>Basic values</emphasis></entry>
-      </row>
-      <row>
-        <entry><literal>"Hello world"</literal></entry>
-        <entry>A string</entry>
-      </row>
-      <row>
-        <entry><literal>"${pkgs.bash}/bin/sh"</literal></entry>
-        <entry>A string containing an expression (expands to <literal>"/nix/store/<replaceable>hash</replaceable>-bash-<replaceable>version</replaceable>/bin/sh"</literal>)</entry>
-      </row>
-      <row>
-        <entry><literal>true</literal>, <literal>false</literal></entry>
-        <entry>Booleans</entry>
-      </row>
-      <row>
-        <entry><literal>123</literal></entry>
-        <entry>An integer</entry>
-      </row>
-      <row>
-        <entry><literal>./foo.png</literal></entry>
-        <entry>A path (relative to the containing Nix expression)</entry>
-      </row>
-
-      <row>
-        <entry namest="c1" nameend="c2"><emphasis>Compound values</emphasis></entry>
-      </row>
-      <row>
-        <entry><literal>{ x = 1; y = 2; }</literal></entry>
-        <entry>An set with attributes names <literal>x</literal> and <literal>y</literal></entry>
-      </row>
-      <row>
-        <entry><literal>{ foo.bar = 1; }</literal></entry>
-        <entry>A nested set, equivalent to <literal>{ foo = { bar = 1; }; }</literal></entry>
-      </row>
-      <row>
-        <entry><literal>rec { x = "bla"; y = x + "bar"; }</literal></entry>
-        <entry>A recursive set, equivalent to <literal>{ x = "foo"; y = "foobar"; }</literal></entry>
-      </row>
-      <row>
-        <entry><literal>[ "foo" "bar" ]</literal></entry>
-        <entry>A list with two elements</entry>
-      </row>
-
-      <row>
-        <entry namest="c1" nameend="c2"><emphasis>Operators</emphasis></entry>
-      </row>
-      <row>
-        <entry><literal>"foo" + "bar"</literal></entry>
-        <entry>String concatenation</entry>
-      </row>
-      <row>
-        <entry><literal>1 + 2</literal></entry>
-        <entry>Integer addition</entry>
-      </row>
-      <row>
-        <entry><literal>"foo" == "f" + "oo"</literal></entry>
-        <entry>Equality test (evaluates to <literal>true</literal>)</entry>
-      </row>
-      <row>
-        <entry><literal>"foo" != "bar"</literal></entry>
-        <entry>Inequality test (evaluates to <literal>true</literal>)</entry>
-      </row>
-      <row>
-        <entry><literal>!true</literal></entry>
-        <entry>Boolean negation</entry>
-      </row>
-      <row>
-        <entry><literal>{ x = 1; y = 2; }.x</literal></entry>
-        <entry>Attribute selection (evaluates to <literal>1</literal>)</entry>
-      </row>
-      <row>
-        <entry><literal>{ x = 1; y = 2; }.z or 3</literal></entry>
-        <entry>Attribute selection with default (evaluates to <literal>3</literal>)</entry>
-      </row>
-      <row>
-        <entry><literal>{ x = 1; y = 2; } // { z = 3; }</literal></entry>
-        <entry>Merge two sets (attributes in the right-hand set taking precedence)</entry>
-      </row>
-
-      <row>
-        <entry namest="c1" nameend="c2"><emphasis>Control structures</emphasis></entry>
-      </row>
-      <row>
-        <entry><literal>if 1 + 1 == 2 then "yes!" else "no!"</literal></entry>
-        <entry>Conditional expression</entry>
-      </row>
-      <row>
-        <entry><literal>assert 1 + 1 == 2; "yes!"</literal></entry>
-        <entry>Assertion check (evaluates to <literal>"yes!"</literal>)</entry>
-      </row>
-      <row>
-        <entry><literal>let x = "foo"; y = "bar"; in x + y</literal></entry>
-        <entry>Variable definition</entry>
-      </row>
-      <row>
-        <entry><literal>with pkgs.lib; head [ 1 2 3 ]</literal></entry>
-        <entry>Add all attributes from the given set to the scope
-        (evaluates to <literal>1</literal>)</entry>
-      </row>
-
-      <row>
-        <entry namest="c1" nameend="c2"><emphasis>Functions (lambdas)</emphasis></entry>
-      </row>
-      <row>
-        <entry><literal>x: x + 1</literal></entry>
-        <entry>A function that expects an integer and returns it increased by 1</entry>
-      </row>
-      <row>
-        <entry><literal>(x: x + 1) 100</literal></entry>
-        <entry>A function call (evaluates to 101)</entry>
-      </row>
-      <row>
-        <entry><literal>let inc = x: x + 1; in inc (inc (inc 100))</literal></entry>
-        <entry>A function bound to a variable and subsequently called by name (evaluates to 103)</entry>
-      </row>
-      <row>
-        <entry><literal>{ x, y }: x + y</literal></entry>
-        <entry>A function that expects a set with required attributes
-        <literal>x</literal> and <literal>y</literal> and concatenates
-        them</entry>
-      </row>
-      <row>
-        <entry><literal>{ x, y ? "bar" }: x + y</literal></entry>
-        <entry>A function that expects a set with required attribute
-        <literal>x</literal> and optional <literal>y</literal>, using
-        <literal>"bar"</literal> as default value for
-        <literal>y</literal></entry>
-      </row>
-      <row>
-        <entry><literal>{ x, y, ... }: x + y</literal></entry>
-        <entry>A function that expects a set with required attributes
-        <literal>x</literal> and <literal>y</literal> and ignores any
-        other attributes</entry>
-      </row>
-      <row>
-        <entry><literal>{ x, y } @ args: x + y</literal></entry>
-        <entry>A function that expects a set with required attributes
-        <literal>x</literal> and <literal>y</literal>, and binds the
-        whole set to <literal>args</literal></entry>
-      </row>
-
-      <row>
-        <entry namest="c1" nameend="c2"><emphasis>Built-in functions</emphasis></entry>
-      </row>
-      <row>
-        <entry><literal>import ./foo.nix</literal></entry>
-        <entry>Load and return Nix expression in given file</entry>
-      </row>
-      <row>
-        <entry><literal>map (x: x + x) [ 1 2 3 ]</literal></entry>
-        <entry>Apply a function to every element of a list (evaluates to <literal>[ 2 4 6 ]</literal>)</entry>
-      </row>
-      <!--
-      <row>
-        <entry><literal>throw "Urgh"</literal></entry>
-        <entry>Raise an error condition</entry>
-      </row>
-      -->
-
-    </tbody>
-  </tgroup>
-</informaltable>
-
-</section>
-
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-package-management"><title>Package management</title>
-
-<para>This section describes how to add additional packages to your
-system.  NixOS has two distinct styles of package management:
-
-<itemizedlist>
-
-  <listitem><para><emphasis>Declarative</emphasis>, where you declare
-  what packages you want in your
-  <filename>configuration.nix</filename>.  Every time you run
-  <command>nixos-rebuild</command>, NixOS will ensure that you get a
-  consistent set of binaries corresponding to your
-  specification.</para></listitem>
-
-  <listitem><para><emphasis>Ad hoc</emphasis>, where you install,
-  upgrade and uninstall packages via the <command>nix-env</command>
-  command.  This style allows mixing packages from different Nixpkgs
-  versions.  It’s the only choice for non-root
-  users.</para></listitem>
-
-</itemizedlist>
-
-</para>
-
-<para>The next two sections describe these two styles.</para>
-
-
-<section><title>Declarative package management</title>
-
-<para>With declarative package management, you specify which packages
-you want on your system by setting the option
-<option>environment.systemPackages</option>.  For instance, adding the
-following line to <filename>configuration.nix</filename> enables the
-Mozilla Thunderbird email application:
-
-<programlisting>
-environment.systemPackages = [ pkgs.thunderbird ];
-</programlisting>
-
-The effect of this specification is that the Thunderbird package from
-Nixpkgs will be built or downloaded as part of the system when you run
-<command>nixos-rebuild switch</command>.</para>
-
-<para>You can get a list of the available packages as follows:
-<screen>
-$ nix-env -qaP '*' --description
-nixos.pkgs.firefox   firefox-23.0   Mozilla Firefox - the browser, reloaded
-<replaceable>...</replaceable>
-</screen>
-
-The first column in the output is the <emphasis>attribute
-name</emphasis>, such as
-<literal>nixos.pkgs.thunderbird</literal>. (The
-<literal>nixos</literal> prefix allows distinguishing between
-different channels that you might have.)</para>
-
-<para>To “uninstall” a package, simply remove it from
-<option>environment.systemPackages</option> and run
-<command>nixos-rebuild switch</command>.</para>
-
-
-<section xml:id="sec-customising-packages"><title>Customising packages</title>
-
-<para>Some packages in Nixpkgs have options to enable or disable
-optional functionality or change other aspects of the package.  For
-instance, the Firefox wrapper package (which provides Firefox with a
-set of plugins such as the Adobe Flash player) has an option to enable
-the Google Talk plugin.  It can be set in
-<filename>configuration.nix</filename> as follows:
-
-<filename>
-nixpkgs.config.firefox.enableGoogleTalkPlugin = true;
-</filename>
-</para>
-
-<warning><para>Unfortunately, Nixpkgs currently lacks a way to query
-available configuration options.</para></warning>
-
-<para>Apart from high-level options, it’s possible to tweak a package
-in almost arbitrary ways, such as changing or disabling dependencies
-of a package.  For instance, the Emacs package in Nixpkgs by default
-has a dependency on GTK+ 2.  If you want to build it against GTK+ 3,
-you can specify that as follows:
-
-<programlisting>
-environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
-</programlisting>
-
-The function <varname>override</varname> performs the call to the Nix
-function that produces Emacs, with the original arguments amended by
-the set of arguments specified by you.  So here the function argument
-<varname>gtk</varname> gets the value <literal>pkgs.gtk3</literal>,
-causing Emacs to depend on GTK+ 3.  (The parentheses are necessary
-because in Nix, function application binds more weakly than list
-construction, so without them,
-<literal>environment.systemPackages</literal> would be a list with two
-elements.)</para>
-
-<para>Even greater customisation is possible using the function
-<varname>overrideDerivation</varname>.  While the
-<varname>override</varname> mechanism above overrides the arguments of
-a package function, <varname>overrideDerivation</varname> allows
-changing the <emphasis>result</emphasis> of the function.  This
-permits changing any aspect of the package, such as the source code.
-For instance, if you want to override the source code of Emacs, you
-can say:
-
-<programlisting>
-environment.systemPackages =
-  [ (pkgs.lib.overrideDerivation pkgs.emacs (attrs: {
-      name = "emacs-25.0-pre";
-      src = /path/to/my/emacs/tree;
-    }))
-  ];
-</programlisting>
-
-Here, <varname>overrideDerivation</varname> takes the Nix derivation
-specified by <varname>pkgs.emacs</varname> and produces a new
-derivation in which the original’s <literal>name</literal> and
-<literal>src</literal> attribute have been replaced by the given
-values.  The original attributes are accessible via
-<varname>attrs</varname>.</para>
-
-<para>The overrides shown above are not global.  They do not affect
-the original package; other packages in Nixpkgs continue to depend on
-the original rather than the customised package.  This means that if
-another package in your system depends on the original package, you
-end up with two instances of the package.  If you want to have
-everything depend on your customised instance, you can apply a
-<emphasis>global</emphasis> override as follows:
-
-<screen>
-nixpkgs.config.packageOverrides = pkgs:
-  { emacs = pkgs.emacs.override { gtk = pkgs.gtk3; };
-  };
-</screen>
-
-The effect of this definition is essentially equivalent to modifying
-the <literal>emacs</literal> attribute in the Nixpkgs source tree.
-Any package in Nixpkgs that depends on <literal>emacs</literal> will
-be passed your customised instance.  (However, the value
-<literal>pkgs.emacs</literal> in
-<varname>nixpkgs.config.packageOverrides</varname> refers to the
-original rather than overridden instance, to prevent an infinite
-recursion.)</para>
-
-</section>
-
-<section xml:id="sec-custom-packages"><title>Adding custom packages</title>
-
-<para>It’s possible that a package you need is not available in NixOS.
-In that case, you can do two things.  First, you can clone the Nixpkgs
-repository, add the package to your clone, and (optionally) submit a
-patch or pull request to have it accepted into the main Nixpkgs
-repository.  This is described in detail in the <link
-xlink:href="http://nixos.org/nixpkgs/manual">Nixpkgs manual</link>.
-In short, you clone Nixpkgs:
-
-<screen>
-$ git clone git://github.com/NixOS/nixpkgs.git
-$ cd nixpkgs
-</screen>
-
-Then you write and test the package as described in the Nixpkgs
-manual.  Finally, you add it to
-<literal>environment.systemPackages</literal>, e.g.
-
-<programlisting>
-environment.systemPackages = [ pkgs.my-package ];
-</programlisting>
-
-and you run <command>nixos-rebuild</command>, specifying your own
-Nixpkgs tree:
-
-<screen>
-$ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen>
-
-</para>
-
-<para>The second possibility is to add the package outside of the
-Nixpkgs tree.  For instance, here is how you specify a build of the
-<link xlink:href="http://www.gnu.org/software/hello/">GNU Hello</link>
-package directly in <filename>configuration.nix</filename>:
-
-<programlisting>
-environment.systemPackages =
-  let
-    my-hello = with pkgs; stdenv.mkDerivation rec {
-      name = "hello-2.8";
-      src = fetchurl {
-        url = "mirror://gnu/hello/${name}.tar.gz";
-        sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
-      };
-    };
-  in
-  [ my-hello ];
-</programlisting>
-
-Of course, you can also move the definition of
-<literal>my-hello</literal> into a separate Nix expression, e.g.
-<programlisting>
-environment.systemPackages = [ (import ./my-hello.nix) ];
-</programlisting>
-where <filename>my-hello.nix</filename> contains:
-<programlisting>
-with import &lt;nixpkgs> {}; # bring all of Nixpkgs into scope
-
-stdenv.mkDerivation rec {
-  name = "hello-2.8";
-  src = fetchurl {
-    url = "mirror://gnu/hello/${name}.tar.gz";
-    sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
-  };
-}
-</programlisting>
-
-This allows testing the package easily:
-<screen>
-$ nix-build my-hello.nix
-$ ./result/bin/hello
-Hello, world!
-</screen>
-
-</para>
-
-</section>
-
-</section>
-
-
-<section><title>Ad hoc package management</title>
-
-<para>With the command <command>nix-env</command>, you can install and
-uninstall packages from the command line.  For instance, to install
-Mozilla Thunderbird:
-
-<screen>
-$ nix-env -iA nixos.pkgs.thunderbird</screen>
-
-If you invoke this as root, the package is installed in the Nix
-profile <filename>/nix/var/nix/profiles/default</filename> and visible
-to all users of the system; otherwise, the package ends up in
-<filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/profile</filename>
-and is not visible to other users.  The <option>-A</option> flag
-specifies the package by its attribute name; without it, the package
-is installed by matching against its package name
-(e.g. <literal>thunderbird</literal>).  The latter is slower because
-it requires matching against all available Nix packages, and is
-ambiguous if there are multiple matching packages.</para>
-
-<para>Packages come from the NixOS channel.  You typically upgrade a
-package by updating to the latest version of the NixOS channel:
-<screen>
-$ nix-channel --update nixos
-</screen>
-and then running <literal>nix-env -i</literal> again.  Other packages
-in the profile are <emphasis>not</emphasis> affected; this is the
-crucial difference with the declarative style of package management,
-where running <command>nixos-rebuild switch</command> causes all
-packages to be updated to their current versions in the NixOS channel.
-You can however upgrade all packages for which there is a newer
-version by doing:
-<screen>
-$ nix-env -u '*'
-</screen>
-</para>
-
-<para>A package can be uninstalled using the <option>-e</option>
-flag:
-<screen>
-$ nix-env -e thunderbird
-</screen>
-</para>
-
-<para>Finally, you can roll back an undesirable
-<command>nix-env</command> action:
-<screen>
-$ nix-env --rollback
-</screen>
-</para>
-
-<para><command>nix-env</command> has many more flags.  For details,
-see the
-<citerefentry><refentrytitle>nix-env</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-manpage or the Nix manual.</para>
-
-</section>
-
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-user-management"><title>User management</title>
-
-<para>NixOS supports both declarative and imperative styles of user
-management.  In the declarative style, users are specified in
-<filename>configuration.nix</filename>.  For instance, the following
-states that a user account named <literal>alice</literal> shall exist:
-
-<programlisting>
-users.extraUsers.alice =
-  { createHome = true;
-    home = "/home/alice";
-    description = "Alice Foobar";
-    extraGroups = [ "wheel" "networkmanager" ];
-    useDefaultShell = true;
-    openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
-  };
-</programlisting>
-
-Note that <literal>alice</literal> is a member of the
-<literal>wheel</literal> and <literal>networkmanager</literal> groups,
-which allows her to use <command>sudo</command> to execute commands as
-<literal>root</literal> and to configure the network, respectively.
-Also note the SSH public key that allows remote logins with the
-corresponding private key. Users created in this way do not have a
-password by default, so they cannot log in via mechanisms that require
-a password. However, you can use the <command>passwd</command> program
-to set a password, which is retained across invocations of
-<command>nixos-rebuild</command>.</para>
-
-<para>A user ID (uid) is assigned automatically.  You can also specify
-a uid manually by adding
-
-<programlisting>
-    uid = 1000;
-</programlisting>
-
-to the user specification.</para>
-
-<para>Groups can be specified similarly.  The following states that a
-group named <literal>students</literal> shall exist:
-
-<programlisting>
-users.extraGroups.students.gid = 1000;
-</programlisting>
-
-As with users, the group ID (gid) is optional and will be assigned
-automatically if it’s missing.</para>
-
-<warning><para>Currently declarative user management is not perfect:
-<command>nixos-rebuild</command> does not know how to realise certain
-configuration changes.  This includes removing a user or group, and
-removing group membership from a user.</para></warning>
-
-<para>In the imperative style, users and groups are managed by
-commands such as <command>useradd</command>,
-<command>groupmod</command> and so on.  For instance, to create a user
-account named <literal>alice</literal>:
-
-<screen>
-$ useradd -m alice</screen>
-
-The flag <option>-m</option> causes the creation of a home directory
-for the new user, which is generally what you want.  The user does not
-have an initial password and therefore cannot log in.  A password can
-be set using the <command>passwd</command> utility:
-
-<screen>
-$ passwd alice
-Enter new UNIX password: ***
-Retype new UNIX password: ***
-</screen>
-
-A user can be deleted using <command>userdel</command>:
-
-<screen>
-$ userdel -r alice</screen>
-
-The flag <option>-r</option> deletes the user’s home directory.
-Accounts can be modified using <command>usermod</command>.  Unix
-groups can be managed using <command>groupadd</command>,
-<command>groupmod</command> and <command>groupdel</command>.</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section><title>File systems</title>
-
-<para>You can define file systems using the
-<option>fileSystems</option> configuration option.  For instance, the
-following definition causes NixOS to mount the Ext4 file system on
-device <filename>/dev/disk/by-label/data</filename> onto the mount
-point <filename>/data</filename>:
-
-<programlisting>
-fileSystems."/data" =
-  { device = "/dev/disk/by-label/data";
-    fsType = "ext4";
-  };
-</programlisting>
-
-Mount points are created automatically if they don’t already exist.
-For <option>device</option>, it’s best to use the topology-independent
-device aliases in <filename>/dev/disk/by-label</filename> and
-<filename>/dev/disk/by-uuid</filename>, as these don’t change if the
-topology changes (e.g. if a disk is moved to another IDE
-controller).</para>
-
-<para>You can usually omit the file system type
-(<option>fsType</option>), since <command>mount</command> can usually
-detect the type and load the necessary kernel module automatically.
-However, if the file system is needed at early boot (in the initial
-ramdisk) and is not <literal>ext2</literal>, <literal>ext3</literal>
-or <literal>ext4</literal>, then it’s best to specify
-<option>fsType</option> to ensure that the kernel module is
-available.</para>
-
-<section><title>LUKS-encrypted file systems</title>
-
-<para>NixOS supports file systems that are encrypted using
-<emphasis>LUKS</emphasis> (Linux Unified Key Setup).  For example,
-here is how you create an encrypted Ext4 file system on the device
-<filename>/dev/sda2</filename>:
-
-<screen>
-$ cryptsetup luksFormat /dev/sda2
-
-WARNING!
-========
-This will overwrite data on /dev/sda2 irrevocably.
-
-Are you sure? (Type uppercase yes): YES
-Enter LUKS passphrase: ***
-Verify passphrase: ***
-
-$ cryptsetup luksOpen /dev/sda2 crypted
-Enter passphrase for /dev/sda2: ***
-
-$ mkfs.ext4 /dev/mapper/crypted
-</screen>
-
-To ensure that this file system is automatically mounted at boot time
-as <filename>/</filename>, add the following to
-<filename>configuration.nix</filename>:
-
-<programlisting>
-boot.initrd.luks.devices = [ { device = "/dev/sda2"; name = "crypted"; } ];
-fileSystems."/".device = "/dev/mapper/crypted";
-</programlisting>
-
-</para>
-
-</section>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-x11"><title>X Window System</title>
-
-<para>The X Window System (X11) provides the basis of NixOS’ graphical
-user interface.  It can be enabled as follows:
-<programlisting>
-services.xserver.enable = true;
-</programlisting>
-The X server will automatically detect and use the appropriate video
-driver from a set of X.org drivers (such as <literal>vesa</literal>
-and <literal>intel</literal>).  You can also specify a driver
-manually, e.g.
-<programlisting>
-services.xserver.videoDrivers = [ "r128" ];
-</programlisting>
-to enable X.org’s <literal>xf86-video-r128</literal> driver.</para>
-
-<para>You also need to enable at least one desktop or window manager.
-Otherwise, you can only log into a plain undecorated
-<command>xterm</command> window.  Thus you should pick one or more of
-the following lines:
-<programlisting>
-services.xserver.desktopManager.kde4.enable = true;
-services.xserver.desktopManager.xfce.enable = true;
-services.xserver.windowManager.xmonad.enable = true;
-services.xserver.windowManager.twm.enable = true;
-services.xserver.windowManager.icewm.enable = true;
-</programlisting>
-</para>
-
-<para>NixOS’s default <emphasis>display manager</emphasis> (the
-program that provides a graphical login prompt and manages the X
-server) is SLiM.  You can select KDE’s <command>kdm</command> instead:
-<programlisting>
-services.xserver.displayManager.kdm.enable = true;
-</programlisting>
-</para>
-
-<para>The X server is started automatically at boot time.  If you
-don’t want this to happen, you can set:
-<programlisting>
-services.xserver.autorun = false;
-</programlisting>
-The X server can then be started manually:
-<screen>
-$ systemctl start display-manager.service
-</screen>
-</para>
-
-
-<section><title>NVIDIA graphics cards</title>
-
-<para>NVIDIA provides a proprietary driver for its graphics cards that
-has better 3D performance than the X.org drivers.  It is not enabled
-by default because it’s not free software.  You can enable it as follows:
-<programlisting>
-services.xserver.videoDrivers = [ "nvidia" ];
-</programlisting>
-You may need to reboot after enabling this driver to prevent a clash
-with other kernel modules.</para>
-
-<para>On 64-bit systems, if you want full acceleration for 32-bit
-programs such as Wine, you should also set the following:
-<programlisting>
-services.xserver.driSupport32Bit = true;
-</programlisting>
-</para>
-
-</section>
-
-
-<section><title>Touchpads</title>
-
-<para>Support for Synaptics touchpads (found in many laptops such as
-the Dell Latitude series) can be enabled as follows:
-<programlisting>
-services.xserver.synaptics.enable = true;
-</programlisting>
-The driver has many options (see <xref linkend="ch-options"/>).  For
-instance, the following enables two-finger scrolling:
-<programlisting>
-services.xserver.synaptics.twoFingerScroll = true;
-</programlisting>
-</para>
-
-</section>
-
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-networking"><title>Networking</title>
-
-<section xml:id="sec-networkmanager"><title>NetworkManager</title>
-
-<para>To facilitate network configuration, some desktop environments
-use NetworkManager. You can enable NetworkManager by setting:
-
-<programlisting>
-services.networkmanager.enable = true;
-</programlisting>
-
-Some desktop managers (e.g., GNOME) enable NetworkManager
-automatically for you.</para>
-
-<para>All users that should have permission to change network settings
-must belong to the <code>networkmanager</code> group.</para>
-
-<note><para><code>services.networkmanager</code> and
-<code>services.wireless</code> can not be enabled at the same time:
-you can still connect to the wireless networks using
-NetworkManager.</para></note>
-
-</section>
-
-<section xml:id="sec-ssh"><title>Secure shell access</title>
-
-<para>Secure shell (SSH) access to your machine can be enabled by
-setting:
-
-<programlisting>
-services.openssh.enable = true;
-</programlisting>
-
-By default, root logins using a password are disallowed.  They can be
-disabled entirely by setting
-<literal>services.openssh.permitRootLogin</literal> to
-<literal>"no"</literal>.</para>
-
-<para>You can declaratively specify authorised RSA/DSA public keys for
-a user as follows:
-
-<!-- FIXME: this might not work if the user is unmanaged. -->
-<programlisting>
-users.extraUsers.alice.openssh.authorizedKeys.keys =
-  [ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
-</programlisting>
-
-</para>
-
-</section>
-
-
-<section xml:id="sec-ipv4"><title>IPv4 configuration</title>
-
-<para>By default, NixOS uses DHCP (specifically,
-<command>dhcpcd</command>) to automatically configure network
-interfaces.  However, you can configure an interface manually as
-follows:
-
-<programlisting>
-networking.interfaces.eth0 = { ipAddress = "192.168.1.2"; prefixLength = 24; };
-</programlisting>
-
-(The network prefix can also be specified using the option
-<literal>subnetMask</literal>,
-e.g. <literal>"255.255.255.0"</literal>, but this is deprecated.)
-Typically you’ll also want to set a default gateway and set of name
-servers:
-
-<programlisting>
-networking.defaultGateway = "192.168.1.1";
-networking.nameservers = [ "8.8.8.8" ];
-</programlisting>
-
-</para>
-
-<note><para>Statically configured interfaces are set up by the systemd
-service
-<replaceable>interface-name</replaceable><literal>-cfg.service</literal>.
-The default gateway and name server configuration is performed by
-<literal>network-setup.service</literal>.</para></note>
-
-<para>The host name is set using <option>networking.hostName</option>:
-
-<programlisting>
-networking.hostName = "cartman";
-</programlisting>
-
-The default host name is <literal>nixos</literal>.  Set it to the
-empty string (<literal>""</literal>) to allow the DHCP server to
-provide the host name.</para>
-
-</section>
-
-
-<section xml:id="sec-ipv6"><title>IPv6 configuration</title>
-
-<para>IPv6 is enabled by default.  Stateless address autoconfiguration
-is used to automatically assign IPv6 addresses to all interfaces.  You
-can disable IPv6 support globally by setting:
-
-<programlisting>
-networking.enableIPv6 = false;
-</programlisting>
-
-</para>
-
-</section>
-
-
-<section xml:id="sec-firewall"><title>Firewall</title>
-
-<para>NixOS has a simple stateful firewall that blocks incoming
-connections and other unexpected packets.  The firewall applies to
-both IPv4 and IPv6 traffic. It is enabled by default. It can be
-disabled as follows:
-
-<programlisting>
-networking.firewall.enable = false;
-</programlisting>
-
-If the firewall is enabled, you can open specific TCP ports to the
-outside world:
-
-<programlisting>
-networking.firewall.allowedTCPPorts = [ 80 443 ];
-</programlisting>
-
-Note that TCP port 22 (ssh) is opened automatically if the SSH daemon
-is enabled (<option>services.openssh.enable = true</option>).  UDP
-ports can be opened through
-<option>networking.firewall.allowedUDPPorts</option>.  Also of
-interest is
-
-<programlisting>
-networking.firewall.allowPing = true;
-</programlisting>
-
-to allow the machine to respond to ping requests.  (ICMPv6 pings are
-always allowed.)</para>
-
-</section>
-
-
-<section xml:id="sec-wireless"><title>Wireless networks</title>
-
-<para>For a desktop installation using NetworkManager (e.g., GNOME),
-you just have to make sure the user is in the
-<code>networkmanager</code> group and you can skip the rest of this
-section on wireless networks.</para>
-
-<para>
-NixOS will start wpa_supplicant for you if you enable this setting:
-
-<programlisting>
-networking.wireless.enable = true;
-</programlisting>
-
-NixOS currently does not generate wpa_supplicant's
-configuration file, <literal>/etc/wpa_supplicant.conf</literal>. You should edit this file
-yourself to define wireless networks, WPA keys and so on (see
-wpa_supplicant.conf(5)).
-</para>
-
-<para>
-If you are using WPA2 the <command>wpa_passphrase</command> tool might be useful
-to generate the <literal>wpa_supplicant.conf</literal>.
-
-<screen>
-$ wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf</screen>
-
-After you have edited the <literal>wpa_supplicant.conf</literal>,
-you need to restart the wpa_supplicant service.
-
-<screen>
-$ systemctl restart wpa_supplicant.service</screen>
-</para>
-
-
-</section>
-
-
-<section><title>Ad-hoc configuration</title>
-
-<para>You can use <option>networking.localCommands</option> to specify
-shell commands to be run at the end of
-<literal>network-setup.service</literal>.  This is useful for doing
-network configuration not covered by the existing NixOS modules.  For
-instance, to statically configure an IPv6 address:
-
-<programlisting>
-networking.localCommands =
-  ''
-    ip -6 addr add 2001:610:685:1::1/64 dev eth0
-  '';
-</programlisting>
-
-</para>
-
-</section>
-
-
-<!-- TODO: OpenVPN, NAT -->
-
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-kernel-config"><title>Linux kernel</title>
-
-<para>You can override the Linux kernel and associated packages using
-the option <option>boot.kernelPackages</option>.  For instance, this
-selects the Linux 3.10 kernel:
-<programlisting>
-boot.kernelPackages = pkgs.linuxPackages_3_10;
-</programlisting>
-Note that this not only replaces the kernel, but also packages that
-are specific to the kernel version, such as the NVIDIA video drivers.
-This ensures that driver packages are consistent with the
-kernel.</para>
-
-<para>The default Linux kernel configuration should be fine for most users. You can see the configuration of your current kernel with the following command:
-<programlisting>
-cat /proc/config.gz | gunzip
-</programlisting>
-If you want to change the kernel configuration, you can use the
-<option>packageOverrides</option> feature (see <xref
-linkend="sec-customising-packages" />).  For instance, to enable
-support for the kernel debugger KGDB:
-
-<programlisting>
-nixpkgs.config.packageOverrides = pkgs:
-  { linux_3_4 = pkgs.linux_3_4.override {
-      extraConfig =
-        ''
-          KGDB y
-        '';
-    };
-  };
-</programlisting>
-
-<varname>extraConfig</varname> takes a list of Linux kernel
-configuration options, one per line.  The name of the option should
-not include the prefix <literal>CONFIG_</literal>.  The option value
-is typically <literal>y</literal>, <literal>n</literal> or
-<literal>m</literal> (to build something as a kernel module).</para>
-
-<para>Kernel modules for hardware devices are generally loaded
-automatically by <command>udev</command>.  You can force a module to
-be loaded via <option>boot.kernelModules</option>, e.g.
-<programlisting>
-boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
-</programlisting>
-If the module is required early during the boot (e.g. to mount the
-root file system), you can use
-<option>boot.initrd.extraKernelModules</option>:
-<programlisting>
-boot.initrd.extraKernelModules = [ "cifs" ];
-</programlisting>
-This causes the specified modules and their dependencies to be added
-to the initial ramdark.</para>
-
-<para>Kernel runtime parameters can be set through
-<option>boot.kernel.sysctl</option>, e.g.
-<programlisting>
-boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
-</programlisting>
-sets the kernel’s TCP keepalive time to 120 seconds.  To see the
-available parameters, run <command>sysctl -a</command>.</para>
-
-</section>
-
-
-<!-- Apache; libvirtd virtualisation -->
-
-
-</chapter>
diff --git a/nixos/doc/manual/configuration/abstractions.xml b/nixos/doc/manual/configuration/abstractions.xml
new file mode 100644
index 00000000000..cbd54bca62f
--- /dev/null
+++ b/nixos/doc/manual/configuration/abstractions.xml
@@ -0,0 +1,166 @@
+<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-module-abstractions">
+
+<title>Abstractions</title>
+
+<para>If you find yourself repeating yourself over and over, it’s time
+to abstract.  Take, for instance, this Apache HTTP Server configuration:
+
+<programlisting>
+{
+  services.httpd.virtualHosts =
+    [ { hostName = "example.org";
+        documentRoot = "/webroot";
+        adminAddr = "alice@example.org";
+        enableUserDir = true;
+      }
+      { hostName = "example.org";
+        documentRoot = "/webroot";
+        adminAddr = "alice@example.org";
+        enableUserDir = true;
+        enableSSL = true;
+        sslServerCert = "/root/ssl-example-org.crt";
+        sslServerKey = "/root/ssl-example-org.key";
+      }
+    ];
+}
+</programlisting>
+
+It defines two virtual hosts with nearly identical configuration; the
+only difference is that the second one has SSL enabled.  To prevent
+this duplication, we can use a <literal>let</literal>:
+
+<programlisting>
+let
+  exampleOrgCommon =
+    { hostName = "example.org";
+      documentRoot = "/webroot";
+      adminAddr = "alice@example.org";
+      enableUserDir = true;
+    };
+in
+{
+  services.httpd.virtualHosts =
+    [ exampleOrgCommon
+      (exampleOrgCommon // {
+        enableSSL = true;
+        sslServerCert = "/root/ssl-example-org.crt";
+        sslServerKey = "/root/ssl-example-org.key";
+      })
+    ];
+}
+</programlisting>
+
+The <literal>let exampleOrgCommon =
+<replaceable>...</replaceable></literal> defines a variable named
+<literal>exampleOrgCommon</literal>.  The <literal>//</literal>
+operator merges two attribute sets, so the configuration of the second
+virtual host is the set <literal>exampleOrgCommon</literal> extended
+with the SSL options.</para>
+
+<para>You can write a <literal>let</literal> wherever an expression is
+allowed.  Thus, you also could have written:
+
+<programlisting>
+{
+  services.httpd.virtualHosts =
+    let exampleOrgCommon = <replaceable>...</replaceable>; in
+    [ exampleOrgCommon
+      (exampleOrgCommon // { <replaceable>...</replaceable> })
+    ];
+}
+</programlisting>
+
+but not <literal>{ let exampleOrgCommon =
+<replaceable>...</replaceable>; in <replaceable>...</replaceable>;
+}</literal> since attributes (as opposed to attribute values) are not
+expressions.</para>
+
+<para><emphasis>Functions</emphasis> provide another method of
+abstraction.  For instance, suppose that we want to generate lots of
+different virtual hosts, all with identical configuration except for
+the host name.  This can be done as follows:
+
+<programlisting>
+{
+  services.httpd.virtualHosts =
+    let
+      makeVirtualHost = name:
+        { hostName = name;
+          documentRoot = "/webroot";
+          adminAddr = "alice@example.org";
+        };
+    in
+      [ (makeVirtualHost "example.org")
+        (makeVirtualHost "example.com")
+        (makeVirtualHost "example.gov")
+        (makeVirtualHost "example.nl")
+      ];
+}
+</programlisting>
+
+Here, <varname>makeVirtualHost</varname> is a function that takes a
+single argument <literal>name</literal> and returns the configuration
+for a virtual host.  That function is then called for several names to
+produce the list of virtual host configurations.</para>
+
+<para>We can further improve on this by using the function
+<varname>map</varname>, which applies another function to every
+element in a list:
+
+<programlisting>
+{
+  services.httpd.virtualHosts =
+    let
+      makeVirtualHost = <replaceable>...</replaceable>;
+    in map makeVirtualHost
+      [ "example.org" "example.com" "example.gov" "example.nl" ];
+}
+</programlisting>
+
+(The function <literal>map</literal> is called a
+<emphasis>higher-order function</emphasis> because it takes another
+function as an argument.)</para>
+
+<para>What if you need more than one argument, for instance, if we
+want to use a different <literal>documentRoot</literal> for each
+virtual host?  Then we can make <varname>makeVirtualHost</varname> a
+function that takes a <emphasis>set</emphasis> as its argument, like this:
+
+<programlisting>
+{
+  services.httpd.virtualHosts =
+    let
+      makeVirtualHost = { name, root }:
+        { hostName = name;
+          documentRoot = root;
+          adminAddr = "alice@example.org";
+        };
+    in map makeVirtualHost
+      [ { name = "example.org"; root = "/sites/example.org"; }
+        { name = "example.com"; root = "/sites/example.com"; }
+        { name = "example.gov"; root = "/sites/example.gov"; }
+        { name = "example.nl"; root = "/sites/example.nl"; }
+      ];
+}
+</programlisting>
+
+But in this case (where every root is a subdirectory of
+<filename>/sites</filename> named after the virtual host), it would
+have been shorter to define <varname>makeVirtualHost</varname> as
+<programlisting>
+makeVirtualHost = name:
+  { hostName = name;
+    documentRoot = "/sites/${name}";
+    adminAddr = "alice@example.org";
+  };
+</programlisting>
+
+Here, the construct
+<literal>${<replaceable>...</replaceable>}</literal> allows the result
+of an expression to be spliced into a string.</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/ad-hoc-network-config.xml b/nixos/doc/manual/configuration/ad-hoc-network-config.xml
new file mode 100644
index 00000000000..26a572ba1fb
--- /dev/null
+++ b/nixos/doc/manual/configuration/ad-hoc-network-config.xml
@@ -0,0 +1,24 @@
+<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="ad-hoc-network-config">
+
+<title>Ad-Hoc Configuration</title>
+
+<para>You can use <option>networking.localCommands</option> to specify
+shell commands to be run at the end of
+<literal>network-setup.service</literal>.  This is useful for doing
+network configuration not covered by the existing NixOS modules.  For
+instance, to statically configure an IPv6 address:
+
+<programlisting>
+networking.localCommands =
+  ''
+    ip -6 addr add 2001:610:685:1::1/64 dev eth0
+  '';
+</programlisting>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/ad-hoc-packages.xml b/nixos/doc/manual/configuration/ad-hoc-packages.xml
new file mode 100644
index 00000000000..e237e20c4ff
--- /dev/null
+++ b/nixos/doc/manual/configuration/ad-hoc-packages.xml
@@ -0,0 +1,63 @@
+<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-ad-hoc-packages">
+
+<title>Ad-Hoc Package Management</title>
+
+<para>With the command <command>nix-env</command>, you can install and
+uninstall packages from the command line.  For instance, to install
+Mozilla Thunderbird:
+
+<screen>
+$ nix-env -iA nixos.pkgs.thunderbird</screen>
+
+If you invoke this as root, the package is installed in the Nix
+profile <filename>/nix/var/nix/profiles/default</filename> and visible
+to all users of the system; otherwise, the package ends up in
+<filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/profile</filename>
+and is not visible to other users.  The <option>-A</option> flag
+specifies the package by its attribute name; without it, the package
+is installed by matching against its package name
+(e.g. <literal>thunderbird</literal>).  The latter is slower because
+it requires matching against all available Nix packages, and is
+ambiguous if there are multiple matching packages.</para>
+
+<para>Packages come from the NixOS channel.  You typically upgrade a
+package by updating to the latest version of the NixOS channel:
+<screen>
+$ nix-channel --update nixos
+</screen>
+and then running <literal>nix-env -i</literal> again.  Other packages
+in the profile are <emphasis>not</emphasis> affected; this is the
+crucial difference with the declarative style of package management,
+where running <command>nixos-rebuild switch</command> causes all
+packages to be updated to their current versions in the NixOS channel.
+You can however upgrade all packages for which there is a newer
+version by doing:
+<screen>
+$ nix-env -u '*'
+</screen>
+</para>
+
+<para>A package can be uninstalled using the <option>-e</option>
+flag:
+<screen>
+$ nix-env -e thunderbird
+</screen>
+</para>
+
+<para>Finally, you can roll back an undesirable
+<command>nix-env</command> action:
+<screen>
+$ nix-env --rollback
+</screen>
+</para>
+
+<para><command>nix-env</command> has many more flags.  For details,
+see the
+<citerefentry><refentrytitle>nix-env</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+manpage or the Nix manual.</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/adding-custom-packages.xml b/nixos/doc/manual/configuration/adding-custom-packages.xml
new file mode 100644
index 00000000000..c1789fcbc04
--- /dev/null
+++ b/nixos/doc/manual/configuration/adding-custom-packages.xml
@@ -0,0 +1,84 @@
+<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-custom-packages">
+
+<title>Adding Custom Packages</title>
+
+<para>It’s possible that a package you need is not available in NixOS.
+In that case, you can do two things.  First, you can clone the Nixpkgs
+repository, add the package to your clone, and (optionally) submit a
+patch or pull request to have it accepted into the main Nixpkgs
+repository.  This is described in detail in the <link
+xlink:href="http://nixos.org/nixpkgs/manual">Nixpkgs manual</link>.
+In short, you clone Nixpkgs:
+
+<screen>
+$ git clone git://github.com/NixOS/nixpkgs.git
+$ cd nixpkgs
+</screen>
+
+Then you write and test the package as described in the Nixpkgs
+manual.  Finally, you add it to
+<literal>environment.systemPackages</literal>, e.g.
+
+<programlisting>
+environment.systemPackages = [ pkgs.my-package ];
+</programlisting>
+
+and you run <command>nixos-rebuild</command>, specifying your own
+Nixpkgs tree:
+
+<screen>
+$ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen>
+
+</para>
+
+<para>The second possibility is to add the package outside of the
+Nixpkgs tree.  For instance, here is how you specify a build of the
+<link xlink:href="http://www.gnu.org/software/hello/">GNU Hello</link>
+package directly in <filename>configuration.nix</filename>:
+
+<programlisting>
+environment.systemPackages =
+  let
+    my-hello = with pkgs; stdenv.mkDerivation rec {
+      name = "hello-2.8";
+      src = fetchurl {
+        url = "mirror://gnu/hello/${name}.tar.gz";
+        sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
+      };
+    };
+  in
+  [ my-hello ];
+</programlisting>
+
+Of course, you can also move the definition of
+<literal>my-hello</literal> into a separate Nix expression, e.g.
+<programlisting>
+environment.systemPackages = [ (import ./my-hello.nix) ];
+</programlisting>
+where <filename>my-hello.nix</filename> contains:
+<programlisting>
+with import &lt;nixpkgs> {}; # bring all of Nixpkgs into scope
+
+stdenv.mkDerivation rec {
+  name = "hello-2.8";
+  src = fetchurl {
+    url = "mirror://gnu/hello/${name}.tar.gz";
+    sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
+  };
+}
+</programlisting>
+
+This allows testing the package easily:
+<screen>
+$ nix-build my-hello.nix
+$ ./result/bin/hello
+Hello, world!
+</screen>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/config-file.xml b/nixos/doc/manual/configuration/config-file.xml
new file mode 100644
index 00000000000..2a58ff25941
--- /dev/null
+++ b/nixos/doc/manual/configuration/config-file.xml
@@ -0,0 +1,213 @@
+<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-configuration-file">
+
+<title>NixOS Configuration File</title>
+
+<para>The NixOS configuration file generally looks like this:
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ <replaceable>option definitions</replaceable>
+}
+</programlisting>
+
+The first line (<literal>{ config, pkgs, ... }:</literal>) denotes
+that this is actually a function that takes at least the two arguments
+ <varname>config</varname> and <varname>pkgs</varname>.  (These are
+explained later.)  The function returns a <emphasis>set</emphasis> of
+option definitions (<literal>{ <replaceable>...</replaceable> }</literal>).  These definitions have the
+form <literal><replaceable>name</replaceable> =
+<replaceable>value</replaceable></literal>, where
+<replaceable>name</replaceable> is the name of an option and
+<replaceable>value</replaceable> is its value.  For example,
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ services.httpd.enable = true;
+  services.httpd.adminAddr = "alice@example.org";
+  services.httpd.documentRoot = "/webroot";
+}
+</programlisting>
+
+defines a configuration with three option definitions that together
+enable the Apache HTTP Server with <filename>/webroot</filename> as
+the document root.</para>
+
+<para>Sets can be nested, and in fact dots in option names are
+shorthand for defining a set containing another set.  For instance,
+<option>services.httpd.enable</option> defines a set named
+<varname>services</varname> that contains a set named
+<varname>httpd</varname>, which in turn contains an option definition
+named <varname>enable</varname> with value <literal>true</literal>.
+This means that the example above can also be written as:
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ services = {
+    httpd = {
+      enable = true;
+      adminAddr = "alice@example.org";
+      documentRoot = "/webroot";
+    };
+  };
+}
+</programlisting>
+
+which may be more convenient if you have lots of option definitions
+that share the same prefix (such as
+<literal>services.httpd</literal>).</para>
+
+<para>NixOS checks your option definitions for correctness.  For
+instance, if you try to define an option that doesn’t exist (that is,
+doesn’t have a corresponding <emphasis>option declaration</emphasis>),
+<command>nixos-rebuild</command> will give an error like:
+<screen>
+The option `services.httpd.enabl' defined in `/etc/nixos/configuration.nix' does not exist.
+</screen>
+Likewise, values in option definitions must have a correct type.  For
+instance, <option>services.httpd.enable</option> must be a Boolean
+(<literal>true</literal> or <literal>false</literal>).  Trying to give
+it a value of another type, such as a string, will cause an error:
+<screen>
+The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
+</screen>
+
+</para>
+
+<para>Options have various types of values.  The most important are:
+
+<variablelist>
+  <varlistentry>
+    <term>Strings</term>
+    <listitem>
+      <para>Strings are enclosed in double quotes, e.g.
+
+<programlisting>
+networking.hostName = "dexter";
+</programlisting>
+
+      Special characters can be escaped by prefixing them with a
+      backslash (e.g. <literal>\"</literal>).</para>
+
+      <para>Multi-line strings can be enclosed in <emphasis>double
+      single quotes</emphasis>, e.g.
+
+<programlisting>
+networking.extraHosts =
+  ''
+    127.0.0.2 other-localhost
+    10.0.0.1 server
+  '';
+</programlisting>
+
+      The main difference is that preceding whitespace is
+      automatically stripped from each line, and that characters like
+      <literal>"</literal> and <literal>\</literal> are not special
+      (making it more convenient for including things like shell
+      code).</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>Booleans</term>
+    <listitem>
+      <para>These can be <literal>true</literal> or
+      <literal>false</literal>, e.g.
+
+<programlisting>
+networking.firewall.enable = true;
+networking.firewall.allowPing = false;
+</programlisting>
+      </para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>Integers</term>
+    <listitem>
+      <para>For example,
+
+<programlisting>
+boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
+</programlisting>
+
+      (Note that here the attribute name
+      <literal>net.ipv4.tcp_keepalive_time</literal> is enclosed in
+      quotes to prevent it from being interpreted as a set named
+      <literal>net</literal> containing a set named
+      <literal>ipv4</literal>, and so on.  This is because it’s not a
+      NixOS option but the literal name of a Linux kernel
+      setting.)</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>Sets</term>
+    <listitem>
+      <para>Sets were introduced above.  They are name/value pairs
+      enclosed in braces, as in the option definition
+
+<programlisting>
+fileSystems."/boot" =
+  { device = "/dev/sda1";
+    fsType = "ext4";
+    options = "rw,data=ordered,relatime";
+  };
+</programlisting>
+      </para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>Lists</term>
+    <listitem>
+      <para>The important thing to note about lists is that list
+      elements are separated by whitespace, like this:
+
+<programlisting>
+boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
+</programlisting>
+
+      List elements can be any other type, e.g. sets:
+
+<programlisting>
+swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
+</programlisting>
+      </para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>Packages</term>
+    <listitem>
+      <para>Usually, the packages you need are already part of the Nix
+      Packages collection, which is a set that can be accessed through
+      the function argument <varname>pkgs</varname>.  Typical uses:
+
+<programlisting>
+environment.systemPackages =
+  [ pkgs.thunderbird
+    pkgs.emacs
+  ];
+
+postgresql.package = pkgs.postgresql90;
+</programlisting>
+
+      The latter option definition changes the default PostgreSQL
+      package used by NixOS’s PostgreSQL service to 9.0.  For more
+      information on packages, including how to add new ones, see
+      <xref linkend="sec-custom-packages"/>.</para>
+    </listitem>
+  </varlistentry>
+
+</variablelist>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/config-syntax.xml b/nixos/doc/manual/configuration/config-syntax.xml
new file mode 100644
index 00000000000..87847f8451e
--- /dev/null
+++ b/nixos/doc/manual/configuration/config-syntax.xml
@@ -0,0 +1,27 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-configuration-syntax">
+
+<title>Configuration Syntax</title>
+
+<para>The NixOS configuration file
+<filename>/etc/nixos/configuration.nix</filename> is actually a
+<emphasis>Nix expression</emphasis>, which is the Nix package
+manager’s purely functional language for describing how to build
+packages and configurations.  This means you have all the expressive
+power of that language at your disposal, including the ability to
+abstract over common patterns, which is very useful when managing
+complex systems.  The syntax and semantics of the Nix language are
+fully described in the <link
+xlink:href="http://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
+manual</link>, but here we give a short overview of the most important
+constructs useful in NixOS configuration files.</para>
+
+<xi:include href="config-file.xml" />
+<xi:include href="abstractions.xml" />
+<xi:include href="modularity.xml" />
+<xi:include href="summary.xml" />
+
+</chapter>
diff --git a/nixos/doc/manual/configuration/configuration.xml b/nixos/doc/manual/configuration/configuration.xml
new file mode 100644
index 00000000000..8fde0dc7e61
--- /dev/null
+++ b/nixos/doc/manual/configuration/configuration.xml
@@ -0,0 +1,32 @@
+<part 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="ch-configuration">
+
+<title>Configuration</title>
+
+<partintro>
+
+<para>This chapter describes how to configure various aspects of a
+NixOS machine through the configuration file
+<filename>/etc/nixos/configuration.nix</filename>.  As described in
+<xref linkend="sec-changing-config" />, changes to this file only take
+effect after you run <command>nixos-rebuild</command>.</para>
+
+</partintro>
+
+<xi:include href="config-syntax.xml" />
+<xi:include href="package-mgmt.xml" />
+<xi:include href="user-mgmt.xml" />
+<xi:include href="file-systems.xml" />
+<xi:include href="x-windows.xml" />
+<xi:include href="networking.xml" />
+<xi:include href="linux-kernel.xml" />
+
+<!-- FIXME: auto-include NixOS module docs -->
+<xi:include href="postgresql.xml" />
+
+<!-- Apache; libvirtd virtualisation -->
+
+</part>
diff --git a/nixos/doc/manual/configuration/customizing-packages.xml b/nixos/doc/manual/configuration/customizing-packages.xml
new file mode 100644
index 00000000000..6ee7a95dc6f
--- /dev/null
+++ b/nixos/doc/manual/configuration/customizing-packages.xml
@@ -0,0 +1,92 @@
+<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-customising-packages">
+
+<title>Customising Packages</title>
+
+<para>Some packages in Nixpkgs have options to enable or disable
+optional functionality or change other aspects of the package.  For
+instance, the Firefox wrapper package (which provides Firefox with a
+set of plugins such as the Adobe Flash player) has an option to enable
+the Google Talk plugin.  It can be set in
+<filename>configuration.nix</filename> as follows:
+
+<filename>
+nixpkgs.config.firefox.enableGoogleTalkPlugin = true;
+</filename>
+</para>
+
+<warning><para>Unfortunately, Nixpkgs currently lacks a way to query
+available configuration options.</para></warning>
+
+<para>Apart from high-level options, it’s possible to tweak a package
+in almost arbitrary ways, such as changing or disabling dependencies
+of a package.  For instance, the Emacs package in Nixpkgs by default
+has a dependency on GTK+ 2.  If you want to build it against GTK+ 3,
+you can specify that as follows:
+
+<programlisting>
+environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
+</programlisting>
+
+The function <varname>override</varname> performs the call to the Nix
+function that produces Emacs, with the original arguments amended by
+the set of arguments specified by you.  So here the function argument
+<varname>gtk</varname> gets the value <literal>pkgs.gtk3</literal>,
+causing Emacs to depend on GTK+ 3.  (The parentheses are necessary
+because in Nix, function application binds more weakly than list
+construction, so without them,
+<literal>environment.systemPackages</literal> would be a list with two
+elements.)</para>
+
+<para>Even greater customisation is possible using the function
+<varname>overrideDerivation</varname>.  While the
+<varname>override</varname> mechanism above overrides the arguments of
+a package function, <varname>overrideDerivation</varname> allows
+changing the <emphasis>result</emphasis> of the function.  This
+permits changing any aspect of the package, such as the source code.
+For instance, if you want to override the source code of Emacs, you
+can say:
+
+<programlisting>
+environment.systemPackages =
+  [ (pkgs.lib.overrideDerivation pkgs.emacs (attrs: {
+      name = "emacs-25.0-pre";
+      src = /path/to/my/emacs/tree;
+    }))
+  ];
+</programlisting>
+
+Here, <varname>overrideDerivation</varname> takes the Nix derivation
+specified by <varname>pkgs.emacs</varname> and produces a new
+derivation in which the original’s <literal>name</literal> and
+<literal>src</literal> attribute have been replaced by the given
+values.  The original attributes are accessible via
+<varname>attrs</varname>.</para>
+
+<para>The overrides shown above are not global.  They do not affect
+the original package; other packages in Nixpkgs continue to depend on
+the original rather than the customised package.  This means that if
+another package in your system depends on the original package, you
+end up with two instances of the package.  If you want to have
+everything depend on your customised instance, you can apply a
+<emphasis>global</emphasis> override as follows:
+
+<screen>
+nixpkgs.config.packageOverrides = pkgs:
+  { emacs = pkgs.emacs.override { gtk = pkgs.gtk3; };
+  };
+</screen>
+
+The effect of this definition is essentially equivalent to modifying
+the <literal>emacs</literal> attribute in the Nixpkgs source tree.
+Any package in Nixpkgs that depends on <literal>emacs</literal> will
+be passed your customised instance.  (However, the value
+<literal>pkgs.emacs</literal> in
+<varname>nixpkgs.config.packageOverrides</varname> refers to the
+original rather than overridden instance, to prevent an infinite
+recursion.)</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/declarative-packages.xml b/nixos/doc/manual/configuration/declarative-packages.xml
new file mode 100644
index 00000000000..6de38b452e2
--- /dev/null
+++ b/nixos/doc/manual/configuration/declarative-packages.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-declarative-package-mgmt">
+
+<title>Declarative Package Management</title>
+
+<para>With declarative package management, you specify which packages
+you want on your system by setting the option
+<option>environment.systemPackages</option>.  For instance, adding the
+following line to <filename>configuration.nix</filename> enables the
+Mozilla Thunderbird email application:
+
+<programlisting>
+environment.systemPackages = [ pkgs.thunderbird ];
+</programlisting>
+
+The effect of this specification is that the Thunderbird package from
+Nixpkgs will be built or downloaded as part of the system when you run
+<command>nixos-rebuild switch</command>.</para>
+
+<para>You can get a list of the available packages as follows:
+<screen>
+$ nix-env -qaP '*' --description
+nixos.pkgs.firefox   firefox-23.0   Mozilla Firefox - the browser, reloaded
+<replaceable>...</replaceable>
+</screen>
+
+The first column in the output is the <emphasis>attribute
+name</emphasis>, such as
+<literal>nixos.pkgs.thunderbird</literal>. (The
+<literal>nixos</literal> prefix allows distinguishing between
+different channels that you might have.)</para>
+
+<para>To “uninstall” a package, simply remove it from
+<option>environment.systemPackages</option> and run
+<command>nixos-rebuild switch</command>.</para>
+
+<xi:include href="customizing-packages.xml" />
+<xi:include href="adding-custom-packages.xml" />
+
+</section>
diff --git a/nixos/doc/manual/configuration/file-systems.xml b/nixos/doc/manual/configuration/file-systems.xml
new file mode 100644
index 00000000000..d1b324af3f1
--- /dev/null
+++ b/nixos/doc/manual/configuration/file-systems.xml
@@ -0,0 +1,40 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="ch-file-systems">
+
+<title>File Systems</title>
+
+<para>You can define file systems using the
+<option>fileSystems</option> configuration option.  For instance, the
+following definition causes NixOS to mount the Ext4 file system on
+device <filename>/dev/disk/by-label/data</filename> onto the mount
+point <filename>/data</filename>:
+
+<programlisting>
+fileSystems."/data" =
+  { device = "/dev/disk/by-label/data";
+    fsType = "ext4";
+  };
+</programlisting>
+
+Mount points are created automatically if they don’t already exist.
+For <option>device</option>, it’s best to use the topology-independent
+device aliases in <filename>/dev/disk/by-label</filename> and
+<filename>/dev/disk/by-uuid</filename>, as these don’t change if the
+topology changes (e.g. if a disk is moved to another IDE
+controller).</para>
+
+<para>You can usually omit the file system type
+(<option>fsType</option>), since <command>mount</command> can usually
+detect the type and load the necessary kernel module automatically.
+However, if the file system is needed at early boot (in the initial
+ramdisk) and is not <literal>ext2</literal>, <literal>ext3</literal>
+or <literal>ext4</literal>, then it’s best to specify
+<option>fsType</option> to ensure that the kernel module is
+available.</para>
+
+<xi:include href="luks-file-systems.xml" />
+
+</chapter>
diff --git a/nixos/doc/manual/configuration/firewall.xml b/nixos/doc/manual/configuration/firewall.xml
new file mode 100644
index 00000000000..87406c28c2f
--- /dev/null
+++ b/nixos/doc/manual/configuration/firewall.xml
@@ -0,0 +1,38 @@
+<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-firewall">
+
+<title>Firewall</title>
+
+<para>NixOS has a simple stateful firewall that blocks incoming
+connections and other unexpected packets.  The firewall applies to
+both IPv4 and IPv6 traffic. It is enabled by default. It can be
+disabled as follows:
+
+<programlisting>
+networking.firewall.enable = false;
+</programlisting>
+
+If the firewall is enabled, you can open specific TCP ports to the
+outside world:
+
+<programlisting>
+networking.firewall.allowedTCPPorts = [ 80 443 ];
+</programlisting>
+
+Note that TCP port 22 (ssh) is opened automatically if the SSH daemon
+is enabled (<option>services.openssh.enable = true</option>).  UDP
+ports can be opened through
+<option>networking.firewall.allowedUDPPorts</option>.  Also of
+interest is
+
+<programlisting>
+networking.firewall.allowPing = true;
+</programlisting>
+
+to allow the machine to respond to ping requests.  (ICMPv6 pings are
+always allowed.)</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/ipv4-config.xml b/nixos/doc/manual/configuration/ipv4-config.xml
new file mode 100644
index 00000000000..053501b1736
--- /dev/null
+++ b/nixos/doc/manual/configuration/ipv4-config.xml
@@ -0,0 +1,44 @@
+<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-ipv4">
+
+<title>IPv4 Configuration</title>
+
+<para>By default, NixOS uses DHCP (specifically,
+<command>dhcpcd</command>) to automatically configure network
+interfaces.  However, you can configure an interface manually as
+follows:
+
+<programlisting>
+networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
+</programlisting>
+
+Typically you’ll also want to set a default gateway and set of name
+servers:
+
+<programlisting>
+networking.defaultGateway = "192.168.1.1";
+networking.nameservers = [ "8.8.8.8" ];
+</programlisting>
+
+</para>
+
+<note><para>Statically configured interfaces are set up by the systemd
+service
+<replaceable>interface-name</replaceable><literal>-cfg.service</literal>.
+The default gateway and name server configuration is performed by
+<literal>network-setup.service</literal>.</para></note>
+
+<para>The host name is set using <option>networking.hostName</option>:
+
+<programlisting>
+networking.hostName = "cartman";
+</programlisting>
+
+The default host name is <literal>nixos</literal>.  Set it to the
+empty string (<literal>""</literal>) to allow the DHCP server to
+provide the host name.</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/ipv6-config.xml b/nixos/doc/manual/configuration/ipv6-config.xml
new file mode 100644
index 00000000000..592bf20e545
--- /dev/null
+++ b/nixos/doc/manual/configuration/ipv6-config.xml
@@ -0,0 +1,19 @@
+<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-ipv6">
+
+<title>IPv6 Configuration</title>
+
+<para>IPv6 is enabled by default.  Stateless address autoconfiguration
+is used to automatically assign IPv6 addresses to all interfaces.  You
+can disable IPv6 support globally by setting:
+
+<programlisting>
+networking.enableIPv6 = false;
+</programlisting>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/linux-kernel.xml b/nixos/doc/manual/configuration/linux-kernel.xml
new file mode 100644
index 00000000000..8fe2f5255df
--- /dev/null
+++ b/nixos/doc/manual/configuration/linux-kernel.xml
@@ -0,0 +1,69 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-kernel-config">
+
+<title>Linux Kernel</title>
+
+<para>You can override the Linux kernel and associated packages using
+the option <option>boot.kernelPackages</option>.  For instance, this
+selects the Linux 3.10 kernel:
+<programlisting>
+boot.kernelPackages = pkgs.linuxPackages_3_10;
+</programlisting>
+Note that this not only replaces the kernel, but also packages that
+are specific to the kernel version, such as the NVIDIA video drivers.
+This ensures that driver packages are consistent with the
+kernel.</para>
+
+<para>The default Linux kernel configuration should be fine for most users. You can see the configuration of your current kernel with the following command:
+<programlisting>
+cat /proc/config.gz | gunzip
+</programlisting>
+If you want to change the kernel configuration, you can use the
+<option>packageOverrides</option> feature (see <xref
+linkend="sec-customising-packages" />).  For instance, to enable
+support for the kernel debugger KGDB:
+
+<programlisting>
+nixpkgs.config.packageOverrides = pkgs:
+  { linux_3_4 = pkgs.linux_3_4.override {
+      extraConfig =
+        ''
+          KGDB y
+        '';
+    };
+  };
+</programlisting>
+
+<varname>extraConfig</varname> takes a list of Linux kernel
+configuration options, one per line.  The name of the option should
+not include the prefix <literal>CONFIG_</literal>.  The option value
+is typically <literal>y</literal>, <literal>n</literal> or
+<literal>m</literal> (to build something as a kernel module).</para>
+
+<para>Kernel modules for hardware devices are generally loaded
+automatically by <command>udev</command>.  You can force a module to
+be loaded via <option>boot.kernelModules</option>, e.g.
+<programlisting>
+boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
+</programlisting>
+If the module is required early during the boot (e.g. to mount the
+root file system), you can use
+<option>boot.initrd.extraKernelModules</option>:
+<programlisting>
+boot.initrd.extraKernelModules = [ "cifs" ];
+</programlisting>
+This causes the specified modules and their dependencies to be added
+to the initial ramdark.</para>
+
+<para>Kernel runtime parameters can be set through
+<option>boot.kernel.sysctl</option>, e.g.
+<programlisting>
+boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
+</programlisting>
+sets the kernel’s TCP keepalive time to 120 seconds.  To see the
+available parameters, run <command>sysctl -a</command>.</para>
+
+</chapter>
diff --git a/nixos/doc/manual/configuration/luks-file-systems.xml b/nixos/doc/manual/configuration/luks-file-systems.xml
new file mode 100644
index 00000000000..45475dbcd44
--- /dev/null
+++ b/nixos/doc/manual/configuration/luks-file-systems.xml
@@ -0,0 +1,42 @@
+<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-luks-file-systems">
+
+<title>LUKS-Encrypted File Systems</title>
+
+<para>NixOS supports file systems that are encrypted using
+<emphasis>LUKS</emphasis> (Linux Unified Key Setup).  For example,
+here is how you create an encrypted Ext4 file system on the device
+<filename>/dev/sda2</filename>:
+
+<screen>
+$ cryptsetup luksFormat /dev/sda2
+
+WARNING!
+========
+This will overwrite data on /dev/sda2 irrevocably.
+
+Are you sure? (Type uppercase yes): YES
+Enter LUKS passphrase: ***
+Verify passphrase: ***
+
+$ cryptsetup luksOpen /dev/sda2 crypted
+Enter passphrase for /dev/sda2: ***
+
+$ mkfs.ext4 /dev/mapper/crypted
+</screen>
+
+To ensure that this file system is automatically mounted at boot time
+as <filename>/</filename>, add the following to
+<filename>configuration.nix</filename>:
+
+<programlisting>
+boot.initrd.luks.devices = [ { device = "/dev/sda2"; name = "crypted"; } ];
+fileSystems."/".device = "/dev/mapper/crypted";
+</programlisting>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/modularity.xml b/nixos/doc/manual/configuration/modularity.xml
new file mode 100644
index 00000000000..d95091bd162
--- /dev/null
+++ b/nixos/doc/manual/configuration/modularity.xml
@@ -0,0 +1,143 @@
+<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-modularity">
+
+<title>Modularity</title>
+
+<para>The NixOS configuration mechanism is modular.  If your
+<filename>configuration.nix</filename> becomes too big, you can split
+it into multiple files.  Likewise, if you have multiple NixOS
+configurations (e.g. for different computers) with some commonality,
+you can move the common configuration into a shared file.</para>
+
+<para>Modules have exactly the same syntax as
+<filename>configuration.nix</filename>.  In fact,
+<filename>configuration.nix</filename> is itself a module.  You can
+use other modules by including them from
+<filename>configuration.nix</filename>, e.g.:
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ imports = [ ./vpn.nix ./kde.nix ];
+  services.httpd.enable = true;
+  environment.systemPackages = [ pkgs.emacs ];
+  <replaceable>...</replaceable>
+}
+</programlisting>
+
+Here, we include two modules from the same directory,
+<filename>vpn.nix</filename> and <filename>kde.nix</filename>.  The
+latter might look like this:
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ services.xserver.enable = true;
+  services.xserver.displayManager.kdm.enable = true;
+  services.xserver.desktopManager.kde4.enable = true;
+  environment.systemPackages = [ pkgs.kde4.kscreensaver ];
+}
+</programlisting>
+
+Note that both <filename>configuration.nix</filename> and
+<filename>kde.nix</filename> define the option
+<option>environment.systemPackages</option>.  When multiple modules
+define an option, NixOS will try to <emphasis>merge</emphasis> the
+definitions.  In the case of
+<option>environment.systemPackages</option>, that’s easy: the lists of
+packages can simply be concatenated.  The value in
+<filename>configuration.nix</filename> is merged last, so for
+list-type options, it will appear at the end of the merged list. If
+you want it to appear first, you can use <varname>mkBefore</varname>:
+
+<programlisting>
+boot.kernelModules = mkBefore [ "kvm-intel" ];
+</programlisting>
+
+This causes the <literal>kvm-intel</literal> kernel module to be
+loaded before any other kernel modules.</para>
+
+<para>For other types of options, a merge may not be possible. For
+instance, if two modules define
+<option>services.httpd.adminAddr</option>,
+<command>nixos-rebuild</command> will give an error:
+
+<screen>
+The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
+</screen>
+
+When that happens, it’s possible to force one definition take
+precedence over the others:
+
+<programlisting>
+services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
+</programlisting>
+
+</para>
+
+<para>When using multiple modules, you may need to access
+configuration values defined in other modules.  This is what the
+<varname>config</varname> function argument is for: it contains the
+complete, merged system configuration.  That is,
+<varname>config</varname> is the result of combining the
+configurations returned by every module<footnote><para>If you’re
+wondering how it’s possible that the (indirect)
+<emphasis>result</emphasis> of a function is passed as an
+<emphasis>input</emphasis> to that same function: that’s because Nix
+is a “lazy” language — it only computes values when they are needed.
+This works as long as no individual configuration value depends on
+itself.</para></footnote>.  For example, here is a module that adds
+some packages to <option>environment.systemPackages</option> only if
+<option>services.xserver.enable</option> is set to
+<literal>true</literal> somewhere else:
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ environment.systemPackages =
+    if config.services.xserver.enable then
+      [ pkgs.firefox
+        pkgs.thunderbird
+      ]
+    else
+      [ ];
+}
+</programlisting>
+
+</para>
+
+<para>With multiple modules, it may not be obvious what the final
+value of a configuration option is.  The command
+<option>nixos-option</option> allows you to find out:
+
+<screen>
+$ nixos-option services.xserver.enable
+true
+
+$ nixos-option boot.kernelModules
+[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
+</screen>
+
+Interactive exploration of the configuration is possible using
+<command
+xlink:href="https://github.com/edolstra/nix-repl">nix-repl</command>,
+a read-eval-print loop for Nix expressions.  It’s not installed by
+default; run <literal>nix-env -i nix-repl</literal> to get it.  A
+typical use:
+
+<screen>
+$ nix-repl '&lt;nixos>'
+
+nix-repl> config.networking.hostName
+"mandark"
+
+nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
+[ "example.org" "example.gov" ]
+</screen>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/network-manager.xml b/nixos/doc/manual/configuration/network-manager.xml
new file mode 100644
index 00000000000..e65060021b4
--- /dev/null
+++ b/nixos/doc/manual/configuration/network-manager.xml
@@ -0,0 +1,27 @@
+<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-networkmanager">
+
+<title>NetworkManager</title>
+
+<para>To facilitate network configuration, some desktop environments
+use NetworkManager. You can enable NetworkManager by setting:
+
+<programlisting>
+services.networkmanager.enable = true;
+</programlisting>
+
+Some desktop managers (e.g., GNOME) enable NetworkManager
+automatically for you.</para>
+
+<para>All users that should have permission to change network settings
+must belong to the <code>networkmanager</code> group.</para>
+
+<note><para><code>services.networkmanager</code> and
+<code>services.wireless</code> can not be enabled at the same time:
+you can still connect to the wireless networks using
+NetworkManager.</para></note>
+
+</section>
diff --git a/nixos/doc/manual/configuration/networking.xml b/nixos/doc/manual/configuration/networking.xml
new file mode 100644
index 00000000000..5f08bc1f127
--- /dev/null
+++ b/nixos/doc/manual/configuration/networking.xml
@@ -0,0 +1,22 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-networking">
+
+<title>Networking</title>
+
+<para>This section describes how to configure networking components on
+your NixOS machine.</para>
+
+<xi:include href="network-manager.xml" />
+<xi:include href="ssh.xml" />
+<xi:include href="ipv4-config.xml" />
+<xi:include href="ipv6-config.xml" />
+<xi:include href="firewall.xml" />
+<xi:include href="wireless.xml" />
+<xi:include href="ad-hoc-network-config.xml" />
+
+<!-- TODO: OpenVPN, NAT -->
+
+</chapter>
diff --git a/nixos/doc/manual/configuration/package-mgmt.xml b/nixos/doc/manual/configuration/package-mgmt.xml
new file mode 100644
index 00000000000..73c1722da02
--- /dev/null
+++ b/nixos/doc/manual/configuration/package-mgmt.xml
@@ -0,0 +1,34 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-package-management">
+
+<title>Package Management</title>
+
+<para>This section describes how to add additional packages to your
+system.  NixOS has two distinct styles of package management:
+
+<itemizedlist>
+
+  <listitem><para><emphasis>Declarative</emphasis>, where you declare
+  what packages you want in your
+  <filename>configuration.nix</filename>.  Every time you run
+  <command>nixos-rebuild</command>, NixOS will ensure that you get a
+  consistent set of binaries corresponding to your
+  specification.</para></listitem>
+
+  <listitem><para><emphasis>Ad hoc</emphasis>, where you install,
+  upgrade and uninstall packages via the <command>nix-env</command>
+  command.  This style allows mixing packages from different Nixpkgs
+  versions.  It’s the only choice for non-root
+  users.</para></listitem>
+
+</itemizedlist>
+
+</para>
+
+<xi:include href="declarative-packages.xml" />
+<xi:include href="ad-hoc-packages.xml" />
+
+</chapter>
diff --git a/nixos/doc/manual/configuration/ssh.xml b/nixos/doc/manual/configuration/ssh.xml
new file mode 100644
index 00000000000..7c928baaf89
--- /dev/null
+++ b/nixos/doc/manual/configuration/ssh.xml
@@ -0,0 +1,32 @@
+<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-ssh">
+
+<title>Secure Shell Access</title>
+
+<para>Secure shell (SSH) access to your machine can be enabled by
+setting:
+
+<programlisting>
+services.openssh.enable = true;
+</programlisting>
+
+By default, root logins using a password are disallowed.  They can be
+disabled entirely by setting
+<literal>services.openssh.permitRootLogin</literal> to
+<literal>"no"</literal>.</para>
+
+<para>You can declaratively specify authorised RSA/DSA public keys for
+a user as follows:
+
+<!-- FIXME: this might not work if the user is unmanaged. -->
+<programlisting>
+users.extraUsers.alice.openssh.authorizedKeys.keys =
+  [ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
+</programlisting>
+
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/summary.xml b/nixos/doc/manual/configuration/summary.xml
new file mode 100644
index 00000000000..9bb5e35e16b
--- /dev/null
+++ b/nixos/doc/manual/configuration/summary.xml
@@ -0,0 +1,191 @@
+<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-nix-syntax-summary">
+
+<title>Syntax Summary</title>
+
+<para>Below is a summary of the most important syntactic constructs in
+the Nix expression language.  It’s not complete.  In particular, there
+are many other built-in functions.  See the <link
+xlink:href="http://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
+manual</link> for the rest.</para>
+
+<informaltable frame='none'>
+  <tgroup cols='2'>
+    <colspec colname='c1' rowsep='1' colsep='1' />
+    <colspec colname='c2' rowsep='1' />
+    <thead>
+      <row>
+        <entry>Example</entry>
+        <entry>Description</entry>
+      </row>
+    </thead>
+    <tbody>
+
+      <row>
+        <entry namest="c1" nameend="c2"><emphasis>Basic values</emphasis></entry>
+      </row>
+      <row>
+        <entry><literal>"Hello world"</literal></entry>
+        <entry>A string</entry>
+      </row>
+      <row>
+        <entry><literal>"${pkgs.bash}/bin/sh"</literal></entry>
+        <entry>A string containing an expression (expands to <literal>"/nix/store/<replaceable>hash</replaceable>-bash-<replaceable>version</replaceable>/bin/sh"</literal>)</entry>
+      </row>
+      <row>
+        <entry><literal>true</literal>, <literal>false</literal></entry>
+        <entry>Booleans</entry>
+      </row>
+      <row>
+        <entry><literal>123</literal></entry>
+        <entry>An integer</entry>
+      </row>
+      <row>
+        <entry><literal>./foo.png</literal></entry>
+        <entry>A path (relative to the containing Nix expression)</entry>
+      </row>
+
+      <row>
+        <entry namest="c1" nameend="c2"><emphasis>Compound values</emphasis></entry>
+      </row>
+      <row>
+        <entry><literal>{ x = 1; y = 2; }</literal></entry>
+        <entry>An set with attributes names <literal>x</literal> and <literal>y</literal></entry>
+      </row>
+      <row>
+        <entry><literal>{ foo.bar = 1; }</literal></entry>
+        <entry>A nested set, equivalent to <literal>{ foo = { bar = 1; }; }</literal></entry>
+      </row>
+      <row>
+        <entry><literal>rec { x = "bla"; y = x + "bar"; }</literal></entry>
+        <entry>A recursive set, equivalent to <literal>{ x = "foo"; y = "foobar"; }</literal></entry>
+      </row>
+      <row>
+        <entry><literal>[ "foo" "bar" ]</literal></entry>
+        <entry>A list with two elements</entry>
+      </row>
+
+      <row>
+        <entry namest="c1" nameend="c2"><emphasis>Operators</emphasis></entry>
+      </row>
+      <row>
+        <entry><literal>"foo" + "bar"</literal></entry>
+        <entry>String concatenation</entry>
+      </row>
+      <row>
+        <entry><literal>1 + 2</literal></entry>
+        <entry>Integer addition</entry>
+      </row>
+      <row>
+        <entry><literal>"foo" == "f" + "oo"</literal></entry>
+        <entry>Equality test (evaluates to <literal>true</literal>)</entry>
+      </row>
+      <row>
+        <entry><literal>"foo" != "bar"</literal></entry>
+        <entry>Inequality test (evaluates to <literal>true</literal>)</entry>
+      </row>
+      <row>
+        <entry><literal>!true</literal></entry>
+        <entry>Boolean negation</entry>
+      </row>
+      <row>
+        <entry><literal>{ x = 1; y = 2; }.x</literal></entry>
+        <entry>Attribute selection (evaluates to <literal>1</literal>)</entry>
+      </row>
+      <row>
+        <entry><literal>{ x = 1; y = 2; }.z or 3</literal></entry>
+        <entry>Attribute selection with default (evaluates to <literal>3</literal>)</entry>
+      </row>
+      <row>
+        <entry><literal>{ x = 1; y = 2; } // { z = 3; }</literal></entry>
+        <entry>Merge two sets (attributes in the right-hand set taking precedence)</entry>
+      </row>
+
+      <row>
+        <entry namest="c1" nameend="c2"><emphasis>Control structures</emphasis></entry>
+      </row>
+      <row>
+        <entry><literal>if 1 + 1 == 2 then "yes!" else "no!"</literal></entry>
+        <entry>Conditional expression</entry>
+      </row>
+      <row>
+        <entry><literal>assert 1 + 1 == 2; "yes!"</literal></entry>
+        <entry>Assertion check (evaluates to <literal>"yes!"</literal>)</entry>
+      </row>
+      <row>
+        <entry><literal>let x = "foo"; y = "bar"; in x + y</literal></entry>
+        <entry>Variable definition</entry>
+      </row>
+      <row>
+        <entry><literal>with pkgs.lib; head [ 1 2 3 ]</literal></entry>
+        <entry>Add all attributes from the given set to the scope
+        (evaluates to <literal>1</literal>)</entry>
+      </row>
+
+      <row>
+        <entry namest="c1" nameend="c2"><emphasis>Functions (lambdas)</emphasis></entry>
+      </row>
+      <row>
+        <entry><literal>x: x + 1</literal></entry>
+        <entry>A function that expects an integer and returns it increased by 1</entry>
+      </row>
+      <row>
+        <entry><literal>(x: x + 1) 100</literal></entry>
+        <entry>A function call (evaluates to 101)</entry>
+      </row>
+      <row>
+        <entry><literal>let inc = x: x + 1; in inc (inc (inc 100))</literal></entry>
+        <entry>A function bound to a variable and subsequently called by name (evaluates to 103)</entry>
+      </row>
+      <row>
+        <entry><literal>{ x, y }: x + y</literal></entry>
+        <entry>A function that expects a set with required attributes
+        <literal>x</literal> and <literal>y</literal> and concatenates
+        them</entry>
+      </row>
+      <row>
+        <entry><literal>{ x, y ? "bar" }: x + y</literal></entry>
+        <entry>A function that expects a set with required attribute
+        <literal>x</literal> and optional <literal>y</literal>, using
+        <literal>"bar"</literal> as default value for
+        <literal>y</literal></entry>
+      </row>
+      <row>
+        <entry><literal>{ x, y, ... }: x + y</literal></entry>
+        <entry>A function that expects a set with required attributes
+        <literal>x</literal> and <literal>y</literal> and ignores any
+        other attributes</entry>
+      </row>
+      <row>
+        <entry><literal>{ x, y } @ args: x + y</literal></entry>
+        <entry>A function that expects a set with required attributes
+        <literal>x</literal> and <literal>y</literal>, and binds the
+        whole set to <literal>args</literal></entry>
+      </row>
+
+      <row>
+        <entry namest="c1" nameend="c2"><emphasis>Built-in functions</emphasis></entry>
+      </row>
+      <row>
+        <entry><literal>import ./foo.nix</literal></entry>
+        <entry>Load and return Nix expression in given file</entry>
+      </row>
+      <row>
+        <entry><literal>map (x: x + x) [ 1 2 3 ]</literal></entry>
+        <entry>Apply a function to every element of a list (evaluates to <literal>[ 2 4 6 ]</literal>)</entry>
+      </row>
+      <!--
+      <row>
+        <entry><literal>throw "Urgh"</literal></entry>
+        <entry>Raise an error condition</entry>
+      </row>
+      -->
+
+    </tbody>
+  </tgroup>
+</informaltable>
+
+</section>
diff --git a/nixos/doc/manual/configuration/user-mgmt.xml b/nixos/doc/manual/configuration/user-mgmt.xml
new file mode 100644
index 00000000000..40dc687d03b
--- /dev/null
+++ b/nixos/doc/manual/configuration/user-mgmt.xml
@@ -0,0 +1,95 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-user-management">
+
+<title>User Management</title>
+
+<para>NixOS supports both declarative and imperative styles of user
+management.  In the declarative style, users are specified in
+<filename>configuration.nix</filename>.  For instance, the following
+states that a user account named <literal>alice</literal> shall exist:
+
+<programlisting>
+users.extraUsers.alice =
+  { createHome = true;
+    home = "/home/alice";
+    description = "Alice Foobar";
+    extraGroups = [ "wheel" "networkmanager" ];
+    useDefaultShell = true;
+    openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
+  };
+</programlisting>
+
+Note that <literal>alice</literal> is a member of the
+<literal>wheel</literal> and <literal>networkmanager</literal> groups,
+which allows her to use <command>sudo</command> to execute commands as
+<literal>root</literal> and to configure the network, respectively.
+Also note the SSH public key that allows remote logins with the
+corresponding private key. Users created in this way do not have a
+password by default, so they cannot log in via mechanisms that require
+a password. However, you can use the <command>passwd</command> program
+to set a password, which is retained across invocations of
+<command>nixos-rebuild</command>.</para>
+
+<para>If you set users.mutableUsers to false, then the contents of /etc/passwd
+and /etc/group will be congruent to your NixOS configuration. For instance,
+if you remove a user from users.extraUsers and run nixos-rebuild, the user
+account will cease to exist. Also, imperative commands for managing users
+and groups, such as useradd, are no longer available.</para>
+
+<para>A user ID (uid) is assigned automatically.  You can also specify
+a uid manually by adding
+
+<programlisting>
+    uid = 1000;
+</programlisting>
+
+to the user specification.</para>
+
+<para>Groups can be specified similarly.  The following states that a
+group named <literal>students</literal> shall exist:
+
+<programlisting>
+users.extraGroups.students.gid = 1000;
+</programlisting>
+
+As with users, the group ID (gid) is optional and will be assigned
+automatically if it’s missing.</para>
+
+<warning><para>Currently declarative user management is not perfect:
+<command>nixos-rebuild</command> does not know how to realise certain
+configuration changes.  This includes removing a user or group, and
+removing group membership from a user.</para></warning>
+
+<para>In the imperative style, users and groups are managed by
+commands such as <command>useradd</command>,
+<command>groupmod</command> and so on.  For instance, to create a user
+account named <literal>alice</literal>:
+
+<screen>
+$ useradd -m alice</screen>
+
+The flag <option>-m</option> causes the creation of a home directory
+for the new user, which is generally what you want.  The user does not
+have an initial password and therefore cannot log in.  A password can
+be set using the <command>passwd</command> utility:
+
+<screen>
+$ passwd alice
+Enter new UNIX password: ***
+Retype new UNIX password: ***
+</screen>
+
+A user can be deleted using <command>userdel</command>:
+
+<screen>
+$ userdel -r alice</screen>
+
+The flag <option>-r</option> deletes the user’s home directory.
+Accounts can be modified using <command>usermod</command>.  Unix
+groups can be managed using <command>groupadd</command>,
+<command>groupmod</command> and <command>groupdel</command>.</para>
+
+</chapter>
diff --git a/nixos/doc/manual/configuration/wireless.xml b/nixos/doc/manual/configuration/wireless.xml
new file mode 100644
index 00000000000..373a9168cc8
--- /dev/null
+++ b/nixos/doc/manual/configuration/wireless.xml
@@ -0,0 +1,41 @@
+<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-wireless">
+
+<title>Wireless Networks</title>
+
+<para>For a desktop installation using NetworkManager (e.g., GNOME),
+you just have to make sure the user is in the
+<code>networkmanager</code> group and you can skip the rest of this
+section on wireless networks.</para>
+
+<para>
+NixOS will start wpa_supplicant for you if you enable this setting:
+
+<programlisting>
+networking.wireless.enable = true;
+</programlisting>
+
+NixOS currently does not generate wpa_supplicant's
+configuration file, <literal>/etc/wpa_supplicant.conf</literal>. You should edit this file
+yourself to define wireless networks, WPA keys and so on (see
+wpa_supplicant.conf(5)).
+</para>
+
+<para>
+If you are using WPA2 the <command>wpa_passphrase</command> tool might be useful
+to generate the <literal>wpa_supplicant.conf</literal>.
+
+<screen>
+$ wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf</screen>
+
+After you have edited the <literal>wpa_supplicant.conf</literal>,
+you need to restart the wpa_supplicant service.
+
+<screen>
+$ systemctl restart wpa_supplicant.service</screen>
+</para>
+
+</section>
diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml
new file mode 100644
index 00000000000..bc58bb1f066
--- /dev/null
+++ b/nixos/doc/manual/configuration/x-windows.xml
@@ -0,0 +1,94 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-x11">
+
+<title>X Window System</title>
+    
+<para>The X Window System (X11) provides the basis of NixOS’ graphical
+user interface.  It can be enabled as follows:
+<programlisting>
+services.xserver.enable = true;
+</programlisting>
+The X server will automatically detect and use the appropriate video
+driver from a set of X.org drivers (such as <literal>vesa</literal>
+and <literal>intel</literal>).  You can also specify a driver
+manually, e.g.
+<programlisting>
+services.xserver.videoDrivers = [ "r128" ];
+</programlisting>
+to enable X.org’s <literal>xf86-video-r128</literal> driver.</para>
+
+<para>You also need to enable at least one desktop or window manager.
+Otherwise, you can only log into a plain undecorated
+<command>xterm</command> window.  Thus you should pick one or more of
+the following lines:
+<programlisting>
+services.xserver.desktopManager.kde4.enable = true;
+services.xserver.desktopManager.xfce.enable = true;
+services.xserver.windowManager.xmonad.enable = true;
+services.xserver.windowManager.twm.enable = true;
+services.xserver.windowManager.icewm.enable = true;
+</programlisting>
+</para>
+
+<para>NixOS’s default <emphasis>display manager</emphasis> (the
+program that provides a graphical login prompt and manages the X
+server) is SLiM.  You can select KDE’s <command>kdm</command> instead:
+<programlisting>
+services.xserver.displayManager.kdm.enable = true;
+</programlisting>
+</para>
+
+<para>The X server is started automatically at boot time.  If you
+don’t want this to happen, you can set:
+<programlisting>
+services.xserver.autorun = false;
+</programlisting>
+The X server can then be started manually:
+<screen>
+$ systemctl start display-manager.service
+</screen>
+</para>
+
+
+<simplesect><title>NVIDIA Graphics Cards</title>
+
+<para>NVIDIA provides a proprietary driver for its graphics cards that
+has better 3D performance than the X.org drivers.  It is not enabled
+by default because it’s not free software.  You can enable it as follows:
+<programlisting>
+services.xserver.videoDrivers = [ "nvidia" ];
+</programlisting>
+You may need to reboot after enabling this driver to prevent a clash
+with other kernel modules.</para>
+
+<para>On 64-bit systems, if you want full acceleration for 32-bit
+programs such as Wine, you should also set the following:
+<programlisting>
+services.xserver.driSupport32Bit = true;
+</programlisting>
+</para>
+
+</simplesect>
+
+
+<simplesect><title>Touchpads</title>
+
+<para>Support for Synaptics touchpads (found in many laptops such as
+the Dell Latitude series) can be enabled as follows:
+<programlisting>
+services.xserver.synaptics.enable = true;
+</programlisting>
+The driver has many options (see <xref linkend="ch-options"/>).  For
+instance, the following enables two-finger scrolling:
+<programlisting>
+services.xserver.synaptics.twoFingerScroll = true;
+</programlisting>
+</para>
+
+</simplesect>
+
+
+</chapter>
diff --git a/nixos/doc/manual/containers.xml b/nixos/doc/manual/containers.xml
deleted file mode 100644
index 2530d519521..00000000000
--- a/nixos/doc/manual/containers.xml
+++ /dev/null
@@ -1,242 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-         xmlns:xlink="http://www.w3.org/1999/xlink"
-         xml:id="ch-containers">
-
-<title>Containers</title>
-
-<para>NixOS allows you to easily run other NixOS instances as
-<emphasis>containers</emphasis>. Containers are a light-weight
-approach to virtualisation that runs software in the container at the
-same speed as in the host system. NixOS containers share the Nix store
-of the host, making container creation very efficient.</para>
-
-<warning><para>Currently, NixOS containers are not perfectly isolated
-from the host system. This means that a user with root access to the
-container can do things that affect the host. So you should not give
-container root access to untrusted users.</para></warning>
-
-<para>NixOS containers can be created in two ways: imperatively, using
-the command <command>nixos-container</command>, and declaratively, by
-specifying them in your <filename>configuration.nix</filename>. The
-declarative approach implies that containers get upgraded along with
-your host system when you run <command>nixos-rebuild</command>, which
-is often not what you want. By contrast, in the imperative approach,
-containers are configured and updated independently from the host
-system.</para>
-
-
-<section><title>Imperative container management</title>
-
-<para>We’ll cover imperative container management using
-<command>nixos-container</command> first. You create a container with
-identifier <literal>foo</literal> as follows:
-
-<screen>
-$ nixos-container create foo
-</screen>
-
-This creates the container’s root directory in
-<filename>/var/lib/containers/foo</filename> and a small configuration
-file in <filename>/etc/containers/foo.conf</filename>. It also builds
-the container’s initial system configuration and stores it in
-<filename>/nix/var/nix/profiles/per-container/foo/system</filename>. You
-can modify the initial configuration of the container on the command
-line. For instance, to create a container that has
-<command>sshd</command> running, with the given public key for
-<literal>root</literal>:
-
-<screen>
-$ nixos-container create foo --config 'services.openssh.enable = true; \
-  users.extraUsers.root.openssh.authorizedKeys.keys = ["ssh-dss AAAAB3N…"];'
-</screen>
-
-</para>
-
-<para>Creating a container does not start it. To start the container,
-run:
-
-<screen>
-$ nixos-container start foo
-</screen>
-
-This command will return as soon as the container has booted and has
-reached <literal>multi-user.target</literal>. On the host, the
-container runs within a systemd unit called
-<literal>container@<replaceable>container-name</replaceable>.service</literal>.
-Thus, if something went wrong, you can get status info using
-<command>systemctl</command>:
-
-<screen>
-$ systemctl status container@foo
-</screen>
-
-</para>
-
-<para>If the container has started succesfully, you can log in as
-root using the <command>root-login</command> operation:
-
-<screen>
-$ nixos-container root-login foo
-[root@foo:~]#
-</screen>
-
-Note that only root on the host can do this (since there is no
-authentication).  You can also get a regular login prompt using the
-<command>login</command> operation, which is available to all users on
-the host:
-
-<screen>
-$ nixos-container login foo
-foo login: alice
-Password: ***
-</screen>
-
-With <command>nixos-container run</command>, you can execute arbitrary
-commands in the container:
-
-<screen>
-$ nixos-container run foo -- uname -a
-Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
-</screen>
-
-</para>
-
-<para>There are several ways to change the configuration of the
-container. First, on the host, you can edit
-<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>,
-and run
-
-<screen>
-$ nixos-container update foo
-</screen>
-
-This will build and activate the new configuration. You can also
-specify a new configuration on the command line:
-
-<screen>
-$ nixos-container update foo --config 'services.httpd.enable = true; \
-  services.httpd.adminAddr = "foo@example.org";'
-
-$ curl http://$(nixos-container show-ip foo)/
-&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">…
-</screen>
-
-However, note that this will overwrite the container’s
-<filename>/etc/nixos/configuration.nix</filename>.</para>
-
-<para>Alternatively, you can change the configuration from within the
-container itself by running <command>nixos-rebuild switch</command>
-inside the container. Note that the container by default does not have
-a copy of the NixOS channel, so you should run <command>nix-channel
---update</command> first.</para>
-
-<para>Containers can be stopped and started using
-<literal>nixos-container stop</literal> and <literal>nixos-container
-start</literal>, respectively, or by using
-<command>systemctl</command> on the container’s service unit. To
-destroy a container, including its file system, do
-
-<screen>
-$ nixos-container destroy foo
-</screen>
-
-</para>
-
-</section>
-
-
-<section><title>Declarative container specification</title>
-
-<para>You can also specify containers and their configuration in the
-host’s <filename>configuration.nix</filename>.  For example, the
-following specifies that there shall be a container named
-<literal>database</literal> running PostgreSQL:
-
-<programlisting>
-containers.database =
-  { config =
-      { config, pkgs, ... }:
-      { services.postgresql.enable = true;
-        services.postgresql.package = pkgs.postgresql92;
-      };
-  };
-</programlisting>
-
-If you run <literal>nixos-rebuild switch</literal>, the container will
-be built and started. If the container was already running, it will be
-updated in place, without rebooting.</para>
-
-<para>By default, declarative containers share the network namespace
-of the host, meaning that they can listen on (privileged)
-ports. However, they cannot change the network configuration. You can
-give a container its own network as follows:
-
-<programlisting>
-containers.database =
-  { privateNetwork = true;
-    hostAddress = "192.168.100.10";
-    localAddress = "192.168.100.11";
-  };
-</programlisting>
-
-This gives the container a private virtual Ethernet interface with IP
-address <literal>192.168.100.11</literal>, which is hooked up to a
-virtual Ethernet interface on the host with IP address
-<literal>192.168.100.10</literal>.  (See the next section for details
-on container networking.)</para>
-
-<para>To disable the container, just remove it from
-<filename>configuration.nix</filename> and run <literal>nixos-rebuild
-switch</literal>. Note that this will not delete the root directory of
-the container in <literal>/var/lib/containers</literal>.</para>
-
-</section>
-
-
-<section><title>Networking</title>
-
-<para>When you create a container using <literal>nixos-container
-create</literal>, it gets it own private IPv4 address in the range
-<literal>10.233.0.0/16</literal>. You can get the container’s IPv4
-address as follows:
-
-<screen>
-$ nixos-container show-ip foo
-10.233.4.2
-
-$ ping -c1 10.233.4.2
-64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms
-</screen>
-
-</para>
-
-<para>Networking is implemented using a pair of virtual Ethernet
-devices. The network interface in the container is called
-<literal>eth0</literal>, while the matching interface in the host is
-called <literal>ve-<replaceable>container-name</replaceable></literal>
-(e.g., <literal>ve-foo</literal>).  The container has its own network
-namespace and the <literal>CAP_NET_ADMIN</literal> capability, so it
-can perform arbitrary network configuration such as setting up
-firewall rules, without affecting or having access to the host’s
-network.</para>
-
-<para>By default, containers cannot talk to the outside network. If
-you want that, you should set up Network Address Translation (NAT)
-rules on the host to rewrite container traffic to use your external
-IP address. This can be accomplished using the following configuration
-on the host:
-
-<programlisting>
-networking.nat.enable = true;
-networking.nat.internalInterfaces = ["ve-+"];
-networking.nat.externalInterface = "eth0";
-</programlisting>
-where <literal>eth0</literal> should be replaced with the desired
-external interface. Note that <literal>ve-+</literal> is a wildcard
-that matches all container interfaces.</para>
-
-</section>
-
-
-</chapter>
-
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 55533a05b06..47e01437ccc 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -36,30 +36,29 @@ let
       -o $out ${./options-to-docbook.xsl} ${optionsXML}
   '';
 
+  sources = sourceFilesBySuffices ./. [".xml"];
+
+  copySources =
+    ''
+      cp -prd $sources/* . # */
+      chmod -R u+w .
+      cp ${../../modules/services/databases/postgresql.xml} configuration/postgresql.xml
+      ln -s ${optionsDocBook} options-db.xml
+      echo "${version}" > version
+    '';
+
 in rec {
 
   # Generate the NixOS manual.
   manual = stdenv.mkDerivation {
     name = "nixos-manual";
 
-    sources = sourceFilesBySuffices ./. [".xml"];
+    inherit sources;
 
     buildInputs = [ libxml2 libxslt ];
 
-    xsltFlags = ''
-      --param section.autolabel 1
-      --param section.label.includes.component.label 1
-      --param html.stylesheet 'style.css'
-      --param xref.with.number.and.title 1
-      --param toc.section.depth 3
-      --param admon.style '''
-      --param callout.graphics.extension '.gif'
-    '';
-
     buildCommand = ''
-      ln -s $sources/*.xml . # */
-      ln -s ${optionsDocBook} options-db.xml
-      echo "${version}" > version
+      ${copySources}
 
       # Check the validity of the manual sources.
       xmllint --noout --nonet --xinclude --noxincludenode \
@@ -69,10 +68,20 @@ in rec {
       # Generate the HTML manual.
       dst=$out/share/doc/nixos
       mkdir -p $dst
-      xsltproc $xsltFlags --nonet --xinclude \
-        --output $dst/manual.html \
-        ${docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \
-        ./manual.xml
+      xsltproc \
+        --param section.autolabel 1 \
+        --param section.label.includes.component.label 1 \
+        --stringparam html.stylesheet style.css \
+        --param xref.with.number.and.title 1 \
+        --param toc.section.depth 3 \
+        --stringparam admon.style "" \
+        --stringparam callout.graphics.extension .gif \
+        --param chunk.section.depth 0 \
+        --param chunk.first.sections 1 \
+        --param use.id.as.filename 1 \
+        --stringparam generate.toc "book toc chapter toc appendix toc" \
+        --nonet --xinclude --output $dst/ \
+        ${docbook5_xsl}/xml/xsl/docbook/xhtml/chunkfast.xsl ./manual.xml
 
       mkdir -p $dst/images/callouts
       cp ${docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/images/callouts/
@@ -90,7 +99,7 @@ in rec {
   manualPDF = stdenv.mkDerivation {
     name = "nixos-manual-pdf";
 
-    sources = sourceFilesBySuffices ./. [".xml"];
+    inherit sources;
 
     buildInputs = [ libxml2 libxslt dblatex tetex ];
 
@@ -98,9 +107,7 @@ in rec {
       # TeX needs a writable font cache.
       export VARTEXFONTS=$TMPDIR/texfonts
 
-      ln -s $sources/*.xml . # */
-      ln -s ${optionsDocBook} options-db.xml
-      echo "${version}" > version
+      ${copySources}
 
       dst=$out/share/doc/nixos
       mkdir -p $dst
@@ -117,13 +124,12 @@ in rec {
   manpages = stdenv.mkDerivation {
     name = "nixos-manpages";
 
-    sources = sourceFilesBySuffices ./. [".xml"];
+    inherit sources;
 
     buildInputs = [ libxml2 libxslt ];
 
     buildCommand = ''
-      ln -s $sources/*.xml . # */
-      ln -s ${optionsDocBook} options-db.xml
+      ${copySources}
 
       # Check the validity of the manual sources.
       xmllint --noout --nonet --xinclude --noxincludenode \
diff --git a/nixos/doc/manual/development.xml b/nixos/doc/manual/development.xml
deleted file mode 100644
index 2f0c2a7aa8d..00000000000
--- a/nixos/doc/manual/development.xml
+++ /dev/null
@@ -1,1119 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-         xmlns:xlink="http://www.w3.org/1999/xlink"
-         xml:id="ch-development">
-
-<title>Development</title>
-
-<para>This chapter describes how you can modify and extend
-NixOS.</para>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-getting-sources">
-
-<title>Getting the sources</title>
-
-<para>By default, NixOS’s <command>nixos-rebuild</command> command
-uses the NixOS and Nixpkgs sources provided by the
-<literal>nixos-unstable</literal> channel (kept in
-<filename>/nix/var/nix/profiles/per-user/root/channels/nixos</filename>).
-To modify NixOS, however, you should check out the latest sources from
-Git.  This is done using the following command:
-
-<screen>
-$ nixos-checkout <replaceable>/my/sources</replaceable>
-</screen>
-
-or
-
-<screen>
-$ mkdir -p <replaceable>/my/sources</replaceable>
-$ cd <replaceable>/my/sources</replaceable>
-$ nix-env -i git
-$ git clone git://github.com/NixOS/nixpkgs.git
-</screen>
-
-This will check out the latest NixOS sources to
-<filename><replaceable>/my/sources</replaceable>/nixpkgs/nixos</filename>
-and the Nixpkgs sources to
-<filename><replaceable>/my/sources</replaceable>/nixpkgs</filename>.
-(The NixOS source tree lives in a subdirectory of the Nixpkgs
-repository.)</para>
-
-<para>It’s often inconvenient to develop directly on the master
-branch, since if somebody has just committed (say) a change to GCC,
-then the binary cache may not have caught up yet and you’ll have to
-rebuild everything from source. So you may want to create a local
-branch based on your current NixOS version:
-
-<screen>
-$ nixos-version
-14.04.273.ea1952b (Baboon)
-
-$ git checkout -b local ea1952b
-</screen>
-
-Or, to base your local branch on the latest version available in the
-NixOS channel:
-
-<screen>
-$ curl -sI http://nixos.org/channels/nixos-unstable/ | grep Location
-Location: http://releases.nixos.org/nixos/unstable/nixos-14.10pre43986.acaf4a6/
-
-$ git checkout -b local acaf4a6
-</screen>
-
-You can then use <command>git rebase</command> to sync your local
-branch with the upstream branch, and use <command>git
-cherry-pick</command> to copy commits from your local branch to the
-upstream branch.</para>
-
-<para>If you want to rebuild your system using your (modified)
-sources, you need to tell <command>nixos-rebuild</command> about them
-using the <option>-I</option> flag:
-
-<screen>
-$ nixos-rebuild switch -I nixpkgs=<replaceable>/my/sources</replaceable>/nixpkgs
-</screen>
-
-</para>
-
-<para>If you want <command>nix-env</command> to use the expressions in
-<replaceable>/my/sources</replaceable>, use <command>nix-env -f
-<replaceable>/my/sources</replaceable>/nixpkgs</command>, or change
-the default by adding a symlink in
-<filename>~/.nix-defexpr</filename>:
-
-<screen>
-$ ln -s <replaceable>/my/sources</replaceable>/nixpkgs ~/.nix-defexpr/nixpkgs
-</screen>
-
-You may want to delete the symlink
-<filename>~/.nix-defexpr/channels_root</filename> to prevent root’s
-NixOS channel from clashing with your own tree.</para>
-
-<!-- FIXME: not sure what this means.
-<para>You should not pass the base directory
-<filename><replaceable>/my/sources</replaceable></filename>
-to <command>nix-env</command>, as it will break after interpreting expressions
-in <filename>nixos/</filename> as packages.</para>
--->
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-writing-modules">
-
-<title>Writing NixOS modules</title>
-
-<para>NixOS has a modular system for declarative configuration.  This
-system combines multiple <emphasis>modules</emphasis> to produce the
-full system configuration.  One of the modules that constitute the
-configuration is <filename>/etc/nixos/configuration.nix</filename>.
-Most of the others live in the <link
-xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><filename>nixos/modules</filename></link>
-subdirectory of the Nixpkgs tree.</para>
-
-<para>Each NixOS module is a file that handles one logical aspect of
-the configuration, such as a specific kind of hardware, a service, or
-network settings.  A module configuration does not have to handle
-everything from scratch; it can use the functionality provided by
-other modules for its implementation.  Thus a module can
-<emphasis>declare</emphasis> options that can be used by other
-modules, and conversely can <emphasis>define</emphasis> options
-provided by other modules in its own implementation.  For example, the
-module <link
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/pam.nix"><filename>pam.nix</filename></link>
-declares the option <option>security.pam.services</option> that allows
-other modules (e.g. <link
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><filename>sshd.nix</filename></link>)
-to define PAM services; and it defines the option
-<option>environment.etc</option> (declared by <link
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><filename>etc.nix</filename></link>)
-to cause files to be created in
-<filename>/etc/pam.d</filename>.</para>
-
-<para xml:id="para-module-syn">In <xref
-linkend="sec-configuration-syntax"/>, we saw the following structure
-of NixOS modules:
-
-<programlisting>
-{ config, pkgs, ... }:
-
-{ <replaceable>option definitions</replaceable>
-}
-</programlisting>
-
-This is actually an <emphasis>abbreviated</emphasis> form of module
-that only defines options, but does not declare any.  The structure of
-full NixOS modules is shown in <xref linkend='ex-module-syntax' />.</para>
-
-<example xml:id='ex-module-syntax'><title>Structure of NixOS modules</title>
-<programlisting>
-{ config, pkgs, ... }: <co xml:id='module-syntax-1' />
-
-{
-  imports =
-    [ <replaceable>paths of other modules</replaceable> <co xml:id='module-syntax-2' />
-    ];
-
-  options = {
-    <replaceable>option declarations</replaceable> <co xml:id='module-syntax-3' />
-  };
-
-  config = {
-    <replaceable>option definitions</replaceable> <co xml:id='module-syntax-4' />
-  };
-}</programlisting>
-</example>
-
-<para>The meaning of each part is as follows.
-
-<calloutlist>
-  <callout arearefs='module-syntax-1'>
-    <para>This line makes the current Nix expression a function.  The
-    variable <varname>pkgs</varname> contains Nixpkgs, while
-    <varname>config</varname> contains the full system configuration.
-    This line can be omitted if there is no reference to
-    <varname>pkgs</varname> and <varname>config</varname> inside the
-    module.</para>
-  </callout>
-
-  <callout arearefs='module-syntax-2'>
-    <para>This list enumerates the paths to other NixOS modules that
-    should be included in the evaluation of the system configuration.
-    A default set of modules is defined in the file
-    <filename>modules/module-list.nix</filename>.  These don't need to
-    be added in the import list.</para>
-  </callout>
-
-  <callout arearefs='module-syntax-3'>
-    <para>The attribute <varname>options</varname> is a nested set of
-    <emphasis>option declarations</emphasis> (described below).</para>
-  </callout>
-
-  <callout arearefs='module-syntax-4'>
-    <para>The attribute <varname>config</varname> is a nested set of
-    <emphasis>option definitions</emphasis> (also described
-    below).</para>
-  </callout>
-</calloutlist>
-
-</para>
-
-<para><xref linkend='locate-example' /> shows a module that handles
-the regular update of the “locate” database, an index of all files in
-the file system.  This module declares two options that can be defined
-by other modules (typically the user’s
-<filename>configuration.nix</filename>):
-<option>services.locate.enable</option> (whether the database should
-be updated) and <option>services.locate.period</option> (when the
-update should be done).  It implements its functionality by defining
-two options declared by other modules:
-<option>systemd.services</option> (the set of all systemd services)
-and <option>services.cron.systemCronJobs</option> (the list of
-commands to be executed periodically by <command>cron</command>).</para>
-
-<example xml:id='locate-example'><title>NixOS module for the “locate” service</title>
-<programlisting>
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let locatedb = "/var/cache/locatedb"; in
-
-{
-  options = {
-
-    services.locate = {
-
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          If enabled, NixOS will periodically update the database of
-          files used by the <command>locate</command> command.
-        '';
-      };
-
-      period = mkOption {
-        type = types.str;
-        default = "15 02 * * *";
-        description = ''
-          This option defines (in the format used by cron) when the
-          locate database is updated.  The default is to update at
-          02:15 at night every day.
-        '';
-      };
-
-    };
-
-  };
-
-  config = {
-
-    systemd.services.update-locatedb =
-      { description = "Update Locate Database";
-        path  = [ pkgs.su ];
-        script =
-          ''
-            mkdir -m 0755 -p $(dirname ${locatedb})
-            exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /media /run'
-          '';
-      };
-
-    services.cron.systemCronJobs = optional config.services.locate.enable
-      "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service";
-
-  };
-}</programlisting>
-</example>
-
-<section><title>Option declarations</title>
-
-<para>An option declaration specifies the name, type and description
-of a NixOS configuration option.  It is illegal to define an option
-that hasn’t been declared in any module.  A option declaration
-generally looks like this:
-
-<programlisting>
-options = {
-  <replaceable>name</replaceable> = mkOption {
-    type = <replaceable>type specification</replaceable>;
-    default = <replaceable>default value</replaceable>;
-    example = <replaceable>example value</replaceable>;
-    description = "<replaceable>Description for use in the NixOS manual.</replaceable>";
-  };
-};
-</programlisting>
-
-</para>
-
-<para>The function <varname>mkOption</varname> accepts the following arguments.
-
-<variablelist>
-
-  <varlistentry>
-    <term><varname>type</varname></term>
-    <listitem>
-      <para>The type of the option (see below).  It may be omitted,
-      but that’s not advisable since it may lead to errors that are
-      hard to diagnose.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>default</varname></term>
-    <listitem>
-      <para>The default value used if no value is defined by any
-      module.  A default is not required; in that case, if the option
-      value is ever used, an error will be thrown.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>example</varname></term>
-    <listitem>
-      <para>An example value that will be shown in the NixOS manual.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>description</varname></term>
-    <listitem>
-      <para>A textual description of the option, in DocBook format,
-      that will be included in the NixOS manual.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-</para>
-
-<para>Here is a non-exhaustive list of option types:
-
-<variablelist>
-
-  <varlistentry>
-    <term><varname>types.bool</varname></term>
-    <listitem>
-      <para>A Boolean.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.int</varname></term>
-    <listitem>
-      <para>An integer.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.str</varname></term>
-    <listitem>
-      <para>A string.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.lines</varname></term>
-    <listitem>
-      <para>A string.  If there are multiple definitions, they are
-      concatenated, with newline characters in between.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.path</varname></term>
-    <listitem>
-      <para>A path, defined as anything that, when coerced to a
-      string, starts with a slash.  This includes derivations.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>A list of elements of type <replaceable>t</replaceable>
-      (e.g., <literal>types.listOf types.str</literal> is a list of
-      strings).  Multiple definitions are concatenated together.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>A set of elements of type <replaceable>t</replaceable>
-      (e.g., <literal>types.attrsOf types.int</literal> is a set of
-      name/value pairs, the values being integers).</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>Either the value <literal>null</literal> or something of
-      type <replaceable>t</replaceable>.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-You can also create new types using the function
-<varname>mkOptionType</varname>.  See
-<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
-
-</section>
-
-
-<section><title>Option definitions</title>
-
-<para>Option definitions are generally straight-forward bindings of values to option names, like
-
-<programlisting>
-config = {
-  services.httpd.enable = true;
-};
-</programlisting>
-
-However, sometimes you need to wrap an option definition or set of
-option definitions in a <emphasis>property</emphasis> to achieve
-certain effects:</para>
-
-<simplesect><title>Delaying conditionals</title>
-
-<para>If a set of option definitions is conditional on the value of
-another option, you may need to use <varname>mkIf</varname>.
-Consider, for instance:
-
-<programlisting>
-config = if config.services.httpd.enable then {
-  environment.systemPackages = [ <replaceable>...</replaceable> ];
-  <replaceable>...</replaceable>
-} else {};
-</programlisting>
-
-This definition will cause Nix to fail with an “infinite recursion”
-error.  Why?  Because the value of
-<option>config.services.httpd.enable</option> depends on the value
-being constructed here.  After all, you could also write the clearly
-circular and contradictory:
-<programlisting>
-config = if config.services.httpd.enable then {
-  services.httpd.enable = false;
-} else {
-  services.httpd.enable = true;
-};
-</programlisting>
-
-The solution is to write:
-
-<programlisting>
-config = mkIf config.services.httpd.enable {
-  environment.systemPackages = [ <replaceable>...</replaceable> ];
-  <replaceable>...</replaceable>
-};
-</programlisting>
-
-The special function <varname>mkIf</varname> causes the evaluation of
-the conditional to be “pushed down” into the individual definitions,
-as if you had written:
-
-<programlisting>
-config = {
-  environment.systemPackages = if config.services.httpd.enable then [ <replaceable>...</replaceable> ] else [];
-  <replaceable>...</replaceable>
-};
-</programlisting>
-
-</para>
-
-</simplesect>
-
-<simplesect><title>Setting priorities</title>
-
-<para>A module can override the definitions of an option in other
-modules by setting a <emphasis>priority</emphasis>.  All option
-definitions that do not have the lowest priority value are discarded.
-By default, option definitions have priority 1000.  You can specify an
-explicit priority by using <varname>mkOverride</varname>, e.g.
-
-<programlisting>
-services.openssh.enable = mkOverride 10 false;
-</programlisting>
-
-This definition causes all other definitions with priorities above 10
-to be discarded.  The function <varname>mkForce</varname> is
-equal to <varname>mkOverride 50</varname>.</para>
-
-</simplesect>
-
-<simplesect><title>Merging configurations</title>
-
-<para>In conjunction with <literal>mkIf</literal>, it is sometimes
-useful for a module to return multiple sets of option definitions, to
-be merged together as if they were declared in separate modules.  This
-can be done using <varname>mkMerge</varname>:
-
-<programlisting>
-config = mkMerge
-  [ # Unconditional stuff.
-    { environment.systemPackages = [ <replaceable>...</replaceable> ];
-    }
-    # Conditional stuff.
-    (mkIf config.services.bla.enable {
-      environment.systemPackages = [ <replaceable>...</replaceable> ];
-    })
-  ];
-</programlisting>
-
-</para>
-
-</simplesect>
-
-</section>
-
-
-<section><title>Important options</title>
-
-<para>NixOS has many options, but some are of particular importance to
-module writers.</para>
-
-<variablelist>
-
-  <varlistentry>
-    <term><option>environment.etc</option></term>
-    <listitem>
-      <para>This set defines files in <filename>/etc</filename>.  A
-      typical use is:
-<programlisting>
-environment.etc."os-release".text =
-  ''
-    NAME=NixOS
-    <replaceable>...</replaceable>
-  '';
-</programlisting>
-      which causes a file named <filename>/etc/os-release</filename>
-      to be created with the given contents.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>system.activationScripts</option></term>
-    <listitem>
-      <para>A set of shell script fragments that must be executed
-      whenever the configuration is activated (i.e., at boot time, or
-      after running <command>nixos-rebuild switch</command>).  For instance,
-<programlisting>
-system.activationScripts.media =
-  ''
-    mkdir -m 0755 -p /media
-  '';
-</programlisting>
-      causes the directory <filename>/media</filename> to be created.
-      Activation scripts must be idempotent.  They should not start
-      background processes such as daemons; use
-      <option>systemd.services</option> for that.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>systemd.services</option></term>
-    <listitem>
-      <para>This is the set of systemd services.  Example:
-<programlisting>
-systemd.services.dhcpcd =
-  { description = "DHCP Client";
-    wantedBy = [ "multi-user.target" ];
-    after = [ "systemd-udev-settle.service" ];
-    path = [ dhcpcd pkgs.nettools pkgs.openresolv ];
-    serviceConfig =
-      { Type = "forking";
-        PIDFile = "/run/dhcpcd.pid";
-        ExecStart = "${dhcpcd}/sbin/dhcpcd --config ${dhcpcdConf}";
-        Restart = "always";
-      };
-  };
-</programlisting>
-      which creates the systemd unit
-      <literal>dhcpcd.service</literal>.  The option
-      <option>wantedBy</option> determined which other units pull this
-      one in; <literal>multi-user.target</literal> is the default
-      target of the system, so <literal>dhcpcd.service</literal> will
-      always be started.  The option
-      <option>serviceConfig.ExecStart</option> provides the main
-      command for the service; it’s also possible to provide pre-start
-      actions, stop scripts, and so on.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>users.extraUsers</option></term>
-    <term><option>users.extraGroups</option></term>
-    <listitem>
-      <para>If your service requires special UIDs or GIDs, you can
-      define them with these options.  See <xref
-      linkend="sec-user-management"/> for details.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-</section>
-
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-building-parts">
-
-<title>Building specific parts of NixOS</title>
-
-<para>With the command <command>nix-build</command>, you can build
-specific parts of your NixOS configuration.  This is done as follows:
-
-<screen>
-$ cd <replaceable>/path/to/nixpkgs/nixos</replaceable>
-$ nix-build -A config.<replaceable>option</replaceable></screen>
-
-where <replaceable>option</replaceable> is a NixOS option with type
-“derivation” (i.e. something that can be built).  Attributes of
-interest include:
-
-<variablelist>
-
-  <varlistentry>
-    <term><varname>system.build.toplevel</varname></term>
-    <listitem>
-      <para>The top-level option that builds the entire NixOS system.
-      Everything else in your configuration is indirectly pulled in by
-      this option.  This is what <command>nixos-rebuild</command>
-      builds and what <filename>/run/current-system</filename> points
-      to afterwards.</para>
-
-      <para>A shortcut to build this is:
-
-<screen>
-$ nix-build -A system</screen>
-      </para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>system.build.manual.manual</varname></term>
-    <listitem><para>The NixOS manual.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>system.build.etc</varname></term>
-    <listitem><para>A tree of symlinks that form the static parts of
-    <filename>/etc</filename>.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>system.build.initialRamdisk</varname></term>
-    <term><varname>system.build.kernel</varname></term>
-    <listitem>
-      <para>The initial ramdisk and kernel of the system.  This allows
-      a quick way to test whether the kernel and the initial ramdisk
-      boot correctly, by using QEMU’s <option>-kernel</option> and
-      <option>-initrd</option> options:
-
-<screen>
-$ nix-build -A config.system.build.initialRamdisk -o initrd
-$ nix-build -A config.system.build.kernel -o kernel
-$ qemu-system-x86_64 -kernel ./kernel/bzImage -initrd ./initrd/initrd -hda /dev/null
-</screen>
-
-      </para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>system.build.nixos-rebuild</varname></term>
-    <term><varname>system.build.nixos-install</varname></term>
-    <term><varname>system.build.nixos-generate-config</varname></term>
-    <listitem>
-      <para>These build the corresponding NixOS commands.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>systemd.units.<replaceable>unit-name</replaceable>.unit</varname></term>
-    <listitem>
-      <para>This builds the unit with the specified name.  Note that
-      since unit names contain dots
-      (e.g. <literal>httpd.service</literal>), you need to put them
-      between quotes, like this:
-
-<screen>
-$ nix-build -A 'config.systemd.units."httpd.service".unit'
-</screen>
-
-      You can also test individual units, without rebuilding the whole
-      system, by putting them in
-      <filename>/run/systemd/system</filename>:
-
-<screen>
-$ cp $(nix-build -A 'config.systemd.units."httpd.service".unit')/httpd.service \
-    /run/systemd/system/tmp-httpd.service
-$ systemctl daemon-reload
-$ systemctl start tmp-httpd.service
-</screen>
-
-      Note that the unit must not have the same name as any unit in
-      <filename>/etc/systemd/system</filename> since those take
-      precedence over <filename>/run/systemd/system</filename>.
-      That’s why the unit is installed as
-      <filename>tmp-httpd.service</filename> here.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-building-cd">
-
-<title>Building your own NixOS CD</title>
-
-<para>Building a NixOS CD is as easy as configuring your own computer. The
-idea is to use another module which will replace
-your <filename>configuration.nix</filename> to configure the system that
-would be installed on the CD.</para>
-
-<para>Default CD/DVD configurations are available
-inside <filename>nixos/modules/installer/cd-dvd</filename>.  To build them
-you have to set <envar>NIXOS_CONFIG</envar> before
-running <command>nix-build</command> to build the ISO.
-
-<screen>
-$ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-minimal.nix</screen>
-
-</para>
-
-<para>Before burning your CD/DVD, you can check the content of the image by mounting anywhere like
-suggested by the following command:
-
-<screen>
-$ mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso</screen>
-
-</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section>
-
-<title>Testing the installer</title>
-
-<para>Building, burning, and booting from an installation CD is rather
-tedious, so here is a quick way to see if the installer works
-properly:
-
-<screen>
-$ nix-build -A config.system.build.nixos-install
-$ mount -t tmpfs none /mnt
-$ ./result/bin/nixos-install</screen>
-
-To start a login shell in the new NixOS installation in
-<filename>/mnt</filename>:
-
-<screen>
-$ ./result/bin/nixos-install --chroot
-</screen>
-
-</para>
-
-</section>
-
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-nixos-tests">
-
-<title>NixOS tests</title>
-
-<para>When you add some feature to NixOS, you should write a test for
-it. NixOS tests are kept in the directory <filename
-xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/tests">nixos/tests</filename>,
-and are executed (using Nix) by a testing framework that automatically
-starts one or more virtual machines containing the NixOS system(s)
-required for the test.</para>
-
-<simplesect><title>Writing tests</title>
-
-<para>A NixOS test is a Nix expression that has the following structure:
-
-<programlisting>
-import ./make-test.nix {
-
-  # Either the configuration of a single machine:
-  machine =
-    { config, pkgs, ... }:
-    { <replaceable>configuration…</replaceable>
-    };
-
-  # Or a set of machines:
-  nodes =
-    { <replaceable>machine1</replaceable> =
-        { config, pkgs, ... }: { <replaceable>…</replaceable> };
-      <replaceable>machine2</replaceable> =
-        { config, pkgs, ... }: { <replaceable>…</replaceable> };
-      …
-    };
-
-  testScript =
-    ''
-      <replaceable>Perl code…</replaceable>
-    '';
-}
-</programlisting>
-
-The attribute <literal>testScript</literal> is a bit of Perl code that
-executes the test (described below). During the test, it will start
-one or more virtual machines, the configuration of which is described
-by the attribute <literal>machine</literal> (if you need only one
-machine in your test) or by the attribute <literal>nodes</literal> (if
-you need multiple machines). For instance, <filename
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">login.nix</filename>
-only needs a single machine to test whether users can log in on the
-virtual console, whether device ownership is correctly maintained when
-switching between consoles, and so on. On the other hand, <filename
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs.nix">nfs.nix</filename>,
-which tests NFS client and server functionality in the Linux kernel
-(including whether locks are maintained across server crashes),
-requires three machines: a server and two clients.</para>
-
-<para>There are a few special NixOS configuration options for test
-VMs:
-
-<!-- FIXME: would be nice to generate this automatically. -->
-
-<variablelist>
-
-  <varlistentry>
-    <term><option>virtualisation.memorySize</option></term>
-    <listitem><para>The memory of the VM in
-    megabytes.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>virtualisation.vlans</option></term>
-    <listitem><para>The virtual networks to which the VM is
-    connected. See <filename
-    xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nat.nix">nat.nix</filename>
-    for an example.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>virtualisation.writableStore</option></term>
-    <listitem><para>By default, the Nix store in the VM is not
-    writable. If you enable this option, a writable union file system
-    is mounted on top of the Nix store to make it appear
-    writable. This is necessary for tests that run Nix operations that
-    modify the store.</para></listitem>
-  </varlistentry>
-
-</variablelist>
-
-For more options, see the module <filename
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/qemu-vm.nix">qemu-vm.nix</filename>.</para>
-
-<para>The test script is a sequence of Perl statements that perform
-various actions, such as starting VMs, executing commands in the VMs,
-and so on. Each virtual machine is represented as an object stored in
-the variable <literal>$<replaceable>name</replaceable></literal>,
-where <replaceable>name</replaceable> is the identifier of the machine
-(which is just <literal>machine</literal> if you didn’t specify
-multiple machines using the <literal>nodes</literal> attribute). For
-instance, the following starts the machine, waits until it has
-finished booting, then executes a command and checks that the output
-is more-or-less correct:
-
-<programlisting>
-$machine->start;
-$machine->waitForUnit("default.target");
-$machine->succeed("uname") =~ /Linux/;
-</programlisting>
-
-The first line is actually unnecessary; machines are implicitly
-started when you first execute an action on them (such as
-<literal>waitForUnit</literal> or <literal>succeed</literal>). If you
-have multiple machines, you can speed up the test by starting them in
-parallel:
-
-<programlisting>
-startAll;
-</programlisting>
-
-</para>
-
-<para>The following methods are available on machine objects:
-
-<variablelist>
-
-  <varlistentry>
-    <term><methodname>start</methodname></term>
-    <listitem><para>Start the virtual machine. This method is
-    asynchronous — it does not wait for the machine to finish
-    booting.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>shutdown</methodname></term>
-    <listitem><para>Shut down the machine, waiting for the VM to
-    exit.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>crash</methodname></term>
-    <listitem><para>Simulate a sudden power failure, by telling the VM
-    to exit immediately.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>block</methodname></term>
-    <listitem><para>Simulate unplugging the Ethernet cable that
-    connects the machine to the other machines.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>unblock</methodname></term>
-    <listitem><para>Undo the effect of
-    <methodname>block</methodname>.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>screenshot</methodname></term>
-    <listitem><para>Take a picture of the display of the virtual
-    machine, in PNG format. The screenshot is linked from the HTML
-    log.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>sendMonitorCommand</methodname></term>
-    <listitem><para>Send a command to the QEMU monitor. This is rarely
-    used, but allows doing stuff such as attaching virtual USB disks
-    to a running machine.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>sendKeys</methodname></term>
-    <listitem><para>Simulate pressing keys on the virtual keyboard,
-    e.g., <literal>sendKeys("ctrl-alt-delete")</literal>.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>sendChars</methodname></term>
-    <listitem><para>Simulate typing a sequence of characters on the
-    virtual keyboard, e.g., <literal>sendKeys("foobar\n")</literal>
-    will type the string <literal>foobar</literal> followed by the
-    Enter key.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>execute</methodname></term>
-    <listitem><para>Execute a shell command, returning a list
-    <literal>(<replaceable>status</replaceable>,
-    <replaceable>stdout</replaceable>)</literal>.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>succeed</methodname></term>
-    <listitem><para>Execute a shell command, raising an exception if
-    the exit status is not zero, otherwise returning the standard
-    output.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>fail</methodname></term>
-    <listitem><para>Like <methodname>succeed</methodname>, but raising
-    an exception if the command returns a zero status.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitUntilSucceeds</methodname></term>
-    <listitem><para>Repeat a shell command with 1-second intervals
-    until it succeeds.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitUntilFails</methodname></term>
-    <listitem><para>Repeat a shell command with 1-second intervals
-    until it fails.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitForUnit</methodname></term>
-    <listitem><para>Wait until the specified systemd unit has reached
-    the “active” state.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitForFile</methodname></term>
-    <listitem><para>Wait until the specified file
-    exists.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitForOpenPort</methodname></term>
-    <listitem><para>Wait until a process is listening on the given TCP
-    port (on <literal>localhost</literal>, at least).</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitForClosedPort</methodname></term>
-    <listitem><para>Wait until nobody is listening on the given TCP
-    port.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitForX</methodname></term>
-    <listitem><para>Wait until the X11 server is accepting
-    connections.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><methodname>waitForWindow</methodname></term>
-    <listitem><para>Wait until an X11 window has appeared whose name
-    matches the given regular expression, e.g.,
-    <literal>waitForWindow(qr/Terminal/)</literal>.</para></listitem>
-  </varlistentry>
-
-</variablelist>
-
-</para>
-
-</simplesect>
-
-
-<simplesect><title>Running tests</title>
-
-<para>You can run tests using <command>nix-build</command>. For
-example, to run the test <filename
-xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">login.nix</filename>,
-you just do:
-
-<screen>
-$ nix-build '&lt;nixpkgs/nixos/tests/login.nix>'
-</screen>
-
-or, if you don’t want to rely on <envar>NIX_PATH</envar>:
-
-<screen>
-$ cd /my/nixpkgs/nixos/tests
-$ nix-build login.nix
-…
-running the VM test script
-machine: QEMU running (pid 8841)
-…
-6 out of 6 tests succeeded
-</screen>
-
-After building/downloading all required dependencies, this will
-perform a build that starts a QEMU/KVM virtual machine containing a
-NixOS system. The virtual machine mounts the Nix store of the host;
-this makes VM creation very fast, as no disk image needs to be
-created. Afterwards, you can view a pretty-printed log of the test:
-
-<screen>
-$ firefox result/log.html
-</screen>
-
-</para>
-
-<para>It is also possible to run the test environment interactively,
-allowing you to experiment with the VMs.  For example:
-
-<screen>
-$ nix-build login.nix -A driver
-$ ./result/bin/nixos-run-vms
-</screen>
-
-The script <command>nixos-run-vms</command> starts the virtual
-machines defined by test.  The root file system of the VMs is created
-on the fly and kept across VM restarts in
-<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
-
-<para>Finally, the test itself can be run interactively.  This is
-particularly useful when developing or debugging a test:
-
-<screen>
-$ nix-build tests/ -A nfs.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; $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>
-
-</simplesect>
-
-</section>
-
-
-</chapter>
diff --git a/nixos/doc/manual/development/building-nixos.xml b/nixos/doc/manual/development/building-nixos.xml
new file mode 100644
index 00000000000..21c5bfe6a5b
--- /dev/null
+++ b/nixos/doc/manual/development/building-nixos.xml
@@ -0,0 +1,32 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-building-cd">
+
+<title>Building Your Own NixOS CD</title>
+
+<para>Building a NixOS CD is as easy as configuring your own computer. The
+idea is to use another module which will replace
+your <filename>configuration.nix</filename> to configure the system that
+would be installed on the CD.</para>
+
+<para>Default CD/DVD configurations are available
+inside <filename>nixos/modules/installer/cd-dvd</filename>.  To build them
+you have to set <envar>NIXOS_CONFIG</envar> before
+running <command>nix-build</command> to build the ISO.
+
+<screen>
+$ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-minimal.nix</screen>
+
+</para>
+
+<para>Before burning your CD/DVD, you can check the content of the image by mounting anywhere like
+suggested by the following command:
+
+<screen>
+$ mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso</screen>
+
+</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/building-parts.xml b/nixos/doc/manual/development/building-parts.xml
new file mode 100644
index 00000000000..cb8dee039c8
--- /dev/null
+++ b/nixos/doc/manual/development/building-parts.xml
@@ -0,0 +1,113 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-building-parts">
+
+<title>Building Specific Parts of NixOS</title>
+
+<para>With the command <command>nix-build</command>, you can build
+specific parts of your NixOS configuration.  This is done as follows:
+
+<screen>
+$ cd <replaceable>/path/to/nixpkgs/nixos</replaceable>
+$ nix-build -A config.<replaceable>option</replaceable></screen>
+
+where <replaceable>option</replaceable> is a NixOS option with type
+“derivation” (i.e. something that can be built).  Attributes of
+interest include:
+
+<variablelist>
+
+  <varlistentry>
+    <term><varname>system.build.toplevel</varname></term>
+    <listitem>
+      <para>The top-level option that builds the entire NixOS system.
+      Everything else in your configuration is indirectly pulled in by
+      this option.  This is what <command>nixos-rebuild</command>
+      builds and what <filename>/run/current-system</filename> points
+      to afterwards.</para>
+
+      <para>A shortcut to build this is:
+
+<screen>
+$ nix-build -A system</screen>
+      </para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>system.build.manual.manual</varname></term>
+    <listitem><para>The NixOS manual.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>system.build.etc</varname></term>
+    <listitem><para>A tree of symlinks that form the static parts of
+    <filename>/etc</filename>.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>system.build.initialRamdisk</varname></term>
+    <term><varname>system.build.kernel</varname></term>
+    <listitem>
+      <para>The initial ramdisk and kernel of the system.  This allows
+      a quick way to test whether the kernel and the initial ramdisk
+      boot correctly, by using QEMU’s <option>-kernel</option> and
+      <option>-initrd</option> options:
+
+<screen>
+$ nix-build -A config.system.build.initialRamdisk -o initrd
+$ nix-build -A config.system.build.kernel -o kernel
+$ qemu-system-x86_64 -kernel ./kernel/bzImage -initrd ./initrd/initrd -hda /dev/null
+</screen>
+
+      </para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>system.build.nixos-rebuild</varname></term>
+    <term><varname>system.build.nixos-install</varname></term>
+    <term><varname>system.build.nixos-generate-config</varname></term>
+    <listitem>
+      <para>These build the corresponding NixOS commands.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>systemd.units.<replaceable>unit-name</replaceable>.unit</varname></term>
+    <listitem>
+      <para>This builds the unit with the specified name.  Note that
+      since unit names contain dots
+      (e.g. <literal>httpd.service</literal>), you need to put them
+      between quotes, like this:
+
+<screen>
+$ nix-build -A 'config.systemd.units."httpd.service".unit'
+</screen>
+
+      You can also test individual units, without rebuilding the whole
+      system, by putting them in
+      <filename>/run/systemd/system</filename>:
+
+<screen>
+$ cp $(nix-build -A 'config.systemd.units."httpd.service".unit')/httpd.service \
+    /run/systemd/system/tmp-httpd.service
+$ systemctl daemon-reload
+$ systemctl start tmp-httpd.service
+</screen>
+
+      Note that the unit must not have the same name as any unit in
+      <filename>/etc/systemd/system</filename> since those take
+      precedence over <filename>/run/systemd/system</filename>.
+      That’s why the unit is installed as
+      <filename>tmp-httpd.service</filename> here.</para>
+    </listitem>
+  </varlistentry>
+
+</variablelist>
+
+</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/development.xml b/nixos/doc/manual/development/development.xml
new file mode 100644
index 00000000000..747159c4427
--- /dev/null
+++ b/nixos/doc/manual/development/development.xml
@@ -0,0 +1,20 @@
+<part   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="ch-development">
+
+<title>Development</title>
+
+<partintro>
+<para>This chapter describes how you can modify and extend
+NixOS.</para>
+</partintro>
+
+<xi:include href="sources.xml" />
+<xi:include href="writing-modules.xml" />
+<xi:include href="building-parts.xml" />
+<xi:include href="building-nixos.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
new file mode 100644
index 00000000000..a98da993330
--- /dev/null
+++ b/nixos/doc/manual/development/nixos-tests.xml
@@ -0,0 +1,19 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-nixos-tests">
+
+<title>NixOS Tests</title>
+
+<para>When you add some feature to NixOS, you should write a test for
+it. NixOS tests are kept in the directory <filename
+xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/tests">nixos/tests</filename>,
+and are executed (using Nix) by a testing framework that automatically
+starts one or more virtual machines containing the NixOS system(s)
+required for the test.</para>
+
+<xi:include href="writing-nixos-tests.xml" />
+<xi:include href="running-nixos-tests.xml" />
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml
new file mode 100644
index 00000000000..6d93dc5c009
--- /dev/null
+++ b/nixos/doc/manual/development/option-declarations.xml
@@ -0,0 +1,141 @@
+<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-option-declarations">
+
+<title>Option Declarations</title>
+
+<para>An option declaration specifies the name, type and description
+of a NixOS configuration option.  It is illegal to define an option
+that hasn’t been declared in any module.  A option declaration
+generally looks like this:
+
+<programlisting>
+options = {
+  <replaceable>name</replaceable> = mkOption {
+    type = <replaceable>type specification</replaceable>;
+    default = <replaceable>default value</replaceable>;
+    example = <replaceable>example value</replaceable>;
+    description = "<replaceable>Description for use in the NixOS manual.</replaceable>";
+  };
+};
+</programlisting>
+
+</para>
+
+<para>The function <varname>mkOption</varname> accepts the following arguments.
+
+<variablelist>
+
+  <varlistentry>
+    <term><varname>type</varname></term>
+    <listitem>
+      <para>The type of the option (see below).  It may be omitted,
+      but that’s not advisable since it may lead to errors that are
+      hard to diagnose.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>default</varname></term>
+    <listitem>
+      <para>The default value used if no value is defined by any
+      module.  A default is not required; in that case, if the option
+      value is ever used, an error will be thrown.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>example</varname></term>
+    <listitem>
+      <para>An example value that will be shown in the NixOS manual.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>description</varname></term>
+    <listitem>
+      <para>A textual description of the option, in DocBook format,
+      that will be included in the NixOS manual.</para>
+    </listitem>
+  </varlistentry>
+
+</variablelist>
+
+</para>
+
+<para>Here is a non-exhaustive list of option types:
+
+<variablelist>
+
+  <varlistentry>
+    <term><varname>types.bool</varname></term>
+    <listitem>
+      <para>A Boolean.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.int</varname></term>
+    <listitem>
+      <para>An integer.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.str</varname></term>
+    <listitem>
+      <para>A string.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.lines</varname></term>
+    <listitem>
+      <para>A string.  If there are multiple definitions, they are
+      concatenated, with newline characters in between.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.path</varname></term>
+    <listitem>
+      <para>A path, defined as anything that, when coerced to a
+      string, starts with a slash.  This includes derivations.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
+    <listitem>
+      <para>A list of elements of type <replaceable>t</replaceable>
+      (e.g., <literal>types.listOf types.str</literal> is a list of
+      strings).  Multiple definitions are concatenated together.</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
+    <listitem>
+      <para>A set of elements of type <replaceable>t</replaceable>
+      (e.g., <literal>types.attrsOf types.int</literal> is a set of
+      name/value pairs, the values being integers).</para>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
+    <listitem>
+      <para>Either the value <literal>null</literal> or something of
+      type <replaceable>t</replaceable>.</para>
+    </listitem>
+  </varlistentry>
+
+</variablelist>
+
+You can also create new types using the function
+<varname>mkOptionType</varname>.  See
+<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/option-def.xml b/nixos/doc/manual/development/option-def.xml
new file mode 100644
index 00000000000..4e267ecfd1e
--- /dev/null
+++ b/nixos/doc/manual/development/option-def.xml
@@ -0,0 +1,112 @@
+<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-option-definitions">
+
+<title>Option Definitions</title>
+
+<para>Option definitions are generally straight-forward bindings of values to option names, like
+
+<programlisting>
+config = {
+  services.httpd.enable = true;
+};
+</programlisting>
+
+However, sometimes you need to wrap an option definition or set of
+option definitions in a <emphasis>property</emphasis> to achieve
+certain effects:</para>
+
+<simplesect><title>Delaying Conditionals</title>
+
+<para>If a set of option definitions is conditional on the value of
+another option, you may need to use <varname>mkIf</varname>.
+Consider, for instance:
+
+<programlisting>
+config = if config.services.httpd.enable then {
+  environment.systemPackages = [ <replaceable>...</replaceable> ];
+  <replaceable>...</replaceable>
+} else {};
+</programlisting>
+
+This definition will cause Nix to fail with an “infinite recursion”
+error.  Why?  Because the value of
+<option>config.services.httpd.enable</option> depends on the value
+being constructed here.  After all, you could also write the clearly
+circular and contradictory:
+<programlisting>
+config = if config.services.httpd.enable then {
+  services.httpd.enable = false;
+} else {
+  services.httpd.enable = true;
+};
+</programlisting>
+
+The solution is to write:
+
+<programlisting>
+config = mkIf config.services.httpd.enable {
+  environment.systemPackages = [ <replaceable>...</replaceable> ];
+  <replaceable>...</replaceable>
+};
+</programlisting>
+
+The special function <varname>mkIf</varname> causes the evaluation of
+the conditional to be “pushed down” into the individual definitions,
+as if you had written:
+
+<programlisting>
+config = {
+  environment.systemPackages = if config.services.httpd.enable then [ <replaceable>...</replaceable> ] else [];
+  <replaceable>...</replaceable>
+};
+</programlisting>
+
+</para>
+
+</simplesect>
+
+<simplesect><title>Setting Priorities</title>
+
+<para>A module can override the definitions of an option in other
+modules by setting a <emphasis>priority</emphasis>.  All option
+definitions that do not have the lowest priority value are discarded.
+By default, option definitions have priority 1000.  You can specify an
+explicit priority by using <varname>mkOverride</varname>, e.g.
+
+<programlisting>
+services.openssh.enable = mkOverride 10 false;
+</programlisting>
+
+This definition causes all other definitions with priorities above 10
+to be discarded.  The function <varname>mkForce</varname> is
+equal to <varname>mkOverride 50</varname>.</para>
+
+</simplesect>
+
+<simplesect><title>Merging Configurations</title>
+
+<para>In conjunction with <literal>mkIf</literal>, it is sometimes
+useful for a module to return multiple sets of option definitions, to
+be merged together as if they were declared in separate modules.  This
+can be done using <varname>mkMerge</varname>:
+
+<programlisting>
+config = mkMerge
+  [ # Unconditional stuff.
+    { environment.systemPackages = [ <replaceable>...</replaceable> ];
+    }
+    # Conditional stuff.
+    (mkIf config.services.bla.enable {
+      environment.systemPackages = [ <replaceable>...</replaceable> ];
+    })
+  ];
+</programlisting>
+
+</para>
+
+</simplesect>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/running-nixos-tests.xml b/nixos/doc/manual/development/running-nixos-tests.xml
new file mode 100644
index 00000000000..d9be761eb01
--- /dev/null
+++ b/nixos/doc/manual/development/running-nixos-tests.xml
@@ -0,0 +1,77 @@
+<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</title>
+
+<para>You can run tests using <command>nix-build</command>. For
+example, to run the test <filename
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">login.nix</filename>,
+you just do:
+
+<screen>
+$ nix-build '&lt;nixpkgs/nixos/tests/login.nix>'
+</screen>
+
+or, if you don’t want to rely on <envar>NIX_PATH</envar>:
+
+<screen>
+$ cd /my/nixpkgs/nixos/tests
+$ nix-build login.nix
+…
+running the VM test script
+machine: QEMU running (pid 8841)
+…
+6 out of 6 tests succeeded
+</screen>
+
+After building/downloading all required dependencies, this will
+perform a build that starts a QEMU/KVM virtual machine containing a
+NixOS system. The virtual machine mounts the Nix store of the host;
+this makes VM creation very fast, as no disk image needs to be
+created. Afterwards, you can view a pretty-printed log of the test:
+
+<screen>
+$ firefox result/log.html
+</screen>
+
+</para>
+
+<para>It is also possible to run the test environment interactively,
+allowing you to experiment with the VMs.  For example:
+
+<screen>
+$ nix-build login.nix -A driver
+$ ./result/bin/nixos-run-vms
+</screen>
+
+The script <command>nixos-run-vms</command> starts the virtual
+machines defined by test.  The root file system of the VMs is created
+on the fly and kept across VM restarts in
+<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
+
+<para>Finally, the test itself can be run interactively.  This is
+particularly useful when developing or debugging a test:
+
+<screen>
+$ nix-build tests/ -A nfs.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; $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>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/sources.xml b/nixos/doc/manual/development/sources.xml
new file mode 100644
index 00000000000..992a07af981
--- /dev/null
+++ b/nixos/doc/manual/development/sources.xml
@@ -0,0 +1,95 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-getting-sources">
+
+<title>Getting the Sources</title>
+
+<para>By default, NixOS’s <command>nixos-rebuild</command> command
+uses the NixOS and Nixpkgs sources provided by the
+<literal>nixos-unstable</literal> channel (kept in
+<filename>/nix/var/nix/profiles/per-user/root/channels/nixos</filename>).
+To modify NixOS, however, you should check out the latest sources from
+Git.  This is done using the following command:
+
+<screen>
+$ nixos-checkout <replaceable>/my/sources</replaceable>
+</screen>
+
+or
+
+<screen>
+$ mkdir -p <replaceable>/my/sources</replaceable>
+$ cd <replaceable>/my/sources</replaceable>
+$ nix-env -i git
+$ git clone git://github.com/NixOS/nixpkgs.git
+</screen>
+
+This will check out the latest NixOS sources to
+<filename><replaceable>/my/sources</replaceable>/nixpkgs/nixos</filename>
+and the Nixpkgs sources to
+<filename><replaceable>/my/sources</replaceable>/nixpkgs</filename>.
+(The NixOS source tree lives in a subdirectory of the Nixpkgs
+repository.)</para>
+
+<para>It’s often inconvenient to develop directly on the master
+branch, since if somebody has just committed (say) a change to GCC,
+then the binary cache may not have caught up yet and you’ll have to
+rebuild everything from source. So you may want to create a local
+branch based on your current NixOS version:
+
+<screen>
+$ nixos-version
+14.04.273.ea1952b (Baboon)
+
+$ git checkout -b local ea1952b
+</screen>
+
+Or, to base your local branch on the latest version available in the
+NixOS channel:
+
+<screen>
+$ curl -sI http://nixos.org/channels/nixos-unstable/ | grep Location
+Location: http://releases.nixos.org/nixos/unstable/nixos-14.10pre43986.acaf4a6/
+
+$ git checkout -b local acaf4a6
+</screen>
+
+You can then use <command>git rebase</command> to sync your local
+branch with the upstream branch, and use <command>git
+cherry-pick</command> to copy commits from your local branch to the
+upstream branch.</para>
+
+<para>If you want to rebuild your system using your (modified)
+sources, you need to tell <command>nixos-rebuild</command> about them
+using the <option>-I</option> flag:
+
+<screen>
+$ nixos-rebuild switch -I nixpkgs=<replaceable>/my/sources</replaceable>/nixpkgs
+</screen>
+
+</para>
+
+<para>If you want <command>nix-env</command> to use the expressions in
+<replaceable>/my/sources</replaceable>, use <command>nix-env -f
+<replaceable>/my/sources</replaceable>/nixpkgs</command>, or change
+the default by adding a symlink in
+<filename>~/.nix-defexpr</filename>:
+
+<screen>
+$ ln -s <replaceable>/my/sources</replaceable>/nixpkgs ~/.nix-defexpr/nixpkgs
+</screen>
+
+You may want to delete the symlink
+<filename>~/.nix-defexpr/channels_root</filename> to prevent root’s
+NixOS channel from clashing with your own tree.</para>
+
+<!-- FIXME: not sure what this means.
+<para>You should not pass the base directory
+<filename><replaceable>/my/sources</replaceable></filename>
+to <command>nix-env</command>, as it will break after interpreting expressions
+in <filename>nixos/</filename> as packages.</para>
+-->
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/testing-installer.xml b/nixos/doc/manual/development/testing-installer.xml
new file mode 100644
index 00000000000..87e40e32617
--- /dev/null
+++ b/nixos/doc/manual/development/testing-installer.xml
@@ -0,0 +1,27 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="ch-testing-installer">
+
+<title>Testing the Installer</title>
+
+<para>Building, burning, and booting from an installation CD is rather
+tedious, so here is a quick way to see if the installer works
+properly:
+
+<screen>
+$ nix-build -A config.system.build.nixos-install
+$ mount -t tmpfs none /mnt
+$ ./result/bin/nixos-install</screen>
+
+To start a login shell in the new NixOS installation in
+<filename>/mnt</filename>:
+
+<screen>
+$ ./result/bin/nixos-install --chroot
+</screen>
+
+</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml
new file mode 100644
index 00000000000..9cf29e5dc57
--- /dev/null
+++ b/nixos/doc/manual/development/writing-modules.xml
@@ -0,0 +1,175 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-writing-modules">
+
+<title>Writing NixOS Modules</title>
+
+<para>NixOS has a modular system for declarative configuration.  This
+system combines multiple <emphasis>modules</emphasis> to produce the
+full system configuration.  One of the modules that constitute the
+configuration is <filename>/etc/nixos/configuration.nix</filename>.
+Most of the others live in the <link
+xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><filename>nixos/modules</filename></link>
+subdirectory of the Nixpkgs tree.</para>
+
+<para>Each NixOS module is a file that handles one logical aspect of
+the configuration, such as a specific kind of hardware, a service, or
+network settings.  A module configuration does not have to handle
+everything from scratch; it can use the functionality provided by
+other modules for its implementation.  Thus a module can
+<emphasis>declare</emphasis> options that can be used by other
+modules, and conversely can <emphasis>define</emphasis> options
+provided by other modules in its own implementation.  For example, the
+module <link
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/pam.nix"><filename>pam.nix</filename></link>
+declares the option <option>security.pam.services</option> that allows
+other modules (e.g. <link
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><filename>sshd.nix</filename></link>)
+to define PAM services; and it defines the option
+<option>environment.etc</option> (declared by <link
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><filename>etc.nix</filename></link>)
+to cause files to be created in
+<filename>/etc/pam.d</filename>.</para>
+
+<para xml:id="para-module-syn">In <xref
+linkend="sec-configuration-syntax"/>, we saw the following structure
+of NixOS modules:
+
+<programlisting>
+{ config, pkgs, ... }:
+
+{ <replaceable>option definitions</replaceable>
+}
+</programlisting>
+
+This is actually an <emphasis>abbreviated</emphasis> form of module
+that only defines options, but does not declare any.  The structure of
+full NixOS modules is shown in <xref linkend='ex-module-syntax' />.</para>
+
+<example xml:id='ex-module-syntax'><title>Structure of NixOS Modules</title>
+<programlisting>
+{ config, pkgs, ... }: <co xml:id='module-syntax-1' />
+
+{
+  imports =
+    [ <replaceable>paths of other modules</replaceable> <co xml:id='module-syntax-2' />
+    ];
+
+  options = {
+    <replaceable>option declarations</replaceable> <co xml:id='module-syntax-3' />
+  };
+
+  config = {
+    <replaceable>option definitions</replaceable> <co xml:id='module-syntax-4' />
+  };
+}</programlisting>
+</example>
+
+<para>The meaning of each part is as follows.
+
+<calloutlist>
+  <callout arearefs='module-syntax-1'>
+    <para>This line makes the current Nix expression a function.  The
+    variable <varname>pkgs</varname> contains Nixpkgs, while
+    <varname>config</varname> contains the full system configuration.
+    This line can be omitted if there is no reference to
+    <varname>pkgs</varname> and <varname>config</varname> inside the
+    module.</para>
+  </callout>
+
+  <callout arearefs='module-syntax-2'>
+    <para>This list enumerates the paths to other NixOS modules that
+    should be included in the evaluation of the system configuration.
+    A default set of modules is defined in the file
+    <filename>modules/module-list.nix</filename>.  These don't need to
+    be added in the import list.</para>
+  </callout>
+
+  <callout arearefs='module-syntax-3'>
+    <para>The attribute <varname>options</varname> is a nested set of
+    <emphasis>option declarations</emphasis> (described below).</para>
+  </callout>
+
+  <callout arearefs='module-syntax-4'>
+    <para>The attribute <varname>config</varname> is a nested set of
+    <emphasis>option definitions</emphasis> (also described
+    below).</para>
+  </callout>
+</calloutlist>
+
+</para>
+
+<para><xref linkend='locate-example' /> shows a module that handles
+the regular update of the “locate” database, an index of all files in
+the file system.  This module declares two options that can be defined
+by other modules (typically the user’s
+<filename>configuration.nix</filename>):
+<option>services.locate.enable</option> (whether the database should
+be updated) and <option>services.locate.period</option> (when the
+update should be done).  It implements its functionality by defining
+two options declared by other modules:
+<option>systemd.services</option> (the set of all systemd services)
+and <option>services.cron.systemCronJobs</option> (the list of
+commands to be executed periodically by <command>cron</command>).</para>
+
+<example xml:id='locate-example'><title>NixOS Module for the “locate” Service</title>
+<programlisting>
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let locatedb = "/var/cache/locatedb"; in
+
+{
+  options = {
+
+    services.locate = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If enabled, NixOS will periodically update the database of
+          files used by the <command>locate</command> command.
+        '';
+      };
+
+      period = mkOption {
+        type = types.str;
+        default = "15 02 * * *";
+        description = ''
+          This option defines (in the format used by cron) when the
+          locate database is updated.  The default is to update at
+          02:15 at night every day.
+        '';
+      };
+
+    };
+
+  };
+
+  config = {
+
+    systemd.services.update-locatedb =
+      { description = "Update Locate Database";
+        path  = [ pkgs.su ];
+        script =
+          ''
+            mkdir -m 0755 -p $(dirname ${locatedb})
+            exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /media /run'
+          '';
+      };
+
+    services.cron.systemCronJobs = optional config.services.locate.enable
+      "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service";
+
+  };
+}</programlisting>
+</example>
+
+<xi:include href="option-declarations.xml" />
+<xi:include href="option-def.xml" />
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/development/writing-nixos-tests.xml b/nixos/doc/manual/development/writing-nixos-tests.xml
new file mode 100644
index 00000000000..bbb655eed2a
--- /dev/null
+++ b/nixos/doc/manual/development/writing-nixos-tests.xml
@@ -0,0 +1,251 @@
+<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-writing-nixos-tests">
+
+<title>Writing Tests</title>
+
+<para>A NixOS test is a Nix expression that has the following structure:
+
+<programlisting>
+import ./make-test.nix {
+
+  # Either the configuration of a single machine:
+  machine =
+    { config, pkgs, ... }:
+    { <replaceable>configuration…</replaceable>
+    };
+
+  # Or a set of machines:
+  nodes =
+    { <replaceable>machine1</replaceable> =
+        { config, pkgs, ... }: { <replaceable>…</replaceable> };
+      <replaceable>machine2</replaceable> =
+        { config, pkgs, ... }: { <replaceable>…</replaceable> };
+      …
+    };
+
+  testScript =
+    ''
+      <replaceable>Perl code…</replaceable>
+    '';
+}
+</programlisting>
+
+The attribute <literal>testScript</literal> is a bit of Perl code that
+executes the test (described below). During the test, it will start
+one or more virtual machines, the configuration of which is described
+by the attribute <literal>machine</literal> (if you need only one
+machine in your test) or by the attribute <literal>nodes</literal> (if
+you need multiple machines). For instance, <filename
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">login.nix</filename>
+only needs a single machine to test whether users can log in on the
+virtual console, whether device ownership is correctly maintained when
+switching between consoles, and so on. On the other hand, <filename
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs.nix">nfs.nix</filename>,
+which tests NFS client and server functionality in the Linux kernel
+(including whether locks are maintained across server crashes),
+requires three machines: a server and two clients.</para>
+
+<para>There are a few special NixOS configuration options for test
+VMs:
+
+<!-- FIXME: would be nice to generate this automatically. -->
+
+<variablelist>
+
+  <varlistentry>
+    <term><option>virtualisation.memorySize</option></term>
+    <listitem><para>The memory of the VM in
+    megabytes.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><option>virtualisation.vlans</option></term>
+    <listitem><para>The virtual networks to which the VM is
+    connected. See <filename
+    xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nat.nix">nat.nix</filename>
+    for an example.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><option>virtualisation.writableStore</option></term>
+    <listitem><para>By default, the Nix store in the VM is not
+    writable. If you enable this option, a writable union file system
+    is mounted on top of the Nix store to make it appear
+    writable. This is necessary for tests that run Nix operations that
+    modify the store.</para></listitem>
+  </varlistentry>
+
+</variablelist>
+
+For more options, see the module <filename
+xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/qemu-vm.nix">qemu-vm.nix</filename>.</para>
+
+<para>The test script is a sequence of Perl statements that perform
+various actions, such as starting VMs, executing commands in the VMs,
+and so on. Each virtual machine is represented as an object stored in
+the variable <literal>$<replaceable>name</replaceable></literal>,
+where <replaceable>name</replaceable> is the identifier of the machine
+(which is just <literal>machine</literal> if you didn’t specify
+multiple machines using the <literal>nodes</literal> attribute). For
+instance, the following starts the machine, waits until it has
+finished booting, then executes a command and checks that the output
+is more-or-less correct:
+
+<programlisting>
+$machine->start;
+$machine->waitForUnit("default.target");
+$machine->succeed("uname") =~ /Linux/;
+</programlisting>
+
+The first line is actually unnecessary; machines are implicitly
+started when you first execute an action on them (such as
+<literal>waitForUnit</literal> or <literal>succeed</literal>). If you
+have multiple machines, you can speed up the test by starting them in
+parallel:
+
+<programlisting>
+startAll;
+</programlisting>
+
+</para>
+
+<para>The following methods are available on machine objects:
+
+<variablelist>
+
+  <varlistentry>
+    <term><methodname>start</methodname></term>
+    <listitem><para>Start the virtual machine. This method is
+    asynchronous — it does not wait for the machine to finish
+    booting.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>shutdown</methodname></term>
+    <listitem><para>Shut down the machine, waiting for the VM to
+    exit.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>crash</methodname></term>
+    <listitem><para>Simulate a sudden power failure, by telling the VM
+    to exit immediately.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>block</methodname></term>
+    <listitem><para>Simulate unplugging the Ethernet cable that
+    connects the machine to the other machines.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>unblock</methodname></term>
+    <listitem><para>Undo the effect of
+    <methodname>block</methodname>.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>screenshot</methodname></term>
+    <listitem><para>Take a picture of the display of the virtual
+    machine, in PNG format. The screenshot is linked from the HTML
+    log.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>sendMonitorCommand</methodname></term>
+    <listitem><para>Send a command to the QEMU monitor. This is rarely
+    used, but allows doing stuff such as attaching virtual USB disks
+    to a running machine.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>sendKeys</methodname></term>
+    <listitem><para>Simulate pressing keys on the virtual keyboard,
+    e.g., <literal>sendKeys("ctrl-alt-delete")</literal>.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>sendChars</methodname></term>
+    <listitem><para>Simulate typing a sequence of characters on the
+    virtual keyboard, e.g., <literal>sendKeys("foobar\n")</literal>
+    will type the string <literal>foobar</literal> followed by the
+    Enter key.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>execute</methodname></term>
+    <listitem><para>Execute a shell command, returning a list
+    <literal>(<replaceable>status</replaceable>,
+    <replaceable>stdout</replaceable>)</literal>.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>succeed</methodname></term>
+    <listitem><para>Execute a shell command, raising an exception if
+    the exit status is not zero, otherwise returning the standard
+    output.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>fail</methodname></term>
+    <listitem><para>Like <methodname>succeed</methodname>, but raising
+    an exception if the command returns a zero status.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitUntilSucceeds</methodname></term>
+    <listitem><para>Repeat a shell command with 1-second intervals
+    until it succeeds.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitUntilFails</methodname></term>
+    <listitem><para>Repeat a shell command with 1-second intervals
+    until it fails.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitForUnit</methodname></term>
+    <listitem><para>Wait until the specified systemd unit has reached
+    the “active” state.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitForFile</methodname></term>
+    <listitem><para>Wait until the specified file
+    exists.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitForOpenPort</methodname></term>
+    <listitem><para>Wait until a process is listening on the given TCP
+    port (on <literal>localhost</literal>, at least).</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitForClosedPort</methodname></term>
+    <listitem><para>Wait until nobody is listening on the given TCP
+    port.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitForX</methodname></term>
+    <listitem><para>Wait until the X11 server is accepting
+    connections.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><methodname>waitForWindow</methodname></term>
+    <listitem><para>Wait until an X11 window has appeared whose name
+    matches the given regular expression, e.g.,
+    <literal>waitForWindow(qr/Terminal/)</literal>.</para></listitem>
+  </varlistentry>
+
+</variablelist>
+
+</para>
+
+</section>
\ No newline at end of file
diff --git a/nixos/doc/manual/installation.xml b/nixos/doc/manual/installation.xml
deleted file mode 100644
index 4cbfcc229fa..00000000000
--- a/nixos/doc/manual/installation.xml
+++ /dev/null
@@ -1,570 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-         xmlns:xlink="http://www.w3.org/1999/xlink"
-         xml:id="ch-installation">
-
-<title>Installing NixOS</title>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-obtaining">
-
-<title>Obtaining NixOS</title>
-
-<para>NixOS ISO images can be downloaded from the <link
-xlink:href="http://nixos.org/nixos/download.html">NixOS
-homepage</link>.  These can be burned onto a CD.  It is also possible
-to copy them onto a USB stick and install NixOS from there.  For
-details, see the <link
-xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS
-Wiki</link>.</para>
-
-<para>As an alternative to installing NixOS yourself, you can get a
-running NixOS system through several other means:
-
-<itemizedlist>
-  <listitem>
-    <para>Using virtual appliances in Open Virtualization Format (OVF)
-    that can be imported into VirtualBox.  These are available from
-    the <link xlink:href="http://nixos.org/nixos/download.html">NixOS
-    homepage</link>.</para>
-  </listitem>
-  <listitem>
-    <para>Using AMIs for Amazon’s EC2.  To find one for your region
-    and instance type, please refer to the <link
-    xlink:href="https://github.com/NixOS/nixops/blob/master/nix/ec2-amis.nix">list
-    of most recent AMIs</link>.</para>
-  </listitem>
-  <listitem>
-    <para>Using NixOps, the NixOS-based cloud deployment tool, which
-    allows you to provision VirtualBox and EC2 NixOS instances from
-    declarative specifications.  Check out the <link
-    xlink:href="https://github.com/NixOS/nixops">NixOps
-    homepage</link> for details.</para>
-  </listitem>
-</itemizedlist>
-
-</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-installation">
-
-<title>Installation</title>
-
-<orderedlist>
-
-  <listitem><para>Boot from the CD.</para></listitem>
-
-  <listitem><para>The CD contains a basic NixOS installation.  (It
-  also contains Memtest86+, useful if you want to test new hardware.)
-  When it’s finished booting, it should have detected most of your
-  hardware and brought up networking (check
-  <command>ifconfig</command>).  Networking is necessary for the
-  installer, since it will download lots of stuff (such as source
-  tarballs or Nixpkgs channel binaries).  It’s best if you have a DHCP
-  server on your network.  Otherwise configure networking manually
-  using <command>ifconfig</command>.</para></listitem>
-
-  <listitem><para>The NixOS manual is available on virtual console 8
-  (press Alt+F8 to access).</para></listitem>
-
-  <listitem><para>Login as <literal>root</literal> and the empty
-  password.</para></listitem>
-
-  <listitem><para>If you downloaded the graphical ISO image, you can
-  run <command>start display-manager</command> to start KDE.</para></listitem>
-
-  <listitem><para>The NixOS installer doesn’t do any partitioning or
-  formatting yet, so you need to that yourself.  Use the following
-  commands:
-
-  <itemizedlist>
-
-    <listitem><para>For partitioning:
-    <command>fdisk</command>.</para></listitem>
-
-    <listitem><para>For initialising Ext4 partitions:
-    <command>mkfs.ext4</command>.  It is recommended that you assign a
-    unique symbolic label to the file system using the option
-    <option>-L <replaceable>label</replaceable></option>, since this
-    makes the file system configuration independent from device
-    changes.  For example:
-
-<screen>
-$ mkfs.ext4 -L nixos /dev/sda1</screen>
-
-    </para></listitem>
-
-    <listitem><para>For creating swap partitions:
-    <command>mkswap</command>.  Again it’s recommended to assign a
-    label to the swap partition: <option>-L
-    <replaceable>label</replaceable></option>.</para></listitem>
-
-    <listitem><para>For creating LVM volumes, the LVM commands, e.g.,
-
-<screen>
-$ pvcreate /dev/sda1 /dev/sdb1
-$ vgcreate MyVolGroup /dev/sda1 /dev/sdb1
-$ lvcreate --size 2G --name bigdisk MyVolGroup
-$ lvcreate --size 1G --name smalldisk MyVolGroup</screen>
-
-    </para></listitem>
-
-    <listitem><para>For creating software RAID devices, use
-    <command>mdadm</command>.</para></listitem>
-
-  </itemizedlist>
-
-  </para></listitem>
-
-  <listitem><para>Mount the target file system on which NixOS should
-  be installed on <filename>/mnt</filename>, e.g.
-
-<screen>
-$ mount /dev/disk/by-label/nixos /mnt
-</screen>
-
-  </para></listitem>
-
-  <listitem><para>If your machine has a limited amount of memory, you
-  may want to activate swap devices now (<command>swapon
-  <replaceable>device</replaceable></command>).  The installer (or
-  rather, the build actions that it may spawn) may need quite a bit of
-  RAM, depending on your configuration.</para></listitem>
-
-  <listitem>
-
-    <para>You now need to create a file
-    <filename>/mnt/etc/nixos/configuration.nix</filename> that
-    specifies the intended configuration of the system.  This is
-    because NixOS has a <emphasis>declarative</emphasis> configuration
-    model: you create or edit a description of the desired
-    configuration of your system, and then NixOS takes care of making
-    it happen.  The syntax of the NixOS configuration file is
-    described in <xref linkend="sec-configuration-syntax"/>, while a
-    list of available configuration options appears in <xref
-    linkend="ch-options"/>.  A minimal example is shown in <xref
-    linkend="ex-config"/>.</para>
-
-    <para>The command <command>nixos-generate-config</command> can
-    generate an initial configuration file for you:
-
-<screen>
-$ nixos-generate-config --root /mnt</screen>
-
-    You should then edit
-    <filename>/mnt/etc/nixos/configuration.nix</filename> to suit your
-    needs:
-
-<screen>
-$ nano /mnt/etc/nixos/configuration.nix
-</screen>
-
-    The <command>vim</command> text editor is also available.</para>
-
-    <para>You <emphasis>must</emphasis> set the option
-    <option>boot.loader.grub.device</option> to specify on which disk
-    the GRUB boot loader is to be installed.  Without it, NixOS cannot
-    boot.</para>
-
-    <para>Another critical option is <option>fileSystems</option>,
-    specifying the file systems that need to be mounted by NixOS.
-    However, you typically don’t need to set it yourself, because
-    <command>nixos-generate-config</command> sets it automatically in
-    <filename>/mnt/etc/nixos/hardware-configuration.nix</filename>
-    from your currently mounted file systems.  (The configuration file
-    <filename>hardware-configuration.nix</filename> is included from
-    <filename>configuration.nix</filename> and will be overwritten by
-    future invocations of <command>nixos-generate-config</command>;
-    thus, you generally should not modify it.)</para>
-
-    <note><para>Depending on your hardware configuration or type of
-    file system, you may need to set the option
-    <option>boot.initrd.kernelModules</option> to include the kernel
-    modules that are necessary for mounting the root file system,
-    otherwise the installed system will not be able to boot.  (If this
-    happens, boot from the CD again, mount the target file system on
-    <filename>/mnt</filename>, fix
-    <filename>/mnt/etc/nixos/configuration.nix</filename> and rerun
-    <filename>nixos-install</filename>.)  In most cases,
-    <command>nixos-generate-config</command> will figure out the
-    required modules.</para></note>
-
-    <para>Examples of real-world NixOS configuration files can be
-    found at <link
-    xlink:href="https://nixos.org/repos/nix/configurations/trunk/"/>.</para>
-
-  </listitem>
-
-  <listitem><para>Do the installation:
-
-<screen>
-$ nixos-install</screen>
-
-    Cross fingers.  If this fails due to a temporary problem (such as
-    a network issue while downloading binaries from the NixOS binary
-    cache), you can just re-run <command>nixos-install</command>.
-    Otherwise, fix your <filename>configuration.nix</filename> and
-    then re-run <command>nixos-install</command>.</para>
-
-    <para>As the last step, <command>nixos-install</command> will ask
-    you to set the password for the <literal>root</literal> user, e.g.
-
-<screen>
-setting root password...
-Enter new UNIX password: ***
-Retype new UNIX password: ***
-</screen>
-
-    </para>
-
-  </listitem>
-
-  <listitem><para>If everything went well:
-
-<screen>
-$ reboot</screen>
-
-  </para></listitem>
-
-  <listitem>
-
-    <para>You should now be able to boot into the installed NixOS.
-    The GRUB boot menu shows a list of <emphasis>available
-    configurations</emphasis> (initially just one).  Every time you
-    change the NixOS configuration (see <xref
-    linkend="sec-changing-config" />), a new item appears in the menu.
-    This allows you to easily roll back to another configuration if
-    something goes wrong.</para>
-
-    <para>You should log in and change the <literal>root</literal>
-    password with <command>passwd</command>.</para>
-
-    <para>You’ll probably want to create some user accounts as well,
-    which can be done with <command>useradd</command>:
-
-<screen>
-$ useradd -c 'Eelco Dolstra' -m eelco
-$ passwd eelco</screen>
-
-    </para>
-
-    <para>You may also want to install some software.  For instance,
-
-<screen>
-$ nix-env -qa \*</screen>
-
-    shows what packages are available, and
-
-<screen>
-$ nix-env -i w3m</screen>
-
-    install the <literal>w3m</literal> browser.</para>
-
-  </listitem>
-
-</orderedlist>
-
-<para>To summarise, <xref linkend="ex-install-sequence" /> shows a
-typical sequence of commands for installing NixOS on an empty hard
-drive (here <filename>/dev/sda</filename>).  <xref linkend="ex-config"
-/> shows a corresponding configuration Nix expression.</para>
-
-<example xml:id='ex-install-sequence'><title>Commands for installing NixOS on <filename>/dev/sda</filename></title>
-<screen>
-$ fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
-$ mkfs.ext4 -L nixos /dev/sda1
-$ mkswap -L swap /dev/sda2
-$ swapon /dev/sda2
-$ mount /dev/disk/by-label/nixos /mnt
-$ nixos-generate-config --root /mnt
-$ nano /mnt/etc/nixos/configuration.nix
-$ nixos-install
-$ reboot</screen>
-</example>
-
-<example xml:id='ex-config'><title>NixOS configuration</title>
-<screen>
-{ config, pkgs, ... }:
-
-{
-  imports =
-    [ # Include the results of the hardware scan.
-      ./hardware-configuration.nix
-    ];
-
-  boot.loader.grub.device = "/dev/sda";
-
-  # Note: setting fileSystems is generally not
-  # necessary, since nixos-generate-config figures them out
-  # automatically in hardware-configuration.nix.
-  #fileSystems."/".device = "/dev/disk/by-label/nixos";
-
-  # Enable the OpenSSH server.
-  services.sshd.enable = true;
-}</screen>
-</example>
-
-<section xml:id="sec-uefi-installation">
-
-<title>UEFI Installation</title>
-
-<para>NixOS can also be installed on UEFI systems.  The procedure
-is by and large the same as a BIOS installation, with the following
-changes:
-
-<itemizedlist>
-  <listitem>
-    <para>You should boot the live CD in UEFI mode (consult your
-    specific hardware's documentation for instructions). You may find
-    the <link
-    xlink:href="http://www.rodsbooks.com/refind">rEFInd
-    boot manager</link> useful.</para>
-  </listitem>
-  <listitem>
-    <para>Instead of <command>fdisk</command>, you should use
-    <command>gdisk</command> to partition your disks. You will need to
-    have a separate partition for <filename>/boot</filename> with
-    partition code EF00, and it should be formatted as a
-    <literal>vfat</literal> filesystem.</para>
-  </listitem>
-  <listitem>
-    <para>You must set <option>boot.loader.gummiboot.enable</option> to
-    <literal>true</literal>. <command>nixos-generate-config</command>
-    should do this automatically for new configurations when booted in
-    UEFI mode.</para>
-  </listitem>
-  <listitem>
-    <para>After having mounted your installation partition to
-    <code>/mnt</code>, you must mount the <code>boot</code> partition
-    to <code>/mnt/boot</code>.</para>
-  </listitem>
-  <listitem>
-    <para>You may want to look at the options starting with
-    <option>boot.loader.efi</option> and <option>boot.loader.gummiboot</option>
-    as well.</para>
-  </listitem>
-  <listitem>
-    <para>To see console messages during early boot, add <literal>"fbcon"</literal>
-    to your <option>boot.initrd.kernelModules</option>.</para>
-  </listitem>
-</itemizedlist>
-</para>
-
-</section>
-
-<section>
-
-<title xml:id="sec-booting-from-usb">Booting from a USB stick</title>
-
-<para>For systems without CD drive, the NixOS livecd can be booted from
-a usb stick. For non-UEFI installations,
-<link xlink:href="http://unetbootin.sourceforge.net/">unetbootin</link>
-will work. For UEFI installations, you should mount the ISO, copy its contents
-verbatim to your drive, then either:
-
-<itemizedlist>
-  <listitem>
-    <para>Change the label of the disk partition to the label of the ISO
-    (visible with the blkid command), or</para>
-  </listitem>
-  <listitem>
-    <para>Edit <filename>loader/entries/nixos-livecd.conf</filename> on the drive
-    and change the <literal>root=</literal> field in the <literal>options</literal>
-    line to point to your drive (see the documentation on <literal>root=</literal>
-    in <link xlink:href="https://www.kernel.org/doc/Documentation/kernel-parameters.txt">
-    the kernel documentation</link> for more details).</para>
-  </listitem>
-</itemizedlist>
-</para>
-</section>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-changing-config">
-
-<title>Changing the configuration</title>
-
-<para>The file <filename>/etc/nixos/configuration.nix</filename>
-contains the current configuration of your machine.  Whenever you’ve
-changed something to that file, you should do
-
-<screen>
-$ nixos-rebuild switch</screen>
-
-to build the new configuration, make it the default configuration for
-booting, and try to realise the configuration in the running system
-(e.g., by restarting system services).</para>
-
-<warning><para>These commands must be executed as root, so you should
-either run them from a root shell or by prefixing them with
-<literal>sudo -i</literal>.</para></warning>
-
-<para>You can also do
-
-<screen>
-$ nixos-rebuild test</screen>
-
-to build the configuration and switch the running system to it, but
-without making it the boot default.  So if (say) the configuration
-locks up your machine, you can just reboot to get back to a working
-configuration.</para>
-
-<para>There is also
-
-<screen>
-$ nixos-rebuild boot</screen>
-
-to build the configuration and make it the boot default, but not
-switch to it now (so it will only take effect after the next
-reboot).</para>
-
-<para>You can make your configuration show up in a different submenu
-of the GRUB 2 boot screen by giving it a different <emphasis>profile
-name</emphasis>, e.g.
-
-<screen>
-$ nixos-rebuild switch -p test </screen>
-
-which causes the new configuration (and previous ones created using
-<literal>-p test</literal>) to show up in the GRUB submenu “NixOS -
-Profile 'test'”.  This can be useful to separate test configurations
-from “stable” configurations.</para>
-
-<para>Finally, you can do
-
-<screen>
-$ nixos-rebuild build</screen>
-
-to build the configuration but nothing more.  This is useful to see
-whether everything compiles cleanly.</para>
-
-<para>If you have a machine that supports hardware virtualisation, you
-can also test the new configuration in a sandbox by building and
-running a QEMU <emphasis>virtual machine</emphasis> that contains the
-desired configuration.  Just do
-
-<screen>
-$ nixos-rebuild build-vm
-$ ./result/bin/run-*-vm
-</screen>
-
-The VM does not have any data from your host system, so your existing
-user accounts and home directories will not be available.  You can
-forward ports on the host to the guest.  For instance, the following
-will forward host port 2222 to guest port 22 (SSH):
-
-<screen>
-$ QEMU_NET_OPTS="hostfwd=tcp::2222-:22" ./result/bin/run-*-vm
-</screen>
-
-allowing you to log in via SSH (assuming you have set the appropriate
-passwords or SSH authorized keys):
-
-<screen>
-$ ssh -p 2222 localhost
-</screen>
-
-</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-upgrading">
-
-<title>Upgrading NixOS</title>
-
-<para>The best way to keep your NixOS installation up to date is to
-use one of the NixOS <emphasis>channels</emphasis>.  A channel is a
-Nix mechanism for distributing Nix expressions and associated
-binaries.  The NixOS channels are updated automatically from NixOS’s
-Git repository after certain tests have passed and all packages have
-been built.  These channels are:
-
-<itemizedlist>
-  <listitem>
-    <para>Stable channels, such as <literal
-    xlink:href="http://nixos.org/channels/nixos-14.04">nixos-14.04</literal>.
-    These only get conservative bug fixes and package upgrades.  For
-    instance, a channel update may cause the Linux kernel on your
-    system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but
-    not from 3.4.<replaceable>x</replaceable> to
-    3.11.<replaceable>x</replaceable> (a major change that has the
-    potential to break things).  Stable channels are generally
-    maintained until the next stable branch is created.</para>
-  </listitem>
-  <listitem>
-    <para>The unstable channel, <literal
-    xlink:href="http://nixos.org/channels/nixos-unstable">nixos-unstable</literal>.
-    This corresponds to NixOS’s main development branch, and may thus
-    see radical changes between channel updates.  It’s not recommended
-    for production systems.</para>
-  </listitem>
-</itemizedlist>
-
-To see what channels are available, go to <link
-xlink:href="http://nixos.org/channels"/>.  (Note that the URIs of the
-various channels redirect to a directory that contains the channel’s
-latest version and includes ISO images and VirtualBox
-appliances.)</para>
-
-<para>When you first install NixOS, you’re automatically subscribed to
-the NixOS channel that corresponds to your installation source.   For
-instance, if you installed from a 14.04 ISO, you will be subscribed to
-the <literal>nixos-14.04</literal> channel.  To see which NixOS
-channel you’re subscribed to, run the following as root:
-
-<screen>
-$ nix-channel --list | grep nixos
-nixos https://nixos.org/channels/nixos-unstable
-</screen>
-
-To switch to a different NixOS channel, do
-
-<screen>
-$ nix-channel --add http://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
-</screen>
-
-(Be sure to include the <literal>nixos</literal> parameter at the
-end.)  For instance, to use the NixOS 14.04 stable channel:
-
-<screen>
-$ nix-channel --add http://nixos.org/channels/nixos-14.04 nixos
-</screen>
-
-But it you want to live on the bleeding edge:
-
-<screen>
-$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos
-</screen>
-
-</para>
-
-<para>You can then upgrade NixOS to the latest version in your chosen
-channel by running
-
-<screen>
-$ nixos-rebuild switch --upgrade
-</screen>
-
-which is equivalent to the more verbose <literal>nix-channel --update
-nixos; nixos-rebuild switch</literal>.</para>
-
-<warning><para>It is generally safe to switch back and forth between
-channels.  The only exception is that a newer NixOS may also have a
-newer Nix version, which may involve an upgrade of Nix’s database
-schema.  This cannot be undone easily, so in that case you will not be
-able to go back to your original channel.</para></warning>
-
-</section>
-
-</chapter>
diff --git a/nixos/doc/manual/installation/changing-config.xml b/nixos/doc/manual/installation/changing-config.xml
new file mode 100644
index 00000000000..aa31742434e
--- /dev/null
+++ b/nixos/doc/manual/installation/changing-config.xml
@@ -0,0 +1,90 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         version="5.0"
+         xml:id="sec-changing-config">
+
+<title>Changing the Configuration</title>
+
+<para>The file <filename>/etc/nixos/configuration.nix</filename>
+contains the current configuration of your machine.  Whenever you’ve
+changed something to that file, you should do
+
+<screen>
+$ nixos-rebuild switch</screen>
+
+to build the new configuration, make it the default configuration for
+booting, and try to realise the configuration in the running system
+(e.g., by restarting system services).</para>
+
+<warning><para>These commands must be executed as root, so you should
+either run them from a root shell or by prefixing them with
+<literal>sudo -i</literal>.</para></warning>
+
+<para>You can also do
+
+<screen>
+$ nixos-rebuild test</screen>
+
+to build the configuration and switch the running system to it, but
+without making it the boot default.  So if (say) the configuration
+locks up your machine, you can just reboot to get back to a working
+configuration.</para>
+
+<para>There is also
+
+<screen>
+$ nixos-rebuild boot</screen>
+
+to build the configuration and make it the boot default, but not
+switch to it now (so it will only take effect after the next
+reboot).</para>
+
+<para>You can make your configuration show up in a different submenu
+of the GRUB 2 boot screen by giving it a different <emphasis>profile
+name</emphasis>, e.g.
+
+<screen>
+$ nixos-rebuild switch -p test </screen>
+
+which causes the new configuration (and previous ones created using
+<literal>-p test</literal>) to show up in the GRUB submenu “NixOS -
+Profile 'test'”.  This can be useful to separate test configurations
+from “stable” configurations.</para>
+
+<para>Finally, you can do
+
+<screen>
+$ nixos-rebuild build</screen>
+
+to build the configuration but nothing more.  This is useful to see
+whether everything compiles cleanly.</para>
+
+<para>If you have a machine that supports hardware virtualisation, you
+can also test the new configuration in a sandbox by building and
+running a QEMU <emphasis>virtual machine</emphasis> that contains the
+desired configuration.  Just do
+
+<screen>
+$ nixos-rebuild build-vm
+$ ./result/bin/run-*-vm
+</screen>
+
+The VM does not have any data from your host system, so your existing
+user accounts and home directories will not be available.  You can
+forward ports on the host to the guest.  For instance, the following
+will forward host port 2222 to guest port 22 (SSH):
+
+<screen>
+$ QEMU_NET_OPTS="hostfwd=tcp::2222-:22" ./result/bin/run-*-vm
+</screen>
+
+allowing you to log in via SSH (assuming you have set the appropriate
+passwords or SSH authorized keys):
+
+<screen>
+$ ssh -p 2222 localhost
+</screen>
+
+</para>
+
+</chapter>
diff --git a/nixos/doc/manual/installation/installation.xml b/nixos/doc/manual/installation/installation.xml
new file mode 100644
index 00000000000..ee61bedc418
--- /dev/null
+++ b/nixos/doc/manual/installation/installation.xml
@@ -0,0 +1,21 @@
+<part 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="ch-installation">
+
+<title>Installation</title>
+
+<partintro>
+
+<para>This section describes how to obtain, install, and configure
+NixOS for first-time use.</para>
+
+</partintro>
+
+<xi:include href="obtaining.xml" />
+<xi:include href="installing.xml" />
+<xi:include href="changing-config.xml" />
+<xi:include href="upgrading.xml" />
+
+</part>
diff --git a/nixos/doc/manual/installation/installing-uefi.xml b/nixos/doc/manual/installation/installing-uefi.xml
new file mode 100644
index 00000000000..dbd5606c4a5
--- /dev/null
+++ b/nixos/doc/manual/installation/installing-uefi.xml
@@ -0,0 +1,51 @@
+<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-uefi-installation">
+
+<title>UEFI Installation</title>
+    
+<para>NixOS can also be installed on UEFI systems.  The procedure
+is by and large the same as a BIOS installation, with the following
+changes:
+
+<itemizedlist>
+  <listitem>
+    <para>You should boot the live CD in UEFI mode (consult your
+    specific hardware's documentation for instructions). You may find
+    the <link
+    xlink:href="http://www.rodsbooks.com/refind">rEFInd
+    boot manager</link> useful.</para>
+  </listitem>
+  <listitem>
+    <para>Instead of <command>fdisk</command>, you should use
+    <command>gdisk</command> to partition your disks. You will need to
+    have a separate partition for <filename>/boot</filename> with
+    partition code EF00, and it should be formatted as a
+    <literal>vfat</literal> filesystem.</para>
+  </listitem>
+  <listitem>
+    <para>You must set <option>boot.loader.gummiboot.enable</option> to
+    <literal>true</literal>. <command>nixos-generate-config</command>
+    should do this automatically for new configurations when booted in
+    UEFI mode.</para>
+  </listitem>
+  <listitem>
+    <para>After having mounted your installation partition to
+    <code>/mnt</code>, you must mount the <code>boot</code> partition
+    to <code>/mnt/boot</code>.</para>
+  </listitem>
+  <listitem>
+    <para>You may want to look at the options starting with
+    <option>boot.loader.efi</option> and <option>boot.loader.gummiboot</option>
+    as well.</para>
+  </listitem>
+  <listitem>
+    <para>To see console messages during early boot, add <literal>"fbcon"</literal>
+    to your <option>boot.initrd.kernelModules</option>.</para>
+  </listitem>
+</itemizedlist>
+</para>
+
+</section>
diff --git a/nixos/doc/manual/installation/installing-usb.xml b/nixos/doc/manual/installation/installing-usb.xml
new file mode 100644
index 00000000000..97e3d2eaa1c
--- /dev/null
+++ b/nixos/doc/manual/installation/installing-usb.xml
@@ -0,0 +1,30 @@
+<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-booting-from-usb">
+
+<title>Booting from a USB Drive</title>
+
+<para>For systems without CD drive, the NixOS livecd can be booted from
+a usb stick. For non-UEFI installations,
+<link xlink:href="http://unetbootin.sourceforge.net/">unetbootin</link>
+will work. For UEFI installations, you should mount the ISO, copy its contents
+verbatim to your drive, then either:
+
+<itemizedlist>
+  <listitem>
+    <para>Change the label of the disk partition to the label of the ISO
+    (visible with the blkid command), or</para>
+  </listitem>
+  <listitem>
+    <para>Edit <filename>loader/entries/nixos-livecd.conf</filename> on the drive
+    and change the <literal>root=</literal> field in the <literal>options</literal>
+    line to point to your drive (see the documentation on <literal>root=</literal>
+    in <link xlink:href="https://www.kernel.org/doc/Documentation/kernel-parameters.txt">
+    the kernel documentation</link> for more details).</para>
+  </listitem>
+</itemizedlist>
+</para>
+
+</section>
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
new file mode 100644
index 00000000000..b140c56fbee
--- /dev/null
+++ b/nixos/doc/manual/installation/installing.xml
@@ -0,0 +1,264 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+            xmlns:xlink="http://www.w3.org/1999/xlink"
+            xmlns:xi="http://www.w3.org/2001/XInclude"
+            version="5.0"
+            xml:id="sec-installation">
+
+<title>Installing NixOS</title>
+
+<orderedlist>
+
+  <listitem><para>Boot from the CD.</para></listitem>
+
+  <listitem><para>The CD contains a basic NixOS installation.  (It
+  also contains Memtest86+, useful if you want to test new hardware.)
+  When it’s finished booting, it should have detected most of your
+  hardware and brought up networking (check
+  <command>ifconfig</command>).  Networking is necessary for the
+  installer, since it will download lots of stuff (such as source
+  tarballs or Nixpkgs channel binaries).  It’s best if you have a DHCP
+  server on your network.  Otherwise configure networking manually
+  using <command>ifconfig</command>.</para></listitem>
+
+  <listitem><para>The NixOS manual is available on virtual console 8
+  (press Alt+F8 to access).</para></listitem>
+
+  <listitem><para>Login as <literal>root</literal> and the empty
+  password.</para></listitem>
+
+  <listitem><para>If you downloaded the graphical ISO image, you can
+  run <command>start display-manager</command> to start KDE.</para></listitem>
+
+  <listitem><para>The NixOS installer doesn’t do any partitioning or
+  formatting yet, so you need to that yourself.  Use the following
+  commands:
+
+  <itemizedlist>
+
+    <listitem><para>For partitioning:
+    <command>fdisk</command>.</para></listitem>
+
+    <listitem><para>For initialising Ext4 partitions:
+    <command>mkfs.ext4</command>.  It is recommended that you assign a
+    unique symbolic label to the file system using the option
+    <option>-L <replaceable>label</replaceable></option>, since this
+    makes the file system configuration independent from device
+    changes.  For example:
+
+<screen>
+$ mkfs.ext4 -L nixos /dev/sda1</screen>
+
+    </para></listitem>
+
+    <listitem><para>For creating swap partitions:
+    <command>mkswap</command>.  Again it’s recommended to assign a
+    label to the swap partition: <option>-L
+    <replaceable>label</replaceable></option>.</para></listitem>
+
+    <listitem><para>For creating LVM volumes, the LVM commands, e.g.,
+
+<screen>
+$ pvcreate /dev/sda1 /dev/sdb1
+$ vgcreate MyVolGroup /dev/sda1 /dev/sdb1
+$ lvcreate --size 2G --name bigdisk MyVolGroup
+$ lvcreate --size 1G --name smalldisk MyVolGroup</screen>
+
+    </para></listitem>
+
+    <listitem><para>For creating software RAID devices, use
+    <command>mdadm</command>.</para></listitem>
+
+  </itemizedlist>
+
+  </para></listitem>
+
+  <listitem><para>Mount the target file system on which NixOS should
+  be installed on <filename>/mnt</filename>, e.g.
+
+<screen>
+$ mount /dev/disk/by-label/nixos /mnt
+</screen>
+
+  </para></listitem>
+
+  <listitem><para>If your machine has a limited amount of memory, you
+  may want to activate swap devices now (<command>swapon
+  <replaceable>device</replaceable></command>).  The installer (or
+  rather, the build actions that it may spawn) may need quite a bit of
+  RAM, depending on your configuration.</para></listitem>
+
+  <listitem>
+
+    <para>You now need to create a file
+    <filename>/mnt/etc/nixos/configuration.nix</filename> that
+    specifies the intended configuration of the system.  This is
+    because NixOS has a <emphasis>declarative</emphasis> configuration
+    model: you create or edit a description of the desired
+    configuration of your system, and then NixOS takes care of making
+    it happen.  The syntax of the NixOS configuration file is
+    described in <xref linkend="sec-configuration-syntax"/>, while a
+    list of available configuration options appears in <xref
+    linkend="ch-options"/>.  A minimal example is shown in <xref
+    linkend="ex-config"/>.</para>
+
+    <para>The command <command>nixos-generate-config</command> can
+    generate an initial configuration file for you:
+
+<screen>
+$ nixos-generate-config --root /mnt</screen>
+
+    You should then edit
+    <filename>/mnt/etc/nixos/configuration.nix</filename> to suit your
+    needs:
+
+<screen>
+$ nano /mnt/etc/nixos/configuration.nix
+</screen>
+
+    The <command>vim</command> text editor is also available.</para>
+
+    <para>You <emphasis>must</emphasis> set the option
+    <option>boot.loader.grub.device</option> to specify on which disk
+    the GRUB boot loader is to be installed.  Without it, NixOS cannot
+    boot.</para>
+
+    <para>Another critical option is <option>fileSystems</option>,
+    specifying the file systems that need to be mounted by NixOS.
+    However, you typically don’t need to set it yourself, because
+    <command>nixos-generate-config</command> sets it automatically in
+    <filename>/mnt/etc/nixos/hardware-configuration.nix</filename>
+    from your currently mounted file systems.  (The configuration file
+    <filename>hardware-configuration.nix</filename> is included from
+    <filename>configuration.nix</filename> and will be overwritten by
+    future invocations of <command>nixos-generate-config</command>;
+    thus, you generally should not modify it.)</para>
+
+    <note><para>Depending on your hardware configuration or type of
+    file system, you may need to set the option
+    <option>boot.initrd.kernelModules</option> to include the kernel
+    modules that are necessary for mounting the root file system,
+    otherwise the installed system will not be able to boot.  (If this
+    happens, boot from the CD again, mount the target file system on
+    <filename>/mnt</filename>, fix
+    <filename>/mnt/etc/nixos/configuration.nix</filename> and rerun
+    <filename>nixos-install</filename>.)  In most cases,
+    <command>nixos-generate-config</command> will figure out the
+    required modules.</para></note>
+
+    <para>Examples of real-world NixOS configuration files can be
+    found at <link
+    xlink:href="https://nixos.org/repos/nix/configurations/trunk/"/>.</para>
+
+  </listitem>
+
+  <listitem><para>Do the installation:
+
+<screen>
+$ nixos-install</screen>
+
+    Cross fingers.  If this fails due to a temporary problem (such as
+    a network issue while downloading binaries from the NixOS binary
+    cache), you can just re-run <command>nixos-install</command>.
+    Otherwise, fix your <filename>configuration.nix</filename> and
+    then re-run <command>nixos-install</command>.</para>
+
+    <para>As the last step, <command>nixos-install</command> will ask
+    you to set the password for the <literal>root</literal> user, e.g.
+
+<screen>
+setting root password...
+Enter new UNIX password: ***
+Retype new UNIX password: ***
+</screen>
+
+    </para>
+
+  </listitem>
+
+  <listitem><para>If everything went well:
+
+<screen>
+$ reboot</screen>
+
+  </para></listitem>
+
+  <listitem>
+
+    <para>You should now be able to boot into the installed NixOS. The GRUB boot menu shows a list
+                of <emphasis>available configurations</emphasis> (initially just one). Every time
+                you change the NixOS configuration (see<link linkend="sec-changing-config">Changing
+                    Configuration</link> ), a new item appears in the menu. This allows you to
+                easily roll back to another configuration if something goes wrong.</para>
+
+    <para>You should log in and change the <literal>root</literal>
+    password with <command>passwd</command>.</para>
+
+    <para>You’ll probably want to create some user accounts as well,
+    which can be done with <command>useradd</command>:
+
+<screen>
+$ useradd -c 'Eelco Dolstra' -m eelco
+$ passwd eelco</screen>
+
+    </para>
+
+    <para>You may also want to install some software.  For instance,
+
+<screen>
+$ nix-env -qa \*</screen>
+
+    shows what packages are available, and
+
+<screen>
+$ nix-env -i w3m</screen>
+
+    install the <literal>w3m</literal> browser.</para>
+
+  </listitem>
+
+</orderedlist>
+
+<para>To summarise, <xref linkend="ex-install-sequence" /> shows a
+typical sequence of commands for installing NixOS on an empty hard
+drive (here <filename>/dev/sda</filename>).  <xref linkend="ex-config"
+/> shows a corresponding configuration Nix expression.</para>
+
+<example xml:id='ex-install-sequence'><title>Commands for Installing NixOS on <filename>/dev/sda</filename></title>
+<screen>
+$ fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
+$ mkfs.ext4 -L nixos /dev/sda1
+$ mkswap -L swap /dev/sda2
+$ swapon /dev/sda2
+$ mount /dev/disk/by-label/nixos /mnt
+$ nixos-generate-config --root /mnt
+$ nano /mnt/etc/nixos/configuration.nix
+$ nixos-install
+$ reboot</screen>
+</example>
+
+<example xml:id='ex-config'><title>NixOS Configuration</title>
+<screen>
+{ config, pkgs, ... }:
+
+{
+  imports =
+    [ # Include the results of the hardware scan.
+      ./hardware-configuration.nix
+    ];
+
+  boot.loader.grub.device = "/dev/sda";
+
+  # Note: setting fileSystems is generally not
+  # necessary, since nixos-generate-config figures them out
+  # automatically in hardware-configuration.nix.
+  #fileSystems."/".device = "/dev/disk/by-label/nixos";
+
+  # Enable the OpenSSH server.
+  services.sshd.enable = true;
+}</screen>
+</example>
+
+<xi:include href="installing-uefi.xml" />
+<xi:include href="installing-usb.xml" />
+
+</chapter>
diff --git a/nixos/doc/manual/installation/obtaining.xml b/nixos/doc/manual/installation/obtaining.xml
new file mode 100644
index 00000000000..ceeeb5c0ac0
--- /dev/null
+++ b/nixos/doc/manual/installation/obtaining.xml
@@ -0,0 +1,44 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-obtaining">
+
+<title>Obtaining NixOS</title>
+
+<para>NixOS ISO images can be downloaded from the <link
+xlink:href="http://nixos.org/nixos/download.html">NixOS
+homepage</link>.  These can be burned onto a CD.  It is also possible
+to copy them onto a USB stick and install NixOS from there.  For
+details, see the <link
+xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS
+Wiki</link>.</para>
+
+<para>As an alternative to installing NixOS yourself, you can get a
+running NixOS system through several other means:
+
+<itemizedlist>
+  <listitem>
+    <para>Using virtual appliances in Open Virtualization Format (OVF)
+    that can be imported into VirtualBox.  These are available from
+    the <link xlink:href="http://nixos.org/nixos/download.html">NixOS
+    homepage</link>.</para>
+  </listitem>
+  <listitem>
+    <para>Using AMIs for Amazon’s EC2.  To find one for your region
+    and instance type, please refer to the <link
+    xlink:href="https://github.com/NixOS/nixops/blob/master/nix/ec2-amis.nix">list
+    of most recent AMIs</link>.</para>
+  </listitem>
+  <listitem>
+    <para>Using NixOps, the NixOS-based cloud deployment tool, which
+    allows you to provision VirtualBox and EC2 NixOS instances from
+    declarative specifications.  Check out the <link
+    xlink:href="https://github.com/NixOS/nixops">NixOps
+    homepage</link> for details.</para>
+  </listitem>
+</itemizedlist>
+
+</para>
+
+</chapter>
diff --git a/nixos/doc/manual/installation/upgrading.xml b/nixos/doc/manual/installation/upgrading.xml
new file mode 100644
index 00000000000..ed71a7e23a3
--- /dev/null
+++ b/nixos/doc/manual/installation/upgrading.xml
@@ -0,0 +1,90 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         version="5.0"
+         xml:id="sec-upgrading">
+
+<title>Upgrading NixOS</title>
+
+<para>The best way to keep your NixOS installation up to date is to
+use one of the NixOS <emphasis>channels</emphasis>.  A channel is a
+Nix mechanism for distributing Nix expressions and associated
+binaries.  The NixOS channels are updated automatically from NixOS’s
+Git repository after certain tests have passed and all packages have
+been built.  These channels are:
+
+<itemizedlist>
+  <listitem>
+    <para>Stable channels, such as <literal
+    xlink:href="http://nixos.org/channels/nixos-14.04">nixos-14.04</literal>.
+    These only get conservative bug fixes and package upgrades.  For
+    instance, a channel update may cause the Linux kernel on your
+    system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but
+    not from 3.4.<replaceable>x</replaceable> to
+    3.11.<replaceable>x</replaceable> (a major change that has the
+    potential to break things).  Stable channels are generally
+    maintained until the next stable branch is created.</para>
+  </listitem>
+  <listitem>
+    <para>The unstable channel, <literal
+    xlink:href="http://nixos.org/channels/nixos-unstable">nixos-unstable</literal>.
+    This corresponds to NixOS’s main development branch, and may thus
+    see radical changes between channel updates.  It’s not recommended
+    for production systems.</para>
+  </listitem>
+</itemizedlist>
+
+To see what channels are available, go to <link
+xlink:href="http://nixos.org/channels"/>.  (Note that the URIs of the
+various channels redirect to a directory that contains the channel’s
+latest version and includes ISO images and VirtualBox
+appliances.)</para>
+
+<para>When you first install NixOS, you’re automatically subscribed to
+the NixOS channel that corresponds to your installation source.   For
+instance, if you installed from a 14.04 ISO, you will be subscribed to
+the <literal>nixos-14.04</literal> channel.  To see which NixOS
+channel you’re subscribed to, run the following as root:
+
+<screen>
+$ nix-channel --list | grep nixos
+nixos https://nixos.org/channels/nixos-unstable
+</screen>
+
+To switch to a different NixOS channel, do
+
+<screen>
+$ nix-channel --add http://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
+</screen>
+
+(Be sure to include the <literal>nixos</literal> parameter at the
+end.)  For instance, to use the NixOS 14.04 stable channel:
+
+<screen>
+$ nix-channel --add http://nixos.org/channels/nixos-14.04 nixos
+</screen>
+
+But it you want to live on the bleeding edge:
+
+<screen>
+$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos
+</screen>
+
+</para>
+
+<para>You can then upgrade NixOS to the latest version in your chosen
+channel by running
+
+<screen>
+$ nixos-rebuild switch --upgrade
+</screen>
+
+which is equivalent to the more verbose <literal>nix-channel --update
+nixos; nixos-rebuild switch</literal>.</para>
+
+<warning><para>It is generally safe to switch back and forth between
+channels.  The only exception is that a newer NixOS may also have a
+newer Nix version, which may involve an upgrade of Nix’s database
+schema.  This cannot be undone easily, so in that case you will not be
+able to go back to your original channel.</para></warning>
+
+</chapter>
diff --git a/nixos/doc/manual/man-nixos-option.xml b/nixos/doc/manual/man-nixos-option.xml
index 7952847d4db..554b2969180 100644
--- a/nixos/doc/manual/man-nixos-option.xml
+++ b/nixos/doc/manual/man-nixos-option.xml
@@ -17,11 +17,6 @@
 <refsynopsisdiv>
   <cmdsynopsis>
     <command>nixos-option</command>
-    <group choice="opt">
-      <option>-v</option>
-      <option>-d</option>
-      <option>-l</option>
-    </group>
     <arg choice='plain'><replaceable>option.name</replaceable></arg>
   </cmdsynopsis>
 </refsynopsisdiv>
@@ -31,50 +26,13 @@
 
 <para>This command evaluates the configuration specified in
 <filename>/etc/nixos/configuration.nix</filename> and returns the properties
-of the option name given as argument.  By default, it returns the value of
-the option.</para>
+of the option name given as argument.</para>
 
 <para>When the option name is not an option, the command prints the list of
 attributes contained in the attribute set.</para>
 
 </refsection>
 
-<refsection><title>Options</title>
-
-<para>This command accepts the following options:</para>
-
-<variablelist>
-
-  <varlistentry>
-    <term><option>--value</option>, <option>-v</option></term>
-    <listitem>
-      <para>Returns the value of the option.  This is the default operation
-      if no other options are defined.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>--description</option>, <option>-d</option></term>
-    <listitem>
-      <para>Return the default value, the example and the description of the
-      option when available.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>--lookup</option>, <option>-l</option></term>
-    <listitem>
-      <para>Return the locations where the option is declared and where it
-      is defined.  This is extremely useful to find sources of errors in
-      your configuration.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-</refsection>
-
-
 <refsection><title>Environment</title>
 
 <variablelist>
@@ -103,27 +61,21 @@ grub
 initScript
 
 $ nixos-option boot.loader.grub.enable
-true</screen></para>
+Value:
+true
 
-<para>Prints option information:
+Default: 
+true
 
-<screen>$ nixos-option -d networking.hostName
-Default: "nixos"
 Description:
-The name of the machine. Leave it empty if you want to obtain
-it from a DHCP server (if using DHCP).</screen></para>
-
-<para>Find the locations which are declaring and defining an option:
+Whether to enable the GNU GRUB boot loader.
 
-<screen>$ nixos-option -l hardware.firmware
 Declared by:
-  /mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix
+  "/path/to/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
 
 Defined by:
-  /path/to/nixpkgs/nixos/modules/system/boot/kernel.nix
-  /path/to/nixpkgs/nixos/modules/hardware/network/rt73.nix
-  /path/to/nixpkgs/nixos/modules/hardware/network/intel-3945abg.nix
-  /path/to/nixpkgs/nixos/modules/hardware/network/intel-2200bg.nix</screen></para>
+  "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
+</screen></para>
 
 </refsection>
 
diff --git a/nixos/doc/manual/manual.xml b/nixos/doc/manual/manual.xml
index f51a04cdf25..a3ad76209ac 100644
--- a/nixos/doc/manual/manual.xml
+++ b/nixos/doc/manual/manual.xml
@@ -1,15 +1,14 @@
 <book xmlns="http://docbook.org/ns/docbook"
       xmlns:xlink="http://www.w3.org/1999/xlink"
-      xmlns:xi="http://www.w3.org/2001/XInclude">
-
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      version="5.0"
+      xml:id="NixOSManual">
+  
   <info>
-
     <title>NixOS Manual</title>
     <subtitle>Version <xi:include href="version" parse="text" /></subtitle>
-
   </info>
 
-
   <preface>
     <title>Preface</title>
 
@@ -29,19 +28,14 @@
 
   </preface>
 
-
-  <xi:include href="installation.xml" />
-  <xi:include href="configuration.xml" />
-  <xi:include href="running.xml" />
+  <xi:include href="installation/installation.xml" />
+  <xi:include href="configuration/configuration.xml" />
+  <xi:include href="administration/running.xml" />
   <!-- <xi:include href="userconfiguration.xml" /> -->
-  <xi:include href="troubleshooting.xml" />
-  <xi:include href="containers.xml" />
-  <xi:include href="development.xml" />
-
-  <xi:include href="release-notes.xml" />
+  <xi:include href="release-notes/release-notes.xml" />
 
   <appendix xml:id="ch-options">
-    <title>Configuration options</title>
+    <title>Configuration Options</title>
     <xi:include href="options-db.xml" />
   </appendix>
 
diff --git a/nixos/doc/manual/release-notes/release-notes.xml b/nixos/doc/manual/release-notes/release-notes.xml
new file mode 100644
index 00000000000..fb82d5adcef
--- /dev/null
+++ b/nixos/doc/manual/release-notes/release-notes.xml
@@ -0,0 +1,17 @@
+<part   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="ch-release-notes">
+
+<title>Release Notes</title>
+
+<partintro>
+<para>This section lists the release notes for each stable version of NixOS.</para>
+</partintro>
+
+<xi:include href="rl-1410.xml" />
+<xi:include href="rl-1404.xml" />
+<xi:include href="rl-1310.xml" />
+
+</part>
diff --git a/nixos/doc/manual/release-notes/rl-1310.xml b/nixos/doc/manual/release-notes/rl-1310.xml
new file mode 100644
index 00000000000..234fb5a643f
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-1310.xml
@@ -0,0 +1,11 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-release-13.10">
+
+<title>Release 13.10 (“Aardvark”, 2013/10/31)</title>
+
+<para>This is the first stable release branch of NixOS.</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/release-notes.xml b/nixos/doc/manual/release-notes/rl-1404.xml
index 52e88bb4c86..74af1ed1274 100644
--- a/nixos/doc/manual/release-notes.xml
+++ b/nixos/doc/manual/release-notes/rl-1404.xml
@@ -1,34 +1,8 @@
-<appendix xmlns="http://docbook.org/ns/docbook"
-          xmlns:xlink="http://www.w3.org/1999/xlink"
-          xml:id="ch-release-notes">
-
-<title>Release notes</title>
-
-<!--==================================================================-->
-
-<section xml:id="sec-release-14.10">
-
-<title>Release 14.10 (“Caterpillar”, 2014/10/??)</title>
-
-<para>When upgrading from a previous release, please be aware of the
-following incompatible changes:
-
-<itemizedlist>
-
-  <listitem><para>The host side of a container virtual Ethernet pair
-  is now called <literal>ve-<replaceable>container-name</replaceable></literal>
-  rather than <literal>c-<replaceable>container-name</replaceable></literal>.</para></listitem>
-
-</itemizedlist>
-
-</para>
-
-</section>
-
-
-<!--==================================================================-->
-
-<section xml:id="sec-release-14.04">
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-release-14.04">
 
 <title>Release 14.04 (“Baboon”, 2014/04/30)</title>
 
@@ -183,16 +157,4 @@ networking.firewall.enable = false;
 
 </para>
 
-</section>
-
-<!--==================================================================-->
-
-<section xml:id="sec-release-13.10">
-
-<title>Release 13.10 (“Aardvark”, 2013/10/31)</title>
-
-<para>This is the first stable release branch of NixOS.</para>
-
-</section>
-
-</appendix>
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/release-notes/rl-1410.xml b/nixos/doc/manual/release-notes/rl-1410.xml
new file mode 100644
index 00000000000..09da15ce236
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-1410.xml
@@ -0,0 +1,22 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:xi="http://www.w3.org/2001/XInclude"
+        version="5.0"
+        xml:id="sec-release-14.10">
+
+<title>Release 14.10 (“Caterpillar”, 2014/10/??)</title>
+
+<para>When upgrading from a previous release, please be aware of the
+following incompatible changes:
+
+<itemizedlist>
+
+  <listitem><para>The host side of a container virtual Ethernet pair
+  is now called <literal>ve-<replaceable>container-name</replaceable></literal>
+  rather than <literal>c-<replaceable>container-name</replaceable></literal>.</para></listitem>
+
+</itemizedlist>
+
+</para>
+
+</chapter>
\ No newline at end of file
diff --git a/nixos/doc/manual/running.xml b/nixos/doc/manual/running.xml
deleted file mode 100644
index e1a358df2aa..00000000000
--- a/nixos/doc/manual/running.xml
+++ /dev/null
@@ -1,369 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-         xmlns:xlink="http://www.w3.org/1999/xlink"
-         xml:id="ch-running">
-
-<title>Running NixOS</title>
-
-<para>This chapter describes various aspects of managing a running
-NixOS system, such as how to use the <command>systemd</command>
-service manager.</para>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-systemctl"><title>Service management</title>
-
-<para>In NixOS, all system services are started and monitored using
-the systemd program.  Systemd is the “init” process of the system
-(i.e. PID 1), the parent of all other processes.  It manages a set of
-so-called “units”, which can be things like system services
-(programs), but also mount points, swap files, devices, targets
-(groups of units) and more.  Units can have complex dependencies; for
-instance, one unit can require that another unit must be successfully
-started before the first unit can be started.  When the system boots,
-it starts a unit named <literal>default.target</literal>; the
-dependencies of this unit cause all system services to be started,
-file systems to be mounted, swap files to be activated, and so
-on.</para>
-
-<para>The command <command>systemctl</command> is the main way to
-interact with <command>systemd</command>.  Without any arguments, it
-shows the status of active units:
-
-<screen>
-$ systemctl
--.mount          loaded active mounted   /
-swapfile.swap    loaded active active    /swapfile
-sshd.service     loaded active running   SSH Daemon
-graphical.target loaded active active    Graphical Interface
-<replaceable>...</replaceable>
-</screen>
-
-</para>
-
-<para>You can ask for detailed status information about a unit, for
-instance, the PostgreSQL database service:
-
-<screen>
-$ systemctl status postgresql.service
-postgresql.service - PostgreSQL Server
-          Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service)
-          Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago
-        Main PID: 2390 (postgres)
-          CGroup: name=systemd:/system/postgresql.service
-                  ├─2390 postgres
-                  ├─2418 postgres: writer process
-                  ├─2419 postgres: wal writer process
-                  ├─2420 postgres: autovacuum launcher process
-                  ├─2421 postgres: stats collector process
-                  └─2498 postgres: zabbix zabbix [local] idle
-
-Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG:  database system was shut down at 2013-01-07 15:55:05 CET
-Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG:  database system is ready to accept connections
-Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG:  autovacuum launcher started
-Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
-</screen>
-
-Note that this shows the status of the unit (active and running), all
-the processes belonging to the service, as well as the most recent log
-messages from the service.
-
-</para>
-
-<para>Units can be stopped, started or restarted:
-
-<screen>
-$ systemctl stop postgresql.service
-$ systemctl start postgresql.service
-$ systemctl restart postgresql.service
-</screen>
-
-These operations are synchronous: they wait until the service has
-finished starting or stopping (or has failed).  Starting a unit will
-cause the dependencies of that unit to be started as well (if
-necessary).</para>
-
-<!-- - cgroups: each service and user session is a cgroup
-
-- cgroup resource management -->
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-rebooting"><title>Rebooting and shutting down</title>
-
-<para>The system can be shut down (and automatically powered off) by
-doing:
-
-<screen>
-$ shutdown
-</screen>
-
-This is equivalent to running <command>systemctl
-poweroff</command>.</para>
-
-<para>To reboot the system, run
-
-<screen>
-$ reboot
-</screen>
-
-which is equivalent to <command>systemctl reboot</command>.
-Alternatively, you can quickly reboot the system using
-<literal>kexec</literal>, which bypasses the BIOS by directly loading
-the new kernel into memory:
-
-<screen>
-$ systemctl kexec
-</screen>
-
-</para>
-
-<para>The machine can be suspended to RAM (if supported) using
-<command>systemctl suspend</command>, and suspended to disk using
-<command>systemctl hibernate</command>.</para>
-
-<para>These commands can be run by any user who is logged in locally,
-i.e. on a virtual console or in X11; otherwise, the user is asked for
-authentication.</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-user-sessions"><title>User sessions</title>
-
-<para>Systemd keeps track of all users who are logged into the system
-(e.g. on a virtual console or remotely via SSH).  The command
-<command>loginctl</command> allows querying and manipulating user
-sessions.  For instance, to list all user sessions:
-
-<screen>
-$ loginctl
-   SESSION        UID USER             SEAT
-        c1        500 eelco            seat0
-        c3          0 root             seat0
-        c4        500 alice
-</screen>
-
-This shows that two users are logged in locally, while another is
-logged in remotely.  (“Seats” are essentially the combinations of
-displays and input devices attached to the system; usually, there is
-only one seat.)  To get information about a session:
-
-<screen>
-$ loginctl session-status c3
-c3 - root (0)
-           Since: Tue, 2013-01-08 01:17:56 CET; 4min 42s ago
-          Leader: 2536 (login)
-            Seat: seat0; vc3
-             TTY: /dev/tty3
-         Service: login; type tty; class user
-           State: online
-          CGroup: name=systemd:/user/root/c3
-                  ├─ 2536 /nix/store/10mn4xip9n7y9bxqwnsx7xwx2v2g34xn-shadow-4.1.5.1/bin/login --
-                  ├─10339 -bash
-                  └─10355 w3m nixos.org
-</screen>
-
-This shows that the user is logged in on virtual console 3.  It also
-lists the processes belonging to this session.  Since systemd keeps
-track of this, you can terminate a session in a way that ensures that
-all the session’s processes are gone:
-
-<screen>
-$ loginctl terminate-session c3
-</screen>
-
-</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-cgroups"><title>Control groups</title>
-
-<para>To keep track of the processes in a running system, systemd uses
-<emphasis>control groups</emphasis> (cgroups).  A control group is a
-set of processes used to allocate resources such as CPU, memory or I/O
-bandwidth.  There can be multiple control group hierarchies, allowing
-each kind of resource to be managed independently.</para>
-
-<para>The command <command>systemd-cgls</command> lists all control
-groups in the <literal>systemd</literal> hierarchy, which is what
-systemd uses to keep track of the processes belonging to each service
-or user session:
-
-<screen>
-$ systemd-cgls
-├─user
-│ └─eelco
-│   └─c1
-│     ├─ 2567 -:0
-│     ├─ 2682 kdeinit4: kdeinit4 Running...
-│     ├─ <replaceable>...</replaceable>
-│     └─10851 sh -c less -R
-└─system
-  ├─httpd.service
-  │ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH
-  │ └─<replaceable>...</replaceable>
-  ├─dhcpcd.service
-  │ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf
-  └─ <replaceable>...</replaceable>
-</screen>
-
-Similarly, <command>systemd-cgls cpu</command> shows the cgroups in
-the CPU hierarchy, which allows per-cgroup CPU scheduling priorities.
-By default, every systemd service gets its own CPU cgroup, while all
-user sessions are in the top-level CPU cgroup.  This ensures, for
-instance, that a thousand run-away processes in the
-<literal>httpd.service</literal> cgroup cannot starve the CPU for one
-process in the <literal>postgresql.service</literal> cgroup.  (By
-contrast, it they were in the same cgroup, then the PostgreSQL process
-would get 1/1001 of the cgroup’s CPU time.)  You can limit a service’s
-CPU share in <filename>configuration.nix</filename>:
-
-<programlisting>
-systemd.services.httpd.serviceConfig.CPUShares = 512;
-</programlisting>
-
-By default, every cgroup has 1024 CPU shares, so this will halve the
-CPU allocation of the <literal>httpd.service</literal> cgroup.</para>
-
-<para>There also is a <literal>memory</literal> hierarchy that
-controls memory allocation limits; by default, all processes are in
-the top-level cgroup, so any service or session can exhaust all
-available memory.  Per-cgroup memory limits can be specified in
-<filename>configuration.nix</filename>; for instance, to limit
-<literal>httpd.service</literal> to 512 MiB of RAM (excluding swap)
-and 640 MiB of RAM (including swap):
-
-<programlisting>
-systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
-systemd.services.httpd.serviceConfig.ControlGroupAttribute = [ "memory.memsw.limit_in_bytes 640M" ];
-</programlisting>
-
-</para>
-
-<para>The command <command>systemd-cgtop</command> shows a
-continuously updated list of all cgroups with their CPU and memory
-usage.</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-logging"><title>Logging</title>
-
-<para>System-wide logging is provided by systemd’s
-<emphasis>journal</emphasis>, which subsumes traditional logging
-daemons such as syslogd and klogd.  Log entries are kept in binary
-files in <filename>/var/log/journal/</filename>.  The command
-<literal>journalctl</literal> allows you to see the contents of the
-journal.  For example,
-
-<screen>
-$ journalctl -b
-</screen>
-
-shows all journal entries since the last reboot.  (The output of
-<command>journalctl</command> is piped into <command>less</command> by
-default.)  You can use various options and match operators to restrict
-output to messages of interest.  For instance, to get all messages
-from PostgreSQL:
-
-<screen>
-$ journalctl -u postgresql.service
--- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. --
-...
-Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG:  database system is shut down
--- Reboot --
-Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG:  database system was shut down at 2013-01-07 15:44:14 CET
-Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG:  database system is ready to accept connections
-</screen>
-
-Or to get all messages since the last reboot that have at least a
-“critical” severity level:
-
-<screen>
-$ journalctl -b -p crit
-Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice]
-Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1)
-</screen>
-
-</para>
-
-<para>The system journal is readable by root and by users in the
-<literal>wheel</literal> and <literal>systemd-journal</literal>
-groups.  All users have a private journal that can be read using
-<command>journalctl</command>.</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-nix-gc"><title>Cleaning up the Nix store</title>
-
-<para>Nix has a purely functional model, meaning that packages are
-never upgraded in place.  Instead new versions of packages end up in a
-different location in the Nix store (<filename>/nix/store</filename>).
-You should periodically run Nix’s <emphasis>garbage
-collector</emphasis> to remove old, unreferenced packages.  This is
-easy:
-
-<screen>
-$ nix-collect-garbage
-</screen>
-
-Alternatively, you can use a systemd unit that does the same in the
-background:
-
-<screen>
-$ systemctl start nix-gc.service
-</screen>
-
-You can tell NixOS in <filename>configuration.nix</filename> to run
-this unit automatically at certain points in time, for instance, every
-night at 03:15:
-
-<programlisting>
-nix.gc.automatic = true;
-nix.gc.dates = "03:15";
-</programlisting>
-
-</para>
-
-<para>The commands above do not remove garbage collector roots, such
-as old system configurations.  Thus they do not remove the ability to
-roll back to previous configurations.  The following command deletes
-old roots, removing the ability to roll back to them:
-<screen>
-$ nix-collect-garbage -d
-</screen>
-You can also do this for specific profiles, e.g.
-<screen>
-$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old
-</screen>
-Note that NixOS system configurations are stored in the profile
-<filename>/nix/var/nix/profiles/system</filename>.</para>
-
-<para>Another way to reclaim disk space (often as much as 40% of the
-size of the Nix store) is to run Nix’s store optimiser, which seeks
-out identical files in the store and replaces them with hard links to
-a single copy.
-<screen>
-$ nix-store --optimise
-</screen>
-Since this command needs to read the entire Nix store, it can take
-quite a while to finish.</para>
-
-</section>
-
-
-</chapter>
diff --git a/nixos/doc/manual/style.css b/nixos/doc/manual/style.css
index e2204c159e2..3118b37ead1 100644
--- a/nixos/doc/manual/style.css
+++ b/nixos/doc/manual/style.css
@@ -262,7 +262,6 @@ table.simplelist
     margin-bottom: 1em;
 }
 
-div.affiliation
-{
-    font-style: italic;
-}
\ No newline at end of file
+div.navheader table, div.navfooter table {
+    box-shadow: none;
+}
diff --git a/nixos/doc/manual/troubleshooting.xml b/nixos/doc/manual/troubleshooting.xml
deleted file mode 100644
index c7d65112b64..00000000000
--- a/nixos/doc/manual/troubleshooting.xml
+++ /dev/null
@@ -1,199 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
-         xmlns:xlink="http://www.w3.org/1999/xlink"
-         xml:id="ch-troubleshooting">
-
-<title>Troubleshooting</title>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-boot-problems"><title>Boot problems</title>
-
-<para>If NixOS fails to boot, there are a number of kernel command
-line parameters that may help you to identify or fix the issue.  You
-can add these parameters in the GRUB boot menu by pressing “e” to
-modify the selected boot entry and editing the line starting with
-<literal>linux</literal>.  The following are some useful kernel command
-line parameters that are recognised by the NixOS boot scripts or by
-systemd:
-
-<variablelist>
-
-  <varlistentry><term><literal>boot.shell_on_fail</literal></term>
-    <listitem><para>Start a root shell if something goes wrong in
-    stage 1 of the boot process (the initial ramdisk).  This is
-    disabled by default because there is no authentication for the
-    root shell.</para></listitem>
-  </varlistentry>
-
-  <varlistentry><term><literal>boot.debug1</literal></term>
-    <listitem><para>Start an interactive shell in stage 1 before
-    anything useful has been done.  That is, no modules have been
-    loaded and no file systems have been mounted, except for
-    <filename>/proc</filename> and
-    <filename>/sys</filename>.</para></listitem>
-  </varlistentry>
-
-  <varlistentry><term><literal>boot.trace</literal></term>
-    <listitem><para>Print every shell command executed by the stage 1
-    and 2 boot scripts.</para></listitem>
-  </varlistentry>
-
-  <varlistentry><term><literal>single</literal></term>
-    <listitem><para>Boot into rescue mode (a.k.a. single user mode).
-    This will cause systemd to start nothing but the unit
-    <literal>rescue.target</literal>, which runs
-    <command>sulogin</command> to prompt for the root password and
-    start a root login shell.  Exiting the shell causes the system to
-    continue with the normal boot process.</para></listitem>
-  </varlistentry>
-
-  <varlistentry><term><literal>systemd.log_level=debug systemd.log_target=console</literal></term>
-    <listitem><para>Make systemd very verbose and send log messages to
-    the console instead of the journal.</para></listitem>
-  </varlistentry>
-
-</variablelist>
-
-For more parameters recognised by systemd, see
-<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
-
-<para>If no login prompts or X11 login screens appear (e.g. due to
-hanging dependencies), you can press Alt+ArrowUp.  If you’re lucky,
-this will start rescue mode (described above).  (Also note that since
-most units have a 90-second timeout before systemd gives up on them,
-the <command>agetty</command> login prompts should appear eventually
-unless something is very wrong.)</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-maintenance-mode"><title>Maintenance mode</title>
-
-<para>You can enter rescue mode by running:
-
-<screen>
-$ systemctl rescue</screen>
-
-This will eventually give you a single-user root shell.  Systemd will
-stop (almost) all system services.  To get out of maintenance mode,
-just exit from the rescue shell.</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-rollback"><title>Rolling back configuration changes</title>
-
-<para>After running <command>nixos-rebuild</command> to switch to a
-new configuration, you may find that the new configuration doesn’t
-work very well.  In that case, there are several ways to return to a
-previous configuration.</para>
-
-<para>First, the GRUB boot manager allows you to boot into any
-previous configuration that hasn’t been garbage-collected.  These
-configurations can be found under the GRUB submenu “NixOS - All
-configurations”.  This is especially useful if the new configuration
-fails to boot.  After the system has booted, you can make the selected
-configuration the default for subsequent boots:
-
-<screen>
-$ /run/current-system/bin/switch-to-configuration boot</screen>
-
-</para>
-
-<para>Second, you can switch to the previous configuration in a running
-system:
-
-<screen>
-$ nixos-rebuild switch --rollback</screen>
-
-This is equivalent to running:
-
-<screen>
-$ /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen>
-
-where <replaceable>N</replaceable> is the number of the NixOS system
-configuration.  To get a list of the available configurations, do:
-
-<screen>
-$ ls -l /nix/var/nix/profiles/system-*-link
-<replaceable>...</replaceable>
-lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055
-</screen>
-
-</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-nix-store-corruption"><title>Nix store corruption</title>
-
-<para>After a system crash, it’s possible for files in the Nix store
-to become corrupted.  (For instance, the Ext4 file system has the
-tendency to replace un-synced files with zero bytes.)  NixOS tries
-hard to prevent this from happening: it performs a
-<command>sync</command> before switching to a new configuration, and
-Nix’s database is fully transactional.  If corruption still occurs,
-you may be able to fix it automatically.</para>
-
-<para>If the corruption is in a path in the closure of the NixOS
-system configuration, you can fix it by doing
-
-<screen>
-$ nixos-rebuild switch --repair
-</screen>
-
-This will cause Nix to check every path in the closure, and if its
-cryptographic hash differs from the hash recorded in Nix’s database,
-the path is rebuilt or redownloaded.</para>
-
-<para>You can also scan the entire Nix store for corrupt paths:
-
-<screen>
-$ nix-store --verify --check-contents --repair
-</screen>
-
-Any corrupt paths will be redownloaded if they’re available in a
-binary cache; otherwise, they cannot be repaired.</para>
-
-</section>
-
-
-<!--===============================================================-->
-
-<section xml:id="sec-nix-network-issues"><title>Nix network issues</title>
-
-<para>Nix uses a so-called <emphasis>binary cache</emphasis> to
-optimise building a package from source into downloading it as a
-pre-built binary.  That is, whenever a command like
-<command>nixos-rebuild</command> needs a path in the Nix store, Nix
-will try to download that path from the Internet rather than build it
-from source.  The default binary cache is
-<uri>http://cache.nixos.org/</uri>.  If this cache is unreachable, Nix
-operations may take a long time due to HTTP connection timeouts.  You
-can disable the use of the binary cache by adding <option>--option
-use-binary-caches false</option>, e.g.
-
-<screen>
-$ nixos-rebuild switch --option use-binary-caches false
-</screen>
-
-If you have an alternative binary cache at your disposal, you can use
-it instead:
-
-<screen>
-$ nixos-rebuild switch --option binary-caches http://my-cache.example.org/
-</screen>
-
-</para>
-
-</section>
-
-
-</chapter>
diff --git a/nixos/lib/build-vms.nix b/nixos/lib/build-vms.nix
index 498c0a37783..50b3b424166 100644
--- a/nixos/lib/build-vms.nix
+++ b/nixos/lib/build-vms.nix
@@ -48,10 +48,11 @@ rec {
             let
               interfacesNumbered = zipTwoLists config.virtualisation.vlans (range 1 255);
               interfaces = flip map interfacesNumbered ({ first, second }:
-                nameValuePair "eth${toString second}"
-                  { ipAddress = "192.168.${toString first}.${toString m.second}";
-                    subnetMask = "255.255.255.0";
-                  });
+                nameValuePair "eth${toString second}" { ip4 =
+                  [ { address = "192.168.${toString first}.${toString m.second}";
+                      prefixLength = 24;
+                  } ];
+                });
             in
             { key = "ip-address";
               config =
@@ -60,7 +61,7 @@ rec {
                   networking.interfaces = listToAttrs interfaces;
 
                   networking.primaryIPAddress =
-                    optionalString (interfaces != []) (head interfaces).value.ipAddress;
+                    optionalString (interfaces != []) (head (head interfaces).value.ip4).address;
 
                   # Put the IP addresses of all VMs in this machine's
                   # /etc/hosts file.  If a machine has multiple
diff --git a/nixos/lib/make-system-tarball.nix b/nixos/lib/make-system-tarball.nix
index 8fed9a34882..3bd891fdbc2 100644
--- a/nixos/lib/make-system-tarball.nix
+++ b/nixos/lib/make-system-tarball.nix
@@ -15,6 +15,9 @@
   # store path whose closure will be copied, and `symlink' is a
   # symlink to `object' that will be added to the tarball.
   storeContents ? []
+
+  # Extra tar arguments
+, extraArgs ? ""
 }:
 
 stdenv.mkDerivation {
@@ -22,7 +25,7 @@ stdenv.mkDerivation {
   builder = ./make-system-tarball.sh;
   buildInputs = [perl xz];
 
-  inherit fileName pathsFromGraph;
+  inherit fileName pathsFromGraph extraArgs;
 
   # !!! should use XML.
   sources = map (x: x.source) contents;
diff --git a/nixos/lib/make-system-tarball.sh b/nixos/lib/make-system-tarball.sh
index 096d96ac1c8..2eb668115a6 100644
--- a/nixos/lib/make-system-tarball.sh
+++ b/nixos/lib/make-system-tarball.sh
@@ -50,7 +50,7 @@ done
 
 mkdir -p $out/tarball
 
-tar cvJf $out/tarball/$fileName.tar.xz *
+tar cvJf $out/tarball/$fileName.tar.xz * $extraArgs
 
 mkdir -p $out/nix-support
 echo $system > $out/nix-support/system
diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix
index 35c56e8c32b..7b8be2050c1 100644
--- a/nixos/lib/utils.nix
+++ b/nixos/lib/utils.nix
@@ -5,6 +5,7 @@ rec {
   # Escape a path according to the systemd rules, e.g. /dev/xyzzy
   # becomes dev-xyzzy.  FIXME: slow.
   escapeSystemdPath = s:
-   replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"] (substring 1 (stringLength s) s);
+   replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
+    (if hasPrefix "/" s then substring 1 (stringLength s) s else s);
 
 }
diff --git a/nixos/maintainers/scripts/gce/create-gce.sh b/nixos/maintainers/scripts/gce/create-gce.sh
index 8bf36f33c7d..fc476fb6e40 100755
--- a/nixos/maintainers/scripts/gce/create-gce.sh
+++ b/nixos/maintainers/scripts/gce/create-gce.sh
@@ -1,5 +1,6 @@
 #! /bin/sh -e
 
+BUCKET_NAME=${BUCKET_NAME:-nixos}
 export NIX_PATH=nixpkgs=../../../..
 export NIXOS_CONFIG=$(dirname $(readlink -f $0))/../../../modules/virtualisation/google-compute-image.nix
 export TIMESTAMP=$(date +%Y%m%d%H%M)
@@ -8,7 +9,7 @@ nix-build '<nixpkgs/nixos>' \
    -A config.system.build.googleComputeImage --argstr system x86_64-linux -o gce --option extra-binary-caches http://hydra.nixos.org -j 10
 
 img=$(echo gce/*.tar.gz)
-if ! gsutil ls gs://nixos/$(basename $img); then
-  gsutil cp $img gs://nixos/$(basename $img)
+if ! gsutil ls gs://${BUCKET_NAME}/$(basename $img); then
+  gsutil cp $img gs://${BUCKET_NAME}/$(basename $img)
 fi
-gcutil addimage $(basename $img .raw.tar.gz | sed 's|\.|-|' | sed 's|_|-|') gs://nixos/$(basename $img)
+gcloud compute images create $(basename $img .raw.tar.gz | sed 's|\.|-|' | sed 's|_|-|') --source-uri gs://${BUCKET_NAME}/$(basename $img)
diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix
index 49b1e1d42a3..f6060a910a1 100644
--- a/nixos/modules/config/fonts/fonts.nix
+++ b/nixos/modules/config/fonts/fonts.nix
@@ -11,7 +11,7 @@ with lib;
       # TODO: find another name for it.
       fonts = mkOption {
         type = types.listOf types.path;
-        example = [ pkgs.dejavu_fonts ];
+        example = literalExample "[ pkgs.dejavu_fonts ]";
         description = "List of primary font paths.";
         apply = list: list ++
           [ # - the user's current profile
diff --git a/nixos/modules/config/gtk-exe-env.nix b/nixos/modules/config/gtk-exe-env.nix
new file mode 100644
index 00000000000..b565072e3a7
--- /dev/null
+++ b/nixos/modules/config/gtk-exe-env.nix
@@ -0,0 +1,41 @@
+{ config, pkgs, lib, ... }:
+
+{
+  imports = [
+  ];
+
+  options = {
+    gtkPlugins = lib.mkOption {
+      type = lib.types.listOf lib.types.path;
+      default = [];
+      description = ''
+        Plugin packages for GTK+ such as input methods.
+      '';
+    };
+  };
+
+  config = {
+    environment.variables = if builtins.length config.gtkPlugins > 0
+      then
+        let
+          paths = [ pkgs.gtk2 pkgs.gtk3 ] ++ config.gtkPlugins;
+          env = pkgs.buildEnv {
+            name = "gtk-exe-env";
+
+            inherit paths;
+
+            postBuild = lib.concatStringsSep "\n"
+              (map (d: d.gtkExeEnvPostBuild or "") paths);
+
+            ignoreCollisions = true;
+          };
+        in {
+          GTK_EXE_PREFIX = builtins.toString env;
+          GTK_PATH = [
+            "${env}/lib/gtk-2.0"
+            "${env}/lib/gtk-3.0"
+          ];
+        }
+      else {};
+  };
+}
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index fd1e55f673a..136a5bda745 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -7,6 +7,9 @@ with lib;
 let
 
   cfg = config.networking;
+  dnsmasqResolve = config.services.dnsmasq.enable &&
+                   config.services.dnsmasq.resolveLocalQueries;
+  hasLocalResolver = config.services.bind.enable || dnsmasqResolve;
 
 in
 
@@ -74,9 +77,12 @@ in
             '' + optionalString cfg.dnsSingleRequest ''
               # only send one DNS request at a time
               resolv_conf_options='single-request'
-            '' + optionalString config.services.bind.enable ''
+            '' + optionalString hasLocalResolver ''
               # This hosts runs a full-blown DNS resolver.
               name_servers='127.0.0.1'
+            '' + optionalString dnsmasqResolve ''
+              dnsmasq_conf=/etc/dnsmasq-conf.conf
+              dnsmasq_resolv=/etc/dnsmasq-resolv.conf
             '';
       };
 
diff --git a/nixos/modules/config/power-management.nix b/nixos/modules/config/power-management.nix
index 17f3ed00b9b..32a7987617a 100644
--- a/nixos/modules/config/power-management.nix
+++ b/nixos/modules/config/power-management.nix
@@ -35,7 +35,9 @@ in
       powerUpCommands = mkOption {
         type = types.lines;
         default = "";
-        example = "${pkgs.hdparm}/sbin/hdparm -B 255 /dev/sda";
+        example = literalExample ''
+          "''${pkgs.hdparm}/sbin/hdparm -B 255 /dev/sda"
+        '';
         description =
           ''
             Commands executed when the machine powers up.  That is,
@@ -47,7 +49,9 @@ in
       powerDownCommands = mkOption {
         type = types.lines;
         default = "";
-        example = "${pkgs.hdparm}/sbin/hdparm -B 255 /dev/sda";
+        example = literalExample ''
+          "''${pkgs.hdparm}/sbin/hdparm -B 255 /dev/sda"
+        '';
         description =
           ''
             Commands executed when the machine powers down.  That is,
diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix
index 96593885e5b..fb5715022b7 100644
--- a/nixos/modules/config/pulseaudio.nix
+++ b/nixos/modules/config/pulseaudio.nix
@@ -10,10 +10,12 @@ let
   systemWide = cfg.enable && cfg.systemWide;
   nonSystemWide = cfg.enable && !cfg.systemWide;
 
-  uid = config.ids.uids.pulseaudio;
-  gid = config.ids.gids.pulseaudio;
+  ids = config.ids;
 
-  stateDir = "/run/pulse";
+  uid = ids.uids.pulseaudio;
+  gid = ids.gids.pulseaudio;
+
+  stateDir = "/var/run/pulse";
 
   # Create pulse/client.conf even if PulseAudio is disabled so
   # that we can disable the autospawn feature in programs that
@@ -81,7 +83,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pulseaudioFull;
-        example = literalExample "pulseaudioFull";
+        example = literalExample "pkgs.pulseaudioFull";
         description = ''
           The PulseAudio derivation to use.  This can be used to disable
           features (such as JACK support, Bluetooth) that are enabled in the
@@ -138,6 +140,8 @@ in {
         group = "pulse";
         extraGroups = [ "audio" ];
         description = "PulseAudio system service user";
+        home = stateDir;
+        createHome = true;
       };
 
       users.extraGroups.pulse.gid = gid;
@@ -147,10 +151,6 @@ in {
         wantedBy = [ "sound.target" ];
         before = [ "sound.target" ];
         environment.PULSE_RUNTIME_PATH = stateDir;
-        preStart = ''
-          mkdir -p --mode 755 ${stateDir}
-          chown -R pulse:pulse ${stateDir}
-        '';
         serviceConfig = {
           ExecStart = "${cfg.package}/bin/pulseaudio -D --log-level=${cfg.daemon.logLevel} --system --use-pid-file -n --file=${cfg.configFile}";
           PIDFile = "${stateDir}/pid";
diff --git a/nixos/modules/config/qt-plugin-env.nix b/nixos/modules/config/qt-plugin-env.nix
new file mode 100644
index 00000000000..c5986560416
--- /dev/null
+++ b/nixos/modules/config/qt-plugin-env.nix
@@ -0,0 +1,37 @@
+{ config, pkgs, lib, ... }:
+
+{
+  imports = [
+  ];
+
+  options = {
+    qtPlugins = lib.mkOption {
+      type = lib.types.listOf lib.types.path;
+      default = [];
+      description = ''
+        Plugin packages for Qt such as input methods.
+      '';
+    };
+  };
+
+  config = {
+    environment.variables = if builtins.length config.qtPlugins > 0
+      then
+        let
+          paths = [ pkgs.qt48 ] ++ config.qtPlugins;
+          env = pkgs.buildEnv {
+            name = "qt-plugin-env";
+
+            inherit paths;
+
+            postBuild = lib.concatStringsSep "\n"
+              (map (d: d.qtPluginEnvPostBuild or "") paths);
+
+            ignoreCollisions = true;
+          };
+        in {
+          QT_PLUGIN_PATH = [ (builtins.toString env) ];
+        }
+      else {};
+  };
+}
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index cc079cdc585..2559c53ac16 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -122,7 +122,9 @@ in
 
     environment.binsh = mkOption {
       default = "${config.system.build.binsh}/bin/sh";
-      example = "\${pkgs.dash}/bin/dash";
+      example = literalExample ''
+        "''${pkgs.dash}/bin/dash"
+      '';
       type = types.path;
       description = ''
         The shell executable that is linked system-wide to
diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix
index 6b4c38172e9..f3e86bfd201 100644
--- a/nixos/modules/config/system-path.nix
+++ b/nixos/modules/config/system-path.nix
@@ -63,7 +63,7 @@ in
       systemPackages = mkOption {
         type = types.listOf types.path;
         default = [];
-        example = "[ pkgs.icecat3 pkgs.thunderbird ]";
+        example = literalExample "[ pkgs.firefox pkgs.thunderbird ]";
         description = ''
           The set of packages that appear in
           /run/current-system/sw.  These packages are
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 5de81a77342..a55593c2bad 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -100,6 +100,36 @@ let
         description = "The path to the user's shell.";
       };
 
+      subUidRanges = mkOption {
+        type = types.listOf types.optionSet;
+        default = [];
+        example = [
+          { startUid = 1000; count = 1; }
+          { startUid = 100001; count = 65534; }
+        ];
+        options = [ subordinateUidRange ];
+        description = ''
+          Subordinate user ids that user is allowed to use.
+          They are set into <filename>/etc/subuid</filename> and are used
+          by <literal>newuidmap</literal> for user namespaces.
+        '';
+      };
+
+      subGidRanges = mkOption {
+        type = types.listOf types.optionSet;
+        default = [];
+        example = [
+          { startGid = 100; count = 1; }
+          { startGid = 1001; count = 999; }
+        ];
+        options = [ subordinateGidRange ];
+        description = ''
+          Subordinate group ids that user is allowed to use.
+          They are set into <filename>/etc/subgid</filename> and are used
+          by <literal>newgidmap</literal> for user namespaces.
+        '';
+      };
+
       createHome = mkOption {
         type = types.bool;
         default = false;
@@ -211,6 +241,36 @@ let
 
   };
 
+  subordinateUidRange = {
+    startUid = mkOption {
+      type = types.int;
+      description = ''
+        Start of the range of subordinate user ids that user is
+        allowed to use.
+      '';
+    };
+    count = mkOption {
+      type = types.int;
+      default = 1;
+      description = ''Count of subordinate user ids'';
+    };
+  };
+
+  subordinateGidRange = {
+    startGid = mkOption {
+      type = types.int;
+      description = ''
+        Start of the range of subordinate group ids that user is
+        allowed to use.
+      '';
+    };
+    count = mkOption {
+      type = types.int;
+      default = 1;
+      description = ''Count of subordinate group ids'';
+    };
+  };
+
   getGroup = gname:
     let
       groups = mapAttrsToList (n: g: g) (
@@ -249,22 +309,36 @@ let
       u.description u.home u.shell
     ];
 
+  filterNull = a: filter (x: hasAttr a x && getAttr a x != null);
+
   sortOn = a: sort (as1: as2: lessThan (getAttr a as1) (getAttr a as2));
 
   groupFile = pkgs.writeText "group" (
     concatStringsSep "\n" (map (g: mkGroupEntry g.name) (
-      let f = g: g.gid != null; in
-        sortOn "gid" (filter f (attrValues cfg.extraGroups))
+      sortOn "gid" (filterNull "gid" (attrValues cfg.extraGroups))
     ))
   );
 
   passwdFile = pkgs.writeText "passwd" (
     concatStringsSep "\n" (map (u: mkPasswdEntry u.name) (
-      let f = u: u.createUser && (u.uid != null); in
-        sortOn "uid" (filter f (attrValues cfg.extraUsers))
+      sortOn "uid" (filterNull "uid" (attrValues cfg.extraUsers))
     ))
   );
 
+  mkSubuidEntry = user: concatStrings (
+    map (range: "${user.name}:${toString range.startUid}:${toString range.count}\n")
+        user.subUidRanges);
+
+  subuidFile = concatStrings (map mkSubuidEntry (
+    sortOn "uid" (filterNull "uid" (attrValues cfg.extraUsers))));
+
+  mkSubgidEntry = user: concatStrings (
+    map (range: "${user.name}:${toString range.startGid}:${toString range.count}\n")
+        user.subGidRanges);
+
+  subgidFile = concatStrings (map mkSubgidEntry (
+    sortOn "uid" (filterNull "uid" (attrValues cfg.extraUsers))));
+
   # If mutableUsers is true, this script adds all users/groups defined in
   # users.extra{Users,Groups} to /etc/{passwd,group} iff there isn't any
   # existing user/group with the same name in those files.
@@ -404,7 +478,7 @@ in {
         uid = ids.uids.root;
         description = "System administrator";
         home = "/root";
-        shell = cfg.defaultUserShell;
+        shell = mkDefault cfg.defaultUserShell;
         group = "root";
         extraGroups = [ "grsecurity" ];
         hashedPassword = mkDefault config.security.initialRootPassword;
@@ -504,6 +578,15 @@ in {
     # for backwards compatibility
     system.activationScripts.groups = stringAfter [ "users" ] "";
 
+    environment.etc."subuid" = {
+      text = subuidFile;
+      mode = "0644";
+    };
+    environment.etc."subgid" = {
+      text = subgidFile;
+      mode = "0644";
+    };
+
     assertions = [
       { assertion = !cfg.enforceIdUniqueness || (uidsAreUnique && gidsAreUnique);
         message = "uids and gids must be unique!";
diff --git a/nixos/modules/config/vpnc.nix b/nixos/modules/config/vpnc.nix
new file mode 100644
index 00000000000..68d755232eb
--- /dev/null
+++ b/nixos/modules/config/vpnc.nix
@@ -0,0 +1,41 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.networking.vpnc;
+  mkServiceDef = name: value:
+    {
+      name = "vpnc/${name}.conf";
+      value = { text = value; };
+    };
+
+in
+{
+  options = {
+    networking.vpnc = {
+      services = mkOption {
+       type = types.attrsOf types.str;
+       default = {};
+       example = {
+         test = 
+          ''
+           IPSec gateway 192.168.1.1 
+           IPSec ID someID
+           IPSec secret secretKey
+           Xauth username name
+           Xauth password pass
+          '';
+       };
+       description = 
+         ''
+           The names of cisco VPNs and their associated definitions
+         '';
+      };
+    };
+  };
+
+  config.environment.etc = mapAttrs' mkServiceDef cfg.services;
+}
+
+
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index d43fa220381..22f31c46080 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -11,7 +11,7 @@ let
   # The Grub image.
   grubImage = pkgs.runCommand "grub_eltorito" {}
     ''
-      ${pkgs.grub2}/bin/grub-mkimage -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
+      ${pkgs.grub2}/bin/grub-mkimage -p /boot/grub -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
       cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out
     ''; # */
 
@@ -113,11 +113,12 @@ in
     };
 
     isoImage.contents = mkOption {
-      example =
+      example = literalExample ''
         [ { source = pkgs.memtest86 + "/memtest.bin";
             target = "boot/memtest.bin";
           }
-        ];
+        ]
+      '';
       description = ''
         This option lists files to be copied to fixed locations in the
         generated ISO image.
@@ -125,7 +126,7 @@ in
     };
 
     isoImage.storeContents = mkOption {
-      example = [pkgs.stdenv];
+      example = literalExample "[ pkgs.stdenv ]";
       description = ''
         This option lists additional derivations to be included in the
         Nix store in the generated ISO image.
diff --git a/nixos/modules/installer/cd-dvd/system-tarball.nix b/nixos/modules/installer/cd-dvd/system-tarball.nix
index eaecbe1381f..c24fe97fba4 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball.nix
+++ b/nixos/modules/installer/cd-dvd/system-tarball.nix
@@ -15,11 +15,12 @@ in
 {
   options = {
     tarball.contents = mkOption {
-      example =
+      example = literalExample ''
         [ { source = pkgs.memtest86 + "/memtest.bin";
             target = "boot/memtest.bin";
           }
-        ];
+        ]
+      '';
       description = ''
         This option lists files to be copied to fixed locations in the
         generated ISO image.
@@ -27,7 +28,7 @@ in
     };
 
     tarball.storeContents = mkOption {
-      example = [pkgs.stdenv];
+      example = literalExample "[ pkgs.stdenv ]";
       description = ''
         This option lists additional derivations to be included in the
         Nix store in the generated ISO image.
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 66a8152a3a6..c6f499b8250 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -20,6 +20,13 @@ sub uniq {
     return @res;
 }
 
+sub runCommand {
+    my ($cmd) = @_;
+    open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n";
+    my @ret = <FILE>;
+    close FILE;
+    return ($?, @ret);
+}
 
 # Process the command line.
 my $outDir = "/etc/nixos";
@@ -304,10 +311,13 @@ foreach my $fs (read_file("/proc/self/mountinfo")) {
 
     # Maybe this is a bind-mount of a filesystem we saw earlier?
     if (defined $fsByDev{$fields[2]}) {
-        my $path = $fields[3]; $path = "" if $path eq "/";
-        my $base = $fsByDev{$fields[2]};
-        $base = "" if $base eq "/";
-        $fileSystems .= <<EOF;
+        # Make sure this isn't a btrfs subvolume
+        my ($status, @msg) = runCommand("btrfs subvol show $rootDir$mountPoint");
+        if (join("", @msg) =~ /ERROR:/) {
+            my $path = $fields[3]; $path = "" if $path eq "/";
+            my $base = $fsByDev{$fields[2]};
+            $base = "" if $base eq "/";
+            $fileSystems .= <<EOF;
   fileSystems.\"$mountPoint\" =
     { device = \"$base$path\";
       fsType = \"none\";
@@ -315,7 +325,8 @@ foreach my $fs (read_file("/proc/self/mountinfo")) {
     };
 
 EOF
-        next;
+            next;
+        }
     }
     $fsByDev{$fields[2]} = $mountPoint;
 
@@ -337,6 +348,30 @@ EOF
         }
     }
 
+    # Is this a btrfs filesystem?
+    if ($fsType eq "btrfs") {
+        my ($status, @id_info) = runCommand("btrfs subvol show $rootDir$mountPoint");
+        if ($status != 0 || join("", @msg) =~ /ERROR:/) {
+            die "Failed to retreive subvolume info for $mountPoint\n";
+        }
+        my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/;
+        if ($#ids > 0) {
+            die "Btrfs subvol name for $mountPoint listed multiple times in mount\n"
+        } elsif ($#ids == 0) {
+            my ($status, @path_info) = runCommand("btrfs subvol list $rootDir$mountPoint");
+            if ($status != 0) {
+                die "Failed to find $mountPoint subvolume id from btrfs\n";
+            }
+            my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/;
+            if ($#paths > 0) {
+                die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n";
+            } elsif ($#paths != 0) {
+                die "Btrfs did not return a path for the subvolume at $mountPoint\n";
+            }
+            push @extraOptions, "subvol=$paths[0]";
+        }
+    }
+
     # Emit the filesystem.
     $fileSystems .= <<EOF;
   fileSystems.\"$mountPoint\" =
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index a55eda1cb8f..bd334c2a3cb 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -7,6 +7,9 @@
 #   * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration>
 #   * install the boot loader
 
+# Ensure a consistent umask.
+umask 0022
+
 # Re-exec ourselves in a private mount namespace so that our bind
 # mounts get cleaned up automatically.
 if [ "$(id -u)" = 0 ]; then
@@ -30,6 +33,9 @@ while [ "$#" -gt 0 ]; do
             absolute_path=$(readlink -m $given_path)
             extraBuildFlags+=("$i" "/mnt$absolute_path")
             ;;
+        --root)
+            mountPoint="$1"; shift 1
+            ;;
         --show-trace)
             extraBuildFlags+=("$i")
             ;;
@@ -240,7 +246,7 @@ chroot $mountPoint /nix/var/nix/profiles/system/activate
 # Ask the user to set a root password.
 if [ -t 0 ] ; then
     echo "setting root password..."
-    chroot $mountPoint passwd
+    chroot $mountPoint /var/setuid-wrappers/passwd
 fi
 
 
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
index edc94d73208..d995787c76f 100644
--- a/nixos/modules/installer/tools/nixos-option.sh
+++ b/nixos/modules/installer/tools/nixos-option.sh
@@ -11,9 +11,6 @@ usage () {
 # Process Arguments #
 #####################
 
-desc=false
-defs=false
-value=false
 xml=false
 verbose=false
 
@@ -24,14 +21,11 @@ for arg; do
   if test -z "$argfun"; then
     case $arg in
       -*)
-        longarg=""
         sarg="$arg"
+        longarg=""
         while test "$sarg" != "-"; do
           case $sarg in
             --*) longarg=$arg; sarg="--";;
-            -d*) longarg="$longarg --description";;
-            -v*) longarg="$longarg --value";;
-            -l*) longarg="$longarg --lookup";;
             -*) usage;;
           esac
           # remove the first letter option
@@ -42,9 +36,6 @@ for arg; do
     esac
     for larg in $longarg; do
       case $larg in
-        --description) desc=true;;
-        --value) value=true;;
-        --lookup) defs=true;;
         --xml) xml=true;;
         --verbose) verbose=true;;
         --help) usage;;
@@ -67,16 +58,6 @@ for arg; do
   fi
 done
 
-if $xml; then
-  value=true
-  desc=true
-  defs=true
-fi
-
-if ! $defs && ! $desc; then
-  value=true
-fi
-
 if $verbose; then
   set -x
 else
@@ -95,8 +76,7 @@ evalAttr(){
   local prefix="$1"
   local strict="$2"
   local suffix="$3"
-  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" |
-    evalNix ${strict:+--strict}
+  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" | evalNix ${strict:+--strict}
 }
 
 evalOpt(){
@@ -189,35 +169,35 @@ EOF
 fi
 
 if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then
-  $value && evalCfg 1
-
-  if $desc; then
-    $value && echo;
-
-    if default=$(evalOpt "default" - 2> /dev/null); then
-      echo "Default: $default"
-    else
-      echo "Default: <None>"
-    fi
-    if example=$(evalOpt "example" - 2> /dev/null); then
-      echo "Example: $example"
-    fi
-    echo "Description:"
-    eval printf $(evalOpt "description")
+  echo "Value:"
+  evalCfg 1
+
+  echo
+
+  echo "Default:"
+  if default=$(evalOpt "default" - 2> /dev/null); then
+    echo "$default"
+  else
+    echo "<None>"
+  fi
+  echo
+  if example=$(evalOpt "example" - 2> /dev/null); then
+    echo "Example: $example"
   fi
+  echo "Description:"
+  echo
+  eval printf $(evalOpt "description")
 
-  if $defs; then
-    $desc || $value && echo;
+  echo $desc;
 
-    printPath () { echo "  $1"; }
+  printPath () { echo "  $1"; }
 
-    echo "Declared by:"
-    nixMap printPath "$(findSources "declarations")"
-    echo ""
-    echo "Defined by:"
-    nixMap printPath "$(findSources "files")"
-    echo ""
-  fi
+  echo "Declared by:"
+  nixMap printPath "$(findSources "declarations")"
+  echo
+  echo "Defined by:"
+  nixMap printPath "$(findSources "files")"
+  echo
 
 else
   # echo 1>&2 "Warning: This value is not an option."
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 39da2f1f0be..91a30695a7a 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -38,6 +38,7 @@ let
   nixos-generate-config = makeProg {
     name = "nixos-generate-config";
     src = ./nixos-generate-config.pl;
+    path = [ pkgs.btrfsProgs ];
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
   };
 
diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix
index f68f8dc40aa..49ec0899610 100644
--- a/nixos/modules/installer/virtualbox-demo.nix
+++ b/nixos/modules/installer/virtualbox-demo.nix
@@ -10,6 +10,9 @@ with lib;
       ../profiles/clone-config.nix
     ];
 
+  # FIXME: UUID detection is currently broken
+  boot.loader.grub.fsIdentifier = "provided";
+
   # Allow mounting of shared folders.
   users.extraUsers.demo.extraGroups = [ "vboxsf" ];
 
diff --git a/nixos/modules/misc/crashdump.nix b/nixos/modules/misc/crashdump.nix
index d68f38bae2f..773b5ac9da3 100644
--- a/nixos/modules/misc/crashdump.nix
+++ b/nixos/modules/misc/crashdump.nix
@@ -28,7 +28,7 @@ in
           # We don't want to evaluate all of linuxPackages for the manual
           # - some of it might not even evaluate correctly.
           defaultText = "pkgs.linuxPackages";
-          example = "pkgs.linuxPackages_2_6_25";
+          example = literalExample "pkgs.linuxPackages_2_6_25";
           description = ''
             This will override the boot.kernelPackages, and will add some
             kernel configuration parameters for the crash dump to work.
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index fa81ff8a839..37531ad1cdf 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -141,6 +141,16 @@
       unifi = 131;
       gdm = 132;
       dhcpd = 133;
+      siproxd = 134;
+      mlmmj = 135;
+      neo4j = 136;
+      riemann = 137;
+      riemanndash = 138;
+      radvd = 139;
+      zookeeper = 140;
+      dnsmasq = 141;
+      uhub = 142;
+      yandexdisk=143;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -256,6 +266,11 @@
       docker = 131;
       gdm = 132;
       tss = 133;
+      siproxd = 134;
+      mlmmj = 135;
+      riemann = 137;
+      riemanndash = 138;
+      uhub = 142;
 
       # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399!
 
diff --git a/nixos/modules/misc/meta.nix b/nixos/modules/misc/meta.nix
new file mode 100644
index 00000000000..22622706f2c
--- /dev/null
+++ b/nixos/modules/misc/meta.nix
@@ -0,0 +1,63 @@
+{ config, lib, ... }:
+
+with lib;
+
+let
+  maintainer = mkOptionType {
+    name = "maintainer";
+    check = email: elem email (attrValues lib.maintainers);
+    merge = loc: defs: listToAttrs (singleton (nameValuePair (last defs).file (last defs).value));
+  };
+
+  listOfMaintainers = types.listOf maintainer // {
+    # Returns list of
+    #   { "module-file" = [
+    #        "maintainer1 <first@nixos.org>"
+    #        "maintainer2 <second@nixos.org>" ];
+    #   }
+    merge = loc: defs:
+      zipAttrs
+        (flatten (imap (n: def: imap (m: def':
+          maintainer.merge (loc ++ ["[${toString n}-${toString m}]"])
+            [{ inherit (def) file; value = def'; }]) def.value) defs));
+  };
+
+  docFile = types.path // {
+    # Returns tuples of
+    #   { file = "module location"; value = <path/to/doc.xml>; }
+    merge = loc: defs: defs;
+  };
+in
+
+{
+  options = {
+    meta = {
+
+      maintainers = mkOption {
+        type = listOfMaintainers;
+        internal = true;
+        default = [];
+        example = [ lib.maintainers.all ];
+        description = ''
+	  List of maintainers of each module.  This option should be defined at
+          most once per module.
+        '';
+      };
+
+      doc = mkOption {
+        type = docFile;
+        internal = true;
+        example = "./meta.xml";
+        description = ''
+	  Documentation prologe for the set of options of each module.  This
+          option should be defined at most once per module.
+        '';
+      };
+
+    };
+  };
+
+  config = {
+    meta.maintainers = singleton lib.maintainers.pierron;
+  };
+}
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 453899175e0..61a98ca12ff 100644..100755
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -5,6 +5,7 @@
   ./config/fonts/fonts.nix
   ./config/fonts/ghostscript.nix
   ./config/gnu.nix
+  ./config/gtk-exe-env.nix
   ./config/i18n.nix
   ./config/krb5.nix
   ./config/ldap.nix
@@ -13,12 +14,14 @@
   ./config/nsswitch.nix
   ./config/power-management.nix
   ./config/pulseaudio.nix
+  ./config/qt-plugin-env.nix
   ./config/shells-environment.nix
   ./config/swap.nix
   ./config/sysctl.nix
   ./config/system-environment.nix
   ./config/system-path.nix
   ./config/timezone.nix
+  ./config/vpnc.nix
   ./config/unix-odbc-drivers.nix
   ./config/users-groups.nix
   ./config/zram.nix
@@ -43,6 +46,7 @@
   ./misc/ids.nix
   ./misc/lib.nix
   ./misc/locate.nix
+  ./misc/meta.nix
   ./misc/nixpkgs.nix
   ./misc/passthru.nix
   ./misc/version.nix
@@ -59,8 +63,10 @@
   ./programs/shell.nix
   ./programs/ssh.nix
   ./programs/ssmtp.nix
+  ./programs/uim.nix
   ./programs/venus.nix
   ./programs/wvdial.nix
+  ./programs/freetds.nix
   ./programs/zsh/zsh.nix
   ./rename.nix
   ./security/apparmor.nix
@@ -100,6 +106,7 @@
   ./services/databases/monetdb.nix
   ./services/databases/mongodb.nix
   ./services/databases/mysql.nix
+  ./services/databases/neo4j.nix 
   ./services/databases/openldap.nix
   ./services/databases/postgresql.nix
   ./services/databases/redis.nix
@@ -142,6 +149,7 @@
   ./services/mail/dovecot.nix
   ./services/mail/freepops.nix
   ./services/mail/mail.nix
+  ./services/mail/mlmmj.nix
   ./services/mail/opensmtpd.nix
   ./services/mail/postfix.nix
   ./services/mail/spamassassin.nix
@@ -153,20 +161,28 @@
   ./services/misc/folding-at-home.nix
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
+  ./services/misc/mesos-master.nix
+  ./services/misc/mesos-slave.nix
   ./services/misc/nix-daemon.nix
   ./services/misc/nix-gc.nix
   ./services/misc/nixos-manual.nix
   ./services/misc/nix-ssh-serve.nix
+  ./services/misc/phd.nix
   ./services/misc/rippled.nix
   ./services/misc/rogue.nix
+  ./services/misc/siproxd.nix
   ./services/misc/svnserve.nix
   ./services/misc/synergy.nix
+  ./services/misc/uhub.nix
+  ./services/misc/zookeeper.nix
   ./services/monitoring/apcupsd.nix
   ./services/monitoring/dd-agent.nix
   ./services/monitoring/graphite.nix
   ./services/monitoring/monit.nix
   ./services/monitoring/munin.nix
   ./services/monitoring/nagios.nix
+  ./services/monitoring/riemann.nix
+  ./services/monitoring/riemann-dash.nix
   ./services/monitoring/smartd.nix
   ./services/monitoring/statsd.nix
   ./services/monitoring/systemhealth.nix
@@ -179,7 +195,10 @@
   ./services/network-filesystems/openafs-client/default.nix
   ./services/network-filesystems/rsyncd.nix
   ./services/network-filesystems/samba.nix
+  ./services/network-filesystems/diod.nix
+  ./services/network-filesystems/yandex-disk.nix
   ./services/networking/amuled.nix
+  ./services/networking/atftpd.nix
   ./services/networking/avahi-daemon.nix
   ./services/networking/bind.nix
   ./services/networking/bitlbee.nix
@@ -217,6 +236,7 @@
   ./services/networking/ntpd.nix
   ./services/networking/oidentd.nix
   ./services/networking/openfire.nix
+  ./services/networking/openntpd.nix
   ./services/networking/openvpn.nix
   ./services/networking/polipo.nix
   ./services/networking/prayer.nix
@@ -252,6 +272,7 @@
   ./services/search/elasticsearch.nix
   ./services/search/solr.nix
   ./services/security/clamav.nix
+  ./services/security/fail2ban.nix
   ./services/security/fprot.nix
   ./services/security/frandom.nix
   ./services/security/haveged.nix
@@ -293,6 +314,7 @@
   ./services/x11/window-managers/awesome.nix
   #./services/x11/window-managers/compiz.nix
   ./services/x11/window-managers/default.nix
+  ./services/x11/window-managers/fluxbox.nix
   ./services/x11/window-managers/icewm.nix
   ./services/x11/window-managers/bspwm.nix
   ./services/x11/window-managers/metacity.nix
@@ -348,6 +370,7 @@
   ./virtualisation/docker.nix
   ./virtualisation/libvirtd.nix
   #./virtualisation/nova.nix
+  ./virtualisation/openvswitch.nix
   ./virtualisation/virtualbox-guest.nix
   #./virtualisation/xen-dom0.nix
 ]
diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix
index 511c118e2bf..6385ee69500 100644
--- a/nixos/modules/profiles/all-hardware.nix
+++ b/nixos/modules/profiles/all-hardware.nix
@@ -8,7 +8,7 @@
 {
 
   # The initrd has to contain any module that might be necessary for
-  # mounting the CD/DVD.
+  # supporting the most important parts of HW like drives.
   boot.initrd.availableKernelModules =
     [ # SATA/PATA support.
       "ahci"
@@ -43,7 +43,7 @@
       "virtio_net" "virtio_pci" "virtio_blk" "virtio_balloon" "virtio_console"
 
       # Keyboards
-      "hid_apple"
+      "usbhid" "hid_apple" "hid_logitech_dj" "hid_lenovo_tpkbd" "hid_roccat"
     ];
 
   # Include lots of firmware.
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index e7bde81fb23..6bf98442013 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -51,7 +51,7 @@ in
         STRIGI_PLUGIN_PATH = [ "${i}/lib/strigi/" ];
         QT_PLUGIN_PATH = [ "${i}/lib/qt4/plugins" "${i}/lib/kde4/plugins" ];
         QTWEBKIT_PLUGIN_PATH = [ "${i}/lib/mozilla/plugins/" ];
-        GTK_PATH = [ "${i}/lib/gtk-2.0" ];
+        GTK_PATH = [ "${i}/lib/gtk-2.0" "${i}/lib/gtk-3.0" ];
         XDG_CONFIG_DIRS = [ "${i}/etc/xdg" ];
         XDG_DATA_DIRS = [ "${i}/share" ];
         MOZ_PLUGIN_PATH = [ "${i}/lib/mozilla/plugins" ];
diff --git a/nixos/modules/programs/freetds.nix b/nixos/modules/programs/freetds.nix
new file mode 100644
index 00000000000..398fd104363
--- /dev/null
+++ b/nixos/modules/programs/freetds.nix
@@ -0,0 +1,61 @@
+# Global configuration for freetds environment.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.environment.freetds;
+
+in
+{
+  ###### interface
+
+  options = {
+
+    environment.freetds = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = {
+        MYDATABASE = 
+          ''
+          host = 10.0.2.100
+          port = 1433
+          tds version = 7.2
+          '';
+      };
+      description = 
+        ''
+        Configure freetds database entries. Each attribute denotes
+        a section within freetds.conf, and the value (a string) is the config
+        content for that section. When at least one entry is configured
+        the global environment variables FREETDSCONF, FREETDS and SYBASE
+        will be configured to allow the programs that use freetds to find the
+        library and config.
+        '';
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf (length (attrNames cfg) > 0) {
+
+    environment.variables.FREETDSCONF = "/etc/freetds.conf";
+    environment.variables.FREETDS = "/etc/freetds.conf";
+    environment.variables.SYBASE = "${pkgs.freetds}";
+
+    environment.etc."freetds.conf" = { text = 
+      (concatStrings (mapAttrsToList (name: value:
+        ''
+        [${name}]
+        ${value}
+        ''
+      ) cfg));
+    };
+
+  };
+
+}
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 658b08b3d87..5c2ea07c554 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -83,7 +83,7 @@ in
     security.pam.services =
       { chsh = { rootOK = true; };
         chfn = { rootOK = true; };
-        su = { rootOK = true; forwardXAuth = true; };
+        su = { rootOK = true; forwardXAuth = true; logFailures = true; };
         passwd = {};
         # Note: useradd, groupadd etc. aren't setuid root, so it
         # doesn't really matter what the PAM config says as long as it
@@ -100,7 +100,9 @@ in
         chgpasswd = { rootOK = true; };
       };
 
-    security.setuidPrograms = [ "passwd" "chfn" "su" "newgrp" ];
+    security.setuidPrograms = [ "passwd" "chfn" "su" "newgrp"
+      "newuidmap" "newgidmap"  # new in shadow 4.2.x
+      ];
 
   };
 
diff --git a/nixos/modules/programs/uim.nix b/nixos/modules/programs/uim.nix
new file mode 100644
index 00000000000..237da3415dc
--- /dev/null
+++ b/nixos/modules/programs/uim.nix
@@ -0,0 +1,29 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+  cfg = config.uim;
+in
+{
+  options = {
+    uim = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        example = true;
+        description = "enable UIM input method";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.uim ];
+    gtkPlugins = [ pkgs.uim ];
+    qtPlugins = [ pkgs.uim ];
+    environment.variables.GTK_IM_MODULE = "uim";
+    environment.variables.QT_IM_MODULE = "uim";
+    environment.variables.XMODIFIERS = "@im=uim";
+    services.xserver.displayManager.sessionCommands = "uim-xim &";
+  };
+}
diff --git a/nixos/modules/programs/virtualbox.nix b/nixos/modules/programs/virtualbox.nix
index e2dd76219eb..fec1a7b61f3 100644
--- a/nixos/modules/programs/virtualbox.nix
+++ b/nixos/modules/programs/virtualbox.nix
@@ -44,5 +44,5 @@ let virtualbox = config.boot.kernelPackages.virtualbox; in
         '';
     };
 
-  networking.interfaces.vboxnet0 = { ipAddress = "192.168.56.1"; prefixLength = 24; };
+  networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ];
 }
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index b1b75a0068d..844a9da0eb4 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -126,12 +126,28 @@ let
         description = "Whether to show the message of the day.";
       };
 
+      makeHomeDir = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to try to create home directories for users
+          with <literal>$HOME</literal>s pointing to nonexistent
+          locations on session login.
+        '';
+      };
+
       updateWtmp = mkOption {
         default = false;
         type = types.bool;
         description = "Whether to update <filename>/var/log/wtmp</filename>.";
       };
 
+      logFailures = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Whether to log authentication failures in <filename>/var/log/faillog</filename>.";
+      };
+
       text = mkOption {
         type = types.nullOr types.lines;
         description = "Contents of the PAM service file.";
@@ -159,6 +175,8 @@ let
           # Authentication management.
           ${optionalString cfg.rootOK
               "auth sufficient pam_rootok.so"}
+          ${optionalString cfg.logFailures
+              "auth required pam_tally.so"}
           ${optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth)
               "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"}
           ${optionalString cfg.usbAuth
@@ -192,6 +210,8 @@ let
               "session ${
                 if config.boot.isContainer then "optional" else "required"
               } pam_loginuid.so"}
+          ${optionalString cfg.makeHomeDir
+              "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022"}
           ${optionalString cfg.updateWtmp
               "session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
           ${optionalString config.users.ldap.enable
diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix
index 373afffd3fb..22dbdf6a6bf 100644
--- a/nixos/modules/security/setuid-wrappers.nix
+++ b/nixos/modules/security/setuid-wrappers.nix
@@ -77,7 +77,9 @@ in
   config = {
 
     security.setuidPrograms =
-      [ "fusermount" "wodim" "cdrdao" "growisofs" ];
+      [ "mount.nfs" "mount.nfs4" "mount.cifs"
+        "fusermount" "umount"
+        "wodim" "cdrdao" "growisofs" ];
 
     system.activationScripts.setuid =
       let
diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix
index 5b865cf4c1b..a7a7e8ae688 100644
--- a/nixos/modules/services/audio/mopidy.nix
+++ b/nixos/modules/services/audio/mopidy.nix
@@ -49,7 +49,7 @@ in {
       extensionPackages = mkOption {
         default = [];
         type = types.listOf types.package;
-        example = [ mopidy-spotify ];
+        example = literalExample "[ pkgs.mopidy-spotify ]";
         description = ''
           Mopidy extensions that should be loaded by the service.
         '';
diff --git a/nixos/modules/services/backup/rsnapshot.nix b/nixos/modules/services/backup/rsnapshot.nix
index 48ad7582b7e..091b5cfd4d5 100644
--- a/nixos/modules/services/backup/rsnapshot.nix
+++ b/nixos/modules/services/backup/rsnapshot.nix
@@ -31,7 +31,7 @@ in
 
       cronIntervals = mkOption {
         default = {};
-        example = { "hourly" = "0 * * * *"; "daily" = "50 21 * * *"; };
+        example = { hourly = "0 * * * *"; daily = "50 21 * * *"; };
         type = types.attrsOf types.string;
         description = ''
           Periodicity at which intervals should be run by cron.
diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
new file mode 100644
index 00000000000..2ef49a95166
--- /dev/null
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -0,0 +1,143 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.neo4j;
+
+  serverConfig = pkgs.writeText "neo4j-server.properties" ''
+    org.neo4j.server.database.location=${cfg.dataDir}/data/graph.db
+    org.neo4j.server.webserver.address=${cfg.host}
+    org.neo4j.server.webserver.port=${toString cfg.port}
+    ${optionalString cfg.enableHttps ''
+      org.neo4j.server.webserver.https.enabled=true
+      org.neo4j.server.webserver.https.port=${toString cfg.httpsPort}
+      org.neo4j.server.webserver.https.cert.location=${cfg.cert}
+      org.neo4j.server.webserver.https.key.location=${cfg.key}
+      org.neo4j.server.webserver.https.keystore.location=${cfg.dataDir}/data/keystore
+    ''}
+    org.neo4j.server.webadmin.rrdb.location=${cfg.dataDir}/data/rrd
+    org.neo4j.server.webadmin.data.uri=/db/data/
+    org.neo4j.server.webadmin.management.uri=/db/manage/
+    org.neo4j.server.db.tuning.properties=${pkgs.neo4j}/share/neo4j/conf/neo4j.properties
+    org.neo4j.server.manage.console_engines=shell
+    ${cfg.extraServerConfig}
+  '';
+
+  loggingConfig = pkgs.writeText "logging.properties" cfg.loggingConfig;
+
+  wrapperConfig = pkgs.writeText "neo4j-wrapper.conf" ''
+    wrapper.java.additional=-Dorg.neo4j.server.properties=${serverConfig}
+    wrapper.java.additional=-Djava.util.logging.config.file=${loggingConfig}
+    wrapper.java.additional=-XX:+UseConcMarkSweepGC
+    wrapper.java.additional=-XX:+CMSClassUnloadingEnabled
+    wrapper.pidfile=${cfg.dataDir}/neo4j-server.pid
+    wrapper.name=neo4j
+  '';
+
+in {
+
+  ###### interface
+
+  options.services.neo4j = {
+    enable = mkOption {
+      description = "Whether to enable neo4j.";
+      default = false;
+      type = types.uniq types.bool;
+    };
+
+    host = mkOption {
+      description = "Neo4j listen address.";
+      default = "127.0.0.1";
+      type = types.str;
+    };
+
+    port = mkOption {
+      description = "Neo4j port to listen for HTTP traffic.";
+      default = 7474;
+      type = types.int;
+    };
+
+    enableHttps = mkOption {
+      description = "Enable https for Neo4j.";
+      default = false;
+      type = types.bool;
+    };
+
+    httpsPort = mkOption {
+      description = "Neo4j port to listen for HTTPS traffic.";
+      default = 7473;
+      type = types.int;
+    };
+
+    cert = mkOption {
+      description = "Neo4j https certificate.";
+      default = "${cfg.dataDir}/conf/ssl/neo4j.cert";
+      type = types.path;
+    };
+
+    key = mkOption {
+      description = "Neo4j https certificate key.";
+      default = "${cfg.dataDir}/conf/ssl/neo4j.key";
+      type = types.path;
+    };
+
+    dataDir = mkOption {
+      description = "Neo4j data directory.";
+      default = "/var/lib/neo4j";
+      type = types.path;
+    };
+
+    loggingConfig = mkOption {
+      description = "Neo4j logging configuration.";
+      default = ''
+        handlers=java.util.logging.ConsoleHandler
+        .level=INFO
+        org.neo4j.server.level=INFO
+
+        java.util.logging.ConsoleHandler.level=INFO
+        java.util.logging.ConsoleHandler.formatter=org.neo4j.server.logging.SimpleConsoleFormatter
+        java.util.logging.ConsoleHandler.filter=org.neo4j.server.logging.NeoLogFilter
+      '';
+      type = types.lines;
+    };
+
+    extraServerConfig = mkOption {
+      description = "Extra configuration for neo4j server.";
+      default = "";
+      type = types.lines;
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    systemd.services.neo4j = {
+      description = "Neo4j Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      environment = { NEO4J_INSTANCE = cfg.dataDir; };
+      serviceConfig = {
+        ExecStart = "${pkgs.neo4j}/bin/neo4j console";
+        User = "neo4j";
+        PermissionsStartOnly = true;
+      };
+      preStart = ''
+        mkdir -m 0700 -p ${cfg.dataDir}/{data/graph.db,conf}
+        ln -fs ${wrapperConfig} ${cfg.dataDir}/conf/neo4j-wrapper.conf
+        if [ "$(id -u)" = 0 ]; then chown -R neo4j ${cfg.dataDir}; fi
+      '';
+    };
+
+    environment.systemPackages = [ pkgs.neo4j ];
+
+    users.extraUsers = singleton {
+      name = "neo4j";
+      uid = config.ids.uids.neo4j;
+      description = "Neo4j daemon user";
+      home = cfg.dataDir;
+    };
+  };
+
+}
diff --git a/nixos/modules/services/databases/postgresql.xml b/nixos/modules/services/databases/postgresql.xml
new file mode 100644
index 00000000000..e98b431bd60
--- /dev/null
+++ b/nixos/modules/services/databases/postgresql.xml
@@ -0,0 +1,77 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-postgresql">
+
+<title>PostgreSQL</title>
+
+<!-- FIXME: render nicely -->
+
+<!-- FIXME: source can be added automatically -->
+<para><emphasis>Source:</emphasis> <filename>modules/services/databases/postgresql.nix</filename></para>
+
+<para><emphasis>Upstream documentation:</emphasis> <link xlink:href="http://www.postgresql.org/docs/"/></para>
+
+<!-- FIXME: more stuff, like maintainer? -->
+
+<para>PostgreSQL is an advanced, free relational database.<!-- MORE --></para>
+
+<section><title>Configuring</title>
+
+<para>To enable PostgreSQL, add the following to your
+<filename>configuration.nix</filename>:
+
+<programlisting>
+services.postgresql.enable = true;
+services.postgresql.package = pkgs.postgresql93;
+</programlisting>
+
+Note that you are required to specify the desired version of
+PostgreSQL (e.g. <literal>pkgs.postgresql93</literal>). Since
+upgrading your PostgreSQL version requires a database dump and reload
+(see below), NixOS cannot provide a default value for
+<option>services.postgresql.package</option> such as the most recent
+release of PostgreSQL.</para>
+
+<!--
+<para>After running <command>nixos-rebuild</command>, you can verify
+whether PostgreSQL works by running <command>psql</command>:
+
+<screen>
+$ psql
+psql (9.2.9)
+Type "help" for help.
+
+alice=>
+</screen>
+-->
+
+<para>By default, PostgreSQL stores its databases in
+<filename>/var/db/postgresql</filename>. You can override this using
+<option>services.postgresql.dataDir</option>, e.g.
+
+<programlisting>
+services.postgresql.dataDir = "/data/postgresql";
+</programlisting>
+
+</para>
+
+</section>
+
+
+<section><title>Upgrading</title>
+
+<para>FIXME: document dump/upgrade/load cycle.</para>
+
+</section>
+
+
+<section><title>Options</title>
+
+<para>FIXME: auto-generated list of module options.</para>
+
+</section>
+
+
+</chapter>
diff --git a/nixos/modules/services/hardware/tcsd.nix b/nixos/modules/services/hardware/tcsd.nix
index 26b2c884b8f..d7f6c188feb 100644
--- a/nixos/modules/services/hardware/tcsd.nix
+++ b/nixos/modules/services/hardware/tcsd.nix
@@ -1,8 +1,8 @@
 # tcsd daemon.
 
-{ config, pkgs, ... }:
+{ config, pkgs, lib, ... }:
 
-with pkgs.lib;
+with lib;
 let
 
   cfg = config.services.tcsd;
diff --git a/nixos/modules/services/hardware/thermald.nix b/nixos/modules/services/hardware/thermald.nix
new file mode 100644
index 00000000000..5233794a20c
--- /dev/null
+++ b/nixos/modules/services/hardware/thermald.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.thermald;
+in {
+  ###### interface
+  options = { 
+    services.thermald = { 
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to enable thermald, the temperature management daemon.
+        ''; 
+      };  
+    };  
+  };  
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    systemd.services.thermald = {
+      description = "Thermal Daemon Service";
+      wantedBy = [ "multi-user.target" ];
+      script = "exec ${pkgs.thermald}/sbin/thermald --no-daemon --dbus-enable";
+    };
+  };
+}
diff --git a/nixos/modules/services/logging/syslog-ng.nix b/nixos/modules/services/logging/syslog-ng.nix
index 8b892a33bb7..0b3f0cabb00 100644
--- a/nixos/modules/services/logging/syslog-ng.nix
+++ b/nixos/modules/services/logging/syslog-ng.nix
@@ -49,7 +49,9 @@ in {
       extraModulePaths = mkOption {
         type = types.listOf types.str;
         default = [];
-        example = [ "${pkgs.syslogng_incubator}/lib/syslog-ng" ];
+        example = literalExample ''
+          [ "''${pkgs.syslogng_incubator}/lib/syslog-ng" ]
+        '';
         description = ''
           A list of paths that should be included in syslog-ng's
           <literal>--module-path</literal> option. They should usually
diff --git a/nixos/modules/services/mail/mlmmj.nix b/nixos/modules/services/mail/mlmmj.nix
new file mode 100644
index 00000000000..637974f05cd
--- /dev/null
+++ b/nixos/modules/services/mail/mlmmj.nix
@@ -0,0 +1,128 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.mlmmj;
+  stateDir = "/var/lib/mlmmj";
+  spoolDir = "/var/spool/mlmmj";
+  listDir = domain: list: "${spoolDir}/${domain}/${list}";
+  listCtl = domain: list: "${listDir domain list}/control";
+  transport = domain: list: "${domain}--${list}@local.list.mlmmj mlmmj:${domain}/${list}";
+  virtual = domain: list: "${list}@${domain} ${domain}--${list}@local.list.mlmmj";
+  alias = domain: list: "${list}: \"|${pkgs.mlmmj}/mlmmj-receive -L ${listDir domain list}/\"";
+  subjectPrefix = list: "[${list}]";
+  listAddress = domain: list: "${list}@${domain}";
+  customHeaders = list: domain: [ "List-Id: ${list}" "Reply-To: ${list}@${domain}" ];
+  footer = domain: list: "To unsubscribe send a mail to ${list}+unsubscribe@${domain}";
+  createList = d: l: ''
+    ${pkgs.coreutils}/bin/mkdir -p ${listCtl d l}
+    echo ${listAddress d l} > ${listCtl d l}/listadress
+    echo "${lib.concatStringsSep "\n" (customHeaders d l)}" > ${listCtl d l}/customheaders
+    echo ${footer d l} > ${listCtl d l}/footer
+    echo ${subjectPrefix l} > ${listCtl d l}/prefix
+  '';
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.mlmmj = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable mlmmj";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "mlmmj";
+        description = "mailinglist local user";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "mlmmj";
+        description = "mailinglist local group";
+      };
+
+      listDomain = mkOption {
+        type = types.str;
+        default = "localhost";
+        description = "Set the mailing list domain";
+      };
+
+      mailLists = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = "The collection of hosted maillists";
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = singleton {
+      name = cfg.user;
+      description = "mlmmj user";
+      home = stateDir;
+      createHome = true;
+      uid = config.ids.uids.mlmmj;
+      group = cfg.group;
+      useDefaultShell = true;
+    };
+
+    users.extraGroups = singleton {
+      name = cfg.group;
+      gid = config.ids.gids.mlmmj;
+    };
+
+    services.postfix = {
+      enable = true;
+      recipientDelimiter= "+";
+      extraMasterConf = ''
+        mlmmj unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj}/bin/mlmmj-recieve -F -L ${spoolDir}/$nextHop
+      '';
+
+      extraAliases = concatMapStrings (alias cfg.listDomain) cfg.mailLists;
+
+      extraConfig = ''
+        transport = hash:${stateDir}/transports
+        virtual = hash:${stateDir}/virtuals
+      '';
+    };
+
+    environment.systemPackages = [ pkgs.mlmmj ];
+
+    system.activationScripts.mlmmj = ''
+          ${pkgs.coreutils}/bin/mkdir -p ${stateDir} ${spoolDir}/${cfg.listDomain}
+          ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${spoolDir}
+          ${lib.concatMapStrings (createList cfg.listDomain) cfg.mailLists}
+          echo ${lib.concatMapStrings (virtual cfg.listDomain) cfg.mailLists} > ${stateDir}/virtuals
+          echo ${cfg.listDomain} mailman: > ${stateDir}/transports
+          echo ${lib.concatMapStrings (transport cfg.listDomain) cfg.mailLists} >> ${stateDir}/transports
+    '';
+
+    systemd.services."mlmmj-maintd" = {
+      description = "mlmmj maintenance daemon";
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        ExecStart = "${pkgs.mlmmj}/bin/mlmmj-maintd -F -d ${spoolDir}/${cfg.listDomain}";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/mesos-master.nix b/nixos/modules/services/misc/mesos-master.nix
new file mode 100644
index 00000000000..bdf88d427c5
--- /dev/null
+++ b/nixos/modules/services/misc/mesos-master.nix
@@ -0,0 +1,103 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mesos.master;
+  
+in {
+
+  options.services.mesos = {
+    
+    master = {
+      enable = mkOption {
+        description = "Whether to enable the Mesos Master.";
+        default = false;
+        type = types.uniq types.bool;
+      };
+
+      port = mkOption {
+        description = "Mesos Master port";
+        default = 5050;
+        type = types.int;
+      };
+
+      zk = mkOption {
+        description = ''
+          ZooKeeper URL (used for leader election amongst masters).
+          May be one of:
+            zk://host1:port1,host2:port2,.../mesos
+            zk://username:password@host1:port1,host2:port2,.../mesos
+        '';
+        type = types.str;
+      };
+      
+      workDir = mkOption {
+        description = "The Mesos work directory.";
+        default = "/var/lib/mesos/master";
+        type = types.str;
+      };
+      
+      extraCmdLineOptions = mkOption {
+        description = ''
+	  Extra command line options for Mesos Master.
+	  
+	  See https://mesos.apache.org/documentation/latest/configuration/
+	'';
+        default = [ "" ];
+        type = types.listOf types.string;
+        example = [ "--credentials=VALUE" ];
+      };
+      
+      quorum = mkOption {
+        description = ''
+          The size of the quorum of replicas when using 'replicated_log' based
+          registry. It is imperative to set this value to be a majority of
+          masters i.e., quorum > (number of masters)/2.
+          
+          If 0 will fall back to --registry=in_memory.
+        '';
+        default = 0;
+        type = types.int;
+      };
+      
+      logLevel = mkOption {
+        description = ''
+          The logging level used. Possible values:
+            'INFO', 'WARNING', 'ERROR'
+        '';
+        default = "INFO";
+        type = types.str;
+      };
+
+    };
+
+
+  };
+
+
+  config = mkIf cfg.enable {
+    systemd.services.mesos-master = {
+      description = "Mesos Master";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      serviceConfig = {
+	ExecStart = ''
+	  ${pkgs.mesos}/bin/mesos-master \
+	    --port=${toString cfg.port} \
+	    --zk=${cfg.zk} \
+	    ${if cfg.quorum == 0 then "--registry=in_memory" else "--registry=replicated_log --quorum=${cfg.quorum}"} \
+	    --work_dir=${cfg.workDir} \
+	    --logging_level=${cfg.logLevel} \
+	    ${toString cfg.extraCmdLineOptions}
+	'';
+	PermissionsStartOnly = true;
+      };
+      preStart = ''
+	mkdir -m 0700 -p ${cfg.workDir}
+      '';
+    };
+  };
+  
+}
+
diff --git a/nixos/modules/services/misc/mesos-slave.nix b/nixos/modules/services/misc/mesos-slave.nix
new file mode 100644
index 00000000000..e9a89816716
--- /dev/null
+++ b/nixos/modules/services/misc/mesos-slave.nix
@@ -0,0 +1,93 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mesos.slave;
+  
+in {
+
+  options.services.mesos = {
+    slave = {
+      enable = mkOption {
+        description = "Whether to enable the Mesos Slave.";
+        default = false;
+        type = types.uniq types.bool;
+      };
+
+      port = mkOption {
+        description = "Mesos Slave port";
+        default = 5051;
+        type = types.int;
+      };
+
+      master = mkOption {
+        description = ''
+          May be one of:
+            zk://host1:port1,host2:port2,.../path
+            zk://username:password@host1:port1,host2:port2,.../path
+        '';
+        type = types.str;
+      };
+      
+      withHadoop = mkOption {
+	description = "Add the HADOOP_HOME to the slave.";
+	default = false;
+	type = types.bool;
+      };
+      
+      workDir = mkOption {
+        description = "The Mesos work directory.";
+        default = "/var/lib/mesos/slave";
+        type = types.str;
+      };
+      
+      extraCmdLineOptions = mkOption {
+        description = ''
+	  Extra command line options for Mesos Slave.
+	  
+	  See https://mesos.apache.org/documentation/latest/configuration/
+	'';
+        default = [ "" ];
+        type = types.listOf types.string;
+        example = [ "--gc_delay=3days" ];
+      };
+      
+      logLevel = mkOption {
+        description = ''
+          The logging level used. Possible values:
+            'INFO', 'WARNING', 'ERROR'
+        '';
+        default = "INFO";
+        type = types.str;
+      };
+
+    };
+
+  };
+
+
+  config = mkIf cfg.enable {
+    systemd.services.mesos-slave = {
+      description = "Mesos Slave";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      serviceConfig = {
+	ExecStart = ''
+	  ${pkgs.mesos}/bin/mesos-slave \
+	    --port=${toString cfg.port} \
+	    --master=${cfg.master} \
+	    ${optionalString cfg.withHadoop "--hadoop-home=${pkgs.hadoop}"} \
+	    --work_dir=${cfg.workDir} \
+	    --logging_level=${cfg.logLevel} \
+	    ${toString cfg.extraCmdLineOptions}
+	'';
+	PermissionsStartOnly = true;
+      };
+      preStart = ''
+	mkdir -m 0700 -p ${cfg.workDir}
+      '';
+    };
+  };
+  
+}
\ No newline at end of file
diff --git a/nixos/modules/services/misc/nixos-manual.nix b/nixos/modules/services/misc/nixos-manual.nix
index 808c5dcbdc6..c0d7885280a 100644
--- a/nixos/modules/services/misc/nixos-manual.nix
+++ b/nixos/modules/services/misc/nixos-manual.nix
@@ -28,7 +28,7 @@ let
     options = eval.options;
   };
 
-  entry = "${manual.manual}/share/doc/nixos/manual.html";
+  entry = "${manual.manual}/share/doc/nixos/index.html";
 
   help = pkgs.writeScriptBin "nixos-help"
     ''
diff --git a/nixos/modules/services/misc/phd.nix b/nixos/modules/services/misc/phd.nix
new file mode 100644
index 00000000000..e605ce5de16
--- /dev/null
+++ b/nixos/modules/services/misc/phd.nix
@@ -0,0 +1,52 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.phd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.phd = {
+
+      enable = mkOption {
+        default = false;
+        description = "
+          Enable daemons for phabricator.
+        ";
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.phd = {
+      path = [ pkgs.phabricator pkgs.php pkgs.mercurial pkgs.git pkgs.subversion ];
+
+      after = [ "httpd.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.phabricator}/phabricator/bin/phd start";
+        ExecStop = "${pkgs.phabricator}/phabricator/bin/phd stop";
+        User = "wwwrun";
+        RestartSec = "30s";
+        Restart = "always";
+        StartLimitInterval = "1m";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/siproxd.nix b/nixos/modules/services/misc/siproxd.nix
new file mode 100644
index 00000000000..9e8fb6c228f
--- /dev/null
+++ b/nixos/modules/services/misc/siproxd.nix
@@ -0,0 +1,180 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.siproxd;
+
+  conf = ''
+    daemonize = 0
+    rtp_proxy_enable = 1
+    user = siproxd
+    if_inbound  = ${cfg.ifInbound}
+    if_outbound = ${cfg.ifOutbound}
+    sip_listen_port = ${toString cfg.sipListenPort}
+    rtp_port_low    = ${toString cfg.rtpPortLow}
+    rtp_port_high   = ${toString cfg.rtpPortHigh}
+    rtp_dscp        = ${toString cfg.rtpDscp}
+    sip_dscp        = ${toString cfg.sipDscp}
+    ${optionalString (cfg.hostsAllowReg != []) "hosts_allow_reg = ${concatStringsSep "," cfg.hostsAllowReg}"}
+    ${optionalString (cfg.hostsAllowSip != []) "hosts_allow_sip = ${concatStringsSep "," cfg.hostsAllowSip}"}
+    ${optionalString (cfg.hostsDenySip != []) "hosts_deny_sip  = ${concatStringsSep "," cfg.hostsDenySip}"}
+    ${if (cfg.passwordFile != "") then "proxy_auth_pwfile = ${cfg.passwordFile}" else ""}
+    ${cfg.extraConfig}
+  '';
+
+  confFile = builtins.toFile "siproxd.conf" conf;
+
+in
+{
+  ##### interface
+
+  options = {
+
+    services.siproxd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable the Siproxd SIP 
+	  proxy/masquerading daemon.
+        '';
+      };
+
+      ifInbound = mkOption {
+        type = types.str;
+        example = "eth0";
+        description = "Local network interface";
+      };
+
+      ifOutbound = mkOption {
+        type = types.str;
+        example = "ppp0";
+        description = "Public network interface";
+      };
+
+      hostsAllowReg = mkOption {
+        type = types.listOf types.str;
+	default = [ ];
+        example = [ "192.168.1.0/24" "192.168.2.0/24" ];
+	description = ''
+          Acess control list for incoming SIP registrations.
+        '';
+      };
+
+      hostsAllowSip = mkOption {
+        type = types.listOf types.str;
+	default = [ ];
+        example = [ "123.45.0.0/16" "123.46.0.0/16" ];
+	description = ''
+          Acess control list for incoming SIP traffic.
+        '';
+      };
+
+      hostsDenySip = mkOption {
+        type = types.listOf types.str;
+	default = [ ];
+        example = [ "10.0.0.0/8" "11.0.0.0/8" ];
+	description = ''
+          Acess control list for denying incoming
+	   SIP registrations and traffic.
+        '';
+      };
+
+      sipListenPort = mkOption {
+        type = types.int;
+        default = 5060;
+        description = ''
+	  Port to listen for incoming SIP messages.
+        '';
+      };
+
+      rtpPortLow = mkOption {
+        type = types.int;
+        default = 7070;
+        description = ''
+         Bottom of UDP port range for incoming and outgoing RTP traffic
+        '';
+      };
+
+      rtpPortHigh = mkOption {
+        type = types.int;
+        default = 7089;
+        description = ''
+         Top of UDP port range for incoming and outgoing RTP traffic
+        '';
+      };
+
+      rtpTimeout = mkOption {
+        type = types.int;
+        default = 300;
+        description = ''
+          Timeout for an RTP stream. If for the specified 
+          number of seconds no data is relayed on an active
+          stream, it is considered dead and will be killed.
+        '';
+      };
+
+      rtpDscp = mkOption {
+        type = types.int;
+        default = 46;
+        description = ''
+          DSCP (differentiated services) value to be assigned
+          to RTP packets. Allows QOS aware routers to handle 
+          different types traffic with different priorities.
+        '';
+      };
+
+      sipDscp = mkOption {
+        type = types.int;
+        default = 0;
+        description = ''
+          DSCP (differentiated services) value to be assigned
+          to SIP packets. Allows QOS aware routers to handle 
+          different types traffic with different priorities.
+        '';
+      };
+
+      passwordFile = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          Path to per-user password file.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra configuration to add to siproxd configuration.
+        '';
+      };
+
+    };
+
+  };
+
+  ##### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = singleton {
+      name = "siproxyd";
+      uid = config.ids.uids.siproxd;
+    };
+
+    systemd.services.siproxd = {
+      description = "SIP proxy/masquerading daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.siproxd}/sbin/siproxd -c ${confFile}";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/uhub.nix b/nixos/modules/services/misc/uhub.nix
new file mode 100644
index 00000000000..15071202b9c
--- /dev/null
+++ b/nixos/modules/services/misc/uhub.nix
@@ -0,0 +1,186 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.uhub;
+
+  uhubPkg = pkgs.uhub.override { tlsSupport = cfg.enableTLS; };
+
+  pluginConfig = ""
+  + optionalString cfg.plugins.authSqlite.enable ''
+    plugin ${uhubPkg.mod_auth_sqlite}/mod_auth_sqlite.so "file=${cfg.plugins.authSqlite.file}"
+  ''
+  + optionalString cfg.plugins.logging.enable ''
+    plugin ${uhubPkg.mod_logging}/mod_logging.so ${if cfg.plugins.logging.syslog then "syslog=true" else "file=${cfg.plugins.logging.file}"}
+  ''
+  + optionalString cfg.plugins.welcome.enable ''
+    plugin ${uhubPkg.mod_welcome}/mod_welcome.so "motd=${pkgs.writeText "motd.txt"  cfg.plugins.welcome.motd} rules=${pkgs.writeText "rules.txt" cfg.plugins.welcome.rules}"
+  ''
+  + optionalString cfg.plugins.history.enable ''
+    plugin ${uhubPkg.mod_chat_history}/mod_chat_history.so "history_max=${toString cfg.plugins.history.max} history_default=${toString cfg.plugins.history.default} history_connect=${toString cfg.plugins.history.connect}"
+  '';
+
+  uhubConfigFile = pkgs.writeText "uhub.conf" ''
+    file_acl=${pkgs.writeText "users.conf" cfg.aclConfig}
+    file_plugins=${pkgs.writeText "plugins.conf" pluginConfig}
+    server_bind_addr=${cfg.address}
+    server_port=${toString cfg.port}
+    ${lib.optionalString cfg.enableTLS "tls_enable=yes"}
+    ${cfg.hubConfig}
+  '';
+
+in
+
+{
+  options = {
+
+    services.uhub = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+	description = "Whether to enable the uhub ADC hub.";
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 1511;
+	description = "TCP port to bind the hub to.";
+      };
+
+      address = mkOption {
+        type = types.string;
+        default = "any";
+	description = "Address to bind the hub to.";
+      };
+
+      enableTLS = mkOption {
+        type = types.bool;
+        default = false;
+	description = "Whether to enable TLS support.";
+      };
+
+      hubConfig = mkOption {
+        type = types.lines;
+        default = "";
+	description = "Contents of uhub configuration file.";
+      };
+
+      aclConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Contents of user ACL configuration file.";
+      };
+
+      plugins = {
+
+        authSqlite = {
+	  enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Whether to enable the Sqlite authentication database plugin";
+	  };
+          file = mkOption {
+            type = types.string;
+            example = "/var/db/uhub-users";
+            description = "Path to user database. Use the uhub-passwd utility to create the database and add/remove users.";
+          };
+        };
+
+        logging = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Whether to enable the logging plugin.";
+          };
+          file = mkOption {
+            type = types.string;
+            default = "";
+            description = "Path of log file.";
+          };
+          syslog = mkOption {
+            type = types.bool;
+            default = false;
+            description = "If true then the system log is used instead of writing to file.";
+          };
+        };
+
+        welcome = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Whether to enable the welcome plugin.";
+          };
+          motd = mkOption {
+            default = "";
+            type = types.lines;
+            description = ''
+              Welcome message displayed to clients after connecting 
+              and with the <literal>!motd</literal> command.
+            '';
+          };
+          rules = mkOption {
+            default = "";
+            type = types.lines;
+            description = ''
+              Rules message, displayed to clients with the <literal>!rules</literal> command.
+            '';
+          };
+        };
+
+        history = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Whether to enable the history plugin.";
+          };
+          max = mkOption {
+            type = types.int;
+            default = 200;
+            description = "The maximum number of messages to keep in history";
+          };
+          default = mkOption {
+            type = types.int;
+            default = 10;
+            description = "When !history is provided without arguments, then this default number of messages are returned.";
+          };
+          connect = mkOption {
+            type = types.int;
+            default = 5;
+            description = "The number of chat history messages to send when users connect (0 = do not send any history).";
+          };
+        };
+
+      };
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    users = {
+      extraUsers = singleton {
+        name = "uhub";
+        uid = config.ids.uids.uhub;
+      };
+      extraGroups = singleton {
+        name = "uhub";
+        gid = config.ids.gids.uhub;
+      };
+    };
+
+    systemd.services.uhub = {
+      description = "high performance peer-to-peer hub for the ADC network";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type = "notify";
+        ExecStart  = "${uhubPkg}/bin/uhub -c ${uhubConfigFile} -u uhub -g uhub -L";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+    };
+  };
+
+}
\ No newline at end of file
diff --git a/nixos/modules/services/misc/zookeeper.nix b/nixos/modules/services/misc/zookeeper.nix
new file mode 100755
index 00000000000..47675b8876c
--- /dev/null
+++ b/nixos/modules/services/misc/zookeeper.nix
@@ -0,0 +1,145 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.zookeeper;
+  
+  zookeeperConfig = ''
+    dataDir=${cfg.dataDir}
+    clientPort=${toString cfg.port}
+    autopurge.purgeInterval=${toString cfg.purgeInterval}
+    ${cfg.extraConf}
+    ${cfg.servers}
+  '';
+
+  configDir = pkgs.buildEnv {
+    name = "zookeeper-conf";
+    paths = [
+      (pkgs.writeTextDir "zoo.cfg" zookeeperConfig)
+      (pkgs.writeTextDir "log4j.properties" cfg.logging)
+    ];
+  };
+
+in {
+
+  options.services.zookeeper = {
+    enable = mkOption {
+      description = "Whether to enable Zookeeper.";
+      default = false;
+      type = types.uniq types.bool;
+    };
+
+    port = mkOption {
+      description = "Zookeeper Client port.";
+      default = 2181;
+      type = types.int;
+    };
+
+    id = mkOption {
+      description = "Zookeeper ID.";
+      default = 0;
+      type = types.int;
+    };
+
+    purgeInterval = mkOption {
+      description = ''
+        The time interval in hours for which the purge task has to be triggered. Set to a positive integer (1 and above) to enable the auto purging.
+      '';
+      default = 1;
+      type = types.int;
+    };
+ 
+    extraConf = mkOption {
+      description = "Extra configuration for Zookeeper.";
+      type = types.lines;
+      default = ''
+        initLimit=5
+        syncLimit=2
+        tickTime=2000
+      '';
+    };
+
+    servers = mkOption {
+      description = "All Zookeeper Servers.";
+      default = "";
+      type = types.lines;
+      example = ''
+        server.0=host0:2888:3888
+        server.1=host1:2888:3888
+        server.2=host2:2888:3888
+      '';
+    };
+
+    logging = mkOption {
+      description = "Zookeeper logging configuration.";
+      default = ''
+        zookeeper.root.logger=INFO, CONSOLE
+        log4j.rootLogger=INFO, CONSOLE
+        log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+        log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+        log4j.appender.CONSOLE.layout.ConversionPattern=[myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
+      '';
+      type = types.lines;
+    };
+
+    dataDir = mkOption {
+      type = types.path;
+      default = "/var/lib/zookeeper";
+      description = ''
+        Data directory for Zookeeper
+      '';
+    };
+
+    extraCmdLineOptions = mkOption {
+      description = "Extra command line options for the Zookeeper launcher.";
+      default = [ "-Dcom.sun.management.jmxremote" "-Dcom.sun.management.jmxremote.local.only=true" ];
+      type = types.listOf types.string;
+      example = [ "-Djava.net.preferIPv4Stack=true" "-Dcom.sun.management.jmxremote" "-Dcom.sun.management.jmxremote.local.only=true" ];
+    };
+
+    preferIPv4 = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Add the -Djava.net.preferIPv4Stack=true flag to the Zookeeper server.
+      '';
+    };
+
+  };
+
+
+  config = mkIf cfg.enable {
+    systemd.services.zookeeper = {
+      description = "Zookeeper Daemon";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      environment = { ZOOCFGDIR = configDir; };
+      serviceConfig = {
+        ExecStart = ''
+          ${pkgs.jre}/bin/java \
+            -cp "${pkgs.zookeeper}/lib/*:${pkgs.zookeeper}/${pkgs.zookeeper.name}.jar:${configDir}" \
+            ${toString cfg.extraCmdLineOptions} \
+            -Dzookeeper.datadir.autocreate=false \
+            ${optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \
+            org.apache.zookeeper.server.quorum.QuorumPeerMain \
+            ${configDir}/zoo.cfg
+        '';
+        User = "zookeeper";
+        PermissionsStartOnly = true;
+      };
+      preStart = ''
+        mkdir -m 0700 -p ${cfg.dataDir}
+        if [ "$(id -u)" = 0 ]; then chown zookeeper ${cfg.dataDir}; fi
+        echo "${toString cfg.id}" > ${cfg.dataDir}/myid
+      '';
+    };
+
+    users.extraUsers = singleton {
+      name = "zookeeper";
+      uid = config.ids.uids.zookeeper;
+      description = "Zookeeper daemon user";
+      home = cfg.dataDir;
+    };
+  };
+}
diff --git a/nixos/modules/services/monitoring/riemann-dash.nix b/nixos/modules/services/monitoring/riemann-dash.nix
new file mode 100644
index 00000000000..148dc046805
--- /dev/null
+++ b/nixos/modules/services/monitoring/riemann-dash.nix
@@ -0,0 +1,79 @@
+{ config, pkgs, lib, ... }:
+
+with pkgs;
+with lib;
+
+let
+
+  cfg = config.services.riemann-dash;
+
+  conf = writeText "config.rb" ''
+    riemann_base = "${cfg.dataDir}"
+    config.store[:ws_config] = "#{riemann_base}/config/config.json"
+    ${cfg.config}
+  '';
+
+  launcher = writeScriptBin "riemann-dash" ''
+    #!/bin/sh
+    exec ${rubyLibs.riemann_dash}/bin/riemann-dash ${conf}
+  '';
+
+in {
+
+  options = {
+
+    services.riemann-dash = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the riemann-dash dashboard daemon.
+        '';
+      };
+      config = mkOption {
+        type = types.lines;
+        description = ''
+          Contents added to the end of the riemann-dash configuration file.
+        '';
+      };
+      dataDir = mkOption {
+        type = types.str;
+        default = "/var/riemann-dash";
+        description = ''
+          Location of the riemann-base dir. The dashboard configuration file is
+          is stored to this directory. The directory is created automatically on
+          service start, and owner is set to the riemanndash user.
+        '';
+      };
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraGroups.riemanndash.gid = config.ids.gids.riemanndash;
+
+    users.extraUsers.riemanndash = {
+      description = "riemann-dash daemon user";
+      uid = config.ids.uids.riemanndash;
+      group = "riemanndash";
+    };
+
+    systemd.services.riemann-dash = {
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "riemann.service" ];
+      after = [ "riemann.service" ];
+      preStart = ''
+        mkdir -p ${cfg.dataDir}/config
+        chown -R riemanndash:riemanndash ${cfg.dataDir}
+      '';
+      serviceConfig = {
+        User = "riemanndash";
+        ExecStart = "${launcher}/bin/riemann-dash";
+        PermissionsStartOnly = true;
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/monitoring/riemann.nix b/nixos/modules/services/monitoring/riemann.nix
new file mode 100644
index 00000000000..a1935c29a04
--- /dev/null
+++ b/nixos/modules/services/monitoring/riemann.nix
@@ -0,0 +1,77 @@
+{ config, pkgs, lib, ... }:
+
+with pkgs;
+with lib;
+
+let
+
+  cfg = config.services.riemann;
+
+  classpath = concatStringsSep ":" (
+    cfg.extraClasspathEntries ++ [ "${riemann}/share/java/riemann.jar" ]
+  );
+
+  launcher = writeScriptBin "riemann" ''
+    #!/bin/sh
+    exec ${openjdk}/bin/java ${concatStringsSep "\n" cfg.extraJavaOpts} \
+      -cp ${classpath} \
+      riemann.bin ${writeText "riemann.config" cfg.config}
+  '';
+
+in {
+
+  options = {
+
+    services.riemann = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the Riemann network monitoring daemon.
+        '';
+      };
+      config = mkOption {
+        type = types.lines;
+        description = ''
+          Contents of the Riemann configuration file.
+        '';
+      };
+      extraClasspathEntries = mkOption {
+        type = with types; listOf str;
+        default = [];
+        description = ''
+          Extra entries added to the Java classpath when running Riemann.
+        '';
+      };
+      extraJavaOpts = mkOption {
+        type = with types; listOf str;
+        default = [];
+        description = ''
+          Extra Java options used when launching Riemann.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraGroups.riemann.gid = config.ids.gids.riemann;
+
+    users.extraUsers.riemann = {
+      description = "riemann daemon user";
+      uid = config.ids.uids.riemann;
+      group = "riemann";
+    };
+
+    systemd.services.riemann = {
+      wantedBy = [ "multi-user.target" ];
+      path = [ inetutils ];
+      serviceConfig = {
+        User = "riemann";
+        ExecStart = "${launcher}/bin/riemann";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix
index 250035fe447..803bd9e9a65 100644
--- a/nixos/modules/services/monitoring/smartd.nix
+++ b/nixos/modules/services/monitoring/smartd.nix
@@ -62,7 +62,7 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        example = "true";
+        example = true;
         description = ''
           Run smartd from the smartmontools package. Note that e-mail
           notifications will not be enabled unless you configure the list of
diff --git a/nixos/modules/services/network-filesystems/diod.nix b/nixos/modules/services/network-filesystems/diod.nix
new file mode 100644
index 00000000000..1ab5f52d438
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/diod.nix
@@ -0,0 +1,159 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  cfg = config.services.diod;
+
+  diodBool = b: if b then "1" else "0";
+
+  diodConfig = pkgs.writeText "diod.conf" ''
+    allsquash = ${diodBool cfg.allsquash}
+    auth_required = ${diodBool cfg.authRequired}
+    exportall = ${diodBool cfg.exportall}
+    exportopts = "${concatStringsSep "," cfg.exportopts}"
+    exports = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.exports)} }
+    listen = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.listen)} }
+    logdest = "${cfg.logdest}"
+    nwthreads = ${toString cfg.nwthreads}
+    squashuser = "${cfg.squashuser}"
+    statfs_passthru = ${diodBool cfg.statfsPassthru}
+    userdb = ${diodBool cfg.userdb}
+    ${cfg.extraConfig}
+  '';
+in
+{
+  options = {
+    services.diod = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the diod 9P file server.";
+      };
+
+      listen = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        description = ''
+          [ "IP:PORT" [,"IP:PORT",...] ]
+          List the interfaces and ports that diod should listen on.
+        '';
+      };
+
+      exports = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          List the file systems that clients will be allowed to mount. All paths should
+          be fully qualified. The exports table can include two types of element:
+          a string element (as above),
+          or an alternate table element form { path="/path", opts="ro" }.
+          In the alternate form, the (optional) opts attribute is a comma-separated list
+          of export options. The two table element forms can be mixed in the exports
+          table. Note that although diod will not traverse file system boundaries for a
+          given mount due to inode uniqueness constraints, subdirectories of a file
+          system can be separately exported.
+        '';
+      };
+
+      exportall = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Export all file systems listed in /proc/mounts. If new file systems are mounted
+          after diod has started, they will become immediately mountable. If there is a
+          duplicate entry for a file system in the exports list, any options listed in
+          the exports entry will apply.
+        '';
+      };
+
+      exportopts = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          Establish a default set of export options. These are overridden, not appended
+          to, by opts attributes in an "exports" entry.
+        '';
+      };
+
+      nwthreads = mkOption {
+        type = types.int;
+        default = 16;
+        description = ''
+          Sets the (fixed) number of worker threads created to handle 9P
+          requests for a unique aname.
+        '';
+      };
+
+      authRequired = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Allow clients to connect without authentication, i.e. without a valid MUNGE credential.
+        '';
+      };
+
+      userdb = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          This option disables password/group lookups. It allows any uid to attach and
+          assumes gid=uid, and supplementary groups contain only the primary gid.
+        '';
+      };
+
+      allsquash = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Remap all users to "nobody". The attaching user need not be present in the
+          password file.
+        '';
+      };
+
+      squashuser = mkOption {
+        type = types.str;
+        default = "nobody";
+        description = ''
+          Change the squash user. The squash user must be present in the password file.
+        '';
+      };
+
+      logdest = mkOption {
+        type = types.str;
+        default = "syslog:daemon:err";
+        description = ''
+          Set the destination for logging.
+          The value has the form of "syslog:facility:level" or "filename".
+        '';
+      };
+
+
+      statfsPassthru = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          This option configures statfs to return the host file system's type
+          rather than V9FS_MAGIC.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Extra configuration options for diod.conf.";
+      };
+    };
+  };
+
+  config = mkIf config.services.diod.enable {
+    environment.systemPackages = [ pkgs.diod ];
+
+    systemd.services.diod = {
+      description = "diod 9P file server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.diod}/sbin/diod -c ${diodConfig}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/nfsd.nix b/nixos/modules/services/network-filesystems/nfsd.nix
index 2217fec3b0f..57d56cd7287 100644
--- a/nixos/modules/services/network-filesystems/nfsd.nix
+++ b/nixos/modules/services/network-filesystems/nfsd.nix
@@ -56,6 +56,14 @@ in
           default = false;
           description = "Whether to create the mount points in the exports file at startup time.";
         };
+
+        mountdPort = mkOption {
+          default = null;
+          example = 4002;
+          description = ''
+            Use fixed port for rpc.mountd, usefull if server is behind firewall.
+          '';
+        };
       };
 
     };
@@ -138,7 +146,10 @@ in
         restartTriggers = [ exports ];
 
         serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = "@${pkgs.nfsUtils}/sbin/rpc.mountd rpc.mountd";
+        serviceConfig.ExecStart = ''
+          @${pkgs.nfsUtils}/sbin/rpc.mountd rpc.mountd \
+              ${if cfg.mountdPort != null then "-p ${toString cfg.mountdPort}" else ""}
+        '';
         serviceConfig.Restart = "always";
       };
 
diff --git a/nixos/modules/services/network-filesystems/yandex-disk.nix b/nixos/modules/services/network-filesystems/yandex-disk.nix
new file mode 100644
index 00000000000..df9626d17c9
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/yandex-disk.nix
@@ -0,0 +1,104 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.yandex-disk;
+
+  dir = "/var/lib/yandex-disk";
+
+  u = if cfg.user != null then cfg.user else "yandexdisk";
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.yandex-disk = {
+
+      enable = mkOption {
+        default = false;
+        description = "
+          Whether to enable Yandex-disk client. See https://disk.yandex.ru/
+        ";
+      };
+
+      username = mkOption {
+        default = "";
+        type = types.string;
+        description = ''
+          Your yandex.com login name.
+        '';
+      };
+
+      password = mkOption {
+        default = "";
+        type = types.string;
+        description = ''
+          Your yandex.com password. Warning: it will be world-readable in /nix/store.
+        '';
+      };
+
+      user = mkOption {
+        default = null;
+        description = ''
+          The user the yandex-disk daemon should run as.
+        '';
+      };
+
+      directory = mkOption {
+        default = "/home/Yandex.Disk";
+        description = "The directory to use for Yandex.Disk storage";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = mkIf (cfg.user == null) [ {
+      name = u;
+      uid = config.ids.uids.yandexdisk;
+      group = "nogroup";
+      home = dir;
+    } ];
+
+    systemd.services.yandex-disk = {
+      description = "Yandex-disk server";
+
+      after = [ "network.target" ];
+
+      wantedBy = [ "multi-user.target" ];
+
+      # FIXME: have to specify ${directory} here as well
+      unitConfig.RequiresMountsFor = dir;
+
+      script = ''
+        mkdir -p -m 700 ${dir}
+        chown ${u} ${dir}
+
+        if ! test -d "${cfg.directory}" ; then
+          mkdir -p -m 755 ${cfg.directory} ||
+            exit 1
+        fi
+
+        ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \
+          -c '${pkgs.yandex-disk}/bin/yandex-disk token -p ${cfg.password} ${cfg.username} ${dir}/token'
+
+        ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \
+          -c '${pkgs.yandex-disk}/bin/yandex-disk start --no-daemon -a ${dir}/token -d ${cfg.directory}'
+      '';
+
+    };
+  };
+
+}
+
diff --git a/nixos/modules/services/networking/atftpd.nix b/nixos/modules/services/networking/atftpd.nix
new file mode 100644
index 00000000000..ab9f8650f0f
--- /dev/null
+++ b/nixos/modules/services/networking/atftpd.nix
@@ -0,0 +1,51 @@
+# NixOS module for atftpd TFTP server
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.atftpd;
+
+in
+
+{
+
+  options = {
+
+    services.atftpd = {
+
+      enable = mkOption {
+        default = false;
+        type = types.uniq types.bool;
+        description = ''
+          Whenever to enable the atftpd TFTP server.
+        '';
+      };
+
+      root = mkOption {
+        default = "/var/empty";
+        type = types.uniq types.string;
+        description = ''
+          Document root directory for the atftpd.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.atftpd = {
+      description = "atftpd TFTP server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      # runs as nobody
+      serviceConfig.ExecStart = "${pkgs.atftp}/sbin/atftpd --daemon --no-fork --bind-address 0.0.0.0 ${cfg.root}";
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 9306ffd5a18..0519172db91 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -1,13 +1,3 @@
-# You may notice the commented out sections in this file,
-# it would be great to configure cjdns from nix, but cjdns 
-# reads its configuration from stdin, including the private
-# key and admin password, all nested in a JSON structure.
-#
-# Until a good method of storing the keys outside the nix 
-# store and mixing them back into a string is devised
-# (without too much shell hackery), a skeleton of the
-# configuration building lies commented out.
-
 { config, lib, pkgs, ... }:
 
 with lib;
@@ -16,41 +6,35 @@ let
 
   cfg = config.services.cjdns;
 
-  /*
-  # can't keep keys and passwords in the nix store,
-  # but don't want to deal with this stdin quagmire.
-
-  cjdrouteConf = '' {
-    "admin": {"bind": "${cfg.admin.bind}", "password": "\${CJDNS_ADMIN}" },
-    "privateKey": "\${CJDNS_KEY}",
-
-    "interfaces": {
-    ''
-
-    + optionalString (cfg.interfaces.udp.bind.address != null) ''
-      "UDPInterface": [ {
-        "bind": "${cfg.interfaces.udp.bind.address}:"''
-	   ${if cfg.interfaces.upd.bind.port != null
-             then ${toString cfg.interfaces.udp.bind.port}
-	     else ${RANDOM}
-	   fi)
-      + '' } ]''
-
-    + (if cfg.interfaces.eth.bind != null then ''
-      "ETHInterface": [ {
-        "bind": "${cfg.interfaces.eth.bind}",
-        "beacon": ${toString cfg.interfaces.eth.beacon}
-      } ]
-    '' fi )
-    + ''
-    },
-    "router": { "interface": { "type": "TUNInterface" }, },
-    "security": [ { "setuser": "nobody" } ]
-    }
-    '';   
-
-    cjdrouteConfFile = pkgs.writeText "cjdroute.conf" cjdrouteConf
-    */
+  # would be nice to  merge 'cfg' with a //,
+  # but the json nesting is wacky.
+  cjdrouteConf = builtins.toJSON ( {
+    admin = {
+      bind = cfg.admin.bind;
+      password = "@CJDNS_ADMIN_PASSWORD@";
+    };
+    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 [ ];
+    };
+
+    privateKey = "@CJDNS_PRIVATE_KEY@";
+
+    resetAfterInactivitySeconds = 100;
+
+    router = {
+      interface = { type = "TUNInterface"; };
+      ipTunnel = {
+        allowedConnections = [];
+        outgoingConnections = [];
+      };
+    };
+
+    security = [ { exemptAngel = 1; setuser = "nobody"; } ];
+
+  });
+
 in
 
 {
@@ -62,146 +46,180 @@ in
         type = types.bool;
 	default = false;
         description = ''
-          Enable this option to start a instance of the 
-          cjdns network encryption and and routing engine.
-          Configuration will be read from <literal>confFile</literal>.
+          Whether to enable the cjdns network encryption
+          and routing engine. A file at /etc/cjdns.keys will
+          be created if it does not exist to contain a random
+          secret key that your IPv6 address will be derived from.
         '';
       };
 
-      confFile = mkOption {
-	default = "/etc/cjdroute.conf";
-        description = ''
-          Configuration file to pipe to cjdroute.
+      authorizedPasswords = mkOption {
+        type = types.listOf types.str;
+	default = [ ];
+	example = [
+          "snyrfgkqsc98qh1y4s5hbu0j57xw5s0"
+	  "z9md3t4p45mfrjzdjurxn4wuj0d8swv"
+	  "49275fut6tmzu354pq70sr5b95qq0vj"
+        ];
+	description = ''
+	  Any remote cjdns nodes that offer these passwords on 
+	  connection will be allowed to route through this node.
         '';
       };
-
-      /*
+    
       admin = {
         bind = mkOption {
+          type = types.string;
 	  default = "127.0.0.1:11234";
 	  description = ''
             Bind the administration port to this address and port.
 	  '';
         };
+      };
 
-	passwordFile = mkOption {
-	  example = "/root/cjdns.adminPassword";
-	  description = ''
-	    File containing a password to the administration port.
+      UDPInterface = {
+        bind = mkOption {
+          type = types.string;
+	  default = "";
+          example = "192.168.1.32:43211";
+          description = ''
+	    Address and port to bind UDP tunnels to.
+	  '';
+ 	};
+        connectTo = mkOption {
+          type = types.attrsOf ( types.submodule (
+	    { options, ... }:
+            { options = {
+                # TODO make host an option, and add it to networking.extraHosts
+                password = mkOption {
+                  type = types.str;
+                  description = "Authorized password to the opposite end of the tunnel.";
+                };
+                publicKey = mkOption {
+                  type = types.str;
+                  description = "Public key at the opposite end of the tunnel.";
+                };
+              };
+            }
+          ));
+	  default = { };
+          example = {
+            "192.168.1.1:27313" = {
+	      password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
+              publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
+            };
+          };
+          description = ''
+	    Credentials for making UDP tunnels.
 	  '';
 	};
       };
 
-      keyFile = mkOption {
-        type = types.str;
-	example = "/root/cjdns.key";
-	description = ''
-	  Path to a file containing a cjdns private key on a single line.
-	'';
-      };
-      
-      passwordsFile = mkOption {
-        type = types.str;
-	default = null;
-	example = "/root/cjdns.authorizedPasswords";
-	description = ''
-	  A file containing a list of json dictionaries with passwords.
-	  For example:
-	    {"password": "s8xf5z7znl4jt05g922n3wpk75wkypk"},
-	    { "name": "nice guy",
-	      "password": "xhthk1mglz8tpjrbbvdlhyc092rhpx5"},
-	    {"password": "3qfxyhmrht7uwzq29pmhbdm9w4bnc8w"}
+      ETHInterface = {
+        bind = mkOption {
+	  default = "";
+	  example = "eth0";
+	  description = ''
+	    Bind to this device for native ethernet operation.
 	  '';
-	};
-
-      interfaces = {
-        udp = {
-	  bind = { 
-            address = mkOption {
-	      default = "0.0.0.0";
-	      description = ''
-	        Address to bind UDP tunnels to; disable by setting to null;
-	      '';
- 	    };
-	    port = mkOption {
-	      type = types.int;
-	      default = null;
-	      description = ''
-	        Port to bind UDP tunnels to.
-	        A port will be choosen at random if this is not set.
-	        This option is required to act as the server end of 
-	        a tunnel.
-	      '';
- 	    };
-	  };
-	};
+        };
 
-	eth = {
-	  bind = mkOption {
-	    default = null;
-	    example = "eth0";
-	    description = ''
-	      Bind to this device and operate with native wire format.
-	    '';
-	  };
-
-	  beacon = mkOption {
-	    default = 2;
-	    description = ''
-	      Auto-connect to other cjdns nodes on the same network.
-	      Options:
-	        0 -- Disabled.
-
-                1 -- Accept beacons, this will cause cjdns to accept incoming
-		     beacon messages and try connecting to the sender.
-
-		2 -- Accept and send beacons, this will cause cjdns to broadcast
-		     messages on the local network which contain a randomly
-		     generated per-session password, other nodes which have this
-                     set to 1 or 2 will hear the beacon messages and connect
-                     automatically.
-            '';
-	  };
-	  
-	  connectTo = mkOption {
-	    type = types.listOf types.str;
-	    default = [];
-	    description = ''
-	      Credentials for connecting look similar to UDP credientials
-              except they begin with the mac address, for example:
-              "01:02:03:04:05:06":{"password":"a","publicKey":"b"}
-	    '';
-	  };
+        beacon = mkOption {
+	  type = types.int;
+          default = 2;
+          description = ''
+            Auto-connect to other cjdns nodes on the same network.
+            Options:
+	      0: Disabled.
+              1: Accept beacons, this will cause cjdns to accept incoming
+                 beacon messages and try connecting to the sender.
+              2: Accept and send beacons, this will cause cjdns to broadcast
+                 messages on the local network which contain a randomly
+                 generated per-session password, other nodes which have this
+                 set to 1 or 2 will hear the beacon messages and connect
+                 automatically.
+          '';
         };
+
+        connectTo = mkOption {
+          type = types.attrsOf ( types.submodule (
+	    { options, ... }:
+            { options = {
+                password = mkOption {
+                  type = types.str;
+                  description = "Authorized password to the opposite end of the tunnel.";
+                };
+                publicKey = mkOption {
+                  type = types.str;
+                  description = "Public key at the opposite end of the tunnel.";
+                };
+              };
+            }
+          ));
+	  default = { };
+          example = {
+            "01:02:03:04:05:06" = {
+	      password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
+              publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
+            };
+          };
+	  description = ''
+	    Credentials for connecting look similar to UDP credientials
+            except they begin with the mac address.
+	  '';
+	};
       };
-      */
+
     };
+
   };
 
   config = mkIf config.services.cjdns.enable {
 
     boot.kernelModules = [ "tun" ];
 
-    /*
-    networking.firewall.allowedUDPPorts = mkIf (cfg.udp.bind.port != null) [
-      cfg.udp.bind.port
-    ];
-    */
+    # networking.firewall.allowedUDPPorts = ...
 
     systemd.services.cjdns = {
       description = "encrypted networking for everybody";
       wantedBy = [ "multi-user.target" ];
-      wants = [ "network.target" ];
-      before = [ "network.target" ];
-      path = [ pkgs.cjdns ];
+      after = [ "network-interfaces.target" ];
+
+      script = ''
+        source /etc/cjdns.keys
+        echo '${cjdrouteConf}' | sed \
+	  -e "s/@CJDNS_ADMIN_PASSWORD@/$CJDNS_ADMIN_PASSWORD/g" \
+          -e "s/@CJDNS_PRIVATE_KEY@/$CJDNS_PRIVATE_KEY/g" \
+            | ${pkgs.cjdns}/sbin/cjdroute
+      '';
 
       serviceConfig = {
         Type = "forking";
-	ExecStart = ''
-          ${pkgs.stdenv.shell} -c "${pkgs.cjdns}/sbin/cjdroute < ${cfg.confFile}"
-	'';
 	Restart = "on-failure";
       };
     };
+
+    system.activationScripts.cjdns = ''
+      grep -q "CJDNS_PRIVATE_KEY=" /etc/cjdns.keys || \
+        echo "CJDNS_PRIVATE_KEY=$(${pkgs.cjdns}/sbin/makekey)" \
+	  >> /etc/cjdns.keys
+
+      grep -q "CJDNS_ADMIN_PASSWORD=" /etc/cjdns.keys || \
+        echo "CJDNS_ADMIN_PASSWORD=$(${pkgs.coreutils}/bin/head -c 96 /dev/urandom | ${pkgs.coreutils}/bin/tr -dc A-Za-z0-9)" \
+	  >> /etc/cjdns.keys
+
+      chmod 600 /etc/cjdns.keys
+    '';
+
+    assertions = [
+      { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" );
+        message = "Neither cjdns.ETHInterface.bind nor cjdns.UDPInterface.bind defined.";
+      }
+      { assertion = config.networking.enableIPv6;
+        message = "networking.enableIPv6 must be enabled for CJDNS to work";
+      }
+    ];
+
   };
-}
+
+}
\ No newline at end of file
diff --git a/nixos/modules/services/networking/copy-com.nix b/nixos/modules/services/networking/copy-com.nix
new file mode 100644
index 00000000000..36bd29109b8
--- /dev/null
+++ b/nixos/modules/services/networking/copy-com.nix
@@ -0,0 +1,53 @@
+{ config, lib, pkgs, ... }:

+

+with lib;

+

+let

+  

+  cfg = config.services.copy-com;

+

+in 

+

+{

+  options = {

+

+    services.copy-com = {

+	  

+	  enable = mkOption {

+          default = false;

+          description = "

+            Enable the copy.com client.

+

+            The first time copy.com is run, it needs to be configured. Before enabling run 

+            copy_console manually.

+          ";

+      };

+

+      user = mkOption {

+        description = "The user for which copy should run.";

+      };

+

+      debug = mkOption {

+        default = false;

+        description = "Output more.";

+      };

+	  };

+  };

+

+  config = mkIf cfg.enable {

+    environment.systemPackages = [ pkgs.postfix ];

+

+    systemd.services."copy-com-${cfg.user}" = {

+      description = "Copy.com Client";

+      after = [ "network.target" "local-fs.target" ];

+      wantedBy = [ "multi-user.target" ];

+      serviceConfig = {

+        ExecStart = "${pkgs.copy-com}/bin/copy_console ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}";

+        User = "${cfg.user}";

+      };

+

+    };

+  };

+

+}

+

diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 5a353fc0942..084ac69e8d5 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -6,10 +6,13 @@ let
 
   dhcpcd = if !config.boot.isContainer then pkgs.dhcpcd else pkgs.dhcpcd.override { udev = null; };
 
+  cfg = config.networking.dhcpcd;
+
   # Don't start dhcpcd on explicitly configured interfaces or on
-  # interfaces that are part of a bridge.
+  # interfaces that are part of a bridge, bond or sit device.
   ignoredInterfaces =
-    map (i: i.name) (filter (i: i.ipAddress != null) (attrValues config.networking.interfaces))
+    map (i: i.name) (filter (i: i.ip4 != [ ] || i.ipAddress != null) (attrValues config.networking.interfaces))
+    ++ mapAttrsToList (i: _: i) config.networking.sits
     ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
     ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
     ++ config.networking.dhcpcd.denyInterfaces;
@@ -35,9 +38,12 @@ let
       # Ignore peth* devices; on Xen, they're renamed physical
       # Ethernet cards used for bridging.  Likewise for vif* and tap*
       # (Xen) and virbr* and vnet* (libvirt).
-      denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet*
+      denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* sit*
+
+      # Use the list of allowed interfaces if specified
+      ${optionalString (cfg.allowInterfaces != null) "allowinterfaces ${toString cfg.allowInterfaces}"}
 
-      ${config.networking.dhcpcd.extraConfig}
+      ${cfg.extraConfig}
     '';
 
   # Hook for emitting ip-up/ip-down events.
@@ -58,7 +64,7 @@ let
       #    ${config.systemd.package}/bin/systemctl start ip-down.target
       #fi
 
-      ${config.networking.dhcpcd.runHook}
+      ${cfg.runHook}
     '';
 
 in
@@ -69,6 +75,18 @@ in
 
   options = {
 
+    networking.dhcpcd.persistent = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+          Whenever to leave interfaces configured on dhcpcd daemon
+          shutdown. Set to true if you have your root or store mounted
+          over the network or this machine accepts SSH connections
+          through DHCP interfaces and clients should be notified when
+          it shuts down.
+      '';
+    };
+
     networking.dhcpcd.denyInterfaces = mkOption {
       type = types.listOf types.str;
       default = [];
@@ -80,6 +98,17 @@ in
       '';
     };
 
+    networking.dhcpcd.allowInterfaces = mkOption {
+      type = types.nullOr (types.listOf types.str);
+      default = null;
+      description = ''
+         Enable the DHCP client for any interface whose name matches
+         any of the shell glob patterns in this list. Any interface not
+         explicitly matched by this pattern will be denied. This pattern only
+         applies when non-null.
+      '';
+    };
+
     networking.dhcpcd.extraConfig = mkOption {
       type = types.lines;
       default = "";
@@ -122,7 +151,7 @@ in
         serviceConfig =
           { Type = "forking";
             PIDFile = "/run/dhcpcd.pid";
-            ExecStart = "@${dhcpcd}/sbin/dhcpcd dhcpcd --quiet --config ${dhcpcdConf}";
+            ExecStart = "@${dhcpcd}/sbin/dhcpcd dhcpcd --quiet ${optionalString cfg.persistent "--persistent"} --config ${dhcpcdConf}";
             ExecReload = "${dhcpcd}/sbin/dhcpcd --rebind";
             Restart = "always";
           };
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index 8e38b9d017a..5c68dd89fb1 100644
--- a/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixos/modules/services/networking/dnsmasq.nix
@@ -6,9 +6,14 @@ let
   cfg = config.services.dnsmasq;
   dnsmasq = pkgs.dnsmasq;
 
-  serversParam = concatMapStrings (s: "-S ${s} ") cfg.servers;
-
   dnsmasqConf = pkgs.writeText "dnsmasq.conf" ''
+    ${optionalString cfg.resolveLocalQueries ''
+      conf-file=/etc/dnsmasq-conf.conf
+      resolv-file=/etc/dnsmasq-resolv.conf
+    ''}
+    ${flip concatMapStrings cfg.servers (server: ''
+      server=${server}
+    '')}
     ${cfg.extraConfig}
   '';
 
@@ -29,11 +34,19 @@ in
         '';
       };
 
+      resolveLocalQueries = mkOption {
+        default = true;
+        description = ''
+          Whether dnsmasq should resolve local queries (i.e. add 127.0.0.1 to
+          /etc/resolv.conf)
+        '';
+      };
+
       servers = mkOption {
         default = [];
         example = [ "8.8.8.8" "8.8.4.4" ];
         description = ''
-          The parameter to dnsmasq -S.
+          The DNS servers which dnsmasq should query.
         '';
       };
 
@@ -55,16 +68,35 @@ in
 
   config = mkIf config.services.dnsmasq.enable {
 
-    jobs.dnsmasq =
-      { description = "dnsmasq daemon";
+    networking.nameservers =
+      optional cfg.resolveLocalQueries "127.0.0.1";
 
-        startOn = "ip-up";
+    services.dbus.packages = [ dnsmasq ];
 
-        daemonType = "daemon";
-
-        exec = "${dnsmasq}/bin/dnsmasq -R ${serversParam} -o -C ${dnsmasqConf}";
+    users.extraUsers = singleton
+      { name = "dnsmasq";
+        uid = config.ids.uids.dnsmasq;
+        description = "Dnsmasq daemon user";
+        home = "/var/empty";
       };
 
+    systemd.services.dnsmasq = {
+        description = "dnsmasq daemon";
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        path = [ dnsmasq ];
+        preStart = ''
+          touch /etc/dnsmasq-{conf,resolv}.conf
+          dnsmasq --test
+        '';
+        serviceConfig = {
+          Type = "dbus";
+          BusName = "uk.org.thekelleys.dnsmasq";
+          ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}";
+          ExecReload = "${dnsmasq}/bin/kill -HUP $MAINPID";
+        };
+    };
+
   };
 
 }
diff --git a/nixos/modules/services/networking/ircd-hybrid/default.nix b/nixos/modules/services/networking/ircd-hybrid/default.nix
index a3d5b71740f..2c397f94d23 100644
--- a/nixos/modules/services/networking/ircd-hybrid/default.nix
+++ b/nixos/modules/services/networking/ircd-hybrid/default.nix
@@ -66,7 +66,7 @@ in
 
       rsaKey = mkOption {
         default = null;
-        example = /root/certificates/irc.key;
+        example = literalExample "/root/certificates/irc.key";
         description = "
           IRCD server RSA key.
         ";
@@ -74,7 +74,7 @@ in
 
       certificate = mkOption {
         default = null;
-        example = /root/certificates/irc.pem;
+        example = literalExample "/root/certificates/irc.pem";
         description = "
           IRCD server SSL certificate. There are some limitations - read manual.
         ";
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index e8d9d00cc0a..4a4c06503c2 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -75,6 +75,31 @@ in
         '';
     };
 
+    networking.nat.forwardPorts = mkOption {
+      type = types.listOf types.optionSet;
+      default = [];
+      example = [ { sourcePort = 8080; destination = "10.0.0.1:80"; } ];
+      options = {
+        sourcePort = mkOption {
+          type = types.int;
+          example = 8080;
+          description = "Source port of the external interface";
+        };
+
+        destination = mkOption {
+          type = types.str;
+          example = "10.0.0.1:80";
+          description = "Forward tcp connection to destination ip:port";
+        };
+      };
+
+      description =
+        ''
+          List of forwarded ports from the external interface to
+          internal destinations by using DNAT.
+        '';
+    };
+
   };
 
 
@@ -118,6 +143,14 @@ in
                 -s '${range}' -o ${cfg.externalInterface} ${dest}
             '') cfg.internalIPs}
 
+            # NAT from external ports to internal ports.
+            ${concatMapStrings (fwd: ''
+              iptables -w -t nat -A PREROUTING \
+                -i ${cfg.externalInterface} -p tcp \
+                --dport ${builtins.toString fwd.sourcePort} \
+                -j DNAT --to-destination ${fwd.destination}
+            '') cfg.forwardPorts}
+
             echo 1 > /proc/sys/net/ipv4/ip_forward
           '';
 
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index db8cb122871..cacd52f130f 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -456,156 +456,131 @@ in
       };
 
 
-      ratelimit = mkOption {
-        type = types.submodule (
-          { options, ... }:
-          { options = {
-
-              enable = mkOption {
-                type        = types.bool;
-                default     = false;
-                description = ''
-                  Enable ratelimit capabilities.
-                '';
-              };
-
-              size = mkOption {
-                type        = types.int;
-                default     = 1000000;
-                description = ''
-                  Size of the hashtable. More buckets use more memory but lower
-                  the chance of hash hash collisions.
-                '';
-              };
+      ratelimit = {
+        enable = mkOption {
+          type        = types.bool;
+          default     = false;
+          description = ''
+            Enable ratelimit capabilities.
+          '';
+        };
 
-              ratelimit = mkOption {
-                type        = types.int;
-                default     = 200;
-                description = ''
-                  Max qps allowed from any query source.
-                  0 means unlimited. With an verbosity of 2 blocked and
-                  unblocked subnets will be logged.
-                '';
-              };
+        size = mkOption {
+          type        = types.int;
+          default     = 1000000;
+          description = ''
+            Size of the hashtable. More buckets use more memory but lower
+            the chance of hash hash collisions.
+          '';
+        };
 
-              whitelistRatelimit = mkOption {
-                type        = types.int;
-                default     = 2000;
-                description = ''
-                  Max qps allowed from whitelisted sources.
-                  0 means unlimited. Set the rrl-whitelist option for specific
-                  queries to apply this limit instead of the default to them.
-                '';
-              };
+        ratelimit = mkOption {
+          type        = types.int;
+          default     = 200;
+          description = ''
+            Max qps allowed from any query source.
+            0 means unlimited. With an verbosity of 2 blocked and
+            unblocked subnets will be logged.
+          '';
+        };
 
-              slip = mkOption {
-                type        = types.nullOr types.int;
-                default     = null;
-                description = ''
-                  Number of packets that get discarded before replying a SLIP response.
-                  0 disables SLIP responses. 1 will make every response a SLIP response.
-                '';
-              };
+        whitelistRatelimit = mkOption {
+          type        = types.int;
+          default     = 2000;
+          description = ''
+            Max qps allowed from whitelisted sources.
+            0 means unlimited. Set the rrl-whitelist option for specific
+            queries to apply this limit instead of the default to them.
+          '';
+        };
 
-              ipv4PrefixLength = mkOption {
-                type        = types.nullOr types.int;
-                default     = null;
-                description = ''
-                  IPv4 prefix length. Addresses are grouped by netblock.
-                '';
-              };
+        slip = mkOption {
+          type        = types.nullOr types.int;
+          default     = null;
+          description = ''
+            Number of packets that get discarded before replying a SLIP response.
+            0 disables SLIP responses. 1 will make every response a SLIP response.
+          '';
+        };
 
-              ipv6PrefixLength = mkOption {
-                type        = types.nullOr types.int;
-                default     = null;
-                description = ''
-                  IPv6 prefix length. Addresses are grouped by netblock.
-                '';
-              };
+        ipv4PrefixLength = mkOption {
+          type        = types.nullOr types.int;
+          default     = null;
+          description = ''
+            IPv4 prefix length. Addresses are grouped by netblock.
+          '';
+        };
 
-            };
-          });
-        default = {
+        ipv6PrefixLength = mkOption {
+          type        = types.nullOr types.int;
+          default     = null;
+          description = ''
+            IPv6 prefix length. Addresses are grouped by netblock.
+          '';
         };
-        example = {};
-        description = ''
-        '';
       };
 
 
-      remoteControl = mkOption {
-        type = types.submodule (
-          { config, options, ... }:
-          { options = {
-
-              enable = mkOption {
-                type        = types.bool;
-                default     = false;
-                description = ''
-                  Wheter to enable remote control via nsd-control(8).
-                '';
-              };
-
-              interfaces = mkOption {
-                type        = types.listOf types.str;
-                default     = [ "127.0.0.1" "::1" ];
-                description = ''
-                  Which interfaces NSD should bind to for remote control.
-                '';
-              };
-
-              port = mkOption {
-                type        = types.int;
-                default     = 8952;
-                description = ''
-                  Port number for remote control operations (uses TLS over TCP).
-                '';
-              };
+      remoteControl = {
+        enable = mkOption {
+          type        = types.bool;
+          default     = false;
+          description = ''
+            Wheter to enable remote control via nsd-control(8).
+          '';
+        };
 
-              serverKeyFile = mkOption {
-                type        = types.path;
-                default     = "/etc/nsd/nsd_server.key";
-                description = ''
-                  Path to the server private key, which is used by the server
-                  but not by nsd-control. This file is generated by nsd-control-setup.
-                '';
-              };
+        interfaces = mkOption {
+          type        = types.listOf types.str;
+          default     = [ "127.0.0.1" "::1" ];
+          description = ''
+            Which interfaces NSD should bind to for remote control.
+          '';
+        };
 
-              serverCertFile = mkOption {
-                type        = types.path;
-                default     = "/etc/nsd/nsd_server.pem";
-                description = ''
-                  Path to the server self signed certificate, which is used by the server
-                  but and by nsd-control. This file is generated by nsd-control-setup.
-                '';
-              };
+        port = mkOption {
+          type        = types.int;
+          default     = 8952;
+          description = ''
+            Port number for remote control operations (uses TLS over TCP).
+          '';
+        };
 
-              controlKeyFile = mkOption {
-                type        = types.path;
-                default     = "/etc/nsd/nsd_control.key";
-                description = ''
-                  Path to the client private key, which is used by nsd-control
-                  but not by the server. This file is generated by nsd-control-setup.
-                '';
-              };
+        serverKeyFile = mkOption {
+          type        = types.path;
+          default     = "/etc/nsd/nsd_server.key";
+          description = ''
+            Path to the server private key, which is used by the server
+            but not by nsd-control. This file is generated by nsd-control-setup.
+          '';
+        };
 
-              controlCertFile = mkOption {
-                type        = types.path;
-                default     = "/etc/nsd/nsd_control.pem";
-                description = ''
-                  Path to the client certificate signed with the server certificate.
-                  This file is used by nsd-control and generated by nsd-control-setup.
-                '';
-              };
+        serverCertFile = mkOption {
+          type        = types.path;
+          default     = "/etc/nsd/nsd_server.pem";
+          description = ''
+            Path to the server self signed certificate, which is used by the server
+            but and by nsd-control. This file is generated by nsd-control-setup.
+          '';
+        };
 
-            };
+        controlKeyFile = mkOption {
+          type        = types.path;
+          default     = "/etc/nsd/nsd_control.key";
+          description = ''
+            Path to the client private key, which is used by nsd-control
+            but not by the server. This file is generated by nsd-control-setup.
+          '';
+        };
 
-          });
-        default = {
+        controlCertFile = mkOption {
+          type        = types.path;
+          default     = "/etc/nsd/nsd_control.pem";
+          description = ''
+            Path to the client certificate signed with the server certificate.
+            This file is used by nsd-control and generated by nsd-control-setup.
+          '';
         };
-        example = {};
-        description = ''
-        '';
       };
 
 
diff --git a/nixos/modules/services/networking/openntpd.nix b/nixos/modules/services/networking/openntpd.nix
new file mode 100644
index 00000000000..bd8a7a04a2a
--- /dev/null
+++ b/nixos/modules/services/networking/openntpd.nix
@@ -0,0 +1,49 @@
+{ pkgs, lib, config, options, ... }:
+
+with lib;
+
+let
+  cfg = config.services.openntpd;
+
+  package = pkgs.openntpd.override {
+    privsepUser = "ntp";
+    privsepPath = "/var/empty";
+  };
+
+  cfgFile = pkgs.writeText "openntpd.conf" ''
+    ${concatStringsSep "\n" (map (s: "server ${s}") cfg.servers)}
+  '';
+in
+{
+  ###### interface
+
+  options.services.openntpd = {
+    enable = mkEnableOption "OpenNTP time synchronization server";
+
+    servers = mkOption {
+      default = config.services.ntp.servers;
+      type = types.listOf types.str;
+      inherit (options.services.ntp.servers) description;
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    services.ntp.enable = mkForce false;
+
+    users.extraUsers = singleton {
+      name = "ntp";
+      uid = config.ids.uids.ntp;
+      description = "OpenNTP daemon user";
+      home = "/var/empty";
+    };
+
+    systemd.services.openntpd = {
+      description = "OpenNTP Server";
+      wantedBy = [ "ip-up.target" ];
+      partOf = [ "ip-up.target" ];
+      serviceConfig.ExecStart = "${package}/sbin/ntpd -d -f ${cfgFile}";
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/privoxy.nix b/nixos/modules/services/networking/privoxy.nix
index 950112b2dab..94beb78ef5a 100644
--- a/nixos/modules/services/networking/privoxy.nix
+++ b/nixos/modules/services/networking/privoxy.nix
@@ -6,19 +6,18 @@ let
 
   inherit (pkgs) privoxy;
 
-  stateDir = "/var/spool/privoxy";
-
   privoxyUser = "privoxy";
 
-  privoxyFlags = "--no-daemon --user ${privoxyUser} ${privoxyCfg}";
-
-  privoxyCfg = pkgs.writeText "privoxy.conf" ''
-    listen-address  ${config.services.privoxy.listenAddress}
-    logdir          ${config.services.privoxy.logDir}
-    confdir         ${privoxy}/etc
-    filterfile      default.filter
+  cfg = config.services.privoxy;
 
-    ${config.services.privoxy.extraConfig}
+  confFile = pkgs.writeText "privoxy.conf" ''
+    user-manual ${privoxy}/share/doc/privoxy/user-manual
+    confdir ${privoxy}/etc/
+    listen-address  ${cfg.listenAddress}
+    enable-edit-actions ${if (cfg.enableEditActions == true) then "1" else "0"}
+    ${concatMapStrings (f: "actionsfile ${f}\n") cfg.actionsFiles}
+    ${concatMapStrings (f: "filterfile ${f}\n") cfg.filterFiles}
+    ${cfg.extraConfig}
   '';
 
 in
@@ -32,27 +31,51 @@ in
     services.privoxy = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = ''
-          Whether to run the machine as a HTTP proxy server.
+          Whether to enable the Privoxy non-caching filtering proxy.
         '';
       };
 
       listenAddress = mkOption {
+        type = types.str;
         default = "127.0.0.1:8118";
         description = ''
           Address the proxy server is listening to.
         '';
       };
 
-      logDir = mkOption {
-        default = "/var/log/privoxy" ;
+      actionsFiles = mkOption {
+        type = types.listOf types.str;
+        example = [ "match-all.action" "default.action" "/etc/privoxy/user.action" ];
+        default = [ "match-all.action" "default.action" ];
+        description = ''
+          List of paths to Privoxy action files.
+          These paths may either be absolute or relative to the privoxy configuration directory.
+        '';
+      };
+
+      filterFiles = mkOption {
+        type = types.listOf types.str;
+        example = [ "default.filter" "/etc/privoxy/user.filter" ];
+        default = [ "default.filter" ];
+        description = ''
+          List of paths to Privoxy filter files.
+          These paths may either be absolute or relative to the privoxy configuration directory.
+        '';
+      };
+
+      enableEditActions = mkOption {
+        type = types.bool;
+        default = false;
         description = ''
-          Location for privoxy log files.
+          Whether or not the web-based actions file editor may be used.
         '';
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "" ;
         description = ''
           Extra configuration. Contents will be added verbatim to the configuration file.
@@ -62,33 +85,22 @@ in
 
   };
 
-
   ###### implementation
 
-  config = mkIf config.services.privoxy.enable {
+  config = mkIf cfg.enable {
   
-    environment.systemPackages = [ privoxy ];
-
     users.extraUsers = singleton
       { name = privoxyUser;
         uid = config.ids.uids.privoxy;
         description = "Privoxy daemon user";
-        home = stateDir;
       };
 
-    jobs.privoxy =
-      { name = "privoxy";
-
-        startOn = "startup";
-
-        preStart =
-          ''
-            mkdir -m 0755 -p ${stateDir}
-            chown ${privoxyUser} ${stateDir}
-          '';
-
-        exec = "${privoxy}/sbin/privoxy ${privoxyFlags}";
-      };
+    systemd.services.privoxy = {
+      description = "Filtering web proxy";
+      after = [ "network.target" "nss-lookup.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig.ExecStart = "${privoxy}/sbin/privoxy --no-daemon --user ${privoxyUser} ${confFile}";
+    };
 
   };
 
diff --git a/nixos/modules/services/networking/radvd.nix b/nixos/modules/services/networking/radvd.nix
index 08762c9c837..0199502163a 100644
--- a/nixos/modules/services/networking/radvd.nix
+++ b/nixos/modules/services/networking/radvd.nix
@@ -52,24 +52,32 @@ in
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.radvd ];
+    users.extraUsers.radvd =
+      { uid = config.ids.uids.radvd;
+        description = "Router Advertisement Daemon User";
+      };
 
-    jobs.radvd =
+    systemd.services.radvd =
       { description = "IPv6 Router Advertisement Daemon";
 
-        startOn = "started network-interfaces";
+        wantedBy = [ "multi-user.target" ];
+
+        after = [ "network.target" ];
 
-        preStart =
-          ''
-            # !!! Radvd only works if IPv6 forwarding is enabled.  But
-            # this should probably be done somewhere else (and not
-            # necessarily for all interfaces).
-            echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
-          '';
+        path = [ pkgs.radvd ];
 
-        exec = "${pkgs.radvd}/sbin/radvd -m syslog -s -C ${confFile}";
+        preStart = ''
+          mkdir -m 755 -p /run/radvd
+          chown radvd /run/radvd
+        '';
 
-        daemonType = "fork";
+        serviceConfig =
+          { ExecStart = "@${pkgs.radvd}/sbin/radvd radvd"
+              + " -p /run/radvd/radvd.pid -m syslog -u radvd -C ${confFile}";
+            Restart = "always";
+            Type = "forking";
+            PIDFile = "/run/radvd/radvd.pid";
+          };
       };
 
   };
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index e4b29a0b909..379dec2e92c 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -144,6 +144,36 @@ in
         '';
       };
 
+      listenAddresses = mkOption {
+        type = types.listOf types.optionSet;
+        default = [];
+        example = [ { addr = "192.168.3.1"; port = 22; } { addr = "0.0.0.0"; port = 64022; } ];
+        description = ''
+          List of addresses and ports to listen on (ListenAddress directive
+          in config). If port is not specified for address sshd will listen
+          on all ports specified by <literal>ports</literal> option.
+          NOTE: this will override default listening on all local addresses and port 22.
+          NOTE: setting this option won't automatically enable given ports
+          in firewall configuration.
+        '';
+        options = {
+          addr = mkOption {
+            type = types.nullOr types.str;
+            default = null;
+            description = ''
+              Host, IPv4 or IPv6 address to listen to.
+            '';
+          };
+          port = mkOption {
+            type = types.nullOr types.int;
+            default = null;
+            description = ''
+              Port to listen to.
+            '';
+          };
+        };
+      };
+
       passwordAuthentication = mkOption {
         type = types.bool;
         default = true;
@@ -349,6 +379,10 @@ in
           Port ${toString port}
         '') cfg.ports}
 
+        ${concatMapStrings ({ port, addr }: ''
+          ListenAddress ${addr}${if port != null then ":" + toString port else ""}
+        '') cfg.listenAddresses}
+
         ${optionalString cfgc.setXAuthLocation ''
             XAuthLocation ${pkgs.xorg.xauth}/bin/xauth
         ''}
@@ -383,6 +417,10 @@ in
         assertion = (data.publicKey == null && data.publicKeyFile != null) ||
                     (data.publicKey != null && data.publicKeyFile == null);
         message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
+      })
+      ++ 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/unbound.nix b/nixos/modules/services/networking/unbound.nix
index 415ff13bdda..73b10c1d561 100644
--- a/nixos/modules/services/networking/unbound.nix
+++ b/nixos/modules/services/networking/unbound.nix
@@ -6,8 +6,6 @@ let
 
   cfg = config.services.unbound;
 
-  username = "unbound";
-
   stateDir = "/var/lib/unbound";
 
   access = concatMapStrings (x: "  access-control: ${x} allow\n") cfg.allowedAccess;
@@ -21,21 +19,13 @@ let
   confFile = pkgs.writeText "unbound.conf" ''
     server:
       directory: "${stateDir}"
-      username: ${username}
-      # make sure unbound can access entropy from inside the chroot.
-      # e.g. on linux the use these commands (on BSD, devfs(8) is used):
-      #      mount --bind -n /dev/random /etc/unbound/dev/random
-      # and  mount --bind -n /dev/log /etc/unbound/dev/log
+      username: unbound
       chroot: "${stateDir}"
-      # logfile: "${stateDir}/unbound.log"  #uncomment to use logfile.
-      pidfile: "${stateDir}/unbound.pid"
-      verbosity: 1      # uncomment and increase to get more logging.
+      pidfile: ""
       ${interfaces}
       ${access}
-
-    ${forward}
-
     ${cfg.extraConfig}
+    ${forward}
   '';
 
 in
@@ -82,7 +72,7 @@ in
     environment.systemPackages = [ pkgs.unbound ];
 
     users.extraUsers = singleton {
-      name = username;
+      name = "unbound";
       uid = config.ids.uids.unbound;
       description = "unbound daemon user";
       home = stateDir;
@@ -96,8 +86,18 @@ in
       wants = [" nss-lookup.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      path = [ pkgs.unbound ];
-      serviceConfig.ExecStart = "${pkgs.unbound}/sbin/unbound -d -c ${confFile}";
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}/dev/
+	cp ${confFile} ${stateDir}/unbound.conf
+	chown unbound ${stateDir}
+	touch ${stateDir}/dev/random
+        ${pkgs.utillinux}/bin/mount --bind -n /dev/random ${stateDir}/dev/random
+      '';
+
+      serviceConfig = {
+        ExecStart = "${pkgs.unbound}/sbin/unbound -d -c ${stateDir}/unbound.conf";
+        ExecStopPost="${pkgs.utillinux}/bin/umount ${stateDir}/dev/random";
+      };
     };
 
   };
diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix
index 4d53cd0750f..9b26b2b3244 100644
--- a/nixos/modules/services/networking/znc.nix
+++ b/nixos/modules/services/networking/znc.nix
@@ -25,85 +25,6 @@ let
     paths = cfg.modulePackages;
   };
 
-  confOptions = { ... }: {
-    options = {
-      modules = mkOption {
-        type = types.listOf types.string;
-        default = [ "partyline" "webadmin" "adminlog" "log" ];
-        example = [ "partyline" "webadmin" "adminlog" "log" ];
-        description = ''
-          A list of modules to include in the `znc.conf` file.
-        '';
-      };
-
-      userModules = mkOption {
-        type = types.listOf types.string;
-        default = [ ];
-        example = [ "fish" "push" ];
-        description = ''
-          A list of user modules to include in the `znc.conf` file.
-        '';
-      };
-
-      userName = mkOption {
-        default = defaultUserName;
-        example = "johntron";
-        type = types.string;
-        description = ''
-          The user name to use when generating the `znc.conf` file.
-          This is the user name used by the user logging into the ZNC web admin. 
-        '';
-      };
-
-      nick = mkOption {
-        default = "znc-user";
-        example = "john";
-        type = types.string;
-        description = ''
-          The IRC nick to use when generating the `znc.conf` file.
-        '';
-      };
-
-      passBlock = mkOption {
-        default = defaultPassBlock;
-        example = "Must be the block generated by the `znc --makepass` command.";
-        type = types.string;
-        description = ''
-          The pass block to use when generating the `znc.conf` file.
-          This is the password used by the user logging into the ZNC web admin.
-          This is the block generated by the `znc --makepass` command.
-          !!! If not specified, please change this after starting the service. !!!
-        '';
-      };
-
-      port = mkOption {
-        default = 5000;
-        example = 5000;
-        type = types.int;
-        description = ''
-          Specifies the port on which to listen.
-        '';
-      };
- 
-      useSSL = mkOption {
-        default = true;
-        example = true;
-        type = types.bool;
-        description = ''
-          Indicates whether the ZNC server should use SSL when listening on the specified port.
-        '';
-      };
-
-      extraZncConf = mkOption {
-        default = "";
-        type = types.lines;
-        description = ''
-          Extra config to `znc.conf` file
-        '';
-      };
-    };
-  };
-
   # Keep znc.conf in nix store, then symlink or copy into `dataDir`, depending on `mutable`.
   mkZncConf = confOpts: ''
     // Also check http://en.znc.in/wiki/Configuration
@@ -211,24 +132,97 @@ in
         '';
       };
 
-      confOptions = mkOption {
-        default = {};
-        example = {
-          modules = [ "log" ];
-          userName = "john";
-          nick = "johntron";
+      /* TODO: add to the documentation of the current module:
+
+         Values to use when creating a `znc.conf` file.
+
+           confOptions = {
+             modules = [ "log" ];
+             userName = "john";
+             nick = "johntron";
+           };
+      */
+      confOptions = {
+        modules = mkOption {
+          type = types.listOf types.string;
+          default = [ "partyline" "webadmin" "adminlog" "log" ];
+          example = [ "partyline" "webadmin" "adminlog" "log" ];
+          description = ''
+            A list of modules to include in the `znc.conf` file.
+          '';
+        };
+
+        userModules = mkOption {
+          type = types.listOf types.string;
+          default = [ ];
+          example = [ "fish" "push" ];
+          description = ''
+            A list of user modules to include in the `znc.conf` file.
+          '';
+        };
+
+        userName = mkOption {
+          default = defaultUserName;
+          example = "johntron";
+          type = types.string;
+          description = ''
+            The user name to use when generating the `znc.conf` file.
+            This is the user name used by the user logging into the ZNC web admin.
+          '';
+        };
+
+        nick = mkOption {
+          default = "znc-user";
+          example = "john";
+          type = types.string;
+          description = ''
+            The IRC nick to use when generating the `znc.conf` file.
+          '';
+        };
+
+        passBlock = mkOption {
+          default = defaultPassBlock;
+          example = "Must be the block generated by the `znc --makepass` command.";
+          type = types.string;
+          description = ''
+            The pass block to use when generating the `znc.conf` file.
+            This is the password used by the user logging into the ZNC web admin.
+            This is the block generated by the `znc --makepass` command.
+            !!! If not specified, please change this after starting the service. !!!
+          '';
+        };
+
+        port = mkOption {
+          default = 5000;
+          example = 5000;
+          type = types.int;
+          description = ''
+            Specifies the port on which to listen.
+          '';
+        };
+
+        useSSL = mkOption {
+          default = true;
+          example = true;
+          type = types.bool;
+          description = ''
+            Indicates whether the ZNC server should use SSL when listening on the specified port.
+          '';
+        };
+
+        extraZncConf = mkOption {
+          default = "";
+          type = types.lines;
+          description = ''
+            Extra config to `znc.conf` file
+          '';
         };
-        type = types.optionSet;
-        description = ''
-          Values to use when creating a `znc.conf` file.
-        '';
-        options = confOptions; 
       };
 
       modulePackages = mkOption {
         type = types.listOf types.package;
         default = [ ];
-        example = [ pkgs.zncModules.fish pkgs.zncModules.push ];
+        example = literalExample "[ pkgs.zncModules.fish pkgs.zncModules.push ]";
         description = ''
           A list of global znc module packages to add to znc.
         '';
@@ -280,20 +274,16 @@ in
 
         # If mutable, regenerate conf file every time.
         ${optionalString (!cfg.mutable) ''
-          ${pkgs.coreutils}/echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated."
-          ${pkgs.coreutils}/rm -f ${cfg.dataDir}/configs/znc.conf
+          ${pkgs.coreutils}/bin/echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated."
+          ${pkgs.coreutils}/bin/rm -f ${cfg.dataDir}/configs/znc.conf
         ''}
 
         # Ensure essential files exist.
         if [[ ! -f ${cfg.dataDir}/configs/znc.conf ]]; then
-          ${pkgs.coreutils}/bin/echo "No znc.conf file found in ${cfg.dataDir}. Creating one now."
-          ${if (!cfg.mutable)
-            then "${pkgs.coreutils}/bin/ln --force -s ${zncConfFile} ${cfg.dataDir}/.znc/configs/znc.conf"
-            else ''
-              ${pkgs.coreutils}/bin/cp --no-clobber ${zncConfFile} ${cfg.dataDir}/configs/znc.conf
-              ${pkgs.coreutils}/bin/chmod u+rw ${cfg.dataDir}/configs/znc.conf
-              ${pkgs.coreutils}/bin/chown ${cfg.user} ${cfg.dataDir}/configs/znc.conf
-            ''}
+            ${pkgs.coreutils}/bin/echo "No znc.conf file found in ${cfg.dataDir}. Creating one now."
+            ${pkgs.coreutils}/bin/cp --no-clobber ${zncConfFile} ${cfg.dataDir}/configs/znc.conf
+            ${pkgs.coreutils}/bin/chmod u+rw ${cfg.dataDir}/configs/znc.conf
+            ${pkgs.coreutils}/bin/chown ${cfg.user} ${cfg.dataDir}/configs/znc.conf
         fi
 
         if [[ ! -f ${cfg.dataDir}/znc.pem ]]; then
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index d229c610669..8a8085cad28 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -35,7 +35,7 @@ let
   bindir = pkgs.buildEnv {
     name = "cups-progs";
     paths = cfg.drivers;
-    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" ];
+    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" "/etc/cups" ];
     postBuild = cfg.bindirCmds;
   };
 
@@ -89,6 +89,20 @@ in
         '';
       };
 
+      clientConf = mkOption {
+        type = types.lines;
+        default = "";
+        example =
+          ''
+            ServerName server.example.com
+            Encryption Never
+          '';
+        description = ''
+          The contents of the client configuration.
+          (<filename>client.conf</filename>)
+        '';
+      };
+
       drivers = mkOption {
         type = types.listOf types.path;
         example = literalExample "[ pkgs.splix ]";
@@ -124,6 +138,14 @@ in
 
     environment.systemPackages = [ cups ];
 
+    environment.variables.CUPS_SERVERROOT = "/etc/cups";
+
+    environment.etc = [
+      { source = pkgs.writeText "client.conf" cfg.clientConf;
+        target = "cups/client.conf";
+      }
+    ];
+
     services.dbus.packages = [ cups ];
 
     # Cups uses libusb to talk to printers, and does not use the
diff --git a/nixos/modules/services/security/clamav.nix b/nixos/modules/services/security/clamav.nix
index 057891a6047..a4d54301fc1 100644
--- a/nixos/modules/services/security/clamav.nix
+++ b/nixos/modules/services/security/clamav.nix
@@ -71,10 +71,10 @@ in
             mkdir -m 0755 -p ${stateDir}
             chown ${clamavUser}:${clamavGroup} ${stateDir}
           '';
-          exec = "${pkgs.clamav}/bin/freshclam --config-file=${pkgs.writeText "freshclam.conf" cfg.updater.config}";
+          exec = "${pkgs.clamav}/bin/freshclam --daemon --config-file=${pkgs.writeText "freshclam.conf" cfg.updater.config}";
       }; 
     };
 
   };
 
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix
index df21ebbd974..3958be33df2 100644
--- a/nixos/modules/services/ttys/agetty.nix
+++ b/nixos/modules/services/ttys/agetty.nix
@@ -66,6 +66,13 @@ with lib;
         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.Restart = "always";
+        restartIfChanged = false;
+	enable = mkDefault config.boot.isContainer;
+      };
+
     environment.etc = singleton
       { # Friendly greeting on the virtual consoles.
         source = pkgs.writeText "issue" ''
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 78f3cf2b7e4..9ac28373dac 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -130,7 +130,7 @@ let
   '';
 
 
-  loggingConf = ''
+  loggingConf = (if mainCfg.logFormat != "none" then ''
     ErrorLog ${mainCfg.logDir}/error_log
 
     LogLevel notice
@@ -141,7 +141,9 @@ let
     LogFormat "%{User-agent}i" agent
 
     CustomLog ${mainCfg.logDir}/access_log ${mainCfg.logFormat}
-  '';
+  '' else ''
+    ErrorLog /dev/null
+  '');
 
 
   browserHacks = ''
@@ -421,7 +423,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.apacheHttpd.override { mpm = mainCfg.multiProcessingModule; };
-        example = "pkgs.apacheHttpd_2_4";
+        example = literalExample "pkgs.apacheHttpd_2_4";
         description = ''
           Overridable attribute of the Apache HTTP Server package to use.
         '';
diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
index aa9aec87f0c..bb066aa6c47 100644
--- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
@@ -133,6 +133,7 @@ in
         RewriteEngine On
         RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
         RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
+        ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedDirs}
         RewriteRule ${if config.enableUploads
           then "!^/images"
           else "^.*\$"
diff --git a/nixos/modules/services/web-servers/apache-httpd/phabricator.nix b/nixos/modules/services/web-servers/apache-httpd/phabricator.nix
index c7a9bdf68c5..e4e3aac8d41 100644
--- a/nixos/modules/services/web-servers/apache-httpd/phabricator.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/phabricator.nix
@@ -1,35 +1,30 @@
 { config, lib, pkgs, ... }:
+
+with lib;
+
 let
-  phabricatorRoot = pkgs.stdenv.mkDerivation rec {
-    version = "2014-05-12";
-    name = "phabricator-${version}";
-    srcLibphutil = pkgs.fetchgit {
-        url = git://github.com/facebook/libphutil.git;
-        rev = "2f3b5a1cf6ea464a0250d4b1c653a795a90d2716";
-        sha256 = "9598cec400984dc149162f1e648814a54ea0cd34fcd529973dc83f5486fdd9fd";
-    };
-    srcArcanist = pkgs.fetchgit {
-        url = git://github.com/facebook/arcanist.git;
-        rev = "54c377448db8dbc40f0ca86d43c837d30e493485";
-        sha256 = "086db3c0d1154fbad23e7c6def31fd913384ee20247b329515838b669c3028e0";
-    };
-    srcPhabricator = pkgs.fetchgit {
-        url = git://github.com/facebook/phabricator.git;
-        rev = "1644ef185ecf1e9fca3eb6b16351ef46b19d110f";
-        sha256 = "e1135e4ba76d53f48aad4161563035414ed7e878f39a8a34a875a01b41b2a084";
-    };
-    
-    buildCommand = ''
-      mkdir -p $out
-      cp -R ${srcLibphutil} $out/libphutil
-      cp -R ${srcArcanist} $out/arcanist
-      cp -R ${srcPhabricator} $out/phabricator
-    '';
-  };
+  phabricatorRoot = pkgs.phabricator;
 in {
+
   enablePHP = true;
   extraApacheModules = [ "mod_rewrite" ];
   DocumentRoot = "${phabricatorRoot}/phabricator/webroot";
+
+  options = {
+      git = mkOption {
+          default = true;
+          description = "Enable git repositories.";
+      };
+      mercurial = mkOption {
+          default = true;
+          description = "Enable mercurial repositories.";
+      };
+      subversion = mkOption {
+          default = true;
+          description = "Enable subversion repositories.";
+      };
+  };
+
   extraConfig = ''
       DocumentRoot ${phabricatorRoot}/phabricator/webroot
 
@@ -38,4 +33,18 @@ in {
       RewriteRule ^/favicon.ico - [L,QSA]
       RewriteRule ^(.*)$ /index.php?__path__=$1 [B,L,QSA]
   '';
+
+  extraServerPath = [
+      "${pkgs.which}"
+      "${pkgs.diffutils}"
+      ] ++
+      (if config.mercurial then ["${pkgs.mercurial}"] else []) ++
+      (if config.subversion then ["${pkgs.subversion}"] else []) ++
+      (if config.git then ["${pkgs.git}"] else []);
+
+  startupScript = pkgs.writeScript "activatePhabricator" ''
+      mkdir -p /var/repo
+      chown wwwrun /var/repo
+  '';
+
 }
diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix
index c2f464014ae..2af249a8e96 100644
--- a/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixos/modules/services/web-servers/tomcat.nix
@@ -5,7 +5,7 @@ with lib;
 let
 
   cfg = config.services.tomcat;
-  tomcat = pkgs.tomcat6;
+  tomcat = pkgs.tomcat7;
 in
 
 {
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 06bcb6dbb8b..049c96c54e7 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -37,7 +37,7 @@ in {
 
     services.xserver.desktopManager.gnome3.sessionPath = mkOption {
       default = [];
-      example = "[ pkgs.gnome3.gpaste ]";
+      example = literalExample "[ pkgs.gnome3.gpaste ]";
       description = "Additional list of packages to be added to the session search path.
                      Useful for gnome shell extensions or gsettings-conditionated autostart.";
       apply = list: list ++ [ gnome3.gnome_shell ]; 
@@ -51,7 +51,7 @@ in {
     
     environment.gnome3.excludePackages = mkOption {
       default = [];
-      example = "[ pkgs.gnome3.totem ]";
+      example = literalExample "[ pkgs.gnome3.totem ]";
       type = types.listOf types.package;
       description = "Which packages gnome should exclude from the default environment";
     };
diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix
index f74dd7e0444..669ddbd904f 100644
--- a/nixos/modules/services/x11/desktop-managers/kde4.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde4.nix
@@ -65,7 +65,7 @@ in
 
     environment.kdePackages = mkOption {
       default = [];
-      example = "[ pkgs.kde4.kdesdk ]";
+      example = literalExample "[ pkgs.kde4.kdesdk ]";
       type = types.listOf types.package;
       description = "This option is obsolete.  Please use <option>environment.systemPackages</option> instead.";
     };
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 3bf18bd58c8..6e61576f501 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -251,14 +251,16 @@ in
 
         execCmd = mkOption {
           type = types.str;
-          example = "${pkgs.slim}/bin/slim";
+          example = literalExample ''
+            "''${pkgs.slim}/bin/slim"
+          '';
           description = "Command to start the display manager.";
         };
 
         environment = mkOption {
           type = types.attrsOf types.unspecified;
           default = {};
-          example = { SLIM_CFGFILE = /etc/slim.conf; };
+          example = { SLIM_CFGFILE = "/etc/slim.conf"; };
           description = "Additional environment variables needed by the display manager.";
         };
 
diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix
index 9ee4e0dc7cb..c7fbfa85e33 100644
--- a/nixos/modules/services/x11/display-managers/slim.nix
+++ b/nixos/modules/services/x11/display-managers/slim.nix
@@ -19,6 +19,7 @@ let
       reboot_cmd ${config.systemd.package}/sbin/shutdown -r now
       ${optionalString (cfg.defaultUser != null) ("default_user " + cfg.defaultUser)}
       ${optionalString cfg.autoLogin "auto_login yes"}
+      ${cfg.extraConfig}
     '';
 
   # Unpack the SLiM theme, or use the default.
@@ -89,6 +90,15 @@ in
         '';
       };
 
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra configuration options for SLiM login manager. Do not
+          add options that can be configured directly.
+        '';
+      };
+
     };
 
   };
diff --git a/nixos/modules/services/x11/window-managers/fluxbox.nix b/nixos/modules/services/x11/window-managers/fluxbox.nix
new file mode 100644
index 00000000000..4748ce99ccf
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/fluxbox.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.fluxbox;
+in
+{
+  ###### interface
+  options = {
+    services.xserver.windowManager.fluxbox.enable = mkOption {
+      default = false;
+      description = "Enable the Fluxbox window manager.";
+    };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "fluxbox";
+      start = ''
+        ${pkgs.fluxbox}/bin/startfluxbox &
+        waitPID=$!
+      '';
+    };
+    environment.systemPackages = [ pkgs.fluxbox ];
+  };
+}
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 5f3e8003b45..21eaf6bb6b7 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -151,7 +151,7 @@ in
       modules = mkOption {
         type = types.listOf types.path;
         default = [];
-        example = [ pkgs.xf86_input_wacom ];
+        example = literalExample "[ pkgs.xf86_input_wacom ]";
         description = "Packages to be added to the module search path of the X server.";
       };
 
@@ -201,7 +201,7 @@ in
       vaapiDrivers = mkOption {
         type = types.listOf types.path;
         default = [ ];
-        example = "[ pkgs.vaapiIntel pkgs.vaapiVdpau ]";
+        example = literalExample "[ pkgs.vaapiIntel pkgs.vaapiVdpau ]";
         description = ''
           Packages providing libva acceleration drivers.
         '';
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index 9beb7fabce1..79b173a6ead 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -195,6 +195,7 @@ in
         "xhci_hcd"
         "usbhid"
         "hid_generic"
+        "hid_apple" "hid_logitech_dj" "hid_lenovo_tpkbd" "hid_roccat"
 
         # Unix domain sockets (needed by udev).
         "unix"
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index 0cc060db8f9..bc9a155ac95 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -6,7 +6,8 @@ let
 
   cfg = config.boot.loader.grub;
 
-  realGrub = if cfg.version == 1 then pkgs.grub else pkgs.grub2;
+  realGrub = if cfg.version == 1 then pkgs.grub
+    else pkgs.grub2.override { zfsSupport = cfg.zfsSupport; };
 
   grub =
     # Don't include GRUB if we're only generating a GRUB menu (e.g.,
@@ -25,11 +26,12 @@ let
       inherit (cfg)
         version extraConfig extraPerEntryConfig extraEntries
         extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout
-        default devices explicitBootRoot;
+        default devices fsIdentifier;
       path = (makeSearchPath "bin" [
-        pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils
+        pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfsProgs
+        pkgs.utillinux
       ]) + ":" + (makeSearchPath "sbin" [
-        pkgs.mdadm
+        pkgs.mdadm pkgs.utillinux
       ]);
     });
 
@@ -209,12 +211,26 @@ in
         '';
       };
 
-      explicitBootRoot = mkOption {
-        default = "";
-        type = types.str;
+      fsIdentifier = mkOption {
+        default = "uuid";
+        type = types.addCheck types.str
+          (type: type == "uuid" || type == "label" || type == "provided");
         description = ''
-          The relative path of /boot within the parent volume. Leave empty
-          if /boot is not a btrfs subvolume.
+          Determines how grub will identify devices when generating the
+          configuration file. A value of uuid / label signifies that grub
+          will always resolve the uuid or label of the device before using
+          it in the configuration. A value of provided means that grub will
+          use the device name as show in <command>df</command> or
+          <command>mount</command>. Note, zfs zpools / datasets are ignored
+          and will always be mounted using their labels.
+        '';
+      };
+
+      zfsSupport = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether grub should be build against libzfs.
         '';
       };
 
@@ -260,6 +276,9 @@ in
           ${pkgs.coreutils}/bin/cp -pf "${v}" "/boot/${n}"
         '') config.boot.loader.grub.extraFiles);
 
+    assertions = [{ assertion = !cfg.zfsSupport || cfg.version == 2;
+                    message = "Only grub version 2 provides zfs support";}];
+
     })
 
   ];
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index c3aa8518b8b..2dad8b36db3 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -1,5 +1,6 @@
 use strict;
 use warnings;
+use Class::Struct;
 use XML::LibXML;
 use File::Basename;
 use File::Path;
@@ -27,6 +28,14 @@ sub writeFile {
     close FILE or die;
 }
 
+sub runCommand {
+    my ($cmd) = @_;
+    open FILE, "$cmd 2>/dev/null |" or die "Failed to execute: $cmd\n";
+    my @ret = <FILE>;
+    close FILE;
+    return ($?, @ret);
+}
+
 my $grub = get("grub");
 my $grubVersion = int(get("version"));
 my $extraConfig = get("extraConfig");
@@ -39,7 +48,7 @@ my $configurationLimit = int(get("configurationLimit"));
 my $copyKernels = get("copyKernels") eq "true";
 my $timeout = int(get("timeout"));
 my $defaultEntry = int(get("default"));
-my $explicitBootRoot = get("explicitBootRoot");
+my $fsIdentifier = get("fsIdentifier");
 $ENV{'PATH'} = get("path");
 
 die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
@@ -48,24 +57,114 @@ print STDERR "updating GRUB $grubVersion menu...\n";
 
 mkpath("/boot/grub", 0, 0700);
 
-
 # Discover whether /boot is on the same filesystem as / and
 # /nix/store.  If not, then all kernels and initrds must be copied to
-# /boot, and all paths in the GRUB config file must be relative to the
-# root of the /boot filesystem.  `$bootRoot' is the path to be
-# prepended to paths under /boot.
-my $bootRoot = "/boot";
-if (stat("/")->dev != stat("/boot")->dev) {
-    $bootRoot = "";
-    $copyKernels = 1;
-} elsif (stat("/boot")->dev != stat("/nix/store")->dev) {
+# /boot.
+if (stat("/boot")->dev != stat("/nix/store")->dev) {
     $copyKernels = 1;
 }
 
-if ($explicitBootRoot ne "") {
-    $bootRoot = $explicitBootRoot;
+# Discover information about the location of /boot
+struct(Fs => {
+    device => '$',
+    type => '$',
+    mount => '$',
+});
+sub GetFs {
+    my ($dir) = @_;
+    my ($status, @dfOut) = runCommand("df -T $dir");
+    if ($status != 0 || $#dfOut != 1) {
+        die "Failed to retrieve output about $dir from `df`";
+    }
+    my @boot = split(/[ \n\t]+/, $dfOut[1]);
+    return Fs->new(device => $boot[0], type => $boot[1], mount => $boot[6]);
 }
-
+struct (Grub => {
+    path => '$',
+    search => '$',
+});
+my $driveid = 1;
+sub GrubFs {
+    my ($dir) = @_;
+    my $fs = GetFs($dir);
+    my $path = "/" . substr($dir, length($fs->mount));
+    my $search = "";
+
+    if ($grubVersion > 1) {
+        # ZFS is completely separate logic as zpools are always identified by a label
+        # or custom UUID
+        if ($fs->type eq 'zfs') {
+            my $sid = index($fs->device, '/');
+
+            if ($sid < 0) {
+                $search = '--label ' . $fs->device;
+                $path = '/@' . $path;
+            } else {
+                $search = '--label ' . substr($fs->device, 0, $sid);
+                $path = '/' . substr($fs->device, $sid) . '/@' . $path;
+            }
+        } else {
+            my %types = ('uuid' => '--fs-uuid', 'label' => '--label');
+
+            if ($fsIdentifier eq 'provided') {
+                # If the provided dev is identifying the partition using a label or uuid,
+                # we should get the label / uuid and do a proper search
+                my @matches = $fs->device =~ m/\/dev\/disk\/by-(label|uuid)\/(.*)/;
+                if ($#matches > 1) {
+                    die "Too many matched devices"
+                } elsif ($#matches == 1) {
+                    $search = "$types{$matches[0]} $matches[1]"
+                }
+            } else {
+                # Determine the identifying type
+                $search = $types{$fsIdentifier} . ' ';
+
+                # Based on the type pull in the identifier from the system
+                my ($status, @devInfo) = runCommand("blkid -o export @{[$fs->device]}");
+                if ($status != 0) {
+                    die "Failed to get blkid info for @{[$fs->mount]} on @{[$fs->device]}";
+                }
+                my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/;
+                if ($#matches != 0) {
+                    die "Couldn't find a $types{$fsIdentifier} for @{[$fs->device]}\n"
+                }
+                $search .= $matches[0];
+            }
+
+            # BTRFS is a special case in that we need to fix the referrenced path based on subvolumes
+            if ($fs->type eq 'btrfs') {
+                my ($status, @id_info) = runCommand("btrfs subvol show @{[$fs->mount]}");
+                if ($status != 0) {
+                    die "Failed to retrieve subvolume info for @{[$fs->mount]}\n";
+                }
+                my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/;
+                if ($#ids > 0) {
+                    die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n"
+                } elsif ($#ids == 0) {
+                    my ($status, @path_info) = runCommand("btrfs subvol list @{[$fs->mount]}");
+                    if ($status != 0) {
+                        die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n";
+                    }
+                    my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/;
+                    if ($#paths > 0) {
+                        die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n";
+                    } elsif ($#paths != 0) {
+                        die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n";
+                    }
+                    $path = "/$paths[0]$path";
+                }
+            }
+        }
+        if (not $search eq "") {
+            $search = "search --set=drive$driveid " . $search;
+            $path = "(\$drive$driveid)$path";
+            $driveid += 1;
+        }
+    }
+    return Grub->new(path => $path, search => $search);
+}
+my $grubBoot = GrubFs("/boot");
+my $grubStore = GrubFs("/nix/store");
 
 # Generate the header.
 my $conf .= "# Automatically generated.  DO NOT EDIT THIS FILE!\n";
@@ -77,12 +176,17 @@ if ($grubVersion == 1) {
     ";
     if ($splashImage) {
         copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n";
-        $conf .= "splashimage $bootRoot/background.xpm.gz\n";
+        $conf .= "splashimage " . $grubBoot->path . "/background.xpm.gz\n";
     }
 }
 
 else {
+    if ($copyKernels == 0) {
+        $conf .= "
+            " . $grubStore->search;
+    }
     $conf .= "
+        " . $grubBoot->search . "
         if [ -s \$prefix/grubenv ]; then
           load_env
         fi
@@ -103,7 +207,7 @@ else {
           set timeout=$timeout
         fi
 
-        if loadfont $bootRoot/grub/fonts/unicode.pf2; then
+        if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then
           set gfxmode=640x480
           insmod gfxterm
           insmod vbe
@@ -117,7 +221,7 @@ else {
         copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n";
         $conf .= "
             insmod png
-            if background_image $bootRoot/background.png; then
+            if background_image " . $grubBoot->path . "/background.png; then
               set color_normal=white/black
               set color_highlight=black/white
             else
@@ -139,7 +243,7 @@ mkpath("/boot/kernels", 0, 0755) if $copyKernels;
 
 sub copyToKernelsDir {
     my ($path) = @_;
-    return $path unless $copyKernels;
+    return $grubStore->path . substr($path, length("/nix/store")) unless $copyKernels;
     $path =~ /\/nix\/store\/(.*)/ or die;
     my $name = $1; $name =~ s/\//-/g;
     my $dst = "/boot/kernels/$name";
@@ -152,7 +256,7 @@ sub copyToKernelsDir {
         rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
     }
     $copied{$dst} = 1;
-    return "$bootRoot/kernels/$name";
+    return $grubBoot->path . "/kernels/$name";
 }
 
 sub addEntry {
@@ -179,6 +283,10 @@ sub addEntry {
         $conf .= "  " . ($xen ? "module" : "initrd") . " $initrd\n\n";
     } else {
         $conf .= "menuentry \"$name\" {\n";
+        $conf .= $grubBoot->search . "\n";
+        if ($copyKernels == 0) {
+            $conf .= $grubStore->search . "\n";
+        }
         $conf .= "  $extraPerEntryConfig\n" if $extraPerEntryConfig;
         $conf .= "  multiboot $xen $xenParams\n" if $xen;
         $conf .= "  " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";
@@ -196,7 +304,7 @@ addEntry("NixOS - Default", $defaultConfig);
 $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
 
 # extraEntries could refer to @bootRoot@, which we have to substitute
-$conf =~ s/\@bootRoot\@/$bootRoot/g;
+$conf =~ s/\@bootRoot\@/$grubBoot->path/g;
 
 # Emit submenus for all system profiles.
 sub addProfile {
diff --git a/nixos/modules/system/boot/loader/gummiboot/gummiboot.nix b/nixos/modules/system/boot/loader/gummiboot/gummiboot.nix
index e7a481e90a7..003f72b37f9 100644
--- a/nixos/modules/system/boot/loader/gummiboot/gummiboot.nix
+++ b/nixos/modules/system/boot/loader/gummiboot/gummiboot.nix
@@ -16,7 +16,7 @@ let
 
     nix = config.nix.package;
 
-    inherit (cfg) timeout;
+    timeout = if cfg.timeout != null then cfg.timeout else "";
 
     inherit (efi) efiSysMountPoint canTouchEfiVariables;
   };
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index c923cc49c44..70ff1d588a3 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -342,40 +342,39 @@ in
               description = "Path where the ramfs used to update the LUKS key will be mounted in stage-1";
             };
 
-            storage = mkOption {
-              type = types.optionSet;
-              description = "Options related to the storing the salt";
-
-              options = {
-                device = mkOption {
-                  default = /dev/sda1;
-                  type = types.path;
-                  description = ''
-                    An unencrypted device that will temporarily be mounted in stage-1.
-                    Must contain the current salt to create the challenge for this LUKS device.
-                  '';
-                };
-
-                fsType = mkOption {
-                  default = "vfat";
-                  type = types.string;
-                  description = "The filesystem of the unencrypted device";
-                };
-
-                mountPoint = mkOption {
-                  default = "/crypt-storage";
-                  type = types.string;
-                  description = "Path where the unencrypted device will be mounted in stage-1";
-                };
-
-                path = mkOption {
-                  default = "/crypt-storage/default";
-                  type = types.string;
-                  description = ''
-                    Absolute path of the salt on the unencrypted device with
-                    that device's root directory as "/".
-                  '';
-                };
+            /* TODO: Add to the documentation of the current module:
+
+               Options related to the storing the salt.
+            */
+            storage = {
+              device = mkOption {
+                default = "/dev/sda1";
+                type = types.path;
+                description = ''
+                  An unencrypted device that will temporarily be mounted in stage-1.
+                  Must contain the current salt to create the challenge for this LUKS device.
+                '';
+              };
+
+              fsType = mkOption {
+                default = "vfat";
+                type = types.string;
+                description = "The filesystem of the unencrypted device";
+              };
+
+              mountPoint = mkOption {
+                default = "/crypt-storage";
+                type = types.string;
+                description = "Path where the unencrypted device will be mounted in stage-1";
+              };
+
+              path = mkOption {
+                default = "/crypt-storage/default";
+                type = types.string;
+                description = ''
+                  Absolute path of the salt on the unencrypted device with
+                  that device's root directory as "/".
+                '';
               };
             };
           };
diff --git a/nixos/modules/system/boot/modprobe.nix b/nixos/modules/system/boot/modprobe.nix
index 652eb046f50..eaf8cf1ecd6 100644
--- a/nixos/modules/system/boot/modprobe.nix
+++ b/nixos/modules/system/boot/modprobe.nix
@@ -77,6 +77,11 @@ with lib;
         '')}
         ${config.boot.extraModprobeConfig}
       '';
+    environment.etc."modprobe.d/usb-load-ehci-first.conf".text =
+      ''
+        softdep uhci_hcd pre: ehci_hcd
+        softdep ohci_hcd pre: ehci_hcd
+      '';
 
     environment.systemPackages = [ config.system.sbin.modprobe pkgs.kmod ];
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 6a069c5d054..426da778f43 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -199,6 +199,18 @@ let
         { object = pkgs.writeText "mdadm.conf" config.boot.initrd.mdadmConf;
           symlink = "/etc/mdadm.conf";
         }
+        { object = pkgs.stdenv.mkDerivation {
+            name = "initrd-kmod-blacklist-ubuntu";
+            builder = pkgs.writeText "builder.sh" ''
+              source $stdenv/setup
+              target=$out
+
+              ${pkgs.perl}/bin/perl -0pe 's/## file: iwlwifi.conf(.+?)##/##/s;' $src > $out
+            '';
+            src = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf";
+          };
+          symlink = "/etc/modprobe.d/ubuntu.conf";
+        }
       ];
   };
 
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index fcefdfa88a3..6fff776f858 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -29,7 +29,9 @@ setPath "@path@"
 # Normally, stage 1 mounts the root filesystem read/writable.
 # However, in some environments, stage 2 is executed directly, and the
 # root is read-only.  So make it writable here.
-mount -n -o remount,rw none /
+if [ "$container" != systemd-nspawn ]; then
+    mount -n -o remount,rw none /
+fi
 
 
 # Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 455c40693b0..e353e9246b0 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -744,7 +744,7 @@ in
         # Make all journals readable to users in the wheel and adm
         # groups, in addition to those in the systemd-journal group.
         # Users can always read their own journals.
-        ${pkgs.acl}/bin/setfacl -nm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal
+        ${pkgs.acl}/bin/setfacl -nm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal || true
       '';
 
     # Target for ‘charon send-keys’ to hook into.
diff --git a/nixos/modules/tasks/cpu-freq.nix b/nixos/modules/tasks/cpu-freq.nix
index a8c63c13428..70bbee8474e 100644
--- a/nixos/modules/tasks/cpu-freq.nix
+++ b/nixos/modules/tasks/cpu-freq.nix
@@ -30,9 +30,7 @@ in
 
   config = mkIf (!config.boot.isContainer && config.powerManagement.cpuFreqGovernor != null) {
 
-    boot.kernelModules = [ "acpi-cpufreq" "speedstep-lib" "pcc-cpufreq"
-      "cpufreq_${cfg.cpuFreqGovernor}"
-    ];
+    boot.kernelModules = [ "cpufreq_${cfg.cpuFreqGovernor}" ];
 
     environment.systemPackages = [ cpupower ];
 
diff --git a/nixos/modules/tasks/filesystems/nfs.nix b/nixos/modules/tasks/filesystems/nfs.nix
index e8c3d8ab56d..c902b9e0790 100644
--- a/nixos/modules/tasks/filesystems/nfs.nix
+++ b/nixos/modules/tasks/filesystems/nfs.nix
@@ -24,13 +24,37 @@ let
     Method = nsswitch
   '';
 
+  cfg = config.services.nfs;
+
 in
 
 {
+  ###### interface
+
+  options = {
+
+    services.nfs = {
+      statdPort = mkOption {
+        default = null;
+        example = 4000;
+        description = ''
+          Use fixed port for rpc.statd, usefull if NFS server is behind firewall.
+        '';
+      };
+      lockdPort = mkOption {
+        default = null;
+        example = 4001;
+        description = ''
+          Use fixed port for NFS lock manager kernel module (lockd/nlockmgr),
+          usefull if NFS server is behind firewall.
+        '';
+      };
+    };
+  };
 
   ###### implementation
 
-  config = mkIf (any (fs: fs == "nfs" || fs == "nfs4") config.boot.supportedFilesystems) {
+  config = mkIf (any (fs: fs == "nfs" || fs == "nfs4") config.boot.supportedFilesystems) ({
 
     services.rpcbind.enable = true;
 
@@ -60,7 +84,10 @@ in
           '';
 
         serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = "@${pkgs.nfsUtils}/sbin/rpc.statd rpc.statd --no-notify";
+        serviceConfig.ExecStart = ''
+          @${pkgs.nfsUtils}/sbin/rpc.statd rpc.statd --no-notify \
+              ${if cfg.statdPort != null then "-p ${toString statdPort}" else ""}
+        '';
         serviceConfig.Restart = "always";
       };
 
@@ -90,5 +117,9 @@ in
         serviceConfig.Restart = "always";
       };
 
-  };
+  } // mkIf (cfg.lockdPort != null) {
+    boot.extraModprobeConfig = ''
+      options lockd nlm_udpport=${toString cfg.lockdPort} nlm_tcpport=${toString cfg.lockdPort}
+    '';
+  });
 }
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index d7deb44c407..1c4bbc16b49 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -133,7 +133,7 @@ in
       };
 
       boot.initrd = mkIf inInitrd {
-        kernelModules = [ "spl" "zfs" ] ;
+        kernelModules = [ "spl" "zfs" ];
         extraUtilsCommands =
           ''
             cp -v ${zfsPkg}/sbin/zfs $out/bin
@@ -148,6 +148,10 @@ in
           '';
       };
 
+      boot.loader.grub = mkIf inInitrd {
+        zfsSupport = true;
+      };
+
       systemd.services."zpool-import" = {
         description = "Import zpools";
         after = [ "systemd-udev-settle.service" ];
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 991f9f26145..868039177d8 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -1,14 +1,40 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, utils, ... }:
 
 with lib;
+with utils;
 
 let
 
   cfg = config.networking;
   interfaces = attrValues cfg.interfaces;
   hasVirtuals = any (i: i.virtual) interfaces;
+  hasSits = cfg.sits != { };
   hasBonds = cfg.bonds != { };
 
+  # We must escape interfaces due to the systemd interpretation
+  subsystemDevice = interface:
+    "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
+
+  addrOpts = v:
+    assert v == 4 || v == 6;
+    {
+      address = mkOption {
+        type = types.str;
+        description = ''
+          IPv${toString v} address of the interface.  Leave empty to configure the
+          interface using DHCP.
+        '';
+      };
+
+      prefixLength = mkOption {
+        type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128));
+        description = ''
+          Subnet mask of the interface, specified as the number of
+          bits in the prefix (<literal>${if v == 4 then "24" else "64"}</literal>).
+        '';
+      };
+    };
+
   interfaceOpts = { name, ... }: {
 
     options = {
@@ -19,10 +45,36 @@ let
         description = "Name of the interface.";
       };
 
+      ip4 = mkOption {
+        default = [ ];
+        example = [
+          { address = "10.0.0.1"; prefixLength = 16; }
+          { address = "192.168.1.1"; prefixLength = 24; }
+        ];
+        type = types.listOf types.optionSet;
+        options = addrOpts 4;
+        description = ''
+          List of IPv4 addresses that will be statically assigned to the interface.
+        '';
+      };
+
+      ip6 = mkOption {
+        default = [ ];
+        example = [
+          { address = "fdfd:b3f0:482::1"; prefixLength = 48; }
+          { address = "2001:1470:fffd:2098::e006"; prefixLength = 64; }
+        ];
+        type = types.listOf types.optionSet;
+        options = addrOpts 6;
+        description = ''
+          List of IPv6 addresses that will be statically assigned to the interface.
+        '';
+      };
+
       ipAddress = mkOption {
         default = null;
         example = "10.0.0.1";
-        type = types.nullOr (types.str);
+        type = types.nullOr types.str;
         description = ''
           IP address of the interface.  Leave empty to configure the
           interface using DHCP.
@@ -40,20 +92,16 @@ let
       };
 
       subnetMask = mkOption {
-        default = "";
-        example = "255.255.255.0";
-        type = types.str;
+        default = null;
         description = ''
-          Subnet mask of the interface, specified as a bitmask.
-          This is deprecated; use <option>prefixLength</option>
-          instead.
+          Defunct, supply the prefix length instead.
         '';
       };
 
       ipv6Address = mkOption {
         default = null;
         example = "2001:1470:fffd:2098::e006";
-        type = types.nullOr types.string;
+        type = types.nullOr types.str;
         description = ''
           IPv6 address of the interface.  Leave empty to configure the
           interface using NDP.
@@ -95,8 +143,6 @@ let
           Whether this interface is virtual and should be created by tunctl.
           This is mainly useful for creating bridges between a host a virtual
           network such as VPN or a virtual machine.
-
-          Defaults to tap device, unless interface contains "tun" in its name.
         '';
       };
 
@@ -108,6 +154,15 @@ let
         '';
       };
 
+      virtualType = mkOption {
+        default = null;
+        type = types.nullOr (types.addCheck types.str (v: v == "tun" || v == "tap"));
+        description = ''
+          The explicit type of interface to create. Accepts tun or tap strings.
+          Also accepts null to implicitly detect the type of device.
+        '';
+      };
+
       proxyARP = mkOption {
         default = false;
         type = types.bool;
@@ -223,10 +278,10 @@ in
     networking.interfaces = mkOption {
       default = {};
       example =
-        { eth0 = {
-            ipAddress = "131.211.84.78";
-            subnetMask = "255.255.255.128";
-          };
+        { eth0.ip4 = [ {
+            address = "131.211.84.78";
+            prefixLength = 25;
+          } ];
         };
       description = ''
         The configuration for each network interface.  If
@@ -321,6 +376,66 @@ in
       };
     };
 
+    networking.sits = mkOption {
+      type = types.attrsOf types.optionSet;
+      default = { };
+      example = {
+        hurricane = {
+          remote = "10.0.0.1";
+          local = "10.0.0.22";
+          ttl = 255;
+        };
+        msipv6 = {
+          remote = "192.168.0.1";
+          dev = "enp3s0";
+          ttl = 127;
+        };
+      };
+      description = ''
+        This option allows you to define 6-to-4 interfaces which should be automatically created.
+      '';
+      options = {
+
+        remote = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          example = "10.0.0.1";
+          description = ''
+            The address of the remote endpoint to forward traffic over.
+          '';
+        };
+
+        local = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          example = "10.0.0.22";
+          description = ''
+            The address of the local endpoint which the remote
+            side should send packets to.
+          '';
+        };
+
+        ttl = mkOption {
+          type = types.nullOr types.int;
+          default = null;
+          example = 255;
+          description = ''
+            The time-to-live of the connection to the remote tunnel endpoint.
+          '';
+        };
+
+        dev = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          example = "enp4s0f0";
+          description = ''
+            The underlying network device on which the tunnel resides.
+          '';
+        };
+
+      };
+    };
+
     networking.vlans = mkOption {
       default = { };
       example = {
@@ -377,9 +492,16 @@ in
 
   config = {
 
+    assertions =
+      flip map interfaces (i: {
+        assertion = i.subnetMask == null;
+        message = "The networking.interfaces.${i.name}.subnetMask option is defunct. Use prefixLength instead.";
+      });
+
     boot.kernelModules = [ ]
       ++ optional cfg.enableIPv6 "ipv6"
       ++ optional hasVirtuals "tun"
+      ++ optional hasSits "sit"
       ++ optional hasBonds "bonding";
 
     boot.extraModprobeConfig =
@@ -472,16 +594,22 @@ in
         # network device, so it only gets started after the interface
         # has appeared, and it's stopped when the interface
         # disappears.
-        configureInterface = i: nameValuePair "${i.name}-cfg"
-          (let mask =
-                if i.prefixLength != null then toString i.prefixLength else
-                if i.subnetMask != "" then i.subnetMask else "32";
-               staticIPv6 = cfg.enableIPv6 && i.ipv6Address != null;
+        configureInterface = i:
+          let
+            ips = i.ip4 ++ optionals cfg.enableIPv6 i.ip6
+              ++ optional (i.ipAddress != null) {
+                address = i.ipAddress;
+                prefixLength = i.prefixLength;
+              } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) {
+                address = i.ipv6Address;
+                prefixLength = i.ipv6PrefixLength;
+              };
           in
+          nameValuePair "${i.name}-cfg"
           { description = "Configuration of ${i.name}";
             wantedBy = [ "network-interfaces.target" ];
-            bindsTo = [ "sys-subsystem-net-devices-${i.name}.device" ];
-            after = [ "sys-subsystem-net-devices-${i.name}.device" ];
+            bindsTo = [ (subsystemDevice i.name) ];
+            after = [ (subsystemDevice i.name) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute pkgs.gawk ];
@@ -500,36 +628,32 @@ in
                   echo "setting MTU to ${toString i.mtu}..."
                   ip link set "${i.name}" mtu "${toString i.mtu}"
                 ''
-              + optionalString (i.ipAddress != null)
+
+              # Ip Setup
+              +
                 ''
-                  cur=$(ip -4 -o a show dev "${i.name}" | awk '{print $4}')
-                  # Only do a flush/add if it's necessary.  This is
+                  curIps=$(ip -o a show dev "${i.name}" | awk '{print $4}')
+                  # Only do an add if it's necessary.  This is
                   # useful when the Nix store is accessed via this
                   # interface (e.g. in a QEMU VM test).
-                  if [ "$cur" != "${i.ipAddress}/${mask}" ]; then
-                    echo "configuring interface..."
-                    ip -4 addr flush dev "${i.name}"
-                    ip -4 addr add "${i.ipAddress}/${mask}" dev "${i.name}"
-                    restart_network_setup=true
-                  else
-                    echo "skipping configuring interface"
-                  fi
                 ''
-              + optionalString (staticIPv6)
+              + flip concatMapStrings (ips) (ip:
+                let
+                  address = "${ip.address}/${toString ip.prefixLength}";
+                in
                 ''
-                  # Only do a flush/add if it's necessary.  This is
-                  # useful when the Nix store is accessed via this
-                  # interface (e.g. in a QEMU VM test).
-                  if ! ip -6 -o a show dev "${i.name}" | grep "${i.ipv6Address}/${toString i.ipv6prefixLength}"; then
-                    echo "configuring interface..."
-                    ip -6 addr flush dev "${i.name}"
-                    ip -6 addr add "${i.ipv6Address}/${toString i.ipv6prefixLength}" dev "${i.name}"
-                    restart_network_setup=true
-                  else
-                    echo "skipping configuring interface"
+                  echo "checking ip ${address}..."
+                  if ! echo "$curIps" | grep "${address}" >/dev/null 2>&1; then
+                    if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then
+                      echo "added ip ${address}..."
+                      restart_network_setup=true
+                    elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
+                      echo "failed to add ${address}"
+                      exit 1
+                    fi
                   fi
-                ''
-              + optionalString (i.ipAddress != null || staticIPv6)
+                '')
+              + optionalString (ips != [ ])
                 ''
                   if [ restart_network_setup = true ]; then
                     # Ensure that the default gateway remains set.
@@ -546,28 +670,47 @@ in
                 ''
                   echo 1 > /proc/sys/net/ipv6/conf/${i.name}/proxy_ndp
                 '';
-          });
+            preStop =
+              ''
+                echo "releasing configured ip's..."
+              ''
+              + flip concatMapStrings (ips) (ip:
+                let
+                  address = "${ip.address}/${toString ip.prefixLength}";
+                in
+                ''
+                  echo -n "Deleting ${address}..."
+                  ip addr del "${address}" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed"
+                  echo ""
+                '');
+          };
 
-        createTunDevice = i: nameValuePair "${i.name}"
+        createTunDevice = i: nameValuePair "${i.name}-netdev"
           { description = "Virtual Network Interface ${i.name}";
             requires = [ "dev-net-tun.device" ];
             after = [ "dev-net-tun.device" ];
-            wantedBy = [ "network.target" ];
-            requiredBy = [ "sys-subsystem-net-devices-${i.name}.device" ];
-            serviceConfig =
-              { Type = "oneshot";
-                RemainAfterExit = true;
-                ExecStart = "${pkgs.tunctl}/bin/tunctl -t '${i.name}' -u '${i.virtualOwner}'";
-                ExecStop = "${pkgs.tunctl}/bin/tunctl -d '${i.name}'";
-              };
+            wantedBy = [ "network.target" (subsystemDevice i.name) ];
+            path = [ pkgs.iproute ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+            };
+            script = ''
+              ip tuntap add dev "${i.name}" \
+              ${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \
+              user "${i.virtualOwner}"
+            '';
+            postStop = ''
+              ip link del ${i.name}
+            '';
           };
 
-        createBridgeDevice = n: v:
-          let
-            deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces;
+        createBridgeDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = map subsystemDevice v.interfaces;
           in
           { description = "Bridge Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -600,14 +743,14 @@ in
                 ip link set "${n}" down
                 brctl delbr "${n}"
               '';
-          };
+          });
 
-        createBondDevice = n: v:
-          let
-            deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces;
+        createBondDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = map subsystemDevice v.interfaces;
           in
           { description = "Bond Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -639,14 +782,40 @@ in
               ifenslave -d "${n}"
               ip link delete "${n}"
             '';
-          };
+          });
 
-        createVlanDevice = n: v:
-          let
-            deps = [ "sys-subsystem-net-devices-${v.interface}.device" ];
+        createSitDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = optional (v.dev != null) (subsystemDevice v.dev);
+          in
+          { description = "6-to-4 Tunnel Interface ${n}";
+            wantedBy = [ "network.target" (subsystemDevice n) ];
+            bindsTo = deps;
+            after = deps;
+            serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = true;
+            path = [ pkgs.iproute ];
+            script = ''
+              # Remove Dead Interfaces
+              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
+              ip link add "${n}" type sit \
+                ${optionalString (v.remote != null) "remote \"${v.remote}\""} \
+                ${optionalString (v.local != null) "local \"${v.local}\""} \
+                ${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \
+                ${optionalString (v.dev != null) "dev \"${v.dev}\""}
+              ip link set "${n}" up
+            '';
+            postStop = ''
+              ip link delete "${n}"
+            '';
+          });
+
+        createVlanDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = [ (subsystemDevice v.interface) ];
           in
           { description = "Vlan Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -661,14 +830,15 @@ in
             postStop = ''
               ip link delete "${n}"
             '';
-          };
+          });
 
       in listToAttrs (
            map configureInterface interfaces ++
            map createTunDevice (filter (i: i.virtual) interfaces))
-         // mapAttrs createBridgeDevice cfg.bridges
-         // mapAttrs createBondDevice cfg.bonds
-         // mapAttrs createVlanDevice cfg.vlans
+         // mapAttrs' createBridgeDevice cfg.bridges
+         // mapAttrs' createBondDevice cfg.bonds
+         // mapAttrs' createSitDevice cfg.sits
+         // mapAttrs' createVlanDevice cfg.vlans
          // { "network-setup" = networkSetup; };
 
     # Set the host and domain names in the activation script.  Don't
diff --git a/nixos/modules/tasks/trackpoint.nix b/nixos/modules/tasks/trackpoint.nix
index d1c6f8ac156..5d1bb631b54 100644
--- a/nixos/modules/tasks/trackpoint.nix
+++ b/nixos/modules/tasks/trackpoint.nix
@@ -36,6 +36,14 @@ with lib;
           configures 97.
         '';
       };
+
+      emulateWheel = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Enable scrolling while holding the middle mouse button.
+        '';
+      };
       
     };
 
@@ -44,17 +52,33 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.hardware.trackpoint.enable {
-
-    services.udev.extraRules =
-    ''
-      ACTION=="add|change", SUBSYSTEM=="input", ATTR{name}=="TPPS/2 IBM TrackPoint", ATTR{device/speed}="${toString config.hardware.trackpoint.speed}", ATTR{device/sensitivity}="${toString config.hardware.trackpoint.sensitivity}"
-    '';
-
-    system.activationScripts.trackpoint =
+  config = mkMerge [
+    (mkIf config.hardware.trackpoint.enable {
+      services.udev.extraRules =
       ''
-        ${config.systemd.package}/bin/udevadm trigger --attr-match=name="TPPS/2 IBM TrackPoint"
+        ACTION=="add|change", SUBSYSTEM=="input", ATTR{name}=="TPPS/2 IBM TrackPoint", ATTR{device/speed}="${toString config.hardware.trackpoint.speed}", ATTR{device/sensitivity}="${toString config.hardware.trackpoint.sensitivity}"
       '';
-  };
 
+      system.activationScripts.trackpoint =
+        ''
+          ${config.systemd.package}/bin/udevadm trigger --attr-match=name="TPPS/2 IBM TrackPoint"
+        '';
+    })
+
+    (mkIf config.hardware.trackpoint.emulateWheel {
+      services.xserver.config =
+        ''
+          Section "InputClass"
+            Identifier "Trackpoint Wheel Emulation"
+            MatchProduct "TPPS/2 IBM TrackPoint|DualPoint Stick|Synaptics Inc. Composite TouchPad / TrackPoint|ThinkPad USB Keyboard with TrackPoint|USB Trackpoint pointing device|Composite TouchPad / TrackPoint"
+            MatchDevicePath "/dev/input/event*"
+            Option "EmulateWheel" "true"
+            Option "EmulateWheelButton" "2"
+            Option "Emulate3Buttons" "false"
+            Option "XAxisMapping" "6 7"
+            Option "YAxisMapping" "4 5"
+            EndSection
+        '';
+    })
+  ];
 }
diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix
index b81f97f2b4e..a7e8953827a 100644
--- a/nixos/modules/virtualisation/container-config.nix
+++ b/nixos/modules/virtualisation/container-config.nix
@@ -18,76 +18,7 @@ with lib;
     # Shut up warnings about not having a boot loader.
     system.build.installBootLoader = "${pkgs.coreutils}/bin/true";
 
-    # Provide a root login prompt on /var/lib/root-login.socket that
-    # doesn't ask for a password. This socket can only be used by root
-    # on the host.
-    systemd.sockets.root-login =
-      { description = "Root Login Socket";
-        wantedBy = [ "sockets.target" ];
-        socketConfig =
-          { ListenStream = "/var/lib/root-login.socket";
-            SocketMode = "0600";
-            Accept = true;
-          };
-      };
-
-    systemd.services."root-login@" =
-      { description = "Root Login %i";
-        environment.TERM = "linux";
-        serviceConfig =
-          { Type = "simple";
-            StandardInput = "socket";
-            ExecStart = "${pkgs.socat}/bin/socat -t0 - \"exec:${pkgs.shadow}/bin/login -f root,pty,setsid,setpgid,stderr,ctty\"";
-            TimeoutStopSec = 1; # FIXME
-          };
-        restartIfChanged = false;
-      };
-
-    # Provide a daemon on /var/lib/run-command.socket that reads a
-    # command from stdin and executes it.
-    systemd.sockets.run-command =
-      { description = "Run Command Socket";
-        wantedBy = [ "sockets.target" ];
-        socketConfig =
-          { ListenStream = "/var/lib/run-command.socket";
-            SocketMode = "0600";  # only root can connect
-            Accept = true;
-          };
-      };
-
-    systemd.services."run-command@" =
-      { description = "Run Command %i";
-        environment.TERM = "linux";
-        serviceConfig =
-          { Type = "simple";
-            StandardInput = "socket";
-            TimeoutStopSec = 1; # FIXME
-          };
-        script =
-          ''
-            #! ${pkgs.stdenv.shell} -e
-            source /etc/bashrc
-            read c
-            eval "command=($c)"
-            exec "''${command[@]}"
-          '';
-        restartIfChanged = false;
-      };
-
-    systemd.services.container-startup-done =
-      { description = "Container Startup Notification";
-        wantedBy = [ "multi-user.target" ];
-        after = [ "multi-user.target" ];
-        script =
-          ''
-            if [ -p /var/lib/startup-done ]; then
-              echo done > /var/lib/startup-done
-            fi
-          '';
-        serviceConfig.Type = "oneshot";
-        serviceConfig.RemainAfterExit = true;
-        restartIfChanged = false;
-      };
+    systemd.services.systemd-remount-fs.enable = false;
 
   };
 
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 7f545a9d303..d62340f2c79 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -10,7 +10,7 @@ let
     isExecutable = true;
     src = ./nixos-container.pl;
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
-    inherit (pkgs) socat;
+    inherit (pkgs) utillinux;
   };
 
   # The container's init script, a small wrapper around the regular
@@ -32,7 +32,10 @@ let
         fi
       fi
 
-      exec "$1"
+      # Start the regular stage 1 script, passing the bind-mounted
+      # notification socket from the host to allow the container
+      # systemd to signal readiness to the host systemd.
+      NOTIFY_SOCKET=/var/lib/private/host-notify exec "$1"
     '';
 
   system = config.nixpkgs.system;
@@ -168,17 +171,18 @@ in
 
         preStart =
           ''
-            mkdir -p -m 0755 $root/var/lib
+            # Clean up existing machined registration and interfaces.
+            machinectl terminate "$INSTANCE" 2> /dev/null || true
 
-            # Create a named pipe to get a signal when the container
-            # has finished booting.
-            rm -f $root/var/lib/startup-done
-            mkfifo -m 0600 $root/var/lib/startup-done
+            if [ "$PRIVATE_NETWORK" = 1 ]; then
+              ip link del dev "ve-$INSTANCE" 2> /dev/null || true
+            fi
          '';
 
         script =
           ''
             mkdir -p -m 0755 "$root/etc" "$root/var/lib"
+            mkdir -p -m 0700 "$root/var/lib/private"
             if ! [ -e "$root/etc/os-release" ]; then
               touch "$root/etc/os-release"
             fi
@@ -205,12 +209,16 @@ in
               fi
             ''}
 
+            # Run systemd-nspawn without startup notification (we'll
+            # wait for the container systemd to signal readiness).
+            EXIT_ON_REBOOT=1 NOTIFY_SOCKET= \
             exec ${config.systemd.package}/bin/systemd-nspawn \
               --keep-unit \
               -M "$INSTANCE" -D "$root" $extraFlags \
               --bind-ro=/nix/store \
               --bind-ro=/nix/var/nix/db \
               --bind-ro=/nix/var/nix/daemon-socket \
+              --bind=/run/systemd/notify:/var/lib/private/host-notify \
               --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \
               --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \
               --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \
@@ -222,12 +230,6 @@ in
 
         postStart =
           ''
-            # This blocks until the container-startup-done service
-            # writes something to this pipe.  FIXME: it also hangs
-            # until the start timeout expires if systemd-nspawn exits.
-            read x < $root/var/lib/startup-done
-            rm -f $root/var/lib/startup-done
-
             if [ "$PRIVATE_NETWORK" = 1 ]; then
               ifaceHost=ve-$INSTANCE
               ip link set dev $ifaceHost up
@@ -242,23 +244,41 @@ in
 
         preStop =
           ''
-            machinectl poweroff "$INSTANCE"
+            machinectl poweroff "$INSTANCE" || true
           '';
 
         restartIfChanged = false;
         #reloadIfChanged = true; # FIXME
 
-        serviceConfig.ExecReload = pkgs.writeScript "reload-container"
-          ''
-            #! ${pkgs.stdenv.shell} -e
-            SYSTEM_PATH=/nix/var/nix/profiles/system
-            echo $SYSTEM_PATH/bin/switch-to-configuration test | \
-              ${pkgs.socat}/bin/socat unix:$root/var/lib/run-command.socket -
-          '';
+        serviceConfig = {
+          ExecReload = pkgs.writeScript "reload-container"
+            ''
+              #! ${pkgs.stdenv.shell} -e
+              ${nixos-container}/bin/nixos-container run "$INSTANCE" -- \
+                bash --login -c "/nix/var/nix/profiles/system/bin/switch-to-configuration test"
+            '';
 
-        serviceConfig.SyslogIdentifier = "container %i";
+          SyslogIdentifier = "container %i";
 
-        serviceConfig.EnvironmentFile = "-/etc/containers/%i.conf";
+          EnvironmentFile = "-/etc/containers/%i.conf";
+
+          Type = "notify";
+
+          NotifyAccess = "all";
+
+          # Note that on reboot, systemd-nspawn returns 10, so this
+          # unit will be restarted. On poweroff, it returns 0, so the
+          # unit won't be restarted.
+          Restart = "on-failure";
+
+          # Hack: we don't want to kill systemd-nspawn, since we call
+          # "machinectl poweroff" in preStop to shut down the
+          # container cleanly. But systemd requires sending a signal
+          # (at least if we want remaining processes to be killed
+          # after the timeout). So send an ignored signal.
+          KillMode = "mixed";
+          KillSignal = "WINCH";
+        };
       };
 
     # Generate a configuration file in /etc/containers for each
@@ -292,5 +312,30 @@ in
 
     environment.systemPackages = [ nixos-container ];
 
+    # Start containers at boot time.
+    systemd.services.all-containers =
+      { description = "All Containers";
+
+        wantedBy = [ "multi-user.target" ];
+
+        unitConfig.ConditionDirectoryNotEmpty = "/etc/containers";
+
+        serviceConfig.Type = "oneshot";
+
+        script =
+          ''
+            res=0
+            shopt -s nullglob
+            for i in /etc/containers/*.conf; do
+              AUTO_START=
+              source "$i"
+              if [ "$AUTO_START" = 1 ]; then
+                systemctl start "container@$(basename "$i" .conf).service" || res=1
+              fi
+            done
+            exit $res
+          ''; # */
+      };
+
   };
 }
diff --git a/nixos/modules/virtualisation/docker-image.nix b/nixos/modules/virtualisation/docker-image.nix
new file mode 100644
index 00000000000..13b861dc988
--- /dev/null
+++ b/nixos/modules/virtualisation/docker-image.nix
@@ -0,0 +1,67 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
+
+in {
+  # Create the tarball
+  system.build.dockerImage = import ../../lib/make-system-tarball.nix {
+    inherit (pkgs) stdenv perl xz pathsFromGraph;
+
+    contents = [];
+    extraArgs = "--owner=0";
+    storeContents = [
+      { object = config.system.build.toplevel + "/init";
+        symlink = "/bin/init";
+      }
+    ] ++ (pkgs2storeContents [ pkgs.stdenv ]);
+  };
+
+  boot.postBootCommands =
+    ''
+      # After booting, register the contents of the Nix store in the Nix
+      # database.
+      if [ -f /nix-path-registration ]; then
+        ${config.nix.package}/bin/nix-store --load-db < /nix-path-registration &&
+        rm /nix-path-registration
+      fi
+
+      # nixos-rebuild also requires a "system" profile and an
+      # /etc/NIXOS tag.
+      touch /etc/NIXOS
+      ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+
+      # Set virtualisation to docker
+      echo "docker" > /run/systemd/container 
+    '';
+
+
+  # docker image config
+  require = [
+    ../installer/cd-dvd/channel.nix
+    ../profiles/minimal.nix
+    ../profiles/clone-config.nix
+  ];
+
+  boot.isContainer = true;
+
+  # Iptables do not work in docker
+  networking.firewall.enable = false;
+
+  services.openssh.enable = true;
+
+  # Socket activated ssh presents problem in docker
+  services.openssh.startWhenNeeded = false;
+
+  # Allow the user to login as root without password
+  security.initialRootPassword = "";
+
+  # Some more help text.
+  services.mingetty.helpLine =
+    ''
+
+      Log in as "root" with an empty password.
+    '';
+}
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index a0aa6135326..1ce066cdc73 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -59,6 +59,7 @@ in
 
   config = mkIf cfg.enable (mkMerge [
     { environment.systemPackages = [ pkgs.docker ];
+      users.extraGroups.docker.gid = config.ids.gids.docker;
     }
     (mkIf cfg.socketActivation {
 
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index d7d700d8841..318460f4c2c 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -7,6 +7,7 @@ with lib;
 let
 
   cfg = config.virtualisation.libvirtd;
+  vswitch = config.virtualisation.vswitch;
   configFile = pkgs.writeText "libvirtd.conf" ''
     unix_sock_group = "libvirtd"
     unix_sock_rw_perms = "0770"
@@ -56,6 +57,20 @@ in
           '';
       };
 
+    virtualisation.libvirtd.onShutdown =
+      mkOption {
+        type = types.enum ["shutdown" "suspend" ];
+        default = "suspend";
+        description =
+          ''
+            When shutting down / restarting the host what method should
+            be used to gracefully halt the guests. Setting to "shutdown"
+            will cause an ACPI shutdown of each guest. "suspend" will
+            attempt to save the state of the guests ready to restore on boot.
+          '';
+      };
+
+
   };
 
 
@@ -73,12 +88,17 @@ in
       { description = "Libvirt Virtual Machine Management Daemon";
 
         wantedBy = [ "multi-user.target" ];
-        after = [ "systemd-udev-settle.service" ];
+        after = [ "systemd-udev-settle.service" ]
+                ++ optional vswitch.enable "vswitchd.service";
 
-        path =
-          [ pkgs.bridge_utils pkgs.dmidecode pkgs.dnsmasq
+        path = [ 
+            pkgs.bridge_utils 
+            pkgs.dmidecode 
+            pkgs.dnsmasq
             pkgs.ebtables
-          ] ++ optional cfg.enableKVM pkgs.qemu_kvm;
+          ] 
+          ++ optional cfg.enableKVM pkgs.qemu_kvm
+          ++ optional vswitch.enable vswitch.package;
 
         preStart =
           ''
@@ -152,7 +172,12 @@ in
             ${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests start || true
           '';
 
-        postStop = "${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests stop";
+        postStop = 
+            ''
+            export PATH=${pkgs.gettext}/bin:$PATH
+            export ON_SHUTDOWN=${cfg.onShutdown}
+            ${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests stop
+            '';
 
         serviceConfig.Type = "oneshot";
         serviceConfig.RemainAfterExit = true;
diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl
index c6a5ecde9e3..7403a42f0f1 100644
--- a/nixos/modules/virtualisation/nixos-container.pl
+++ b/nixos/modules/virtualisation/nixos-container.pl
@@ -7,7 +7,7 @@ use File::Slurp;
 use Fcntl ':flock';
 use Getopt::Long qw(:config gnu_getopt);
 
-my $socat = '@socat@/bin/socat';
+my $nsenter = "@utillinux@/bin/nsenter";
 
 # Ensure a consistent umask.
 umask 0022;
@@ -17,25 +17,30 @@ umask 0022;
 sub showHelp {
     print <<EOF;
 Usage: nixos-container list
-       nixos-container create <container-name> [--config <string>] [--ensure-unique-name]
+       nixos-container create <container-name> [--system-path <path>] [--config <string>] [--ensure-unique-name] [--auto-start]
        nixos-container destroy <container-name>
        nixos-container start <container-name>
        nixos-container stop <container-name>
+       nixos-container status <container-name>
        nixos-container login <container-name>
        nixos-container root-login <container-name>
        nixos-container run <container-name> -- args...
-       nixos-container set-root-password <container-name> <password>
        nixos-container show-ip <container-name>
+       nixos-container show-host-key <container-name>
 EOF
     exit 0;
 }
 
+my $systemPath;
 my $ensureUniqueName = 0;
+my $autoStart = 0;
 my $extraConfig;
 
 GetOptions(
     "help" => sub { showHelp() },
     "ensure-unique-name" => \$ensureUniqueName,
+    "auto-start" => \$autoStart,
+    "system-path=s" => \$systemPath,
     "config=s" => \$extraConfig
     ) or exit 1;
 
@@ -122,17 +127,13 @@ if ($action eq "create") {
     push @conf, "PRIVATE_NETWORK=1\n";
     push @conf, "HOST_ADDRESS=$hostAddress\n";
     push @conf, "LOCAL_ADDRESS=$localAddress\n";
+    push @conf, "AUTO_START=$autoStart\n";
     write_file($confFile, \@conf);
 
     close($lock);
 
     print STDERR "host IP is $hostAddress, container IP is $localAddress\n";
 
-    mkpath("$root/etc/nixos", 0, 0755);
-
-    my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
-    writeNixOSConfig $nixosConfigFile;
-
     # The per-container directory is restricted to prevent users on
     # the host from messing with guest users who happen to have the
     # same uid.
@@ -141,10 +142,21 @@ if ($action eq "create") {
     $profileDir = "$profileDir/$containerName";
     mkpath($profileDir, 0, 0755);
 
-    system("nix-env", "-p", "$profileDir/system",
-           "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>",
-           "--set", "-A", "system") == 0
-        or die "$0: failed to build initial container configuration\n";
+    # Build/set the initial configuration.
+    if (defined $systemPath) {
+        system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
+            or die "$0: failed to set initial container configuration\n";
+    } else {
+        mkpath("$root/etc/nixos", 0, 0755);
+
+        my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
+        writeNixOSConfig $nixosConfigFile;
+
+        system("nix-env", "-p", "$profileDir/system",
+               "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>",
+               "--set", "-A", "system") == 0
+            or die "$0: failed to build initial container configuration\n";
+    }
 
     print "$containerName\n" if $ensureUniqueName;
     exit 0;
@@ -155,7 +167,11 @@ my $profileDir = "/nix/var/nix/profiles/per-container/$containerName";
 my $gcRootsDir = "/nix/var/nix/gcroots/per-container/$containerName";
 my $confFile = "/etc/containers/$containerName.conf";
 if (!-e $confFile) {
-    exit 0 if $action eq "destroy";
+    if ($action eq "destroy") {
+        exit 0;
+    } elsif ($action eq "status") {
+        print "gone\n";
+    }
     die "$0: container ‘$containerName’ does not exist\n" ;
 }
 
@@ -169,6 +185,22 @@ sub stopContainer {
         or die "$0: failed to stop container\n";
 }
 
+# Return the PID of the init process of the container.
+sub getLeader {
+    my $s = `machinectl show "$containerName" -p Leader`;
+    chomp $s;
+    $s =~ /^Leader=(\d+)$/ or die "unable to get container's main PID\n";
+    return int($1);
+}
+
+# Run a command in the container.
+sub runInContainer {
+    my @args = @_;
+    my $leader = getLeader;
+    exec($nsenter, "-t", $leader, "-m", "-u", "-i", "-n", "-p", "--", @args);
+    die "cannot run ‘nsenter’: $!\n";
+}
+
 if ($action eq "destroy") {
     die "$0: cannot destroy declarative container (remove it from your configuration.nix instead)\n"
         unless POSIX::access($confFile, &POSIX::W_OK);
@@ -190,6 +222,10 @@ elsif ($action eq "stop") {
     stopContainer;
 }
 
+elsif ($action eq "status") {
+    print isContainerRunning() ? "up" : "down", "\n";
+}
+
 elsif ($action eq "update") {
     my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
 
@@ -214,28 +250,14 @@ elsif ($action eq "login") {
 }
 
 elsif ($action eq "root-login") {
-    exec($socat, "unix:$root/var/lib/root-login.socket", "-,echo=0,raw");
+    runInContainer("su", "root", "-l");
 }
 
 elsif ($action eq "run") {
     shift @ARGV; shift @ARGV;
-    my $pid = open(SOCAT, "|-", $socat, "-t0", "-", "unix:$root/var/lib/run-command.socket") or die "$0: cannot start $socat: $!\n";
-    print SOCAT join(' ', map { "'$_'" } @ARGV), "\n";
-    flush SOCAT;
-    waitpid($pid, 0);
-    close(SOCAT);
-}
-
-elsif ($action eq "set-root-password") {
-    # FIXME: don't get password from the command line.
-    my $password = $ARGV[2] or die "$0: no password given\n";
-    my $pid = open(SOCAT, "|-", $socat, "-t0", "-", "unix:$root/var/lib/run-command.socket") or die "$0: cannot start $socat: $!\n";
-    print SOCAT "passwd\n";
-    print SOCAT "$password\n";
-    print SOCAT "$password\n";
-    flush SOCAT;
-    waitpid($pid, 0);
-    close(SOCAT);
+    # Escape command.
+    my $s = join(' ', map { s/'/'\\''/g; "'$_'" } @ARGV);
+    runInContainer("su", "root", "-l", "-c", "exec " . $s);
 }
 
 elsif ($action eq "show-ip") {
@@ -244,6 +266,12 @@ elsif ($action eq "show-ip") {
     print "$1\n";
 }
 
+elsif ($action eq "show-host-key") {
+    my $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub";
+    exit 1 if ! -f $fn;
+    print read_file($fn);
+}
+
 else {
     die "$0: unknown action ‘$action’\n";
 }
diff --git a/nixos/modules/virtualisation/openvswitch.nix b/nixos/modules/virtualisation/openvswitch.nix
new file mode 100644
index 00000000000..c1579d94657
--- /dev/null
+++ b/nixos/modules/virtualisation/openvswitch.nix
@@ -0,0 +1,117 @@
+# Systemd services for openvswitch
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.virtualisation.vswitch;
+
+in
+
+{
+
+  options = {
+
+    virtualisation.vswitch.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description =
+        ''
+        Enable Open vSwitch. A configuration 
+        daemon (ovs-server) will be started.
+        '';
+    };
+
+
+    virtualisation.vswitch.package = mkOption {
+      type = types.package;
+      default = pkgs.openvswitch;
+      description =
+        ''
+        Open vSwitch package to use.
+        '';
+    };
+
+  };
+
+  config = mkIf cfg.enable (let 
+
+    # Where the communication sockets live
+    runDir = "/var/run/openvswitch";
+
+    # Where the config database live (can't be in nix-store)
+    stateDir = "/var/db/openvswitch";
+
+    # The path to the an initialized version of the database 
+    db = pkgs.stdenv.mkDerivation {
+      name = "vswitch.db";
+      unpackPhase = "true";
+      buildPhase = "true";
+      buildInputs = with pkgs; [
+        cfg.package
+      ];
+      installPhase = 
+        ''
+        ensureDir $out/
+        '';
+    };
+
+  in {
+
+    environment.systemPackages = [ cfg.package ]; 
+
+    boot.kernelModules = [ "tun" "openvswitch" ];
+
+    boot.extraModulePackages = [ cfg.package ];
+
+    systemd.services.ovsdb = {
+      description = "Open_vSwitch Database Server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "systemd-udev-settle.service" ];
+      wants = [ "vswitchd.service" ];
+      path = [ cfg.package ];
+      restartTriggers = [ db cfg.package ];
+      # Create the config database
+      preStart = 
+        ''
+        mkdir -p ${runDir}
+        mkdir -p /var/db/openvswitch
+        chmod +w /var/db/openvswitch
+        if [[ ! -e /var/db/openvswitch/conf.db ]]; then
+          ${cfg.package}/bin/ovsdb-tool create \
+            "/var/db/openvswitch/conf.db" \
+            "${cfg.package}/share/openvswitch/vswitch.ovsschema"
+        fi
+        chmod -R +w /var/db/openvswitch
+        '';
+      serviceConfig.ExecStart = 
+        ''
+        ${cfg.package}/bin/ovsdb-server \
+          --remote=punix:${runDir}/db.sock \
+          --private-key=db:Open_vSwitch,SSL,private_key \
+          --certificate=db:Open_vSwitch,SSL,certificate \
+          --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
+          --unixctl=ovsdb.ctl.sock \
+          /var/db/openvswitch/conf.db
+        '';       
+      serviceConfig.Restart = "always";
+      serviceConfig.RestartSec = 3;
+      postStart =
+        ''
+        ${cfg.package}/bin/ovs-vsctl --timeout 3 --retry --no-wait init
+        '';
+
+    };
+
+    systemd.services.vswitchd = {
+      description = "Open_vSwitch Daemon";
+      bindsTo = [ "ovsdb.service" ];
+      after = [ "ovsdb.service" ];
+      path = [ cfg.package ];
+      serviceConfig.ExecStart = ''${cfg.package}/bin/ovs-vswitchd'';
+    };
+
+  });
+
+}
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index dae3b9210a8..0c72bae35bb 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -52,6 +52,11 @@ in rec {
         (all nixos.tests.installer.lvm)
         (all nixos.tests.installer.separateBoot)
         (all nixos.tests.installer.simple)
+        (all nixos.tests.installer.simpleLabels)
+        (all nixos.tests.installer.simpleProvided)
+        (all nixos.tests.installer.btrfsSimple)
+        (all nixos.tests.installer.btrfsSubvols)
+        (all nixos.tests.installer.btrfsSubvolDefault)
         (all nixos.tests.ipv6)
         (all nixos.tests.kde4)
         (all nixos.tests.login)
diff --git a/nixos/release.nix b/nixos/release.nix
index ed413d3e928..d4e1a3737e3 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -78,6 +78,16 @@ let
         };
 
 
+  makeClosure = module: forAllSystems (system: (import ./lib/eval-config.nix {
+    inherit system;
+    modules = [ module ] ++ lib.singleton
+      ({ config, lib, ... }:
+      { fileSystems."/".device  = lib.mkDefault "/dev/sda1";
+        boot.loader.grub.device = lib.mkDefault "/dev/sda";
+      });
+  }).config.system.build.toplevel);
+
+
 in rec {
 
   channel =
@@ -218,6 +228,11 @@ in rec {
   tests.installer.rebuildCD = forAllSystems (system: (import tests/installer.nix { inherit system; }).rebuildCD.test);
   tests.installer.separateBoot = forAllSystems (system: (import tests/installer.nix { inherit system; }).separateBoot.test);
   tests.installer.simple = forAllSystems (system: (import tests/installer.nix { inherit system; }).simple.test);
+  tests.installer.simpleLabels = forAllSystems (system: (import tests/installer.nix { inherit system; }).simpleLabels.test);
+  tests.installer.simpleProvided = forAllSystems (system: (import tests/installer.nix { inherit system; }).simpleProvided.test);
+  tests.installer.btrfsSimple = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSimple.test);
+  tests.installer.btrfsSubvols = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvols.test);
+  tests.installer.btrfsSubvolDefault = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test);
   tests.influxdb = callTest tests/influxdb.nix {};
   tests.ipv6 = callTest tests/ipv6.nix {};
   tests.jenkins = callTest tests/jenkins.nix {};
@@ -242,4 +257,46 @@ in rec {
   tests.udisks2 = callTest tests/udisks2.nix {};
   tests.xfce = callTest tests/xfce.nix {};
 
+
+  /* Build a bunch of typical closures so that Hydra can keep track of
+     the evolution of closure sizes. */
+
+  closures = {
+
+    smallContainer = makeClosure ({ pkgs, ... }:
+      { boot.isContainer = true;
+        services.openssh.enable = true;
+      });
+
+    tinyContainer = makeClosure ({ pkgs, ... }:
+      { boot.isContainer = true;
+        imports = [ modules/profiles/minimal.nix ];
+      });
+
+    ec2 = makeClosure ({ pkgs, ... }:
+      { imports = [ modules/virtualisation/amazon-image.nix ];
+      });
+
+    kde = makeClosure ({ pkgs, ... }:
+      { services.xserver.enable = true;
+        services.xserver.displayManager.kdm.enable = true;
+        services.xserver.desktopManager.kde4.enable = true;
+      });
+
+    xfce = makeClosure ({ pkgs, ... }:
+      { services.xserver.enable = true;
+        services.xserver.desktopManager.xfce.enable = true;
+      });
+
+    # Linux/Apache/PostgreSQL/PHP stack.
+    lapp = makeClosure ({ pkgs, ... }:
+      { services.httpd.enable = true;
+        services.httpd.adminAddr = "foo@example.org";
+        services.postgresql.enable = true;
+        services.postgresql.package = pkgs.postgresql93;
+        environment.systemPackages = [ pkgs.php ];
+      });
+
+  };
+
 }
diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix
index 002e012f65f..b12a861f723 100644
--- a/nixos/tests/bittorrent.nix
+++ b/nixos/tests/bittorrent.nix
@@ -16,7 +16,7 @@ let
   miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf"
     ''
       ext_ifname=eth1
-      listening_ip=${nodes.router.config.networking.interfaces.eth2.ipAddress}/24
+      listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address}/24
       allow 1024-65535 192.168.2.0/24 1024-65535
     '';
 
@@ -53,7 +53,7 @@ in
         { environment.systemPackages = [ pkgs.transmission ];
           virtualisation.vlans = [ 2 ];
           networking.defaultGateway =
-            nodes.router.config.networking.interfaces.eth2.ipAddress;
+            (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address;
           networking.firewall.enable = false;
         };
 
@@ -81,7 +81,7 @@ in
       # Create the torrent.
       $tracker->succeed("mkdir /tmp/data");
       $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2");
-      $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -t http://${nodes.tracker.config.networking.interfaces.eth1.ipAddress}:6969/announce -o /tmp/test.torrent");
+      $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ip4).address}:6969/announce -o /tmp/test.torrent");
       $tracker->succeed("chmod 644 /tmp/test.torrent");
 
       # Start the tracker.  !!! use a less crappy tracker
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index d3bbe7a8bd5..66ab2567e19 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -35,8 +35,8 @@ let
 
 
   # The configuration to install.
-  makeConfig = { testChannel, useEFI, grubVersion, grubDevice }: pkgs.writeText "configuration.nix"
-    ''
+  makeConfig = { testChannel, useEFI, grubVersion, grubDevice, grubIdentifier }:
+    pkgs.writeText "configuration.nix" ''
       { config, pkgs, modulesPath, ... }:
 
       { imports =
@@ -54,6 +54,7 @@ let
           ''}
           boot.loader.grub.device = "${grubDevice}";
           boot.loader.grub.extraConfig = "serial; terminal_output.serial";
+          boot.loader.grub.fsIdentifier = "${grubIdentifier}";
         ''}
 
         environment.systemPackages = [ ${optionalString testChannel "pkgs.rlwrap"} ];
@@ -93,12 +94,12 @@ let
   # disk, and then reboot from the hard disk.  It's parameterized with
   # a test script fragment `createPartitions', which must create
   # partitions and filesystems.
-  testScriptFun = { createPartitions, testChannel, useEFI, grubVersion, grubDevice }:
+  testScriptFun = { createPartitions, testChannel, useEFI, grubVersion, grubDevice, grubIdentifier }:
     let
       # FIXME: OVMF doesn't boot from virtio http://www.mail-archive.com/edk2-devel@lists.sourceforge.net/msg01501.html
       iface = if useEFI || grubVersion == 1 then "scsi" else "virtio";
       qemuFlags =
-        (if iso.system == "x86_64-linux" then "-m 512 " else "-m 384 ") +
+        (if iso.system == "x86_64-linux" then "-m 768 " else "-m 512 ") +
         (optionalString (iso.system == "x86_64-linux") "-cpu kvm64 ") +
         (optionalString useEFI ''-L ${efiBios} -hda ''${\(Cwd::abs_path('harddisk'))} '');
       hdFlags = optionalString (!useEFI)
@@ -161,7 +162,7 @@ let
       $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2");
 
       $machine->copyFileFromHost(
-          "${ makeConfig { inherit testChannel useEFI grubVersion grubDevice; } }",
+          "${ makeConfig { inherit testChannel useEFI grubVersion grubDevice grubIdentifier; } }",
           "/mnt/etc/nixos/configuration.nix");
 
       # Perform the installation.
@@ -216,13 +217,13 @@ let
 
 
   makeInstallerTest = name:
-    { createPartitions, testChannel ? false, useEFI ? false, grubVersion ? 2, grubDevice ? "/dev/vda" }:
+    { createPartitions, testChannel ? false, useEFI ? false, grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid" }:
     makeTest {
       inherit iso;
       name = "installer-" + name;
       nodes = if testChannel then { inherit webserver; } else { };
       testScript = testScriptFun {
-        inherit createPartitions testChannel useEFI grubVersion grubDevice;
+        inherit createPartitions testChannel useEFI grubVersion grubDevice grubIdentifier;
       };
     };
 
@@ -394,4 +395,103 @@ in {
           $machine->shutdown;
         '';
     };
+
+  # Test using labels to identify volumes in grub
+  simpleLabels = makeInstallerTest "simpleLabels" {
+    createPartitions = ''
+      $machine->succeed(
+        "sgdisk -Z /dev/vda",
+        "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+        "mkswap /dev/vda2 -L swap",
+        "swapon -L swap",
+        "mkfs.ext4 -L root /dev/vda3",
+        "mount LABEL=root /mnt",
+      );
+    '';
+    grubIdentifier = "label";
+  };
+
+  # Test using the provided disk name within grub
+  # TODO: Fix udev so the symlinks are unneeded in /dev/disks
+  simpleProvided = makeInstallerTest "simpleProvided" {
+    createPartitions = ''
+      my $UUID = "\$(blkid -s UUID -o value /dev/vda2)";
+      $machine->succeed(
+        "sgdisk -Z /dev/vda",
+        "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 -t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda",
+        "mkswap /dev/vda3 -L swap",
+        "swapon -L swap",
+        "mkfs.ext4 -L boot /dev/vda2",
+        "mkfs.ext4 -L root /dev/vda4",
+      );
+      $machine->execute("ln -s ../../vda2 /dev/disk/by-uuid/$UUID");
+      $machine->execute("ln -s ../../vda4 /dev/disk/by-label/root");
+      $machine->succeed(
+        "mount /dev/disk/by-label/root /mnt",
+        "mkdir /mnt/boot",
+        "mount /dev/disk/by-uuid/$UUID /mnt/boot"
+      );
+    '';
+    grubIdentifier = "provided";
+  };
+
+  # Simple btrfs grub testing
+  btrfsSimple = makeInstallerTest "btrfsSimple" {
+    createPartitions = ''
+      $machine->succeed(
+        "sgdisk -Z /dev/vda",
+        "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+        "mkswap /dev/vda2 -L swap",
+        "swapon -L swap",
+        "mkfs.btrfs -L root /dev/vda3",
+        "mount LABEL=root /mnt",
+      );
+    '';
+  };
+
+  # Test to see if we can detect /boot and /nix on subvolumes
+  btrfsSubvols = makeInstallerTest "btrfsSubvols" {
+    createPartitions = ''
+      $machine->succeed(
+        "sgdisk -Z /dev/vda",
+        "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+        "mkswap /dev/vda2 -L swap",
+        "swapon -L swap",
+        "mkfs.btrfs -L root /dev/vda3",
+        "btrfs device scan",
+        "mount LABEL=root /mnt",
+        "btrfs subvol create /mnt/boot",
+        "btrfs subvol create /mnt/nixos",
+        "btrfs subvol create /mnt/nixos/default",
+        "umount /mnt",
+        "mount -o defaults,subvol=nixos/default LABEL=root /mnt",
+        "mkdir /mnt/boot",
+        "mount -o defaults,subvol=boot LABEL=root /mnt/boot",
+      );
+    '';
+  };
+
+  # Test to see if we can detect default and aux subvolumes correctly
+  btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" {
+    createPartitions = ''
+      $machine->succeed(
+        "sgdisk -Z /dev/vda",
+        "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+        "mkswap /dev/vda2 -L swap",
+        "swapon -L swap",
+        "mkfs.btrfs -L root /dev/vda3",
+        "btrfs device scan",
+        "mount LABEL=root /mnt",
+        "btrfs subvol create /mnt/badpath",
+        "btrfs subvol create /mnt/badpath/boot",
+        "btrfs subvol create /mnt/nixos",
+        "btrfs subvol set-default \$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt",
+        "umount /mnt",
+        "mount -o defaults LABEL=root /mnt",
+        "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism is actually looking up subvolumes
+        "mkdir /mnt/boot",
+        "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot",
+      );
+    '';
+  };
 }
diff --git a/nixos/tests/nat.nix b/nixos/tests/nat.nix
index 5fdcc0e97ca..87ed974edad 100644
--- a/nixos/tests/nat.nix
+++ b/nixos/tests/nat.nix
@@ -13,7 +13,7 @@ import ./make-test.nix {
         { virtualisation.vlans = [ 1 ];
           networking.firewall.allowPing = true;
           networking.defaultGateway =
-            nodes.router.config.networking.interfaces.eth2.ipAddress;
+            (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address;
         };
 
       router =
diff --git a/nixos/tests/phabricator.nix b/nixos/tests/phabricator.nix
index 53038474c91..0fe31f66502 100644
--- a/nixos/tests/phabricator.nix
+++ b/nixos/tests/phabricator.nix
@@ -32,9 +32,16 @@ import ./make-test.nix ({ pkgs, ... }: {
             }];
           };
 
+          phd = {
+            enable = true;
+          };
+
           mysql = {
             enable = true;
             package = pkgs.mysql;
+            extraOptions = ''
+              sql_mode=STRICT_ALL_TABLES
+            '';
           };
         };