summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2016-01-19 09:55:31 +0100
committerVladimír Čunát <vcunat@gmail.com>2016-01-19 09:55:31 +0100
commit716aac2519a7571e7f5fd984a886d579a4a051c5 (patch)
tree53cf89cf764d787f4dc8f08474479892b9733177 /nixos/modules
parentf8472457a440de3c44f6f604142d678b6ae2a762 (diff)
parent53b389327e34de319dc0dbda2b6bcab1a69db69d (diff)
downloadnixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.tar
nixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.tar.gz
nixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.tar.bz2
nixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.tar.lz
nixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.tar.xz
nixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.tar.zst
nixpkgs-716aac2519a7571e7f5fd984a886d579a4a051c5.zip
Merge branch 'staging' into closure-size
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/config/ldap.nix1
-rw-r--r--nixos/modules/config/pulseaudio.nix1
-rw-r--r--nixos/modules/config/shells-environment.nix1
-rw-r--r--nixos/modules/config/swap.nix5
-rw-r--r--nixos/modules/config/sysctl.nix7
-rw-r--r--nixos/modules/config/unix-odbc-drivers.nix5
-rw-r--r--nixos/modules/config/users-groups.nix2
-rw-r--r--nixos/modules/hardware/video/encoder/wis-go7007.nix15
-rw-r--r--nixos/modules/installer/cd-dvd/channel.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix5
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-pc.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix4
-rw-r--r--nixos/modules/installer/tools/tools.nix2
-rw-r--r--nixos/modules/misc/crashdump.nix1
-rw-r--r--nixos/modules/misc/ids.nix22
-rw-r--r--nixos/modules/misc/nixos.nix4
-rw-r--r--nixos/modules/misc/version.nix72
-rw-r--r--nixos/modules/module-list.nix17
-rw-r--r--nixos/modules/profiles/graphical.nix1
-rw-r--r--nixos/modules/profiles/installation-device.nix2
-rw-r--r--nixos/modules/programs/cdemu.nix2
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.nix6
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.pl3
-rw-r--r--nixos/modules/programs/fish.nix114
-rw-r--r--nixos/modules/programs/ssh.nix24
-rw-r--r--nixos/modules/programs/zsh/zsh.nix12
-rw-r--r--nixos/modules/rename.nix14
-rw-r--r--nixos/modules/security/acme.nix12
-rw-r--r--nixos/modules/security/audit.nix109
-rw-r--r--nixos/modules/services/audio/fuppes.nix115
-rw-r--r--nixos/modules/services/audio/fuppes/vfolder.cfg155
-rw-r--r--nixos/modules/services/audio/liquidsoap.nix2
-rw-r--r--nixos/modules/services/audio/mpd.nix4
-rw-r--r--nixos/modules/services/backup/bacula.nix4
-rw-r--r--nixos/modules/services/backup/rsnapshot.nix1
-rw-r--r--nixos/modules/services/backup/tarsnap.nix66
-rw-r--r--nixos/modules/services/continuous-integration/jenkins/default.nix1
-rw-r--r--nixos/modules/services/continuous-integration/jenkins/job-builder.nix2
-rw-r--r--nixos/modules/services/databases/4store-endpoint.nix8
-rw-r--r--nixos/modules/services/databases/4store.nix9
-rw-r--r--nixos/modules/services/databases/couchdb.nix1
-rw-r--r--nixos/modules/services/databases/firebird.nix1
-rw-r--r--nixos/modules/services/databases/hbase.nix1
-rw-r--r--nixos/modules/services/databases/influxdb.nix1
-rw-r--r--nixos/modules/services/databases/mongodb.nix1
-rw-r--r--nixos/modules/services/databases/neo4j.nix5
-rw-r--r--nixos/modules/services/databases/openldap.nix30
-rw-r--r--nixos/modules/services/databases/opentsdb.nix1
-rw-r--r--nixos/modules/services/databases/postgresql.nix4
-rw-r--r--nixos/modules/services/databases/redis.nix1
-rw-r--r--nixos/modules/services/databases/virtuoso.nix25
-rw-r--r--nixos/modules/services/games/ghost-one.nix4
-rw-r--r--nixos/modules/services/hardware/acpid.nix117
-rw-r--r--nixos/modules/services/hardware/freefall.nix1
-rw-r--r--nixos/modules/services/hardware/irqbalance.nix30
-rw-r--r--nixos/modules/services/hardware/pommed.nix15
-rw-r--r--nixos/modules/services/hardware/sane.nix4
-rw-r--r--nixos/modules/services/hardware/thinkfan.nix24
-rw-r--r--nixos/modules/services/hardware/upower.nix1
-rw-r--r--nixos/modules/services/logging/klogd.nix25
-rw-r--r--nixos/modules/services/logging/logrotate.nix1
-rw-r--r--nixos/modules/services/logging/logstash.nix3
-rw-r--r--nixos/modules/services/logging/syslog-ng.nix1
-rw-r--r--nixos/modules/services/mail/dovecot.nix3
-rw-r--r--nixos/modules/services/mail/dspam.nix147
-rw-r--r--nixos/modules/services/mail/freepops.nix17
-rw-r--r--nixos/modules/services/mail/opendkim.nix109
-rw-r--r--nixos/modules/services/mail/postfix.nix233
-rw-r--r--nixos/modules/services/mail/postsrsd.nix107
-rw-r--r--nixos/modules/services/mail/rmilter.nix189
-rw-r--r--nixos/modules/services/mail/rspamd.nix90
-rw-r--r--nixos/modules/services/mail/spamassassin.nix6
-rw-r--r--nixos/modules/services/misc/apache-kafka.nix3
-rw-r--r--nixos/modules/services/misc/autofs.nix3
-rw-r--r--nixos/modules/services/misc/cgminer.nix1
-rw-r--r--nixos/modules/services/misc/confd.nix1
-rw-r--r--nixos/modules/services/misc/dictd.nix15
-rw-r--r--nixos/modules/services/misc/disnix.nix111
-rw-r--r--nixos/modules/services/misc/docker-registry.nix6
-rw-r--r--nixos/modules/services/misc/etcd.nix10
-rw-r--r--nixos/modules/services/misc/felix.nix97
-rw-r--r--nixos/modules/services/misc/folding-at-home.nix32
-rw-r--r--nixos/modules/services/misc/gitit.nix1
-rw-r--r--nixos/modules/services/misc/ihaskell.nix1
-rw-r--r--nixos/modules/services/misc/mathics.nix54
-rw-r--r--nixos/modules/services/misc/matrix-synapse-log_config.yaml25
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix279
-rw-r--r--nixos/modules/services/misc/mbpfan.nix2
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix1
-rw-r--r--nixos/modules/services/misc/plex.nix19
-rw-r--r--nixos/modules/services/misc/rippled.nix7
-rw-r--r--nixos/modules/services/misc/subsonic.nix4
-rw-r--r--nixos/modules/services/misc/svnserve.nix10
-rw-r--r--nixos/modules/services/monitoring/bosun.nix1
-rw-r--r--nixos/modules/services/monitoring/cadvisor.nix6
-rw-r--r--nixos/modules/services/monitoring/grafana.nix1
-rw-r--r--nixos/modules/services/monitoring/graphite.nix23
-rw-r--r--nixos/modules/services/monitoring/heapster.nix1
-rw-r--r--nixos/modules/services/monitoring/monit.nix16
-rw-r--r--nixos/modules/services/monitoring/munin.nix18
-rw-r--r--nixos/modules/services/monitoring/nagios.nix6
-rw-r--r--nixos/modules/services/monitoring/scollector.nix3
-rw-r--r--nixos/modules/services/monitoring/statsd.nix4
-rw-r--r--nixos/modules/services/monitoring/ups.nix29
-rw-r--r--nixos/modules/services/network-filesystems/drbd.nix38
-rw-r--r--nixos/modules/services/network-filesystems/openafs-client/default.nix52
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix3
-rw-r--r--nixos/modules/services/networking/amuled.nix31
-rw-r--r--nixos/modules/services/networking/bind.nix25
-rw-r--r--nixos/modules/services/networking/btsync.nix39
-rw-r--r--nixos/modules/services/networking/consul.nix22
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix16
-rw-r--r--nixos/modules/services/networking/ejabberd.nix192
-rw-r--r--nixos/modules/services/networking/firewall.nix3
-rw-r--r--nixos/modules/services/networking/gale.nix182
-rw-r--r--nixos/modules/services/networking/git-daemon.nix9
-rw-r--r--nixos/modules/services/networking/gvpe.nix32
-rw-r--r--nixos/modules/services/networking/ifplugd.nix26
-rw-r--r--nixos/modules/services/networking/ircd-hybrid/default.nix18
-rw-r--r--nixos/modules/services/networking/lambdabot.nix1
-rw-r--r--nixos/modules/services/networking/networkmanager.nix2
-rw-r--r--nixos/modules/services/networking/ngircd.nix1
-rw-r--r--nixos/modules/services/networking/notbit.nix130
-rw-r--r--nixos/modules/services/networking/oidentd.nix17
-rw-r--r--nixos/modules/services/networking/openfire.nix48
-rw-r--r--nixos/modules/services/networking/ostinato.nix104
-rw-r--r--nixos/modules/services/networking/prayer.nix25
-rw-r--r--nixos/modules/services/networking/radicale.nix12
-rw-r--r--nixos/modules/services/networking/shout.nix4
-rw-r--r--nixos/modules/services/networking/skydns.nix1
-rw-r--r--nixos/modules/services/networking/softether.nix6
-rw-r--r--nixos/modules/services/networking/ssh/lshd.nix106
-rw-r--r--nixos/modules/services/networking/sslh.nix4
-rw-r--r--nixos/modules/services/networking/supplicant.nix2
-rw-r--r--nixos/modules/services/networking/syncthing.nix1
-rw-r--r--nixos/modules/services/networking/tcpcrypt.nix8
-rw-r--r--nixos/modules/services/networking/tinc.nix24
-rw-r--r--nixos/modules/services/networking/vsftpd.nix2
-rw-r--r--nixos/modules/services/networking/wicd.nix14
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix163
-rw-r--r--nixos/modules/services/networking/xinetd.nix22
-rw-r--r--nixos/modules/services/scheduling/atd.nix84
-rw-r--r--nixos/modules/services/scheduling/fcron.nix38
-rw-r--r--nixos/modules/services/search/elasticsearch.nix7
-rw-r--r--nixos/modules/services/search/kibana.nix5
-rw-r--r--nixos/modules/services/search/solr.nix2
-rw-r--r--nixos/modules/services/security/fail2ban.nix1
-rw-r--r--nixos/modules/services/security/fprot.nix32
-rw-r--r--nixos/modules/services/system/kerberos.nix33
-rw-r--r--nixos/modules/services/system/uptimed.nix26
-rw-r--r--nixos/modules/services/ttys/agetty.nix20
-rw-r--r--nixos/modules/services/ttys/kmscon.nix9
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix4
-rw-r--r--nixos/modules/services/web-servers/jboss/default.nix13
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix1
-rw-r--r--nixos/modules/services/web-servers/phpfpm.nix2
-rw-r--r--nixos/modules/services/web-servers/tomcat.nix396
-rw-r--r--nixos/modules/services/web-servers/winstone.nix1
-rw-r--r--nixos/modules/services/web-servers/zope2.nix39
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/kdm.nix1
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix6
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix3
-rw-r--r--nixos/modules/services/x11/display-managers/slim.nix4
-rw-r--r--nixos/modules/services/x11/redshift.nix1
-rw-r--r--nixos/modules/services/x11/terminal-server.nix15
-rw-r--r--nixos/modules/services/x11/window-managers/windowlab.nix22
-rw-r--r--nixos/modules/services/x11/xfs.nix17
-rw-r--r--nixos/modules/services/x11/xserver.nix3
-rw-r--r--nixos/modules/system/activation/top-level.nix8
-rw-r--r--nixos/modules/system/boot/kernel.nix7
-rw-r--r--nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh4
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix3
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl4
-rw-r--r--nixos/modules/system/boot/loader/grub/ipxe.nix2
-rw-r--r--nixos/modules/system/boot/luksroot.nix2
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh1
-rw-r--r--nixos/modules/system/boot/stage-1.nix11
-rw-r--r--nixos/modules/system/boot/systemd.nix6
-rw-r--r--nixos/modules/system/etc/etc.nix5
-rw-r--r--nixos/modules/system/upstart/upstart.nix290
-rw-r--r--nixos/modules/tasks/filesystems/btrfs.nix12
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix19
-rw-r--r--nixos/modules/tasks/kbd.nix12
-rw-r--r--nixos/modules/tasks/network-interfaces.nix2
-rw-r--r--nixos/modules/tasks/trackpoint.nix2
-rw-r--r--nixos/modules/testing/test-instrumentation.nix5
-rw-r--r--nixos/modules/virtualisation/azure-image.nix4
-rw-r--r--nixos/modules/virtualisation/brightbox-image.nix2
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix2
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix54
-rw-r--r--nixos/modules/virtualisation/lxd.nix2
-rw-r--r--nixos/modules/virtualisation/openvswitch.nix1
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix4
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix4
199 files changed, 3331 insertions, 2139 deletions
diff --git a/nixos/modules/config/ldap.nix b/nixos/modules/config/ldap.nix
index c87996df885..a6657768e06 100644
--- a/nixos/modules/config/ldap.nix
+++ b/nixos/modules/config/ldap.nix
@@ -57,6 +57,7 @@ in
     users.ldap = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = "Whether to enable authentication against an LDAP server.";
       };
diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix
index 2c40895296c..334fa1f772c 100644
--- a/nixos/modules/config/pulseaudio.nix
+++ b/nixos/modules/config/pulseaudio.nix
@@ -99,6 +99,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pulseaudioLight;
+        defaultText = "pkgs.pulseaudioLight";
         example = literalExample "pkgs.pulseaudioFull";
         description = ''
           The PulseAudio derivation to use.  This can be used to enable
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index d0243f9775c..9642981803b 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -119,6 +119,7 @@ in
 
     environment.binsh = mkOption {
       default = "${config.system.build.binsh}/bin/sh";
+      defaultText = "\${config.system.build.binsh}/bin/sh";
       example = literalExample ''
         "''${pkgs.dash}/bin/dash"
       '';
diff --git a/nixos/modules/config/swap.nix b/nixos/modules/config/swap.nix
index 9a5d6a9fc33..f0353c5a35e 100644
--- a/nixos/modules/config/swap.nix
+++ b/nixos/modules/config/swap.nix
@@ -128,6 +128,7 @@ in
             wantedBy = [ "${realDevice'}.swap" ];
             before = [ "${realDevice'}.swap" ];
             path = [ pkgs.utillinux ] ++ optional sw.randomEncryption pkgs.cryptsetup;
+
             script =
               ''
                 ${optionalString (sw.size != null) ''
@@ -145,11 +146,13 @@ in
                   mkswap ${sw.realDevice}
                 ''}
               '';
+
             unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
             unitConfig.DefaultDependencies = false; # needed to prevent a cycle
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = sw.randomEncryption;
-            serviceConfig.ExecStop = optionalString sw.randomEncryption "cryptsetup luksClose ${sw.deviceName}";
+            serviceConfig.ExecStop = optionalString sw.randomEncryption "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
+            restartIfChanged = false;
           };
 
       in listToAttrs (map createSwapDevice (filter (sw: sw.size != null || sw.randomEncryption) config.swapDevices));
diff --git a/nixos/modules/config/sysctl.nix b/nixos/modules/config/sysctl.nix
index e83562a8356..61b02c5ffa6 100644
--- a/nixos/modules/config/sysctl.nix
+++ b/nixos/modules/config/sysctl.nix
@@ -22,10 +22,9 @@ in
 
     boot.kernel.sysctl = mkOption {
       default = {};
-      example = {
-        "net.ipv4.tcp_syncookies" = false;
-        "vm.swappiness" = 60;
-      };
+      example = literalExample ''
+        { "net.ipv4.tcp_syncookies" = false; "vm.swappiness" = 60; }
+      '';
       type = types.attrsOf sysctlOption;
       description = ''
         Runtime parameters of the Linux kernel, as set by
diff --git a/nixos/modules/config/unix-odbc-drivers.nix b/nixos/modules/config/unix-odbc-drivers.nix
index 98929392ace..eea6477fff2 100644
--- a/nixos/modules/config/unix-odbc-drivers.nix
+++ b/nixos/modules/config/unix-odbc-drivers.nix
@@ -10,8 +10,9 @@ with lib;
 
   options = {
     environment.unixODBCDrivers = mkOption {
+      type = types.listOf types.package;
       default = [];
-      example = literalExample "map (x : x.ini) (with pkgs.unixODBCDrivers; [ mysql psql psqlng ] )";
+      example = literalExample "with pkgs.unixODBCDrivers; [ mysql psql psqlng ]";
       description = ''
         Specifies Unix ODBC drivers to be registered in
         <filename>/etc/odbcinst.ini</filename>.  You may also want to
@@ -26,7 +27,7 @@ with lib;
   config = mkIf (config.environment.unixODBCDrivers != []) {
 
     environment.etc."odbcinst.ini".text =
-      let inis = config.environment.unixODBCDrivers;
+      let inis = map (x : x.ini) config.environment.unixODBCDrivers;
       in lib.concatStringsSep "\n" inis;
 
   };
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 485926fb1dd..e643b2d059b 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -26,7 +26,7 @@ let
   '';
 
   hashedPasswordDescription = ''
-    To generate hashed password install <literal>mkpassword</literal>
+    To generate hashed password install <literal>mkpasswd</literal>
     package and run <literal>mkpasswd -m sha-512</literal>.
   '';
 
diff --git a/nixos/modules/hardware/video/encoder/wis-go7007.nix b/nixos/modules/hardware/video/encoder/wis-go7007.nix
deleted file mode 100644
index e9b3cf72a8d..00000000000
--- a/nixos/modules/hardware/video/encoder/wis-go7007.nix
+++ /dev/null
@@ -1,15 +0,0 @@
-{pkgs, config, ...}:
-
-let
-  wis_go7007 = config.boot.kernelPackages.wis_go7007;
-in
-
-{
-  boot.extraModulePackages = [ wis_go7007 ];
-
-  environment.systemPackages = [ wis_go7007 ];
-
-  hardware.firmware = [ wis_go7007 ];
-
-  services.udev.packages = [ wis_go7007 ];
-}
diff --git a/nixos/modules/installer/cd-dvd/channel.nix b/nixos/modules/installer/cd-dvd/channel.nix
index ea7e3e16b8d..1e5e2b2615c 100644
--- a/nixos/modules/installer/cd-dvd/channel.nix
+++ b/nixos/modules/installer/cd-dvd/channel.nix
@@ -17,7 +17,9 @@ let
       mkdir -p $out
       cp -prd ${pkgs.path} $out/nixos
       chmod -R u+w $out/nixos
-      ln -s . $out/nixos/nixpkgs
+      if [ ! -e $out/nixos/nixpkgs ]; then
+        ln -s . $out/nixos/nixpkgs
+      fi
       rm -rf $out/nixos/.git
       echo -n ${config.system.nixosVersionSuffix} > $out/nixos/.version-suffix
     '';
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
index bc3bd872d2a..2569860a098 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -16,7 +16,7 @@ with lib;
     ];
 
   # ISO naming.
-  isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixosVersion}-${pkgs.stdenv.system}.iso";
+  isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixosLabel}-${pkgs.stdenv.system}.iso";
 
   isoImage.volumeID = substring 0 11 "NIXOS_ISO";
 
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index d3353ee7d64..248b0f00283 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -39,7 +39,7 @@ let
     DEFAULT boot
 
     LABEL boot
-    MENU LABEL NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel}
+    MENU LABEL NixOS ${config.system.nixosLabel}${config.isoImage.appendToMenuLabel}
     LINUX /boot/bzImage
     APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
     INITRD /boot/initrd
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
index bbf0311c04d..6fe490b02bf 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
+++ b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
@@ -74,7 +74,7 @@ in
 
       # Tools to create / manipulate filesystems.
       pkgs.ntfsprogs # for resizing NTFS partitions
-      pkgs.btrfsProgs
+      pkgs.btrfs-progs
       pkgs.jfsutils
 
       # Some compression/archiver tools.
@@ -149,8 +149,7 @@ in
   # not be started by default on the installation CD because the
   # default root password is empty.
   services.openssh.enable = true;
-
-  jobs.openssh.startOn = lib.mkOverride 50 "";
+  systemd.services.openssh.wantedBy = lib.mkOverride 50 [];
 
   boot.loader.grub.enable = false;
   boot.loader.generationsDir.enable = false;
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-pc.nix b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix
index 1156003d3f4..5da5df81ede 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball-pc.nix
+++ b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix
@@ -109,7 +109,7 @@ in
   # not be started by default on the installation CD because the
   # default root password is empty.
   services.openssh.enable = true;
-  jobs.openssh.startOn = lib.mkOverride 50 "";
+  systemd.services.openssh.wantedBy = lib.mkOverride 50 [];
 
   # To be able to use the systemTarball to catch troubles.
   boot.crashDump = {
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
index 46dc1c70502..de0cc604bf3 100644
--- a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
+++ b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
@@ -67,7 +67,7 @@ in
       pkgs.dmraid
 
       # Tools to create / manipulate filesystems.
-      pkgs.btrfsProgs
+      pkgs.btrfs-progs
 
       # Some compression/archiver tools.
       pkgs.unzip
@@ -164,7 +164,7 @@ in
   # not be started by default on the installation CD because the
   # default root password is empty.
   services.openssh.enable = true;
-  jobs.openssh.startOn = lib.mkOverride 50 "";
+  systemd.services.openssh.wantedBy = lib.mkOverride 50 [];
 
   # cpufrequtils fails to build on non-pc
   powerManagement.enable = false;
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 04e4c1eb945..9ac3b7a5b16 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -38,7 +38,7 @@ let
   nixos-generate-config = makeProg {
     name = "nixos-generate-config";
     src = ./nixos-generate-config.pl;
-    path = [ pkgs.btrfsProgs ];
+    path = [ pkgs.btrfs-progs ];
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
     inherit (config.system) nixosRelease;
   };
diff --git a/nixos/modules/misc/crashdump.nix b/nixos/modules/misc/crashdump.nix
index 773b5ac9da3..5ef4b7781bd 100644
--- a/nixos/modules/misc/crashdump.nix
+++ b/nixos/modules/misc/crashdump.nix
@@ -24,6 +24,7 @@ in
           '';
         };
         kernelPackages = mkOption {
+          type = types.package;
           default = pkgs.linuxPackages;
           # We don't want to evaluate all of linuxPackages for the manual
           # - some of it might not even evaluate correctly.
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 7a7ed2f4408..064b4cbc4b3 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -136,7 +136,7 @@
       kippo = 108;
       jenkins = 109;
       systemd-journal-gateway = 110;
-      notbit = 111;
+      #notbit = 111; # unused
       ngircd = 112;
       btsync = 113;
       minecraft = 114;
@@ -239,6 +239,15 @@
       bepasty = 215;
       pumpio = 216;
       nm-openvpn = 217;
+      mathics = 218;
+      ejabberd = 219;
+      postsrsd = 220;
+      opendkim = 221;
+      dspam = 222;
+      gale = 223;
+      matrix-synapse = 224;
+      rspamd = 225;
+      rmilter = 226;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -355,7 +364,7 @@
       kippo = 108;
       jenkins = 109;
       systemd-journal-gateway = 110;
-      notbit = 111;
+      #notbit = 111; # unused
       #ngircd = 112; # unused
       btsync = 113;
       #minecraft = 114; # unused
@@ -455,6 +464,15 @@
       bepasty = 215;
       pumpio = 216;
       nm-openvpn = 217;
+      mathics = 218;
+      ejabberd = 219;
+      postsrsd = 220;
+      opendkim = 221;
+      dspam = 222;
+      gale = 223;
+      matrix-synapse = 224;
+      rspamd = 225;
+      rmilter = 226;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/misc/nixos.nix b/nixos/modules/misc/nixos.nix
index 356129211d0..84365b640a4 100644
--- a/nixos/modules/misc/nixos.nix
+++ b/nixos/modules/misc/nixos.nix
@@ -37,8 +37,8 @@ with lib;
 
     nixos.extraModules = mkOption {
       default = [];
-      example = literalExample "mkIf config.services.openssh.enable [ ./sshd-config.nix ]";
-      type = types.listOf types.unspecified;
+      example = literalExample "[ ./sshd-config.nix ]";
+      type = types.listOf (types.either (types.submodule ({...}:{options={};})) types.path);
       description = ''
         Define additional modules which would be loaded to evaluate the
         configuration.
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index b4b0281fe58..18f270cd531 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -2,13 +2,21 @@
 
 with lib;
 
+let
+  cfg = config.system;
+
+  releaseFile = "${toString pkgs.path}/.version";
+  suffixFile = "${toString pkgs.path}/.version-suffix";
+  revisionFile = "${toString pkgs.path}/.git-revision";
+in
+
 {
 
-  options = {
+  options.system = {
 
-    system.stateVersion = mkOption {
+    stateVersion = mkOption {
       type = types.str;
-      default = config.system.nixosRelease;
+      default = cfg.nixosRelease;
       description = ''
         Every once in a while, a new NixOS release may change
         configuration defaults in a way incompatible with stateful
@@ -22,38 +30,63 @@ with lib;
       '';
     };
 
-    system.nixosVersion = mkOption {
+    nixosLabel = mkOption {
+      type = types.str;
+      description = ''
+        NixOS version name to be used in the names of generated
+        outputs and boot labels.
+
+        If you ever wanted to influence the labels in your GRUB menu,
+        this is option is for you.
+
+        Can be set directly or with <envar>NIXOS_LABEL</envar>
+        environment variable for <command>nixos-rebuild</command>,
+        e.g.:
+
+        <screen>
+        #!/bin/sh
+        today=`date +%Y%m%d`
+        branch=`(cd nixpkgs ; git branch 2>/dev/null | sed -n '/^\* / { s|^\* ||; p; }')`
+        revision=`(cd nixpkgs ; git rev-parse HEAD)`
+        export NIXOS_LABEL="$today.$branch-''${revision:0:7}"
+        nixos-rebuild switch</screen>
+      '';
+    };
+
+    nixosVersion = mkOption {
       internal = true;
       type = types.str;
       description = "NixOS version.";
     };
 
-    system.nixosRelease = mkOption {
+    nixosRelease = mkOption {
       readOnly = true;
       type = types.str;
-      default = readFile "${toString pkgs.path}/.version";
+      default = readFile releaseFile;
       description = "NixOS release.";
     };
 
-    system.nixosVersionSuffix = mkOption {
+    nixosVersionSuffix = mkOption {
       internal = true;
       type = types.str;
+      default = if pathExists suffixFile then readFile suffixFile else "pre-git";
       description = "NixOS version suffix.";
     };
 
-    system.nixosRevision = mkOption {
+    nixosRevision = mkOption {
       internal = true;
       type = types.str;
+      default = if pathExists revisionFile then readFile revisionFile else "master";
       description = "NixOS Git revision hash.";
     };
 
-    system.nixosCodeName = mkOption {
+    nixosCodeName = mkOption {
       readOnly = true;
       type = types.str;
       description = "NixOS release code name.";
     };
 
-    system.defaultChannel = mkOption {
+    defaultChannel = mkOption {
       internal = true;
       type = types.str;
       default = https://nixos.org/channels/nixos-unstable;
@@ -64,18 +97,15 @@ with lib;
 
   config = {
 
-    system.nixosVersion = mkDefault (config.system.nixosRelease + config.system.nixosVersionSuffix);
-
-    system.nixosVersionSuffix =
-      let suffixFile = "${toString pkgs.path}/.version-suffix"; in
-      mkDefault (if pathExists suffixFile then readFile suffixFile else "pre-git");
+    system = {
+      # These defaults are set here rather than up there so that
+      # changing them would not rebuild the manual
+      nixosLabel   = mkDefault (maybeEnv "NIXOS_LABEL" cfg.nixosVersion);
+      nixosVersion = mkDefault (maybeEnv "NIXOS_VERSION" (cfg.nixosRelease + cfg.nixosVersionSuffix));
 
-    system.nixosRevision =
-      let fn = "${toString pkgs.path}/.git-revision"; in
-      mkDefault (if pathExists fn then readFile fn else "master");
-
-    # Note: code names must only increase in alphabetical order.
-    system.nixosCodeName = "Emu";
+      # Note: code names must only increase in alphabetical order.
+      nixosCodeName = "Emu";
+    };
 
     # Generate /etc/os-release.  See
     # http://0pointer.de/public/systemd-man/os-release.html for the
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 5c1cde98d3d..2ff61877c23 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -64,6 +64,7 @@
   ./programs/dconf.nix
   ./programs/environment.nix
   ./programs/freetds.nix
+  ./programs/fish.nix
   ./programs/ibus.nix
   ./programs/kbdlight.nix
   ./programs/light.nix
@@ -83,6 +84,7 @@
   ./security/acme.nix
   ./security/apparmor.nix
   ./security/apparmor-suid.nix
+  ./security/audit.nix
   ./security/ca.nix
   ./security/duosec.nix
   ./security/grsecurity.nix
@@ -98,8 +100,6 @@
   ./services/amqp/activemq/default.nix
   ./services/amqp/rabbitmq.nix
   ./services/audio/alsa.nix
-  # Disabled as fuppes no longer builds.
-  # ./services/audio/fuppes.nix
   ./services/audio/icecast.nix
   ./services/audio/liquidsoap.nix
   ./services/audio/mpd.nix
@@ -162,6 +162,7 @@
   ./services/hardware/bluetooth.nix
   ./services/hardware/brltty.nix
   ./services/hardware/freefall.nix
+  ./services/hardware/irqbalance.nix
   ./services/hardware/nvidia-optimus.nix
   ./services/hardware/pcscd.nix
   ./services/hardware/pommed.nix
@@ -182,13 +183,18 @@
   ./services/logging/syslogd.nix
   ./services/logging/syslog-ng.nix
   ./services/mail/dovecot.nix
+  ./services/mail/dspam.nix
   ./services/mail/exim.nix
   ./services/mail/freepops.nix
   ./services/mail/mail.nix
   ./services/mail/mlmmj.nix
+  ./services/mail/opendkim.nix
   ./services/mail/opensmtpd.nix
   ./services/mail/postfix.nix
+  ./services/mail/postsrsd.nix
   ./services/mail/spamassassin.nix
+  ./services/mail/rspamd.nix
+  ./services/mail/rmilter.nix
   ./services/misc/apache-kafka.nix
   ./services/misc/autofs.nix
   ./services/misc/bepasty.nix
@@ -209,6 +215,8 @@
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
   ./services/misc/ihaskell.nix
+  ./services/misc/mathics.nix
+  ./services/misc/matrix-synapse.nix
   ./services/misc/mbpfan.nix
   ./services/misc/mediatomb.nix
   ./services/misc/mesos-master.nix
@@ -296,6 +304,7 @@
   ./services/networking/firewall.nix
   ./services/networking/flashpolicyd.nix
   ./services/networking/freenet.nix
+  ./services/networking/gale.nix
   ./services/networking/gateone.nix
   ./services/networking/git-daemon.nix
   ./services/networking/gnunet.nix
@@ -321,7 +330,6 @@
   ./services/networking/networkmanager.nix
   ./services/networking/ngircd.nix
   ./services/networking/nix-serve.nix
-  ./services/networking/notbit.nix
   ./services/networking/nsd.nix
   ./services/networking/ntopng.nix
   ./services/networking/ntpd.nix
@@ -330,6 +338,7 @@
   ./services/networking/openfire.nix
   ./services/networking/openntpd.nix
   ./services/networking/openvpn.nix
+  ./services/networking/ostinato.nix
   ./services/networking/polipo.nix
   ./services/networking/prayer.nix
   ./services/networking/privoxy.nix
@@ -441,6 +450,7 @@
   ./services/x11/window-managers/metacity.nix
   ./services/x11/window-managers/none.nix
   ./services/x11/window-managers/twm.nix
+  ./services/x11/window-managers/windowlab.nix
   ./services/x11/window-managers/wmii.nix
   ./services/x11/window-managers/xmonad.nix
   ./services/x11/xfs.nix
@@ -473,7 +483,6 @@
   ./system/boot/timesyncd.nix
   ./system/boot/tmp.nix
   ./system/etc/etc.nix
-  ./system/upstart/upstart.nix
   ./tasks/bcache.nix
   ./tasks/cpu-freq.nix
   ./tasks/encrypted-devices.nix
diff --git a/nixos/modules/profiles/graphical.nix b/nixos/modules/profiles/graphical.nix
index 75ac5e41f83..8ee1628f876 100644
--- a/nixos/modules/profiles/graphical.nix
+++ b/nixos/modules/profiles/graphical.nix
@@ -8,6 +8,7 @@
     enable = true;
     displayManager.kdm.enable = true;
     desktopManager.kde4.enable = true;
+    synaptics.enable = true; # for touchpad support on many laptops
   };
 
   environment.systemPackages = [ pkgs.glxinfo ];
diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix
index 946032781f4..669b6975c69 100644
--- a/nixos/modules/profiles/installation-device.nix
+++ b/nixos/modules/profiles/installation-device.nix
@@ -51,7 +51,7 @@ with lib;
 
     # Enable wpa_supplicant, but don't start it by default.
     networking.wireless.enable = mkDefault true;
-    jobs.wpa_supplicant.startOn = mkOverride 50 "";
+    systemd.services.wpa_supplicant.wantedBy = mkOverride 50 [];
 
     # Tell the Nix evaluator to garbage collect more aggressively.
     # This is desirable in memory-constrained environments that don't
diff --git a/nixos/modules/programs/cdemu.nix b/nixos/modules/programs/cdemu.nix
index 98df9b94380..6a0185d362c 100644
--- a/nixos/modules/programs/cdemu.nix
+++ b/nixos/modules/programs/cdemu.nix
@@ -38,7 +38,7 @@ in {
   config = mkIf cfg.enable {
 
     boot = {
-      extraModulePackages = [ pkgs.linuxPackages.vhba ];
+      extraModulePackages = [ config.boot.kernelPackages.vhba ];
       kernelModules = [ "vhba" ];
     };
 
diff --git a/nixos/modules/programs/command-not-found/command-not-found.nix b/nixos/modules/programs/command-not-found/command-not-found.nix
index 9524d91ea3b..9741aa7ca53 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.nix
+++ b/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -16,7 +16,7 @@ let
     isExecutable = true;
     inherit (pkgs) perl;
     perlFlags = concatStrings (map (path: "-I ${path}/lib/perl5/site_perl ")
-      [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite ]);
+      [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite pkgs.perlPackages.StringShellQuote ]);
   };
 
 in
@@ -30,7 +30,7 @@ in
         local p=/run/current-system/sw/bin/command-not-found
         if [ -x $p -a -f /nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite ]; then
           # Run the helper program.
-          $p "$1"
+          $p "$@"
           # Retry the command if we just installed it.
           if [ $? = 126 ]; then
             "$@"
@@ -51,7 +51,7 @@ in
         local p=/run/current-system/sw/bin/command-not-found
         if [ -x $p -a -f /nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite ]; then
           # Run the helper program.
-          $p "$1"
+          $p "$@"
 
           # Retry the command if we just installed it.
           if [ $? = 126 ]; then
diff --git a/nixos/modules/programs/command-not-found/command-not-found.pl b/nixos/modules/programs/command-not-found/command-not-found.pl
index b233d973a4a..5bdda26592e 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.pl
+++ b/nixos/modules/programs/command-not-found/command-not-found.pl
@@ -3,6 +3,7 @@
 use strict;
 use DBI;
 use DBD::SQLite;
+use String::ShellQuote;
 use Config;
 
 my $program = $ARGV[0];
@@ -31,6 +32,8 @@ the package ‘$package’, which I will now install for you.
 EOF
         ;
         exit 126 if system("nix-env", "-iA", "nixos.$package") == 0;
+    } elsif ($ENV{"NIX_AUTO_RUN"} // "") {
+        exec("nix-shell", "-p", $package, "--run", shell_quote("exec", @ARGV));
     } else {
         print STDERR <<EOF;
 The program ‘$program’ is currently not installed. You can install it by typing:
diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix
new file mode 100644
index 00000000000..b4259f7ec87
--- /dev/null
+++ b/nixos/modules/programs/fish.nix
@@ -0,0 +1,114 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfge = config.environment;
+
+  cfg = config.programs.fish;
+
+  fishAliases = concatStringsSep "\n" (
+    mapAttrsFlatten (k: v: "alias ${k} '${v}'") cfg.shellAliases
+  );
+
+in
+
+{
+
+  options = {
+
+    programs.fish = {
+
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to configure fish as an interactive shell.
+        '';
+        type = types.bool;
+      };
+
+      shellAliases = mkOption {
+        default = config.environment.shellAliases;
+        description = ''
+          Set of aliases for fish shell. See <option>environment.shellAliases</option>
+          for an option format description.
+        '';
+        type = types.attrs;
+      };
+
+      shellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during fish shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      loginShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during fish login shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      interactiveShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during interactive fish shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      promptInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code used to initialise fish prompt.
+        '';
+        type = types.lines;
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit;
+    environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit;
+    environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit;
+
+    environment.etc."fish/config.fish".text = ''
+      # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically.
+
+      set fish_function_path $fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions
+
+      fenv source ${config.system.build.setEnvironment} 1> /dev/null
+      fenv source /etc/fish/foreign-env/shellInit 1> /dev/null
+
+      ${cfg.shellInit}
+
+      if builtin status --is-login
+        fenv source /etc/fish/foreign-env/loginShellInit 1> /dev/null
+        ${cfg.loginShellInit}
+      end
+
+      if builtin status --is-interactive
+        ${fishAliases}
+        fenv source /etc/fish/foreign-env/interactiveShellInit 1> /dev/null
+        ${cfg.interactiveShellInit}
+      end
+    '';
+
+    environment.systemPackages = [ pkgs.fish ];
+
+    environment.shells = [
+      "/run/current-system/sw/bin/fish"
+      "/var/run/current-system/sw/bin/fish"
+      "${pkgs.fish}/bin/fish"
+    ];
+
+  };
+
+}
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 87a7bac208b..260888be485 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -93,7 +93,9 @@ in
       };
 
       package = mkOption {
+        type = types.package;
         default = pkgs.openssh;
+        defaultText = "pkgs.openssh";
         description = ''
           The package used for the openssh client and daemon.
         '';
@@ -142,16 +144,18 @@ in
         description = ''
           The set of system-wide known SSH hosts.
         '';
-        example = [
-          {
-            hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
-            publicKeyFile = literalExample "./pubkeys/myhost_ssh_host_dsa_key.pub";
-          }
-          {
-            hostNames = [ "myhost2" ];
-            publicKeyFile = literalExample "./pubkeys/myhost2_ssh_host_dsa_key.pub";
-          }
-        ];
+        example = literalExample ''
+          [
+            {
+              hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
+              publicKeyFile = "./pubkeys/myhost_ssh_host_dsa_key.pub";
+            }
+            {
+              hostNames = [ "myhost2" ];
+              publicKeyFile = "./pubkeys/myhost2_ssh_host_dsa_key.pub";
+            }
+          ]
+        '';
       };
 
     };
diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix
index dae7e446b4c..b51104c16fa 100644
--- a/nixos/modules/programs/zsh/zsh.nix
+++ b/nixos/modules/programs/zsh/zsh.nix
@@ -98,18 +98,18 @@ in
       loginShellInit = cfge.loginShellInit;
 
       interactiveShellInit = ''
-        ${cfge.interactiveShellInit}
-
-        ${cfg.promptInit}
-        ${zshAliases}
-
-        # Some sane history defaults
+        # history defaults
         export SAVEHIST=2000
         export HISTSIZE=2000
         export HISTFILE=$HOME/.zsh_history
 
         setopt HIST_IGNORE_DUPS SHARE_HISTORY HIST_FCNTL_LOCK
 
+        ${cfge.interactiveShellInit}
+
+        ${cfg.promptInit}
+        ${zshAliases}
+
         # Tell zsh how to find installed completions
         for p in ''${(z)NIX_PROFILES}; do
           fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions)
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 2a3d89e9f6f..010d44c40d1 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -14,6 +14,20 @@ with lib;
     (mkRenamedOptionModule [ "networking" "enableWLAN" ] [ "networking" "wireless" "enable" ])
     (mkRenamedOptionModule [ "networking" "enableRT73Firmware" ] [ "networking" "enableRalinkFirmware" ])
 
+    (mkRenamedOptionModule [ "services" "cadvisor" "host" ] [ "services" "cadvisor" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "dockerRegistry" "host" ] [ "services" "dockerRegistry" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "kibana" "host" ] [ "services" "kibana" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "mpd" "network" "host" ] [ "services" "mpd" "network" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "neo4j" "host" ] [ "services" "neo4j" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "shout" "host" ] [ "services" "shout" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "sslh" "host" ] [ "services" "sslh" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "statsd" "host" ] [ "services" "statsd" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "subsonic" "host" ] [ "services" "subsonic" "listenAddress" ])
+    (mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ])
+
     # Old Grub-related options.
     (mkRenamedOptionModule [ "boot" "initrd" "extraKernelModules" ] [ "boot" "initrd" "kernelModules" ])
     (mkRenamedOptionModule [ "boot" "extraKernelParams" ] [ "boot" "kernelParams" ])
diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index 2de57dd68cb..15e5b49878f 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -37,6 +37,12 @@ let
         description = "Group running the ACME client.";
       };
 
+      allowKeysForGroup = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Give read permissions to the specified group to read SSL private certificates.";
+      };
+
       postRun = mkOption {
         type = types.lines;
         default = "";
@@ -137,6 +143,7 @@ in
       systemd.services = flip mapAttrs' cfg.certs (cert: data:
         let
           cpath = "${cfg.directory}/${cert}";
+          rights = if data.allowKeysForGroup then "750" else "700";
           cmdline = [ "-v" "-d" cert "--default_root" data.webroot "--valid_min" cfg.validMin ]
                     ++ optionals (data.email != null) [ "--email" data.email ]
                     ++ concatMap (p: [ "-f" p ]) data.plugins
@@ -159,9 +166,10 @@ in
           preStart = ''
             mkdir -p '${cfg.directory}'
             if [ ! -d '${cpath}' ]; then
-              mkdir -m 700 '${cpath}'
-              chown '${data.user}:${data.group}' '${cpath}'
+              mkdir '${cpath}'
             fi
+            chmod ${rights} '${cpath}'
+            chown -R '${data.user}:${data.group}' '${cpath}'
           '';
           script = ''
             cd '${cpath}'
diff --git a/nixos/modules/security/audit.nix b/nixos/modules/security/audit.nix
new file mode 100644
index 00000000000..3aa31e07907
--- /dev/null
+++ b/nixos/modules/security/audit.nix
@@ -0,0 +1,109 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.security.audit;
+
+  failureModes = {
+    silent = 0;
+    printk = 1;
+    panic  = 2;
+  };
+
+  # TODO: it seems like people like their rules to be somewhat secret, yet they will not be if
+  # put in the store like this. At the same time, it doesn't feel like a huge deal and working
+  # around that is a pain so I'm leaving it like this for now.
+  startScript = pkgs.writeScript "audit-start" ''
+    #!${pkgs.stdenv.shell} -eu
+    # Clear out any rules we may start with
+    auditctl -D
+
+    # Put the rules in a temporary file owned and only readable by root
+    rulesfile="$(mktemp)"
+    ${concatMapStrings (x: "echo '${x}' >> $rulesfile\n") cfg.rules}
+
+    # Apply the requested rules
+    auditctl -R "$rulesfile"
+
+    # Enable and configure auditing
+    auditctl \
+      -e ${if cfg.enable == "lock" then "2" else "1"} \
+      -b ${toString cfg.backlogLimit} \
+      -f ${toString failureModes.${cfg.failureMode}} \
+      -r ${toString cfg.rateLimit}
+  '';
+
+  stopScript = pkgs.writeScript "audit-stop" ''
+    #!${pkgs.stdenv.shell} -eu
+    # Clear the rules
+    auditctl -D
+
+    # Disable auditing
+    auditctl -e 0
+  '';
+in {
+  options = {
+    security.audit = {
+      enable = mkOption {
+        type        = types.enum [ false true "lock" ];
+        default     = true; # The kernel seems to enable it by default with no rules anyway
+        description = ''
+          Whether to enable the Linux audit system. The special `lock' value can be used to
+          enable auditing and prevent disabling it until a restart. Be careful about locking
+          this, as it will prevent you from changing your audit configuration until you
+          restart. If possible, test your configuration using build-vm beforehand.
+        '';
+      };
+
+      failureMode = mkOption {
+        type        = types.enum [ "silent" "printk" "panic" ];
+        default     = "printk";
+        description = "How to handle critical errors in the auditing system";
+      };
+
+      backlogLimit = mkOption {
+        type        = types.int;
+        default     = 64; # Apparently the kernel default
+        description = ''
+          The maximum number of outstanding audit buffers allowed; exceeding this is
+          considered a failure and handled in a manner specified by failureMode.
+        '';
+      };
+
+      rateLimit = mkOption {
+        type        = types.int;
+        default     = 0;
+        description = ''
+          The maximum messages per second permitted before triggering a failure as
+          specified by failureMode. Setting it to zero disables the limit.
+        '';
+      };
+
+      rules = mkOption {
+        type        = types.listOf types.str; # (types.either types.str (types.submodule rule));
+        default     = [];
+        example     = [ "-a exit,always -F arch=b64 -S execve" ];
+        description = ''
+          The ordered audit rules, with each string appearing as one line of the audit.rules file.
+        '';
+      };
+    };
+  };
+
+  config = mkIf (cfg.enable == "lock" || cfg.enable) {
+    systemd.services.audit = {
+      description = "pseudo-service representing the kernel audit state";
+      wantedBy = [ "basic.target" ];
+
+      path = [ pkgs.audit ];
+
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+        ExecStart = "@${startScript} audit-start";
+        ExecStop  = "@${stopScript}  audit-stop";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/audio/fuppes.nix b/nixos/modules/services/audio/fuppes.nix
deleted file mode 100644
index 4a975ed5f53..00000000000
--- a/nixos/modules/services/audio/fuppes.nix
+++ /dev/null
@@ -1,115 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-let
-  cfg = config.services.fuppesd;
-in
-
-with lib;
-
-{
-  options = {
-    services.fuppesd = {
-      enable = mkOption {
-        default = false;
-        type = with types; bool;
-        description = ''
-          Enables Fuppes (UPnP A/V Media Server).  Can be used to watch
-          photos, video and listen to music from a phone/tv connected to the
-          local network.
-        '';
-      };
-
-      name = mkOption {
-        example = "Media Center";
-        type = types.str;
-        description = ''
-          Enables Fuppes (UPnP A/V Media Server).  Can be used to watch
-          photos, video and listen to music from a phone/tv connected to the
-          local network.
-        '';
-      };
-
-      log = {
-        level = mkOption {
-          default = 0;
-          example = 3;
-          type = with types; uniq int;
-          description = ''
-            Logging level of fuppes, An integer between 0 and 3.
-          '';
-        };
-
-        file = mkOption {
-          default = "/var/log/fuppes.log";
-          type = types.str;
-          description = ''
-            File which will contains the log produced by the daemon.
-          '';
-        };
-      };
-
-      config = mkOption {
-        example = "/etc/fuppes/fuppes.cfg";
-        type = types.str;
-        description = ''
-          Mutable configuration file which can be edited with the web
-          interface.  Due to possible modification, double quote the full
-          path of the filename stored in your filesystem to avoid attempts
-          to modify the content of the nix store.
-        '';
-      };
-
-      vfolder = mkOption {
-        example = literalExample "/etc/fuppes/vfolder.cfg";
-        description = ''
-          XML file describing the layout of virtual folder visible by the
-          client.
-        '';
-      };
-
-      database = mkOption {
-        default = "/var/lib/fuppes/fuppes.db";
-        type = types.str;
-        description = ''
-          Database file which index all shared files.
-        '';
-      };
-
-      ## At the moment, no plugins are packaged.
-      /*
-      plugins = mkOption {
-        type = with types; listOf package;
-        description = ''
-          List of Fuppes plugins.
-        '';
-      };
-      */
-
-      user = mkOption {
-        default = "root"; # The default is not secure.
-        example = "fuppes";
-        type = types.str;
-        description = ''
-          Name of the user which own the configuration files and under which
-          the fuppes daemon will be executed.
-        '';
-      };
-
-    };
-  };
-
-  config = mkIf cfg.enable {
-    jobs.fuppesd = {
-      description = "UPnP A/V Media Server. (${cfg.name})";
-      startOn = "ip-up";
-      daemonType = "fork";
-      exec = ''/var/setuid-wrappers/sudo -u ${cfg.user} -- ${pkgs.fuppes}/bin/fuppesd --friendly-name ${cfg.name} --log-level ${toString cfg.log.level} --log-file ${cfg.log.file} --config-file ${cfg.config} --vfolder-config-file ${cfg.vfolder} --database-file ${cfg.database}'';
-    };
-
-    services.fuppesd.name = mkDefault config.networking.hostName;
-
-    services.fuppesd.vfolder = mkDefault ./fuppes/vfolder.cfg;
-
-    security.sudo.enable = true;
-  };
-}
diff --git a/nixos/modules/services/audio/fuppes/vfolder.cfg b/nixos/modules/services/audio/fuppes/vfolder.cfg
deleted file mode 100644
index 35ec3bffeb0..00000000000
--- a/nixos/modules/services/audio/fuppes/vfolder.cfg
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<fuppes_vfolder_config version="0.2">
-
- <vfolder_layout device="default" enabled="false">
-
-    <vfolder name="Genre">
-      <vfolders property="genre">
-        <items type="audioItem" />
-      </vfolders>
-    </vfolder>
-
-    <vfolder name="Genre/Artists">
-      <vfolders property="genre">
-        <vfolders property="artist">
-          <items type="audioItem" />
-        </vfolders>
-      </vfolders>
-    </vfolder>
-
-    <vfolder name="Artists/Albums">
-      <vfolders property="artist">
-        <vfolders property="album">
-          <items type="audioItem" />
-        </vfolders>
-      </vfolders>
-    </vfolder> 
-    
-    <vfolder name="ABC/Artists/Albums">
-      <vfolders split="ABC">
-        <vfolders property="artist">
-          <vfolders property="album">
-            <items type="audioItem" />
-          </vfolders>
-        </vfolders>
-      </vfolders>
-    </vfolder>
-       
-    <vfolder name="Photos">
-      <vfolder name="All">
-        <items type="imageItem" />
-      </vfolder>
-      <vfolder name="Folders">
-        <folders filter="contains(imageItem)" />
-      </vfolder>      
-    </vfolder>
-
-    <vfolder name="Videos">
-      <vfolder name="All">
-        <items type="videoItem" />
-      </vfolder>
-      <vfolder name="Folders">
-        <folders filter="contains(videoItem)" />
-      </vfolder>
-    </vfolder>
-    
-    <vfolder name="shared dirs">
-      <shared_dirs full_extend="true" />
-    </vfolder>
-    
-  </vfolder_layout>
-
-  <vfolder_layout device="Xbox 360" enabled="false">
-
-    <vfolder name="Music" id="1">
-      <vfolder name="Album" id="7">
-        <vfolders property="album">
-          <items type="audioItem" />
-        </vfolders>
-      </vfolder>
-            
-      <vfolder name="All Music" id="4">
-        <items type="audioItem" />
-      </vfolder>
-      
-      <vfolder name="Artist" id="6">
-        <vfolders property="artist">
-          <items type="audioItem" />
-        </vfolders>
-      </vfolder>
-      
-      <vfolder name="Folders" id="20">
-        <folders filter="contains(audioItem)" />
-      </vfolder>
-      
-      <vfolder name="Genre" id="5">
-        <vfolders property="genre">
-          <items type="audioItem" />
-        </vfolders>
-      </vfolder>
-      
-      <vfolder name="Playlist" id="15" />
-    </vfolder>
-   
-    <vfolder name="Pictures" id="3">
-      <vfolder name="Album" id="13" />
-      
-      <vfolder name="All Pictures" id="11">
-        <items type="imageItem" />
-      </vfolder>
-      
-      <vfolder name="Date Taken" id="12" />
-      
-      <vfolder name="Folders" id="22">
-        <folders filter="contains(imageItem)" />
-      </vfolder>
-    </vfolder>
-
-    <vfolder name="Playlists" id="18">
-      <vfolder name="All Playlists" id="19" />
-      <vfolder name="Folders" id="23" />
-    </vfolder>
-
-    <vfolder name="Video" id="2">
-      <vfolder name="Actor" id="10" />
-      <vfolder name="Album" id="14" />
-      <vfolder name="All Video" id="8">
-				<items type="videoItem" />
-			</vfolder>
-      <vfolder name="Folders" id="21">
-			   <folders filter="contains(videoItem)" />
-			</vfolder>
-      <vfolder name="Genre" id="9" />
-    </vfolder>
-
-  </vfolder_layout>
-
-  <vfolder_layout device="Yamaha" enabled="false" create_references="true" >
-
-    <vfolder name="Playlists" />
-
-    <vfolder name="Artists">
-      <vfolders property="artist">
-        <items type="audioItem" />
-      </vfolders>
-    </vfolder>
-
-    <vfolder name="Albums">
-      <vfolders property="album">
-        <items type="audioItem" />
-      </vfolders>
-    </vfolder>
-
-    <vfolder name="Songs">
-      <items type="audioItem" />
-    </vfolder>
-
-    <vfolder name="Genres">
-      <vfolders property="genre">
-        <items type="audioItem" />
-      </vfolders>
-    </vfolder>
-
-  </vfolder_layout>
-
-</fuppes_vfolder_config>
diff --git a/nixos/modules/services/audio/liquidsoap.nix b/nixos/modules/services/audio/liquidsoap.nix
index bf67d2399eb..1c19ed36bdc 100644
--- a/nixos/modules/services/audio/liquidsoap.nix
+++ b/nixos/modules/services/audio/liquidsoap.nix
@@ -46,7 +46,7 @@ in
       example = {
         myStream1 = literalExample "\"/etc/liquidsoap/myStream1.liq\"";
         myStream2 = literalExample "./myStream2.liq";
-        myStream3 = literalExample "\"out(playlist(\"/srv/music/\"))\"";
+        myStream3 = literalExample "\"out(playlist(\\\"/srv/music/\\\"))\"";
       };
 
       type = types.attrsOf (types.either types.path types.str);
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 5515f827b29..5d5fef66794 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -18,7 +18,7 @@ let
     user                "${cfg.user}"
     group               "${cfg.group}"
 
-    ${optionalString (cfg.network.host != "any") ''bind_to_address "${cfg.network.host}"''}
+    ${optionalString (cfg.network.listenAddress != "any") ''bind_to_address "${cfg.network.listenAddress}"''}
     ${optionalString (cfg.network.port != 6600)  ''port "${toString cfg.network.port}"''}
 
     ${cfg.extraConfig}
@@ -75,7 +75,7 @@ in {
 
       network = {
 
-        host = mkOption {
+        listenAddress = mkOption {
           default = "any";
           description = ''
             This setting sets the address for the daemon to listen on. Careful attention
diff --git a/nixos/modules/services/backup/bacula.nix b/nixos/modules/services/backup/bacula.nix
index 69f3c3f8a75..8a26aae75fe 100644
--- a/nixos/modules/services/backup/bacula.nix
+++ b/nixos/modules/services/backup/bacula.nix
@@ -207,7 +207,7 @@ in {
         description = ''
           Extra configuration to be passed in Client directive.
         '';
-        example = literalExample ''
+        example = ''
           Maximum Concurrent Jobs = 20;
           Heartbeat Interval = 30;
         '';
@@ -218,7 +218,7 @@ in {
         description = ''
           Extra configuration to be passed in Messages directive.
         '';
-        example = literalExample ''
+        example = ''
           console = all
         '';
       };
diff --git a/nixos/modules/services/backup/rsnapshot.nix b/nixos/modules/services/backup/rsnapshot.nix
index fb25bd9dd1e..96657cf17fc 100644
--- a/nixos/modules/services/backup/rsnapshot.nix
+++ b/nixos/modules/services/backup/rsnapshot.nix
@@ -43,6 +43,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.rsnapshot;
+        defaultText = "pkgs.rsnapshot";
         example = literalExample "pkgs.rsnapshotGit";
         description = ''
           RSnapshot package to use.
diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix
index 57121e23855..78776786468 100644
--- a/nixos/modules/services/backup/tarsnap.nix
+++ b/nixos/modules/services/backup/tarsnap.nix
@@ -5,9 +5,9 @@ with lib;
 let
   cfg = config.services.tarsnap;
 
-  configFile = cfg: ''
-    cachedir ${config.services.tarsnap.cachedir}
-    keyfile  ${config.services.tarsnap.keyfile}
+  configFile = name: cfg: ''
+    cachedir ${config.services.tarsnap.cachedir}/${name}
+    keyfile  ${cfg.keyfile}
     ${optionalString cfg.nodump "nodump"}
     ${optionalString cfg.printStats "print-stats"}
     ${optionalString cfg.printStats "humanize-numbers"}
@@ -41,6 +41,20 @@ in
           account.
           Create the keyfile with <command>tarsnap-keygen</command>.
 
+          Note that each individual archive (specified below) may also have its
+          own individual keyfile specified. Tarsnap does not allow multiple
+          concurrent backups with the same cache directory and key (starting a
+          new backup will cause another one to fail). If you have multiple
+          archives specified, you should either spread out your backups to be
+          far apart, or specify a separate key for each archive. By default
+          every archive defaults to using
+          <literal>"/root/tarsnap.key"</literal>.
+
+          It's recommended for backups that you generate a key for every archive
+          using <literal>tarsnap-keygen(1)</literal>, and then generate a
+          write-only tarsnap key using <literal>tarsnap-keymgmt(1)</literal>,
+          and keep your master key(s) for a particular machine off-site.
+
           The keyfile name should be given as a string and not a path, to
           avoid the key being copied into the Nix store.
         '';
@@ -57,6 +71,12 @@ in
           will refuse to run until you manually rebuild the cache with
           <command>tarsnap --fsck</command>.
 
+          Note that each individual archive (specified below) has its own cache
+          directory specified under <literal>cachedir</literal>; this is because
+          tarsnap locks the cache during backups, meaning multiple services
+          archives cannot be backed up concurrently or overlap with a shared
+          cache.
+
           Set to <literal>null</literal> to disable caching.
         '';
       };
@@ -65,6 +85,28 @@ in
         type = types.attrsOf (types.submodule (
           {
             options = {
+              keyfile = mkOption {
+                type = types.str;
+                default = config.services.tarsnap.keyfile;
+                description = ''
+                  Set a specific keyfile for this archive. This defaults to
+                  <literal>"/root/tarsnap.key"</literal> if left unspecified.
+
+                  Use this option if you want to run multiple backups
+                  concurrently - each archive must have a unique key. You can
+                  generate a write-only key derived from your master key (which
+                  is recommended) using <literal>tarsnap-keymgmt(1)</literal>.
+
+                  Note: every archive must have an individual master key. You
+                  must generate multiple keys with
+                  <literal>tarsnap-keygen(1)</literal>, and then generate write
+                  only keys from those.
+
+                  The keyfile name should be given as a string and not a path, to
+                  avoid the key being copied into the Nix store.
+                '';
+              };
+
               nodump = mkOption {
                 type = types.bool;
                 default = true;
@@ -242,15 +284,23 @@ in
 
     systemd.services."tarsnap@" = {
       description = "Tarsnap archive '%i'";
-      requires    = [ "network.target" ];
+      requires    = [ "network-online.target" ];
+      after       = [ "network-online.target" ];
+
+      path = [ pkgs.iputils pkgs.tarsnap pkgs.coreutils ];
 
-      path = [ pkgs.tarsnap pkgs.coreutils ];
+      # In order for the persistent tarsnap timer to work reliably, we have to
+      # make sure that the tarsnap server is reachable after systemd starts up
+      # the service - therefore we sleep in a loop until we can ping the
+      # endpoint.
+      preStart = "while ! ping -q -c 1 betatest-server.tarsnap.com &> /dev/null; do sleep 3; done";
       scriptArgs = "%i";
       script = ''
         mkdir -p -m 0755 ${dirOf cfg.cachedir}
         mkdir -p -m 0700 ${cfg.cachedir}
         chown root:root ${cfg.cachedir}
         chmod 0700 ${cfg.cachedir}
+        mkdir -p -m 0700 ${cfg.cachedir}/$1
         DIRS=`cat /etc/tarsnap/$1.dirs`
         exec tarsnap --configfile /etc/tarsnap/$1.conf -c -f $1-$(date +"%Y%m%d%H%M%S") $DIRS
       '';
@@ -259,17 +309,21 @@ in
         IOSchedulingClass = "idle";
         NoNewPrivileges = "true";
         CapabilityBoundingSet = "CAP_DAC_READ_SEARCH";
+        PermissionsStartOnly = "true";
       };
     };
 
+    # Note: the timer must be Persistent=true, so that systemd will start it even
+    # if e.g. your laptop was asleep while the latest interval occurred.
     systemd.timers = mapAttrs' (name: cfg: nameValuePair "tarsnap@${name}"
       { timerConfig.OnCalendar = cfg.period;
+        timerConfig.Persistent = "true";
         wantedBy = [ "timers.target" ];
       }) cfg.archives;
 
     environment.etc =
       (mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.conf"
-        { text = configFile cfg;
+        { text = configFile name cfg;
         }) cfg.archives) //
       (mapAttrs' (name: cfg: nameValuePair "tarsnap/${name}.dirs"
         { text = concatStringsSep " " cfg.directories;
diff --git a/nixos/modules/services/continuous-integration/jenkins/default.nix b/nixos/modules/services/continuous-integration/jenkins/default.nix
index ac64e861664..fb77586f689 100644
--- a/nixos/modules/services/continuous-integration/jenkins/default.nix
+++ b/nixos/modules/services/continuous-integration/jenkins/default.nix
@@ -80,6 +80,7 @@ in {
 
       packages = mkOption {
         default = [ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ];
+        defaultText = "[ pkgs.stdenv pkgs.git pkgs.jdk config.programs.ssh.package pkgs.nix ]";
         type = types.listOf types.package;
         description = ''
           Packages to add to PATH for the jenkins process.
diff --git a/nixos/modules/services/continuous-integration/jenkins/job-builder.nix b/nixos/modules/services/continuous-integration/jenkins/job-builder.nix
index 702d452279f..7b1fe6269fe 100644
--- a/nixos/modules/services/continuous-integration/jenkins/job-builder.nix
+++ b/nixos/modules/services/continuous-integration/jenkins/job-builder.nix
@@ -74,7 +74,7 @@ in {
                 ];
               };
             }
-          ];
+          ]
         '';
         description = ''
           Job descriptions for Jenkins Job Builder in Nix format.
diff --git a/nixos/modules/services/databases/4store-endpoint.nix b/nixos/modules/services/databases/4store-endpoint.nix
index a0379043371..5c55ef406d5 100644
--- a/nixos/modules/services/databases/4store-endpoint.nix
+++ b/nixos/modules/services/databases/4store-endpoint.nix
@@ -60,11 +60,9 @@ with lib;
 
     services.avahi.enable = true;
 
-    jobs.fourStoreEndpoint = {
-      name = "4store-endpoint";
-      startOn = "ip-up";
-
-      exec = ''
+    systemd.services."4store-endpoint" = {
+      wantedBy = [ "ip-up.target" ];
+      script = ''
         ${run} '${pkgs.rdf4store}/bin/4s-httpd -D ${cfg.options} ${if cfg.listenAddress!=null then "-H ${cfg.listenAddress}" else "" } -p ${toString cfg.port} ${cfg.database}'
       '';
     };
diff --git a/nixos/modules/services/databases/4store.nix b/nixos/modules/services/databases/4store.nix
index 807317d2745..33e731e9681 100644
--- a/nixos/modules/services/databases/4store.nix
+++ b/nixos/modules/services/databases/4store.nix
@@ -52,9 +52,8 @@ with lib;
 
     services.avahi.enable = true;
 
-    jobs.fourStore = {
-      name = "4store";
-      startOn = "ip-up";
+    systemd.services."4store" = {
+      wantedBy = [ "ip-up.target" ];
 
       preStart = ''
         mkdir -p ${stateDir}/
@@ -64,11 +63,9 @@ with lib;
         fi
       '';
 
-      exec = ''
+      script = ''
         ${run} -c '${pkgs.rdf4store}/bin/4s-backend -D ${cfg.options} ${cfg.database}'
       '';
     };
-
   };
-
 }
diff --git a/nixos/modules/services/databases/couchdb.nix b/nixos/modules/services/databases/couchdb.nix
index 2b1d07c355e..ae0589b399e 100644
--- a/nixos/modules/services/databases/couchdb.nix
+++ b/nixos/modules/services/databases/couchdb.nix
@@ -38,6 +38,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pkgs.couchdb;
+        defaultText = "pkgs.couchdb";
         example = literalExample "pkgs.couchdb";
         description = ''
           CouchDB package to use.
diff --git a/nixos/modules/services/databases/firebird.nix b/nixos/modules/services/databases/firebird.nix
index c874b218a5e..b9f66612d4e 100644
--- a/nixos/modules/services/databases/firebird.nix
+++ b/nixos/modules/services/databases/firebird.nix
@@ -49,6 +49,7 @@ in
 
       package = mkOption {
         default = pkgs.firebirdSuper;
+        defaultText = "pkgs.firebirdSuper";
         type = types.package;
         /*
           Example: <code>package = pkgs.firebirdSuper.override { icu =
diff --git a/nixos/modules/services/databases/hbase.nix b/nixos/modules/services/databases/hbase.nix
index ccfabc9de0b..629d02209a9 100644
--- a/nixos/modules/services/databases/hbase.nix
+++ b/nixos/modules/services/databases/hbase.nix
@@ -44,6 +44,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pkgs.hbase;
+        defaultText = "pkgs.hbase";
         example = literalExample "pkgs.hbase";
         description = ''
           HBase package to use.
diff --git a/nixos/modules/services/databases/influxdb.nix b/nixos/modules/services/databases/influxdb.nix
index 8d63f14c67b..e2268bd556e 100644
--- a/nixos/modules/services/databases/influxdb.nix
+++ b/nixos/modules/services/databases/influxdb.nix
@@ -120,6 +120,7 @@ in
 
       package = mkOption {
         default = pkgs.influxdb;
+        defaultText = "pkgs.influxdb";
         description = "Which influxdb derivation to use";
         type = types.package;
       };
diff --git a/nixos/modules/services/databases/mongodb.nix b/nixos/modules/services/databases/mongodb.nix
index 14ffdad9217..ef9bc46e4a0 100644
--- a/nixos/modules/services/databases/mongodb.nix
+++ b/nixos/modules/services/databases/mongodb.nix
@@ -41,6 +41,7 @@ in
 
       package = mkOption {
         default = pkgs.mongodb;
+        defaultText = "pkgs.mongodb";
         type = types.package;
         description = "
           Which MongoDB derivation to use.
diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
index 3cf22db7da2..41b96068590 100644
--- a/nixos/modules/services/databases/neo4j.nix
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -7,7 +7,7 @@ let
 
   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.address=${cfg.listenAddress}
     org.neo4j.server.webserver.port=${toString cfg.port}
     ${optionalString cfg.enableHttps ''
       org.neo4j.server.webserver.https.enabled=true
@@ -49,10 +49,11 @@ in {
     package = mkOption {
       description = "Neo4j package to use.";
       default = pkgs.neo4j;
+      defaultText = "pkgs.neo4j";
       type = types.package;
     };
 
-    host = mkOption {
+    listenAddress = mkOption {
       description = "Neo4j listen address.";
       default = "127.0.0.1";
       type = types.str;
diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix
index 7eecf5d8e44..9e86559dda0 100644
--- a/nixos/modules/services/databases/openldap.nix
+++ b/nixos/modules/services/databases/openldap.nix
@@ -25,22 +25,7 @@ in
         description = "
           Whether to enable the ldap server.
         ";
-        example = literalExample ''
-          openldap.enable = true;
-          openldap.extraConfig = '''
-            include ''${pkgs.openldap.out}/etc/openldap/schema/core.schema
-            include ''${pkgs.openldap.out}/etc/openldap/schema/cosine.schema
-            include ''${pkgs.openldap.out}/etc/openldap/schema/inetorgperson.schema
-            include ''${pkgs.openldap.out}/etc/openldap/schema/nis.schema
-
-            database bdb 
-            suffix dc=example,dc=org 
-            rootdn cn=admin,dc=example,dc=org 
-            # NOTE: change after first start
-            rootpw secret
-            directory /var/db/openldap
-          ''';
-        '';
+        example = true;
       };
 
       user = mkOption {
@@ -67,6 +52,19 @@ in
         description = "
           sldapd.conf configuration
         ";
+        example = ''
+            include ''${pkgs.openldap}/etc/openldap/schema/core.schema
+            include ''${pkgs.openldap}/etc/openldap/schema/cosine.schema
+            include ''${pkgs.openldap}/etc/openldap/schema/inetorgperson.schema
+            include ''${pkgs.openldap}/etc/openldap/schema/nis.schema
+
+            database bdb 
+            suffix dc=example,dc=org 
+            rootdn cn=admin,dc=example,dc=org 
+            # NOTE: change after first start
+            rootpw secret
+            directory /var/db/openldap
+          '';
       };
     };
 
diff --git a/nixos/modules/services/databases/opentsdb.nix b/nixos/modules/services/databases/opentsdb.nix
index 0e73d4aca0e..489cdcffe65 100644
--- a/nixos/modules/services/databases/opentsdb.nix
+++ b/nixos/modules/services/databases/opentsdb.nix
@@ -26,6 +26,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pkgs.opentsdb;
+        defaultText = "pkgs.opentsdb";
         example = literalExample "pkgs.opentsdb";
         description = ''
           OpenTSDB package to use.
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 16e3235eb2c..c2045a5859c 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -122,8 +122,8 @@ in
         example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql94; }).v_2_1_4 ]";
         description = ''
           When this list contains elements a new store path is created.
-          PostgreSQL and the elments are symlinked into it. Then pg_config,
-          postgres and pc_ctl are copied to make them use the new
+          PostgreSQL and the elements are symlinked into it. Then pg_config,
+          postgres and pg_ctl are copied to make them use the new
           $out/lib directory as pkglibdir. This makes it possible to use postgis
           without patching the .sql files which reference $libdir/postgis-1.5.
         '';
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index f2612d0b43b..6323d2c8ce4 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -46,6 +46,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.redis;
+        defaultText = "pkgs.redis";
         description = "Which Redis derivation to use.";
       };
 
diff --git a/nixos/modules/services/databases/virtuoso.nix b/nixos/modules/services/databases/virtuoso.nix
index 8a49e13395c..bdd210a2550 100644
--- a/nixos/modules/services/databases/virtuoso.nix
+++ b/nixos/modules/services/databases/virtuoso.nix
@@ -29,20 +29,20 @@ with lib;
       };
 
       listenAddress = mkOption {
-	default = "1111";
-	example = "myserver:1323";
+        default = "1111";
+        example = "myserver:1323";
         description = "ip:port or port to listen on.";
       };
 
       httpListenAddress = mkOption {
-	default = null;
-	example = "myserver:8080";
+        default = null;
+        example = "myserver:8080";
         description = "ip:port or port for Virtuoso HTTP server to listen on.";
       };
 
       dirsAllowed = mkOption {
-	default = null;
-	example = "/www, /home/";
+        default = null;
+        example = "/www, /home/";
         description = "A list of directories Virtuoso is allowed to access";
       };
     };
@@ -61,18 +61,17 @@ with lib;
         home = stateDir;
       };
 
-    jobs.virtuoso = {
-      name = "virtuoso";
-      startOn = "ip-up";
+    systemd.services.virtuoso = {
+      wantedBy = [ "ip-up.target" ];
 
       preStart = ''
-	mkdir -p ${stateDir}
-	chown ${virtuosoUser} ${stateDir}
+        mkdir -p ${stateDir}
+        chown ${virtuosoUser} ${stateDir}
       '';
 
       script = ''
-	cd ${stateDir}
-	${pkgs.virtuoso}/bin/virtuoso-t +foreground +configfile ${pkgs.writeText "virtuoso.ini" cfg.config}
+        cd ${stateDir}
+        ${pkgs.virtuoso}/bin/virtuoso-t +foreground +configfile ${pkgs.writeText "virtuoso.ini" cfg.config}
       '';
     };
 
diff --git a/nixos/modules/services/games/ghost-one.nix b/nixos/modules/services/games/ghost-one.nix
index 07d7287ed88..5762148df2b 100644
--- a/nixos/modules/services/games/ghost-one.nix
+++ b/nixos/modules/services/games/ghost-one.nix
@@ -78,8 +78,8 @@ in
       bot_replaypath = replays
     '';
 
-    jobs.ghostOne = {
-      name = "ghost-one";
+    systemd.services."ghost-one" = {
+      wantedBy = [ "multi-user.target" ];
       script = ''
         mkdir -p ${stateDir}
         cd ${stateDir}
diff --git a/nixos/modules/services/hardware/acpid.nix b/nixos/modules/services/hardware/acpid.nix
index a20b1a1ee3a..48b2b6be09e 100644
--- a/nixos/modules/services/hardware/acpid.nix
+++ b/nixos/modules/services/hardware/acpid.nix
@@ -20,7 +20,7 @@ let
       }
     '';
 
-  events = [powerEvent lidEvent acEvent];
+  events = [powerEvent lidEvent acEvent muteEvent volumeDownEvent volumeUpEvent cdPlayEvent cdNextEvent cdPrevEvent];
 
   # Called when the power button is pressed.
   powerEvent =
@@ -55,6 +55,61 @@ let
         '';
     };
 
+  muteEvent = {
+    name = "mute";
+    event = "button/mute.*";
+    action = ''
+      #! ${pkgs.bash}/bin/sh
+      ${config.services.acpid.muteCommands}
+    '';
+  };
+
+  volumeDownEvent = {
+    name = "volume-down";
+    event = "button/volumedown.*";
+    action = ''
+      #! ${pkgs.bash}/bin/sh
+      ${config.services.acpid.volumeDownEventCommands}
+    '';
+  };
+
+  volumeUpEvent = {
+    name = "volume-up";
+    event = "button/volumeup.*";
+    action = ''
+      #! ${pkgs.bash}/bin/sh
+      ${config.services.acpid.volumeUpEventCommands}
+    '';
+  };
+
+  cdPlayEvent = {
+    name = "cd-play";
+    event = "cd/play.*";
+    action = ''
+      #! ${pkgs.bash}/bin/sh
+      ${config.services.acpid.cdPlayEventCommands}
+    '';
+  };
+
+  cdNextEvent = {
+    name = "cd-next";
+    event = "cd/next.*";
+    action = ''
+      #! ${pkgs.bash}/bin/sh
+      ${config.services.acpid.cdNextEventCommands}
+    '';
+  };
+
+  cdPrevEvent = {
+    name = "cd-prev";
+    event = "cd/prev.*";
+    action = ''
+      #! ${pkgs.bash}/bin/sh
+      ${config.services.acpid.cdPrevEventCommands}
+    '';
+  };
+
+
 in
 
 {
@@ -89,6 +144,42 @@ in
         description = "Shell commands to execute on an ac_adapter.* event.";
       };
 
+      muteCommands = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Shell commands to execute on an button/mute.* event.";
+      };
+
+      volumeDownEventCommands = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Shell commands to execute on an button/volumedown.* event.";
+      };
+
+      volumeUpEventCommands = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Shell commands to execute on an button/volumeup.* event.";
+      };
+
+      cdPlayEventCommands = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Shell commands to execute on an cd/play.* event.";
+      };
+
+      cdNextEventCommands = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Shell commands to execute on an cd/next.* event.";
+      };
+
+      cdPrevEventCommands = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Shell commands to execute on an cd/prev.* event.";
+      };
+
     };
 
   };
@@ -98,22 +189,26 @@ in
 
   config = mkIf config.services.acpid.enable {
 
-    jobs.acpid =
-      { description = "ACPI Daemon";
-
-        wantedBy = [ "multi-user.target" ];
-        after = [ "systemd-udev-settle.service" ];
+    systemd.services.acpid = {
+      description = "ACPI Daemon";
 
-        path = [ pkgs.acpid ];
+      wantedBy = [ "multi-user.target" ];
+      after = [ "systemd-udev-settle.service" ];
 
-        daemonType = "fork";
+      path = [ pkgs.acpid ];
 
-        exec = "acpid --confdir ${acpiConfDir}";
+      serviceConfig = {
+        Type = "forking";
+      };
 
-        unitConfig.ConditionVirtualization = "!systemd-nspawn";
-        unitConfig.ConditionPathExists = [ "/proc/acpi" ];
+      unitConfig = {
+        ConditionVirtualization = "!systemd-nspawn";
+        ConditionPathExists = [ "/proc/acpi" ];
       };
 
+      script = "acpid --confdir ${acpiConfDir}";
+    };
+
   };
 
 }
diff --git a/nixos/modules/services/hardware/freefall.nix b/nixos/modules/services/hardware/freefall.nix
index 2be33976606..066ccaa4d7c 100644
--- a/nixos/modules/services/hardware/freefall.nix
+++ b/nixos/modules/services/hardware/freefall.nix
@@ -21,6 +21,7 @@ in {
     package = mkOption {
       type = types.package;
       default = pkgs.freefall;
+      defaultText = "pkgs.freefall";
       description = ''
         freefall derivation to use.
       '';
diff --git a/nixos/modules/services/hardware/irqbalance.nix b/nixos/modules/services/hardware/irqbalance.nix
new file mode 100644
index 00000000000..b139154432c
--- /dev/null
+++ b/nixos/modules/services/hardware/irqbalance.nix
@@ -0,0 +1,30 @@
+#
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.irqbalance;
+
+in
+{
+  options.services.irqbalance.enable = mkEnableOption "irqbalance daemon";
+
+  config = mkIf cfg.enable {
+
+    systemd.services = {
+      irqbalance = {
+        description = "irqbalance daemon";
+        path = [ pkgs.irqbalance ];
+        serviceConfig =
+          { ExecStart = "${pkgs.irqbalance}/bin/irqbalance --foreground"; };
+        wantedBy = [ "multi-user.target" ];
+      };
+    };
+
+    environment.systemPackages = [ pkgs.irqbalance ];
+
+  };
+
+}
diff --git a/nixos/modules/services/hardware/pommed.nix b/nixos/modules/services/hardware/pommed.nix
index a24557b40ba..7be4dc1e846 100644
--- a/nixos/modules/services/hardware/pommed.nix
+++ b/nixos/modules/services/hardware/pommed.nix
@@ -35,18 +35,13 @@ with lib;
 
     services.dbus.packages = [ pkgs.pommed ];
 
-    jobs.pommed = { name = "pommed";
-
+    systemd.services.pommed = {
       description = "Pommed hotkey management";
-
-      startOn = "started dbus";
-
+      wantedBy = [ "multi-user.target" ];
+      after = [ "dbus.service" ];
       postStop = "rm -f /var/run/pommed.pid";
-
-      exec = "${pkgs.pommed}/bin/pommed";
-
-      daemonType = "fork";
-
+      script = "${pkgs.pommed}/bin/pommed";
+      serviceConfig.Type = "forking";
       path = [ pkgs.eject ];
     };
   };
diff --git a/nixos/modules/services/hardware/sane.nix b/nixos/modules/services/hardware/sane.nix
index 0428602688d..56504cd2361 100644
--- a/nixos/modules/services/hardware/sane.nix
+++ b/nixos/modules/services/hardware/sane.nix
@@ -4,7 +4,9 @@ with lib;
 
 let
 
-  pkg = if config.hardware.sane.snapshot then pkgs.saneBackendsGit else pkgs.saneBackends;
+  pkg = if config.hardware.sane.snapshot
+    then pkgs.sane-backends-git
+    else pkgs.sane-backends;
   backends = [ pkg ] ++ config.hardware.sane.extraBackends;
   saneConfig = pkgs.mkSaneConfig { paths = backends; };
 
diff --git a/nixos/modules/services/hardware/thinkfan.nix b/nixos/modules/services/hardware/thinkfan.nix
index 16c31aab2d5..018e82e58a3 100644
--- a/nixos/modules/services/hardware/thinkfan.nix
+++ b/nixos/modules/services/hardware/thinkfan.nix
@@ -43,13 +43,7 @@ let
 
     sensor ${cfg.sensor} (0, 10, 15, 2, 10, 5, 0, 3, 0, 3)
     
-    (0,     0,      55)
-    (1,     48,     60)
-    (2,     50,     61)
-    (3,     52,     63)
-    (6,     56,     65)
-    (7,     60,     85)
-    (127,   80,     32767)
+    ${cfg.levels}
   '';
 
 in {
@@ -72,6 +66,22 @@ in {
         '';
       };
 
+      levels = mkOption {
+        default = ''
+          (0,     0,      55)
+          (1,     48,     60)
+          (2,     50,     61)
+          (3,     52,     63)
+          (6,     56,     65)
+          (7,     60,     85)
+          (127,   80,     32767)
+        '';
+        description =''
+          Sensor used by thinkfan
+        '';
+      };
+
+
     };
 
   };
diff --git a/nixos/modules/services/hardware/upower.nix b/nixos/modules/services/hardware/upower.nix
index 46481a86a14..2198842a451 100644
--- a/nixos/modules/services/hardware/upower.nix
+++ b/nixos/modules/services/hardware/upower.nix
@@ -27,6 +27,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.upower;
+        defaultText = "pkgs.upower";
         example = lib.literalExample "pkgs.upower";
         description = ''
           Which upower package to use.
diff --git a/nixos/modules/services/logging/klogd.nix b/nixos/modules/services/logging/klogd.nix
index f69e08152b5..2d1f515da92 100644
--- a/nixos/modules/services/logging/klogd.nix
+++ b/nixos/modules/services/logging/klogd.nix
@@ -24,21 +24,14 @@ with lib;
   ###### implementation
 
   config = mkIf config.services.klogd.enable {
-
-    jobs.klogd =
-      { description = "Kernel Log Daemon";
-
-        wantedBy = [ "multi-user.target" ];
-
-        path = [ pkgs.sysklogd ];
-
-        unitConfig.ConditionVirtualization = "!systemd-nspawn";
-
-        exec =
-          "klogd -c 1 -2 -n " +
-          "-k $(dirname $(readlink -f /run/booted-system/kernel))/System.map";
-      };
-
+    systemd.services.klogd = {
+      description = "Kernel Log Daemon";
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.sysklogd ];
+      unitConfig.ConditionVirtualization = "!systemd-nspawn";
+      script =
+        "klogd -c 1 -2 -n " +
+        "-k $(dirname $(readlink -f /run/booted-system/kernel))/System.map";
+    };
   };
-
 }
diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix
index 0186452de95..fdd9f0f3e5c 100644
--- a/nixos/modules/services/logging/logrotate.nix
+++ b/nixos/modules/services/logging/logrotate.nix
@@ -13,6 +13,7 @@ in
   options = {
     services.logrotate = {
       enable = mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Enable the logrotate cron job
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index 3a798c6f372..e019e6c3f23 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -33,6 +33,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.logstash;
+        defaultText = "pkgs.logstash";
         example = literalExample "pkgs.logstash";
         description = "Logstash package to use.";
       };
@@ -84,7 +85,7 @@ in
         type = types.lines;
         default = ''stdin { type => "example" }'';
         description = "Logstash input configuration.";
-        example = literalExample ''
+        example = ''
           # Read from journal
           pipe {
             command => "''${pkgs.systemd}/bin/journalctl -f -o json"
diff --git a/nixos/modules/services/logging/syslog-ng.nix b/nixos/modules/services/logging/syslog-ng.nix
index 2bf6d1ff790..21be286a6e9 100644
--- a/nixos/modules/services/logging/syslog-ng.nix
+++ b/nixos/modules/services/logging/syslog-ng.nix
@@ -39,6 +39,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pkgs.syslogng;
+        defaultText = "pkgs.syslogng";
         description = ''
           The package providing syslog-ng binaries.
         '';
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index 7ca4faae5d4..36bdcaca47a 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -90,6 +90,7 @@ in
     package = mkOption {
       type = types.package;
       default = pkgs.dovecot22;
+      defaultText = "pkgs.dovecot22";
       description = "Dovecot package to use.";
     };
 
@@ -131,7 +132,7 @@ in
     modules = mkOption {
       type = types.listOf types.package;
       default = [];
-      example = [ pkgs.dovecot_pigeonhole ];
+      example = literalExample "[ pkgs.dovecot_pigeonhole ]";
       description = ''
         Symlinks the contents of lib/dovecot of every given package into
         /var/lib/dovecot/modules. This will make the given modules available
diff --git a/nixos/modules/services/mail/dspam.nix b/nixos/modules/services/mail/dspam.nix
new file mode 100644
index 00000000000..10352ba6abc
--- /dev/null
+++ b/nixos/modules/services/mail/dspam.nix
@@ -0,0 +1,147 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.dspam;
+
+  dspam = pkgs.dspam;
+
+  defaultSock = "/run/dspam/dspam.sock";
+
+  cfgfile = pkgs.writeText "dspam.conf" ''
+    Home /var/lib/dspam
+    StorageDriver ${dspam}/lib/dspam/lib${cfg.storageDriver}_drv.so
+
+    Trust root
+    Trust ${cfg.user}
+    SystemLog on
+    UserLog on
+
+    ${optionalString (cfg.domainSocket != null) ''ServerDomainSocketPath "${cfg.domainSocket}"''}
+
+    ${cfg.extraConfig}
+  '';
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.dspam = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the dspam spam filter.";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "dspam";
+        description = "User for the dspam daemon.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "dspam";
+        description = "Group for the dspam daemon.";
+      };
+
+      storageDriver = mkOption {
+        type = types.str;
+        default = "hash";
+        description =  "Storage driver backend to use for dspam.";
+      };
+
+      domainSocket = mkOption {
+        type = types.nullOr types.path;
+        default = defaultSock;
+        description = "Path to local domain socket which is used for communication with the daemon. Set to null to disable UNIX socket.";
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Additional dspam configuration.";
+      };
+
+      maintenanceInterval = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "If set, maintenance script will be run at specified (in systemd.timer format) interval";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable (mkMerge [
+    {
+      users.extraUsers = optionalAttrs (cfg.user == "dspam") (singleton
+        { name = "dspam";
+          group = cfg.group;
+          uid = config.ids.uids.dspam;
+        });
+
+      users.extraGroups = optionalAttrs (cfg.group == "dspam") (singleton
+        { name = "dspam";
+          gid = config.ids.gids.dspam;
+        });
+
+      environment.systemPackages = [ dspam ];
+
+      environment.etc."dspam/dspam.conf".source = cfgfile;
+
+      systemd.services.dspam = {
+        description = "dspam spam filtering daemon";
+        wantedBy = [ "multi-user.target" ];
+        restartTriggers = [ cfgfile ];
+
+        serviceConfig = {
+          ExecStart = "${dspam}/bin/dspam --daemon --nofork";
+          User = cfg.user;
+          Group = cfg.group;
+          RuntimeDirectory = optional (cfg.domainSocket == defaultSock) "dspam";
+          PermissionsStartOnly = true;
+        };
+
+        preStart = ''
+          mkdir -m750 -p /var/lib/dspam
+          chown -R "${cfg.user}:${cfg.group}" /var/lib/dspam
+
+          mkdir -m750 -p /var/log/dspam
+          chown -R "${cfg.user}:${cfg.group}" /var/log/dspam
+        '';
+      };
+    }
+
+    (mkIf (cfg.maintenanceInterval != null) {
+      systemd.timers.dspam-maintenance = {
+        description = "Timer for dspam maintenance script";
+        wantedBy = [ "timers.target" ];
+        timerConfig = {
+          OnCalendar = cfg.maintenanceInterval;
+          Unit = "dspam-maintenance.service";
+        };
+      };
+
+      systemd.services.dspam-maintenance = {
+        description = "dspam maintenance script";
+        restartTriggers = [ cfgfile ];
+
+        serviceConfig = {
+          ExecStart = "${dspam}/bin/dspam_maintenance";
+          Type = "oneshot";
+          User = cfg.user;
+          Group = cfg.group;
+        };
+      };
+    })
+  ]);
+}
diff --git a/nixos/modules/services/mail/freepops.nix b/nixos/modules/services/mail/freepops.nix
index 2dd27a2033a..e8c30a36923 100644
--- a/nixos/modules/services/mail/freepops.nix
+++ b/nixos/modules/services/mail/freepops.nix
@@ -72,15 +72,16 @@ in
   };
 
   config = mkIf cfg.enable {
-    jobs.freepopsd = {
+    systemd.services.freepopsd = {
       description = "Freepopsd (webmail over POP3)";
-      startOn = "ip-up";
-      exec = ''${pkgs.freepops}/bin/freepopsd \
-        -p ${toString cfg.port} \
-        -t ${toString cfg.threads} \
-        -b ${cfg.bind} \
-        -vv -l ${cfg.logFile} \
-        -s ${cfg.suid.user}.${cfg.suid.group}
+      wantedBy = [ "ip-up.target" ];
+      script = ''
+        ${pkgs.freepops}/bin/freepopsd \
+          -p ${toString cfg.port} \
+          -t ${toString cfg.threads} \
+          -b ${cfg.bind} \
+          -vv -l ${cfg.logFile} \
+          -s ${cfg.suid.user}.${cfg.suid.group}
       '';
     };
   };
diff --git a/nixos/modules/services/mail/opendkim.nix b/nixos/modules/services/mail/opendkim.nix
new file mode 100644
index 00000000000..1cdae9cb654
--- /dev/null
+++ b/nixos/modules/services/mail/opendkim.nix
@@ -0,0 +1,109 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.opendkim;
+
+  defaultSock = "local:/run/opendkim/opendkim.sock";
+
+  args = [ "-f" "-l"
+           "-p" cfg.socket
+           "-d" cfg.domains
+           "-k" cfg.keyFile
+           "-s" cfg.selector
+         ] ++ optionals (cfg.configFile != null) [ "-x" cfg.configFile ];
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.opendkim = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the OpenDKIM sender authentication system.";
+      };
+
+      socket = mkOption {
+        type = types.str;
+        default = defaultSock;
+        description = "Socket which is used for communication with OpenDKIM.";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "opendkim";
+        description = "User for the daemon.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "opendkim";
+        description = "Group for the daemon.";
+      };
+
+      domains = mkOption {
+        type = types.str;
+        description = "Local domains set; messages from them are signed, not verified.";
+      };
+
+      keyFile = mkOption {
+        type = types.path;
+        description = "Secret key file used for signing messages.";
+      };
+
+      selector = mkOption {
+        type = types.str;
+        description = "Selector to use when signing.";
+      };
+
+      configFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = "Additional opendkim configuration.";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    services.opendkim.domains = mkDefault "csl:${config.networking.hostName}";
+
+    users.extraUsers = optionalAttrs (cfg.user == "opendkim") (singleton
+      { name = "opendkim";
+        group = cfg.group;
+        uid = config.ids.uids.opendkim;
+      });
+
+    users.extraGroups = optionalAttrs (cfg.group == "opendkim") (singleton
+      { name = "opendkim";
+        gid = config.ids.gids.opendkim;
+      });
+
+    environment.systemPackages = [ pkgs.opendkim ];
+
+    systemd.services.opendkim = {
+      description = "OpenDKIM signing and verification daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.opendkim}/bin/opendkim ${concatMapStringsSep " " escapeShellArg args}";
+        User = cfg.user;
+        Group = cfg.group;
+        RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim";
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index 3a9e62a0205..6c5d7e92702 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -9,14 +9,14 @@ let
   group = cfg.group;
   setgidGroup = cfg.setgidGroup;
 
+  haveAliases = cfg.postmasterAlias != "" || cfg.rootAlias != "" || cfg.extraAliases != "";
+  haveTransport = cfg.transport != "";
+  haveVirtual = cfg.virtual != "";
+
   mainCf =
     ''
       compatibility_level = 2
 
-      queue_directory = /var/postfix/queue
-      command_directory = ${pkgs.postfix}/sbin
-      daemon_directory = ${pkgs.postfix}/libexec/postfix
-
       mail_owner = ${user}
       default_privs = nobody
 
@@ -57,8 +57,6 @@ let
         else
           "[" + cfg.relayHost + "]"}
 
-      alias_maps = hash:/var/postfix/conf/aliases
-
       mail_spool_directory = /var/spool/mail/
 
       setgid_group = ${setgidGroup}
@@ -80,7 +78,13 @@ let
     + optionalString (cfg.recipientDelimiter != "") ''
       recipient_delimiter = ${cfg.recipientDelimiter}
     ''
-    + optionalString (cfg.virtual != "") ''
+    + optionalString haveAliases ''
+      alias_maps = hash:/etc/postfix/aliases
+    ''
+    + optionalString haveTransport ''
+      transport_maps = hash:/etc/postfix/transport
+    ''
+    + optionalString haveVirtual ''
       virtual_alias_maps = hash:/etc/postfix/virtual
     ''
     + cfg.extraConfig;
@@ -108,10 +112,14 @@ let
     flush     unix  n       -       n       1000?   0       flush
     proxymap  unix  -       -       n       -       -       proxymap
     proxywrite unix -       -       n       -       1       proxymap
+  ''
+  + optionalString cfg.enableSmtp ''
     smtp      unix  -       -       n       -       -       smtp
     relay     unix  -       -       n       -       -       smtp
     	      -o smtp_fallback_relay=
     #       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+  ''
+  + ''
     showq     unix  n       -       n       -       -       showq
     error     unix  -       -       n       -       -       error
     retry     unix  -       -       n       -       -       error
@@ -138,6 +146,7 @@ let
   virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
   mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
   masterCfFile = pkgs.writeText "postfix-master.cf" masterCf;
+  transportFile = pkgs.writeText "postfix-transport" cfg.transport;
 
 in
 
@@ -150,26 +159,36 @@ in
     services.postfix = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = "Whether to run the Postfix mail server.";
       };
 
+      enableSmtp = mkOption {
+        default = true;
+        description = "Whether to enable smtp in master.cf.";
+      };
+
       setSendmail = mkOption {
+        type = types.bool;
         default = true;
         description = "Whether to set the system sendmail to postfix's.";
       };
 
       user = mkOption {
+        type = types.str;
         default = "postfix";
         description = "What to call the Postfix user (must be used only for postfix).";
       };
 
       group = mkOption {
+        type = types.str;
         default = "postfix";
         description = "What to call the Postfix group (must be used only for postfix).";
       };
 
       setgidGroup = mkOption {
+        type = types.str;
         default = "postdrop";
         description = "
           How to call postfix setgid group (for postdrop). Should
@@ -178,6 +197,7 @@ in
       };
 
       networks = mkOption {
+        type = types.nullOr (types.listOf types.str);
         default = null;
         example = ["192.168.0.1/24"];
         description = "
@@ -188,6 +208,7 @@ in
       };
 
       networksStyle = mkOption {
+        type = types.str;
         default = "";
         description = "
           Name of standard way of trusted network specification to use,
@@ -197,6 +218,7 @@ in
       };
 
       hostname = mkOption {
+        type = types.str;
         default = "";
         description ="
           Hostname to use. Leave blank to use just the hostname of machine.
@@ -205,6 +227,7 @@ in
       };
 
       domain = mkOption {
+        type = types.str;
         default = "";
         description ="
           Domain to use. Leave blank to use hostname minus first component.
@@ -212,6 +235,7 @@ in
       };
 
       origin = mkOption {
+        type = types.str;
         default = "";
         description ="
           Origin to use in outgoing e-mail. Leave blank to use hostname.
@@ -219,6 +243,7 @@ in
       };
 
       destination = mkOption {
+        type = types.nullOr (types.listOf types.str);
         default = null;
         example = ["localhost"];
         description = "
@@ -228,6 +253,7 @@ in
       };
 
       relayDomains = mkOption {
+        type = types.nullOr (types.listOf types.str);
         default = null;
         example = ["localdomain"];
         description = "
@@ -236,6 +262,7 @@ in
       };
 
       relayHost = mkOption {
+        type = types.str;
         default = "";
         description = "
           Mail relay for outbound mail.
@@ -243,6 +270,7 @@ in
       };
 
       lookupMX = mkOption {
+        type = types.bool;
         default = false;
         description = "
           Whether relay specified is just domain whose MX must be used.
@@ -250,11 +278,13 @@ in
       };
 
       postmasterAlias = mkOption {
+        type = types.str;
         default = "root";
         description = "Who should receive postmaster e-mail.";
       };
 
       rootAlias = mkOption {
+        type = types.str;
         default = "";
         description = "
           Who should receive root e-mail. Blank for no redirection.
@@ -262,6 +292,7 @@ in
       };
 
       extraAliases = mkOption {
+        type = types.lines;
         default = "";
         description = "
           Additional entries to put verbatim into aliases file, cf. man-page aliases(8).
@@ -269,6 +300,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "";
         description = "
           Extra lines to be added verbatim to the main.cf configuration file.
@@ -276,21 +308,25 @@ in
       };
 
       sslCert = mkOption {
+        type = types.str;
         default = "";
         description = "SSL certificate to use.";
       };
 
       sslCACert = mkOption {
+        type = types.str;
         default = "";
         description = "SSL certificate of CA.";
       };
 
       sslKey = mkOption {
+        type = types.str;
         default = "";
         description = "SSL key to use.";
       };
 
       recipientDelimiter = mkOption {
+        type = types.str;
         default = "";
         example = "+";
         description = "
@@ -299,18 +335,39 @@ in
       };
 
       virtual = mkOption {
+        type = types.lines;
         default = "";
         description = "
           Entries for the virtual alias map, cf. man-page virtual(8).
         ";
       };
 
+      transport = mkOption {
+        default = "";
+        description = "
+          Entries for the transport map, cf. man-page transport(8).
+        ";
+      };
+
       extraMasterConf = mkOption {
+        type = types.lines;
         default = "";
         example = "submission inet n - n - - smtpd";
         description = "Extra lines to append to the generated master.cf file.";
       };
 
+      aliasFiles = mkOption {
+        type = types.attrsOf types.path;
+        default = {};
+        description = "Aliases' tables to be compiled and placed into /var/lib/postfix/conf.";
+      };
+
+      mapFiles = mkOption {
+        type = types.attrsOf types.path;
+        default = {};
+        description = "Maps to be compiled and placed into /var/lib/postfix/conf.";
+      };
+
     };
 
   };
@@ -318,90 +375,104 @@ in
 
   ###### implementation
 
-  config = mkIf config.services.postfix.enable {
+  config = mkIf config.services.postfix.enable (mkMerge [
+    {
 
-    environment = {
-      etc = singleton
-        { source = "/var/postfix/conf";
-          target = "postfix";
-        };
-
-      # This makes comfortable for root to run 'postqueue' for example.
-      systemPackages = [ pkgs.postfix ];
-    };
+      environment = {
+        etc = singleton
+          { source = "/var/lib/postfix/conf";
+            target = "postfix";
+          };
 
-    services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
-      program = "sendmail";
-      source = "${pkgs.postfix}/bin/sendmail";
-      owner = "nobody";
-      group = "postdrop";
-      setuid = false;
-      setgid = true;
-    };
+        # This makes comfortable for root to run 'postqueue' for example.
+        systemPackages = [ pkgs.postfix ];
+      };
 
-    users.extraUsers = singleton
-      { name = user;
-        description = "Postfix mail server user";
-        uid = config.ids.uids.postfix;
-        group = group;
+      services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
+        program = "sendmail";
+        source = "${pkgs.postfix}/bin/sendmail";
+        group = setgidGroup;
+        setuid = false;
+        setgid = true;
       };
 
-    users.extraGroups =
-      [ { name = group;
+      users.extraUsers = optional (user == "postfix")
+        { name = "postfix";
+          description = "Postfix mail server user";
+          uid = config.ids.uids.postfix;
+          group = group;
+        };
+
+      users.extraGroups =
+        optional (group == "postfix")
+        { name = group;
           gid = config.ids.gids.postfix;
         }
+        ++ optional (setgidGroup == "postdrop")
         { name = setgidGroup;
           gid = config.ids.gids.postdrop;
-        }
-      ];
-
-    systemd.services.postfix =
-      { description = "Postfix mail server";
-
-        wantedBy = [ "multi-user.target" ];
-        after = [ "network.target" ];
-
-        serviceConfig = {
-          Type = "forking";
-          Restart = "always";
-          PIDFile = "/var/postfix/queue/pid/master.pid";
         };
 
-        preStart = ''
-          ${pkgs.coreutils}/bin/mkdir -p /var/spool/mail /var/postfix/conf /var/postfix/queue
-
-          ${pkgs.coreutils}/bin/chown -R ${user}:${group} /var/postfix
-          ${pkgs.coreutils}/bin/chown -R ${user}:${setgidGroup} /var/postfix/queue
-          ${pkgs.coreutils}/bin/chmod -R ug+rwX /var/postfix/queue
-          ${pkgs.coreutils}/bin/chown root:root /var/spool/mail
-          ${pkgs.coreutils}/bin/chmod a+rwxt /var/spool/mail
-          ${pkgs.coreutils}/bin/ln -sf /var/spool/mail /var/
-
-          ln -sf ${pkgs.postfix}/etc/postfix/postfix-files /var/postfix/conf
-
-          ln -sf ${aliasesFile} /var/postfix/conf/aliases
-          ln -sf ${virtualFile} /var/postfix/conf/virtual
-          ln -sf ${mainCfFile} /var/postfix/conf/main.cf
-          ln -sf ${masterCfFile} /var/postfix/conf/master.cf
-
-          ${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases
-          ${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual
-        '';
-
-        script = ''
-          ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start
-        '';
-
-        reload = ''
-          ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf reload
-        '';
-
-        preStop = ''
-          ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf stop
-        '';
-
-      };
-
-  };
+      systemd.services.postfix =
+        { description = "Postfix mail server";
+
+          wantedBy = [ "multi-user.target" ];
+          after = [ "network.target" ];
+          path = [ pkgs.postfix ];
+
+          serviceConfig = {
+            Type = "forking";
+            Restart = "always";
+            PIDFile = "/var/lib/postfix/queue/pid/master.pid";
+            ExecStart = "${pkgs.postfix}/bin/postfix start";
+            ExecStop = "${pkgs.postfix}/bin/postfix stop";
+            ExecReload = "${pkgs.postfix}/bin/postfix reload";
+          };
+
+          preStart = ''
+            # Backwards compatibility
+            if [ ! -d /var/lib/postfix ] && [ -d /var/postfix ]; then
+              mkdir -p /var/lib
+              mv /var/postfix /var/lib/postfix
+            fi
+            mkdir -p /var/lib/postfix/data /var/lib/postfix/queue/{pid,public,maildrop}
+
+            chown -R ${user}:${group} /var/lib/postfix
+            chown root /var/lib/postfix/queue
+            chown root /var/lib/postfix/queue/pid
+            chgrp -R ${setgidGroup} /var/lib/postfix/queue/{public,maildrop}
+            chmod 770 /var/lib/postfix/queue/{public,maildrop}
+
+            rm -rf /var/lib/postfix/conf
+            mkdir -p /var/lib/postfix/conf
+            ln -sf ${mainCfFile} /var/lib/postfix/conf/main.cf
+            ln -sf ${masterCfFile} /var/lib/postfix/conf/master.cf
+            ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
+              ln -sf ${from} /var/lib/postfix/conf/${to}
+              postalias /var/lib/postfix/conf/${to}
+            '') cfg.aliasFiles)}
+            ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
+              ln -sf ${from} /var/lib/postfix/conf/${to}
+              postmap /var/lib/postfix/conf/${to}
+            '') cfg.mapFiles)}
+
+            mkdir -p /var/spool/mail
+            chown root:root /var/spool/mail
+            chmod a+rwxt /var/spool/mail
+            ln -sf /var/spool/mail /var/
+          '';
+        };
+    }
+
+    (mkIf haveAliases {
+      services.postfix.aliasFiles."aliases" = aliasesFile;
+    })
+    (mkIf haveTransport {
+      services.postfix.mapFiles."transport" = transportFile;
+    })
+    (mkIf haveVirtual {
+      services.postfix.mapFiles."virtual" = virtualFile;
+    })
+  ]);
 
 }
diff --git a/nixos/modules/services/mail/postsrsd.nix b/nixos/modules/services/mail/postsrsd.nix
new file mode 100644
index 00000000000..36a0f8218d8
--- /dev/null
+++ b/nixos/modules/services/mail/postsrsd.nix
@@ -0,0 +1,107 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.postsrsd;
+
+in {
+
+  ###### interface
+
+  options = {
+
+    services.postsrsd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the postsrsd SRS server for Postfix.";
+      };
+
+      domain = mkOption {
+        type = types.str;
+        description = "Domain name for rewrite";
+      };
+
+      secretsFile = mkOption {
+        type = types.path;
+        default = "/var/lib/postsrsd/postsrsd.secret";
+        description = "Secret keys used for signing and verification";
+      };
+
+      forwardPort = mkOption {
+        type = types.int;
+        default = 10001;
+        description = "Port for the forward SRS lookup";
+      };
+
+      reversePort = mkOption {
+        type = types.int;
+        default = 10002;
+        description = "Port for the reverse SRS lookup";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "postsrsd";
+        description = "User for the daemon";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "postsrsd";
+        description = "Group for the daemon";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    services.postsrsd.domain = mkDefault config.networking.hostName;
+
+    users.extraUsers = optionalAttrs (cfg.user == "postsrsd") (singleton
+      { name = "postsrsd";
+        group = cfg.group;
+        uid = config.ids.uids.postsrsd;
+      });
+
+    users.extraGroups = optionalAttrs (cfg.group == "postsrsd") (singleton
+      { name = "postsrsd";
+        gid = config.ids.gids.postsrsd;
+      });
+
+    systemd.services.postsrsd = {
+      description = "PostSRSd SRS rewriting server";
+      after = [ "network.target" ];
+      before = [ "postfix.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+      path = [ pkgs.coreutils ];
+
+      serviceConfig = {
+        ExecStart = ''${pkgs.postsrsd}/sbin/postsrsd "-s${cfg.secretsFile}" "-d${cfg.domain}" -f${toString cfg.forwardPort} -r${toString cfg.reversePort}'';
+        User = cfg.user;
+        Group = cfg.group;
+        PermissionsStartOnly = true;
+      };
+
+      preStart = ''
+        if [ ! -e "${cfg.secretsFile}" ]; then
+          echo "WARNING: secrets file not found, autogenerating!"
+          mkdir -p -m750 "$(dirname "${cfg.secretsFile}")"
+          dd if=/dev/random bs=18 count=1 | base64 > "${cfg.secretsFile}"
+          chmod 600 "${cfg.secretsFile}"
+        fi
+        chown "${cfg.user}:${cfg.group}" "${cfg.secretsFile}"
+      '';
+    };
+
+  };
+}
diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix
new file mode 100644
index 00000000000..a6e2a9fc780
--- /dev/null
+++ b/nixos/modules/services/mail/rmilter.nix
@@ -0,0 +1,189 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  rspamdCfg = config.services.rspamd;
+  cfg = config.services.rmilter;
+
+  rmilterConf = ''
+pidfile = /run/rmilter/rmilter.pid;
+bind_socket = ${cfg.bindSocket};
+tempdir = /tmp;
+
+  '' + (with cfg.rspamd; if enable then ''
+spamd {
+        servers = ${concatStringsSep ", " servers};
+        connect_timeout = 1s;
+        results_timeout = 20s;
+        error_time = 10;
+        dead_time = 300;
+        maxerrors = 10;
+        reject_message = "${rejectMessage}";
+        ${optionalString (length whitelist != 0)  "whitelist = ${concatStringsSep ", " whitelist};"}
+
+        # rspamd_metric - metric for using with rspamd
+        # Default: "default"
+        rspamd_metric = "default";
+        ${extraConfig}
+};
+    '' else "") + cfg.extraConfig;
+
+  rmilterConfigFile = pkgs.writeText "rmilter.conf" rmilterConf;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.rmilter = {
+
+      enable = mkOption {
+        default = cfg.rspamd.enable;
+        description = "Whether to run the rmilter daemon.";
+      };
+
+      debug = mkOption {
+        default = false;
+        description = "Whether to run the rmilter daemon in debug mode.";
+      };
+
+      user = mkOption {
+        type = types.string;
+        default = "rmilter";
+        description = ''
+          User to use when no root privileges are required.
+        '';
+       };
+
+      group = mkOption {
+        type = types.string;
+        default = "rmilter";
+        description = ''
+          Group to use when no root privileges are required.
+        '';
+       };
+
+      bindSocket =  mkOption {
+        type = types.string;
+        default = "unix:/run/rmilter/rmilter.sock";
+        description = "Socket to listed for MTA requests";
+        example = ''
+            "unix:/run/rmilter/rmilter.sock" or
+            "inet:11990@127.0.0.1"
+          '';
+      };
+
+      rspamd = {
+        enable = mkOption {
+          default = rspamdCfg.enable;
+          description = "Whether to use rspamd to filter mails";
+        };
+
+        servers = mkOption {
+          type = types.listOf types.str;
+          default = ["r:0.0.0.0:11333"];
+          description = ''
+            Spamd socket definitions.
+            Is server name is prefixed with r: it is rspamd server.
+          '';
+        };
+
+        whitelist = mkOption {
+          type = types.listOf types.str;
+          default = [ ];
+          description = "list of ips or nets that should be not checked with spamd";
+        };
+
+        rejectMessage = mkOption {
+          type = types.str;
+          default = "Spam message rejected; If this is not spam contact abuse";
+          description = "reject message for spam";
+        };
+
+        extraConfig = mkOption {
+          type = types.lines;
+          default = "";
+          description = "Custom snippet to append to end of `spamd' section";
+        };
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Custom snippet to append to rmilter config";
+      };
+
+      postfix = {
+        enable = mkOption {
+          type = types.bool;
+          default = false;
+          description = "Add rmilter to postfix main.conf";
+        };
+
+        configFragment = mkOption {
+          type = types.str;
+          description = "Addon to postfix configuration";
+          default = ''
+smtpd_milters = ${cfg.bindSocket}
+# or for TCP socket
+# # smtpd_milters = inet:localhost:9900
+milter_protocol = 6
+milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}
+# skip mail without checks if milter will die
+milter_default_action = accept
+          '';
+        };
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = singleton {
+      name = cfg.user;
+      description = "rspamd daemon";
+      uid = config.ids.uids.rmilter;
+      group = cfg.group;
+    };
+
+    users.extraGroups = singleton {
+      name = cfg.group;
+      gid = config.ids.gids.rmilter;
+    };
+
+    systemd.services.rmilter = {
+      description = "Rmilter Service";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}";
+        User = cfg.user;
+        Group = cfg.group;
+        PermissionsStartOnly = true;
+        Restart = "always";
+      };
+
+      preStart = ''
+        ${pkgs.coreutils}/bin/mkdir -p /run/rmilter
+        ${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /run/rmilter
+      '';
+
+    };
+
+    services.postfix.extraConfig = optionalString cfg.postfix.enable cfg.postfix.configFragment;
+
+  };
+
+}
diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix
new file mode 100644
index 00000000000..a083f829324
--- /dev/null
+++ b/nixos/modules/services/mail/rspamd.nix
@@ -0,0 +1,90 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.rspamd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.rspamd = {
+
+      enable = mkOption {
+        default = false;
+        description = "Whether to run the rspamd daemon.";
+      };
+
+      debug = mkOption {
+        default = false;
+        description = "Whether to run the rspamd daemon in debug mode.";
+      };
+
+      user = mkOption {
+        type = types.string;
+        default = "rspamd";
+        description = ''
+          User to use when no root privileges are required.
+        '';
+       };
+
+      group = mkOption {
+        type = types.string;
+        default = "rspamd";
+        description = ''
+          Group to use when no root privileges are required.
+        '';
+       };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    # Allow users to run 'rspamc' and 'rspamadm'.
+    environment.systemPackages = [ pkgs.rspamd ];
+
+    users.extraUsers = singleton {
+      name = cfg.user;
+      description = "rspamd daemon";
+      uid = config.ids.uids.rspamd;
+      group = cfg.group;
+    };
+
+    users.extraGroups = singleton {
+      name = cfg.group;
+      gid = config.ids.gids.spamd;
+    };
+
+    systemd.services.rspamd = {
+      description = "Rspamd Service";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -f";
+        RuntimeDirectory = "/var/lib/rspamd";
+        PermissionsStartOnly = true;
+        Restart = "always";
+      };
+
+      preStart = ''
+        ${pkgs.coreutils}/bin/mkdir -p /var/{lib,log}/rspamd
+        ${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /var/lib/rspamd
+      '';
+
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/mail/spamassassin.nix b/nixos/modules/services/mail/spamassassin.nix
index a3ac9e37242..08953134b3b 100644
--- a/nixos/modules/services/mail/spamassassin.nix
+++ b/nixos/modules/services/mail/spamassassin.nix
@@ -50,15 +50,13 @@ in
       gid = config.ids.gids.spamd;
     };
 
-    jobs.spamd = {
+    systemd.services.spamd = {
       description = "Spam Assassin Server";
 
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
 
-      exec = "${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --nouser-config --virtual-config-dir=/var/lib/spamassassin/user-%u --allow-tell --pidfile=/var/run/spamd.pid";
+      script = "${pkgs.spamassassin}/bin/spamd ${optionalString cfg.debug "-D"} --username=spamd --groupname=spamd --nouser-config --virtual-config-dir=/var/lib/spamassassin/user-%u --allow-tell --pidfile=/var/run/spamd.pid";
     };
-
   };
-
 }
diff --git a/nixos/modules/services/misc/apache-kafka.nix b/nixos/modules/services/misc/apache-kafka.nix
index f6198e03bae..88ce8b5a23f 100644
--- a/nixos/modules/services/misc/apache-kafka.nix
+++ b/nixos/modules/services/misc/apache-kafka.nix
@@ -118,9 +118,8 @@ in {
 
     package = mkOption {
       description = "The kafka package to use";
-
       default = pkgs.apacheKafka;
-
+      defaultText = "pkgs.apacheKafka";
       type = types.package;
     };
 
diff --git a/nixos/modules/services/misc/autofs.nix b/nixos/modules/services/misc/autofs.nix
index b4dae79cf8a..3a95e922820 100644
--- a/nixos/modules/services/misc/autofs.nix
+++ b/nixos/modules/services/misc/autofs.nix
@@ -27,8 +27,9 @@ in
       };
 
       autoMaster = mkOption {
+        type = types.str;
         example = literalExample ''
-          autoMaster = let
+          let
             mapConf = pkgs.writeText "auto" '''
              kernel    -ro,soft,intr       ftp.kernel.org:/pub/linux
              boot      -fstype=ext2        :/dev/hda1
diff --git a/nixos/modules/services/misc/cgminer.nix b/nixos/modules/services/misc/cgminer.nix
index 8f25df809cd..868dc87f723 100644
--- a/nixos/modules/services/misc/cgminer.nix
+++ b/nixos/modules/services/misc/cgminer.nix
@@ -41,6 +41,7 @@ in
 
       package = mkOption {
         default = pkgs.cgminer;
+        defaultText = "pkgs.cgminer";
         description = "Which cgminer derivation to use.";
         type = types.package;
       };
diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix
index 50532a8a16f..c0fbf06e6c4 100644
--- a/nixos/modules/services/misc/confd.nix
+++ b/nixos/modules/services/misc/confd.nix
@@ -64,6 +64,7 @@ in {
     package = mkOption {
       description = "Confd package to use.";
       default = pkgs.confd;
+      defaultText = "pkgs.confd";
       type = types.package;
     };
   };
diff --git a/nixos/modules/services/misc/dictd.nix b/nixos/modules/services/misc/dictd.nix
index 552e0a435ef..118d299042d 100644
--- a/nixos/modules/services/misc/dictd.nix
+++ b/nixos/modules/services/misc/dictd.nix
@@ -51,13 +51,12 @@ with lib;
         gid = config.ids.gids.dictd;
       };
 
-    jobs.dictd =
-      { description = "DICT.org Dictionary Server";
-        startOn = "startup";
-        environment = { LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; };
-        daemonType = "fork";
-        exec = "${pkgs.dict}/sbin/dictd -s -c ${dictdb}/share/dictd/dictd.conf --locale en_US.UTF-8";
-      };
+    systemd.services.dictd = {
+      description = "DICT.org Dictionary Server";
+      wantedBy = [ "multi-user.target" ];
+      environment = { LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; };
+      serviceConfig.Type = "forking";
+      script = "${pkgs.dict}/sbin/dictd -s -c ${dictdb}/share/dictd/dictd.conf --locale en_US.UTF-8";
+    };
   };
-
 }
diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix
index 0534c4fc942..218802e0cf0 100644
--- a/nixos/modules/services/misc/disnix.nix
+++ b/nixos/modules/services/misc/disnix.nix
@@ -91,7 +91,7 @@ in
       ( { hostname = config.networking.hostName;
           #targetHost = config.deployment.targetHost;
           system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system;
-          
+
           supportedTypes = (import "${pkgs.stdenv.mkDerivation {
             name = "supportedtypes";
             buildCommand = ''
@@ -110,6 +110,7 @@ in
         // optionalAttrs (config.services.mysql.enable) { mysqlPort = config.services.mysql.port; }
         // optionalAttrs (config.services.tomcat.enable) { tomcatPort = 8080; }
         // optionalAttrs (config.services.svnserve.enable) { svnBaseDir = config.services.svnserve.svnBaseDir; }
+        // optionalAttrs (config.services.ejabberd.enable) { ejabberdUser = config.services.ejabberd.user; }
         // optionalAttrs (cfg.publishInfrastructure.enableAuthentication) (
           optionalAttrs (config.services.mysql.enable) { mysqlUsername = "root"; mysqlPassword = readFile config.services.mysql.rootPassword; })
         )
@@ -117,63 +118,61 @@ in
 
     services.disnix.publishInfrastructure.enable = cfg.publishAvahi;
 
-    jobs = {
-      disnix =
-        { description = "Disnix server";
-        
-          wants = [ "dysnomia.target" ];
-          wantedBy = [ "multi-user.target" ];
-          after = [ "dbus.service" ]
-            ++ optional config.services.httpd.enable "httpd.service"
-            ++ optional config.services.mysql.enable "mysql.service"
-            ++ optional config.services.postgresql.enable "postgresql.service"
-            ++ optional config.services.tomcat.enable "tomcat.service"
-            ++ optional config.services.svnserve.enable "svnserve.service"
-            ++ optional config.services.mongodb.enable "mongodb.service";
-
-          restartIfChanged = false;
-          
-          path = [ pkgs.nix pkgs.disnix dysnomia "/run/current-system/sw" ];
-          
-          environment = {
-            HOME = "/root";
-          };
-          
-          preStart = ''
-            mkdir -p /etc/systemd-mutable/system
-            if [ ! -f /etc/systemd-mutable/system/dysnomia.target ]
-            then
-                ( echo "[Unit]"
-                  echo "Description=Services that are activated and deactivated by Dysnomia"
-                  echo "After=final.target"
-                ) > /etc/systemd-mutable/system/dysnomia.target
-            fi
-          '';
-
-          exec = "disnix-service";
+    systemd.services = {
+      disnix = {
+        description = "Disnix server";
+        wants = [ "dysnomia.target" ];
+        wantedBy = [ "multi-user.target" ];
+        after = [ "dbus.service" ]
+          ++ optional config.services.httpd.enable "httpd.service"
+          ++ optional config.services.mysql.enable "mysql.service"
+          ++ optional config.services.postgresql.enable "postgresql.service"
+          ++ optional config.services.tomcat.enable "tomcat.service"
+          ++ optional config.services.svnserve.enable "svnserve.service"
+          ++ optional config.services.mongodb.enable "mongodb.service";
+
+        restartIfChanged = false;
+
+        path = [ pkgs.nix pkgs.disnix dysnomia "/run/current-system/sw" ];
+
+        environment = {
+          HOME = "/root";
         };
+
+        preStart = ''
+          mkdir -p /etc/systemd-mutable/system
+          if [ ! -f /etc/systemd-mutable/system/dysnomia.target ]
+          then
+              ( echo "[Unit]"
+                echo "Description=Services that are activated and deactivated by Dysnomia"
+                echo "After=final.target"
+              ) > /etc/systemd-mutable/system/dysnomia.target
+          fi
+        '';
+
+        script = "disnix-service";
+      };
     } // optionalAttrs cfg.publishAvahi {
-      disnixAvahi =
-        { description = "Disnix Avahi publisher";
-
-          startOn = "started avahi-daemon";
-
-          exec =
-          ''
-            ${pkgs.avahi}/bin/avahi-publish-service disnix-${config.networking.hostName} _disnix._tcp 22 \
-              "mem=$(grep 'MemTotal:' /proc/meminfo | sed -e 's/kB//' -e 's/MemTotal://' -e 's/ //g')" \
-              ${concatMapStrings (infrastructureAttrName:
-                let infrastructureAttrValue = getAttr infrastructureAttrName (cfg.infrastructure);
-                in
-                if isInt infrastructureAttrValue then
-                ''${infrastructureAttrName}=${toString infrastructureAttrValue} \
-                ''
-                else
-                ''${infrastructureAttrName}=\"${infrastructureAttrValue}\" \
-                ''
-                ) (attrNames (cfg.infrastructure))}
-          '';
-        };
+      disnixAvahi = {
+        description = "Disnix Avahi publisher";
+        wants = [ "avahi-daemon.service" ];
+        wantedBy = [ "multi-user.target" ];
+
+        script = ''
+          ${pkgs.avahi}/bin/avahi-publish-service disnix-${config.networking.hostName} _disnix._tcp 22 \
+            "mem=$(grep 'MemTotal:' /proc/meminfo | sed -e 's/kB//' -e 's/MemTotal://' -e 's/ //g')" \
+            ${concatMapStrings (infrastructureAttrName:
+              let infrastructureAttrValue = getAttr infrastructureAttrName (cfg.infrastructure);
+              in
+              if isInt infrastructureAttrValue then
+              ''${infrastructureAttrName}=${toString infrastructureAttrValue} \
+              ''
+              else
+              ''${infrastructureAttrName}=\"${infrastructureAttrValue}\" \
+              ''
+              ) (attrNames (cfg.infrastructure))}
+        '';
+      };
     };
   };
 }
diff --git a/nixos/modules/services/misc/docker-registry.nix b/nixos/modules/services/misc/docker-registry.nix
index d0431e546e4..add339f9bdf 100644
--- a/nixos/modules/services/misc/docker-registry.nix
+++ b/nixos/modules/services/misc/docker-registry.nix
@@ -15,7 +15,7 @@ in {
       type = types.bool;
     };
 
-    host = mkOption {
+    listenAddress = mkOption {
       description = "Docker registry host or ip to bind to.";
       default = "127.0.0.1";
       type = types.str;
@@ -50,7 +50,7 @@ in {
       after = [ "network.target" ];
 
       environment = {
-        REGISTRY_HOST = cfg.host;
+        REGISTRY_HOST = cfg.listenAddress;
         REGISTRY_PORT = toString cfg.port;
         GUNICORN_OPTS = "[--preload]"; # see https://github.com/docker/docker-registry#sqlalchemy
         STORAGE_PATH = cfg.storagePath;
@@ -65,7 +65,7 @@ in {
       };
 
       postStart = ''
-        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.host}:${toString cfg.port}/'; do
+        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/'; do
           sleep 1;
         done
       '';
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index e1839b936f0..b3354e33096 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -77,11 +77,11 @@ in {
       default = {};
       example = literalExample ''
         {
-          "CORS": "*",
-          "NAME": "default-name",
-          "MAX_RESULT_BUFFER": "1024",
-          "MAX_CLUSTER_SIZE": "9",
-          "MAX_RETRY_ATTEMPTS": "3"
+          "CORS" = "*";
+          "NAME" = "default-name";
+          "MAX_RESULT_BUFFER" = "1024";
+          "MAX_CLUSTER_SIZE" = "9";
+          "MAX_RETRY_ATTEMPTS" = "3";
         }
       '';
     };
diff --git a/nixos/modules/services/misc/felix.nix b/nixos/modules/services/misc/felix.nix
index a01c7f08b91..d6ad9dcaebc 100644
--- a/nixos/modules/services/misc/felix.nix
+++ b/nixos/modules/services/misc/felix.nix
@@ -23,7 +23,9 @@ in
       };
 
       bundles = mkOption {
+        type = types.listOf types.package;
         default = [ pkgs.felix_remoteshell ];
+        defaultText = "[ pkgs.felix_remoteshell ]";
         description = "List of bundles that should be activated on startup";
       };
 
@@ -57,54 +59,51 @@ in
         home = "/homeless-shelter";
       };
 
-    jobs.felix =
-      { description = "Felix server";
-
-        preStart =
-	  ''
-	    # Initialise felix instance on first startup
-	    if [ ! -d /var/felix ]
-	    then
-	        # Symlink system files
-
-	        mkdir -p /var/felix
-		chown ${cfg.user}:${cfg.group} /var/felix
-
-		for i in ${pkgs.felix}/*
-		do
-		    if [ "$i" != "${pkgs.felix}/bundle" ]
-		    then
-		        ln -sfn $i /var/felix/$(basename $i)
-		    fi
-		done
-
-		# Symlink bundles
-		mkdir -p /var/felix/bundle
-		chown ${cfg.user}:${cfg.group} /var/felix/bundle
-
-		for i in ${pkgs.felix}/bundle/* ${toString cfg.bundles}
-		do
-		    if [ -f $i ]
-		    then
-		        ln -sfn $i /var/felix/bundle/$(basename $i)
-		    elif [ -d $i ]
-		    then
-		        for j in $i/bundle/*
-			do
-			    ln -sfn $j /var/felix/bundle/$(basename $j)
-			done
-		    fi
-		done
-	    fi
-	  '';
-
-        script =
-          ''
-	    cd /var/felix
-            ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c '${pkgs.jre}/bin/java -jar bin/felix.jar'
-          '';
-      };
-
+    systemd.services.felix = {
+      description = "Felix server";
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = ''
+        # Initialise felix instance on first startup
+        if [ ! -d /var/felix ]
+        then
+          # Symlink system files
+
+          mkdir -p /var/felix
+          chown ${cfg.user}:${cfg.group} /var/felix
+
+          for i in ${pkgs.felix}/*
+          do
+              if [ "$i" != "${pkgs.felix}/bundle" ]
+              then
+                  ln -sfn $i /var/felix/$(basename $i)
+              fi
+          done
+
+          # Symlink bundles
+          mkdir -p /var/felix/bundle
+          chown ${cfg.user}:${cfg.group} /var/felix/bundle
+
+          for i in ${pkgs.felix}/bundle/* ${toString cfg.bundles}
+          do
+              if [ -f $i ]
+              then
+                  ln -sfn $i /var/felix/bundle/$(basename $i)
+              elif [ -d $i ]
+              then
+                  for j in $i/bundle/*
+              do
+                  ln -sfn $j /var/felix/bundle/$(basename $j)
+              done
+              fi
+          done
+        fi
+      '';
+
+      script = ''
+        cd /var/felix
+        ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c '${pkgs.jre}/bin/java -jar bin/felix.jar'
+      '';
+    };
   };
-
 }
diff --git a/nixos/modules/services/misc/folding-at-home.nix b/nixos/modules/services/misc/folding-at-home.nix
index 392d2d1f002..4f09cbfdd79 100644
--- a/nixos/modules/services/misc/folding-at-home.nix
+++ b/nixos/modules/services/misc/folding-at-home.nix
@@ -49,26 +49,20 @@ in {
         home = stateDir;
       };
 
-    jobs.foldingAtHome =
-      { name = "foldingathome";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        preStart =
-          ''
-            mkdir -m 0755 -p ${stateDir}
-            chown ${fahUser} ${stateDir}
-            cp -f ${pkgs.writeText "client.cfg" cfg.config} ${stateDir}/client.cfg
-          '';
-        exec = "${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${fahUser} -c 'cd ${stateDir}; ${pkgs.foldingathome}/bin/fah6'";
-      };
-
-      services.foldingAtHome.config = ''
-          [settings]
-          username=${cfg.nickname}
+    systemd.services.foldingathome = {
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+        chown ${fahUser} ${stateDir}
+        cp -f ${pkgs.writeText "client.cfg" cfg.config} ${stateDir}/client.cfg
       '';
+      script = "${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${fahUser} -c 'cd ${stateDir}; ${pkgs.foldingathome}/bin/fah6'";
+    };
 
+    services.foldingAtHome.config = ''
+        [settings]
+        username=${cfg.nickname}
+    '';
   };
-
 }
diff --git a/nixos/modules/services/misc/gitit.nix b/nixos/modules/services/misc/gitit.nix
index befd8c628f1..ab4d385ba16 100644
--- a/nixos/modules/services/misc/gitit.nix
+++ b/nixos/modules/services/misc/gitit.nix
@@ -35,6 +35,7 @@ let
       };
 
       haskellPackages = mkOption {
+        type = types.attrsOf types.package;
         default = pkgs.haskellPackages;
         defaultText = "pkgs.haskellPackages";
         example = literalExample "pkgs.haskell.packages.ghc784";
diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix
index 13c41466eab..1927922909e 100644
--- a/nixos/modules/services/misc/ihaskell.nix
+++ b/nixos/modules/services/misc/ihaskell.nix
@@ -22,6 +22,7 @@ in
       };
 
       haskellPackages = mkOption {
+        type = types.attrsOf types.package;
         default = pkgs.haskellPackages;
         defaultText = "pkgs.haskellPackages";
         example = literalExample "pkgs.haskell.packages.ghc784";
diff --git a/nixos/modules/services/misc/mathics.nix b/nixos/modules/services/misc/mathics.nix
new file mode 100644
index 00000000000..50715858881
--- /dev/null
+++ b/nixos/modules/services/misc/mathics.nix
@@ -0,0 +1,54 @@
+{ pkgs, lib, config, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mathics;
+
+in {
+  options = {
+    services.mathics = {
+      enable = mkEnableOption "Mathics notebook service";
+
+      external = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Listen on all interfaces, rather than just localhost?";
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 8000;
+        description = "TCP port to listen on.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers.mathics = {
+      group = config.users.extraGroups.mathics.name;
+      description = "Mathics user";
+      home = "/var/lib/mathics";
+      createHome = true;
+      uid = config.ids.uids.mathics;
+    };
+
+    users.extraGroups.mathics.gid = config.ids.gids.mathics;
+
+    systemd.services.mathics = {
+      description = "Mathics notebook server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        User = config.users.extraUsers.mathics.name;
+        Group = config.users.extraGroups.mathics.name;
+        ExecStart = concatStringsSep " " [
+          "${pkgs.mathics}/bin/mathicsserver"
+          "--port" (toString cfg.port)
+          (if cfg.external then "--external" else "")
+        ];
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/matrix-synapse-log_config.yaml b/nixos/modules/services/misc/matrix-synapse-log_config.yaml
new file mode 100644
index 00000000000..d85bdd1208f
--- /dev/null
+++ b/nixos/modules/services/misc/matrix-synapse-log_config.yaml
@@ -0,0 +1,25 @@
+version: 1
+
+# In systemd's journal, loglevel is implicitly stored, so let's omit it
+# from the message text.
+formatters:
+    journal_fmt:
+        format: '%(name)s: [%(request)s] %(message)s'
+
+filters:
+    context:
+        (): synapse.util.logcontext.LoggingContextFilter
+        request: ""
+
+handlers:
+    journal:
+        class: systemd.journal.JournalHandler
+        formatter: journal_fmt
+        filters: [context]
+        SYSLOG_IDENTIFIER: synapse
+
+root:
+    level: INFO
+    handlers: [journal]
+
+disable_existing_loggers: False
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
new file mode 100644
index 00000000000..27c5a38e6b8
--- /dev/null
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -0,0 +1,279 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.matrix-synapse;
+  logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
+  configFile = pkgs.writeText "homeserver.yaml" ''
+tls_certificate_path: "${cfg.tls_certificate_path}"
+tls_private_key_path: "${cfg.tls_private_key_path}"
+tls_dh_params_path: "${cfg.tls_dh_params_path}"
+no_tls: ${if cfg.no_tls then "true" else "false"}
+bind_port: ${toString cfg.bind_port}
+unsecure_port: ${toString cfg.unsecure_port}
+bind_host: "${cfg.bind_host}"
+server_name: "${cfg.server_name}"
+pid_file: "/var/run/matrix-synapse.pid"
+web_client: ${if cfg.web_client then "true" else "false"}
+database: {
+  name: "${cfg.database_type}",
+  args: {
+    ${concatStringsSep ",\n    " (
+      mapAttrsToList (n: v: "\"${n}\": ${v}") cfg.database_args
+    )}
+  }
+}
+log_file: "/var/log/matrix-synapse/homeserver.log"
+log_config: "${logConfigFile}"
+media_store_path: "/var/lib/matrix-synapse/media"
+recaptcha_private_key: "${cfg.recaptcha_private_key}"
+recaptcha_public_key: "${cfg.recaptcha_public_key}"
+enable_registration_captcha: ${if cfg.enable_registration_captcha then "true" else "false"}
+turn_uris: ${if (length cfg.turn_uris) == 0 then "[]" else ("\n" + (concatStringsSep "\n" (map (s: "- " + s) cfg.turn_uris)))}
+turn_shared_secret: "${cfg.turn_shared_secret}"
+enable_registration: ${if cfg.enable_registration then "true" else "false"}
+${optionalString (cfg.registration_shared_secret != "") ''
+registration_shared_secret: "${cfg.registration_shared_secret}"
+''}
+enable_metrics: ${if cfg.enable_metrics then "true" else "false"}
+report_stats: ${if cfg.report_stats then "true" else "false"}
+signing_key_path: "/var/lib/matrix-synapse/homeserver.signing.key"
+perspectives:
+  servers: {
+    ${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
+    "${n}": {
+      "verify_keys": {
+        ${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
+        "${n}": {
+          "key": "${v}"
+        }'') v)}
+      }
+    '') cfg.servers)}
+    }
+  }
+${cfg.extraConfig}
+'';
+in {
+  options = {
+    services.matrix-synapse = {
+      enable = mkEnableOption "matrix.org synapse";
+      package = mkOption {
+        type = types.package;
+        default = pkgs.matrix-synapse;
+        description = ''
+          Overridable attribute of the matrix synapse server package to use.
+        '';
+      };
+      no_tls = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Don't bind to the https port
+        '';
+      };
+      tls_certificate_path = mkOption {
+        type = types.path;
+        default = "/var/lib/matrix-synapse/homeserver.tls.crt";
+        description = ''
+          PEM encoded X509 certificate for TLS
+        '';
+      };
+      tls_private_key_path = mkOption {
+        type = types.path;
+        default = "/var/lib/matrix-synapse/homeserver.tls.key";
+        description = ''
+          PEM encoded private key for TLS
+        '';
+      };
+      tls_dh_params_path = mkOption {
+        type = types.path;
+        default = "/var/lib/matrix-synapse/homeserver.tls.dh";
+        description = ''
+          PEM dh parameters for ephemeral keys
+        '';
+      };
+      bind_port = mkOption {
+        type = types.int;
+        default = 8448;
+        description = ''
+          The port to listen for HTTPS requests on.
+          For when matrix traffic is sent directly to synapse.
+        '';
+      };
+      unsecure_port = mkOption {
+        type = types.int;
+        default = 8008;
+        description = ''
+          The port to listen for HTTP requests on.
+          For when matrix traffic passes through loadbalancer that unwraps TLS.
+        '';
+      };
+      bind_host = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          Local interface to listen on.
+          The empty string will cause synapse to listen on all interfaces.
+        '';
+      };
+      server_name = mkOption {
+        type = types.str;
+        description = ''
+          The domain name of the server, with optional explicit port.
+          This is used by remote servers to connect to this server,
+          e.g. matrix.org, localhost:8080, etc.
+          This is also the last part of your UserID.
+        '';
+      };
+      web_client = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to serve a web client from the HTTP/HTTPS root resource.
+        '';
+      };
+      database_type = mkOption {
+        type = types.enum [ "sqlite3" "psycopg2" ];
+        default = "sqlite3";
+        description = ''
+          The database engine name. Can be sqlite or psycopg2.
+        '';
+      };
+      database_args = mkOption {
+        type = types.attrs;
+        default = {
+          database = "/var/lib/matrix-synapse/homeserver.db";
+        };
+        description = ''
+          Arguments to pass to the engine.
+        '';
+      };
+      recaptcha_private_key = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          This Home Server's ReCAPTCHA private key.
+        '';
+      };
+      recaptcha_public_key = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          This Home Server's ReCAPTCHA public key.
+        '';
+      };
+      enable_registration_captcha = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enables ReCaptcha checks when registering, preventing signup
+          unless a captcha is answered. Requires a valid ReCaptcha
+          public/private key.
+        '';
+      };
+      turn_uris = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          The public URIs of the TURN server to give to clients
+        '';
+      };
+      turn_shared_secret = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          The shared secret used to compute passwords for the TURN server
+        '';
+      };
+      enable_registration = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable registration for new users.
+        '';
+      };
+      registration_shared_secret = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          If set, allows registration by anyone who also has the shared
+          secret, even if registration is otherwise disabled.
+        '';
+      };
+      enable_metrics = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable collection and rendering of performance metrics
+        '';
+      };
+      report_stats = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+        '';
+      };
+      servers = mkOption {
+        type = types.attrs;
+        default = {
+          "matrix.org" = {
+            "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
+          };
+        };
+        description = ''
+          The trusted servers to download signing keys from.
+        '';
+      };
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra config options for matrix-synapse.
+        '';
+      };
+      logConfig = mkOption {
+        type = types.lines;
+        default = readFile ./matrix-synapse-log_config.yaml;
+        description = ''
+          A yaml python logging config file
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers = [
+      { name = "matrix-synapse";
+        group = "matrix-synapse";
+        home = "/var/lib/matrix-synapse";
+        createHome = true;
+        shell = "${pkgs.bash}/bin/bash";
+        uid = config.ids.uids.matrix-synapse;
+      } ];
+
+    users.extraGroups = [
+      { name = "matrix-synapse";
+        gid = config.ids.gids.matrix-synapse;
+      } ];
+
+    systemd.services.matrix-synapse = {
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -p /var/lib/matrix-synapse
+        chmod 700 /var/lib/matrix-synapse
+        chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse
+        ${cfg.package}/bin/homeserver --config-path ${configFile} --generate-keys
+      '';
+      serviceConfig = {
+        Type = "simple";
+        User = "matrix-synapse";
+        Group = "matrix-synapse";
+        WorkingDirectory = "/var/lib/matrix-synapse";
+        PermissionsStartOnly = true;
+        ExecStart = "${cfg.package}/bin/homeserver --config-path ${configFile}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/mbpfan.nix b/nixos/modules/services/misc/mbpfan.nix
index 3fb5f684b76..972d8b572d3 100644
--- a/nixos/modules/services/misc/mbpfan.nix
+++ b/nixos/modules/services/misc/mbpfan.nix
@@ -17,7 +17,9 @@ in {
     };
 
     package = mkOption {
+      type = types.package;
       default = pkgs.mbpfan;
+      defaultText = "pkgs.mbpfan";
       description = ''
         The package used for the mbpfan daemon.
       '';
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index ceffdbead4e..60e826bafd1 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -66,6 +66,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.nix;
+        defaultText = "pkgs.nix";
         description = ''
           This option specifies the Nix package instance to use throughout the system.
         '';
diff --git a/nixos/modules/services/misc/plex.nix b/nixos/modules/services/misc/plex.nix
index de8bc71a271..fb62351365e 100644
--- a/nixos/modules/services/misc/plex.nix
+++ b/nixos/modules/services/misc/plex.nix
@@ -54,6 +54,15 @@ in
           false.
         '';
       };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.plex;
+        description = ''
+          The Plex package to use. Plex subscribers may wish to use their own
+          package here, pointing to subscriber-only server versions.
+        '';
+      };
     };
   };
 
@@ -66,7 +75,7 @@ in
       preStart = ''
         test -d "${cfg.dataDir}" || {
           echo "Creating initial Plex data directory in \"${cfg.dataDir}\"."
-          mkdir -p "${cfg.dataDir}"
+          mkdir -p "${cfg.dataDir}/Plex Media Server"
           chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}"
         }
 
@@ -75,7 +84,7 @@ in
         # why this is done.
         test -d "${cfg.dataDir}/.skeleton" || mkdir "${cfg.dataDir}/.skeleton"
         for db in "com.plexapp.plugins.library.db"; do
-            cp "${plex}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db"
+            cp "${cfg.package}/usr/lib/plexmediaserver/Resources/base_$db" "${cfg.dataDir}/.skeleton/$db"
             chmod u+w "${cfg.dataDir}/.skeleton/$db"
             chown ${cfg.user}:${cfg.group} "${cfg.dataDir}/.skeleton/$db"
         done
@@ -117,14 +126,14 @@ in
         User = cfg.user;
         Group = cfg.group;
         PermissionsStartOnly = "true";
-        ExecStart = "/bin/sh -c '${plex}/usr/lib/plexmediaserver/Plex\\ Media\\ Server'";
+        ExecStart = "/bin/sh -c '${cfg.package}/usr/lib/plexmediaserver/Plex\\ Media\\ Server'";
       };
       environment = {
         PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR=cfg.dataDir;
-        PLEX_MEDIA_SERVER_HOME="${plex}/usr/lib/plexmediaserver";
+        PLEX_MEDIA_SERVER_HOME="${cfg.package}/usr/lib/plexmediaserver";
         PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="6";
         PLEX_MEDIA_SERVER_TMPDIR="/tmp";
-        LD_LIBRARY_PATH="${plex}/usr/lib/plexmediaserver";
+        LD_LIBRARY_PATH="${cfg.package}/usr/lib/plexmediaserver";
         LC_ALL="en_US.UTF-8";
         LANG="en_US.UTF-8";
       };
diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix
index d940c1bc900..c6b67e8498c 100644
--- a/nixos/modules/services/misc/rippled.nix
+++ b/nixos/modules/services/misc/rippled.nix
@@ -208,6 +208,7 @@ in
 	description = "Which rippled package to use.";
 	type = types.package;
 	default = pkgs.rippled;
+	defaultText = "pkgs.rippled";
       };
 
       ports = mkOption {
@@ -238,7 +239,7 @@ in
       nodeDb = mkOption {
 	description = "Rippled main database options.";
 	type = types.nullOr types.optionSet;
-	options = [dbOptions];
+	options = dbOptions;
 	default = {
 	  type = "rocksdb";
 	  extraOpts = ''
@@ -254,14 +255,14 @@ in
       tempDb = mkOption {
 	description = "Rippled temporary database options.";
 	type = types.nullOr types.optionSet;
-	options = [dbOptions];
+	options = dbOptions;
 	default = null;
       };
 
       importDb = mkOption {
 	description = "Settings for performing a one-time import.";
 	type = types.nullOr types.optionSet;
-	options = [dbOptions];
+	options = dbOptions;
 	default = null;
       };
 
diff --git a/nixos/modules/services/misc/subsonic.nix b/nixos/modules/services/misc/subsonic.nix
index b737a0b8e74..5a33aa33b26 100644
--- a/nixos/modules/services/misc/subsonic.nix
+++ b/nixos/modules/services/misc/subsonic.nix
@@ -21,7 +21,7 @@ in
         '';
       };
 
-      host = mkOption {
+      listenAddress = mkOption {
         type = types.string;
         default = "0.0.0.0";
         description = ''
@@ -115,7 +115,7 @@ in
         ExecStart = ''
           ${pkgs.jre}/bin/java -Xmx${toString cfg.maxMemory}m \
             -Dsubsonic.home=${cfg.home} \
-            -Dsubsonic.host=${cfg.host} \
+            -Dsubsonic.host=${cfg.listenAddress} \
             -Dsubsonic.port=${toString cfg.port} \
             -Dsubsonic.httpsPort=${toString cfg.httpsPort} \
             -Dsubsonic.contextPath=${cfg.contextPath} \
diff --git a/nixos/modules/services/misc/svnserve.nix b/nixos/modules/services/misc/svnserve.nix
index 601d50a3e26..c74befac749 100644
--- a/nixos/modules/services/misc/svnserve.nix
+++ b/nixos/modules/services/misc/svnserve.nix
@@ -34,13 +34,11 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
-    jobs.svnserve = {
-      startOn = "started network-interfaces";
-      stopOn = "stopping network-interfaces";
-
+    systemd.services.svnserve = {
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
       preStart = "mkdir -p ${cfg.svnBaseDir}";
-
-      exec = "${pkgs.subversion.out}/bin/svnserve -r ${cfg.svnBaseDir} -d --foreground --pid-file=/var/run/svnserve.pid";
+      script = "${pkgs.subversion.out}/bin/svnserve -r ${cfg.svnBaseDir} -d --foreground --pid-file=/var/run/svnserve.pid";
     };
   };
 }
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
index 214a19d9483..46273fc1218 100644
--- a/nixos/modules/services/monitoring/bosun.nix
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -33,6 +33,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pkgs.bosun;
+        defaultText = "pkgs.bosun";
         example = literalExample "pkgs.bosun";
         description = ''
           bosun binary to use.
diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix
index 031558a373c..a67df158be4 100644
--- a/nixos/modules/services/monitoring/cadvisor.nix
+++ b/nixos/modules/services/monitoring/cadvisor.nix
@@ -14,7 +14,7 @@ in {
         description = "Whether to enable cadvisor service.";
       };
 
-      host = mkOption {
+      listenAddress = mkOption {
         default = "127.0.0.1";
         type = types.str;
         description = "Cadvisor listening host";
@@ -71,7 +71,7 @@ in {
       after = [ "network.target" "docker.service" "influxdb.service" ];
 
       postStart = mkBefore ''
-        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.host}:${toString cfg.port}/containers/'; do
+        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/containers/'; do
           sleep 1;
         done
       '';
@@ -79,7 +79,7 @@ in {
       serviceConfig = {
         ExecStart = ''${pkgs.cadvisor}/bin/cadvisor \
           -logtostderr=true \
-          -listen_ip=${cfg.host} \
+          -listen_ip=${cfg.listenAddress} \
           -port=${toString cfg.port} \
           ${optionalString (cfg.storageDriver != null) ''
             -storage_driver ${cfg.storageDriver} \
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index 6053990e8d3..0b49038dd27 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -93,6 +93,7 @@ in {
     package = mkOption {
       description = "Package to use.";
       default = pkgs.grafana;
+      defaultText = "pkgs.grafana";
       type = types.package;
     };
 
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index 57abb959fdb..976fd253a7c 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -77,7 +77,7 @@ in {
         type = types.bool;
       };
 
-      host = mkOption {
+      listenAddress = mkOption {
         description = "Graphite web frontend listen address.";
         default = "127.0.0.1";
         type = types.str;
@@ -108,7 +108,7 @@ in {
       finders = mkOption {
         description = "List of finder plugins to load.";
         default = [];
-        example = [ pkgs.python27Packages.graphite_influxdb ];
+        example = literalExample "[ pkgs.python27Packages.graphite_influxdb ]";
         type = types.listOf types.package;
       };
 
@@ -121,7 +121,7 @@ in {
         type = types.listOf types.str;
       };
 
-      host = mkOption {
+      listenAddress = mkOption {
         description = "Graphite web service listen address.";
         default = "127.0.0.1";
         type = types.str;
@@ -136,6 +136,7 @@ in {
       package = mkOption {
         description = "Package to use for graphite api.";
         default = pkgs.python27Packages.graphite_api;
+        defaultText = "pkgs.python27Packages.graphite_api";
         type = types.package;
       };
 
@@ -146,7 +147,7 @@ in {
             directories:
                 - ${dataDir}/whisper
         '';
-        example = literalExample ''
+        example = ''
           allowed_origins:
             - dashboard.example.com
           cheat_times: true
@@ -256,13 +257,13 @@ in {
       };
 
       enableAggregator = mkOption {
-        description = "Whether to enable carbon agregator, the carbon buffering service.";
+        description = "Whether to enable carbon aggregator, the carbon buffering service.";
         default = false;
         type = types.bool;
       };
 
       aggregationRules = mkOption {
-        description = "Defines if and how received metrics will be agregated.";
+        description = "Defines if and how received metrics will be aggregated.";
         default = null;
         type = types.uniq (types.nullOr types.string);
         example = ''
@@ -292,7 +293,7 @@ in {
       };
 
       graphiteUrl = mkOption {
-        default = "http://${cfg.web.host}:${toString cfg.web.port}";
+        default = "http://${cfg.web.listenAddress}:${toString cfg.web.port}";
         description = "Host where graphite service runs.";
         type = types.str;
       };
@@ -337,7 +338,7 @@ in {
 
       graphiteUrl = mkOption {
         description = "URL to your graphite service.";
-        default = "http://${cfg.web.host}:${toString cfg.web.port}";
+        default = "http://${cfg.web.listenAddress}:${toString cfg.web.port}";
         type = types.str;
       };
 
@@ -350,7 +351,7 @@ in {
               critical: 200
               name: Test
         '';
-        example = literalExample ''
+        example = ''
           pushbullet_key: pushbullet_api_key
           alerts:
             - target: stats.seatgeek.app.deal_quality.venue_info_cache.hit
@@ -452,7 +453,7 @@ in {
         serviceConfig = {
           ExecStart = ''
             ${pkgs.python27Packages.waitress}/bin/waitress-serve \
-            --host=${cfg.web.host} --port=${toString cfg.web.port} \
+            --host=${cfg.web.listenAddress} --port=${toString cfg.web.port} \
             --call django.core.handlers.wsgi:WSGIHandler'';
           User = "graphite";
           Group = "graphite";
@@ -494,7 +495,7 @@ in {
         serviceConfig = {
           ExecStart = ''
             ${pkgs.python27Packages.waitress}/bin/waitress-serve \
-            --host=${cfg.api.host} --port=${toString cfg.api.port} \
+            --host=${cfg.api.listenAddress} --port=${toString cfg.api.port} \
             graphite_api.app:app
           '';
           User = "graphite";
diff --git a/nixos/modules/services/monitoring/heapster.nix b/nixos/modules/services/monitoring/heapster.nix
index 74b8c9ccd3e..deee64aa41e 100644
--- a/nixos/modules/services/monitoring/heapster.nix
+++ b/nixos/modules/services/monitoring/heapster.nix
@@ -33,6 +33,7 @@ in {
     package = mkOption {
       description = "Package to use by heapster";
       default = pkgs.heapster;
+      defaultText = "pkgs.heapster";
       type = types.package;
     };
   };
diff --git a/nixos/modules/services/monitoring/monit.nix b/nixos/modules/services/monitoring/monit.nix
index 642fac3b3a0..704693969a3 100644
--- a/nixos/modules/services/monitoring/monit.nix
+++ b/nixos/modules/services/monitoring/monit.nix
@@ -19,10 +19,6 @@ in
         default = "";
         description = "monit.conf content";
       };
-      startOn = mkOption {
-        default = "started network-interfaces";
-        description = "What Monit supposes to be already present";
-      };
     };
   };
 
@@ -39,14 +35,12 @@ in
       }
     ];
 
-    jobs.monit = {
+    systemd.services.monit = {
       description = "Monit system watcher";
-
-      startOn = config.services.monit.startOn;
-
-      exec = "${pkgs.monit}/bin/monit -I -c /etc/monit.conf";
-
-      respawn = true;
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      script = "${pkgs.monit}/bin/monit -I -c /etc/monit.conf";
+      serviceConfig.Restart = "always";
     };
   };
 }
diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix
index 31afa859e25..aaa041ad4cd 100644
--- a/nixos/modules/services/monitoring/munin.nix
+++ b/nixos/modules/services/monitoring/munin.nix
@@ -122,21 +122,6 @@ in
           HTML output is in <filename>/var/www/munin/</filename>, configure your
           favourite webserver to serve static files.
         '';
-        example = literalExample ''
-          services = {
-             munin-node.enable = true;
-             munin-cron = {
-               enable = true;
-               hosts = '''
-                 [''${config.networking.hostName}]
-                 address localhost
-               ''';
-               extraGlobalConfig = '''
-                 contact.email.command mail -s "Munin notification for ''${var:host}" someone@example.com
-               ''';
-             };
-          };
-        '';
       };
 
       extraGlobalConfig = mkOption {
@@ -147,6 +132,9 @@ in
           Useful to setup notifications, see
           <link xlink:href='http://munin-monitoring.org/wiki/HowToContact' />
         '';
+        example = ''
+          contact.email.command mail -s "Munin notification for ''${var:host}" someone@example.com
+        '';
       };
 
       hosts = mkOption {
diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix
index c1f7ba0eca7..f2f7710de9e 100644
--- a/nixos/modules/services/monitoring/nagios.nix
+++ b/nixos/modules/services/monitoring/nagios.nix
@@ -94,7 +94,9 @@ in
       };
 
       plugins = mkOption {
+        type = types.listOf types.package;
         default = [pkgs.nagiosPluginsOfficial pkgs.ssmtp];
+        defaultText = "[pkgs.nagiosPluginsOfficial pkgs.ssmtp]";
         description = "
           Packages to be added to the Nagios <envar>PATH</envar>.
           Typically used to add plugins, but can be anything.
@@ -102,14 +104,18 @@ in
       };
 
       mainConfigFile = mkOption {
+        type = types.package;
         default = nagiosCfgFile;
+        defaultText = "nagiosCfgFile";
         description = "
           Derivation for the main configuration file of Nagios.
         ";
       };
 
       cgiConfigFile = mkOption {
+        type = types.package;
         default = nagiosCGICfgFile;
+        defaultText = "nagiosCGICfgFile";
         description = "
           Derivation for the configuration file of Nagios CGI scripts
           that can be used in web servers for running the Nagios web interface.
diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix
index 8b97daf8881..1e397435e60 100644
--- a/nixos/modules/services/monitoring/scollector.nix
+++ b/nixos/modules/services/monitoring/scollector.nix
@@ -43,6 +43,7 @@ in {
       package = mkOption {
         type = types.package;
         default = pkgs.scollector;
+        defaultText = "pkgs.scollector";
         example = literalExample "pkgs.scollector";
         description = ''
           scollector binary to use.
@@ -77,7 +78,7 @@ in {
       collectors = mkOption {
         type = with types; attrsOf (listOf path);
         default = {};
-        example = literalExample "{ 0 = [ \"\${postgresStats}/bin/collect-stats\" ]; }";
+        example = literalExample "{ \"0\" = [ \"\${postgresStats}/bin/collect-stats\" ]; }";
         description = ''
           An attribute set mapping the frequency of collection to a list of
           binaries that should be executed at that frequency. You can use "0"
diff --git a/nixos/modules/services/monitoring/statsd.nix b/nixos/modules/services/monitoring/statsd.nix
index 39fabc27d6c..df2adb9f276 100644
--- a/nixos/modules/services/monitoring/statsd.nix
+++ b/nixos/modules/services/monitoring/statsd.nix
@@ -11,7 +11,7 @@ let
 
   configFile = pkgs.writeText "statsd.conf" ''
     {
-      address: "${cfg.host}",
+      address: "${cfg.listenAddress}",
       port: "${toString cfg.port}",
       mgmt_address: "${cfg.mgmt_address}",
       mgmt_port: "${toString cfg.mgmt_port}",
@@ -48,7 +48,7 @@ in
       type = types.bool;
     };
 
-    host = mkOption {
+    listenAddress = mkOption {
       description = "Address that statsd listens on over UDP";
       default = "127.0.0.1";
       type = types.str;
diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix
index eb478f7da65..5f80d547dbc 100644
--- a/nixos/modules/services/monitoring/ups.nix
+++ b/nixos/modules/services/monitoring/ups.nix
@@ -180,31 +180,36 @@ in
 
     environment.systemPackages = [ pkgs.nut ];
 
-    jobs.upsmon = {
+    systemd.services.upsmon = {
       description = "Uninterruptible Power Supplies (Monitor)";
-      startOn = "ip-up";
-      daemonType = "fork";
-      exec = ''${pkgs.nut}/sbin/upsmon'';
+      wantedBy = [ "ip-up.target" ];
+      serviceConfig.Type = "forking";
+      script = "${pkgs.nut}/sbin/upsmon";
       environment.NUT_CONFPATH = "/etc/nut/";
       environment.NUT_STATEPATH = "/var/lib/nut/";
     };
 
-    jobs.upsd = {
+    systemd.services.upsd = {
       description = "Uninterruptible Power Supplies (Daemon)";
-      startOn = "started network-interfaces and started upsmon";
-      daemonType = "fork";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" "upsmon.service" ];
+      serviceConfig.Type = "forking";
       # TODO: replace 'root' by another username.
-      exec = ''${pkgs.nut}/sbin/upsd -u root'';
+      script = "${pkgs.nut}/sbin/upsd -u root";
       environment.NUT_CONFPATH = "/etc/nut/";
       environment.NUT_STATEPATH = "/var/lib/nut/";
     };
 
-    jobs.upsdrv = {
+    systemd.services.upsdrv = {
       description = "Uninterruptible Power Supplies (Register all UPS)";
-      startOn = "started upsd";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "upsd.service" ];
       # TODO: replace 'root' by another username.
-      exec = ''${pkgs.nut}/bin/upsdrvctl -u root start'';
-      task = true;
+      script = ''${pkgs.nut}/bin/upsdrvctl -u root start'';
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+      };
       environment.NUT_CONFPATH = "/etc/nut/";
       environment.NUT_STATEPATH = "/var/lib/nut/";
     };
diff --git a/nixos/modules/services/network-filesystems/drbd.nix b/nixos/modules/services/network-filesystems/drbd.nix
index 1bd67206444..9896a93b189 100644
--- a/nixos/modules/services/network-filesystems/drbd.nix
+++ b/nixos/modules/services/network-filesystems/drbd.nix
@@ -31,13 +31,13 @@ let cfg = config.services.drbd; in
 
   };
 
-  
+
   ###### implementation
 
   config = mkIf cfg.enable {
-  
+
     environment.systemPackages = [ pkgs.drbd ];
-    
+
     services.udev.packages = [ pkgs.drbd ];
 
     boot.kernelModules = [ "drbd" ];
@@ -52,26 +52,16 @@ let cfg = config.services.drbd; in
         target = "drbd.conf";
       };
 
-    jobs.drbd_up =
-      { name = "drbd-up";
-        startOn = "stopped udevtrigger or ip-up";
-        task = true;
-        script =
-          ''
-            ${pkgs.drbd}/sbin/drbdadm up all
-          '';
-      };
-    
-    jobs.drbd_down =
-      { name = "drbd-down";
-        startOn = "starting shutdown";
-        task = true;
-        script =
-          ''
-            ${pkgs.drbd}/sbin/drbdadm down all
-          '';
-      };
-    
+    systemd.services.drbd = {
+      after = [ "systemd-udev.settle.service" ];
+      wants = [ "systemd-udev.settle.service" ];
+      wantedBy = [ "ip-up.target" ];
+      script = ''
+        ${pkgs.drbd}/sbin/drbdadm up all
+      '';
+      serviceConfig.ExecStop = ''
+        ${pkgs.drbd}/sbin/drbdadm down all
+      '';
+    };
   };
-  
 }
diff --git a/nixos/modules/services/network-filesystems/openafs-client/default.nix b/nixos/modules/services/network-filesystems/openafs-client/default.nix
index 0297da9e865..7a44fc1ea5e 100644
--- a/nixos/modules/services/network-filesystems/openafs-client/default.nix
+++ b/nixos/modules/services/network-filesystems/openafs-client/default.nix
@@ -72,34 +72,28 @@ in
       }
     ];
 
-    jobs.openafsClient =
-      { name = "afsd";
-
-        description = "AFS client";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        preStart = ''
-          mkdir -p -m 0755 /afs
-          mkdir -m 0700 -p ${cfg.cacheDirectory}
-          ${pkgs.module_init_tools}/sbin/insmod ${openafsPkgs}/lib/openafs/libafs-*.ko || true
-          ${openafsPkgs}/sbin/afsd -confdir ${afsConfig} -cachedir ${cfg.cacheDirectory} ${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} -fakestat -afsdb
-          ${openafsPkgs}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
-        '';
-
-        # Doing this in preStop, because after these commands AFS is basically
-        # stopped, so systemd has nothing to do, just noticing it.  If done in
-        # postStop, then we get a hang + kernel oops, because AFS can't be
-        # stopped simply by sending signals to processes.
-        preStop = ''
-          ${pkgs.utillinux}/bin/umount /afs
-          ${openafsPkgs}/sbin/afsd -shutdown
-          ${pkgs.module_init_tools}/sbin/rmmod libafs
-        '';
-
-      };
-
+    systemd.services.afsd = {
+      description = "AFS client";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+
+      preStart = ''
+        mkdir -p -m 0755 /afs
+        mkdir -m 0700 -p ${cfg.cacheDirectory}
+        ${pkgs.module_init_tools}/sbin/insmod ${openafsPkgs}/lib/openafs/libafs-*.ko || true
+        ${openafsPkgs}/sbin/afsd -confdir ${afsConfig} -cachedir ${cfg.cacheDirectory} ${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} -fakestat -afsdb
+        ${openafsPkgs}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
+      '';
+
+      # Doing this in preStop, because after these commands AFS is basically
+      # stopped, so systemd has nothing to do, just noticing it.  If done in
+      # postStop, then we get a hang + kernel oops, because AFS can't be
+      # stopped simply by sending signals to processes.
+      preStop = ''
+        ${pkgs.utillinux}/bin/umount /afs
+        ${openafsPkgs}/sbin/afsd -shutdown
+        ${pkgs.module_init_tools}/sbin/rmmod libafs
+      '';
+    };
   };
-
 }
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 72e9b6144d4..576e5c9e87a 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -85,7 +85,8 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.samba;
-        example = pkgs.samba4;
+        defaultText = "pkgs.samba";
+        example = literalExample "pkgs.samba4";
         description = ''
           Defines which package should be used for the samba server.
         '';
diff --git a/nixos/modules/services/networking/amuled.nix b/nixos/modules/services/networking/amuled.nix
index 516238fdddf..bc488d0e910 100644
--- a/nixos/modules/services/networking/amuled.nix
+++ b/nixos/modules/services/networking/amuled.nix
@@ -57,22 +57,19 @@ in
         gid = config.ids.gids.amule;
       } ];
 
-    jobs.amuled =
-      { description = "AMule daemon";
-
-        startOn = "ip-up";
-
-        preStart = ''
-            mkdir -p ${cfg.dataDir}
-            chown ${user} ${cfg.dataDir}
-        '';
-
-        exec = ''
-            ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${user} \
-                -c 'HOME="${cfg.dataDir}" ${pkgs.amuleDaemon}/bin/amuled'
-        '';
-      };
-
+    systemd.services.amuled = {
+      description = "AMule daemon";
+      wantedBy = [ "ip-up.target" ];
+
+      preStart = ''
+        mkdir -p ${cfg.dataDir}
+        chown ${user} ${cfg.dataDir}
+      '';
+
+      script = ''
+        ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${user} \
+            -c 'HOME="${cfg.dataDir}" ${pkgs.amuleDaemon}/bin/amuled'
+      '';
+    };
   };
-
 }
diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix
index 34e7470dfc6..b9e0eecf417 100644
--- a/nixos/modules/services/networking/bind.nix
+++ b/nixos/modules/services/networking/bind.nix
@@ -120,7 +120,9 @@ in
       };
 
       configFile = mkOption {
+        type = types.path;
         default = confFile;
+        defaultText = "confFile";
         description = "
           Overridable config file to use for named. By default, that
           generated by nixos.
@@ -142,20 +144,17 @@ in
         description = "BIND daemon user";
       };
 
-    jobs.bind =
-      { description = "BIND name server job";
+    systemd.services.bind = {
+      description = "BIND name server job";
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
 
-        startOn = "started network-interfaces";
-
-        preStart =
-          ''
-            ${pkgs.coreutils}/bin/mkdir -p /var/run/named
-            chown ${bindUser} /var/run/named
-          '';
-
-        exec = "${pkgs.bind}/sbin/named -u ${bindUser} ${optionalString cfg.ipv4Only "-4"} -c ${cfg.configFile} -f";
-      };
+      preStart = ''
+        ${pkgs.coreutils}/bin/mkdir -p /var/run/named
+        chown ${bindUser} /var/run/named
+      '';
 
+      script = "${pkgs.bind}/sbin/named -u ${bindUser} ${optionalString cfg.ipv4Only "-4"} -c ${cfg.configFile} -f";
+    };
   };
-
 }
diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix
index bd7a5bcebe6..572a7387316 100644
--- a/nixos/modules/services/networking/btsync.nix
+++ b/nixos/modules/services/networking/btsync.nix
@@ -16,9 +16,10 @@ let
     ''
       "webui":
       {
-        ${optionalEmptyStr cfg.httpLogin "\"login\":    \"${cfg.httpLogin}\","}
-        ${optionalEmptyStr cfg.httpPass  "\"password\": \"${cfg.httpPass}\","}
-        ${optionalEmptyStr cfg.apiKey    "\"api_key\":  \"${cfg.apiKey}\","}
+        ${optionalEmptyStr cfg.httpLogin     "\"login\":          \"${cfg.httpLogin}\","}
+        ${optionalEmptyStr cfg.httpPass      "\"password\":       \"${cfg.httpPass}\","}
+        ${optionalEmptyStr cfg.apiKey        "\"api_key\":        \"${cfg.apiKey}\","}
+        ${optionalEmptyStr cfg.directoryRoot "\"directory_root\": \"${cfg.directoryRoot}\","}
         "listen": "${listenAddr}"
       }
     '';
@@ -82,15 +83,13 @@ in
         type = types.bool;
         default = false;
         description = ''
-          If enabled, start the Bittorrent Sync daemon. Once enabled,
-          you can interact with the service through the Web UI, or
-          configure it in your NixOS configuration. Enabling the
-          <literal>btsync</literal> service also installs a
-          multi-instance systemd unit which can be used to start
-          user-specific copies of the daemon. Once installed, you can
-          use <literal>systemctl start btsync@user</literal> to start
-          the daemon only for user <literal>user</literal>, using the
-          configuration file located at
+          If enabled, start the Bittorrent Sync daemon. Once enabled, you can
+          interact with the service through the Web UI, or configure it in your
+          NixOS configuration. Enabling the <literal>btsync</literal> service
+          also installs a systemd user unit which can be used to start
+          user-specific copies of the daemon. Once installed, you can use
+          <literal>systemctl --user start btsync</literal> as your user to start
+          the daemon using the configuration file located at
           <literal>$HOME/.config/btsync.conf</literal>.
         '';
       };
@@ -211,7 +210,9 @@ in
         default = "/var/lib/btsync/";
         example = "/var/lib/btsync/";
         description = ''
-          Where to store the bittorrent sync files.
+          Where BitTorrent Sync will store it's database files (containing
+          things like username info and licenses). Generally, you should not
+          need to ever change this.
         '';
       };
 
@@ -221,6 +222,13 @@ in
         description = "API key, which enables the developer API.";
       };
 
+      directoryRoot = mkOption {
+        type = types.str;
+        default = "";
+        example = "/media";
+        description = "Default directory to add folders in the web UI.";
+      };
+
       sharedFolders = mkOption {
         default = [];
         example =
@@ -303,12 +311,11 @@ in
       };
     };
 
-    systemd.services."btsync@" = with pkgs; {
-      description = "Bittorrent Sync Service for %i";
+    systemd.user.services.btsync = with pkgs; {
+      description = "Bittorrent Sync user service";
       after       = [ "network.target" "local-fs.target" ];
       serviceConfig = {
         Restart   = "on-abort";
-        User      = "%i";
         ExecStart =
           "${bittorrentSync}/bin/btsync --nodaemon --config %h/.config/btsync.conf";
       };
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index 66838735c4d..58dad56014b 100644
--- a/nixos/modules/services/networking/consul.nix
+++ b/nixos/modules/services/networking/consul.nix
@@ -7,7 +7,7 @@ let
   cfg = config.services.consul;
 
   configOptions = { data_dir = dataDir; } //
-    (if cfg.webUi then { ui_dir = "${pkgs.consul.ui}"; } else { }) //
+    (if cfg.webUi then { ui_dir = "${cfg.package.ui}"; } else { }) //
     cfg.extraConfig;
 
   configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ]
@@ -30,6 +30,15 @@ in
         '';
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.consul;
+        description = ''
+          The package used for the Consul agent and CLI.
+        '';
+      };
+
+
       webUi = mkOption {
         type = types.bool;
         default = false;
@@ -109,6 +118,7 @@ in
         package = mkOption {
           description = "Package to use for consul-alerts.";
           default = pkgs.consul-alerts;
+          defaultText = "pkgs.consul-alerts";
           type = types.package;
         };
 
@@ -155,7 +165,7 @@ in
         etc."consul.json".text = builtins.toJSON configOptions;
         # We need consul.d to exist for consul to start
         etc."consul.d/dummy.json".text = "{ }";
-        systemPackages = with pkgs; [ consul ];
+        systemPackages = [ cfg.package ];
       };
 
       systemd.services.consul = {
@@ -167,14 +177,14 @@ in
             (filterAttrs (n: _: hasPrefix "consul.d/" n) config.environment.etc);
 
         serviceConfig = {
-          ExecStart = "@${pkgs.consul}/bin/consul consul agent -config-dir /etc/consul.d"
+          ExecStart = "@${cfg.package}/bin/consul consul agent -config-dir /etc/consul.d"
             + concatMapStrings (n: " -config-file ${n}") configFiles;
-          ExecReload = "${pkgs.consul}/bin/consul reload";
+          ExecReload = "${cfg.package}/bin/consul reload";
           PermissionsStartOnly = true;
           User = if cfg.dropPrivileges then "consul" else null;
           TimeoutStartSec = "0";
         } // (optionalAttrs (cfg.leaveOnStop) {
-          ExecStop = "${pkgs.consul}/bin/consul leave";
+          ExecStop = "${cfg.package}/bin/consul leave";
         });
 
         path = with pkgs; [ iproute gnugrep gawk consul ];
@@ -221,7 +231,7 @@ in
         wantedBy = [ "multi-user.target" ];
         after = [ "consul.service" ];
 
-        path = [ pkgs.consul ];
+        path = [ cfg.package ];
 
         serviceConfig = {
           ExecStart = ''
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index 6907d63d761..fcf5aa5f175 100644
--- a/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixos/modules/services/networking/dnsmasq.nix
@@ -5,8 +5,10 @@ with lib;
 let
   cfg = config.services.dnsmasq;
   dnsmasq = pkgs.dnsmasq;
+  stateDir = "/var/lib/dnsmasq";
 
   dnsmasqConf = pkgs.writeText "dnsmasq.conf" ''
+    dhcp-leasefile=${stateDir}/dnsmasq.leases
     ${optionalString cfg.resolveLocalQueries ''
       conf-file=/etc/dnsmasq-conf.conf
       resolv-file=/etc/dnsmasq-resolv.conf
@@ -76,12 +78,11 @@ in
 
     services.dbus.packages = [ dnsmasq ];
 
-    users.extraUsers = singleton
-      { name = "dnsmasq";
-        uid = config.ids.uids.dnsmasq;
-        description = "Dnsmasq daemon user";
-        home = "/var/empty";
-      };
+    users.extraUsers = singleton {
+      name = "dnsmasq";
+      uid = config.ids.uids.dnsmasq;
+      description = "Dnsmasq daemon user";
+    };
 
     systemd.services.dnsmasq = {
         description = "Dnsmasq Daemon";
@@ -89,6 +90,9 @@ in
         wantedBy = [ "multi-user.target" ];
         path = [ dnsmasq ];
         preStart = ''
+          mkdir -m 755 -p ${stateDir}
+          touch ${stateDir}/dnsmasq.leases
+          chown -R dnsmasq ${stateDir}
           touch /etc/dnsmasq-{conf,resolv}.conf
           dnsmasq --test
         '';
diff --git a/nixos/modules/services/networking/ejabberd.nix b/nixos/modules/services/networking/ejabberd.nix
index 28b8e234a5c..7af11f37a43 100644
--- a/nixos/modules/services/networking/ejabberd.nix
+++ b/nixos/modules/services/networking/ejabberd.nix
@@ -6,9 +6,16 @@ let
 
   cfg = config.services.ejabberd;
 
-in
+  ctlcfg = pkgs.writeText "ejabberdctl.cfg" ''
+    ERL_EPMD_ADDRESS=127.0.0.1
+    ${cfg.ctlConfig}
+  '';
 
-{
+  ectl = ''${cfg.package}/bin/ejabberdctl ${if cfg.configFile == null then "" else "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"'';
+
+  dumps = lib.concatMapStringsSep " " lib.escapeShellArg cfg.loadDumps;
+
+in {
 
   ###### interface
 
@@ -17,33 +24,57 @@ in
     services.ejabberd = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = "Whether to enable ejabberd server";
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.ejabberd;
+        description = "ejabberd server package to use";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "ejabberd";
+        description = "User under which ejabberd is ran";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "ejabberd";
+        description = "Group under which ejabberd is ran";
+      };
+
       spoolDir = mkOption {
+        type = types.path;
         default = "/var/lib/ejabberd";
         description = "Location of the spooldir of ejabberd";
       };
 
       logsDir = mkOption {
+        type = types.path;
         default = "/var/log/ejabberd";
         description = "Location of the logfile directory of ejabberd";
       };
 
-      confDir = mkOption {
-        default = "/var/ejabberd";
-        description = "Location of the config directory of ejabberd";
+      configFile = mkOption {
+        type = types.nullOr types.path;
+        description = "Configuration file for ejabberd in YAML format";
+        default = null;
       };
 
-      virtualHosts = mkOption {
-        default = "\"localhost\"";
-        description = "Virtualhosts that ejabberd should host. Hostnames are surrounded with doublequotes and separated by commas";
+      ctlConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Configuration of ejabberdctl";
       };
 
       loadDumps = mkOption {
+        type = types.listOf types.path;
         default = [];
-        description = "Configuration dump that should be loaded on the first startup";
+        description = "Configuration dumps that should be loaded on the first startup";
         example = literalExample "[ ./myejabberd.dump ]";
       };
     };
@@ -54,84 +85,75 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.ejabberd ];
-
-    jobs.ejabberd =
-      { description = "EJabberd server";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        environment = {
-          PATH = "$PATH:${pkgs.ejabberd}/sbin:${pkgs.ejabberd}/bin:${pkgs.coreutils}/bin:${pkgs.bash}/bin:${pkgs.gnused}/bin";
-        };
-
-        preStart =
-          ''
-            PATH="$PATH:${pkgs.ejabberd}/sbin:${pkgs.ejabberd}/bin:${pkgs.coreutils}/bin:${pkgs.bash}/bin:${pkgs.gnused}/bin";
-	    
-            # Initialise state data
-            mkdir -p ${cfg.logsDir}
-
-            if ! test -d ${cfg.spoolDir}
-            then
-                initialize=1
-                cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
-            fi
-
-            if ! test -d ${cfg.confDir}
-            then
-                mkdir -p ${cfg.confDir}
-                cp ${pkgs.ejabberd}/etc/ejabberd/* ${cfg.confDir}
-                sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
-            fi
-
-            ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} start
-
-            ${if cfg.loadDumps == [] then "" else
-              ''
-                if [ "$initialize" = "1" ]
-                then
-                    # Wait until the ejabberd server is available for use
-                    count=0
-                    while ! ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} status
-                    do
-                        if [ $count -eq 30 ]
-                        then
-                            echo "Tried 30 times, giving up..."
-                            exit 1
-                        fi
-
-                        echo "Ejabberd daemon not yet started. Waiting for 1 second..."
-                        count=$((count++))
-                        sleep 1
-                    done
-
-                    ${concatMapStrings (dump:
-                      ''
-                        echo "Importing dump: ${dump}"
-
-                        if [ -f ${dump} ]
-                        then
-                            ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} load ${dump}
-                        elif [ -d ${dump} ]
-                        then
-                            for i in ${dump}/ejabberd-dump/*
-                            do
-                                ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} load $i
-                            done
-                        fi
-                      '') cfg.loadDumps}
-                fi
-              ''}
-          '';
-
-        postStop =
-          ''
-            ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} stop
-          '';
+    environment.systemPackages = [ cfg.package ];
+
+    users.extraUsers = optionalAttrs (cfg.user == "ejabberd") (singleton
+      { name = "ejabberd";
+        group = cfg.group;
+        home = cfg.spoolDir;
+        createHome = true;
+        uid = config.ids.uids.ejabberd;
+      });
+
+    users.extraGroups = optionalAttrs (cfg.group == "ejabberd") (singleton
+      { name = "ejabberd";
+        gid = config.ids.gids.ejabberd;
+      });
+
+    systemd.services.ejabberd = {
+      description = "ejabberd server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      path = [ pkgs.findutils pkgs.coreutils ];
+
+      serviceConfig = {
+        Type = "forking";
+        # FIXME: runit is used for `chpst` -- can we get rid of this?
+        ExecStop = ''${pkgs.runit}/bin/chpst -u "${cfg.user}:${cfg.group}" ${ectl} stop'';
+        ExecReload = ''${pkgs.runit}/bin/chpst -u "${cfg.user}:${cfg.group}" ${ectl} reload_config'';
+        User = cfg.user;
+        Group = cfg.group;
+        PermissionsStartOnly = true;
       };
 
+      preStart = ''
+        mkdir -p -m750 "${cfg.logsDir}"
+        chown "${cfg.user}:${cfg.group}" "${cfg.logsDir}"
+
+        mkdir -p -m750 "/var/lock/ejabberdctl"
+        chown "${cfg.user}:${cfg.group}" "/var/lock/ejabberdctl"
+
+        mkdir -p -m750 "${cfg.spoolDir}"
+        chown -R "${cfg.user}:${cfg.group}" "${cfg.spoolDir}"
+      '';
+
+      script = ''
+        [ -z "$(ls -A '${cfg.spoolDir}')" ] && firstRun=1
+
+        ${ectl} start
+
+        count=0
+        while ! ${ectl} status >/dev/null 2>&1; do
+          if [ $count -eq 30 ]; then
+            echo "ejabberd server hasn't started in 30 seconds, giving up"
+            exit 1
+          fi
+
+          count=$((count++))
+          sleep 1
+        done
+
+        if [ -n "$firstRun" ]; then
+          for src in ${dumps}; do
+            find "$src" -type f | while read dump; do
+              echo "Loading configuration dump at $dump"
+              ${ectl} load "$dump"
+            done
+          done
+        fi
+      '';
+    };
+
     security.pam.services.ejabberd = {};
 
   };
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index a61f0250ef8..e11fe072be6 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -421,8 +421,9 @@ in
     };
 
     networking.firewall.extraPackages = mkOption {
+      type = types.listOf types.package;
       default = [ ];
-      example = [ pkgs.ipset ];
+      example = literalExample "[ pkgs.ipset ]";
       description =
         ''
           Additional packages to be included in the environment of the system
diff --git a/nixos/modules/services/networking/gale.nix b/nixos/modules/services/networking/gale.nix
new file mode 100644
index 00000000000..3a5d9bd63c7
--- /dev/null
+++ b/nixos/modules/services/networking/gale.nix
@@ -0,0 +1,182 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.gale;
+  # we convert the path to a string to avoid it being copied to the nix store,
+  # otherwise users could read the private key as all files in the store are
+  # world-readable
+  keyPath = toString cfg.keyPath;
+  # ...but we refer to the pubkey file using a path so that we can ensure the
+  # config gets rebuilt if the public key changes (we can assume the private key
+  # will never change without the public key having changed)
+  gpubFile = cfg.keyPath + "/${cfg.domain}.gpub";
+  home = "/var/lib/gale";
+  keysPrepared = cfg.keyPath != null && lib.pathExists cfg.keyPath;
+in
+{
+  options = {
+    services.gale = {
+      enable = mkEnableOption "the Gale messaging daemon";
+
+      user = mkOption {
+        default = "gale";
+        type = types.str;
+        description = "Username for the Gale daemon.";
+      };
+
+      group = mkOption {
+        default = "gale";
+        type = types.str;
+        description = "Group name for the Gale daemon.";
+      };
+
+      setuidWrapper = mkOption {
+        default = null;
+        description = "Configuration for the Gale gksign setuid wrapper.";
+      };
+
+      domain = mkOption {
+        default = "";
+        type = types.str;
+        description = "Domain name for the Gale system.";
+      };
+
+      keyPath = mkOption {
+        default = null;
+        type = types.nullOr types.path;
+        description = ''
+          Directory containing the key pair for this Gale domain.  The expected
+          filename will be taken from the domain option with ".gpri" and ".gpub"
+          appended.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Additional text to be added to <filename>/etc/gale/conf</filename>.
+        '';
+      };
+    };
+  };
+
+  config = mkMerge [
+    (mkIf cfg.enable {
+       assertions = [{
+         assertion = cfg.domain != "";
+         message = "A domain must be set for Gale.";
+       }];
+
+       warnings = mkIf (!keysPrepared) [
+         "You must run gale-install in order to generate a domain key."
+       ];
+
+       system.activationScripts.gale = mkIf cfg.enable (
+         stringAfter [ "users" "groups" ] ''
+           chmod -R 755 ${home}
+           mkdir -m 0777 -p ${home}/auth/cache
+           mkdir -m 1777 -p ${home}/auth/local # GALE_DOMAIN.gpub
+           mkdir -m 0700 -p ${home}/auth/private # ROOT.gpub
+           mkdir -m 0755 -p ${home}/auth/trusted # ROOT
+           mkdir -m 0700 -p ${home}/.gale
+           mkdir -m 0700 -p ${home}/.gale/auth
+           mkdir -m 0700 -p ${home}/.gale/auth/private # GALE_DOMAIN.gpri
+
+           ln -sf ${pkgs.gale}/etc/gale/auth/trusted/ROOT "${home}/auth/trusted/ROOT"
+           chown -R ${cfg.user}:${cfg.group} ${home}
+         ''
+       );
+
+       environment = {
+         etc = {
+           "gale/auth".source = home + "/auth"; # symlink /var/lib/gale/auth
+           "gale/conf".text = ''
+             GALE_USER ${cfg.user}
+             GALE_DOMAIN ${cfg.domain}
+             ${cfg.extraConfig}
+           '';
+         };
+
+         systemPackages = [ pkgs.gale ];
+       };
+
+       users.extraUsers = [{
+         name = cfg.user;
+         description = "Gale daemon";
+         uid = config.ids.uids.gale;
+         group = cfg.group;
+         home = home;
+         createHome = true;
+       }];
+
+       users.extraGroups = [{
+         name = cfg.group;
+         gid = config.ids.gids.gale;
+       }];
+    })
+    (mkIf (cfg.enable && keysPrepared) {
+       assertions = [
+         {
+           assertion = cfg.keyPath != null
+                    && lib.pathExists (cfg.keyPath + "/${cfg.domain}.gpub");
+           message = "Couldn't find a Gale public key for ${cfg.domain}.";
+         }
+         {
+           assertion = cfg.keyPath != null
+                    && lib.pathExists (cfg.keyPath + "/${cfg.domain}.gpri");
+           message = "Couldn't find a Gale private key for ${cfg.domain}.";
+         }
+       ];
+
+       services.gale.setuidWrapper = {
+         program = "gksign";
+         source = "${pkgs.gale}/bin/gksign";
+         owner = cfg.user;
+         group = cfg.group;
+         setuid = true;
+         setgid = false;
+       };
+
+       security.setuidOwners = [ cfg.setuidWrapper ];
+
+       systemd.services.gale-galed = {
+         description = "Gale messaging daemon";
+         wantedBy = [ "multi-user.target" ];
+         wants = [ "gale-gdomain.service" ];
+         after = [ "network.target" ];
+
+         preStart = ''
+           install -m 0640 ${keyPath}/${cfg.domain}.gpri "${home}/.gale/auth/private/"
+           install -m 0644 ${gpubFile} "${home}/.gale/auth/private/${cfg.domain}.gpub"
+           install -m 0644 ${gpubFile} "${home}/auth/local/${cfg.domain}.gpub"
+           chown -R ${cfg.user}:${cfg.group} ${home}
+         '';
+
+         serviceConfig = {
+           Type = "forking";
+           ExecStart = "@${pkgs.gale}/bin/galed galed";
+           User = cfg.user;
+           Group = cfg.group;
+           PermissionsStartOnly = true;
+         };
+       };
+
+       systemd.services.gale-gdomain = {
+         description = "Gale AKD daemon";
+         wantedBy = [ "multi-user.target" ];
+         requires = [ "gale-galed.service" ];
+         after = [ "gale-galed.service" ];
+
+         serviceConfig = {
+           Type = "forking";
+           ExecStart = "@${pkgs.gale}/bin/gdomain gdomain";
+           User = cfg.user;
+           Group = cfg.group;
+         };
+       };
+    })
+  ];
+}
diff --git a/nixos/modules/services/networking/git-daemon.nix b/nixos/modules/services/networking/git-daemon.nix
index 566936a7d0f..215ffe48a56 100644
--- a/nixos/modules/services/networking/git-daemon.nix
+++ b/nixos/modules/services/networking/git-daemon.nix
@@ -16,7 +16,7 @@ in
         type = types.bool;
         default = false;
         description = ''
-          Enable Git daemon, which allows public hosting  of git repositories
+          Enable Git daemon, which allows public hosting of git repositories
           without any access controls. This is mostly intended for read-only access.
 
           You can allow write access by setting daemon.receivepack configuration
@@ -115,10 +115,9 @@ in
         gid = config.ids.gids.git;
       };
 
-    jobs.gitDaemon = {
-      name = "git-daemon";
-      startOn = "ip-up";
-      exec = "${pkgs.git}/bin/git daemon --reuseaddr "
+    systemd.services."git-daemon" = {
+      wantedBy = [ "ip-up.target" ];
+      script = "${pkgs.git}/bin/git daemon --reuseaddr "
         + (optionalString (cfg.basePath != "") "--base-path=${cfg.basePath} ")
         + (optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ")
         + "--port=${toString cfg.port} --user=${cfg.user} --group=${cfg.group} ${cfg.options} "
diff --git a/nixos/modules/services/networking/gvpe.nix b/nixos/modules/services/networking/gvpe.nix
index c633ffedef4..27b64b5bb95 100644
--- a/nixos/modules/services/networking/gvpe.nix
+++ b/nixos/modules/services/networking/gvpe.nix
@@ -37,13 +37,6 @@ let
     '';
     executable = true;
   });
-
-  exec = "${pkgs.gvpe}/sbin/gvpe -c /var/gvpe -D ${cfg.nodename} "
-    + " ${cfg.nodename}.pid-file=/var/gvpe/gvpe.pid"
-    + " ${cfg.nodename}.if-up=if-up"
-    + " &> /var/log/gvpe";
-
-  inherit (cfg) startOn stopOn;
 in
 
 {
@@ -55,18 +48,6 @@ in
           Whether to run gvpe
         '';
       };
-      startOn = mkOption {
-        default = "started network-interfaces";
-        description = ''
-          Condition to start GVPE
-        '';
-      };
-      stopOn = mkOption {
-        default = "stopping network-interfaces";
-        description = ''
-          Condition to stop GVPE
-        '';
-      };
       nodename = mkOption {
         default = null;
         description =''
@@ -122,10 +103,10 @@ in
     };
   };
   config = mkIf cfg.enable {
-    jobs.gvpe = {
+    systemd.services.gvpe = {
       description = "GNU Virtual Private Ethernet node";
-
-      inherit startOn stopOn;
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
 
       preStart = ''
         mkdir -p /var/gvpe
@@ -136,9 +117,12 @@ in
         cp ${ifupScript} /var/gvpe/if-up
       '';
 
-      inherit exec;
+      script = "${pkgs.gvpe}/sbin/gvpe -c /var/gvpe -D ${cfg.nodename} "
+        + " ${cfg.nodename}.pid-file=/var/gvpe/gvpe.pid"
+        + " ${cfg.nodename}.if-up=if-up"
+        + " &> /var/log/gvpe";
 
-      respawn = true;
+      serviceConfig.Restart = "always";
     };
   };
 }
diff --git a/nixos/modules/services/networking/ifplugd.nix b/nixos/modules/services/networking/ifplugd.nix
index 20bfca8f872..00b94fe2284 100644
--- a/nixos/modules/services/networking/ifplugd.nix
+++ b/nixos/modules/services/networking/ifplugd.nix
@@ -66,23 +66,17 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
-
-    jobs.ifplugd =
-      { description = "Network interface connectivity monitor";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        exec =
-          ''
-            ${ifplugd}/sbin/ifplugd --no-daemon --no-startup --no-shutdown \
-              ${if config.networking.interfaceMonitor.beep then "" else "--no-beep"} \
-              --run ${plugScript}
-          '';
-      };
+    systemd.services.ifplugd = {
+      description = "Network interface connectivity monitor";
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      script = ''
+        ${ifplugd}/sbin/ifplugd --no-daemon --no-startup --no-shutdown \
+          ${if config.networking.interfaceMonitor.beep then "" else "--no-beep"} \
+          --run ${plugScript}
+      '';
+    };
 
     environment.systemPackages = [ ifplugd ];
-
   };
-
 }
diff --git a/nixos/modules/services/networking/ircd-hybrid/default.nix b/nixos/modules/services/networking/ircd-hybrid/default.nix
index 2c397f94d23..ede57c5046d 100644
--- a/nixos/modules/services/networking/ircd-hybrid/default.nix
+++ b/nixos/modules/services/networking/ircd-hybrid/default.nix
@@ -121,17 +121,11 @@ in
 
     users.extraGroups.ircd.gid = config.ids.gids.ircd;
 
-    jobs.ircd_hybrid =
-      { name = "ircd-hybrid";
-
-        description = "IRCD Hybrid server";
-
-        startOn = "started networking";
-        stopOn = "stopping networking";
-
-        exec = "${ircdService}/bin/control start";
-      };
-
+    systemd.services."ircd-hybrid" = {
+      description = "IRCD Hybrid server";
+      after = [ "started networking" ];
+      wantedBy = [ "multi-user.target" ];
+      script = "${ircdService}/bin/control start";
+    };
   };
-
 }
diff --git a/nixos/modules/services/networking/lambdabot.nix b/nixos/modules/services/networking/lambdabot.nix
index 4ef7c7c9ab6..5a61a9f9678 100644
--- a/nixos/modules/services/networking/lambdabot.nix
+++ b/nixos/modules/services/networking/lambdabot.nix
@@ -27,6 +27,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.lambdabot;
+        defaultText = "pkgs.lambdabot";
         description = "Used lambdabot package";
       };
 
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 8ab4cfcc114..01c05fb4a24 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -110,7 +110,7 @@ in {
 
       # Ugly hack for using the correct gnome3 packageSet
       basePackages = mkOption {
-        type = types.attrsOf types.path;
+        type = types.attrsOf types.package;
         default = { inherit networkmanager modemmanager wpa_supplicant
                             networkmanager_openvpn networkmanager_vpnc
                             networkmanager_openconnect
diff --git a/nixos/modules/services/networking/ngircd.nix b/nixos/modules/services/networking/ngircd.nix
index 49e5f355980..6a5290ffdee 100644
--- a/nixos/modules/services/networking/ngircd.nix
+++ b/nixos/modules/services/networking/ngircd.nix
@@ -34,6 +34,7 @@ in {
         type = types.package;
 
         default = pkgs.ngircd;
+        defaultText = "pkgs.ngircd";
       };
     };
   };
diff --git a/nixos/modules/services/networking/notbit.nix b/nixos/modules/services/networking/notbit.nix
deleted file mode 100644
index a96e181cb80..00000000000
--- a/nixos/modules/services/networking/notbit.nix
+++ /dev/null
@@ -1,130 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-let
-  cfg = config.services.notbit;
-  varDir = "/var/lib/notbit";
-  
-  sendmail = pkgs.stdenv.mkDerivation {
-    name = "notbit-wrapper";
-    buildInputs = [ pkgs.makeWrapper ];
-    propagatedBuildInputs = [ pkgs.notbit ];
-    buildCommand = ''
-      mkdir -p $out/bin
-      makeWrapper ${pkgs.notbit}/bin/notbit-sendmail $out/bin/notbit-system-sendmail \
-        --set XDG_RUNTIME_DIR ${varDir}
-    '';
-  };
-  opts = "${optionalString cfg.allowPrivateAddresses "-L"} ${optionalString cfg.noBootstrap "-b"} ${optionalString cfg.specifiedPeersOnly "-e"}";
-  peers = concatStringsSep " " (map (str: "-P \"${str}\"") cfg.peers);
-  listen = if cfg.listenAddress == [] then "-p ${toString cfg.port}" else
-    concatStringsSep " " (map (addr: "-a \"${addr}:${toString cfg.port}\"") cfg.listenAddress);
-in
-
-with lib;
-{
-
-  ### configuration
-
-  options = {
-
-    services.notbit = {
-
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enables the notbit daemon and provides a sendmail binary named `notbit-system-sendmail` for sending mail over the system instance of notbit. Users must be in the notbit group in order to send mail over the system notbit instance. Currently mail recipt is not supported.
-        '';
-      };
-
-      port = mkOption {
-        type = types.int;
-        default = 8444;
-        description = "The port which the daemon listens for other bitmessage clients";
-      };
-
-      nice = mkOption {
-        type = types.int;
-        default = 10;
-        description = "Set the nice level for the notbit daemon";
-      };
-
-      listenAddress = mkOption {
-        type = types.listOf types.str;
-        default = [ ];
-        example = [ "localhost" "myhostname" ];
-        description = "The addresses which notbit will use to listen for incoming connections. These addresses are advertised to connecting clients.";
-      };
-
-      peers = mkOption {
-        type = types.listOf types.str;
-        default = [ ];
-        example = [ "bitmessage.org:8877" ];
-        description = "The initial set of peers notbit will connect to.";
-      };
-
-      specifiedPeersOnly = mkOption {
-        type = types.bool;
-        default = false;
-        description = "If true, notbit will only connect to peers specified by the peers option.";
-      };
-
-      allowPrivateAddresses = mkOption {
-        type = types.bool;
-        default = false;
-        description = "If true, notbit will allow connections to to RFC 1918 addresses.";
-      };
-
-      noBootstrap = mkOption {
-        type = types.bool;
-        default = false;
-        description = "If true, notbit will not bootstrap an initial peerlist from bitmessage.org servers";
-      };
-
-    };
-
-  };
-
-  ### implementation
-
-  config = mkIf cfg.enable {
-
-    environment.systemPackages = [ sendmail ];
-
-    systemd.services.notbit = {
-      description = "Notbit daemon";
-      after = [ "network.target" ];
-      wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.notbit ];
-      environment = { XDG_RUNTIME_DIR = varDir; };
-
-      postStart = ''
-        [ ! -f "${varDir}/addr" ] && notbit-keygen > ${varDir}/addr
-        chmod 0640 ${varDir}/{addr,notbit/notbit-ipc.lock}
-        chmod 0750 ${varDir}/notbit/{,notbit-ipc}
-      '';
-
-      serviceConfig = {
-        Type = "forking";
-        ExecStart = "${pkgs.notbit}/bin/notbit -d ${listen} ${peers} ${opts}";
-        User = "notbit";
-        Group = "notbit";
-        UMask = "0077";
-        WorkingDirectory = varDir;
-        Nice = cfg.nice;
-      };
-    };
-
-    users.extraUsers.notbit = {
-      group = "notbit";
-      description = "Notbit daemon user";
-      home = varDir;
-      createHome = true;
-      uid = config.ids.uids.notbit;
-    };
-
-    users.extraGroups.notbit.gid = config.ids.gids.notbit;
-  };
-
-}
diff --git a/nixos/modules/services/networking/oidentd.nix b/nixos/modules/services/networking/oidentd.nix
index 738ab8313a5..651bb8e967c 100644
--- a/nixos/modules/services/networking/oidentd.nix
+++ b/nixos/modules/services/networking/oidentd.nix
@@ -20,18 +20,17 @@ with lib;
 
   };
 
-  
+
   ###### implementation
 
   config = mkIf config.services.oidentd.enable {
-
-    jobs.oidentd =
-      { startOn = "started network-interfaces";
-        daemonType = "fork";
-        exec = "${pkgs.oidentd}/sbin/oidentd -u oidentd -g nogroup" +
-          optionalString config.networking.enableIPv6 " -a ::"
-        ;
-      };
+    systemd.services.oidentd = {
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig.Type = "forking";
+      script = "${pkgs.oidentd}/sbin/oidentd -u oidentd -g nogroup" +
+          optionalString config.networking.enableIPv6 " -a ::";
+    };
 
     users.extraUsers.oidentd = {
       description = "Ident Protocol daemon user";
diff --git a/nixos/modules/services/networking/openfire.nix b/nixos/modules/services/networking/openfire.nix
index c3b4ba90b4e..ed91b45ec94 100644
--- a/nixos/modules/services/networking/openfire.nix
+++ b/nixos/modules/services/networking/openfire.nix
@@ -2,17 +2,7 @@
 
 with lib;
 
-let
-
-  inherit (pkgs) jre openfire coreutils which gnugrep gawk gnused;
-
-  extraStartDependency =
-    if config.services.openfire.usePostgreSQL then "and started postgresql" else "";
-
-in
-
 {
-
   ###### interface
 
   options = {
@@ -47,26 +37,24 @@ in
         message = "OpenFire assertion failed.";
       };
 
-    jobs.openfire =
-      { description = "OpenFire XMPP server";
-
-        startOn = "started networking ${extraStartDependency}";
-
-        script =
-          ''
-            export PATH=${jre}/bin:${openfire}/bin:${coreutils}/bin:${which}/bin:${gnugrep}/bin:${gawk}/bin:${gnused}/bin
-            export HOME=/tmp
-            mkdir /var/log/openfire || true
-            mkdir /etc/openfire || true
-            for i in ${openfire}/conf.inst/*; do
-                if ! test -f /etc/openfire/$(basename $i); then
-                    cp $i /etc/openfire/
-                fi
-            done
-            openfire start
-          ''; # */
-      };
-
+    systemd.services.openfire = {
+      description = "OpenFire XMPP server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "networking.target" ] ++
+        optional config.services.openfire.usePostgreSQL "postgresql.service";
+      path = with pkgs; [ jre openfire coreutils which gnugrep gawk gnused ];
+      script = ''
+        export HOME=/tmp
+        mkdir /var/log/openfire || true
+        mkdir /etc/openfire || true
+        for i in ${openfire}/conf.inst/*; do
+            if ! test -f /etc/openfire/$(basename $i); then
+                cp $i /etc/openfire/
+            fi
+        done
+        openfire start
+      ''; # */
+    };
   };
 
 }
diff --git a/nixos/modules/services/networking/ostinato.nix b/nixos/modules/services/networking/ostinato.nix
new file mode 100644
index 00000000000..13f784dc53c
--- /dev/null
+++ b/nixos/modules/services/networking/ostinato.nix
@@ -0,0 +1,104 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  pkg = pkgs.ostinato;
+  cfg = config.services.ostinato;
+  configFile = pkgs.writeText "drone.ini" ''
+    [General]
+    RateAccuracy=${cfg.rateAccuracy}
+
+    [RpcServer]
+    Address=${cfg.rpcServer.address}
+
+    [PortList]
+    Include=${concatStringsSep "," cfg.portList.include}
+    Exclude=${concatStringsSep "," cfg.portList.exclude}
+  '';
+
+in
+{
+
+  ###### interface
+
+  options = {
+
+    services.ostinato = {
+
+      enable = mkEnableOption "Ostinato agent-controller (Drone)";
+
+      port = mkOption {
+        type = types.int;
+        default = 7878;
+        description = ''
+          Port to listen on.
+        '';
+      };
+
+      rateAccuracy = mkOption {
+        type = types.enum [ "High" "Low" ];
+        default = "High";
+        description = ''
+          To ensure that the actual transmit rate is as close as possible to
+          the configured transmit rate, Drone runs a busy-wait loop.
+          While this provides the maximum accuracy possible, the CPU
+          utilization is 100% while the transmit is on. You can however,
+          sacrifice the accuracy to reduce the CPU load.
+        '';
+      };
+
+      rpcServer = {
+        address = mkOption {
+          type = types.string;
+          default = "0.0.0.0";
+          description = ''
+            By default, the Drone RPC server will listen on all interfaces and
+            local IPv4 adresses for incoming connections from clients.  Specify
+            a single IPv4 or IPv6 address if you want to restrict that.
+            To listen on any IPv6 address, use ::
+          '';
+        };
+      };
+
+      portList = {
+        include = mkOption {
+          type = types.listOf types.string;
+          default = [];
+          example = ''[ "eth*" "lo*" ]'';
+          description = ''
+            For a port to pass the filter and appear on the port list managed
+            by drone, it be allowed by this include list.
+          '';
+        };
+        exclude = mkOption {
+          type = types.listOf types.str;
+          default = [];
+          example = ''[ "usbmon*" "eth0" ]'';
+          description = ''
+            A list of ports does not appear on the port list managed by drone.
+          '';
+        };
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkg ];
+
+    systemd.services.drone = {
+      description = "Ostinato agent-controller";
+      wantedBy = [ "multi-user.target" ];
+      script = ''
+        ${pkg}/bin/drone ${toString cfg.port} ${configFile}
+      '';
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/prayer.nix b/nixos/modules/services/networking/prayer.nix
index ad0fb0af01c..cb8fe6bf4fe 100644
--- a/nixos/modules/services/networking/prayer.nix
+++ b/nixos/modules/services/networking/prayer.nix
@@ -83,21 +83,14 @@ in
         gid = config.ids.gids.prayer;
       };
 
-    jobs.prayer =
-      { name = "prayer";
-
-        startOn = "startup";
-
-        preStart =
-          ''
-            mkdir -m 0755 -p ${stateDir}
-            chown ${prayerUser}.${prayerGroup} ${stateDir}
-          '';
-
-        daemonType = "daemon";
-
-        exec = "${prayer}/sbin/prayer --config-file=${prayerCfg}";
-      };
+    systemd.services.prayer = {
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig.Type = "forking";
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+        chown ${prayerUser}.${prayerGroup} ${stateDir}
+      '';
+      script = "${prayer}/sbin/prayer --config-file=${prayerCfg}";
+    };
   };
-
 }
diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix
index fc9afc70aca..4b77ef22ac1 100644
--- a/nixos/modules/services/networking/radicale.nix
+++ b/nixos/modules/services/networking/radicale.nix
@@ -33,16 +33,14 @@ in
   };
 
   config = mkIf cfg.enable {
-
     environment.systemPackages = [ pkgs.pythonPackages.radicale ];
 
-    jobs.radicale = {
+    systemd.services.radicale = {
       description = "A Simple Calendar and Contact Server";
-      startOn = "started network-interfaces";
-      exec = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -d";
-      daemonType = "fork";
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      script = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -d";
+      serviceConfig.Type = "forking";
     };
-
   };
-
 }
diff --git a/nixos/modules/services/networking/shout.nix b/nixos/modules/services/networking/shout.nix
index fe3cba8f149..f069fe7bec9 100644
--- a/nixos/modules/services/networking/shout.nix
+++ b/nixos/modules/services/networking/shout.nix
@@ -19,7 +19,7 @@ in {
       '';
     };
 
-    host = mkOption {
+    listenAddress = mkOption {
       type = types.string;
       default = "0.0.0.0";
       description = "IP interface to listen on for http connections.";
@@ -66,7 +66,7 @@ in {
         "${pkgs.shout}/bin/shout"
         (if cfg.private then "--private" else "--public")
         "--port" (toString cfg.port)
-        "--host" (toString cfg.host)
+        "--host" (toString cfg.listenAddress)
         "--home" shoutHome
       ];
       serviceConfig = {
diff --git a/nixos/modules/services/networking/skydns.nix b/nixos/modules/services/networking/skydns.nix
index f5eb452fec6..39ebaa45a79 100644
--- a/nixos/modules/services/networking/skydns.nix
+++ b/nixos/modules/services/networking/skydns.nix
@@ -56,6 +56,7 @@ in {
 
     package = mkOption {
       default = pkgs.skydns;
+      defaultText = "pkgs.skydns";
       type = types.package;
       description = "Skydns package to use.";
     };
diff --git a/nixos/modules/services/networking/softether.nix b/nixos/modules/services/networking/softether.nix
index 49538af7d35..a421b32f02c 100644
--- a/nixos/modules/services/networking/softether.nix
+++ b/nixos/modules/services/networking/softether.nix
@@ -61,9 +61,10 @@ in
             dataDir = cfg.dataDir;
           }))
         ];
-      jobs.softether = {
+      systemd.services.softether = {
         description = "SoftEther VPN services initial job";
-        startOn = "started network-interfaces";
+        after = [ "network-interfaces.target" ];
+        wantedBy = [ "multi-user.target" ];
         preStart = ''
             for d in vpnserver vpnbridge vpnclient vpncmd; do
                 if ! test -e ${cfg.dataDir}/$d; then
@@ -74,7 +75,6 @@ in
             rm -rf ${cfg.dataDir}/vpncmd/vpncmd
             ln -s ${pkg}${cfg.dataDir}/vpncmd/vpncmd ${cfg.dataDir}/vpncmd/vpncmd
         '';
-        exec = "true";
       };
     }
 
diff --git a/nixos/modules/services/networking/ssh/lshd.nix b/nixos/modules/services/networking/ssh/lshd.nix
index 81e523fd2a5..661a6a52463 100644
--- a/nixos/modules/services/networking/ssh/lshd.nix
+++ b/nixos/modules/services/networking/ssh/lshd.nix
@@ -117,62 +117,60 @@ in
 
     services.lshd.subsystems = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ];
 
-    jobs.lshd =
-      { description = "GNU lshd SSH2 daemon";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        environment =
-          { LD_LIBRARY_PATH = config.system.nssModules.path; };
-
-        preStart =
-          ''
-            test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
-            test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
-
-            if ! test -f /var/spool/lsh/yarrow-seed-file
-            then
-                # XXX: It would be nice to provide feedback to the
-                # user when this fails, so that they can retry it
-                # manually.
-                ${lsh}/bin/lsh-make-seed --sloppy \
-                   -o /var/spool/lsh/yarrow-seed-file
-            fi
-
-            if ! test -f "${cfg.hostKey}"
-            then
-                ${lsh}/bin/lsh-keygen --server | \
-                ${lsh}/bin/lsh-writekey --server -o "${cfg.hostKey}"
-            fi
-          '';
-
-        exec = with cfg;
-          ''
-            ${lsh}/sbin/lshd --daemonic \
-              --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
-              -p ${toString portNumber} \
-              ${if interfaces == [] then ""
-                else (concatStrings (map (i: "--interface=\"${i}\"")
-                                         interfaces))} \
-              -h "${hostKey}" \
-              ${if !syslog then "--no-syslog" else ""} \
-              ${if passwordAuthentication then "--password" else "--no-password" } \
-              ${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
-              ${if rootLogin then "--root-login" else "--no-root-login" } \
-              ${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
-              ${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
-              ${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
-              ${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
-              --subsystems=${concatStringsSep ","
-                                              (map (pair: (head pair) + "=" +
-                                                          (head (tail pair)))
-                                                   subsystems)}
-          '';
+    systemd.services.lshd = {
+      description = "GNU lshd SSH2 daemon";
+
+      after = [ "network-interfaces.target" ];
+
+      wantedBy = [ "multi-user.target" ];
+
+      environment = {
+        LD_LIBRARY_PATH = config.system.nssModules.path;
       };
 
-    security.pam.services.lshd = {};
+      preStart = ''
+        test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
+        test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
+
+        if ! test -f /var/spool/lsh/yarrow-seed-file
+        then
+            # XXX: It would be nice to provide feedback to the
+            # user when this fails, so that they can retry it
+            # manually.
+            ${lsh}/bin/lsh-make-seed --sloppy \
+               -o /var/spool/lsh/yarrow-seed-file
+        fi
+
+        if ! test -f "${cfg.hostKey}"
+        then
+            ${lsh}/bin/lsh-keygen --server | \
+            ${lsh}/bin/lsh-writekey --server -o "${cfg.hostKey}"
+        fi
+      '';
+
+      script = with cfg; ''
+        ${lsh}/sbin/lshd --daemonic \
+          --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
+          -p ${toString portNumber} \
+          ${if interfaces == [] then ""
+            else (concatStrings (map (i: "--interface=\"${i}\"")
+                                     interfaces))} \
+          -h "${hostKey}" \
+          ${if !syslog then "--no-syslog" else ""} \
+          ${if passwordAuthentication then "--password" else "--no-password" } \
+          ${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
+          ${if rootLogin then "--root-login" else "--no-root-login" } \
+          ${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
+          ${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
+          ${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
+          ${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
+          --subsystems=${concatStringsSep ","
+                                          (map (pair: (head pair) + "=" +
+                                                      (head (tail pair)))
+                                               subsystems)}
+      '';
+    };
 
+    security.pam.services.lshd = {};
   };
-
 }
diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix
index c87fe914df8..bd584a3a85d 100644
--- a/nixos/modules/services/networking/sslh.nix
+++ b/nixos/modules/services/networking/sslh.nix
@@ -16,7 +16,7 @@ let
 
     listen:
     (
-      { host: "${cfg.host}"; port: "${toString cfg.port}"; }
+      { host: "${cfg.listenAddress}"; port: "${toString cfg.port}"; }
     );
 
     ${cfg.appendConfig}
@@ -56,7 +56,7 @@ in
         description = "PID file path for sslh daemon.";
       };
 
-      host = mkOption {
+      listenAddress = mkOption {
         type = types.str;
         default = config.networking.hostName;
         description = "Listening hostname.";
diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix
index 502a0468787..16c4ee7e33b 100644
--- a/nixos/modules/services/networking/supplicant.nix
+++ b/nixos/modules/services/networking/supplicant.nix
@@ -115,7 +115,7 @@ in
 
           path = mkOption {
             type = types.path;
-            example = "/etc/wpa_supplicant.conf";
+            example = literalExample "/etc/wpa_supplicant.conf";
             description = ''
               External <literal>wpa_supplicant.conf</literal> configuration file.
               The configuration options defined declaratively within <literal>networking.supplicant</literal> have
diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix
index 56c384731c6..f5d5e1d2556 100644
--- a/nixos/modules/services/networking/syncthing.nix
+++ b/nixos/modules/services/networking/syncthing.nix
@@ -43,6 +43,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.syncthing;
+        defaultText = "pkgs.syncthing";
         example = literalExample "pkgs.syncthing";
         description = ''
           Syncthing package to use.
diff --git a/nixos/modules/services/networking/tcpcrypt.nix b/nixos/modules/services/networking/tcpcrypt.nix
index fbd581cc4b4..267653abce0 100644
--- a/nixos/modules/services/networking/tcpcrypt.nix
+++ b/nixos/modules/services/networking/tcpcrypt.nix
@@ -35,11 +35,11 @@ in
       description = "tcpcrypt daemon user";
     };
 
-    jobs.tcpcrypt = {
+    systemd.services.tcpcrypt = {
       description = "tcpcrypt";
 
-      wantedBy = ["multi-user.target"];
-      after = ["network-interfaces.target"];
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
 
       path = [ pkgs.iptables pkgs.tcpcrypt pkgs.procps ];
 
@@ -58,7 +58,7 @@ in
         iptables -t mangle -I POSTROUTING -j nixos-tcpcrypt
       '';
 
-      exec = "tcpcryptd -x 0x10";
+      script = "tcpcryptd -x 0x10";
 
       postStop = ''
         if [ -f /run/pre-tcpcrypt-ecn-state ]; then
diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix
index 2d43c3d962d..34f4f6b37b6 100644
--- a/nixos/modules/services/networking/tinc.nix
+++ b/nixos/modules/services/networking/tinc.nix
@@ -43,6 +43,14 @@ in
             '';
           };
 
+          ed25519PrivateKeyFile = mkOption {
+            default = null;
+            type = types.nullOr types.path;
+            description = ''
+              Path of the private ed25519 keyfile.
+            '';
+          };
+
           debugLevel = mkOption {
             default = 0;
             type = types.addCheck types.int (l: l >= 0 && l <= 5);
@@ -70,8 +78,18 @@ in
             '';
           };
 
+          listenAddress = mkOption {
+            default = null;
+            type = types.nullOr types.str;
+            description = ''
+              The ip adress to bind to.
+            '';
+          };
+
           package = mkOption {
+            type = types.package;
             default = pkgs.tinc_pre;
+            defaultText = "pkgs.tinc_pre";
             description = ''
               The package to use for the tinc daemon's binary.
             '';
@@ -99,6 +117,8 @@ in
             text = ''
               Name = ${if data.name == null then "$HOST" else data.name}
               DeviceType = ${data.interfaceType}
+              ${optionalString (data.ed25519PrivateKeyFile != null) "Ed25519PrivateKeyFile = ${data.ed25519PrivateKeyFile}"}
+              ${optionalString (data.listenAddress != null) "BindToAddress = ${data.listenAddress}"}
               Device = /dev/net/tun
               Interface = tinc.${network}
               ${data.extraConfig}
@@ -134,10 +154,10 @@ in
           # Determine how we should generate our keys
           if type tinc >/dev/null 2>&1; then
             # Tinc 1.1+ uses the tinc helper application for key generation
-
+          ${if data.ed25519PrivateKeyFile != null then "  # Keyfile managed by nix" else ''
             # Prefer ED25519 keys (only in 1.1+)
             [ -f "/etc/tinc/${network}/ed25519_key.priv" ] || tinc -n ${network} generate-ed25519-keys
-
+          ''}
             # Otherwise use RSA keys
             [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tinc -n ${network} generate-rsa-keys 4096
           else
diff --git a/nixos/modules/services/networking/vsftpd.nix b/nixos/modules/services/networking/vsftpd.nix
index 447149552f4..e7301e9ef5f 100644
--- a/nixos/modules/services/networking/vsftpd.nix
+++ b/nixos/modules/services/networking/vsftpd.nix
@@ -120,7 +120,9 @@ in
       };
 
       userlistFile = mkOption {
+        type = types.path;
         default = pkgs.writeText "userlist" (concatMapStrings (x: "${x}\n") cfg.userlist);
+        defaultText = "pkgs.writeText \"userlist\" (concatMapStrings (x: \"\${x}\n\") cfg.userlist)";
         description = ''
           Newline separated list of names to be allowed/denied if <option>userlistEnable</option>
           is <literal>true</literal>. Meaning see <option>userlistDeny</option>.
diff --git a/nixos/modules/services/networking/wicd.nix b/nixos/modules/services/networking/wicd.nix
index 18258084fc2..9e5a437b485 100644
--- a/nixos/modules/services/networking/wicd.nix
+++ b/nixos/modules/services/networking/wicd.nix
@@ -25,17 +25,13 @@ with lib;
 
     environment.systemPackages = [pkgs.wicd];
 
-    jobs.wicd =
-      { startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        script =
-          "${pkgs.wicd}/sbin/wicd -f";
-      };
+    systemd.services.wicd = {
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      script = "${pkgs.wicd}/sbin/wicd -f";
+    };
 
     services.dbus.enable = true;
     services.dbus.packages = [pkgs.wicd];
-
   };
-
 }
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index 9e04bd40190..1b655af6c82 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -3,51 +3,30 @@
 with lib;
 
 let
-
   cfg = config.networking.wireless;
-  configFile = "/etc/wpa_supplicant.conf";
-
-  ifaces =
-    cfg.interfaces ++
-    optional (config.networking.WLANInterface != "") config.networking.WLANInterface;
-
-in
-
-{
-
-  ###### interface
-
+  configFile = if cfg.networks != {} then pkgs.writeText "wpa_supplicant.conf" ''
+    ${optionalString cfg.userControlled.enable ''
+      ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}
+      update_config=1''}
+    ${concatStringsSep "\n" (mapAttrsToList (ssid: networkConfig: ''
+      network={
+        ssid="${ssid}"
+        ${optionalString (networkConfig.psk != null) ''psk="${networkConfig.psk}"''}
+        ${optionalString (networkConfig.psk == null) ''key_mgmt=NONE''}
+      }
+    '') cfg.networks)}
+  '' else "/etc/wpa_supplicant.conf";
+in {
   options = {
-
-    networking.WLANInterface = mkOption {
-      default = "";
-      description = "Obsolete. Use <option>networking.wireless.interfaces</option> instead.";
-    };
-
     networking.wireless = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to start <command>wpa_supplicant</command> to scan for
-          and associate with wireless networks.  Note: NixOS currently
-          does not manage <command>wpa_supplicant</command>'s
-          configuration file, <filename>${configFile}</filename>.  You
-          should edit this file yourself to define wireless networks,
-          WPA keys and so on (see
-          <citerefentry><refentrytitle>wpa_supplicant.conf</refentrytitle>
-          <manvolnum>5</manvolnum></citerefentry>), or use
-          networking.wireless.userControlled.* to allow users to add entries
-          through <command>wpa_cli</command> and <command>wpa_gui</command>.
-        '';
-      };
+      enable = mkEnableOption "wpa_supplicant";
 
       interfaces = mkOption {
         type = types.listOf types.str;
         default = [];
         example = [ "wlan0" "wlan1" ];
         description = ''
-          The interfaces <command>wpa_supplicant</command> will use.  If empty, it will
+          The interfaces <command>wpa_supplicant</command> will use. If empty, it will
           automatically use all wireless interfaces.
         '';
       };
@@ -58,6 +37,37 @@ in
         description = "Force a specific wpa_supplicant driver.";
       };
 
+      networks = mkOption {
+        type = types.attrsOf (types.submodule {
+          options = {
+            psk = mkOption {
+              type = types.nullOr types.str;
+              default = null;
+              description = ''
+                The network's pre-shared key in plaintext defaulting
+                to being a network without any authentication.
+
+                Be aware that these will be written to the nix store
+                in plaintext!
+              '';
+            };
+          };
+        });
+        description = ''
+          The network definitions to automatically connect to when
+           <command>wpa_supplicant</command> is running. If this
+           parameter is left empty wpa_supplicant will use
+          /etc/wpa_supplicant.conf as the configuration file.
+        '';
+        default = {};
+        example = literalExample ''
+          echelon = {
+            psk = "abcdefgh";
+          };
+          "free.wifi" = {};
+        '';
+      };
+
       userControlled = {
         enable = mkOption {
           type = types.bool;
@@ -68,10 +78,8 @@ in
             to depend on a large package such as NetworkManager just to pick nearby
             access points.
 
-            When you want to use this, make sure ${configFile} doesn't exist.
-            It will be created for you.
-
-            Currently it is also necessary to explicitly specify networking.wireless.interfaces.
+            When using a declarative network specification you cannot persist any
+            settings via wpa_gui or wpa_cli.
           '';
         };
 
@@ -85,64 +93,49 @@ in
     };
   };
 
+  config = mkMerge [
+    (mkIf cfg.enable {
+      environment.systemPackages =  [ pkgs.wpa_supplicant ];
 
-  ###### implementation
-
-  config = mkIf cfg.enable {
-
-    environment.systemPackages =  [ pkgs.wpa_supplicant ];
-
-    services.dbus.packages = [ pkgs.wpa_supplicant ];
+      services.dbus.packages = [ pkgs.wpa_supplicant ];
 
-    # FIXME: start a separate wpa_supplicant instance per interface.
-    jobs.wpa_supplicant =
-      { description = "WPA Supplicant";
+      # FIXME: start a separate wpa_supplicant instance per interface.
+      systemd.services.wpa_supplicant = let
+        ifaces = cfg.interfaces;
+      in {
+        description = "WPA Supplicant";
 
         wantedBy = [ "network.target" ];
 
         path = [ pkgs.wpa_supplicant ];
 
-        preStart = ''
-          touch -a ${configFile}
-          chmod 600 ${configFile}
-        '' + optionalString cfg.userControlled.enable ''
-          if [ ! -s ${configFile} ]; then
-            echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}" >> ${configFile}
-            echo "update_config=1" >> ${configFile}
-          fi
+        script = ''
+          ${if ifaces == [] then ''
+            for i in $(cd /sys/class/net && echo *); do
+              DEVTYPE=
+              source /sys/class/net/$i/uevent
+              if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
+                ifaces="$ifaces''${ifaces:+ -N} -i$i"
+              fi
+            done
+          '' else ''
+            ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
+          ''}
+          exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
         '';
-
-        script =
-          ''
-            ${if ifaces == [] then ''
-              for i in $(cd /sys/class/net && echo *); do
-                DEVTYPE=
-                source /sys/class/net/$i/uevent
-                if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
-                  ifaces="$ifaces''${ifaces:+ -N} -i$i"
-                fi
-              done
-            '' else ''
-              ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
-            ''}
-            exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
-          '';
       };
 
-    powerManagement.resumeCommands =
-      ''
+      powerManagement.resumeCommands = ''
         ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant
       '';
 
-    assertions = [{ assertion = !cfg.userControlled.enable || cfg.interfaces != [];
-                    message = "user controlled wpa_supplicant needs explicit networking.wireless.interfaces";}];
-
-    # Restart wpa_supplicant when a wlan device appears or disappears.
-    services.udev.extraRules =
-      ''
+      # Restart wpa_supplicant when a wlan device appears or disappears.
+      services.udev.extraRules = ''
         ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service"
       '';
-
-  };
-
+    })
+    {
+      meta.maintainers = with lib.maintainers; [ globin ];
+    }
+  ];
 }
diff --git a/nixos/modules/services/networking/xinetd.nix b/nixos/modules/services/networking/xinetd.nix
index 14ee52ae52e..08680b51780 100644
--- a/nixos/modules/services/networking/xinetd.nix
+++ b/nixos/modules/services/networking/xinetd.nix
@@ -6,8 +6,6 @@ let
 
   cfg = config.services.xinetd;
 
-  inherit (pkgs) xinetd;
-
   configFile = pkgs.writeText "xinetd.conf"
     ''
       defaults
@@ -141,18 +139,12 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
-
-    jobs.xinetd =
-      { description = "xinetd server";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        path = [ xinetd ];
-
-        exec = "xinetd -syslog daemon -dontfork -stayalive -f ${configFile}";
-      };
-
+    systemd.services.xinetd = {
+      description = "xinetd server";
+      after = [ "network-interfaces.target" ];
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.xinetd ];
+      script = "xinetd -syslog daemon -dontfork -stayalive -f ${configFile}";
+    };
   };
-
 }
diff --git a/nixos/modules/services/scheduling/atd.nix b/nixos/modules/services/scheduling/atd.nix
index c6f128ec402..2070b2ffa01 100644
--- a/nixos/modules/services/scheduling/atd.nix
+++ b/nixos/modules/services/scheduling/atd.nix
@@ -66,49 +66,47 @@ in
         gid = config.ids.gids.atd;
       };
 
-    jobs.atd =
-      { description = "Job Execution Daemon (atd)";
-
-        startOn = "stopped udevtrigger";
-
-        path = [ at ];
-
-        preStart =
-          ''
-            # Snippets taken and adapted from the original `install' rule of
-            # the makefile.
-
-            # We assume these values are those actually used in Nixpkgs for
-            # `at'.
-            spooldir=/var/spool/atspool
-            jobdir=/var/spool/atjobs
-            etcdir=/etc/at
-
-            for dir in "$spooldir" "$jobdir" "$etcdir"; do
-              if [ ! -d "$dir" ]; then
-                  mkdir -p "$dir"
-                  chown atd:atd "$dir"
-              fi
-            done
-            chmod 1770 "$spooldir" "$jobdir"
-            ${if cfg.allowEveryone then ''chmod a+rwxt "$spooldir" "$jobdir" '' else ""}
-            if [ ! -f "$etcdir"/at.deny ]; then
-                touch "$etcdir"/at.deny
-                chown root:atd "$etcdir"/at.deny
-                chmod 640 "$etcdir"/at.deny
-            fi
-            if [ ! -f "$jobdir"/.SEQ ]; then
-                touch "$jobdir"/.SEQ
-                chown atd:atd "$jobdir"/.SEQ
-                chmod 600 "$jobdir"/.SEQ
-            fi
-          '';
-
-        exec = "atd";
-
-        daemonType = "fork";
-      };
+    systemd.services.atd = {
+      description = "Job Execution Daemon (atd)";
+      after = [ "systemd-udev-settle.service" ];
+      wants = [ "systemd-udev-settle.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+      path = [ at ];
+
+      preStart = ''
+        # Snippets taken and adapted from the original `install' rule of
+        # the makefile.
+
+        # We assume these values are those actually used in Nixpkgs for
+        # `at'.
+        spooldir=/var/spool/atspool
+        jobdir=/var/spool/atjobs
+        etcdir=/etc/at
+
+        for dir in "$spooldir" "$jobdir" "$etcdir"; do
+          if [ ! -d "$dir" ]; then
+              mkdir -p "$dir"
+              chown atd:atd "$dir"
+          fi
+        done
+        chmod 1770 "$spooldir" "$jobdir"
+        ${if cfg.allowEveryone then ''chmod a+rwxt "$spooldir" "$jobdir" '' else ""}
+        if [ ! -f "$etcdir"/at.deny ]; then
+            touch "$etcdir"/at.deny
+            chown root:atd "$etcdir"/at.deny
+            chmod 640 "$etcdir"/at.deny
+        fi
+        if [ ! -f "$jobdir"/.SEQ ]; then
+            touch "$jobdir"/.SEQ
+            chown atd:atd "$jobdir"/.SEQ
+            chmod 600 "$jobdir"/.SEQ
+        fi
+      '';
 
-  };
+      script = "atd";
 
+      serviceConfig.Type = "forking";
+    };
+  };
 }
diff --git a/nixos/modules/services/scheduling/fcron.nix b/nixos/modules/services/scheduling/fcron.nix
index ade8c19329c..7b4665a8204 100644
--- a/nixos/modules/services/scheduling/fcron.nix
+++ b/nixos/modules/services/scheduling/fcron.nix
@@ -108,29 +108,25 @@ in
 
     security.setuidPrograms = [ "fcrontab" ];
 
-    jobs.fcron =
-      { description = "fcron daemon";
-
-        startOn = "startup";
-
-        after = [ "local-fs.target" ];
-
-        environment =
-          { PATH = "/run/current-system/sw/bin";
-          };
-
-        preStart =
-          ''
-            ${pkgs.coreutils}/bin/mkdir -m 0700 -p /var/spool/fcron
-            # load system crontab file
-            ${pkgs.fcron}/bin/fcrontab -u systab ${pkgs.writeText "systab" cfg.systab}
-          '';
+    systemd.services.fcron = {
+      description = "fcron daemon";
+      after = [ "local-fs.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      # FIXME use specific path
+      environment = {
+        PATH = "/run/current-system/sw/bin";
+      };
 
-        daemonType = "fork";
+      preStart = ''
+        ${pkgs.coreutils}/bin/mkdir -m 0700 -p /var/spool/fcron
+        # load system crontab file
+        ${pkgs.fcron}/bin/fcrontab -u systab ${pkgs.writeText "systab" cfg.systab}
+      '';
 
-        exec = "${pkgs.fcron}/sbin/fcron -m ${toString cfg.maxSerialJobs} ${queuelen}";
-      };
+      serviceConfig.Type = "forking";
 
+      script = "${pkgs.fcron}/sbin/fcron -m ${toString cfg.maxSerialJobs} ${queuelen}";
+    };
   };
-
 }
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index 96873987707..e586600cdff 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -6,7 +6,7 @@ let
   cfg = config.services.elasticsearch;
 
   esConfig = ''
-    network.host: ${cfg.host}
+    network.host: ${cfg.listenAddress}
     network.port: ${toString cfg.port}
     network.tcp.port: ${toString cfg.tcp_port}
     cluster.name: ${cfg.cluster_name}
@@ -40,10 +40,11 @@ in {
     package = mkOption {
       description = "Elasticsearch package to use.";
       default = pkgs.elasticsearch;
+      defaultText = "pkgs.elasticsearch";
       type = types.package;
     };
 
-    host = mkOption {
+    listenAddress = mkOption {
       description = "Elasticsearch listen address.";
       default = "127.0.0.1";
       type = types.str;
@@ -142,7 +143,7 @@ in {
         ln -s ${esPlugins}/plugins ${cfg.dataDir}/plugins
       '';
       postStart = mkBefore ''
-        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null ${cfg.host}:${toString cfg.port}; do
+        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null ${cfg.listenAddress}:${toString cfg.port}; do
           sleep 1
         done
       '';
diff --git a/nixos/modules/services/search/kibana.nix b/nixos/modules/services/search/kibana.nix
index f47ab8f5586..4263ed22a8d 100644
--- a/nixos/modules/services/search/kibana.nix
+++ b/nixos/modules/services/search/kibana.nix
@@ -8,7 +8,7 @@ let
   cfgFile = pkgs.writeText "kibana.json" (builtins.toJSON (
     (filterAttrsRecursive (n: v: v != null) ({
       server = {
-        host = cfg.host;
+        host = cfg.listenAddress;
         port = cfg.port;
         ssl = {
           cert = cfg.cert;
@@ -44,7 +44,7 @@ in {
   options.services.kibana = {
     enable = mkEnableOption "enable kibana service";
 
-    host = mkOption {
+    listenAddress = mkOption {
       description = "Kibana listening host";
       default = "127.0.0.1";
       type = types.str;
@@ -127,6 +127,7 @@ in {
     package = mkOption {
       description = "Kibana package to use";
       default = pkgs.kibana;
+      defaultText = "pkgs.kibana";
       type = types.package;
     };
 
diff --git a/nixos/modules/services/search/solr.nix b/nixos/modules/services/search/solr.nix
index 7886d1e2e8e..33d74e89723 100644
--- a/nixos/modules/services/search/solr.nix
+++ b/nixos/modules/services/search/solr.nix
@@ -45,6 +45,7 @@ in {
       javaPackage = mkOption {
         type = types.package;
         default = pkgs.jre;
+        defaultText = "pkgs.jre";
         description = ''
           Which Java derivation to use for running solr.
         '';
@@ -53,6 +54,7 @@ in {
       solrPackage = mkOption {
         type = types.package;
         default = pkgs.solr;
+        defaultText = "pkgs.solr";
         description = ''
           Which solr derivation to use for running solr.
         '';
diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix
index 6288b1b3ba8..1d3e18dcab2 100644
--- a/nixos/modules/services/security/fail2ban.nix
+++ b/nixos/modules/services/security/fail2ban.nix
@@ -138,6 +138,7 @@ in
         findtime = 600
         maxretry = 3
         backend  = systemd
+        enabled  = true
        '';
 
     # Block SSH if there are too many failing connection attempts.
diff --git a/nixos/modules/services/security/fprot.nix b/nixos/modules/services/security/fprot.nix
index 7270a9f9814..a12aa01503e 100644
--- a/nixos/modules/services/security/fprot.nix
+++ b/nixos/modules/services/security/fprot.nix
@@ -67,24 +67,22 @@ in {
 
     services.cron.systemCronJobs = [ "*/${toString cfg.updater.frequency} * * * * root start fprot-updater" ];
 
-    jobs = {
-      fprot_updater = {
-        name = "fprot-updater";
-          task = true;
-
-          # have to copy fpupdate executable because it insists on storing the virus database in the same dir
-          preStart = ''
-            mkdir -m 0755 -p ${stateDir}
-            chown ${fprotUser}:${fprotGroup} ${stateDir}
-            cp ${pkgs.fprot}/opt/f-prot/fpupdate ${stateDir}
-            ln -sf ${cfg.updater.productData} ${stateDir}/product.data
-          '';
-          #setuid = fprotUser;
-          #setgid = fprotGroup;
-          exec = "/var/lib/fprot/fpupdate --keyfile ${cfg.updater.licenseKeyfile}";
+    systemd.services."fprot-updater" = {
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = false;
       };
-    };
+      wantedBy = [ "multi-user.target" ];
 
- };
+      # have to copy fpupdate executable because it insists on storing the virus database in the same dir
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+        chown ${fprotUser}:${fprotGroup} ${stateDir}
+        cp ${pkgs.fprot}/opt/f-prot/fpupdate ${stateDir}
+        ln -sf ${cfg.updater.productData} ${stateDir}/product.data
+      '';
 
+      script = "/var/lib/fprot/fpupdate --keyfile ${cfg.updater.licenseKeyfile}";
+    };
+ };
 }
diff --git a/nixos/modules/services/system/kerberos.nix b/nixos/modules/services/system/kerberos.nix
index 3a0171ca1b9..e0c3f95c3cc 100644
--- a/nixos/modules/services/system/kerberos.nix
+++ b/nixos/modules/services/system/kerberos.nix
@@ -45,27 +45,20 @@ in
         serverArgs = "${pkgs.heimdal}/sbin/kadmind";
       };
 
-    jobs.kdc =
-      { description = "Kerberos Domain Controller daemon";
-
-        startOn = "ip-up";
-
-        preStart =
-          ''
-            mkdir -m 0755 -p ${stateDir}
-          '';
-
-        exec = "${heimdal}/sbin/kdc";
-
-      };
-
-    jobs.kpasswdd =
-      { description = "Kerberos Domain Controller daemon";
-
-        startOn = "ip-up";
+    systemd.services.kdc = {
+      description = "Kerberos Domain Controller daemon";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+      '';
+      script = "${heimdal}/sbin/kdc";
+    };
 
-        exec = "${heimdal}/sbin/kpasswdd";
-      };
+    systemd.services.kpasswdd = {
+      description = "Kerberos Domain Controller daemon";
+      wantedBy = [ "multi-user.target" ];
+      script = "${heimdal}/sbin/kpasswdd";
+    };
   };
 
 }
diff --git a/nixos/modules/services/system/uptimed.nix b/nixos/modules/services/system/uptimed.nix
index ab46c508914..5f8916bbf9a 100644
--- a/nixos/modules/services/system/uptimed.nix
+++ b/nixos/modules/services/system/uptimed.nix
@@ -45,23 +45,21 @@ in
         home = stateDir;
       };
 
-    jobs.uptimed =
-      { description = "Uptimed daemon";
+    systemd.services.uptimed = {
+      description = "Uptimed daemon";
+      wantedBy = [ "multi-user.target" ];
 
-        startOn = "startup";
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}
+        chown ${uptimedUser} ${stateDir}
 
-        preStart =
-          ''
-            mkdir -m 0755 -p ${stateDir}
-            chown ${uptimedUser} ${stateDir}
+        if ! test -f ${stateDir}/bootid ; then
+          ${uptimed}/sbin/uptimed -b
+        fi
+      '';
 
-            if ! test -f ${stateDir}/bootid ; then
-              ${uptimed}/sbin/uptimed -b
-            fi
-          '';
-
-        exec = "${uptimed}/sbin/uptimed";
-      };
+      script = "${uptimed}/sbin/uptimed";
+    };
 
   };
 
diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix
index 85ee23c1a3d..ea7196fc873 100644
--- a/nixos/modules/services/ttys/agetty.nix
+++ b/nixos/modules/services/ttys/agetty.nix
@@ -2,6 +2,13 @@
 
 with lib;
 
+let
+
+  autologinArg = optionalString (config.services.mingetty.autologinUser != null) "--autologin ${config.services.mingetty.autologinUser}";
+  gettyCmd = extraArgs: "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login ${autologinArg} ${extraArgs}";
+
+in
+
 {
 
   ###### interface
@@ -21,9 +28,9 @@ with lib;
 
       greetingLine = mkOption {
         type = types.str;
-        default = ''<<< Welcome to NixOS ${config.system.nixosVersion} (\m) - \l >>>'';
         description = ''
           Welcome line printed by mingetty.
+          The default shows current NixOS version label, machine type and tty.
         '';
       };
 
@@ -55,10 +62,11 @@ with lib;
 
   ###### implementation
 
-  config = let
-    autologinArg = optionalString (config.services.mingetty.autologinUser != null) "--autologin ${config.services.mingetty.autologinUser}";
-    gettyCmd = extraArgs: "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login ${autologinArg} ${extraArgs}";
-  in {
+  config = {
+    # Note: this is set here rather than up there so that changing
+    # nixosLabel would not rebuild manual pages
+    services.mingetty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixosLabel} (\m) - \l >>>'';
+
     systemd.services."getty@" =
       { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud %I 115200,38400,9600 $TERM";
         restartIfChanged = false;
@@ -81,7 +89,7 @@ with lib;
       { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM";
         serviceConfig.Restart = "always";
         restartIfChanged = false;
-	enable = mkDefault config.boot.isContainer;
+        enable = mkDefault config.boot.isContainer;
       };
 
     environment.etc = singleton
diff --git a/nixos/modules/services/ttys/kmscon.nix b/nixos/modules/services/ttys/kmscon.nix
index 7783a1ada71..ba25f912844 100644
--- a/nixos/modules/services/ttys/kmscon.nix
+++ b/nixos/modules/services/ttys/kmscon.nix
@@ -32,6 +32,13 @@ in {
         default = "";
         example = "font-size=14";
       };
+
+      extraOptions = mkOption {
+        description = "Extra flags to pass to kmscon.";
+        type = types.separatedString " ";
+        default = "";
+        example = "--term xterm-256color";
+      };
     };
   };
 
@@ -53,7 +60,7 @@ in {
       ConditionPathExists=/dev/tty0
 
       [Service]
-      ExecStart=${pkgs.kmscon}/bin/kmscon "--vt=%I" --seats=seat0 --no-switchvt --configdir ${configDir} --login -- ${pkgs.shadow}/bin/login -p
+      ExecStart=${pkgs.kmscon}/bin/kmscon "--vt=%I" ${cfg.extraOptions} --seats=seat0 --no-switchvt --configdir ${configDir} --login -- ${pkgs.shadow}/bin/login -p
       UtmpIdentifier=%I
       TTYPath=/dev/%I
       TTYReset=yes
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 9908aea1a66..880cd9f39c4 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -429,6 +429,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.apacheHttpd;
+        defaultText = "pkgs.apacheHttpd";
         description = ''
           Overridable attribute of the Apache HTTP Server package to use.
         '';
@@ -437,7 +438,8 @@ in
       configFile = mkOption {
         type = types.path;
         default = confFile;
-        example = literalExample ''pkgs.writeText "httpd.conf" "# my custom config file ...";'';
+        defaultText = "confFile";
+        example = literalExample ''pkgs.writeText "httpd.conf" "# my custom config file ..."'';
         description = ''
           Override the configuration file used by Apache. By default,
           NixOS generates one automatically.
diff --git a/nixos/modules/services/web-servers/jboss/default.nix b/nixos/modules/services/web-servers/jboss/default.nix
index 8a292ad6791..583fe56eb5e 100644
--- a/nixos/modules/services/web-servers/jboss/default.nix
+++ b/nixos/modules/services/web-servers/jboss/default.nix
@@ -71,13 +71,10 @@ in
   ###### implementation
 
   config = mkIf config.services.jboss.enable {
-
-    jobs.jboss =
-      { description = "JBoss server";
-
-        exec = "${jbossService}/bin/control start";
-      };
-
+    systemd.services.jboss = {
+      description = "JBoss server";
+      script = "${jbossService}/bin/control start";
+      wantedBy = [ "multi-user.target" ];
+    };
   };
-
 }
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 25816446e99..27a33f33ff9 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -34,6 +34,7 @@ in
 
       package = mkOption {
         default = pkgs.nginx;
+        defaultText = "pkgs.nginx";
         type = types.package;
         description = "
           Nginx package to use.
diff --git a/nixos/modules/services/web-servers/phpfpm.nix b/nixos/modules/services/web-servers/phpfpm.nix
index 82398948bfa..bdd41ed702b 100644
--- a/nixos/modules/services/web-servers/phpfpm.nix
+++ b/nixos/modules/services/web-servers/phpfpm.nix
@@ -36,7 +36,9 @@ in {
       };
 
       phpPackage = mkOption {
+        type = types.package;
         default = pkgs.php;
+        defaultText = "pkgs.php";
         description = ''
           The PHP package to use for running the FPM service.
         '';
diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix
index 99460a48835..c3be20b41e2 100644
--- a/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixos/modules/services/web-servers/tomcat.nix
@@ -24,6 +24,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.tomcat7;
+        defaultText = "pkgs.tomcat7";
         example = lib.literalExample "pkgs.tomcat8";
         description = ''
           Which tomcat package to use.
@@ -72,7 +73,9 @@ in
       };
 
       webapps = mkOption {
+        type = types.listOf types.package;
         default = [ tomcat ];
+        defaultText = "[ tomcat ]";
         description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat";
       };
 
@@ -87,7 +90,9 @@ in
       };
 
       jdk = mkOption {
+        type = types.package;
         default = pkgs.jdk;
+        defaultText = "pkgs.jdk";
         description = "Which JDK to use.";
       };
 
@@ -127,124 +132,206 @@ in
         extraGroups = cfg.extraGroups;
       };
 
-    jobs.tomcat =
-      { description = "Apache Tomcat server";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        daemonType = "daemon";
-
-        preStart =
-          ''
-            # Create the base directory
-            mkdir -p ${cfg.baseDir}
-
-            # Create a symlink to the bin directory of the tomcat component
-            ln -sfn ${tomcat}/bin ${cfg.baseDir}/bin
-
-            # Create a conf/ directory
-            mkdir -p ${cfg.baseDir}/conf
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/conf
-
-            # Symlink the config files in the conf/ directory (except for catalina.properties and server.xml)
-            for i in $(ls ${tomcat}/conf | grep -v catalina.properties | grep -v server.xml)
-            do
-                ln -sfn ${tomcat}/conf/$i ${cfg.baseDir}/conf/`basename $i`
-            done
+    systemd.services.tomcat = {
+      description = "Apache Tomcat server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      serviceConfig.Type = "oneshot";
+      serviceConfig.RemainAfterExit = true;
+
+      preStart = ''
+        # Create the base directory
+        mkdir -p ${cfg.baseDir}
+
+        # Create a symlink to the bin directory of the tomcat component
+        ln -sfn ${tomcat}/bin ${cfg.baseDir}/bin
+
+        # Create a conf/ directory
+        mkdir -p ${cfg.baseDir}/conf
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/conf
+
+        # Symlink the config files in the conf/ directory (except for catalina.properties and server.xml)
+        for i in $(ls ${tomcat}/conf | grep -v catalina.properties | grep -v server.xml)
+        do
+            ln -sfn ${tomcat}/conf/$i ${cfg.baseDir}/conf/`basename $i`
+        done
+
+        # Create subdirectory for virtual hosts
+        mkdir -p ${cfg.baseDir}/virtualhosts
+
+        # Create a modified catalina.properties file
+        # Change all references from CATALINA_HOME to CATALINA_BASE and add support for shared libraries
+        sed -e 's|''${catalina.home}|''${catalina.base}|g' \
+            -e 's|shared.loader=|shared.loader=''${catalina.base}/shared/lib/*.jar|' \
+            ${tomcat}/conf/catalina.properties > ${cfg.baseDir}/conf/catalina.properties
+
+        # Create a modified server.xml which also includes all virtual hosts
+        sed -e "/<Engine name=\"Catalina\" defaultHost=\"localhost\">/a\  ${
+                     toString (map (virtualHost: ''<Host name=\"${virtualHost.name}\" appBase=\"virtualhosts/${virtualHost.name}/webapps\" unpackWARs=\"true\" autoDeploy=\"true\" xmlValidation=\"false\" xmlNamespaceAware=\"false\" >${if cfg.logPerVirtualHost then ''<Valve className=\"org.apache.catalina.valves.AccessLogValve\" directory=\"logs/${virtualHost.name}\"  prefix=\"${virtualHost.name}_access_log.\" pattern=\"combined\" resolveHosts=\"false\"/>'' else ""}</Host>'') cfg.virtualHosts)}" \
+            ${tomcat}/conf/server.xml > ${cfg.baseDir}/conf/server.xml
+
+        # Create a logs/ directory
+        mkdir -p ${cfg.baseDir}/logs
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/logs
+        ${if cfg.logPerVirtualHost then
+           toString (map (h: ''
+                                mkdir -p ${cfg.baseDir}/logs/${h.name}
+                                chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/logs/${h.name}
+                             '') cfg.virtualHosts) else ''''}
+
+        # Create a temp/ directory
+        mkdir -p ${cfg.baseDir}/temp
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/temp
+
+        # Create a lib/ directory
+        mkdir -p ${cfg.baseDir}/lib
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/lib
+
+        # Create a shared/lib directory
+        mkdir -p ${cfg.baseDir}/shared/lib
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/shared/lib
+
+        # Create a webapps/ directory
+        mkdir -p ${cfg.baseDir}/webapps
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/webapps
+
+        # Symlink all the given common libs files or paths into the lib/ directory
+        for i in ${tomcat} ${toString cfg.commonLibs}
+        do
+            if [ -f $i ]
+            then
+                # If the given web application is a file, symlink it into the common/lib/ directory
+                ln -sfn $i ${cfg.baseDir}/lib/`basename $i`
+            elif [ -d $i ]
+            then
+                # If the given web application is a directory, then iterate over the files
+                # in the special purpose directories and symlink them into the tomcat tree
+
+                for j in $i/lib/*
+                do
+                    ln -sfn $j ${cfg.baseDir}/lib/`basename $j`
+                done
+            fi
+        done
+
+        # Symlink all the given shared libs files or paths into the shared/lib/ directory
+        for i in ${toString cfg.sharedLibs}
+        do
+            if [ -f $i ]
+            then
+                # If the given web application is a file, symlink it into the common/lib/ directory
+                ln -sfn $i ${cfg.baseDir}/shared/lib/`basename $i`
+            elif [ -d $i ]
+            then
+                # If the given web application is a directory, then iterate over the files
+                # in the special purpose directories and symlink them into the tomcat tree
+
+                for j in $i/shared/lib/*
+                do
+                    ln -sfn $j ${cfg.baseDir}/shared/lib/`basename $j`
+                done
+            fi
+        done
+
+        # Symlink all the given web applications files or paths into the webapps/ directory
+        for i in ${toString cfg.webapps}
+        do
+            if [ -f $i ]
+            then
+                # If the given web application is a file, symlink it into the webapps/ directory
+                ln -sfn $i ${cfg.baseDir}/webapps/`basename $i`
+            elif [ -d $i ]
+            then
+                # If the given web application is a directory, then iterate over the files
+                # in the special purpose directories and symlink them into the tomcat tree
+
+                for j in $i/webapps/*
+                do
+                    ln -sfn $j ${cfg.baseDir}/webapps/`basename $j`
+                done
 
-            # Create subdirectory for virtual hosts
-            mkdir -p ${cfg.baseDir}/virtualhosts
-
-            # Create a modified catalina.properties file
-            # Change all references from CATALINA_HOME to CATALINA_BASE and add support for shared libraries
-            sed -e 's|''${catalina.home}|''${catalina.base}|g' \
-                -e 's|shared.loader=|shared.loader=''${catalina.base}/shared/lib/*.jar|' \
-                ${tomcat}/conf/catalina.properties > ${cfg.baseDir}/conf/catalina.properties
-
-            # Create a modified server.xml which also includes all virtual hosts
-            sed -e "/<Engine name=\"Catalina\" defaultHost=\"localhost\">/a\  ${
-                         toString (map (virtualHost: ''<Host name=\"${virtualHost.name}\" appBase=\"virtualhosts/${virtualHost.name}/webapps\" unpackWARs=\"true\" autoDeploy=\"true\" xmlValidation=\"false\" xmlNamespaceAware=\"false\" >${if cfg.logPerVirtualHost then ''<Valve className=\"org.apache.catalina.valves.AccessLogValve\" directory=\"logs/${virtualHost.name}\"  prefix=\"${virtualHost.name}_access_log.\" pattern=\"combined\" resolveHosts=\"false\"/>'' else ""}</Host>'') cfg.virtualHosts)}" \
-                ${tomcat}/conf/server.xml > ${cfg.baseDir}/conf/server.xml
-
-            # Create a logs/ directory
-            mkdir -p ${cfg.baseDir}/logs
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/logs
-            ${if cfg.logPerVirtualHost then
-               toString (map (h: ''
-                                    mkdir -p ${cfg.baseDir}/logs/${h.name}
-                                    chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/logs/${h.name}
-                                 '') cfg.virtualHosts) else ''''}
-
-            # Create a temp/ directory
-            mkdir -p ${cfg.baseDir}/temp
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/temp
-
-            # Create a lib/ directory
-            mkdir -p ${cfg.baseDir}/lib
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/lib
-
-            # Create a shared/lib directory
-            mkdir -p ${cfg.baseDir}/shared/lib
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/shared/lib
-
-            # Create a webapps/ directory
-            mkdir -p ${cfg.baseDir}/webapps
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/webapps
-
-            # Symlink all the given common libs files or paths into the lib/ directory
-            for i in ${tomcat} ${toString cfg.commonLibs}
-            do
-                if [ -f $i ]
+                # Also symlink the configuration files if they are included
+                if [ -d $i/conf/Catalina ]
                 then
-                    # If the given web application is a file, symlink it into the common/lib/ directory
-                    ln -sfn $i ${cfg.baseDir}/lib/`basename $i`
-                elif [ -d $i ]
-                then
-                    # If the given web application is a directory, then iterate over the files
-                    # in the special purpose directories and symlink them into the tomcat tree
-
-                    for j in $i/lib/*
+                    for j in $i/conf/Catalina/*
                     do
-                        ln -sfn $j ${cfg.baseDir}/lib/`basename $j`
+                        mkdir -p ${cfg.baseDir}/conf/Catalina/localhost
+                        ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j`
                     done
                 fi
-            done
+            fi
+        done
+
+        ${toString (map (virtualHost: ''
+          # Create webapps directory for the virtual host
+          mkdir -p ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps
+
+          # Modify ownership
+          chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps
+
+          # Symlink all the given web applications files or paths into the webapps/ directory
+          # of this virtual host
+          for i in "${if virtualHost ? webapps then toString virtualHost.webapps else ""}"
+          do
+              if [ -f $i ]
+              then
+                  # If the given web application is a file, symlink it into the webapps/ directory
+                  ln -sfn $i ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps/`basename $i`
+              elif [ -d $i ]
+              then
+                  # If the given web application is a directory, then iterate over the files
+                  # in the special purpose directories and symlink them into the tomcat tree
+
+                  for j in $i/webapps/*
+                  do
+                      ln -sfn $j ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps/`basename $j`
+                  done
+
+                  # Also symlink the configuration files if they are included
+                  if [ -d $i/conf/Catalina ]
+                  then
+                      for j in $i/conf/Catalina/*
+                      do
+                          mkdir -p ${cfg.baseDir}/conf/Catalina/${virtualHost.name}
+                          ln -sfn $j ${cfg.baseDir}/conf/Catalina/${virtualHost.name}/`basename $j`
+                      done
+                  fi
+              fi
+          done
 
-            # Symlink all the given shared libs files or paths into the shared/lib/ directory
-            for i in ${toString cfg.sharedLibs}
-            do
-                if [ -f $i ]
-                then
-                    # If the given web application is a file, symlink it into the common/lib/ directory
-                    ln -sfn $i ${cfg.baseDir}/shared/lib/`basename $i`
-                elif [ -d $i ]
-                then
-                    # If the given web application is a directory, then iterate over the files
-                    # in the special purpose directories and symlink them into the tomcat tree
+          ''
+        ) cfg.virtualHosts) }
 
-                    for j in $i/shared/lib/*
-                    do
-                        ln -sfn $j ${cfg.baseDir}/shared/lib/`basename $j`
-                    done
-                fi
-            done
+        # Create a work/ directory
+        mkdir -p ${cfg.baseDir}/work
+        chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/work
+
+        ${if cfg.axis2.enable then
+            ''
+            # Copy the Axis2 web application
+            cp -av ${pkgs.axis2}/webapps/axis2 ${cfg.baseDir}/webapps
 
-            # Symlink all the given web applications files or paths into the webapps/ directory
-            for i in ${toString cfg.webapps}
+            # Turn off addressing, which causes many errors
+            sed -i -e 's%<module ref="addressing"/>%<!-- <module ref="addressing"/> -->%' ${cfg.baseDir}/webapps/axis2/WEB-INF/conf/axis2.xml
+
+            # Modify permissions on the Axis2 application
+            chown -R ${cfg.user}:${cfg.group} ${cfg.baseDir}/webapps/axis2
+
+            # Symlink all the given web service files or paths into the webapps/axis2/WEB-INF/services directory
+            for i in ${toString cfg.axis2.services}
             do
                 if [ -f $i ]
                 then
-                    # If the given web application is a file, symlink it into the webapps/ directory
-                    ln -sfn $i ${cfg.baseDir}/webapps/`basename $i`
+                    # If the given web service is a file, symlink it into the webapps/axis2/WEB-INF/services
+                    ln -sfn $i ${cfg.baseDir}/webapps/axis2/WEB-INF/services/`basename $i`
                 elif [ -d $i ]
                 then
                     # If the given web application is a directory, then iterate over the files
                     # in the special purpose directories and symlink them into the tomcat tree
 
-                    for j in $i/webapps/*
+                    for j in $i/webapps/axis2/WEB-INF/services/*
                     do
-                        ln -sfn $j ${cfg.baseDir}/webapps/`basename $j`
+                        ln -sfn $j ${cfg.baseDir}/webapps/axis2/WEB-INF/services/`basename $j`
                     done
 
                     # Also symlink the configuration files if they are included
@@ -252,110 +339,25 @@ in
                     then
                         for j in $i/conf/Catalina/*
                         do
-                            mkdir -p ${cfg.baseDir}/conf/Catalina/localhost
                             ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j`
                         done
                     fi
                 fi
             done
+            ''
+        else ""}
+      '';
 
-            ${toString (map (virtualHost: ''
-              # Create webapps directory for the virtual host
-              mkdir -p ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps
-
-              # Modify ownership
-              chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps
-
-              # Symlink all the given web applications files or paths into the webapps/ directory
-              # of this virtual host
-              for i in "${if virtualHost ? webapps then toString virtualHost.webapps else ""}"
-              do
-                  if [ -f $i ]
-                  then
-                      # If the given web application is a file, symlink it into the webapps/ directory
-                      ln -sfn $i ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps/`basename $i`
-                  elif [ -d $i ]
-                  then
-                      # If the given web application is a directory, then iterate over the files
-                      # in the special purpose directories and symlink them into the tomcat tree
-
-                      for j in $i/webapps/*
-                      do
-                          ln -sfn $j ${cfg.baseDir}/virtualhosts/${virtualHost.name}/webapps/`basename $j`
-                      done
-
-                      # Also symlink the configuration files if they are included
-                      if [ -d $i/conf/Catalina ]
-                      then
-                          for j in $i/conf/Catalina/*
-                          do
-                              mkdir -p ${cfg.baseDir}/conf/Catalina/${virtualHost.name}
-                              ln -sfn $j ${cfg.baseDir}/conf/Catalina/${virtualHost.name}/`basename $j`
-                          done
-                      fi
-                  fi
-              done
-
-              ''
-            ) cfg.virtualHosts) }
-
-            # Create a work/ directory
-            mkdir -p ${cfg.baseDir}/work
-            chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/work
+      script = ''
+          ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh'
+      '';
 
-            ${if cfg.axis2.enable then
-                ''
-                # Copy the Axis2 web application
-                cp -av ${pkgs.axis2}/webapps/axis2 ${cfg.baseDir}/webapps
+      postStop = ''
+        echo "Stopping tomcat..."
+        CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh
+      '';
 
-                # Turn off addressing, which causes many errors
-                sed -i -e 's%<module ref="addressing"/>%<!-- <module ref="addressing"/> -->%' ${cfg.baseDir}/webapps/axis2/WEB-INF/conf/axis2.xml
-
-                # Modify permissions on the Axis2 application
-                chown -R ${cfg.user}:${cfg.group} ${cfg.baseDir}/webapps/axis2
-
-                # Symlink all the given web service files or paths into the webapps/axis2/WEB-INF/services directory
-                for i in ${toString cfg.axis2.services}
-                do
-                    if [ -f $i ]
-                    then
-                        # If the given web service is a file, symlink it into the webapps/axis2/WEB-INF/services
-                        ln -sfn $i ${cfg.baseDir}/webapps/axis2/WEB-INF/services/`basename $i`
-                    elif [ -d $i ]
-                    then
-                        # If the given web application is a directory, then iterate over the files
-                        # in the special purpose directories and symlink them into the tomcat tree
-
-                        for j in $i/webapps/axis2/WEB-INF/services/*
-                        do
-                            ln -sfn $j ${cfg.baseDir}/webapps/axis2/WEB-INF/services/`basename $j`
-                        done
-
-                        # Also symlink the configuration files if they are included
-                        if [ -d $i/conf/Catalina ]
-                        then
-                            for j in $i/conf/Catalina/*
-                            do
-                                ln -sfn $j ${cfg.baseDir}/conf/Catalina/localhost/`basename $j`
-                            done
-                        fi
-                    fi
-                done
-                ''
-            else ""}
-          '';
-
-        script = ''
-            ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh'
-        '';
-
-        postStop =
-          ''
-            echo "Stopping tomcat..."
-            CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh
-          '';
-
-      };
+    };
 
   };
 
diff --git a/nixos/modules/services/web-servers/winstone.nix b/nixos/modules/services/web-servers/winstone.nix
index eed16a64f2a..6dab467b35e 100644
--- a/nixos/modules/services/web-servers/winstone.nix
+++ b/nixos/modules/services/web-servers/winstone.nix
@@ -31,6 +31,7 @@ let
       javaPackage = mkOption {
         type = types.package;
         default = pkgs.jre;
+        defaultText = "pkgs.jre";
         description = ''
           Which Java derivation to use for running Winstone.
         '';
diff --git a/nixos/modules/services/web-servers/zope2.nix b/nixos/modules/services/web-servers/zope2.nix
index bbe4d10f83d..ef3cffd582e 100644
--- a/nixos/modules/services/web-servers/zope2.nix
+++ b/nixos/modules/services/web-servers/zope2.nix
@@ -75,25 +75,26 @@ in
     services.zope2.instances = mkOption {
       default = {};
       type = types.loaOf types.optionSet;
-      example = {
-        plone01 = {
-          http_address = "127.0.0.1:8080";
-          extra =
-            ''
-            <zodb_db main>
-              mount-point /
-              cache-size 30000
-              <blobstorage>
-                  blob-dir /var/lib/zope2/plone01/blobstorage
-                  <filestorage>
-                  path /var/lib/zope2/plone01/filestorage/Data.fs
-                  </filestorage>
-              </blobstorage>
-            </zodb_db>
-            '';
-
-        };
-      };
+      example = literalExample ''
+        {
+          plone01 = {
+            http_address = "127.0.0.1:8080";
+            extra =
+              '''
+              <zodb_db main>
+                mount-point /
+                cache-size 30000
+                <blobstorage>
+                    blob-dir /var/lib/zope2/plone01/blobstorage
+                    <filestorage>
+                    path /var/lib/zope2/plone01/filestorage/Data.fs
+                    </filestorage>
+                </blobstorage>
+              </zodb_db>
+              ''';
+          };
+        }
+      '';
       description = "zope2 instances to be created automaticaly by the system.";
       options = [ zope2Opts ];
     };
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index b9c97a54fd2..55d7fd80cf9 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -62,6 +62,7 @@ in {
     };
 
     environment.gnome3.packageSet = mkOption {
+      type = types.nullOr types.package;
       default = null;
       example = literalExample "pkgs.gnome3_16";
       description = "Which GNOME 3 package set to use.";
diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix
index 21b6243ba18..29cca248cde 100644
--- a/nixos/modules/services/x11/desktop-managers/kde4.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde4.nix
@@ -66,6 +66,7 @@ in
       kdeWorkspacePackage = mkOption {
         internal = true;
         default = pkgs.kde4.kde_workspace;
+        defaultText = "pkgs.kde4.kde_workspace";
         type = types.package;
         description = "Custom kde-workspace, used for NixOS rebranding.";
       };
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index 2aeb4f67d77..e8c768e41fa 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -102,6 +102,7 @@ in
         kde5.gwenview
         kde5.kate
         kde5.kdegraphics-thumbnailers
+        kde5.kio-extras
         kde5.konsole
         kde5.okular
         kde5.print-manager
@@ -125,6 +126,7 @@ in
       ++ lib.optional config.networking.networkmanager.enable kde5.plasma-nm
       ++ lib.optional config.hardware.pulseaudio.enable kde5.plasma-pa
       ++ lib.optional config.powerManagement.enable kde5.powerdevil
+      ++ lib.optionals config.services.samba.enable [ kde5.kdenetwork-filesharing pkgs.samba ]
 
       ++ lib.optionals cfg.phonon.gstreamer.enable
         [
diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix
index 558f5e8cfc7..9b937ff7ee1 100644
--- a/nixos/modules/services/x11/display-managers/kdm.nix
+++ b/nixos/modules/services/x11/display-managers/kdm.nix
@@ -57,6 +57,7 @@ let
   kdmrc = pkgs.stdenv.mkDerivation {
     name = "kdmrc";
     config = defaultConfig + cfg.extraConfig;
+    preferLocalBuild = true;
     buildCommand =
       ''
         echo "$config" > $out
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
index 4b598ca48b0..543dd628ce6 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -67,8 +67,9 @@ in
       theme = {
 
         package = mkOption {
-          type = types.path;
+          type = types.package;
           default = pkgs.gnome3.gnome_themes_standard;
+          defaultText = "pkgs.gnome3.gnome_themes_standard";
           description = ''
             The package path that contains the theme given in the name option.
           '';
@@ -87,8 +88,9 @@ in
       iconTheme = {
 
         package = mkOption {
-          type = types.path;
+          type = types.package;
           default = pkgs.gnome3.defaultIconTheme;
+          defaultText = "pkgs.gnome3.defaultIconTheme";
           description = ''
             The package path that contains the icon theme given in the name option.
           '';
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index ded694d90d5..9460395f86d 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -69,7 +69,7 @@ in
 
       greeter =  {
         package = mkOption {
-          type = types.path;
+          type = types.package;
           description = ''
             The LightDM greeter to login via. The package should be a directory
             containing a .desktop file matching the name in the 'name' option.
@@ -86,6 +86,7 @@ in
       };
 
       background = mkOption {
+        type = types.path;
         description = ''
           The background image or color to use.
         '';
diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix
index e3db0230d3b..ce44c9f54a3 100644
--- a/nixos/modules/services/x11/display-managers/slim.nix
+++ b/nixos/modules/services/x11/display-managers/slim.nix
@@ -61,6 +61,10 @@ in
           url = "https://github.com/jagajaga/nixos-slim-theme/archive/2.0.tar.gz";
           sha256 = "0lldizhigx7bjhxkipii87y432hlf5wdvamnfxrryf9z7zkfypc8";
         };
+        defaultText = ''pkgs.fetchurl {
+          url = "https://github.com/jagajaga/nixos-slim-theme/archive/2.0.tar.gz";
+          sha256 = "0lldizhigx7bjhxkipii87y432hlf5wdvamnfxrryf9z7zkfypc8";
+        }'';
         example = literalExample ''
           pkgs.fetchurl {
             url = "mirror://sourceforge/slim.berlios/slim-wave.tar.gz";
diff --git a/nixos/modules/services/x11/redshift.nix b/nixos/modules/services/x11/redshift.nix
index 6614be261e5..4318a17a4fa 100644
--- a/nixos/modules/services/x11/redshift.nix
+++ b/nixos/modules/services/x11/redshift.nix
@@ -76,6 +76,7 @@ in {
     package = mkOption {
       type = types.package;
       default = pkgs.redshift;
+      defaultText = "pkgs.redshift";
       description = ''
         redshift derivation to use.
       '';
diff --git a/nixos/modules/services/x11/terminal-server.nix b/nixos/modules/services/x11/terminal-server.nix
index 810cc0c4688..09d0ab07751 100644
--- a/nixos/modules/services/x11/terminal-server.nix
+++ b/nixos/modules/services/x11/terminal-server.nix
@@ -9,19 +9,6 @@
 
 with lib;
 
-let
-
-  # Wrap Xvfb to set some flags/variables.
-  xvfbWrapper = pkgs.writeScriptBin "Xvfb"
-    ''
-      #! ${pkgs.stdenv.shell}
-      export XKB_BINDIR=${pkgs.xorg.xkbcomp}/bin
-      export XORG_DRI_DRIVER_PATH=${pkgs.mesa}/lib/dri
-      exec ${pkgs.xorg.xorgserver.out}/bin/Xvfb "$@" -xkbdir ${pkgs.xkeyboard_config}/etc/X11/xkb
-    '';
-
-in
-
 {
 
   config = {
@@ -54,7 +41,7 @@ in
       { description = "Terminal Server";
 
         path =
-          [ xvfbWrapper pkgs.gawk pkgs.which pkgs.openssl pkgs.xorg.xauth
+          [ pkgs.xorgserver.out pkgs.gawk pkgs.which pkgs.openssl pkgs.xorg.xauth
             pkgs.nettools pkgs.shadow pkgs.procps pkgs.utillinux pkgs.bash
           ];
 
diff --git a/nixos/modules/services/x11/window-managers/windowlab.nix b/nixos/modules/services/x11/window-managers/windowlab.nix
new file mode 100644
index 00000000000..fb891a39fa4
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/windowlab.nix
@@ -0,0 +1,22 @@
+{lib, pkgs, config, ...}:
+
+let
+  cfg = config.services.xserver.windowManager.windowlab;
+in
+
+{
+  options = {
+    services.xserver.windowManager.windowlab.enable =
+      lib.mkEnableOption "windowlab";
+  };
+
+  config = lib.mkIf cfg.enable {
+    services.xserver.windowManager = {
+      session =
+        [{ name  = "windowlab";
+           start = "${pkgs.windowlab}/bin/windowlab";
+        }];
+    };
+    environment.systemPackages = [ pkgs.windowlab ];
+  };
+}
diff --git a/nixos/modules/services/x11/xfs.nix b/nixos/modules/services/x11/xfs.nix
index 196f3beb41e..ea7cfa1aa43 100644
--- a/nixos/modules/services/x11/xfs.nix
+++ b/nixos/modules/services/x11/xfs.nix
@@ -30,20 +30,17 @@ in
   ###### implementation
 
   config = mkIf config.services.xfs.enable {
-
     assertions = singleton
       { assertion = config.fonts.enableFontDir;
         message = "Please enable fonts.enableFontDir to use the X Font Server.";
       };
 
-    jobs.xfs =
-      { description = "X Font Server";
-
-        startOn = "started networking";
-
-        exec = "${pkgs.xorg.xfs}/bin/xfs -config ${configFile}";
-      };
-
+    systemd.services.xfs = {
+      description = "X Font Server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.xorg.xfs ];
+      script = "xfs -config ${configFile}";
+    };
   };
-
 }
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index aec6fb0cc04..86f0641b0e3 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -13,7 +13,6 @@ let
 
   # Map video driver names to driver packages. FIXME: move into card-specific modules.
   knownVideoDrivers = {
-    unichrome    = { modules = [ pkgs.xorgVideoUnichrome ]; };
     virtualbox   = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; };
     ati = { modules = [ pkgs.xorg.xf86videoati pkgs.xorg.glamoregl ]; };
     intel-testing = { modules = with pkgs.xorg; [ xf86videointel-testing glamoregl ]; driverName = "intel"; };
@@ -503,7 +502,7 @@ in
     systemd.services.display-manager =
       { description = "X11 Server";
 
-        after = [ "systemd-udev-settle.service" "local-fs.target" "acpid.service" ];
+        after = [ "systemd-udev-settle.service" "local-fs.target" "acpid.service" "systemd-logind.service" ];
 
         restartIfChanged = false;
 
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index 81088a56fb1..d66580b7b9b 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -67,7 +67,7 @@ let
 
       echo -n "$configurationName" > $out/configuration-name
       echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version
-      echo -n "$nixosVersion" > $out/nixos-version
+      echo -n "$nixosLabel" > $out/nixos-version
       echo -n "$system" > $out/system
 
       mkdir $out/fine-tune
@@ -101,7 +101,7 @@ let
     if [] == failed then pkgs.stdenv.mkDerivation {
       name = let hn = config.networking.hostName;
                  nn = if (hn != "") then hn else "unnamed";
-          in "nixos-system-${nn}-${config.system.nixosVersion}";
+          in "nixos-system-${nn}-${config.system.nixosLabel}";
       preferLocalBuild = true;
       allowSubstitutes = false;
       buildCommand = systemBuilder;
@@ -115,7 +115,7 @@ let
         config.system.build.installBootLoader
         or "echo 'Warning: do not know how to make this configuration bootable; please enable a boot loader.' 1>&2; true";
       activationScript = config.system.activationScripts.script;
-      nixosVersion = config.system.nixosVersion;
+      nixosLabel = config.system.nixosLabel;
 
       configurationName = config.boot.loader.grub.configurationName;
 
@@ -205,7 +205,7 @@ in
 
     system.replaceRuntimeDependencies = mkOption {
       default = [];
-      example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { ... }; }) ]";
+      example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { }; }) ]";
       type = types.listOf (types.submodule (
         { options, ... }: {
           options.original = mkOption {
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index ac40e8a49ac..6bc046d0261 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -63,7 +63,7 @@ in
     };
 
     boot.extraModulePackages = mkOption {
-      type = types.listOf types.path;
+      type = types.listOf types.package;
       default = [];
       example = literalExample "[ pkgs.linuxPackages.nvidia_x11 ]";
       description = "A list of additional packages supplying kernel modules.";
@@ -158,7 +158,7 @@ in
 
     boot.kernel.sysctl."kernel.printk" = config.boot.consoleLogLevel;
 
-    boot.kernelModules = [ "loop" "configs" "atkbd" ];
+    boot.kernelModules = [ "loop" "atkbd" ];
 
     boot.initrd.availableKernelModules =
       [ # Note: most of these (especially the SATA/PATA modules)
@@ -197,9 +197,6 @@ in
         "hid_generic" "hid_lenovo"
         "hid_apple" "hid_logitech_dj" "hid_lenovo_tpkbd" "hid_roccat"
 
-        # Unix domain sockets (needed by udev).
-        "unix"
-
         # Misc. stuff.
         "pcips2" "atkbd"
 
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
index b9a42b2a196..78a8e8fd658 100644
--- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
+++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
@@ -83,7 +83,7 @@ addEntry() {
     timestampEpoch=$(stat -L -c '%Z' $path)
 
     timestamp=$(date "+%Y-%m-%d %H:%M" -d @$timestampEpoch)
-    nixosVersion="$(cat $path/nixos-version)"
+    nixosLabel="$(cat $path/nixos-version)"
     extraParams="$(cat $path/kernel-params)"
 
     echo
@@ -91,7 +91,7 @@ addEntry() {
     if [ "$tag" = "default" ]; then
         echo "  MENU LABEL NixOS - Default"
     else
-        echo "  MENU LABEL NixOS - Configuration $tag ($timestamp - $nixosVersion)"
+        echo "  MENU LABEL NixOS - Configuration $tag ($timestamp - $nixosLabel)"
     fi
     echo "  LINUX ../nixos/$(basename $kernel)"
     echo "  INITRD ../nixos/$(basename $initrd)"
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index 47605e3685c..d9f6f51f13a 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -56,7 +56,7 @@ let
         extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout
         default fsIdentifier efiSupport gfxmodeEfi gfxmodeBios;
       path = (makeSearchPath "bin" ([
-        pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfsProgs
+        pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfs-progs
         pkgs.utillinux ] ++ (if cfg.efiSupport && (cfg.version == 2) then [pkgs.efibootmgr ] else [])
       )) + ":" + (makeSearchPath "sbin" [
         pkgs.mdadm pkgs.utillinux
@@ -251,6 +251,7 @@ in
       };
 
       extraFiles = mkOption {
+        type = types.attrsOf types.path;
         default = {};
         example = literalExample ''
           { "memtest.bin" = "''${pkgs.memtest86plus}/memtest.bin"; }
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index af39e50ff72..b8ef02da4bc 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -387,6 +387,10 @@ sub addProfile {
     my $curEntry = 0;
     foreach my $link (@links) {
         last if $curEntry++ >= $configurationLimit;
+        if (! -e "$link/nixos-version") {
+            warn "skipping corrupt system profile entry ‘$link’\n";
+            next;
+        }
         my $date = strftime("%F", localtime(lstat($link)->mtime));
         my $version =
             -e "$link/nixos-version"
diff --git a/nixos/modules/system/boot/loader/grub/ipxe.nix b/nixos/modules/system/boot/loader/grub/ipxe.nix
index 9b5097a4cfd..249c2761934 100644
--- a/nixos/modules/system/boot/loader/grub/ipxe.nix
+++ b/nixos/modules/system/boot/loader/grub/ipxe.nix
@@ -39,7 +39,7 @@ in
               dhcp
               chain http://boot.ipxe.org/demo/boot.php
             ''';
-          };
+          }
         '';
       };
     };
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 76370320563..59bff5472e8 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -229,7 +229,7 @@ in
 
     boot.initrd.luks.devices = mkOption {
       default = [ ];
-      example = [ { name = "luksroot"; device = "/dev/sda3"; preLVM = true; } ];
+      example = literalExample ''[ { name = "luksroot"; device = "/dev/sda3"; preLVM = true; } ]'';
       description = ''
         The list of devices that should be decrypted using LUKS before trying to mount the
         root partition. This works for both LVM-over-LUKS and LUKS-over-LVM setups.
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 2b5d547353f..7fb368e8c44 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -140,6 +140,7 @@ done
 
 
 # Create device nodes in /dev.
+@preDeviceCommands@
 echo "running udev..."
 mkdir -p /etc/udev
 ln -sfn @udevRules@ /etc/udev/rules.d
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 0bd5387a7c0..81418bdf1c1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -203,7 +203,7 @@ let
     inherit (config.boot) resumeDevice devSize runSize;
 
     inherit (config.boot.initrd) checkJournalingFS
-      postEarlyDeviceCommands preLVMCommands postDeviceCommands postMountCommands kernelModules;
+      preLVMCommands preDeviceCommands postEarlyDeviceCommands postDeviceCommands postMountCommands kernelModules;
 
     resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}")
                     (filter (sd: (sd ? label || hasPrefix "/dev/" sd.device) && !sd.randomEncryption) config.swapDevices);
@@ -303,6 +303,15 @@ in
       '';
     };
 
+    boot.initrd.preDeviceCommands = mkOption {
+      default = "";
+      type = types.lines;
+      description = ''
+        Shell commands to be executed before udev is started to create
+        device nodes.
+      '';
+    };
+
     boot.initrd.postDeviceCommands = mkOption {
       default = "";
       type = types.lines;
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 826368e711a..211e0423216 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -179,8 +179,9 @@ let
     ];
 
   makeJobScript = name: text:
-    let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${shellEscape name}"; inherit text; };
-    in "${x}/bin/${shellEscape name}";
+    let mkScriptName =  s: (replaceChars [ "\\" ] [ "-" ] (shellEscape s) );
+        x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${mkScriptName name}"; inherit text; };
+    in "${x}/bin/${mkScriptName name}";
 
   unitConfig = { name, config, ... }: {
     config = {
@@ -373,6 +374,7 @@ in
 
     systemd.package = mkOption {
       default = pkgs.systemd;
+      defaultText = "pkgs.systemd";
       type = types.package;
       description = "The systemd package.";
     };
diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix
index 300ae0acda5..9d5b3db472c 100644
--- a/nixos/modules/system/etc/etc.nix
+++ b/nixos/modules/system/etc/etc.nix
@@ -112,8 +112,9 @@ in
 
           config = {
             target = mkDefault name;
-            source = mkIf (config.text != null)
-              (mkDefault (pkgs.writeText "etc-file" config.text));
+            source = mkIf (config.text != null) (
+              let name' = "etc-" + baseNameOf name;
+              in mkDefault (pkgs.writeText name' config.text));
           };
 
         });
diff --git a/nixos/modules/system/upstart/upstart.nix b/nixos/modules/system/upstart/upstart.nix
deleted file mode 100644
index 5c046130407..00000000000
--- a/nixos/modules/system/upstart/upstart.nix
+++ /dev/null
@@ -1,290 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-with import ../boot/systemd-unit-options.nix { inherit config lib; };
-
-let
-
-  userExists = u:
-    (u == "") || any (uu: uu.name == u) (attrValues config.users.extraUsers);
-
-  groupExists = g:
-    (g == "") || any (gg: gg.name == g) (attrValues config.users.extraGroups);
-
-  makeJobScript = name: content: "${pkgs.writeScriptBin name content}/bin/${name}";
-
-  # From a job description, generate an systemd unit file.
-  makeUnit = job:
-
-    let
-      hasMain = job.script != "" || job.exec != "";
-
-      env = job.environment;
-
-      preStartScript = makeJobScript "${job.name}-pre-start"
-        ''
-          #! ${pkgs.stdenv.shell} -e
-          ${job.preStart}
-        '';
-
-      startScript = makeJobScript "${job.name}-start"
-        ''
-          #! ${pkgs.stdenv.shell} -e
-          ${if job.script != "" then job.script else ''
-            exec ${job.exec}
-          ''}
-        '';
-
-      postStartScript = makeJobScript "${job.name}-post-start"
-        ''
-          #! ${pkgs.stdenv.shell} -e
-          ${job.postStart}
-        '';
-
-      preStopScript = makeJobScript "${job.name}-pre-stop"
-        ''
-          #! ${pkgs.stdenv.shell} -e
-          ${job.preStop}
-        '';
-
-      postStopScript = makeJobScript "${job.name}-post-stop"
-        ''
-          #! ${pkgs.stdenv.shell} -e
-          ${job.postStop}
-        '';
-    in {
-
-      inherit (job) description requires before partOf environment path restartIfChanged unitConfig;
-
-      after =
-        (if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else
-         if job.startOn == "started udev" then [ "systemd-udev.service" ] else
-         if job.startOn == "started network-interfaces" then [ "network-interfaces.target" ] else
-         if job.startOn == "started networking" then [ "network.target" ] else
-         if job.startOn == "ip-up" then [] else
-         if job.startOn == "" || job.startOn == "startup" then [] else
-         builtins.trace "Warning: job ‘${job.name}’ has unknown startOn value ‘${job.startOn}’." []
-        ) ++ job.after;
-
-      wants = 
-        (if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else []
-        ) ++ job.wants;
-
-      wantedBy =
-        (if job.startOn == "" then [] else
-         if job.startOn == "ip-up" then [ "ip-up.target" ] else
-         [ "multi-user.target" ]) ++ job.wantedBy;
-
-      serviceConfig =
-        job.serviceConfig
-        // optionalAttrs (job.preStart != "" && (job.script != "" || job.exec != ""))
-          { ExecStartPre = preStartScript; }
-        // optionalAttrs (job.preStart != "" && job.script == "" && job.exec == "")
-          { ExecStart = preStartScript; }
-        // optionalAttrs (job.script != "" || job.exec != "")
-          { ExecStart = startScript; }
-        // optionalAttrs (job.postStart != "")
-          { ExecStartPost = postStartScript; }
-        // optionalAttrs (job.preStop != "")
-          { ExecStop = preStopScript; }
-        // optionalAttrs (job.postStop != "")
-          { ExecStopPost = postStopScript; }
-        // (if job.script == "" && job.exec == "" then { Type = "oneshot"; RemainAfterExit = true; } else
-            if job.daemonType == "fork" || job.daemonType == "daemon" then { Type = "forking"; GuessMainPID = true; } else
-            if job.daemonType == "none" then { } else
-            throw "invalid daemon type `${job.daemonType}'")
-        // optionalAttrs (!job.task && !(job.script == "" && job.exec == "") && job.respawn)
-          { Restart = "always"; }
-        // optionalAttrs job.task
-          { Type = "oneshot"; RemainAfterExit = false; };
-    };
-
-
-  jobOptions = serviceOptions // {
-
-    name = mkOption {
-      # !!! The type should ensure that this could be a filename.
-      type = types.str;
-      example = "sshd";
-      description = ''
-        Name of the job, mapped to the systemd unit
-        <literal><replaceable>name</replaceable>.service</literal>.
-      '';
-    };
-
-    startOn = mkOption {
-      #type = types.str;
-      default = "";
-      description = ''
-        The Upstart event that triggers this job to be started.  Some
-        are mapped to systemd dependencies; otherwise you will get a
-        warning.  If empty, the job will not start automatically.
-      '';
-    };
-
-    stopOn = mkOption {
-      type = types.str;
-      default = "starting shutdown";
-      description = ''
-        Ignored; this was the Upstart event that triggers this job to be stopped.
-      '';
-    };
-
-    postStart = mkOption {
-      type = types.lines;
-      default = "";
-      description = ''
-        Shell commands executed after the job is started (i.e. after
-        the job's main process is started), but before the job is
-        considered “running”.
-      '';
-    };
-
-    preStop = mkOption {
-      type = types.lines;
-      default = "";
-      description = ''
-        Shell commands executed before the job is stopped
-        (i.e. before systemd kills the job's main process).  This can
-        be used to cleanly shut down a daemon.
-      '';
-    };
-
-    postStop = mkOption {
-      type = types.lines;
-      default = "";
-      description = ''
-        Shell commands executed after the job has stopped
-        (i.e. after the job's main process has terminated).
-      '';
-    };
-
-    exec = mkOption {
-      type = types.str;
-      default = "";
-      description = ''
-        Command to start the job's main process.  If empty, the
-        job has no main process, but can still have pre/post-start
-        and pre/post-stop scripts, and is considered “running”
-        until it is stopped.
-      '';
-    };
-
-    respawn = mkOption {
-      type = types.bool;
-      default = true;
-      description = ''
-        Whether to restart the job automatically if its process
-        ends unexpectedly.
-      '';
-    };
-
-    task = mkOption {
-      type = types.bool;
-      default = false;
-      description = ''
-        Whether this job is a task rather than a service.  Tasks
-        are executed only once, while services are restarted when
-        they exit.
-      '';
-    };
-
-    daemonType = mkOption {
-      type = types.str;
-      default = "none";
-      description = ''
-        Determines how systemd detects when a daemon should be
-        considered “running”.  The value <literal>none</literal> means
-        that the daemon is considered ready immediately.  The value
-        <literal>fork</literal> means that the daemon will fork once.
-        The value <literal>daemon</literal> means that the daemon will
-        fork twice.  The value <literal>stop</literal> means that the
-        daemon will raise the SIGSTOP signal to indicate readiness.
-      '';
-    };
-
-    setuid = mkOption {
-      type = types.addCheck types.str userExists;
-      default = "";
-      description = ''
-        Run the daemon as a different user.
-      '';
-    };
-
-    setgid = mkOption {
-      type = types.addCheck types.str groupExists;
-      default = "";
-      description = ''
-        Run the daemon as a different group.
-      '';
-    };
-
-    path = mkOption {
-      default = [];
-      description = ''
-        Packages added to the job's <envar>PATH</envar> environment variable.
-        Both the <filename>bin</filename> and <filename>sbin</filename>
-        subdirectories of each package are added.
-      '';
-    };
-
-  };
-
-
-  upstartJob = { name, config, ... }: {
-
-    options = {
-
-      unit = mkOption {
-        default = makeUnit config;
-        description = "Generated definition of the systemd unit corresponding to this job.";
-      };
-
-    };
-
-    config = {
-
-      # The default name is the name extracted from the attribute path.
-      name = mkDefault name;
-
-    };
-
-  };
-
-in
-
-{
-
-  ###### interface
-
-  options = {
-
-    jobs = mkOption {
-      default = {};
-      description = ''
-        This option is a legacy method to define system services,
-        dating from the era where NixOS used Upstart instead of
-        systemd.  You should use <option>systemd.services</option>
-        instead.  Services defined using <option>jobs</option> are
-        mapped automatically to <option>systemd.services</option>, but
-        may not work perfectly; in particular, most
-        <option>startOn</option> conditions are not supported.
-      '';
-      type = types.loaOf types.optionSet;
-      options = [ jobOptions upstartJob ];
-    };
-
-  };
-
-
-  ###### implementation
-
-  config = {
-
-    systemd.services =
-      flip mapAttrs' config.jobs (name: job:
-        nameValuePair job.name job.unit);
-
-  };
-
-}
diff --git a/nixos/modules/tasks/filesystems/btrfs.nix b/nixos/modules/tasks/filesystems/btrfs.nix
index 049f7708d73..8cfa1b6921d 100644
--- a/nixos/modules/tasks/filesystems/btrfs.nix
+++ b/nixos/modules/tasks/filesystems/btrfs.nix
@@ -11,13 +11,13 @@ in
 {
   config = mkIf (any (fs: fs == "btrfs") config.boot.supportedFilesystems) {
 
-    system.fsPackages = [ pkgs.btrfsProgs ];
+    system.fsPackages = [ pkgs.btrfs-progs ];
 
     boot.initrd.kernelModules = mkIf inInitrd [ "btrfs" "crc32c" ];
 
     boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
-        copy_bin_and_libs ${pkgs.btrfsProgs}/bin/btrfs
+        copy_bin_and_libs ${pkgs.btrfs-progs}/bin/btrfs
         ln -sv btrfs $out/bin/btrfsck
         ln -sv btrfsck $out/bin/fsck.btrfs
       '';
@@ -31,13 +31,5 @@ in
       ''
         btrfs device scan
       '';
-
-    # !!! This is broken.  There should be a udev rule to do this when
-    # new devices are discovered.
-    jobs.udev.postStart =
-      ''
-        ${pkgs.btrfsProgs}/bin/btrfs device scan
-      '';
-
   };
 }
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index dedd3f5ca45..f4c42b16220 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -73,6 +73,21 @@ in
         '';
       };
 
+      devNodes = mkOption {
+        type = types.path;
+        default = "/dev/disk/by-id";
+        example = "/dev/disk/by-id";
+        description = ''
+          Name of directory from which to import ZFS devices.
+
+          Usually /dev works. However, ZFS import may fail if a device node is renamed.
+          It should therefore use stable device names, such as from /dev/disk/by-id.
+
+          The default remains /dev for 15.09, due to backwards compatibility concerns.
+          It will change to /dev/disk/by-id in the next NixOS release.
+        '';
+      };
+
       forceImportRoot = mkOption {
         type = types.bool;
         default = true;
@@ -214,7 +229,7 @@ in
             done
             ''] ++ (map (pool: ''
             echo "importing root ZFS pool \"${pool}\"..."
-            zpool import -d /dev/disk/by-id -N $ZFS_FORCE "${pool}"
+            zpool import -d ${cfgZfs.devNodes} -N $ZFS_FORCE "${pool}"
         '') rootPools));
       };
 
@@ -255,7 +270,7 @@ in
             };
             script = ''
               zpool_cmd="${zfsUserPkg}/sbin/zpool"
-              ("$zpool_cmd" list "${pool}" >/dev/null) || "$zpool_cmd" import -d /dev/disk/by-id -N ${optionalString cfgZfs.forceImportAll "-f"} "${pool}"
+              ("$zpool_cmd" list "${pool}" >/dev/null) || "$zpool_cmd" import -d ${cfgZfs.devNodes} -N ${optionalString cfgZfs.forceImportAll "-f"} "${pool}"
             '';
           };
       in listToAttrs (map createImportService dataPools) // {
diff --git a/nixos/modules/tasks/kbd.nix b/nixos/modules/tasks/kbd.nix
index e36e9f85f1e..e1574fa68ad 100644
--- a/nixos/modules/tasks/kbd.nix
+++ b/nixos/modules/tasks/kbd.nix
@@ -5,13 +5,13 @@ with lib;
 let
 
   makeColor = n: value: "COLOR_${toString n}=${value}";
+  colors = concatImapStringsSep "\n" makeColor config.i18n.consoleColors;
 
-  vconsoleConf = pkgs.writeText "vconsole.conf"
-    ''
-      KEYMAP=${config.i18n.consoleKeyMap}
-      FONT=${config.i18n.consoleFont}
-    '' + concatImapStringsSep "\n" makeColor config.i18n.consoleColors;
-
+  vconsoleConf = pkgs.writeText "vconsole.conf" ''
+    KEYMAP=${config.i18n.consoleKeyMap}
+    FONT=${config.i18n.consoleFont}
+    ${colors}
+  '';
 in
 
 {
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index ee21d735f95..e72c0f8956e 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -355,6 +355,7 @@ in
     };
 
     networking.nameservers = mkOption {
+      type = types.listOf types.str;
       default = [];
       example = ["130.161.158.4" "130.161.33.17"];
       description = ''
@@ -390,6 +391,7 @@ in
     };
 
     networking.localCommands = mkOption {
+      type = types.str;
       default = "";
       example = "text=anything; echo You can put $text here.";
       description = ''
diff --git a/nixos/modules/tasks/trackpoint.nix b/nixos/modules/tasks/trackpoint.nix
index bd340869d69..32e69dd2bf5 100644
--- a/nixos/modules/tasks/trackpoint.nix
+++ b/nixos/modules/tasks/trackpoint.nix
@@ -32,7 +32,7 @@ with lib;
         example = 255;
         type = types.int;
         description = ''
-          Configure the trackpoint sensitivity. By default, the kernel
+          Configure the trackpoint speed. By default, the kernel
           configures 97.
         '';
       };
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index f37bbd0246d..c233beb63ca 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -43,6 +43,11 @@ let kernel = config.boot.kernelPackages.kernel; in
     # into thinking they're running interactively.
     environment.variables.PAGER = "";
 
+    boot.initrd.preDeviceCommands =
+      ''
+        echo 600 > /proc/sys/kernel/hung_task_timeout_secs
+      '';
+
     boot.initrd.postDeviceCommands =
       ''
         # Using acpi_pm as a clock source causes the guest clock to
diff --git a/nixos/modules/virtualisation/azure-image.nix b/nixos/modules/virtualisation/azure-image.nix
index 024be4a5116..08944e641d7 100644
--- a/nixos/modules/virtualisation/azure-image.nix
+++ b/nixos/modules/virtualisation/azure-image.nix
@@ -26,7 +26,7 @@ in
               ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vpc $diskImage $out/disk.vhd
               rm $diskImage
             '';
-          diskImageBase = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
+          diskImageBase = "nixos-image-${config.system.nixosLabel}-${pkgs.stdenv.system}.raw";
           buildInputs = [ pkgs.utillinux pkgs.perl ];
           exportReferencesGraph =
             [ "closure" config.system.build.toplevel ];
@@ -105,7 +105,7 @@ in
       path  = [ pkgs.coreutils ];
       script =
         ''
-          eval "$(base64 --decode /metadata/CustomData.bin)"
+          eval "$(cat /metadata/CustomData.bin)"
           if ! [ -z "$ssh_host_ecdsa_key" ]; then
             echo "downloaded ssh_host_ecdsa_key"
             echo "$ssh_host_ecdsa_key" > /etc/ssh/ssh_host_ed25519_key
diff --git a/nixos/modules/virtualisation/brightbox-image.nix b/nixos/modules/virtualisation/brightbox-image.nix
index 0eb46d39b52..b6b2bd4f69b 100644
--- a/nixos/modules/virtualisation/brightbox-image.nix
+++ b/nixos/modules/virtualisation/brightbox-image.nix
@@ -26,7 +26,7 @@ in
               rm $diskImageBase
               popd
             '';
-          diskImageBase = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
+          diskImageBase = "nixos-image-${config.system.nixosLabel}-${pkgs.stdenv.system}.raw";
           buildInputs = [ pkgs.utillinux pkgs.perl ];
           exportReferencesGraph =
             [ "closure" config.system.build.toplevel ];
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index f21ddc12ca5..77074b88246 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -30,7 +30,7 @@ in
               rm $out/disk.raw
               popd
             '';
-          diskImageBase = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.raw";
+          diskImageBase = "nixos-image-${config.system.nixosLabel}-${pkgs.stdenv.system}.raw";
           buildInputs = [ pkgs.utillinux pkgs.perl ];
           exportReferencesGraph =
             [ "closure" config.system.build.toplevel ];
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index 16aedbbb185..67fbb8263b0 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -122,18 +122,14 @@ in
             chmod 755 /var/lib/libvirt
             chmod 755 /var/lib/libvirt/dnsmasq
 
-            # Libvirt unfortunately writes mutable state (such as
-            # runtime changes to VM, network or filter configurations)
-            # to /etc.  So we can't use environment.etc to make the
-            # default network and filter definitions available, since
-            # libvirt will then modify the originals in the Nix store.
-            # So here we copy them instead.  Ugly.
-            for i in $(cd ${pkgs.libvirt}/etc && echo \
+            # Copy default libvirt network config .xml files to /var/lib
+            # Files modified by the user will not be overwritten
+            for i in $(cd ${pkgs.libvirt}/var/lib && echo \
                 libvirt/qemu/networks/*.xml libvirt/qemu/networks/autostart/*.xml \
                 libvirt/nwfilter/*.xml );
             do
-                mkdir -p /etc/$(dirname $i) -m 755
-                cp -fpd ${pkgs.libvirt}/etc/$i /etc/$i
+                mkdir -p /var/lib/$(dirname $i) -m 755
+                cp -npd ${pkgs.libvirt}/var/lib/$i /var/lib/$i
             done
 
             # libvirtd puts the full path of the emulator binary in the machine
@@ -166,33 +162,33 @@ in
           '';
       };
 
-    jobs."libvirt-guests" =
-      { description = "Libvirt Virtual Machines";
+    systemd.services."libvirt-guests" = {
+      description = "Libvirt Virtual Machines";
 
-        wantedBy = [ "multi-user.target" ];
-        wants = [ "libvirtd.service" ];
-        after = [ "libvirtd.service" ];
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "libvirtd.service" ];
+      after = [ "libvirtd.service" ];
 
-        restartIfChanged = false;
+      restartIfChanged = false;
 
-        path = [ pkgs.gettext pkgs.libvirt pkgs.gawk ];
+      path = with pkgs; [ gettext libvirt gawk ];
 
-        preStart =
-          ''
-            mkdir -p /var/lock/subsys -m 755
-            ${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests start || true
-          '';
+      preStart = ''
+        mkdir -p /var/lock/subsys -m 755
+        ${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests start || true
+      '';
 
-        postStop = 
-            ''
-            export PATH=${pkgs.gettext}/bin:$PATH
-            export ON_SHUTDOWN=${cfg.onShutdown}
-            ${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;
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
       };
+    };
 
     users.extraGroups.libvirtd.gid = config.ids.gids.libvirtd;
 
diff --git a/nixos/modules/virtualisation/lxd.nix b/nixos/modules/virtualisation/lxd.nix
index 488153334bc..845f14352f3 100644
--- a/nixos/modules/virtualisation/lxd.nix
+++ b/nixos/modules/virtualisation/lxd.nix
@@ -45,7 +45,7 @@ in
         after = [ "systemd-udev-settle.service" ];
 
         # TODO(wkennington): Add lvm2 and thin-provisioning-tools
-        path = with pkgs; [ acl rsync gnutar xz btrfsProgs ];
+        path = with pkgs; [ acl rsync gnutar xz btrfs-progs ];
 
         serviceConfig.ExecStart = "@${pkgs.lxd}/bin/lxd lxd --syslog --group lxd";
         serviceConfig.Type = "simple";
diff --git a/nixos/modules/virtualisation/openvswitch.nix b/nixos/modules/virtualisation/openvswitch.nix
index a0231315236..4218a3840fc 100644
--- a/nixos/modules/virtualisation/openvswitch.nix
+++ b/nixos/modules/virtualisation/openvswitch.nix
@@ -31,6 +31,7 @@ in {
     package = mkOption {
       type = types.package;
       default = pkgs.openvswitch;
+      defaultText = "pkgs.openvswitch";
       description = ''
         Open vSwitch package to use.
       '';
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 5c468604443..82b58aa67a3 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -77,14 +77,14 @@ let
           -virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
           -virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
           ${if cfg.useBootLoader then ''
-            -drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=${cfg.qemu.diskInterface},cache=none,werror=report \
+            -drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=${cfg.qemu.diskInterface},cache=writeback,werror=report \
             -drive index=1,id=drive2,file=$TMPDIR/disk.img,media=disk \
             ${if cfg.useEFIBoot then ''
               -pflash $TMPDIR/bios.bin \
             '' else ''
             ''}
           '' else ''
-            -drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=${cfg.qemu.diskInterface},cache=none,werror=report \
+            -drive index=0,id=drive1,file=$NIX_DISK_IMAGE,if=${cfg.qemu.diskInterface},cache=writeback,werror=report \
             -kernel ${config.system.build.toplevel}/kernel \
             -initrd ${config.system.build.toplevel}/initrd \
             -append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index 425726333c4..da9e75a003a 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -44,8 +44,8 @@ in {
 
     system.build.virtualBoxOVA = pkgs.runCommand "virtualbox-ova"
       { buildInputs = [ pkgs.linuxPackages.virtualbox ];
-        vmName = "NixOS ${config.system.nixosVersion} (${pkgs.stdenv.system})";
-        fileName = "nixos-image-${config.system.nixosVersion}-${pkgs.stdenv.system}.ova";
+        vmName = "NixOS ${config.system.nixosLabel} (${pkgs.stdenv.system})";
+        fileName = "nixos-image-${config.system.nixosLabel}-${pkgs.stdenv.system}.ova";
       }
       ''
         echo "creating VirtualBox VM..."