summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/config/networking.nix18
-rw-r--r--nixos/modules/config/users-groups.nix60
-rw-r--r--nixos/modules/hardware/opengl.nix2
-rw-r--r--nixos/modules/i18n/input-method/default.nix29
-rw-r--r--nixos/modules/i18n/input-method/default.xml12
-rw-r--r--nixos/modules/i18n/input-method/ibus.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix11
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh2
-rw-r--r--nixos/modules/misc/ids.nix6
-rw-r--r--nixos/modules/module-list.nix8
-rw-r--r--nixos/modules/programs/bash/bash.nix2
-rw-r--r--nixos/modules/programs/java.nix57
-rw-r--r--nixos/modules/programs/zsh/zsh.nix21
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/security/acme.nix4
-rw-r--r--nixos/modules/security/grsecurity.xml6
-rw-r--r--nixos/modules/security/pam.nix3
-rw-r--r--nixos/modules/services/backup/bacula.nix9
-rw-r--r--nixos/modules/services/backup/rsnapshot.nix3
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix10
-rw-r--r--nixos/modules/services/continuous-integration/gitlab-runner.nix51
-rw-r--r--nixos/modules/services/databases/cassandra.nix2
-rw-r--r--nixos/modules/services/databases/influxdb.nix2
-rw-r--r--nixos/modules/services/databases/neo4j.nix2
-rw-r--r--nixos/modules/services/hardware/sane_extra_backends/brscan4.nix5
-rw-r--r--nixos/modules/services/hardware/udev.nix26
-rw-r--r--nixos/modules/services/logging/logcheck.nix68
-rw-r--r--nixos/modules/services/mail/offlineimap.nix (renamed from nixos/modules/services/networking/offlineimap.nix)2
-rw-r--r--nixos/modules/services/mail/postgrey.nix79
-rw-r--r--nixos/modules/services/misc/apache-kafka.nix2
-rwxr-xr-x[-rw-r--r--]nixos/modules/services/misc/confd.nix2
-rw-r--r--nixos/modules/services/misc/emby.nix2
-rw-r--r--nixos/modules/services/misc/etcd.nix10
-rw-r--r--nixos/modules/services/misc/folding-at-home.nix2
-rw-r--r--nixos/modules/services/misc/gitlab.nix18
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix55
-rw-r--r--nixos/modules/services/misc/mesos-master.nix2
-rw-r--r--nixos/modules/services/misc/mesos-slave.nix2
-rw-r--r--nixos/modules/services/misc/rippled.nix78
-rw-r--r--nixos/modules/services/misc/svnserve.nix2
-rw-r--r--nixos/modules/services/misc/zookeeper.nix2
-rw-r--r--nixos/modules/services/monitoring/graphite.nix14
-rw-r--r--nixos/modules/services/monitoring/monit.nix13
-rw-r--r--nixos/modules/services/monitoring/nagios.nix2
-rw-r--r--nixos/modules/services/monitoring/smartd.nix3
-rw-r--r--nixos/modules/services/monitoring/ups.nix3
-rw-r--r--nixos/modules/services/network-filesystems/openafs-client/default.nix2
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix13
-rw-r--r--nixos/modules/services/network-filesystems/tahoe.nix260
-rw-r--r--nixos/modules/services/networking/bind.nix5
-rw-r--r--nixos/modules/services/networking/cjdns.nix6
-rw-r--r--nixos/modules/services/networking/connman.nix12
-rw-r--r--nixos/modules/services/networking/ddclient.nix17
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix2
-rw-r--r--nixos/modules/services/networking/flannel.nix153
-rw-r--r--nixos/modules/services/networking/gvpe.nix2
-rw-r--r--nixos/modules/services/networking/i2pd.nix55
-rw-r--r--nixos/modules/services/networking/nat.nix32
-rw-r--r--nixos/modules/services/networking/nsd.nix58
-rw-r--r--nixos/modules/services/networking/oidentd.nix2
-rw-r--r--nixos/modules/services/networking/openvpn.nix80
-rw-r--r--nixos/modules/services/networking/powerdns.nix1
-rw-r--r--nixos/modules/services/networking/prosody.nix3
-rw-r--r--nixos/modules/services/networking/radicale.nix6
-rw-r--r--nixos/modules/services/networking/softether.nix16
-rw-r--r--nixos/modules/services/networking/ssh/lshd.nix2
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix39
-rw-r--r--nixos/modules/services/networking/supplicant.nix205
-rw-r--r--nixos/modules/services/networking/tcpcrypt.nix2
-rw-r--r--nixos/modules/services/networking/tinc.nix174
-rw-r--r--nixos/modules/services/networking/wicd.nix4
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix4
-rw-r--r--nixos/modules/services/networking/xinetd.nix128
-rw-r--r--nixos/modules/services/networking/zerobin.nix6
-rw-r--r--nixos/modules/services/scheduling/chronos.nix2
-rw-r--r--nixos/modules/services/scheduling/marathon.nix2
-rw-r--r--nixos/modules/services/search/elasticsearch.nix2
-rw-r--r--nixos/modules/services/search/kibana.nix2
-rw-r--r--nixos/modules/services/security/oauth2_proxy.nix2
-rw-r--r--nixos/modules/services/system/dbus.nix58
-rw-r--r--nixos/modules/services/torrent/opentracker.nix44
-rw-r--r--nixos/modules/services/torrent/peerflix.nix2
-rw-r--r--nixos/modules/services/web-apps/selfoss.nix166
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/mediawiki.nix6
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/moodle.nix4
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/wordpress.nix12
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix19
-rw-r--r--nixos/modules/services/web-servers/phpfpm/default.nix24
-rw-r--r--nixos/modules/services/web-servers/tomcat.nix2
-rw-r--r--nixos/modules/services/web-servers/winstone.nix3
-rw-r--r--nixos/modules/services/web-servers/zope2.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4.nix37
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix9
-rw-r--r--nixos/modules/services/x11/display-managers/kdm.nix22
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix9
-rw-r--r--nixos/modules/services/x11/display-managers/slim.nix6
-rw-r--r--nixos/modules/services/x11/xserver.nix36
-rw-r--r--nixos/modules/system/activation/activation-script.nix9
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl40
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix88
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py111
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix2
-rw-r--r--nixos/modules/system/boot/luksroot.nix304
-rw-r--r--nixos/modules/system/boot/networkd.nix70
-rw-r--r--nixos/modules/system/boot/stage-1.nix25
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh10
-rw-r--r--nixos/modules/system/boot/systemd-lib.nix2
-rw-r--r--nixos/modules/system/boot/systemd.nix44
-rw-r--r--nixos/modules/system/etc/etc.nix6
-rw-r--r--nixos/modules/tasks/filesystems.nix7
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix74
-rw-r--r--nixos/modules/tasks/network-interfaces.nix512
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix2
-rw-r--r--nixos/modules/virtualisation/azure-common.nix2
-rw-r--r--nixos/modules/virtualisation/brightbox-image.nix2
-rw-r--r--nixos/modules/virtualisation/containers.nix172
-rw-r--r--nixos/modules/virtualisation/ec2-amis.nix52
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix2
-rw-r--r--nixos/modules/virtualisation/nova-image.nix2
120 files changed, 2472 insertions, 1549 deletions
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index aab5523c6848..fdc782b0579e 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -29,6 +29,19 @@ in
       '';
     };
 
+    networking.hostConf = lib.mkOption {
+      type = types.lines;
+      default = "multi on";
+      example = ''
+        multi on
+        reorder on
+        trim lan
+      '';
+      description = ''
+        The contents of <filename>/etc/host.conf</filename>. See also <citerefentry><refentrytitle>host.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+      '';
+    };
+
     networking.dnsSingleRequest = lib.mkOption {
       type = types.bool;
       default = false;
@@ -171,6 +184,9 @@ in
             ${cfg.extraHosts}
           '';
 
+        # /etc/host.conf: resolver configuration file
+        "host.conf".text = cfg.hostConf;
+
         # /etc/resolvconf.conf: Configuration for openresolv.
         "resolvconf.conf".text =
             ''
@@ -232,7 +248,7 @@ in
     # and other configurations. If the file is destroyed by an environment
     # activation then it must be rebuilt so that applications which interface
     # with /etc/resolv.conf directly don't break.
-    system.activationScripts.resolvconf = stringAfter [ "etc" "tmpfs" "var" ]
+    system.activationScripts.resolvconf = stringAfter [ "etc" "specialfs" "var" ]
       ''
         # Systemd resolved controls its own resolv.conf
         rm -f /run/resolvconf/interfaces/systemd
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index d92deb85d2a5..57e4940378ba 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -131,13 +131,12 @@ let
       };
 
       subUidRanges = mkOption {
-        type = types.listOf types.optionSet;
+        type = with types; listOf (submodule subordinateUidRange);
         default = [];
         example = [
           { startUid = 1000; count = 1; }
           { startUid = 100001; count = 65534; }
         ];
-        options = [ subordinateUidRange ];
         description = ''
           Subordinate user ids that user is allowed to use.
           They are set into <filename>/etc/subuid</filename> and are used
@@ -146,13 +145,12 @@ let
       };
 
       subGidRanges = mkOption {
-        type = types.listOf types.optionSet;
+        type = with types; listOf (submodule subordinateGidRange);
         default = [];
         example = [
           { startGid = 100; count = 1; }
           { startGid = 1001; count = 999; }
         ];
-        options = [ subordinateGidRange ];
         description = ''
           Subordinate group ids that user is allowed to use.
           They are set into <filename>/etc/subgid</filename> and are used
@@ -310,32 +308,36 @@ let
   };
 
   subordinateUidRange = {
-    startUid = mkOption {
-      type = types.int;
-      description = ''
-        Start of the range of subordinate user ids that user is
-        allowed to use.
-      '';
-    };
-    count = mkOption {
-      type = types.int;
-      default = 1;
-      description = ''Count of subordinate user ids'';
+    options = {
+      startUid = mkOption {
+        type = types.int;
+        description = ''
+          Start of the range of subordinate user ids that user is
+          allowed to use.
+        '';
+      };
+      count = mkOption {
+        type = types.int;
+        default = 1;
+        description = ''Count of subordinate user ids'';
+      };
     };
   };
 
   subordinateGidRange = {
-    startGid = mkOption {
-      type = types.int;
-      description = ''
-        Start of the range of subordinate group ids that user is
-        allowed to use.
-      '';
-    };
-    count = mkOption {
-      type = types.int;
-      default = 1;
-      description = ''Count of subordinate group ids'';
+    options = {
+      startGid = mkOption {
+        type = types.int;
+        description = ''
+          Start of the range of subordinate group ids that user is
+          allowed to use.
+        '';
+      };
+      count = mkOption {
+        type = types.int;
+        default = 1;
+        description = ''Count of subordinate group ids'';
+      };
     };
   };
 
@@ -428,7 +430,7 @@ in {
 
     users.users = mkOption {
       default = {};
-      type = types.loaOf types.optionSet;
+      type = with types; loaOf (submodule userOpts);
       example = {
         alice = {
           uid = 1234;
@@ -444,7 +446,6 @@ in {
         Additional user accounts to be created automatically by the system.
         This can also be used to set options for root.
       '';
-      options = [ userOpts ];
     };
 
     users.groups = mkOption {
@@ -453,11 +454,10 @@ in {
         { students.gid = 1001;
           hackers = { };
         };
-      type = types.loaOf types.optionSet;
+      type = with types; loaOf (submodule groupOpts);
       description = ''
         Additional groups to be created automatically by the system.
       '';
-      options = [ groupOpts ];
     };
 
     # FIXME: obsolete - will remove.
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index 0bc574d48190..bef500e30c0b 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -14,7 +14,7 @@ let
     name = "mesa-drivers+txc-${p.mesa_drivers.version}";
     paths =
       [ p.mesa_drivers
-        p.mesa_noglu # mainly for libGL
+        p.mesa_drivers.out # mainly for libGL
         (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc)
       ];
   };
diff --git a/nixos/modules/i18n/input-method/default.nix b/nixos/modules/i18n/input-method/default.nix
index 693e1df66c6c..7ed4a584d646 100644
--- a/nixos/modules/i18n/input-method/default.nix
+++ b/nixos/modules/i18n/input-method/default.nix
@@ -3,26 +3,27 @@
 with lib;
 let
   cfg = config.i18n.inputMethod;
-  gtk2_cache = pkgs.stdenv.mkDerivation {
-    preferLocalBuild = true; 
-    allowSubstitutes = false;
-    name = "gtk2-immodule.cache";
-    buildInputs = [ pkgs.gtk2 cfg.package ];
-    buildCommand = ''
+
+  gtk2_cache = pkgs.runCommand "gtk2-immodule.cache"
+    { preferLocalBuild = true;
+      allowSubstitutes = false;
+      buildInputs = [ pkgs.gtk2 cfg.package ];
+    }
+    ''
       mkdir -p $out/etc/gtk-2.0/
       GTK_PATH=${cfg.package}/lib/gtk-2.0/ gtk-query-immodules-2.0 > $out/etc/gtk-2.0/immodules.cache
     '';
-  };
-  gtk3_cache = pkgs.stdenv.mkDerivation {
-    preferLocalBuild = true; 
-    allowSubstitutes = false;
-    name = "gtk3-immodule.cache";
-    buildInputs = [ pkgs.gtk3 cfg.package ];
-    buildCommand = ''
+
+  gtk3_cache = pkgs.runCommand "gtk3-immodule.cache"
+    { preferLocalBuild = true;
+      allowSubstitutes = false;
+      buildInputs = [ pkgs.gtk3 cfg.package ];
+    }
+    ''
       mkdir -p $out/etc/gtk-3.0/
       GTK_PATH=${cfg.package}/lib/gtk-3.0/ gtk-query-immodules-3.0 > $out/etc/gtk-3.0/immodules.cache
     '';
-  };
+
 in
 {
   options.i18n = {
diff --git a/nixos/modules/i18n/input-method/default.xml b/nixos/modules/i18n/input-method/default.xml
index a32ed100df30..45d6daf068b3 100644
--- a/nixos/modules/i18n/input-method/default.xml
+++ b/nixos/modules/i18n/input-method/default.xml
@@ -56,8 +56,18 @@ i18n.inputMethod = {
   <listitem><para>Table (<literal>ibus-engines.table</literal>): An input method 
       that load tables of input methods.</para></listitem>
   <listitem><para>table-others (<literal>ibus-engines.table-others</literal>): 
-      Various table-based input methods.</para></listitem>
+      Various table-based input methods. To use this, and any other table-based
+      input methods, it must appear in the list of engines along with
+      <literal>table</literal>. For example:
+<programlisting>
+ibus.engines = with pkgs.ibus-engines; [ table table-others ];
+</programlisting>
+  </para></listitem>
 </itemizedlist>
+
+<para>To use any input method, the package must be added in the configuration,
+  as shown above, and also (after running <literal>nixos-rebuild</literal>) the
+  input method must be added from IBus' preference dialog.</para>
 </section>
 
 <section><title>Fcitx</title>
diff --git a/nixos/modules/i18n/input-method/ibus.nix b/nixos/modules/i18n/input-method/ibus.nix
index d64cf2f283bf..e23e28aa25ef 100644
--- a/nixos/modules/i18n/input-method/ibus.nix
+++ b/nixos/modules/i18n/input-method/ibus.nix
@@ -17,7 +17,7 @@ let
       [Desktop Entry]
       Name=IBus
       Type=Application
-      Exec=${ibusPackage}/bin/ibus-daemon --daemonize --xim --cache=refresh
+      Exec=${ibusPackage}/bin/ibus-daemon --daemonize --xim
     '';
   };
 in
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix
index d14768bc1079..b5ee57d9e22e 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix
@@ -96,15 +96,16 @@ with lib;
     '';
 
   in
-    pkgs.stdenv.mkDerivation {
-      inherit (pkg) name meta;
-
-      buildCommand = ''
+    pkgs.runCommand pkg.name
+      { inherit (pkg) meta; }
+      ''
         mkdir -p $out
         cp -prf ${pkg}/* $out/
         chmod a+w $out/share/apps/plasma-desktop/init
         cp -f ${plasmaInit} $out/share/apps/plasma-desktop/init/00-defaultLayout.js
       '';
-    };
+
+  # Disable large stuff that's not very useful on the installation CD.
+  services.xserver.desktopManager.kde4.enablePIM = false;
 
 }
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index 0a452b86018a..da28c027c563 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -259,7 +259,7 @@ chroot $mountPoint /nix/var/nix/profiles/system/activate
 
 
 # Ask the user to set a root password.
-if [ -z "$noRootPasswd" ] && [ -x $mountPoint/var/setuid-wrappers/passwd ] && [ -t 0 ]; then
+if [ -z "$noRootPasswd" ] && chroot $mountPoint [ -x /var/setuid-wrappers/passwd ] && [ -t 0 ]; then
     echo "setting root password..."
     chroot $mountPoint /var/setuid-wrappers/passwd
 fi
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 13a7323e858e..2881d843760d 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -119,7 +119,6 @@
       minidlna = 91;
       elasticsearch = 92;
       tcpcryptd = 93; # tcpcryptd uses a hard-coded uid. We patch it in Nixpkgs to match this choice.
-      #connman = 94; # unused
       firebird = 95;
       #keys = 96; # unused
       haproxy = 97;
@@ -275,6 +274,8 @@
       mattermost = 254;
       prometheus = 255;
       telegraf = 256;
+      gitlab-runner = 257;
+      postgrey = 258;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -376,7 +377,6 @@
       minidlna = 91;
       elasticsearch = 92;
       #tcpcryptd = 93; # unused
-      connman = 94;
       firebird = 95;
       keys = 96;
       haproxy = 97;
@@ -520,6 +520,8 @@
       mattermost = 254;
       prometheus = 255;
       #telegraf = 256; # unused
+      gitlab-runner = 257;
+      postgrey = 258;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 07da64c63847..d1a786d8f629 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -70,6 +70,7 @@
   ./programs/fish.nix
   ./programs/freetds.nix
   ./programs/info.nix
+  ./programs/java.nix
   ./programs/kbdlight.nix
   ./programs/light.nix
   ./programs/man.nix
@@ -133,6 +134,7 @@
   ./services/computing/slurm/slurm.nix
   ./services/continuous-integration/buildkite-agent.nix
   ./services/continuous-integration/hydra/default.nix
+  ./services/continuous-integration/gitlab-runner.nix
   ./services/continuous-integration/gocd-agent/default.nix
   ./services/continuous-integration/gocd-server/default.nix
   ./services/continuous-integration/jenkins/default.nix
@@ -210,10 +212,12 @@
   ./services/mail/freepops.nix
   ./services/mail/mail.nix
   ./services/mail/mlmmj.nix
+  ./services/mail/offlineimap.nix
   ./services/mail/opendkim.nix
   ./services/mail/opensmtpd.nix
   ./services/mail/postfix.nix
   ./services/mail/postsrsd.nix
+  ./services/mail/postgrey.nix
   ./services/mail/spamassassin.nix
   ./services/mail/rspamd.nix
   ./services/mail/rmilter.nix
@@ -343,6 +347,7 @@
   ./services/networking/ferm.nix
   ./services/networking/firefox/sync-server.nix
   ./services/networking/firewall.nix
+  ./services/networking/flannel.nix
   ./services/networking/flashpolicyd.nix
   ./services/networking/freenet.nix
   ./services/networking/gale.nix
@@ -382,7 +387,6 @@
   ./services/networking/ntopng.nix
   ./services/networking/ntpd.nix
   ./services/networking/nylon.nix
-  ./services/networking/offlineimap.nix
   ./services/networking/oidentd.nix
   ./services/networking/openfire.nix
   ./services/networking/openntpd.nix
@@ -469,6 +473,7 @@
   ./services/system/uptimed.nix
   ./services/torrent/deluge.nix
   ./services/torrent/flexget.nix
+  ./services/torrent/opentracker.nix
   ./services/torrent/peerflix.nix
   ./services/torrent/transmission.nix
   ./services/ttys/agetty.nix
@@ -477,6 +482,7 @@
   ./services/web-apps/mattermost.nix
   ./services/web-apps/pump.io.nix
   ./services/web-apps/tt-rss.nix
+  ./services/web-apps/selfoss.nix
   ./services/web-servers/apache-httpd/default.nix
   ./services/web-servers/caddy.nix
   ./services/web-servers/fcgiwrap.nix
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index c09bcfb70e24..e23849d350b4 100644
--- a/nixos/modules/programs/bash/bash.nix
+++ b/nixos/modules/programs/bash/bash.nix
@@ -16,7 +16,7 @@ let
     # programmable completion. If we do, enable all modules installed in
     # the system (and user profile).
     if shopt -q progcomp &>/dev/null; then
-      . "${pkgs.bashCompletion}/etc/profile.d/bash_completion.sh"
+      . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
       nullglobStatus=$(shopt -p nullglob)
       shopt -s nullglob
       for p in $NIX_PROFILES; do
diff --git a/nixos/modules/programs/java.nix b/nixos/modules/programs/java.nix
new file mode 100644
index 000000000000..3292aa369d28
--- /dev/null
+++ b/nixos/modules/programs/java.nix
@@ -0,0 +1,57 @@
+# This module provides JAVA_HOME, with a different way to install java
+# system-wide.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.java;
+in
+
+{
+
+  options = {
+
+    programs.java = {
+
+      enable = mkEnableOption "java" // {
+        description = ''
+          Install and setup the Java development kit.
+          <note>
+          <para>This adds JAVA_HOME to the global environment, by sourcing the
+            jdk's setup-hook on shell init. It is equivalent to starting a shell
+            through 'nix-shell -p jdk', or roughly the following system-wide
+            configuration:
+          </para>
+          <programlisting>
+            environment.variables.JAVA_HOME = ''${pkgs.jdk.home}/lib/openjdk;
+            environment.systemPackages = [ pkgs.jdk ];
+          </programlisting>
+          </note>
+        '';
+      };
+
+      package = mkOption {
+        default = pkgs.jdk;
+        description = ''
+          Java package to install. Typical values are pkgs.jdk or pkgs.jre.
+        '';
+        type = types.package;
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ cfg.package ];
+
+    environment.shellInit = ''
+      test -e ${cfg.package}/nix-support/setup-hook && source ${cfg.package}/nix-support/setup-hook
+    '';
+
+  };
+
+}
diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix
index 91cd84416921..5b7d94157454 100644
--- a/nixos/modules/programs/zsh/zsh.nix
+++ b/nixos/modules/programs/zsh/zsh.nix
@@ -84,6 +84,14 @@ in
         type = types.bool;
       };
 
+      enableSyntaxHighlighting = mkOption {
+        default = false;
+        description = ''
+          Enable zsh-syntax-highlighting
+        '';
+        type = types.bool;
+      };
+
     };
 
   };
@@ -102,9 +110,9 @@ in
 
       interactiveShellInit = ''
         # history defaults
-        export SAVEHIST=2000
-        export HISTSIZE=2000
-        export HISTFILE=$HOME/.zsh_history
+        SAVEHIST=2000
+        HISTSIZE=2000
+        HISTFILE=$HOME/.zsh_history
 
         setopt HIST_IGNORE_DUPS SHARE_HISTORY HIST_FCNTL_LOCK
 
@@ -120,6 +128,10 @@ in
 
         ${if cfg.enableCompletion then "autoload -U compinit && compinit" else ""}
 
+        ${optionalString (cfg.enableSyntaxHighlighting)
+          "source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
+        }
+
         HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
       '';
 
@@ -182,7 +194,8 @@ in
     environment.etc."zinputrc".source = ./zinputrc;
 
     environment.systemPackages = [ pkgs.zsh ]
-      ++ optional cfg.enableCompletion pkgs.nix-zsh-completions;
+      ++ optional cfg.enableCompletion pkgs.nix-zsh-completions
+      ++ optional cfg.enableSyntaxHighlighting pkgs.zsh-syntax-highlighting;
 
     environment.pathsToLink = optional cfg.enableCompletion "/share/zsh";
 
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index e597cec6b32d..9abe7d450c93 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -153,7 +153,7 @@ with lib;
     (mkRemovedOptionModule [ "services" "printing" "cupsFilesConf" ] "")
     (mkRemovedOptionModule [ "services" "printing" "cupsdConf" ] "")
     (mkRemovedOptionModule [ "services" "xserver" "startGnuPGAgent" ]
-      "See the 16.03 release notes for more information.")
+      "See the 16.09 release notes for more information.")
     (mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "")
     (mkRemovedOptionModule [ "services" "dovecot2" "package" ] "")
     (mkRemovedOptionModule [ "services" "dockerRegistry" ]
diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index 45e8f64046b0..12736e57b4a6 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -129,11 +129,10 @@ in
 
       certs = mkOption {
         default = { };
-        type = types.loaOf types.optionSet;
+        type = with types; loaOf (submodule certOpts);
         description = ''
           Attribute set of certificates to get signed and renewed.
         '';
-        options = [ certOpts ];
         example = {
           "example.com" = {
             webroot = "/var/www/challenges/";
@@ -283,6 +282,7 @@ in
           timerConfig = {
             OnCalendar = cfg.renewInterval;
             Unit = "acme-${cert}.service";
+            Persistent = "yes";
           };
         })
       );
diff --git a/nixos/modules/security/grsecurity.xml b/nixos/modules/security/grsecurity.xml
index 28415e89bfab..37314bdba8a5 100644
--- a/nixos/modules/security/grsecurity.xml
+++ b/nixos/modules/security/grsecurity.xml
@@ -149,6 +149,10 @@
 
         <listitem><para>Trusted path execution: a desirable feature, but
         requires some more work to operate smoothly on NixOS.</para></listitem>
+
+        <listitem><para>Module hardening: would break user initiated module
+        loading. Might enable this at some point, depending on the potential
+        breakage.</para></listitem>
       </itemizedlist>
     </para></listitem>
 
@@ -208,8 +212,6 @@
         let
           kernel = pkgs.linux_grsec_nixos.override {
             extraConfig = ''
-              GRKERNSEC y
-              PAX y
               GRKERNSEC_CONFIG_AUTO y
               GRKERNSEC_CONFIG_SERVER y
               GRKERNSEC_CONFIG_SECURITY y
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 814dd21b53de..f9aa4136c8d6 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -386,8 +386,7 @@ in
 
     security.pam.services = mkOption {
       default = [];
-      type = types.loaOf types.optionSet;
-      options = [ pamOpts ];
+      type = with types; loaOf (submodule pamOpts);
       description =
         ''
           This option defines the PAM services.  A service typically
diff --git a/nixos/modules/services/backup/bacula.nix b/nixos/modules/services/backup/bacula.nix
index 8a26aae75fe9..ef8e5e55edef 100644
--- a/nixos/modules/services/backup/bacula.nix
+++ b/nixos/modules/services/backup/bacula.nix
@@ -198,8 +198,7 @@ in {
         description = ''
           This option defines director resources in Bacula File Daemon.
         '';
-        type = types.attrsOf types.optionSet;
-        options = [ directorOptions ];
+        type = with types; attrsOf (submodule directorOptions);
       };
 
       extraClientConfig = mkOption {
@@ -253,8 +252,7 @@ in {
         description = ''
           This option defines Director resources in Bacula Storage Daemon.
         '';
-        type = types.attrsOf types.optionSet;
-        options = [ directorOptions ];
+        type = with types; attrsOf (submodule directorOptions);
       };
 
       device = mkOption {
@@ -262,8 +260,7 @@ in {
         description = ''
           This option defines Device resources in Bacula Storage Daemon.
         '';
-        type = types.attrsOf types.optionSet;
-        options = [ deviceOptions ];
+        type = with types; attrsOf (submodule deviceOptions);
       };
  
       extraStorageConfig = mkOption {
diff --git a/nixos/modules/services/backup/rsnapshot.nix b/nixos/modules/services/backup/rsnapshot.nix
index ce628a720363..16815bcc8605 100644
--- a/nixos/modules/services/backup/rsnapshot.nix
+++ b/nixos/modules/services/backup/rsnapshot.nix
@@ -7,11 +7,14 @@ let
   cfgfile = pkgs.writeText "rsnapshot.conf" ''
     config_version	1.2
     cmd_cp	${pkgs.coreutils}/bin/cp
+    cmd_rm	${pkgs.coreutils}/bin/rm
     cmd_rsync	${pkgs.rsync}/bin/rsync
     cmd_ssh	${pkgs.openssh}/bin/ssh
     cmd_logger	${pkgs.inetutils}/bin/logger
     cmd_du	${pkgs.coreutils}/bin/du
+    cmd_rsnapshot_diff	${pkgs.rsnapshot}/bin/rsnapshot-diff
     lockfile	/run/rsnapshot.pid
+    link_dest	1
 
     ${cfg.extraConfig}
   '';
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index 42efde36678f..4bdd7f95f774 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -421,7 +421,7 @@ in {
         description = "Kubernetes Api Server";
         wantedBy = [ "multi-user.target" ];
         requires = ["kubernetes-setup.service"];
-        after = [ "network-interfaces.target" "etcd.service" ];
+        after = [ "network.target" "etcd.service" "kubernetes-setup.service" ];
         serviceConfig = {
           ExecStart = let
             authorizationPolicyFile =
@@ -468,7 +468,7 @@ in {
       systemd.services.kube-scheduler = {
         description = "Kubernetes Scheduler Service";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" "kubernetes-apiserver.service" ];
+        after = [ "network.target" "kubernetes-apiserver.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-scheduler \
             --address=${cfg.scheduler.address} \
@@ -487,7 +487,7 @@ in {
       systemd.services.kube-controller-manager = {
         description = "Kubernetes Controller Manager Service";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" "kubernetes-apiserver.service" ];
+        after = [ "network.target" "kubernetes-apiserver.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-controller-manager \
             --address=${cfg.controllerManager.address} \
@@ -511,7 +511,7 @@ in {
         description = "Kubernetes Kubelet Service";
         wantedBy = [ "multi-user.target" ];
         requires = ["kubernetes-setup.service"];
-        after = [ "network-interfaces.target" "etcd.service" "docker.service" ];
+        after = [ "network.target" "etcd.service" "docker.service" "kubernetes-setup.service" ];
         path = [ pkgs.gitMinimal pkgs.openssh ];
         script = ''
           export PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH"
@@ -542,7 +542,7 @@ in {
       systemd.services.kube-proxy = {
         description = "Kubernetes Proxy Service";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" "etcd.service" ];
+        after = [ "network.target" "etcd.service" ];
         serviceConfig = {
           ExecStart = ''${cfg.package}/bin/kube-proxy \
             --master=${cfg.proxy.master} \
diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix
new file mode 100644
index 000000000000..1fe4d28f9f35
--- /dev/null
+++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -0,0 +1,51 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.gitlab-runner;
+  configFile = pkgs.writeText "config.toml" cfg.configText;
+in
+{
+  options.services.gitlab-runner = {
+    enable = mkEnableOption "Gitlab Runner";
+
+    configText = mkOption {
+      description = "Verbatim config.toml to use";
+    };
+
+    workDir = mkOption {
+      default = "/var/lib/gitlab-runner";
+      type = types.path;
+      description = "The working directory used";
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.gitlab-runner = {
+      description = "Gitlab Runner";
+      after = [ "network.target" "docker.service" ];
+      requires = [ "docker.service" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = ''${pkgs.gitlab-runner.bin}/bin/gitlab-runner run \
+          --working-directory ${cfg.workDir} \
+          --config ${configFile} \
+          --service gitlab-runner \
+          --user gitlab-runner \
+        '';
+      };
+    };
+
+    users.extraUsers.gitlab-runner = {
+      group = "gitlab-runner";
+      extraGroups = [ "docker" ];
+      uid = config.ids.uids.gitlab-runner;
+      home = cfg.workDir;
+      createHome = true;
+    };
+
+    users.extraGroups.gitlab-runner.gid = config.ids.gids.gitlab-runner;
+  };
+}
diff --git a/nixos/modules/services/databases/cassandra.nix b/nixos/modules/services/databases/cassandra.nix
index c98af617587d..b43b448ed7e1 100644
--- a/nixos/modules/services/databases/cassandra.nix
+++ b/nixos/modules/services/databases/cassandra.nix
@@ -377,7 +377,7 @@ in {
     systemd.services.cassandra = {
       description = "Cassandra Daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       environment = cassandraEnvironment;
       restartTriggers = [ cassandraConfFile cassandraLogFile cassandraRackFile ];
       serviceConfig = {
diff --git a/nixos/modules/services/databases/influxdb.nix b/nixos/modules/services/databases/influxdb.nix
index 11ea0e1b6b41..dd88624f406c 100644
--- a/nixos/modules/services/databases/influxdb.nix
+++ b/nixos/modules/services/databases/influxdb.nix
@@ -160,7 +160,7 @@ in
     systemd.services.influxdb = {
       description = "InfluxDB Server";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       serviceConfig = {
         ExecStart = ''${cfg.package}/bin/influxd -config "${configFile}"'';
         User = "${cfg.user}";
diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
index 41b960685906..146a604adb2f 100644
--- a/nixos/modules/services/databases/neo4j.nix
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -123,7 +123,7 @@ in {
     systemd.services.neo4j = {
       description = "Neo4j Daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       environment = { NEO4J_INSTANCE = cfg.dataDir; };
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/neo4j console";
diff --git a/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix b/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix
index 3ec74458cd29..1923addeb3ac 100644
--- a/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix
+++ b/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix
@@ -81,12 +81,11 @@ in
         { office1 = { model = "MFC-7860DW"; ip = "192.168.1.2"; };
           office2 = { model = "MFC-7860DW"; nodename = "BRW0080927AFBCE"; };
         };
-      type = types.loaOf types.optionSet;
+      type = with types; loaOf (submodule netDeviceOpts);
       description = ''
         The list of network devices that will be registered against the brscan4
         sane backend.
       '';
-      options = [ netDeviceOpts ];
     };
   };
 
@@ -113,4 +112,4 @@ in
     ];
 
   };
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 7c4c93d0fcb3..14d65978c320 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -32,13 +32,11 @@ let
   '';
 
   # Perform substitutions in all udev rules files.
-  udevRules = stdenv.mkDerivation {
-    name = "udev-rules";
-
-    preferLocalBuild = true;
-    allowSubstitutes = false;
-
-    buildCommand = ''
+  udevRules = pkgs.runCommand "udev-rules"
+    { preferLocalBuild = true;
+      allowSubstitutes = false;
+    }
+    ''
       mkdir -p $out
       shopt -s nullglob
       set +o pipefail
@@ -130,15 +128,12 @@ let
         ln -s /dev/null $out/80-drivers.rules
       ''}
     ''; # */
-  };
 
-  hwdbBin = stdenv.mkDerivation {
-    name = "hwdb.bin";
-
-    preferLocalBuild = true;
-    allowSubstitutes = false;
-
-    buildCommand = ''
+  hwdbBin = pkgs.runCommand "hwdb.bin"
+    { preferLocalBuild = true;
+      allowSubstitutes = false;
+    }
+    ''
       mkdir -p etc/udev/hwdb.d
       for i in ${toString ([udev] ++ cfg.packages)}; do
         echo "Adding hwdb files for package $i"
@@ -151,7 +146,6 @@ let
       ${udev}/bin/udevadm hwdb --update --root=$(pwd)
       mv etc/udev/hwdb.bin $out
     '';
-  };
 
   # Udev has a 512-character limit for ENV{PATH}, so create a symlink
   # tree to work around this.
diff --git a/nixos/modules/services/logging/logcheck.nix b/nixos/modules/services/logging/logcheck.nix
index 3a85fa60fe7a..a8a214b21550 100644
--- a/nixos/modules/services/logging/logcheck.nix
+++ b/nixos/modules/services/logging/logcheck.nix
@@ -62,42 +62,46 @@ let
   };
 
   ignoreOptions = {
-    level = levelOption;
+    options = {
+      level = levelOption;
 
-    regex = mkOption {
-      default = "";
-      type = types.str;
-      description = ''
-        Regex specifying which log lines to ignore.
-      '';
+      regex = mkOption {
+        default = "";
+        type = types.str;
+        description = ''
+          Regex specifying which log lines to ignore.
+        '';
+      };
     };
   };
 
   ignoreCronOptions = {
-    user = mkOption {
-      default = "root";
-      type = types.str;
-      description = ''
-        User that runs the cronjob.
-      '';
-    };
+    options = {
+      user = mkOption {
+        default = "root";
+        type = types.str;
+        description = ''
+          User that runs the cronjob.
+        '';
+      };
 
-    cmdline = mkOption {
-      default = "";
-      type = types.str;
-      description = ''
-        Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
-      '';
-    };
+      cmdline = mkOption {
+        default = "";
+        type = types.str;
+        description = ''
+          Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
+        '';
+      };
 
-    timeArgs = mkOption {
-      default = null;
-      type = types.nullOr (types.str);
-      example = "02 06 * * *";
-      description = ''
-        "min hr dom mon dow" crontab time args, to auto-create a cronjob too.
-        Leave at null to not do this and just add a logcheck ignore rule.
-      '';
+      timeArgs = mkOption {
+        default = null;
+        type = types.nullOr (types.str);
+        example = "02 06 * * *";
+        description = ''
+          "min hr dom mon dow" crontab time args, to auto-create a cronjob too.
+          Leave at null to not do this and just add a logcheck ignore rule.
+        '';
+      };
     };
   };
 
@@ -180,8 +184,7 @@ in
         description = ''
           This option defines extra ignore rules.
         '';
-        type = types.loaOf types.optionSet;
-        options = [ ignoreOptions ];
+        type = with types; loaOf (submodule ignoreOptions);
       };
 
       ignoreCron = mkOption {
@@ -189,8 +192,7 @@ in
         description = ''
           This option defines extra ignore rules for cronjobs.
         '';
-        type = types.loaOf types.optionSet;
-        options = [ ignoreOptions ignoreCronOptions ];
+        type = with types; loaOf (submodule ignoreCronOptions);
       };
 
       extraGroups = mkOption {
diff --git a/nixos/modules/services/networking/offlineimap.nix b/nixos/modules/services/mail/offlineimap.nix
index daf6196d3706..85ece020905b 100644
--- a/nixos/modules/services/networking/offlineimap.nix
+++ b/nixos/modules/services/mail/offlineimap.nix
@@ -59,7 +59,7 @@ in {
       };
       path = cfg.path;
     };
-    environment.systemPackages = [ "${cfg.package}" ];
+    environment.systemPackages = [ cfg.package ];
     systemd.user.timers.offlineimap = {
       description = "offlineimap timer";
       timerConfig               = {
diff --git a/nixos/modules/services/mail/postgrey.nix b/nixos/modules/services/mail/postgrey.nix
new file mode 100644
index 000000000000..0db631868cc7
--- /dev/null
+++ b/nixos/modules/services/mail/postgrey.nix
@@ -0,0 +1,79 @@
+{ config, lib, pkgs, ... }:
+
+with lib; let
+
+  cfg = config.services.postgrey;
+
+in {
+
+  options = {
+    services.postgrey = with types; {
+      enable = mkOption {
+        type = bool;
+        default = false;
+        description = "Whether to run the Postgrey daemon";
+      };
+      inetAddr = mkOption {
+        type = nullOr string;
+        default = null;
+        example = "127.0.0.1";
+        description = "The inet address to bind to. If none given, bind to /var/run/postgrey.sock";
+      };
+      inetPort = mkOption {
+        type = int;
+        default = 10030;
+        description = "The tcp port to bind to";
+      };
+      greylistText = mkOption {
+        type = string;
+        default = "Greylisted for %%s seconds";
+        description = "Response status text for greylisted messages";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.postgrey ];
+
+    users = {
+      extraUsers = {
+        postgrey = {
+          description = "Postgrey Daemon";
+          uid = config.ids.uids.postgrey;
+          group = "postgrey";
+        };
+      };
+      extraGroups = {
+        postgrey = {
+          gid = config.ids.gids.postgrey;
+        };
+      };
+    };
+
+    systemd.services.postgrey = let
+      bind-flag = if isNull cfg.inetAddr then
+        "--unix=/var/run/postgrey.sock"
+      else
+        "--inet=${cfg.inetAddr}:${cfg.inetPort}";
+    in {
+      description = "Postfix Greylisting Service";
+      wantedBy = [ "multi-user.target" ];
+      before = [ "postfix.service" ];
+      preStart = ''
+        mkdir -p /var/postgrey
+        chown postgrey:postgrey /var/postgrey
+        chmod 0770 /var/postgrey
+      '';
+      serviceConfig = {
+        Type = "simple";
+        ExecStart = ''${pkgs.postgrey}/bin/postgrey ${bind-flag} --pidfile=/var/run/postgrey.pid --group=postgrey --user=postgrey --dbdir=/var/postgrey --greylist-text="${cfg.greylistText}"'';
+        Restart = "always";
+        RestartSec = 5;
+        TimeoutSec = 10;
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/misc/apache-kafka.nix b/nixos/modules/services/misc/apache-kafka.nix
index 88ce8b5a23fc..c856d3294c01 100644
--- a/nixos/modules/services/misc/apache-kafka.nix
+++ b/nixos/modules/services/misc/apache-kafka.nix
@@ -139,7 +139,7 @@ in {
     systemd.services.apache-kafka = {
       description = "Apache Kafka Daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       serviceConfig = {
         ExecStart = ''
           ${pkgs.jre}/bin/java \
diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix
index 72ec68dee6b3..fe13013286b8 100644..100755
--- a/nixos/modules/services/misc/confd.nix
+++ b/nixos/modules/services/misc/confd.nix
@@ -33,7 +33,7 @@ in {
 
     nodes = mkOption {
       description = "Confd list of nodes to connect to.";
-      default = [ "http://127.0.0.1:4001" ];
+      default = [ "http://127.0.0.1:2379" ];
       type = types.listOf types.str;
     };
 
diff --git a/nixos/modules/services/misc/emby.nix b/nixos/modules/services/misc/emby.nix
index fe872349f45e..9f290ed70c97 100644
--- a/nixos/modules/services/misc/emby.nix
+++ b/nixos/modules/services/misc/emby.nix
@@ -43,7 +43,7 @@ in
         User = cfg.user;
         Group = cfg.group;
         PermissionsStartOnly = "true";
-        ExecStart = "${pkgs.mono}/bin/mono ${pkgs.emby}/bin/MediaBrowser.Server.Mono.exe";
+        ExecStart = "${pkgs.emby}/bin/MediaBrowser.Server.Mono";
         Restart = "on-failure";
       };
     };
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index d30cc5fd7e89..1de02d76ba0a 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -143,9 +143,9 @@ in {
 
   config = mkIf cfg.enable {
     systemd.services.etcd = {
-      description = "Etcd Daemon";
+      description = "etcd key-value store";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
 
       environment = (filterAttrs (n: v: v != null) {
         ETCD_NAME = cfg.name;
@@ -168,12 +168,18 @@ in {
         ETCD_INITIAL_CLUSTER_TOKEN = cfg.initialClusterToken;
       }) // (mapAttrs' (n: v: nameValuePair "ETCD_${n}" v) cfg.extraConf);
 
+      unitConfig = {
+        Documentation = "https://github.com/coreos/etcd";
+      };
+
       serviceConfig = {
         Type = "notify";
         ExecStart = "${pkgs.etcd.bin}/bin/etcd";
         User = "etcd";
         PermissionsStartOnly = true;
+        LimitNOFILE = 40000;
       };
+
       preStart = ''
         mkdir -m 0700 -p ${cfg.dataDir}
         if [ "$(id -u)" = 0 ]; then chown etcd ${cfg.dataDir}; fi
diff --git a/nixos/modules/services/misc/folding-at-home.nix b/nixos/modules/services/misc/folding-at-home.nix
index 4f09cbfdd79b..053e7e95635f 100644
--- a/nixos/modules/services/misc/folding-at-home.nix
+++ b/nixos/modules/services/misc/folding-at-home.nix
@@ -50,7 +50,7 @@ in {
       };
 
     systemd.services.foldingathome = {
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart = ''
         mkdir -m 0755 -p ${stateDir}
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index de90d461f527..f8881233dceb 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -449,13 +449,15 @@ in {
         Group = cfg.group;
         TimeoutSec = "300";
         Restart = "on-failure";
+        WorkingDirectory = gitlabEnv.HOME;
         ExecStart =
           "${cfg.packages.gitlab-workhorse}/bin/gitlab-workhorse "
           + "-listenUmask 0 "
           + "-listenNetwork unix "
           + "-listenAddr /run/gitlab/gitlab-workhorse.socket "
           + "-authSocket ${gitlabSocket} "
-          + "-documentRoot ${cfg.packages.gitlab}/share/gitlab/public";
+          + "-documentRoot ${cfg.packages.gitlab}/share/gitlab/public "
+          + "-secretPath ${cfg.packages.gitlab}/share/gitlab/.gitlab_workhorse_secret";
       };
     };
 
@@ -525,11 +527,6 @@ in {
             psql postgres -c "CREATE ROLE gitlab WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'"
             ${config.services.postgresql.package}/bin/createdb --owner gitlab gitlab || true
             touch "${cfg.statePath}/db-created"
-
-            # The gitlab:setup task is horribly broken somehow, these two tasks will do the same for setting up the initial database
-            ${gitlab-rake}/bin/gitlab-rake db:migrate RAILS_ENV=production
-            ${gitlab-rake}/bin/gitlab-rake db:seed_fu RAILS_ENV=production \
-              GITLAB_ROOT_PASSWORD="${cfg.initialRootPassword}" GITLAB_ROOT_EMAIL="${cfg.initialRootEmail}";
           fi
         fi
 
@@ -538,6 +535,15 @@ in {
         # Always do the db migrations just to be sure the database is up-to-date
         ${gitlab-rake}/bin/gitlab-rake db:migrate RAILS_ENV=production
 
+        # The gitlab:setup task is horribly broken somehow, the db:migrate
+        # task above and the db:seed_fu below will do the same for setting
+        # up the initial database
+        if ! test -e "${cfg.statePath}/db-seeded"; then
+          ${gitlab-rake}/bin/gitlab-rake db:seed_fu RAILS_ENV=production \
+            GITLAB_ROOT_PASSWORD="${cfg.initialRootPassword}" GITLAB_ROOT_EMAIL="${cfg.initialRootEmail}"
+          touch "${cfg.statePath}/db-seeded"
+        fi
+
         # Change permissions in the last step because some of the
         # intermediary scripts like to create directories as root.
         chown -R ${cfg.user}:${cfg.group} ${cfg.statePath}
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index bb8dc640f981..4145f8fa957a 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -5,15 +5,16 @@ with lib;
 let
   cfg = config.services.matrix-synapse;
   logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
-  mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${if r.compress then "true" else "false"}}'';
-  mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${if l.tls then "true" else "false"}, x_forwarded: ${if l.x_forwarded then "true" else "false"}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
+  mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${fromBool r.compress}}'';
+  mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${fromBool l.tls}, x_forwarded: ${fromBool l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
+  fromBool = x: if x then "true" else "false";
   configFile = pkgs.writeText "homeserver.yaml" ''
 tls_certificate_path: "${cfg.tls_certificate_path}"
 ${optionalString (cfg.tls_private_key_path != null) ''
 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"}
+no_tls: ${fromBool cfg.no_tls}
 ${optionalString (cfg.bind_port != null) ''
 bind_port: ${toString cfg.bind_port}
 ''}
@@ -25,7 +26,7 @@ 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"}
+web_client: ${fromBool cfg.web_client}
 ${optionalString (cfg.public_baseurl != null) ''
 public_baseurl: "${cfg.public_baseurl}"
 ''}
@@ -53,14 +54,14 @@ media_store_path: "/var/lib/matrix-synapse/media"
 uploads_path: "/var/lib/matrix-synapse/uploads"
 max_upload_size: "${cfg.max_upload_size}"
 max_image_pixels: "${cfg.max_image_pixels}"
-dynamic_thumbnails: ${if cfg.dynamic_thumbnails then "true" else "false"}
+dynamic_thumbnails: ${fromBool cfg.dynamic_thumbnails}
 url_preview_enabled: False
 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"}
+enable_registration_captcha: ${fromBool cfg.enable_registration_captcha}
 turn_uris: ${builtins.toJSON cfg.turn_uris}
 turn_shared_secret: "${cfg.turn_shared_secret}"
-enable_registration: ${if cfg.enable_registration then "true" else "false"}
+enable_registration: ${fromBool cfg.enable_registration}
 ${optionalString (cfg.registration_shared_secret != null) ''
 registration_shared_secret: "${cfg.registration_shared_secret}"
 ''}
@@ -68,9 +69,15 @@ recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
 turn_user_lifetime: "${cfg.turn_user_lifetime}"
 user_creation_max_duration: ${cfg.user_creation_max_duration}
 bcrypt_rounds: ${cfg.bcrypt_rounds}
-allow_guest_access: {if cfg.allow_guest_access then "true" else "false"}
-enable_metrics: ${if cfg.enable_metrics then "true" else "false"}
-report_stats: ${if cfg.report_stats then "true" else "false"}
+allow_guest_access: ${fromBool cfg.allow_guest_access}
+trusted_third_party_id_servers: ${builtins.toJSON cfg.trusted_third_party_id_servers}
+room_invite_state_types: ${builtins.toJSON cfg.room_invite_state_types}
+${optionalString (cfg.macaroon_secret_key != null) ''
+  macaroon_secret_key: "${cfg.macaroon_secret_key}"
+''}
+expire_access_token: ${fromBool cfg.expire_access_token}
+enable_metrics: ${fromBool cfg.enable_metrics}
+report_stats: ${fromBool cfg.report_stats}
 signing_key_path: "/var/lib/matrix-synapse/homeserver.signing.key"
 key_refresh_interval: "${cfg.key_refresh_interval}"
 perspectives:
@@ -469,6 +476,34 @@ in {
           accessible to anonymous users.
         '';
       };
+      trusted_third_party_id_servers = mkOption {
+        type = types.listOf types.str;
+        default = ["matrix.org"];
+        description = ''
+          The list of identity servers trusted to verify third party identifiers by this server.
+        '';
+      };
+      room_invite_state_types = mkOption {
+        type = types.listOf types.str;
+        default = ["m.room.join_rules" "m.room.canonical_alias" "m.room.avatar" "m.room.name"];
+        description = ''
+          A list of event types that will be included in the room_invite_state
+        '';
+      };
+      macaroon_secret_key = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          Secret key for authentication tokens
+        '';
+      };
+      expire_access_token = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable access token expiration.
+        '';
+      };
       key_refresh_interval = mkOption {
         type = types.str;
         default = "1d";
diff --git a/nixos/modules/services/misc/mesos-master.nix b/nixos/modules/services/misc/mesos-master.nix
index 497646b2b418..99583ebeebd5 100644
--- a/nixos/modules/services/misc/mesos-master.nix
+++ b/nixos/modules/services/misc/mesos-master.nix
@@ -80,7 +80,7 @@ in {
     systemd.services.mesos-master = {
       description = "Mesos Master";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       serviceConfig = {
         ExecStart = ''
           ${pkgs.mesos}/bin/mesos-master \
diff --git a/nixos/modules/services/misc/mesos-slave.nix b/nixos/modules/services/misc/mesos-slave.nix
index 8c29734813a1..9ddecb6fe30c 100644
--- a/nixos/modules/services/misc/mesos-slave.nix
+++ b/nixos/modules/services/misc/mesos-slave.nix
@@ -105,7 +105,7 @@ in {
     systemd.services.mesos-slave = {
       description = "Mesos Slave";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       environment.MESOS_CONTAINERIZERS = concatStringsSep "," containerizers;
       serviceConfig = {
         ExecStart = ''
diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix
index c6b67e8498ca..8bcf35a8ad38 100644
--- a/nixos/modules/services/misc/rippled.nix
+++ b/nixos/modules/services/misc/rippled.nix
@@ -154,43 +154,45 @@ let
   };
 
   dbOptions = {
-    type = mkOption {
-      description = "Rippled database type.";
-      type = types.enum ["rocksdb" "nudb"];
-      default = "rocksdb";
-    };
+    options = {
+      type = mkOption {
+        description = "Rippled database type.";
+        type = types.enum ["rocksdb" "nudb"];
+        default = "rocksdb";
+      };
 
-    path = mkOption {
-      description = "Location to store the database.";
-      type = types.path;
-      default = cfg.databasePath;
-    };
+      path = mkOption {
+        description = "Location to store the database.";
+        type = types.path;
+        default = cfg.databasePath;
+      };
 
-    compression = mkOption {
-      description = "Whether to enable snappy compression.";
-      type = types.nullOr types.bool;
-      default = null;
-    };
+      compression = mkOption {
+        description = "Whether to enable snappy compression.";
+        type = types.nullOr types.bool;
+        default = null;
+      };
 
-    onlineDelete = mkOption {
-      description = "Enable automatic purging of older ledger information.";
-      type = types.addCheck (types.nullOr types.int) (v: v > 256);
-      default = cfg.ledgerHistory;
-    };
+      onlineDelete = mkOption {
+        description = "Enable automatic purging of older ledger information.";
+        type = types.addCheck (types.nullOr types.int) (v: v > 256);
+        default = cfg.ledgerHistory;
+      };
 
-    advisoryDelete = mkOption {
-      description = ''
-	If set, then require administrative RPC call "can_delete"
-	to enable online deletion of ledger records.
-      '';
-      type = types.nullOr types.bool;
-      default = null;
-    };
+      advisoryDelete = mkOption {
+        description = ''
+	        If set, then require administrative RPC call "can_delete"
+	        to enable online deletion of ledger records.
+        '';
+        type = types.nullOr types.bool;
+        default = null;
+      };
 
-    extraOpts = mkOption {
-      description = "Extra database options.";
-      type = types.lines;
-      default = "";
+      extraOpts = mkOption {
+        description = "Extra database options.";
+        type = types.lines;
+        default = "";
+      };
     };
   };
 
@@ -213,8 +215,7 @@ in
 
       ports = mkOption {
 	description = "Ports exposed by rippled";
-	type = types.attrsOf types.optionSet;
-	options = [portOptions];
+	type = with types; attrsOf (submodule portOptions);
 	default = {
 	  rpc = {
 	    port = 5005;
@@ -238,8 +239,7 @@ in
 
       nodeDb = mkOption {
 	description = "Rippled main database options.";
-	type = types.nullOr types.optionSet;
-	options = dbOptions;
+	type = with types; nullOr (submodule dbOptions);
 	default = {
 	  type = "rocksdb";
 	  extraOpts = ''
@@ -254,15 +254,13 @@ in
 
       tempDb = mkOption {
 	description = "Rippled temporary database options.";
-	type = types.nullOr types.optionSet;
-	options = dbOptions;
+	type = with types; nullOr (submodule dbOptions);
 	default = null;
       };
 
       importDb = mkOption {
 	description = "Settings for performing a one-time import.";
-	type = types.nullOr types.optionSet;
-	options = dbOptions;
+	type = with types; nullOr (submodule dbOptions);
 	default = null;
       };
 
diff --git a/nixos/modules/services/misc/svnserve.nix b/nixos/modules/services/misc/svnserve.nix
index c74befac749d..04a6cd7bfa9b 100644
--- a/nixos/modules/services/misc/svnserve.nix
+++ b/nixos/modules/services/misc/svnserve.nix
@@ -35,7 +35,7 @@ in
 
   config = mkIf cfg.enable {
     systemd.services.svnserve = {
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart = "mkdir -p ${cfg.svnBaseDir}";
       script = "${pkgs.subversion.out}/bin/svnserve -r ${cfg.svnBaseDir} -d --foreground --pid-file=/var/run/svnserve.pid";
diff --git a/nixos/modules/services/misc/zookeeper.nix b/nixos/modules/services/misc/zookeeper.nix
index 4ce692b6f6a5..b7bca8b56b28 100644
--- a/nixos/modules/services/misc/zookeeper.nix
+++ b/nixos/modules/services/misc/zookeeper.nix
@@ -113,7 +113,7 @@ in {
     systemd.services.zookeeper = {
       description = "Zookeeper Daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       environment = { ZOOCFGDIR = configDir; };
       serviceConfig = {
         ExecStart = ''
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index 08fc3f04dbfc..1de3320dc42c 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -387,7 +387,7 @@ in {
       systemd.services.carbonCache = let name = "carbon-cache"; in {
         description = "Graphite Data Storage Backend";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" ];
+        after = [ "network.target" ];
         environment = carbonEnv;
         serviceConfig = {
           ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
@@ -410,7 +410,7 @@ in {
         enable = cfg.carbon.enableAggregator;
         description = "Carbon Data Aggregator";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" ];
+        after = [ "network.target" ];
         environment = carbonEnv;
         serviceConfig = {
           ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
@@ -426,7 +426,7 @@ in {
       systemd.services.carbonRelay = let name = "carbon-relay"; in {
         description = "Carbon Data Relay";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" ];
+        after = [ "network.target" ];
         environment = carbonEnv;
         serviceConfig = {
           ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
@@ -448,7 +448,7 @@ in {
       systemd.services.graphiteWeb = {
         description = "Graphite Web Interface";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" ];
+        after = [ "network.target" ];
         path = [ pkgs.perl ];
         environment = {
           PYTHONPATH = let
@@ -501,7 +501,7 @@ in {
       systemd.services.graphiteApi = {
         description = "Graphite Api Interface";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" ];
+        after = [ "network.target" ];
         environment = {
           PYTHONPATH = let
               aenv = pkgs.python.buildEnv.override {
@@ -538,7 +538,7 @@ in {
       systemd.services.seyren = {
         description = "Graphite Alerting Dashboard";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" "mongodb.service" ];
+        after = [ "network.target" "mongodb.service" ];
         environment = seyrenConfig;
         serviceConfig = {
           ExecStart = "${pkgs.seyren}/bin/seyren -httpPort ${toString cfg.seyren.port}";
@@ -561,7 +561,7 @@ in {
       systemd.services.graphitePager = {
         description = "Graphite Pager Alerting Daemon";
         wantedBy = [ "multi-user.target" ];
-        after = [ "network-interfaces.target" "redis.service" ];
+        after = [ "network.target" "redis.service" ];
         environment = {
           REDIS_URL = cfg.pager.redisUrl;
           GRAPHITE_URL = cfg.pager.graphiteUrl;
diff --git a/nixos/modules/services/monitoring/monit.nix b/nixos/modules/services/monitoring/monit.nix
index 704693969a35..e07ffd2e8b54 100644
--- a/nixos/modules/services/monitoring/monit.nix
+++ b/nixos/modules/services/monitoring/monit.nix
@@ -36,11 +36,16 @@ in
     ];
 
     systemd.services.monit = {
-      description = "Monit system watcher";
-      after = [ "network-interfaces.target" ];
+      description = "Pro-active monitoring utility for unix systems";
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      script = "${pkgs.monit}/bin/monit -I -c /etc/monit.conf";
-      serviceConfig.Restart = "always";
+      serviceConfig = {
+        ExecStart = "${pkgs.monit}/bin/monit -I -c /etc/monit.conf";
+        ExecStop = "${pkgs.monit}/bin/monit -c /etc/monit.conf quit";
+        ExecReload = "${pkgs.monit}/bin/monit -c /etc/monit.conf reload";
+        KillMode = "process";
+        Restart = "always";
+      };
     };
   };
 }
diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix
index f2f7710de9e7..4914c5db97d2 100644
--- a/nixos/modules/services/monitoring/nagios.nix
+++ b/nixos/modules/services/monitoring/nagios.nix
@@ -163,7 +163,7 @@ in
       description = "Nagios monitoring daemon";
       path     = [ pkgs.nagios ];
       wantedBy = [ "multi-user.target" ];
-      after    = [ "network-interfaces.target" ];
+      after    = [ "network.target" ];
 
       serviceConfig = {
         User = "nagios";
diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix
index 1017005226b2..f2834f288f90 100644
--- a/nixos/modules/services/monitoring/smartd.nix
+++ b/nixos/modules/services/monitoring/smartd.nix
@@ -197,8 +197,7 @@ in
       devices = mkOption {
         default = [];
         example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ];
-        type = types.listOf types.optionSet;
-        options = [ smartdOpts ];
+        type = with types; listOf (submodule smartdOpts);
         description = "List of devices to monitor.";
       };
 
diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix
index febf0c95f5bd..c4c4ed227b35 100644
--- a/nixos/modules/services/monitoring/ups.nix
+++ b/nixos/modules/services/monitoring/ups.nix
@@ -169,8 +169,7 @@ in
           monitoring directly.  These are usually attached to serial ports,
           but USB devices are also supported.
         '';
-        type = types.attrsOf types.optionSet;
-        options = [ upsOptions ];
+        type = with types; attrsOf (submodule upsOptions);
       };
 
     };
diff --git a/nixos/modules/services/network-filesystems/openafs-client/default.nix b/nixos/modules/services/network-filesystems/openafs-client/default.nix
index 891f41c8dcdc..6f51e287910a 100644
--- a/nixos/modules/services/network-filesystems/openafs-client/default.nix
+++ b/nixos/modules/services/network-filesystems/openafs-client/default.nix
@@ -75,7 +75,7 @@ in
     systemd.services.afsd = {
       description = "AFS client";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
 
       preStart = ''
         mkdir -p -m 0755 /afs
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index a186982ec9c0..7de85b59e2af 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -56,6 +56,7 @@ let
       serviceConfig = {
         ExecStart = "${samba}/sbin/${appName} ${args}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        Type = "notify";
       };
 
       restartTriggers = [ configFile ];
@@ -167,12 +168,12 @@ in
         type = types.attrsOf (types.attrsOf types.unspecified);
         example =
           { public =
-             { path = "/srv/public";
-               "read only" = true;
-               browseable = "yes";
-               "guest ok" = "yes";
-                comment = "Public samba share.";
-             };
+            { path = "/srv/public";
+              "read only" = true;
+              browseable = "yes";
+              "guest ok" = "yes";
+              comment = "Public samba share.";
+            };
           };
       };
 
diff --git a/nixos/modules/services/network-filesystems/tahoe.nix b/nixos/modules/services/network-filesystems/tahoe.nix
index d4b6c05e9432..f1846b963252 100644
--- a/nixos/modules/services/network-filesystems/tahoe.nix
+++ b/nixos/modules/services/network-filesystems/tahoe.nix
@@ -8,148 +8,150 @@ in
     options.services.tahoe = {
       introducers = mkOption {
         default = {};
-        type = types.loaOf types.optionSet;
+        type = with types; loaOf (submodule {
+          options = {
+            nickname = mkOption {
+              type = types.str;
+              description = ''
+                The nickname of this Tahoe introducer.
+              '';
+            };
+            tub.port = mkOption {
+              default = 3458;
+              type = types.int;
+              description = ''
+                The port on which the introducer will listen.
+              '';
+            };
+            tub.location = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              description = ''
+                The external location that the introducer should listen on.
+
+                If specified, the port should be included.
+              '';
+            };
+            package = mkOption {
+              default = pkgs.tahoelafs;
+              defaultText = "pkgs.tahoelafs";
+              type = types.package;
+              example = literalExample "pkgs.tahoelafs";
+              description = ''
+                The package to use for the Tahoe LAFS daemon.
+              '';
+            };
+          };
+        });
         description = ''
           The Tahoe introducers.
         '';
-        options = {
-          nickname = mkOption {
-            type = types.str;
-            description = ''
-              The nickname of this Tahoe introducer.
-            '';
-          };
-          tub.port = mkOption {
-            default = 3458;
-            type = types.int;
-            description = ''
-              The port on which the introducer will listen.
-            '';
-          };
-          tub.location = mkOption {
-            default = null;
-            type = types.nullOr types.str;
-            description = ''
-              The external location that the introducer should listen on.
-
-              If specified, the port should be included.
-            '';
-          };
-          package = mkOption {
-            default = pkgs.tahoelafs;
-            defaultText = "pkgs.tahoelafs";
-            type = types.package;
-            example = literalExample "pkgs.tahoelafs";
-            description = ''
-              The package to use for the Tahoe LAFS daemon.
-            '';
-          };
-        };
       };
       nodes = mkOption {
         default = {};
-        type = types.loaOf types.optionSet;
-        description = ''
-          The Tahoe nodes.
-        '';
-        options = {
-          nickname = mkOption {
-            type = types.str;
-            description = ''
-              The nickname of this Tahoe node.
-            '';
-          };
-          tub.port = mkOption {
-            default = 3457;
-            type = types.int;
-            description = ''
-              The port on which the tub will listen.
+        type = with types; loaOf (submodule {
+          options = {
+            nickname = mkOption {
+              type = types.str;
+              description = ''
+                The nickname of this Tahoe node.
+              '';
+            };
+            tub.port = mkOption {
+              default = 3457;
+              type = types.int;
+              description = ''
+                The port on which the tub will listen.
 
-              This is the correct setting to tweak if you want Tahoe's storage
-              system to listen on a different port.
-            '';
-          };
-          tub.location = mkOption {
-            default = null;
-            type = types.nullOr types.str;
-            description = ''
-              The external location that the node should listen on.
+                This is the correct setting to tweak if you want Tahoe's storage
+                system to listen on a different port.
+              '';
+            };
+            tub.location = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              description = ''
+                The external location that the node should listen on.
 
-              This is the setting to tweak if there are multiple interfaces
-              and you want to alter which interface Tahoe is advertising.
+                This is the setting to tweak if there are multiple interfaces
+                and you want to alter which interface Tahoe is advertising.
 
-              If specified, the port should be included.
-            '';
-          };
-          web.port = mkOption {
-            default = 3456;
-            type = types.int;
-            description = ''
-              The port on which the Web server will listen.
+                If specified, the port should be included.
+              '';
+            };
+            web.port = mkOption {
+              default = 3456;
+              type = types.int;
+              description = ''
+                The port on which the Web server will listen.
 
-              This is the correct setting to tweak if you want Tahoe's WUI to
-              listen on a different port.
-            '';
-          };
-          client.introducer = mkOption {
-            default = null;
-            type = types.nullOr types.str;
-            description = ''
-              The furl for a Tahoe introducer node.
+                This is the correct setting to tweak if you want Tahoe's WUI to
+                listen on a different port.
+              '';
+            };
+            client.introducer = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              description = ''
+                The furl for a Tahoe introducer node.
 
-              Like all furls, keep this safe and don't share it.
-            '';
-          };
-          client.helper = mkOption {
-            default = null;
-            type = types.nullOr types.str;
-            description = ''
-              The furl for a Tahoe helper node.
+                Like all furls, keep this safe and don't share it.
+              '';
+            };
+            client.helper = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              description = ''
+                The furl for a Tahoe helper node.
 
-              Like all furls, keep this safe and don't share it.
-            '';
-          };
-          client.shares.needed = mkOption {
-            default = 3;
-            type = types.int;
-            description = ''
-              The number of shares required to reconstitute a file.
-            '';
-          };
-          client.shares.happy = mkOption {
-            default = 7;
-            type = types.int;
-            description = ''
-              The number of distinct storage nodes required to store
-              a file.
-            '';
-          };
-          client.shares.total = mkOption {
-            default = 10;
-            type = types.int;
-            description = ''
-              The number of shares required to store a file.
-            '';
-          };
-          storage.enable = mkEnableOption "storage service";
-          storage.reservedSpace = mkOption {
-            default = "1G";
-            type = types.str;
-            description = ''
-              The amount of filesystem space to not use for storage.
-            '';
-          };
-          helper.enable = mkEnableOption "helper service";
-          package = mkOption {
-            default = pkgs.tahoelafs;
-            defaultText = "pkgs.tahoelafs";
-            type = types.package;
-            example = literalExample "pkgs.tahoelafs";
-            description = ''
-              The package to use for the Tahoe LAFS daemon.
-            '';
+                Like all furls, keep this safe and don't share it.
+              '';
+            };
+            client.shares.needed = mkOption {
+              default = 3;
+              type = types.int;
+              description = ''
+                The number of shares required to reconstitute a file.
+              '';
+            };
+            client.shares.happy = mkOption {
+              default = 7;
+              type = types.int;
+              description = ''
+                The number of distinct storage nodes required to store
+                a file.
+              '';
+            };
+            client.shares.total = mkOption {
+              default = 10;
+              type = types.int;
+              description = ''
+                The number of shares required to store a file.
+              '';
+            };
+            storage.enable = mkEnableOption "storage service";
+            storage.reservedSpace = mkOption {
+              default = "1G";
+              type = types.str;
+              description = ''
+                The amount of filesystem space to not use for storage.
+              '';
+            };
+            helper.enable = mkEnableOption "helper service";
+            package = mkOption {
+              default = pkgs.tahoelafs;
+              defaultText = "pkgs.tahoelafs";
+              type = types.package;
+              example = literalExample "pkgs.tahoelafs";
+              description = ''
+                The package to use for the Tahoe LAFS daemon.
+              '';
+            };
           };
-        };
+        });
+        description = ''
+          The Tahoe nodes.
+        '';
       };
     };
     config = mkMerge [
diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix
index 08afafceff24..41d7128ec31e 100644
--- a/nixos/modules/services/networking/bind.nix
+++ b/nixos/modules/services/networking/bind.nix
@@ -145,8 +145,8 @@ in
       };
 
     systemd.services.bind = {
-      description = "BIND name server job";
-      after = [ "network-interfaces.target" ];
+      description = "BIND Domain Name Server";
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
       preStart = ''
@@ -155,6 +155,7 @@ in
       '';
 
       script = "${pkgs.bind.bin}/sbin/named -u ${bindUser} ${optionalString cfg.ipv4Only "-4"} -c ${cfg.configFile} -f";
+      unitConfig.Documentation = "man:named(8)";
     };
   };
 }
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 0495b32c6fa8..cb00139c5f1c 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -208,9 +208,9 @@ in
     # networking.firewall.allowedUDPPorts = ...
 
     systemd.services.cjdns = {
-      description = "encrypted networking for everybody";
-      wantedBy = [ "network.target" ];
-      after = [ "networkSetup.service" "network-interfaces.target" ];
+      description = "cjdns: routing engine designed for security, scalability, speed and ease of use";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
 
       preStart = if cfg.confFile != "" then "" else ''
         [ -e /etc/cjdns.keys ] && source /etc/cjdns.keys
diff --git a/nixos/modules/services/networking/connman.nix b/nixos/modules/services/networking/connman.nix
index 3fecfbb13a04..d0683b877801 100644
--- a/nixos/modules/services/networking/connman.nix
+++ b/nixos/modules/services/networking/connman.nix
@@ -27,6 +27,14 @@ in {
         '';
       };
 
+      enableVPN = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to enable ConnMan VPN service.
+        '';
+      };
+
       extraConfig = mkOption {
         type = types.lines;
         default = ''
@@ -78,7 +86,7 @@ in {
       };
     };
 
-    systemd.services."connman-vpn" = {
+    systemd.services."connman-vpn" = mkIf cfg.enableVPN {
       description = "ConnMan VPN service";
       wantedBy = [ "multi-user.target" ];
       after = [ "syslog.target" ];
@@ -91,7 +99,7 @@ in {
       };
     };
 
-    systemd.services."net-connman-vpn" = {
+    systemd.services."net-connman-vpn" = mkIf cfg.enableVPN {
       description = "D-BUS Service";
       serviceConfig = {
         Name = "net.connman.vpn";
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index 005c57dce7c7..e74d68cad902 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -7,7 +7,7 @@ let
 
   stateDir = "/var/spool/ddclient";
   ddclientUser = "ddclient";
-  ddclientFlags = "-foreground -verbose -noquiet -file /etc/ddclient.conf";
+  ddclientFlags = "-foreground -verbose -noquiet -file ${config.services.ddclient.configFile}";
   ddclientPIDFile = "${stateDir}/ddclient.pid";
 
 in
@@ -52,6 +52,17 @@ in
         '';
       };
 
+      configFile = mkOption {
+        default = "/etc/ddclient.conf";
+        type = path;
+        description = ''
+          Path to configuration file.
+          When set to the default '/etc/ddclient.conf' it will be populated with the various other options in this module. When it is changed (for example: '/root/nixos/secrets/ddclient.conf') the file read directly to configure ddclient. This is a source of impurity.
+          The purpose of this is to avoid placing secrets into the store.
+        '';
+        example = "/root/nixos/secrets/ddclient.conf";
+      };
+
       protocol = mkOption {
         default = "dyndns2";
         type = str;
@@ -88,7 +99,7 @@ in
         default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '";
         type = str;
         description = ''
-          Method to determine the IP address to send to the dymanic DNS provider.
+          Method to determine the IP address to send to the dynamic DNS provider.
         '';
       };
     };
@@ -109,9 +120,11 @@ in
     };
 
     environment.etc."ddclient.conf" = {
+      enable = config.services.ddclient.configFile == /etc/ddclient.conf;
       uid = config.ids.uids.ddclient;
       mode = "0600";
       text = ''
+        # This file can be used as a template for configFile or is automatically generated by Nix options.
         daemon=600
         cache=${stateDir}/ddclient.cache
         pid=${ddclientPIDFile}
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 4b0e90886510..87c0aa50a1ff 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -158,8 +158,8 @@ in
       { description = "DHCP Client";
 
         wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
         wants = [ "network.target" ];
-        before = [ "network.target" ];
 
         # Stopping dhcpcd during a reconfiguration is undesirable
         # because it brings down the network interfaces configured by
diff --git a/nixos/modules/services/networking/flannel.nix b/nixos/modules/services/networking/flannel.nix
new file mode 100644
index 000000000000..28b6c4f657dd
--- /dev/null
+++ b/nixos/modules/services/networking/flannel.nix
@@ -0,0 +1,153 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.flannel;
+
+  networkConfig = filterAttrs (n: v: v != null) {
+    Network = cfg.network;
+    SubnetLen = cfg.subnetLen;
+    SubnetMin = cfg.subnetMin;
+    SubnetMax = cfg.subnetMax;
+    Backend = cfg.backend;
+  };
+in {
+  options.services.flannel = {
+    enable = mkEnableOption "flannel";
+
+    package = mkOption {
+      description = "Package to use for flannel";
+      type = types.package;
+      default = pkgs.flannel.bin;
+    };
+
+    publicIp = mkOption {
+      description = ''
+        IP accessible by other nodes for inter-host communication.
+        Defaults to the IP of the interface being used for communication.
+      '';
+      type = types.nullOr types.str;
+      default = null;
+    };
+
+    iface = mkOption {
+      description = ''
+        Interface to use (IP or name) for inter-host communication.
+        Defaults to the interface for the default route on the machine.
+      '';
+      type = types.nullOr types.str;
+      default = null;
+    };
+
+    etcd = {
+      endpoints = mkOption {
+        description = "Etcd endpoints";
+        type = types.listOf types.str;
+        default = ["http://127.0.0.1:2379"];
+      };
+
+      prefix = mkOption {
+        description = "Etcd key prefix";
+        type = types.str;
+        default = "/coreos.com/network";
+      };
+
+      caFile = mkOption {
+        description = "Etcd certificate authority file";
+        type = types.nullOr types.path;
+        default = null;
+      };
+
+      certFile = mkOption {
+        description = "Etcd cert file";
+        type = types.nullOr types.path;
+        default = null;
+      };
+
+      keyFile = mkOption {
+        description = "Etcd key file";
+        type = types.nullOr types.path;
+        default = null;
+      };
+    };
+
+    network = mkOption {
+      description = " IPv4 network in CIDR format to use for the entire flannel network.";
+      type = types.str;
+    };
+
+    subnetLen = mkOption {
+      description = ''
+        The size of the subnet allocated to each host. Defaults to 24 (i.e. /24)
+        unless the Network was configured to be smaller than a /24 in which case
+        it is one less than the network.
+      '';
+      type = types.int;
+      default = 24;
+    };
+
+    subnetMin = mkOption {
+      description = ''
+        The beginning of IP range which the subnet allocation should start with.
+        Defaults to the first subnet of Network.
+      '';
+      type = types.nullOr types.str;
+      default = null;
+    };
+
+    subnetMax = mkOption {
+      description = ''
+        The end of IP range which the subnet allocation should start with.
+        Defaults to the last subnet of Network.
+      '';
+      type = types.nullOr types.str;
+      default = null;
+    };
+
+    backend = mkOption {
+      description = "Type of backend to use and specific configurations for that backend.";
+      type = types.attrs;
+      default = {
+        Type = "vxlan";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.flannel = {
+      description = "Flannel Service";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      environment = {
+        FLANNELD_PUBLIC_IP = cfg.publicIp;
+        FLANNELD_ETCD_ENDPOINTS = concatStringsSep "," cfg.etcd.endpoints;
+        FLANNELD_ETCD_KEYFILE = cfg.etcd.keyFile;
+        FLANNELD_ETCD_CERTFILE = cfg.etcd.certFile;
+        FLANNELD_ETCD_CAFILE = cfg.etcd.caFile;
+        FLANNELD_IFACE = cfg.iface;
+        ETCDCTL_CERT_FILE = cfg.etcd.certFile;
+        ETCDCTL_KEY_FILE = cfg.etcd.keyFile;
+        ETCDCTL_CA_FILE = cfg.etcd.caFile;
+        ETCDCTL_PEERS = concatStringsSep "," cfg.etcd.endpoints;
+      };
+      preStart = ''
+        echo "setting network configuration"
+        until ${pkgs.etcdctl.bin}/bin/etcdctl set /coreos.com/network/config '${builtins.toJSON networkConfig}'
+        do
+          echo "setting network configuration, retry"
+          sleep 1
+        done
+      '';
+      postStart = ''
+        while [ ! -f /run/flannel/subnet.env ]
+        do
+          sleep 1
+        done
+      '';
+      serviceConfig.ExecStart = "${cfg.package}/bin/flannel";
+    };
+
+    services.etcd.enable = mkDefault cfg.etcd.endpoints == ["http://127.0.0.1:2379"];
+  };
+}
diff --git a/nixos/modules/services/networking/gvpe.nix b/nixos/modules/services/networking/gvpe.nix
index 27b64b5bb95f..3ef3548e0a08 100644
--- a/nixos/modules/services/networking/gvpe.nix
+++ b/nixos/modules/services/networking/gvpe.nix
@@ -105,7 +105,7 @@ in
   config = mkIf cfg.enable {
     systemd.services.gvpe = {
       description = "GNU Virtual Private Ethernet node";
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
       preStart = ''
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index 0cbf57314c4b..926857a0ff4e 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -187,44 +187,43 @@ in
 
       outTunnels = mkOption {
         default = {};
-        type = with types; loaOf optionSet;
+        type = with types; loaOf (submodule ( 
+          { name, config, ... }: {
+            options = commonTunOpts name;
+            config = {
+              name = mkDefault name;
+            };
+          }
+        ));
         description = ''
           Connect to someone as a client and establish a local accept endpoint
         '';
-        options = [ ({ name, config, ... }: {
-          options = commonTunOpts name;
-          config = {
-            name = mkDefault name;
-          };
-        }) ];
       };
 
       inTunnels = mkOption {
         default = {};
-        type = with types; loaOf optionSet;
+        type = with types; loaOf (submodule (
+          { name, config, ... }: {
+            options = {
+              inPort = mkOption {
+                type = types.int;
+                default = 0;
+                description = "Service port. Default to the tunnel's listen port.";
+              };
+              accessList = mkOption {
+                type = with types; listOf str;
+                default = [];
+                description = "I2P nodes that are allowed to connect to this service.";
+              };
+            } // commonTunOpts name;
+            config = {
+              name = mkDefault name;
+            };
+          }
+        ));
         description = ''
           Serve something on I2P network at port and delegate requests to address inPort.
         '';
-        options = [ ({ name, config, ... }: {
-
-          options = {
-            inPort = mkOption {
-              type = types.int;
-              default = 0;
-              description = "Service port. Default to the tunnel's listen port.";
-            };
-            accessList = mkOption {
-              type = with types; listOf str;
-              default = [];
-              description = "I2P nodes that are allowed to connect to this service.";
-            };
-          } // commonTunOpts name;
-
-          config = {
-            name = mkDefault name;
-          };
-
-        }) ];
       };
     };
   };
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index 9d163e60d5ea..08ba2fdb1646 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -122,23 +122,23 @@ in
     };
 
     networking.nat.forwardPorts = mkOption {
-      type = types.listOf types.optionSet;
+      type = with types; listOf (submodule {
+        options = {
+          sourcePort = mkOption {
+            type = types.int;
+            example = 8080;
+            description = "Source port of the external interface";
+          };
+
+          destination = mkOption {
+            type = types.str;
+            example = "10.0.0.1:80";
+            description = "Forward tcp connection to destination ip:port";
+          };
+        };
+      });
       default = [];
       example = [ { sourcePort = 8080; destination = "10.0.0.1:80"; } ];
-      options = {
-        sourcePort = mkOption {
-          type = types.int;
-          example = 8080;
-          description = "Source port of the external interface";
-        };
-
-        destination = mkOption {
-          type = types.str;
-          example = "10.0.0.1:80";
-          description = "Forward tcp connection to destination ip:port";
-        };
-      };
-
       description =
         ''
           List of forwarded ports from the external interface to
@@ -171,7 +171,7 @@ in
     systemd.services = mkIf (!config.networking.firewall.enable) { nat = {
       description = "Network Address Translation";
       wantedBy = [ "network.target" ];
-      after = [ "network-interfaces.target" "systemd-modules-load.service" ];
+      after = [ "network-pre.target" "systemd-modules-load.service" ];
       path = [ pkgs.iptables ];
       unitConfig.ConditionCapability = "CAP_NET_ADMIN";
 
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index 333a3378c4cc..6af1dd736431 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -71,6 +71,7 @@ let
       # interfaces
     ${forEach "  ip-address: " cfg.interfaces}
 
+      ip-freebind:         ${yesOrNo  cfg.ipFreebind}
       hide-version:        ${yesOrNo  cfg.hideVersion}
       identity:            "${cfg.identity}"
       ip-transparent:      ${yesOrNo  cfg.ipTransparent}
@@ -84,7 +85,7 @@ let
       reuseport:           ${yesOrNo  cfg.reuseport}
       round-robin:         ${yesOrNo  cfg.roundRobin}
       server-count:        ${toString cfg.serverCount}
-      ${if cfg.statistics == null then "" else "statistics:          ${toString cfg.statistics}"}
+      ${maybeToString "statistics: " cfg.statistics}
       tcp-count:           ${toString cfg.tcpCount}
       tcp-query-count:     ${toString cfg.tcpQueryCount}
       tcp-timeout:         ${toString cfg.tcpTimeout}
@@ -117,7 +118,8 @@ let
   '';
 
   yesOrNo = b: if b then "yes" else "no";
-  maybeString = pre: s: if s == null then "" else ''${pre} "${s}"'';
+  maybeString = prefix: x: if x == null then "" else ''${prefix} "${s}"'';
+  maybeToString = prefix: x: if x == null then "" else ''${prefix} ${toString s}'';
   forEach = pre: l: concatMapStrings (x: pre + x + "\n") l;
 
 
@@ -146,6 +148,11 @@ let
     ${forEach     "  rrl-whitelist: "      zone.rrlWhitelist}
       ${maybeString "zonestats: "          zone.zoneStats}
 
+      ${maybeToString "max-refresh-time: " zone.maxRefreshSecs}
+      ${maybeToString "min-refresh-time: " zone.minRefreshSecs}
+      ${maybeToString "max-retry-time:   " zone.maxRetrySecs}
+      ${maybeToString "min-retry-time:   " zone.minRetrySecs}
+
       allow-axfr-fallback: ${yesOrNo       zone.allowAXFRFallback}
     ${forEach     "  allow-notify: "       zone.allowNotify}
     ${forEach     "  request-xfr: "        zone.requestXFR}
@@ -241,6 +248,44 @@ let
         '';
       };
 
+      maxRefreshSecs = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          Limit refresh time for secondary zones. This is the timer which
+          checks to see if the zone has to be refetched when it expires.
+          Normally the value from the SOA record is used, but this  option
+          restricts that value.
+        '';
+      };
+
+      minRefreshSecs = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          Limit refresh time for secondary zones.
+        '';
+      };
+
+      maxRetrySecs = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          Limit retry time for secondary zones. This is the timeout after
+          a failed fetch attempt for the zone. Normally the value from
+          the SOA record is used, but this option restricts that value.
+        '';
+      };
+
+      minRetrySecs = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          Limit retry time for secondary zones.
+        '';
+      };
+
+
       notify = mkOption {
         type = types.listOf types.str;
         default = [];
@@ -366,6 +411,15 @@ in
       '';
     };
 
+    ipFreebind = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to bind to nonlocal addresses and interfaces that are down.
+        Similar to ip-transparent.
+      '';
+    };
+
     ipTransparent = mkOption {
       type = types.bool;
       default = false;
diff --git a/nixos/modules/services/networking/oidentd.nix b/nixos/modules/services/networking/oidentd.nix
index 651bb8e967cf..ba7acd879546 100644
--- a/nixos/modules/services/networking/oidentd.nix
+++ b/nixos/modules/services/networking/oidentd.nix
@@ -25,7 +25,7 @@ with lib;
 
   config = mkIf config.services.oidentd.enable {
     systemd.services.oidentd = {
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       serviceConfig.Type = "forking";
       script = "${pkgs.oidentd}/sbin/oidentd -u oidentd -g nogroup" +
diff --git a/nixos/modules/services/networking/openvpn.nix b/nixos/modules/services/networking/openvpn.nix
index 82173a841a3f..3fbf5a9f0227 100644
--- a/nixos/modules/services/networking/openvpn.nix
+++ b/nixos/modules/services/networking/openvpn.nix
@@ -56,7 +56,7 @@ let
       description = "OpenVPN instance ‘${name}’";
 
       wantedBy = optional cfg.autoStart "multi-user.target";
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
 
       path = [ pkgs.iptables pkgs.iproute pkgs.nettools ];
 
@@ -116,52 +116,54 @@ in
         attribute name.
       '';
 
-      type = types.attrsOf types.optionSet;
+      type = with types; attrsOf (submodule {
 
-      options = {
+        options = {
 
-        config = mkOption {
-          type = types.lines;
-          description = ''
-            Configuration of this OpenVPN instance.  See
-            <citerefentry><refentrytitle>openvpn</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-            for details.
-          '';
-        };
+          config = mkOption {
+            type = types.lines;
+            description = ''
+              Configuration of this OpenVPN instance.  See
+              <citerefentry><refentrytitle>openvpn</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+              for details.
+            '';
+          };
 
-        up = mkOption {
-          default = "";
-          type = types.lines;
-          description = ''
-            Shell commands executed when the instance is starting.
-          '';
-        };
+          up = mkOption {
+            default = "";
+            type = types.lines;
+            description = ''
+              Shell commands executed when the instance is starting.
+            '';
+          };
 
-        down = mkOption {
-          default = "";
-          type = types.lines;
-          description = ''
-            Shell commands executed when the instance is shutting down.
-          '';
-        };
+          down = mkOption {
+            default = "";
+            type = types.lines;
+            description = ''
+              Shell commands executed when the instance is shutting down.
+            '';
+          };
 
-        autoStart = mkOption {
-          default = true;
-          type = types.bool;
-          description = "Whether this OpenVPN instance should be started automatically.";
-        };
+          autoStart = mkOption {
+            default = true;
+            type = types.bool;
+            description = "Whether this OpenVPN instance should be started automatically.";
+          };
+
+          updateResolvConf = mkOption {
+            default = false;
+            type = types.bool;
+            description = ''
+              Use the script from the update-resolv-conf package to automatically
+              update resolv.conf with the DNS information provided by openvpn. The
+              script will be run after the "up" commands and before the "down" commands.
+            '';
+          };
 
-        updateResolvConf = mkOption {
-          default = false;
-          type = types.bool;
-          description = ''
-            Use the script from the update-resolv-conf package to automatically
-            update resolv.conf with the DNS information provided by openvpn. The
-            script will be run after the "up" commands and before the "down" commands.
-          '';
         };
 
-      };
+      });
 
     };
 
diff --git a/nixos/modules/services/networking/powerdns.nix b/nixos/modules/services/networking/powerdns.nix
index 91ad63b88139..ba05e15389f6 100644
--- a/nixos/modules/services/networking/powerdns.nix
+++ b/nixos/modules/services/networking/powerdns.nix
@@ -35,7 +35,6 @@ in {
         Restart="on-failure";
         RestartSec="1";
         StartLimitInterval="0";
-        PrivateTmp=true;
         PrivateDevices=true;
         CapabilityBoundingSet="CAP_CHOWN CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT";
         NoNewPrivileges=true;
diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix
index f82f8bfddbb7..247c4f1efb07 100644
--- a/nixos/modules/services/networking/prosody.nix
+++ b/nixos/modules/services/networking/prosody.nix
@@ -164,7 +164,7 @@ in
 
         description = "Define the virtual hosts";
 
-        type = types.loaOf types.optionSet;
+        type = with types; loaOf (submodule vHostOpts);
 
         example = {
           myhost = {
@@ -180,7 +180,6 @@ in
           };
         };
 
-        options = [ vHostOpts ];
       };
 
       ssl = mkOption {
diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix
index d5e2e3041b49..f9300fdabc57 100644
--- a/nixos/modules/services/networking/radicale.nix
+++ b/nixos/modules/services/networking/radicale.nix
@@ -33,7 +33,7 @@ in
   };
 
   config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.pythonPackages.radicale ];
+    environment.systemPackages = [ pkgs.radicale ];
 
     users.extraUsers = singleton
       { name = "radicale";
@@ -50,9 +50,9 @@ in
 
     systemd.services.radicale = {
       description = "A Simple Calendar and Contact Server";
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      script = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -f";
+      script = "${pkgs.radicale}/bin/radicale -C ${confFile} -f";
       serviceConfig.User = "radicale";
       serviceConfig.Group = "radicale";
     };
diff --git a/nixos/modules/services/networking/softether.nix b/nixos/modules/services/networking/softether.nix
index 5e49efc3aa3a..16530078b978 100644
--- a/nixos/modules/services/networking/softether.nix
+++ b/nixos/modules/services/networking/softether.nix
@@ -63,7 +63,6 @@ in
         ];
       systemd.services."softether-init" = {
         description = "SoftEther VPN services initial task";
-        wantedBy = [ "network-interfaces.target" ];
         serviceConfig = {
           Type = "oneshot";
           RemainAfterExit = false;
@@ -84,8 +83,9 @@ in
     (mkIf (cfg.vpnserver.enable) {
       systemd.services.vpnserver = {
         description = "SoftEther VPN Server";
-        after = [ "softether-init.service" ];
-        wantedBy = [ "network-interfaces.target" ];
+        after = [ "softether-init.service" "network.target" ];
+        wants = [ "softether-init.service" ];
+        wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           Type = "forking";
           ExecStart = "${pkg}/bin/vpnserver start";
@@ -104,8 +104,9 @@ in
     (mkIf (cfg.vpnbridge.enable) {
       systemd.services.vpnbridge = {
         description = "SoftEther VPN Bridge";
-        after = [ "softether-init.service" ];
-        wantedBy = [ "network-interfaces.target" ];
+        after = [ "softether-init.service" "network.target" ];
+        wants = [ "softether-init.service" ];
+        wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           Type = "forking";
           ExecStart = "${pkg}/bin/vpnbridge start";
@@ -124,8 +125,9 @@ in
     (mkIf (cfg.vpnclient.enable) {
       systemd.services.vpnclient = {
         description = "SoftEther VPN Client";
-        after = [ "softether-init.service" ];
-        wantedBy = [ "network-interfaces.target" ];
+        after = [ "softether-init.service" "network.target" ];
+        wants = [ "softether-init.service" ];
+        wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           Type = "forking";
           ExecStart = "${pkg}/bin/vpnclient start";
diff --git a/nixos/modules/services/networking/ssh/lshd.nix b/nixos/modules/services/networking/ssh/lshd.nix
index 661a6a524631..eca599afb33b 100644
--- a/nixos/modules/services/networking/ssh/lshd.nix
+++ b/nixos/modules/services/networking/ssh/lshd.nix
@@ -120,7 +120,7 @@ in
     systemd.services.lshd = {
       description = "GNU lshd SSH2 daemon";
 
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
 
       wantedBy = [ "multi-user.target" ];
 
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 1d15a1419722..3e9fae35847e 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -102,8 +102,8 @@ in
       };
 
       permitRootLogin = mkOption {
-        default = "without-password";
-        type = types.enum ["yes" "without-password" "forced-commands-only" "no"];
+        default = "prohibit-password";
+        type = types.enum ["yes" "without-password" "prohibit-password" "forced-commands-only" "no"];
         description = ''
           Whether the root user can login using ssh.
         '';
@@ -129,7 +129,24 @@ in
       };
 
       listenAddresses = mkOption {
-        type = types.listOf types.optionSet;
+        type = with types; listOf (submodule {
+          options = {
+            addr = mkOption {
+              type = types.nullOr types.str;
+              default = null;
+              description = ''
+                Host, IPv4 or IPv6 address to listen to.
+              '';
+            };
+            port = mkOption {
+              type = types.nullOr types.int;
+              default = null;
+              description = ''
+                Port to listen to.
+              '';
+            };
+          };
+        });
         default = [];
         example = [ { addr = "192.168.3.1"; port = 22; } { addr = "0.0.0.0"; port = 64022; } ];
         description = ''
@@ -140,22 +157,6 @@ in
           NOTE: setting this option won't automatically enable given ports
           in firewall configuration.
         '';
-        options = {
-          addr = mkOption {
-            type = types.nullOr types.str;
-            default = null;
-            description = ''
-              Host, IPv4 or IPv6 address to listen to.
-            '';
-          };
-          port = mkOption {
-            type = types.nullOr types.int;
-            default = null;
-            description = ''
-              Port to listen to.
-            '';
-          };
-        };
       };
 
       passwordAuthentication = mkOption {
diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix
index 16c4ee7e33bb..e433ec7c5b9b 100644
--- a/nixos/modules/services/networking/supplicant.nix
+++ b/nixos/modules/services/networking/supplicant.nix
@@ -34,7 +34,7 @@ let
       '';
     in
       { description = "Supplicant ${iface}${optionalString (iface=="WLAN"||iface=="LAN") " %I"}";
-        wantedBy = [ "network.target" ];
+        wantedBy = [ "network.target" ] ++ deps;
         bindsTo = deps;
         after = deps;
         before = [ "network.target" ];
@@ -75,7 +75,107 @@ in
   options = {
 
     networking.supplicant = mkOption {
-      type = types.attrsOf types.optionSet;
+      type = with types; attrsOf (submodule {
+        options = {
+  
+          configFile = {
+  
+            path = mkOption {
+              type = types.path;
+              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
+                precedence over options defined in <literal>configFile</literal>.
+              '';
+            };
+  
+            writable = mkOption {
+              type = types.bool;
+              default = false;
+              description = ''
+                Whether the configuration file at <literal>configFile.path</literal> should be written to by
+                <literal>wpa_supplicant</literal>.
+              '';
+            };
+  
+          };
+  
+          extraConf = mkOption {
+            type = types.lines;
+            default = "";
+            example = ''
+              ap_scan=1
+              device_name=My-NixOS-Device
+              device_type=1-0050F204-1
+              driver_param=use_p2p_group_interface=1
+              disable_scan_offload=1
+              p2p_listen_reg_class=81
+              p2p_listen_channel=1
+              p2p_oper_reg_class=81
+              p2p_oper_channel=1
+              manufacturer=NixOS
+              model_name=NixOS_Unstable
+              model_number=2015
+            '';
+            description = ''
+              Configuration options for <literal>wpa_supplicant.conf</literal>.
+              Options defined here have precedence over options in <literal>configFile</literal>.
+              NOTE: Do not write sensitive data into <literal>extraConf</literal> as it will
+              be world-readable in the <literal>nix-store</literal>. For sensitive information
+              use the <literal>configFile</literal> instead.
+            '';
+          };
+  
+          extraCmdArgs = mkOption {
+            type = types.str;
+            default = "";
+            example = "-e/var/run/wpa_supplicant/entropy.bin";
+            description =
+              "Command line arguments to add when executing <literal>wpa_supplicant</literal>.";
+          };
+  
+          driver = mkOption {
+            type = types.nullOr types.str;
+            default = "nl80211,wext";
+            description = "Force a specific wpa_supplicant driver.";
+          };
+  
+          bridge = mkOption {
+            type = types.str;
+            default = "";
+            description = "Name of the bridge interface that wpa_supplicant should listen at.";
+          };
+  
+          userControlled = {
+  
+            enable = mkOption {
+              type = types.bool;
+              default = false;
+              description = ''
+                Allow normal users to control wpa_supplicant through wpa_gui or wpa_cli.
+                This is useful for laptop users that switch networks a lot and don't want
+                to depend on a large package such as NetworkManager just to pick nearby
+                access points.
+              '';
+            };
+  
+            socketDir = mkOption {
+              type = types.str;
+              default = "/var/run/wpa_supplicant";
+              description = "Directory of sockets for controlling wpa_supplicant.";
+            };
+  
+            group = mkOption {
+              type = types.str;
+              default = "wheel";
+              example = "network";
+              description = "Members of this group can control wpa_supplicant.";
+            };
+  
+          };
+        };
+      });
 
       default = { };
 
@@ -109,107 +209,6 @@ in
         service that can be accessed through <literal>D-Bus</literal>.
       '';
 
-      options = {
-
-        configFile = {
-
-          path = mkOption {
-            type = types.path;
-            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
-              precedence over options defined in <literal>configFile</literal>.
-            '';
-          };
-
-          writable = mkOption {
-            type = types.bool;
-            default = false;
-            description = ''
-              Whether the configuration file at <literal>configFile.path</literal> should be written to by
-              <literal>wpa_supplicant</literal>.
-            '';
-          };
-
-        };
-
-        extraConf = mkOption {
-          type = types.lines;
-          default = "";
-          example = ''
-            ap_scan=1
-            device_name=My-NixOS-Device
-            device_type=1-0050F204-1
-            driver_param=use_p2p_group_interface=1
-            disable_scan_offload=1
-            p2p_listen_reg_class=81
-            p2p_listen_channel=1
-            p2p_oper_reg_class=81
-            p2p_oper_channel=1
-            manufacturer=NixOS
-            model_name=NixOS_Unstable
-            model_number=2015
-          '';
-          description = ''
-            Configuration options for <literal>wpa_supplicant.conf</literal>.
-            Options defined here have precedence over options in <literal>configFile</literal>.
-            NOTE: Do not write sensitive data into <literal>extraConf</literal> as it will
-            be world-readable in the <literal>nix-store</literal>. For sensitive information
-            use the <literal>configFile</literal> instead.
-          '';
-        };
-
-        extraCmdArgs = mkOption {
-          type = types.str;
-          default = "";
-          example = "-e/var/run/wpa_supplicant/entropy.bin";
-          description =
-            "Command line arguments to add when executing <literal>wpa_supplicant</literal>.";
-        };
-
-        driver = mkOption {
-          type = types.nullOr types.str;
-          default = "nl80211,wext";
-          description = "Force a specific wpa_supplicant driver.";
-        };
-
-        bridge = mkOption {
-          type = types.str;
-          default = "";
-          description = "Name of the bridge interface that wpa_supplicant should listen at.";
-        };
-
-        userControlled = {
-
-          enable = mkOption {
-            type = types.bool;
-            default = false;
-            description = ''
-              Allow normal users to control wpa_supplicant through wpa_gui or wpa_cli.
-              This is useful for laptop users that switch networks a lot and don't want
-              to depend on a large package such as NetworkManager just to pick nearby
-              access points.
-            '';
-          };
-
-          socketDir = mkOption {
-            type = types.str;
-            default = "/var/run/wpa_supplicant";
-            description = "Directory of sockets for controlling wpa_supplicant.";
-          };
-
-          group = mkOption {
-            type = types.str;
-            default = "wheel";
-            example = "network";
-            description = "Members of this group can control wpa_supplicant.";
-          };
-
-        };
-
-      };
-
     };
 
   };
diff --git a/nixos/modules/services/networking/tcpcrypt.nix b/nixos/modules/services/networking/tcpcrypt.nix
index 267653abce03..2f304165eb4b 100644
--- a/nixos/modules/services/networking/tcpcrypt.nix
+++ b/nixos/modules/services/networking/tcpcrypt.nix
@@ -39,7 +39,7 @@ in
       description = "tcpcrypt";
 
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
 
       path = [ pkgs.iptables pkgs.tcpcrypt pkgs.procps ];
 
diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix
index 8da0f817ae2a..b26d30597b1f 100644
--- a/nixos/modules/services/networking/tinc.nix
+++ b/nixos/modules/services/networking/tinc.nix
@@ -18,94 +18,96 @@ in
 
       networks = mkOption {
         default = { };
-        type = types.loaOf types.optionSet;
+        type = with types; loaOf (submodule {
+          options = {
+
+            extraConfig = mkOption {
+              default = "";
+              type = types.lines;
+              description = ''
+                Extra lines to add to the tinc service configuration file.
+              '';
+            };
+
+            name = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              description = ''
+                The name of the node which is used as an identifier when communicating
+                with the remote nodes in the mesh. If null then the hostname of the system
+                is used.
+              '';
+            };
+
+            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);
+              description = ''
+                The amount of debugging information to add to the log. 0 means little
+                logging while 5 is the most logging. <command>man tincd</command> for
+                more details.
+              '';
+            };
+
+            hosts = mkOption {
+              default = { };
+              type = types.loaOf types.lines;
+              description = ''
+                The name of the host in the network as well as the configuration for that host.
+                This name should only contain alphanumerics and underscores.
+              '';
+            };
+
+            interfaceType = mkOption {
+              default = "tun";
+              type = types.addCheck types.str (n: n == "tun" || n == "tap");
+              description = ''
+                The type of virtual interface used for the network connection
+              '';
+            };
+
+            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.
+              '';
+            };
+
+            chroot = mkOption {
+              default = true;
+              type = types.bool;
+              description = ''
+                Change process root directory to the directory where the config file is located (/etc/tinc/netname/), for added security.
+                The chroot is performed after all the initialization is done, after writing pid files and opening network sockets.
+
+                Note that tinc can't run scripts anymore (such as tinc-down or host-up), unless it is setup to be runnable inside chroot environment.
+              '';
+            };
+          };
+        });
+
         description = ''
           Defines the tinc networks which will be started.
           Each network invokes a different daemon.
         '';
-        options = {
-
-          extraConfig = mkOption {
-            default = "";
-            type = types.lines;
-            description = ''
-              Extra lines to add to the tinc service configuration file.
-            '';
-          };
-
-          name = mkOption {
-            default = null;
-            type = types.nullOr types.str;
-            description = ''
-              The name of the node which is used as an identifier when communicating
-              with the remote nodes in the mesh. If null then the hostname of the system
-              is used.
-            '';
-          };
-
-          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);
-            description = ''
-              The amount of debugging information to add to the log. 0 means little
-              logging while 5 is the most logging. <command>man tincd</command> for
-              more details.
-            '';
-          };
-
-          hosts = mkOption {
-            default = { };
-            type = types.loaOf types.lines;
-            description = ''
-              The name of the host in the network as well as the configuration for that host.
-              This name should only contain alphanumerics and underscores.
-            '';
-          };
-
-          interfaceType = mkOption {
-            default = "tun";
-            type = types.addCheck types.str (n: n == "tun" || n == "tap");
-            description = ''
-              The type of virtual interface used for the network connection
-            '';
-          };
-
-          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.
-            '';
-          };
-
-          chroot = mkOption {
-            default = true;
-            type = types.bool;
-            description = ''
-              Change process root directory to the directory where the config file is located (/etc/tinc/netname/), for added security.
-              The chroot is performed after all the initialization is done, after writing pid files and opening network sockets.
-
-              Note that tinc can't run scripts anymore (such as tinc-down or host-up), unless it is setup to be runnable inside chroot environment.
-            '';
-          };
-        };
       };
     };
 
@@ -149,8 +151,8 @@ in
       ("tinc.${network}")
       ({
         description = "Tinc Daemon - ${network}";
-        wantedBy = [ "network.target" ];
-        after = [ "network-interfaces.target" ];
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
         path = [ data.package ];
         restartTriggers = [ config.environment.etc."tinc/${network}/tinc.conf".source ]
           ++ mapAttrsToList (host: _ : config.environment.etc."tinc/${network}/hosts/${host}".source) data.hosts;
diff --git a/nixos/modules/services/networking/wicd.nix b/nixos/modules/services/networking/wicd.nix
index 9e5a437b4856..03c6bd28aaba 100644
--- a/nixos/modules/services/networking/wicd.nix
+++ b/nixos/modules/services/networking/wicd.nix
@@ -26,7 +26,9 @@ with lib;
     environment.systemPackages = [pkgs.wicd];
 
     systemd.services.wicd = {
-      after = [ "network-interfaces.target" ];
+      after = [ "network-pre.target" ];
+      before = [ "network.target" ];
+      wants = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       script = "${pkgs.wicd}/sbin/wicd -f";
     };
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index de99ce4f0260..a344d7855463 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -128,9 +128,9 @@ in {
     in {
       description = "WPA Supplicant";
 
-      after = [ "network-interfaces.target" ] ++ lib.concatMap deviceUnit ifaces;
+      after = [ "network.target" ] ++ lib.concatMap deviceUnit ifaces;
       requires = lib.concatMap deviceUnit ifaces;
-      wantedBy = [ "network.target" ];
+      wantedBy = [ "network-online.target" ];
 
       path = [ pkgs.wpa_supplicant ];
 
diff --git a/nixos/modules/services/networking/xinetd.nix b/nixos/modules/services/networking/xinetd.nix
index 08680b517808..270122ee659c 100644
--- a/nixos/modules/services/networking/xinetd.nix
+++ b/nixos/modules/services/networking/xinetd.nix
@@ -65,71 +65,73 @@ in
         A list of services provided by xinetd.
       '';
 
-      type = types.listOf types.optionSet;
+      type = with types; listOf (submodule ({
+
+        options = {
+
+          name = mkOption {
+            type = types.string;
+            example = "login";
+            description = "Name of the service.";
+          };
+
+          protocol = mkOption {
+            type = types.string;
+            default = "tcp";
+            description =
+              "Protocol of the service.  Usually <literal>tcp</literal> or <literal>udp</literal>.";
+          };
+
+          port = mkOption {
+            type = types.int;
+            default = 0;
+            example = 123;
+            description = "Port number of the service.";
+          };
+
+          user = mkOption {
+            type = types.string;
+            default = "nobody";
+            description = "User account for the service";
+          };
+
+          server = mkOption {
+            type = types.string;
+            example = "/foo/bin/ftpd";
+            description = "Path of the program that implements the service.";
+          };
+
+          serverArgs = mkOption {
+            type = types.string;
+            default = "";
+            description = "Command-line arguments for the server program.";
+          };
+
+          flags = mkOption {
+            type = types.string;
+            default = "";
+            description = "";
+          };
+
+          unlisted = mkOption {
+            type = types.bool;
+            default = false;
+            description = ''
+              Whether this server is listed in
+              <filename>/etc/services</filename>.  If so, the port
+              number can be omitted.
+            '';
+          };
+
+          extraConfig = mkOption {
+            type = types.string;
+            default = "";
+            description = "Extra configuration-lines added to the section of the service.";
+          };
 
-      options = {
-
-        name = mkOption {
-          type = types.string;
-          example = "login";
-          description = "Name of the service.";
-        };
-
-        protocol = mkOption {
-          type = types.string;
-          default = "tcp";
-          description =
-            "Protocol of the service.  Usually <literal>tcp</literal> or <literal>udp</literal>.";
-        };
-
-        port = mkOption {
-          type = types.int;
-          default = 0;
-          example = 123;
-          description = "Port number of the service.";
-        };
-
-        user = mkOption {
-          type = types.string;
-          default = "nobody";
-          description = "User account for the service";
-        };
-
-        server = mkOption {
-          type = types.string;
-          example = "/foo/bin/ftpd";
-          description = "Path of the program that implements the service.";
-        };
-
-        serverArgs = mkOption {
-          type = types.string;
-          default = "";
-          description = "Command-line arguments for the server program.";
-        };
-
-        flags = mkOption {
-          type = types.string;
-          default = "";
-          description = "";
-        };
-
-        unlisted = mkOption {
-          type = types.bool;
-          default = false;
-          description = ''
-            Whether this server is listed in
-            <filename>/etc/services</filename>.  If so, the port
-            number can be omitted.
-          '';
-        };
-
-        extraConfig = mkOption {
-          type = types.string;
-          default = "";
-          description = "Extra configuration-lines added to the section of the service.";
         };
 
-      };
+      }));
 
     };
 
@@ -141,7 +143,7 @@ in
   config = mkIf cfg.enable {
     systemd.services.xinetd = {
       description = "xinetd server";
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       path = [ pkgs.xinetd ];
       script = "xinetd -syslog daemon -dontfork -stayalive -f ${configFile}";
diff --git a/nixos/modules/services/networking/zerobin.nix b/nixos/modules/services/networking/zerobin.nix
index 1c524602f8e9..274bbca53fa3 100644
--- a/nixos/modules/services/networking/zerobin.nix
+++ b/nixos/modules/services/networking/zerobin.nix
@@ -86,15 +86,15 @@ in
 
       systemd.services.zerobin = {
         enable = true;
-        after = [ "network-interfaces.target" ];
+        after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
         serviceConfig.ExecStart = "${pkgs.pythonPackages.zerobin}/bin/zerobin ${cfg.listenAddress} ${toString cfg.listenPort} false ${cfg.user} ${cfg.group} ${zerobin_config}";
         serviceConfig.PrivateTmp="yes";
         serviceConfig.User = cfg.user;
         serviceConfig.Group = cfg.group;
         preStart = ''
-        mkdir -p ${cfg.dataDir}
-        chown ${cfg.user} ${cfg.dataDir}
+          mkdir -p ${cfg.dataDir}
+          chown ${cfg.user} ${cfg.dataDir}
         '';
       };
     };
diff --git a/nixos/modules/services/scheduling/chronos.nix b/nixos/modules/services/scheduling/chronos.nix
index db1f0f5f00c9..6c39997fec88 100644
--- a/nixos/modules/services/scheduling/chronos.nix
+++ b/nixos/modules/services/scheduling/chronos.nix
@@ -41,7 +41,7 @@ in {
     systemd.services.chronos = {
       description = "Chronos Service";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" "zookeeper.service" ];
+      after = [ "network.target" "zookeeper.service" ];
 
       serviceConfig = {
         ExecStart = "${pkgs.chronos}/bin/chronos --master ${cfg.master} --zk_hosts ${concatStringsSep "," cfg.zookeeperHosts} --http_port ${toString cfg.httpPort}";
diff --git a/nixos/modules/services/scheduling/marathon.nix b/nixos/modules/services/scheduling/marathon.nix
index 4e837c62dc11..19c9a708f21f 100644
--- a/nixos/modules/services/scheduling/marathon.nix
+++ b/nixos/modules/services/scheduling/marathon.nix
@@ -83,7 +83,7 @@ in {
       description = "Marathon Service";
       environment = cfg.environment;
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" "zookeeper.service" "mesos-master.service" "mesos-slave.service" ];
+      after = [ "network.target" "zookeeper.service" "mesos-master.service" "mesos-slave.service" ];
 
       serviceConfig = {
         ExecStart = "${pkgs.marathon}/bin/marathon --master ${cfg.master} --zk zk://${concatStringsSep "," cfg.zookeeperHosts}/marathon --http_port ${toString cfg.httpPort} ${concatStringsSep " " cfg.extraCmdLineOptions}";
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index 9299aaac2f70..574f74d547a5 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -129,7 +129,7 @@ in {
     systemd.services.elasticsearch = {
       description = "Elasticsearch Daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       path = [ pkgs.inetutils ];
       environment = {
         ES_HOME = cfg.dataDir;
diff --git a/nixos/modules/services/search/kibana.nix b/nixos/modules/services/search/kibana.nix
index 033b8139d341..d377a6feeb8e 100644
--- a/nixos/modules/services/search/kibana.nix
+++ b/nixos/modules/services/search/kibana.nix
@@ -138,7 +138,7 @@ in {
     systemd.services.kibana = {
       description = "Kibana Service";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" "elasticsearch.service" ];
+      after = [ "network.target" "elasticsearch.service" ];
       environment = { BABEL_CACHE_PATH = "${cfg.dataDir}/.babelcache.json"; };
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/kibana --config ${cfgFile}";
diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2_proxy.nix
index 4c20392214fc..caa7d9d50812 100644
--- a/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixos/modules/services/security/oauth2_proxy.nix
@@ -510,7 +510,7 @@ in
       description = "OAuth2 Proxy";
       path = [ cfg.package ];
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
 
       serviceConfig = {
         User = "oauth2_proxy";
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index 6c4833afbe8b..a7cf74c15cc5 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -8,7 +8,7 @@ let
 
   cfg = config.services.dbus;
 
-  homeDir = "/var/run/dbus";
+  homeDir = "/run/dbus";
 
   systemExtraxml = concatStrings (flip concatMap cfg.packages (d: [
     "<servicedir>${d}/share/dbus-1/system-services</servicedir>"
@@ -20,15 +20,23 @@ let
     "<includedir>${d}/etc/dbus-1/session.d</includedir>"
   ]));
 
-  configDir = pkgs.stdenv.mkDerivation {
-    name = "dbus-conf";
+  daemonArgs = "--address=systemd: --nofork --nopidfile --systemd-activation";
 
-    preferLocalBuild = true;
-    allowSubstitutes = false;
-
-    buildCommand = ''
+  configDir = pkgs.runCommand "dbus-conf"
+    { preferLocalBuild = true;
+      allowSubstitutes = false;
+    }
+    ''
       mkdir -p $out
 
+      cp ${pkgs.dbus.out}/share/dbus-1/{system,session}.conf $out
+
+      # avoid circular includes
+      sed -ri 's@(<include ignore_missing="yes">/etc/dbus-1/(system|session)\.conf</include>)@<!-- \1 -->@g' $out/{system,session}.conf
+
+      # include by full path
+      sed -ri "s@/etc/dbus-1/(system|session)-@$out/\1-@" $out/{system,session}.conf
+
       sed '${./dbus-system-local.conf.in}' \
         -e 's,@servicehelper@,${config.security.wrapperDir}/dbus-daemon-launch-helper,g' \
         -e 's,@extra@,${systemExtraxml},' \
@@ -38,7 +46,6 @@ let
         -e 's,@extra@,${sessionExtraxml},' \
         > "$out/session-local.conf"
     '';
-  };
 
 in
 
@@ -75,11 +82,16 @@ in
         '';
       };
 
+      socketActivated = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Make the user instance socket activated.
+        '';
+      };
     };
-
   };
 
-
   ###### implementation
 
   config = mkIf cfg.enable {
@@ -117,13 +129,29 @@ in
       config.system.path
     ];
 
-    # Don't restart dbus-daemon. Bad things tend to happen if we do.
-    systemd.services.dbus.reloadIfChanged = true;
+    systemd.services.dbus = {
+      # Don't restart dbus-daemon. Bad things tend to happen if we do.
+      reloadIfChanged = true;
+      restartTriggers = [ configDir ];
+      serviceConfig.ExecStart = [
+        ""
+        "${lib.getBin pkgs.dbus}/bin/dbus-daemon --config-file=${configDir}/system.conf ${daemonArgs}"
+      ];
+    };
 
-    systemd.services.dbus.restartTriggers = [ configDir ];
+    systemd.user = {
+      services.dbus = {
+        # Don't restart dbus-daemon. Bad things tend to happen if we do.
+        reloadIfChanged = true;
+        restartTriggers = [ configDir ];
+        serviceConfig.ExecStart = [
+          ""
+          "${lib.getBin pkgs.dbus}/bin/dbus-daemon --config-file=${configDir}/session.conf ${daemonArgs}"
+        ];
+      };
+      sockets.dbus.wantedBy = mkIf cfg.socketActivated [ "sockets.target" ];
+    };
 
     environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ];
-
   };
-
 }
diff --git a/nixos/modules/services/torrent/opentracker.nix b/nixos/modules/services/torrent/opentracker.nix
new file mode 100644
index 000000000000..d86b9fea2d79
--- /dev/null
+++ b/nixos/modules/services/torrent/opentracker.nix
@@ -0,0 +1,44 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.opentracker;
+in {
+  options.services.opentracker = {
+    enable = mkEnableOption "opentracker";
+
+    package = mkOption {
+      type = types.package;
+      description = ''
+        opentracker package to use
+      '';
+      default = pkgs.opentracker;
+    };
+
+    extraOptions = mkOption {
+      type = types.separatedString " ";
+      description = ''
+        Configuration Arguments for opentracker
+        See https://erdgeist.org/arts/software/opentracker/ for all params
+      '';
+      default = "";
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+
+    systemd.services.opentracker = {
+      description = "opentracker server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      restartIfChanged = true;
+      serviceConfig = {
+        ExecStart = "${cfg.package}/bin/opentracker ${cfg.extraOptions}";
+        PrivateTmp = true;
+        WorkingDirectory = "/var/empty";
+        # By default opentracker drops all privileges and runs in chroot after starting up as root.
+      };
+    };
+  };
+}
+
diff --git a/nixos/modules/services/torrent/peerflix.nix b/nixos/modules/services/torrent/peerflix.nix
index 38fbd3b226cd..2e3dd9902d72 100644
--- a/nixos/modules/services/torrent/peerflix.nix
+++ b/nixos/modules/services/torrent/peerflix.nix
@@ -42,7 +42,7 @@ in {
     systemd.services.peerflix = {
       description = "Peerflix Daemon";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       environment.HOME = cfg.stateDir;
 
       preStart = ''
diff --git a/nixos/modules/services/web-apps/selfoss.nix b/nixos/modules/services/web-apps/selfoss.nix
new file mode 100644
index 000000000000..5571f77334cc
--- /dev/null
+++ b/nixos/modules/services/web-apps/selfoss.nix
@@ -0,0 +1,166 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  cfg = config.services.selfoss;
+
+  poolName = "selfoss_pool";
+  phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock";
+
+  dataDir = "/var/lib/selfoss";
+
+  selfoss-config =
+  let
+    db_type = cfg.database.type;
+    default_port = if (db_type == "mysql") then 3306 else 5342;
+  in
+  pkgs.writeText "selfoss-config.ini" ''
+    [globals]
+    ${lib.optionalString (db_type != "sqlite") ''
+      db_type=${db_type}
+      db_host=${cfg.database.host}
+      db_database=${cfg.database.name}
+      db_username=${cfg.database.user}
+      db_password=${cfg.database.password}
+      db_port=${if (cfg.database.port != null) then cfg.database.port
+                    else default_port}
+    ''
+    }
+    ${cfg.extraConfig}
+  '';
+in
+  {
+    options = {
+      services.selfoss = {
+        enable = mkEnableOption "selfoss";
+
+        user = mkOption {
+          type = types.str;
+          default = "nginx";
+          example = "nginx";
+          description = ''
+            User account under which both the service and the web-application run.
+          '';
+        };
+
+        pool = mkOption {
+          type = types.str;
+          default = "${poolName}";
+          description = ''
+            Name of existing phpfpm pool that is used to run web-application.
+            If not specified a pool will be created automatically with
+            default values.
+          '';
+        };
+
+      database = {
+        type = mkOption {
+          type = types.enum ["pgsql" "mysql" "sqlite"];
+          default = "sqlite";
+          description = ''
+            Database to store feeds. Supported are sqlite, pgsql and mysql.
+          '';
+        };
+
+        host = mkOption {
+          type = types.str;
+          default = "localhost";
+          description = ''
+            Host of the database (has no effect if type is "sqlite").
+          '';
+        };
+
+        name = mkOption {
+          type = types.str;
+          default = "tt_rss";
+          description = ''
+            Name of the existing database (has no effect if type is "sqlite").
+          '';
+        };
+
+        user = mkOption {
+          type = types.str;
+          default = "tt_rss";
+          description = ''
+            The database user. The user must exist and has access to
+            the specified database (has no effect if type is "sqlite").
+          '';
+        };
+
+        password = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          description = ''
+            The database user's password (has no effect if type is "sqlite").
+          '';
+        };
+
+        port = mkOption {
+          type = types.nullOr types.int;
+          default = null;
+          description = ''
+            The database's port. If not set, the default ports will be
+            provided (5432 and 3306 for pgsql and mysql respectively)
+            (has no effect if type is "sqlite").
+          '';
+        };
+      };
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra configuration added to config.ini
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") {
+      "${poolName}" = ''
+        listen = "${phpfpmSocketName}";
+        listen.owner = nginx
+        listen.group = nginx
+        listen.mode = 0600
+        user = nginx
+        pm = dynamic
+        pm.max_children = 75
+        pm.start_servers = 10
+        pm.min_spare_servers = 5
+        pm.max_spare_servers = 20
+        pm.max_requests = 500
+        catch_workers_output = 1
+      '';
+    };
+
+    systemd.services.selfoss-config = {
+      serviceConfig.Type = "oneshot";
+      script = ''
+        mkdir -m 755 -p ${dataDir}
+        cd ${dataDir}
+
+        # Delete all but the "data" folder
+        ls | grep -v data | while read line; do rm -rf $line; done || true
+
+        # Create the files
+        cp -r "${pkgs.selfoss}/"* "${dataDir}"
+        ln -sf "${selfoss-config}" "${dataDir}/config.ini"
+        chown -R "${cfg.user}" "${dataDir}"
+        chmod -R 755 "${dataDir}"
+      '';
+      wantedBy = [ "multi-user.target" ];
+    };
+
+    systemd.services.selfoss-update = {
+      serviceConfig = {
+        ExecStart = "${pkgs.php}/bin/php ${dataDir}/cliupdate.php";
+        User = "${cfg.user}";
+      };
+      startAt = "hourly";
+      after = [ "selfoss-config.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+    };
+
+  };
+}
diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
index b4b5a6fdc07e..4f9e9f52f9e0 100644
--- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
@@ -83,11 +83,11 @@ let
 
   # Unpack Mediawiki and put the config file in its root directory.
   mediawikiRoot = pkgs.stdenv.mkDerivation rec {
-    name= "mediawiki-1.23.13";
+    name= "mediawiki-1.27.1";
 
     src = pkgs.fetchurl {
-      url = "http://download.wikimedia.org/mediawiki/1.23/${name}.tar.gz";
-      sha256 = "168wpf53n4ksj2g5q5r0hxapx6238dvsfng5ff9ixk6axsn0j5d0";
+      url = "http://download.wikimedia.org/mediawiki/1.27/${name}.tar.gz";
+      sha256 = "0sm3ymz93qragbwhzzbwq7f127mbj29inv0afg2z6p32jb1pd9h8";
     };
 
     skins = config.skins;
diff --git a/nixos/modules/services/web-servers/apache-httpd/moodle.nix b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
index 87b1fba5aa10..aa00e89967db 100644
--- a/nixos/modules/services/web-servers/apache-httpd/moodle.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
@@ -63,6 +63,10 @@ let
         cp -r * $out
         cp ${moodleConfig} $out/config.php
       '';
+    # Marked as broken due to needing an update for security issues.
+    # See: https://github.com/NixOS/nixpkgs/issues/18856
+    meta.broken = true;
+
   };
 
 in
diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
index 937b2698ce9b..2315c4729aec 100644
--- a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
@@ -5,7 +5,8 @@ with lib;
 
 let
 
-  version = "4.3.1";
+  # Upgrading? We have a test! nix-build ./nixos/tests/wordpress.nix
+  version = "4.6.1";
   fullversion = "${version}";
 
   # Our bare-bones wp-config.php file using the above settings
@@ -74,7 +75,7 @@ let
       owner = "WordPress";
       repo = "WordPress";
       rev = "${fullversion}";
-      sha256 = "1rk10vcv4z9p04hfzc0wkbilrgx7m9ssyr6c3w6vw3vl1bcgqxza";
+      sha256 = "0n82xgjg1ry2p73hhgpslnkdzrma5n6hxxq76s7qskkzj0qjfvpn";
     };
     installPhase = ''
       mkdir -p $out
@@ -98,7 +99,7 @@ let
       # symlink additional plugin(s)
       ${concatMapStrings (plugin: "ln -s ${plugin} $out/wp-content/plugins/${plugin.name}\n") (config.plugins) }
 
-      # symlink additional translation(s) 
+      # symlink additional translation(s)
       mkdir -p $out/wp-content/languages
       ${concatMapStrings (language: "ln -s ${language}/*.mo ${language}/*.po $out/wp-content/languages/\n") (selectedLanguages) }
     '';
@@ -123,7 +124,7 @@ in
   options = {
     dbHost = mkOption {
       default = "localhost";
-      description = "The location of the database server.";  
+      description = "The location of the database server.";
       example = "localhost";
     };
     dbName = mkOption {
@@ -244,7 +245,6 @@ in
     chown ${serverInfo.serverConfig.user} ${config.wordpressUploads}
 
     # we should use systemd dependencies here
-    #waitForUnit("network-interfaces.target");
     if [ ! -d ${serverInfo.fullConfig.services.mysql.dataDir}/${config.dbName} ]; then
       echo "Need to create the database '${config.dbName}' and grant permissions to user named '${config.dbUser}'."
       # Wait until MySQL is up
@@ -253,7 +253,7 @@ in
       done
       ${pkgs.mysql}/bin/mysql -e 'CREATE DATABASE ${config.dbName};'
       ${pkgs.mysql}/bin/mysql -e 'GRANT ALL ON ${config.dbName}.* TO ${config.dbUser}@localhost IDENTIFIED BY "${config.dbPassword}";'
-    else 
+    else
       echo "Good, no need to do anything database related."
     fi
   '';
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 94c442e165b7..443bd8c10000 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -18,9 +18,13 @@ let
 
     ${cfg.config}
 
-    ${optionalString (cfg.httpConfig == "" && cfg.config == "") ''
-    events {}
+    ${optionalString (cfg.eventsConfig != "" || cfg.config == "") ''
+    events {
+      ${cfg.eventsConfig}
+    }
+    ''}
 
+    ${optionalString (cfg.httpConfig == "" && cfg.config == "") ''
     http {
       include ${cfg.package}/conf/mime.types;
       include ${cfg.package}/conf/fastcgi.conf;
@@ -98,7 +102,6 @@ let
     }''}
 
     ${optionalString (cfg.httpConfig != "") ''
-    events {}
     http {
       include ${cfg.package}/conf/mime.types;
       include ${cfg.package}/conf/fastcgi.conf;
@@ -272,12 +275,20 @@ in
         ";
       };
 
+      eventsConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Configuration lines to be set inside the events block.
+        '';
+      };
+
       appendHttpConfig = mkOption {
         type = types.lines;
         default = "";
         description = "
           Configuration lines to be appended to the generated http block.
-          This is mutually exclusive with using config and httpConfig for 
+          This is mutually exclusive with using config and httpConfig for
           specifying the whole http block verbatim.
         ";
       };
diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix
index 29cfbb8e9a08..a3a23b222fbb 100644
--- a/nixos/modules/services/web-servers/phpfpm/default.nix
+++ b/nixos/modules/services/web-servers/phpfpm/default.nix
@@ -42,7 +42,7 @@ in {
         default = "";
         description = ''
           Extra configuration that should be put in the global section of
-          the PHP FPM configuration file. Do not specify the options
+          the PHP-FPM configuration file. Do not specify the options
           <literal>pid</literal>, <literal>error_log</literal> or
           <literal>daemonize</literal> here, since they are generated by
           NixOS.
@@ -54,7 +54,7 @@ in {
         default = pkgs.php;
         defaultText = "pkgs.php";
         description = ''
-          The PHP package to use for running the FPM service.
+          The PHP package to use for running the PHP-FPM service.
         '';
       };
 
@@ -86,7 +86,7 @@ in {
           }
         '';
         description = ''
-          A mapping between PHP FPM pool names and their configurations.
+          A mapping between PHP-FPM pool names and their configurations.
           See the documentation on <literal>php-fpm.conf</literal> for
           details on configuration directives. If no pools are defined,
           the phpfpm service is disabled.
@@ -98,8 +98,24 @@ in {
           inherit lib;
         }));
         default = {};
+        example = literalExample ''
+         {
+           mypool = {
+             listen = "/path/to/unix/socket";
+             extraConfig = '''
+               user = nobody
+               pm = dynamic
+               pm.max_children = 75
+               pm.start_servers = 10
+               pm.min_spare_servers = 5
+               pm.max_spare_servers = 20
+               pm.max_requests = 500
+             ''';
+           }
+         }'';
         description = ''
-          If no pools are defined, the phpfpm service is disabled.
+          PHP-FPM pools. If no pools or poolConfigs are defined, the PHP-FPM
+          service is disabled.
         '';
       };
     };
diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix
index fa6b4c0629d7..943415e08c64 100644
--- a/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixos/modules/services/web-servers/tomcat.nix
@@ -139,7 +139,7 @@ in
     systemd.services.tomcat = {
       description = "Apache Tomcat server";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" ];
+      after = [ "network.target" ];
       serviceConfig.Type = "oneshot";
       serviceConfig.RemainAfterExit = true;
 
diff --git a/nixos/modules/services/web-servers/winstone.nix b/nixos/modules/services/web-servers/winstone.nix
index 6dab467b35ef..064ead5ce4bb 100644
--- a/nixos/modules/services/web-servers/winstone.nix
+++ b/nixos/modules/services/web-servers/winstone.nix
@@ -113,8 +113,7 @@ in {
   options = {
     services.winstone = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ winstoneOpts ];
+      type = with types; attrsOf (submodule winstoneOpts);
       description = ''
         Defines independent Winstone services, each serving one WAR-file.
       '';
diff --git a/nixos/modules/services/web-servers/zope2.nix b/nixos/modules/services/web-servers/zope2.nix
index ef3cffd582ee..8a453e015577 100644
--- a/nixos/modules/services/web-servers/zope2.nix
+++ b/nixos/modules/services/web-servers/zope2.nix
@@ -74,7 +74,7 @@ in
 
     services.zope2.instances = mkOption {
       default = {};
-      type = types.loaOf types.optionSet;
+      type = with types; loaOf (submodule zope2Opts);
       example = literalExample ''
         {
           plone01 = {
@@ -96,7 +96,6 @@ in
         }
       '';
       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 b3da25448029..dc71531759b8 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -25,9 +25,8 @@ let
     '';
   };
 
-  nixos-gsettings-desktop-schemas = pkgs.stdenv.mkDerivation {
-    name = "nixos-gsettings-desktop-schemas";
-    buildCommand = ''
+  nixos-gsettings-desktop-schemas = pkgs.runCommand "nixos-gsettings-desktop-schemas" {}
+    ''
      mkdir -p $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas
      cp -rf ${gnome3.gsettings_desktop_schemas}/share/gsettings-schemas/gsettings-desktop-schemas*/glib-2.0/schemas/*.xml $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas
 
@@ -46,7 +45,6 @@ let
 
      ${pkgs.glib.dev}/bin/glib-compile-schemas $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/
     '';
-  };
 
 in {
 
diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix
index 1927341e45d4..3aa4821a0521 100644
--- a/nixos/modules/services/x11/desktop-managers/kde4.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde4.nix
@@ -14,7 +14,7 @@ let
   # files), segfault sometimes and consume significant resources.
   # They can be re-enabled in the KDE System Settings under "Desktop
   # Search".
-  nepomukConfig = pkgs.writeTextFile
+  disableNepomuk = pkgs.writeTextFile
     { name = "nepomuk-config";
       destination = "/share/config/nepomukserverrc";
       text =
@@ -70,6 +70,18 @@ in
         type = types.package;
         description = "Custom kde-workspace, used for NixOS rebranding.";
       };
+
+      enablePIM = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Whether to enable PIM support. Note that enabling this pulls in Akonadi and MariaDB as dependencies.";
+      };
+
+      enableNepomuk = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable Nepomuk (deprecated).";
+      };
     };
   };
 
@@ -138,7 +150,6 @@ in
 
           pkgs.kde4.kde_wallpapers # contains kdm's default background
           pkgs.kde4.oxygen_icons
-          pkgs.virtuoso # to enable Nepomuk to find Virtuoso
 
           # Starts KDE's Polkit authentication agent.
           pkgs.kde4.polkit_kde_agent
@@ -149,20 +160,26 @@ in
           xorg.xmessage # so that startkde can show error messages
           xorg.xset # used by startkde, non-essential
           xorg.xauth # used by kdesu
-          pkgs.shared_desktop_ontologies # used by nepomuk
-          pkgs.strigi # used by nepomuk
+        ]
+      ++ optionals cfg.enablePIM
+        [ pkgs.kde4.kdepim_runtime
           pkgs.kde4.akonadi
           pkgs.mysql # used by akonadi
-          pkgs.kde4.kdepim_runtime
         ]
-      ++ lib.optional config.hardware.pulseaudio.enable pkgs.kde4.kmix  # Perhaps this should always be enabled
-      ++ lib.optional config.hardware.bluetooth.enable pkgs.kde4.bluedevil
-      ++ lib.optional config.networking.networkmanager.enable pkgs.kde4.plasma-nm
-      ++ [ nepomukConfig ] ++ phononBackendPackages;
+      ++ (if cfg.enableNepomuk then
+        [ pkgs.shared_desktop_ontologies # used by nepomuk
+          pkgs.strigi # used by nepomuk
+          pkgs.virtuoso # to enable Nepomuk to find Virtuoso
+        ] else
+        [ disableNepomuk ])
+      ++ optional config.hardware.pulseaudio.enable pkgs.kde4.kmix  # Perhaps this should always be enabled
+      ++ optional config.hardware.bluetooth.enable pkgs.kde4.bluedevil
+      ++ optional config.networking.networkmanager.enable pkgs.kde4.plasma-nm
+      ++ phononBackendPackages;
 
     environment.pathsToLink = [ "/share" ];
 
-    environment.profileRelativeEnvVars = mkIf (lib.elem "gstreamer" cfg.phononBackends) {
+    environment.profileRelativeEnvVars = mkIf (elem "gstreamer" cfg.phononBackends) {
       GST_PLUGIN_SYSTEM_PATH = [ "/lib/gstreamer-0.10" ];
     };
 
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 75d80609f73f..ce82af4ca68c 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -134,13 +134,8 @@ let
         (*) echo "$0: Desktop manager '$desktopManager' not found.";;
       esac
 
-      # FIXME: gdbus should not be in glib.dev!
-      ${optionalString (cfg.startDbusSession && cfg.updateDbusEnvironment) ''
-        ${pkgs.glib.dev}/bin/gdbus call --session \
-          --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus \
-          --method org.freedesktop.DBus.UpdateActivationEnvironment \
-          "{$(env | ${pkgs.gnused}/bin/sed "s/'/\\\\'/g; s/\([^=]*\)=\(.*\)/'\1':'\2'/" \
-                  | ${pkgs.coreutils}/bin/paste -sd,)}"
+      ${optionalString cfg.updateDbusEnvironment ''
+        ${lib.getBin pkgs.dbus}/bin/dbus-update-activation-environment --systemd --all
       ''}
 
       test -n "$waitPID" && wait "$waitPID"
diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix
index d9f7f8f0dfc4..8b51c621e112 100644
--- a/nixos/modules/services/x11/display-managers/kdm.nix
+++ b/nixos/modules/services/x11/display-managers/kdm.nix
@@ -54,19 +54,17 @@ let
       ''}
     '';
 
-  kdmrc = pkgs.stdenv.mkDerivation {
-    name = "kdmrc";
-    config = defaultConfig + cfg.extraConfig;
-    preferLocalBuild = true;
-    buildCommand =
-      ''
-        echo "$config" > $out
+  kdmrc = pkgs.runCommand "kdmrc"
+    { config = defaultConfig + cfg.extraConfig;
+      preferLocalBuild = true;
+    }
+    ''
+      echo "$config" > $out
 
-        # The default kdmrc would add "-nolisten tcp", and we already
-        # have that managed by nixos. Hence the grep.
-        cat ${kdebase_workspace}/share/config/kdm/kdmrc | grep -v nolisten >> $out
-      '';
-  };
+      # The default kdmrc would add "-nolisten tcp", and we already
+      # have that managed by nixos. Hence the grep.
+      cat ${kdebase_workspace}/share/config/kdm/kdmrc | grep -v nolisten >> $out
+    '';
 
 in
 
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 543dd628ce66..dfda90978b1e 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -16,11 +16,9 @@ let
   # The default greeter provided with this expression is the GTK greeter.
   # Again, we need a few things in the environment for the greeter to run with
   # fonts/icons.
-  wrappedGtkGreeter = stdenv.mkDerivation {
-    name = "lightdm-gtk-greeter";
-    buildInputs = [ pkgs.makeWrapper ];
-
-    buildCommand = ''
+  wrappedGtkGreeter = pkgs.runCommand "lightdm-gtk-greeter"
+    { buildInputs = [ pkgs.makeWrapper ]; }
+    ''
       # This wrapper ensures that we actually get themes
       makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \
         $out/greeter \
@@ -40,7 +38,6 @@ let
       Type=Application
       EOF
     '';
-  };
 
   gtkGreeterConf = writeText "lightdm-gtk-greeter.conf"
     ''
diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix
index ce44c9f54a31..ca2ae1a47726 100644
--- a/nixos/modules/services/x11/display-managers/slim.nix
+++ b/nixos/modules/services/x11/display-managers/slim.nix
@@ -26,15 +26,13 @@ let
   # Unpack the SLiM theme, or use the default.
   slimThemesDir =
     let
-      unpackedTheme = pkgs.stdenv.mkDerivation {
-        name = "slim-theme";
-        buildCommand = ''
+      unpackedTheme = pkgs.runCommand "slim-theme" {}
+        ''
           mkdir -p $out
           cd $out
           unpackFile ${cfg.theme}
           ln -s * default
         '';
-      };
     in if cfg.theme == null then "${pkgs.slim}/share/slim/themes" else unpackedTheme;
 
 in
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 6c6a1e79ed0e..ec2f3a4f8bb1 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -71,15 +71,11 @@ let
     monitors = reverseList (foldl mkMonitor [] xrandrHeads);
   in concatMapStrings (getAttr "value") monitors;
 
-  configFile = pkgs.stdenv.mkDerivation {
-    name = "xserver.conf";
-
-    xfs = optionalString (cfg.useXFS != false)
-      ''FontPath "${toString cfg.useXFS}"'';
-
-    inherit (cfg) config;
-
-    buildCommand =
+  configFile = pkgs.runCommand "xserver.conf"
+    { xfs = optionalString (cfg.useXFS != false)
+        ''FontPath "${toString cfg.useXFS}"'';
+      inherit (cfg) config;
+    }
       ''
         echo 'Section "Files"' >> $out
         echo $xfs >> $out
@@ -102,7 +98,6 @@ let
 
         echo "$config" >> $out
       ''; # */
-  };
 
 in
 
@@ -154,6 +149,22 @@ in
         '';
       };
 
+      autoRepeatDelay = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          Sets the autorepeat delay (length of time in milliseconds that a key must be depressed before autorepeat starts).
+        '';
+      };
+
+      autoRepeatInterval = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          Sets the autorepeat interval (length of time in milliseconds that should elapse between autorepeat-generated keystrokes).
+        '';
+      };
+
       inputClassSections = mkOption {
         type = types.listOf types.lines;
         default = [];
@@ -509,7 +520,6 @@ in
 
         environment =
           {
-            XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension.
             XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime.
             LD_LIBRARY_PATH = concatStringsSep ":" (
               [ "${xorg.libX11.out}/lib" "${xorg.libXext.out}/lib" "/run/opengl-driver/lib" ]
@@ -541,7 +551,9 @@ in
       ] ++ optional (cfg.display != null) ":${toString cfg.display}"
         ++ optional (cfg.tty     != null) "vt${toString cfg.tty}"
         ++ optional (cfg.dpi     != null) "-dpi ${toString cfg.dpi}"
-        ++ optional (!cfg.enableTCP) "-nolisten tcp";
+        ++ optional (!cfg.enableTCP) "-nolisten tcp"
+        ++ optional (cfg.autoRepeatDelay != null) "-ardelay ${toString cfg.autoRepeatDelay}"
+        ++ optional (cfg.autoRepeatInterval != null) "-arinterval ${toString cfg.autoRepeatInterval}";
 
     services.xserver.modules =
       concatLists (catAttrs "modules" cfg.drivers) ++
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index 4c3d30e346c5..4a16a6762935 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -159,7 +159,7 @@ in
         rmdir --ignore-fail-on-non-empty /usr/bin /usr
       '';
 
-    system.activationScripts.tmpfs =
+    system.activationScripts.specialfs =
       ''
         specialMount() {
           local device="$1"
@@ -167,7 +167,12 @@ in
           local options="$3"
           local fsType="$4"
 
-          ${pkgs.utillinux}/bin/mount -t "$fsType" -o "remount,$options" "$device" "$mountPoint"
+          if ${pkgs.utillinux}/bin/mountpoint -q "$mountPoint"; then
+            local options="remount,$options"
+          else
+            mkdir -m 0755 -p "$mountPoint"
+          fi
+          ${pkgs.utillinux}/bin/mount -t "$fsType" -o "$options" "$device" "$mountPoint"
         }
         source ${config.system.build.earlyMountScript}
       '';
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index bb97d0c53a6b..8747c1e3d4ac 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -213,33 +213,30 @@ while (my ($unit, $state) = each %{$activePrev}) {
                 elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") ) {
                     $unitsToSkip{$unit} = 1;
                 } else {
-                    # If this unit is socket-activated, then stop the
-                    # socket unit(s) as well, and restart the
-                    # socket(s) instead of the service.
-                    my $socketActivated = 0;
-                    if ($unit =~ /\.service$/) {
-                        my @sockets = split / /, ($unitInfo->{Sockets} // "");
-                        if (scalar @sockets == 0) {
-                            @sockets = ("$baseName.socket");
-                        }
-                        foreach my $socket (@sockets) {
-                            if (defined $activePrev->{$socket}) {
-                                $unitsToStop{$unit} = 1;
-                                $unitsToStart{$unit} = 1;
-                                recordUnit($startListFile, $socket);
-                                $socketActivated = 1;
-                            }
-                        }
-                    }
-
                     if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
-
                         # This unit should be restarted instead of
                         # stopped and started.
                         $unitsToRestart{$unit} = 1;
                         recordUnit($restartListFile, $unit);
-
                     } else {
+                        # If this unit is socket-activated, then stop the
+                        # socket unit(s) as well, and restart the
+                        # socket(s) instead of the service.
+                        my $socketActivated = 0;
+                        if ($unit =~ /\.service$/) {
+                            my @sockets = split / /, ($unitInfo->{Sockets} // "");
+                            if (scalar @sockets == 0) {
+                                @sockets = ("$baseName.socket");
+                            }
+                            foreach my $socket (@sockets) {
+                                if (defined $activePrev->{$socket}) {
+                                    $unitsToStop{$socket} = 1;
+                                    $unitsToStart{$socket} = 1;
+                                    recordUnit($startListFile, $socket);
+                                    $socketActivated = 1;
+                                }
+                            }
+                        }
 
                         # If the unit is not socket-activated, record
                         # that this unit needs to be started below.
@@ -251,7 +248,6 @@ while (my ($unit, $state) = each %{$activePrev}) {
                         }
 
                         $unitsToStop{$unit} = 1;
-
                     }
                 }
             }
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index e84cdb3212ce..c3be7407d592 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -131,51 +131,51 @@ in
           to the respective devices corresponding to those partitions.
         '';
 
-        type = types.listOf types.optionSet;
+        type = with types; listOf (submodule {
+          options = {
+
+            path = mkOption {
+              example = "/boot1";
+              type = types.str;
+              description = ''
+                The path to the boot directory where GRUB will be written. Generally
+                this boot path should double as an EFI path.
+              '';
+            };
+
+            efiSysMountPoint = mkOption {
+              default = null;
+              example = "/boot1/efi";
+              type = types.nullOr types.str;
+              description = ''
+                The path to the efi system mount point. Usually this is the same
+                partition as the above path and can be left as null.
+              '';
+            };
+
+            efiBootloaderId = mkOption {
+              default = null;
+              example = "NixOS-fsid";
+              type = types.nullOr types.str;
+              description = ''
+                The id of the bootloader to store in efi nvram.
+                The default is to name it NixOS and append the path or efiSysMountPoint.
+                This is only used if <literal>boot.loader.efi.canTouchEfiVariables</literal> is true.
+              '';
+            };
+
+            devices = mkOption {
+              default = [ ];
+              example = [ "/dev/sda" "/dev/sdb" ];
+              type = types.listOf types.str;
+              description = ''
+                The path to the devices which will have the GRUB MBR written.
+                Note these are typically device paths and not paths to partitions.
+              '';
+            };
 
-        options = {
-
-          path = mkOption {
-            example = "/boot1";
-            type = types.str;
-            description = ''
-              The path to the boot directory where GRUB will be written. Generally
-              this boot path should double as an EFI path.
-            '';
-          };
-
-          efiSysMountPoint = mkOption {
-            default = null;
-            example = "/boot1/efi";
-            type = types.nullOr types.str;
-            description = ''
-              The path to the efi system mount point. Usually this is the same
-              partition as the above path and can be left as null.
-            '';
-          };
-
-          efiBootloaderId = mkOption {
-            default = null;
-            example = "NixOS-fsid";
-            type = types.nullOr types.str;
-            description = ''
-              The id of the bootloader to store in efi nvram.
-              The default is to name it NixOS and append the path or efiSysMountPoint.
-              This is only used if <literal>boot.loader.efi.canTouchEfiVariables</literal> is true.
-            '';
           };
-
-          devices = mkOption {
-            default = [ ];
-            example = [ "/dev/sda" "/dev/sdb" ];
-            type = types.listOf types.str;
-            description = ''
-              The path to the devices which will have the GRUB MBR written.
-              Note these are typically device paths and not paths to partitions.
-            '';
-          };
-
-        };
+        });
       };
 
       configurationName = mkOption {
@@ -503,7 +503,7 @@ in
             + "'boot.loader.grub.mirroredBoots' to make the system bootable.";
         }
         {
-          assertion = all (c: c < 2) (mapAttrsToList (_: c: c) bootDeviceCounters);
+          assertion = cfg.efiSupport || all (c: c < 2) (mapAttrsToList (_: c: c) bootDeviceCounters);
           message = "You cannot have duplicated devices in mirroredBoots";
         }
         {
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index c703a3e083ba..515136c904c5 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -1,4 +1,4 @@
-#! @python@/bin/python
+#! @python3@/bin/python3
 import argparse
 import shutil
 import os
@@ -13,29 +13,21 @@ def copy_if_not_exists(source, dest):
     if not os.path.exists(dest):
         shutil.copyfile(source, dest)
 
-system_dir = lambda generation: "/nix/var/nix/profiles/system-%d-link" % (generation)
+def system_dir(generation):
+    return "/nix/var/nix/profiles/system-%d-link" % (generation)
 
-def write_entry(generation, kernel, initrd):
-    entry_file = "@efiSysMountPoint@/loader/entries/nixos-generation-%d.conf" % (generation)
-    generation_dir = os.readlink(system_dir(generation))
-    tmp_path = "%s.tmp" % (entry_file)
-    kernel_params = "systemConfig=%s init=%s/init " % (generation_dir, generation_dir)
-    with open("%s/kernel-params" % (generation_dir)) as params_file:
-        kernel_params = kernel_params + params_file.read()
-    with open(tmp_path, 'w') as f:
-        print >> f, "title NixOS"
-        print >> f, "version Generation %d" % (generation)
-        if machine_id is not None: print >> f, "machine-id %s" % (machine_id)
-        print >> f, "linux %s" % (kernel)
-        print >> f, "initrd %s" % (initrd)
-        print >> f, "options %s" % (kernel_params)
-    os.rename(tmp_path, entry_file)
+BOOT_ENTRY = """title NixOS
+version Generation {generation}
+linux {kernel}
+initrd {initrd}
+options {kernel_params}
+"""
 
 def write_loader_conf(generation):
     with open("@efiSysMountPoint@/loader/loader.conf.tmp", 'w') as f:
         if "@timeout@" != "":
-            print >> f, "timeout @timeout@"
-        print >> f, "default nixos-generation-%d" % (generation)
+            f.write("timeout @timeout@\n")
+        f.write("default nixos-generation-%d\n" % generation)
     os.rename("@efiSysMountPoint@/loader/loader.conf.tmp", "@efiSysMountPoint@/loader/loader.conf")
 
 def copy_from_profile(generation, name, dry_run=False):
@@ -47,10 +39,23 @@ def copy_from_profile(generation, name, dry_run=False):
         copy_if_not_exists(store_file_path, "@efiSysMountPoint@%s" % (efi_file_path))
     return efi_file_path
 
-def add_entry(generation):
-    efi_kernel_path = copy_from_profile(generation, "kernel")
-    efi_initrd_path = copy_from_profile(generation, "initrd")
-    write_entry(generation, efi_kernel_path, efi_initrd_path)
+def write_entry(generation, machine_id):
+    kernel = copy_from_profile(generation, "kernel")
+    initrd = copy_from_profile(generation, "initrd")
+    entry_file = "@efiSysMountPoint@/loader/entries/nixos-generation-%d.conf" % (generation)
+    generation_dir = os.readlink(system_dir(generation))
+    tmp_path = "%s.tmp" % (entry_file)
+    kernel_params = "systemConfig=%s init=%s/init " % (generation_dir, generation_dir)
+    with open("%s/kernel-params" % (generation_dir)) as params_file:
+        kernel_params = kernel_params + params_file.read()
+    with open(tmp_path, 'w') as f:
+        f.write(BOOT_ENTRY.format(generation=generation,
+                    kernel=kernel,
+                    initrd=initrd,
+                    kernel_params=kernel_params))
+        if machine_id is not None:
+            f.write("machine-id %s\n" % machine_id)
+    os.rename(tmp_path, entry_file)
 
 def mkdir_p(path):
     try:
@@ -65,8 +70,8 @@ def get_generations(profile):
         "--list-generations",
         "-p",
         "/nix/var/nix/profiles/%s" % (profile),
-        "--option", "build-users-group", ""
-        ])
+        "--option", "build-users-group", ""],
+        universal_newlines=True)
     gen_lines = gen_list.split('\n')
     gen_lines.pop()
     return [ int(line.split()[0]) for line in gen_lines ]
@@ -89,33 +94,37 @@ def remove_old_entries(gens):
         if not path in known_paths:
             os.unlink(path)
 
-parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files')
-parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default NixOS config to boot')
-args = parser.parse_args()
+def main():
+    parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files')
+    parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default NixOS config to boot')
+    args = parser.parse_args()
 
-if os.getenv("NIXOS_INSTALL_GRUB") == "1":
-    warnings.warn("NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER", DeprecationWarning)
-    os.environ["NIXOS_INSTALL_BOOTLOADER"] = "1"
+    if os.getenv("NIXOS_INSTALL_GRUB") == "1":
+        warnings.warn("NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER", DeprecationWarning)
+        os.environ["NIXOS_INSTALL_BOOTLOADER"] = "1"
 
-if os.getenv("NIXOS_INSTALL_BOOTLOADER") == "1":
-    if "@canTouchEfiVariables@" == "1":
-        subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "install"])
-    else:
-        subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "--no-variables", "install"])
+    if os.getenv("NIXOS_INSTALL_BOOTLOADER") == "1":
+        if "@canTouchEfiVariables@" == "1":
+            subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "install"])
+        else:
+            subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "--no-variables", "install"])
 
-mkdir_p("@efiSysMountPoint@/efi/nixos")
-mkdir_p("@efiSysMountPoint@/loader/entries")
-try:
-    with open("/etc/machine-id") as machine_file:
-        machine_id = machine_file.readlines()[0]
-except IOError as e:
-    if e.errno != errno.ENOENT:
-        raise
-    machine_id = None
+    mkdir_p("@efiSysMountPoint@/efi/nixos")
+    mkdir_p("@efiSysMountPoint@/loader/entries")
+    try:
+        with open("/etc/machine-id") as machine_file:
+            machine_id = machine_file.readlines()[0]
+    except IOError as e:
+        if e.errno != errno.ENOENT:
+            raise
+        machine_id = None
+
+    gens = get_generations("system")
+    remove_old_entries(gens)
+    for gen in gens:
+        write_entry(gen, machine_id)
+        if os.readlink(system_dir(gen)) == args.default_config:
+            write_loader_conf(gen)
 
-gens = get_generations("system")
-remove_old_entries(gens)
-for gen in gens:
-    add_entry(gen)
-    if os.readlink(system_dir(gen)) == args.default_config:
-        write_loader_conf(gen)
+if __name__ == '__main__':
+    main()
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index a778a4f539c9..cc43fb8bab4c 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -12,7 +12,7 @@ let
 
     isExecutable = true;
 
-    inherit (pkgs) python;
+    inherit (pkgs) python3;
 
     systemd = config.systemd.package;
 
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index f2755b49f88d..1f412fe2d8f2 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -236,165 +236,165 @@ in
         <filename>/dev/mapper/<replaceable>name</replaceable></filename>.
       '';
 
-      type = types.loaOf types.optionSet;
-
-      options = { name, ... }: { options = {
-
-        name = mkOption {
-          visible = false;
-          default = name;
-          example = "luksroot";
-          type = types.str;
-          description = "Name of the unencrypted device in <filename>/dev/mapper</filename>.";
-        };
-
-        device = mkOption {
-          example = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08";
-          type = types.str;
-          description = "Path of the underlying encrypted block device.";
-        };
-
-        header = mkOption {
-          default = null;
-          example = "/root/header.img";
-          type = types.nullOr types.str;
-          description = ''
-            The name of the file or block device that
-            should be used as header for the encrypted device.
-          '';
-        };
-
-        keyFile = mkOption {
-          default = null;
-          example = "/dev/sdb1";
-          type = types.nullOr types.str;
-          description = ''
-            The name of the file (can be a raw device or a partition) that
-            should be used as the decryption key for the encrypted device. If
-            not specified, you will be prompted for a passphrase instead.
-          '';
-        };
-
-        keyFileSize = mkOption {
-          default = null;
-          example = 4096;
-          type = types.nullOr types.int;
-          description = ''
-            The size of the key file. Use this if only the beginning of the
-            key file should be used as a key (often the case if a raw device
-            or partition is used as key file). If not specified, the whole
-            <literal>keyFile</literal> will be used decryption, instead of just
-            the first <literal>keyFileSize</literal> bytes.
-          '';
-        };
-
-        # FIXME: get rid of this option.
-        preLVM = mkOption {
-          default = true;
-          type = types.bool;
-          description = "Whether the luksOpen will be attempted before LVM scan or after it.";
-        };
-
-        allowDiscards = mkOption {
-          default = false;
-          type = types.bool;
-          description = ''
-            Whether to allow TRIM requests to the underlying device. This option
-            has security implications; please read the LUKS documentation before
-            activating it.
-          '';
-        };
-
-        yubikey = mkOption {
-          default = null;
-          type = types.nullOr types.optionSet;
-          description = ''
-            The options to use for this LUKS device in Yubikey-PBA.
-            If null (the default), Yubikey-PBA will be disabled for this device.
-          '';
+      type = with types; loaOf (submodule (
+        { name, ... }: { options = {
+
+          name = mkOption {
+            visible = false;
+            default = name;
+            example = "luksroot";
+            type = types.str;
+            description = "Name of the unencrypted device in <filename>/dev/mapper</filename>.";
+          };
 
-          options = {
-            twoFactor = mkOption {
-              default = true;
-              type = types.bool;
-              description = "Whether to use a passphrase and a Yubikey (true), or only a Yubikey (false).";
-            };
-
-            slot = mkOption {
-              default = 2;
-              type = types.int;
-              description = "Which slot on the Yubikey to challenge.";
-            };
-
-            saltLength = mkOption {
-              default = 16;
-              type = types.int;
-              description = "Length of the new salt in byte (64 is the effective maximum).";
-            };
-
-            keyLength = mkOption {
-              default = 64;
-              type = types.int;
-              description = "Length of the LUKS slot key derived with PBKDF2 in byte.";
-            };
-
-            iterationStep = mkOption {
-              default = 0;
-              type = types.int;
-              description = "How much the iteration count for PBKDF2 is increased at each successful authentication.";
-            };
-
-            gracePeriod = mkOption {
-              default = 2;
-              type = types.int;
-              description = "Time in seconds to wait before attempting to find the Yubikey.";
-            };
-
-            ramfsMountPoint = mkOption {
-              default = "/crypt-ramfs";
-              type = types.str;
-              description = "Path where the ramfs used to update the LUKS key will be mounted during early boot.";
-            };
-
-            /* TODO: Add to the documentation of the current module:
-
-               Options related to the storing the salt.
-            */
-            storage = {
-              device = mkOption {
-                default = "/dev/sda1";
-                type = types.path;
-                description = ''
-                  An unencrypted device that will temporarily be mounted in stage-1.
-                  Must contain the current salt to create the challenge for this LUKS device.
-                '';
-              };
+          device = mkOption {
+            example = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08";
+            type = types.str;
+            description = "Path of the underlying encrypted block device.";
+          };
 
-              fsType = mkOption {
-                default = "vfat";
-                type = types.str;
-                description = "The filesystem of the unencrypted device.";
-              };
+          header = mkOption {
+            default = null;
+            example = "/root/header.img";
+            type = types.nullOr types.str;
+            description = ''
+              The name of the file or block device that
+              should be used as header for the encrypted device.
+            '';
+          };
 
-              mountPoint = mkOption {
-                default = "/crypt-storage";
-                type = types.str;
-                description = "Path where the unencrypted device will be mounted during early boot.";
-              };
+          keyFile = mkOption {
+            default = null;
+            example = "/dev/sdb1";
+            type = types.nullOr types.str;
+            description = ''
+              The name of the file (can be a raw device or a partition) that
+              should be used as the decryption key for the encrypted device. If
+              not specified, you will be prompted for a passphrase instead.
+            '';
+          };
+
+          keyFileSize = mkOption {
+            default = null;
+            example = 4096;
+            type = types.nullOr types.int;
+            description = ''
+              The size of the key file. Use this if only the beginning of the
+              key file should be used as a key (often the case if a raw device
+              or partition is used as key file). If not specified, the whole
+              <literal>keyFile</literal> will be used decryption, instead of just
+              the first <literal>keyFileSize</literal> bytes.
+            '';
+          };
+
+          # FIXME: get rid of this option.
+          preLVM = mkOption {
+            default = true;
+            type = types.bool;
+            description = "Whether the luksOpen will be attempted before LVM scan or after it.";
+          };
+
+          allowDiscards = mkOption {
+            default = false;
+            type = types.bool;
+            description = ''
+              Whether to allow TRIM requests to the underlying device. This option
+              has security implications; please read the LUKS documentation before
+              activating it.
+            '';
+          };
 
-              path = mkOption {
-                default = "/crypt-storage/default";
-                type = types.str;
-                description = ''
-                  Absolute path of the salt on the unencrypted device with
-                  that device's root directory as "/".
-                '';
+          yubikey = mkOption {
+            default = null;
+            description = ''
+              The options to use for this LUKS device in Yubikey-PBA.
+              If null (the default), Yubikey-PBA will be disabled for this device.
+            '';
+
+            type = with types; nullOr (submodule {
+              options = {
+                twoFactor = mkOption {
+                  default = true;
+                  type = types.bool;
+                  description = "Whether to use a passphrase and a Yubikey (true), or only a Yubikey (false).";
+                };
+
+                slot = mkOption {
+                  default = 2;
+                  type = types.int;
+                  description = "Which slot on the Yubikey to challenge.";
+                };
+
+                saltLength = mkOption {
+                  default = 16;
+                  type = types.int;
+                  description = "Length of the new salt in byte (64 is the effective maximum).";
+                };
+
+                keyLength = mkOption {
+                  default = 64;
+                  type = types.int;
+                  description = "Length of the LUKS slot key derived with PBKDF2 in byte.";
+                };
+
+                iterationStep = mkOption {
+                  default = 0;
+                  type = types.int;
+                  description = "How much the iteration count for PBKDF2 is increased at each successful authentication.";
+                };
+
+                gracePeriod = mkOption {
+                  default = 2;
+                  type = types.int;
+                  description = "Time in seconds to wait before attempting to find the Yubikey.";
+                };
+
+                ramfsMountPoint = mkOption {
+                  default = "/crypt-ramfs";
+                  type = types.str;
+                  description = "Path where the ramfs used to update the LUKS key will be mounted during early boot.";
+                };
+
+                /* TODO: Add to the documentation of the current module:
+
+                   Options related to the storing the salt.
+                */
+                storage = {
+                  device = mkOption {
+                    default = "/dev/sda1";
+                    type = types.path;
+                    description = ''
+                      An unencrypted device that will temporarily be mounted in stage-1.
+                      Must contain the current salt to create the challenge for this LUKS device.
+                    '';
+                  };
+
+                  fsType = mkOption {
+                    default = "vfat";
+                    type = types.str;
+                    description = "The filesystem of the unencrypted device.";
+                  };
+
+                  mountPoint = mkOption {
+                    default = "/crypt-storage";
+                    type = types.str;
+                    description = "Path where the unencrypted device will be mounted during early boot.";
+                  };
+
+                  path = mkOption {
+                    default = "/crypt-storage/default";
+                    type = types.str;
+                    description = ''
+                      Absolute path of the salt on the unencrypted device with
+                      that device's root directory as "/".
+                    '';
+                  };
+                };
               };
-            };
+            });
           };
-        };
 
-      }; };
+        }; }));
     };
 
     boot.initrd.luks.yubikeySupport = mkOption {
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 38b4b437369d..8c139a94c0c8 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -296,35 +296,35 @@ let
   };
 
   addressOptions = {
-
-    addressConfig = mkOption {
-      default = {};
-      example = { Address = "192.168.0.100/24"; };
-      type = types.addCheck (types.attrsOf unitOption) checkAddress;
-      description = ''
-        Each attribute in this set specifies an option in the
-        <literal>[Address]</literal> section of the unit.  See
-        <citerefentry><refentrytitle>systemd.network</refentrytitle>
-        <manvolnum>5</manvolnum></citerefentry> for details.
-      '';
+    options = {
+      addressConfig = mkOption {
+        default = {};
+        example = { Address = "192.168.0.100/24"; };
+        type = types.addCheck (types.attrsOf unitOption) checkAddress;
+        description = ''
+          Each attribute in this set specifies an option in the
+          <literal>[Address]</literal> section of the unit.  See
+          <citerefentry><refentrytitle>systemd.network</refentrytitle>
+          <manvolnum>5</manvolnum></citerefentry> for details.
+        '';
+      };
     };
-
   };
 
   routeOptions = {
-
-    routeConfig = mkOption {
-      default = {};
-      example = { Gateway = "192.168.0.1"; };
-      type = types.addCheck (types.attrsOf unitOption) checkRoute;
-      description = ''
-        Each attribute in this set specifies an option in the
-        <literal>[Route]</literal> section of the unit.  See
-        <citerefentry><refentrytitle>systemd.network</refentrytitle>
-        <manvolnum>5</manvolnum></citerefentry> for details.
-      '';
+    options = {
+      routeConfig = mkOption {
+        default = {};
+        example = { Gateway = "192.168.0.1"; };
+        type = types.addCheck (types.attrsOf unitOption) checkRoute;
+        description = ''
+          Each attribute in this set specifies an option in the
+          <literal>[Route]</literal> section of the unit.  See
+          <citerefentry><refentrytitle>systemd.network</refentrytitle>
+          <manvolnum>5</manvolnum></citerefentry> for details.
+        '';
+      };
     };
-
   };
 
   networkOptions = commonNetworkOptions // {
@@ -471,8 +471,7 @@ let
 
     addresses = mkOption {
       default = [ ];
-      type = types.listOf types.optionSet;
-      options = [ addressOptions ];
+      type = with types; listOf (submodule addressOptions);
       description = ''
         A list of address sections to be added to the unit.  See
         <citerefentry><refentrytitle>systemd.network</refentrytitle>
@@ -482,8 +481,7 @@ let
 
     routes = mkOption {
       default = [ ];
-      type = types.listOf types.optionSet;
-      options = [ routeOptions ];
+      type = with types; listOf (submodule routeOptions);
       description = ''
         A list of route sections to be added to the unit.  See
         <citerefentry><refentrytitle>systemd.network</refentrytitle>
@@ -624,35 +622,32 @@ in
 
     systemd.network.links = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ linkOptions ];
+      type = with types; attrsOf (submodule [ { options = linkOptions; } ]);
       description = "Definition of systemd network links.";
     };
 
     systemd.network.netdevs = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ netdevOptions ];
+      type = with types; attrsOf (submodule [ { options = netdevOptions; } ]);
       description = "Definition of systemd network devices.";
     };
 
     systemd.network.networks = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ networkOptions networkConfig ];
+      type = with types; attrsOf (submodule [ { options = networkOptions; } networkConfig ]);
       description = "Definition of systemd networks.";
     };
 
     systemd.network.units = mkOption {
       description = "Definition of networkd units.";
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = { name, config, ... }:
+      type = with types; attrsOf (submodule (
+        { name, config, ... }:
         { options = concreteUnitOptions;
           config = {
             unit = mkDefault (makeUnit name config);
           };
-        };
+        }));
     };
 
   };
@@ -672,7 +667,6 @@ in
 
     systemd.services.systemd-networkd = {
       wantedBy = [ "multi-user.target" ];
-      before = [ "network-interfaces.target" ];
       restartTriggers = [ config.environment.etc."systemd/network".source ];
     };
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 513c121347b1..8d02cd81e0e1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -134,10 +134,9 @@ let
     ''; # */
 
 
-  udevRules = pkgs.stdenv.mkDerivation {
-    name = "udev-rules";
-    allowedReferences = [ extraUtils ];
-    buildCommand = ''
+  udevRules = pkgs.runCommand "udev-rules"
+    { allowedReferences = [ extraUtils ]; }
+    ''
       mkdir -p $out
 
       echo 'ENV{LD_LIBRARY_PATH}="${extraUtils}/lib"' > $out/00-env.rules
@@ -176,7 +175,6 @@ let
       substituteInPlace $out/60-persistent-storage.rules \
         --replace ID_CDROM_MEDIA_TRACK_COUNT_DATA ID_CDROM_MEDIA
     ''; # */
-  };
 
 
   # The init script of boot stage 1 (loading kernel modules for
@@ -198,9 +196,10 @@ let
       preLVMCommands preDeviceCommands postDeviceCommands postMountCommands preFailCommands 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 
-                    # Don't include zram devices
-                    && !(hasPrefix "/dev/zram" sd.device)) config.swapDevices);
+                    (filter (sd: hasPrefix "/dev/" sd.device && !sd.randomEncryption
+                             # Don't include zram devices
+                             && !(hasPrefix "/dev/zram" sd.device)
+                            ) config.swapDevices);
 
     fsInfo =
       let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType (builtins.concatStringsSep "," fs.options) ];
@@ -229,16 +228,12 @@ let
         { object = pkgs.writeText "mdadm.conf" config.boot.initrd.mdadmConf;
           symlink = "/etc/mdadm.conf";
         }
-        { object = pkgs.stdenv.mkDerivation {
-            name = "initrd-kmod-blacklist-ubuntu";
-            builder = pkgs.writeText "builder.sh" ''
-              source $stdenv/setup
+        { object = pkgs.runCommand "initrd-kmod-blacklist-ubuntu"
+            { src = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf"; }
+            ''
               target=$out
-
               ${pkgs.perl}/bin/perl -0pe 's/## file: iwlwifi.conf(.+?)##/##/s;' $src > $out
             '';
-            src = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf";
-          };
           symlink = "/etc/modprobe.d/ubuntu.conf";
         }
         { object = pkgs.kmod-debian-aliases;
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index ae88222f2780..f827e530f877 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -111,16 +111,6 @@ rm -f /etc/{group,passwd,shadow}.lock
 rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots
 
 
-# Create a ramfs on /run/keys to hold secrets that shouldn't be
-# written to disk (generally used for NixOps, harmless elsewhere).
-if ! mountpoint -q /run/keys; then
-    rm -rf /run/keys
-    mkdir /run/keys
-    mount -t ramfs ramfs /run/keys
-    chown 0:96 /run/keys
-    chmod 0750 /run/keys
-fi
-
 mkdir -m 0755 -p /run/lock
 
 
diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix
index 2e93693cbfc8..997770b8beca 100644
--- a/nixos/modules/system/boot/systemd-lib.nix
+++ b/nixos/modules/system/boot/systemd-lib.nix
@@ -182,7 +182,7 @@ rec {
         mkdir -p $out/getty.target.wants/
         ln -s ../autovt@tty1.service $out/getty.target.wants/
 
-        ln -s ../local-fs.target ../remote-fs.target ../network.target \
+        ln -s ../local-fs.target ../remote-fs.target \
         ../nss-lookup.target ../nss-user-lookup.target ../swap.target \
         $out/multi-user.target.wants/
       ''}
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index b2a80a7e395a..d44c2e234b0f 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -393,13 +393,13 @@ in
     systemd.units = mkOption {
       description = "Definition of systemd units.";
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = { name, config, ... }:
+      type = with types; attrsOf (submodule (
+        { name, config, ... }:
         { options = concreteUnitOptions;
           config = {
             unit = mkDefault (makeUnit name config);
           };
-        };
+        }));
     };
 
     systemd.packages = mkOption {
@@ -410,43 +410,37 @@ in
 
     systemd.targets = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ targetOptions unitConfig ];
+      type = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig] );
       description = "Definition of systemd target units.";
     };
 
     systemd.services = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ serviceOptions unitConfig serviceConfig ];
+      type = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ]);
       description = "Definition of systemd service units.";
     };
 
     systemd.sockets = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ socketOptions unitConfig ];
+      type = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ]);
       description = "Definition of systemd socket units.";
     };
 
     systemd.timers = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ timerOptions unitConfig ];
+      type = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ]);
       description = "Definition of systemd timer units.";
     };
 
     systemd.paths = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ pathOptions unitConfig ];
+      type = with types; attrsOf (submodule [ { options = pathOptions; } unitConfig ]);
       description = "Definition of systemd path units.";
     };
 
     systemd.mounts = mkOption {
       default = [];
-      type = types.listOf types.optionSet;
-      options = [ mountOptions unitConfig mountConfig ];
+      type = with types; listOf (submodule [ { options = mountOptions; } unitConfig mountConfig ]);
       description = ''
         Definition of systemd mount units.
         This is a list instead of an attrSet, because systemd mandates the names to be derived from
@@ -456,8 +450,7 @@ in
 
     systemd.automounts = mkOption {
       default = [];
-      type = types.listOf types.optionSet;
-      options = [ automountOptions unitConfig automountConfig ];
+      type = with types; listOf (submodule [ { options = automountOptions; } unitConfig automountConfig ]);
       description = ''
         Definition of systemd automount units.
         This is a list instead of an attrSet, because systemd mandates the names to be derived from
@@ -604,33 +597,30 @@ in
     systemd.user.units = mkOption {
       description = "Definition of systemd per-user units.";
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = { name, config, ... }:
+      type = with types; attrsOf (submodule (
+        { name, config, ... }:
         { options = concreteUnitOptions;
           config = {
             unit = mkDefault (makeUnit name config);
           };
-        };
+        }));
     };
 
     systemd.user.services = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ serviceOptions unitConfig serviceConfig ];
+      type = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ] );
       description = "Definition of systemd per-user service units.";
     };
 
     systemd.user.timers = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ timerOptions unitConfig ];
+      type = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ] );
       description = "Definition of systemd per-user timer units.";
     };
 
     systemd.user.sockets = mkOption {
       default = {};
-      type = types.attrsOf types.optionSet;
-      options = [ socketOptions unitConfig ];
+      type = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ] );
       description = "Definition of systemd per-user socket units.";
     };
 
@@ -819,6 +809,8 @@ in
     systemd.services.systemd-user-sessions.restartIfChanged = false; # Restart kills all active sessions.
     systemd.services.systemd-logind.restartTriggers = [ config.environment.etc."systemd/logind.conf".source ];
     systemd.services.systemd-logind.stopIfChanged = false;
+    systemd.services.systemd-journald.restartTriggers = [ config.environment.etc."systemd/journald.conf".source ];
+    systemd.services.systemd-journald.stopIfChanged = false;
     systemd.targets.local-fs.unitConfig.X-StopOnReconfiguration = true;
     systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true;
     systemd.services.systemd-binfmt.wants = [ "proc-sys-fs-binfmt_misc.automount" ];
diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix
index 163f4f4106e8..dac36229408f 100644
--- a/nixos/modules/system/etc/etc.nix
+++ b/nixos/modules/system/etc/etc.nix
@@ -33,7 +33,6 @@ in
   options = {
 
     environment.etc = mkOption {
-      type = types.loaOf types.optionSet;
       default = {};
       example = literalExample ''
         { example-configuration-file =
@@ -47,7 +46,8 @@ in
         Set of files that have to be linked in <filename>/etc</filename>.
       '';
 
-      options = singleton ({ name, config, ... }:
+      type = with types; loaOf (submodule (
+        { name, config, ... }:
         { options = {
 
             enable = mkOption {
@@ -117,7 +117,7 @@ in
               in mkDefault (pkgs.writeText name' config.text));
           };
 
-        });
+        }));
 
     };
 
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index 3c822c8716d0..49ba66ad50af 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -18,7 +18,7 @@ let
 
   prioOption = prio: optionalString (prio != null) " pri=${toString prio}";
 
-  specialFSTypes = [ "proc" "sysfs" "tmpfs" "devtmpfs" "devpts" ];
+  specialFSTypes = [ "proc" "sysfs" "tmpfs" "ramfs" "devtmpfs" "devpts" ];
 
   coreFileSystemOpts = { name, config, ... }: {
 
@@ -258,7 +258,7 @@ in
           let
             mountPoint' = "${escapeSystemdPath fs.mountPoint}.mount";
             device'  = escapeSystemdPath fs.device;
-            device'' = "${device}.device";
+            device'' = "${device'}.device";
           in nameValuePair "mkfs-${device'}"
           { description = "Initialisation of Filesystem ${fs.device}";
             wantedBy = [ mountPoint' ];
@@ -290,6 +290,9 @@ in
       "/dev" = { fsType = "devtmpfs"; options = [ "nosuid" "strictatime" "mode=755" "size=${config.boot.devSize}" ]; };
       "/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; };
       "/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "gid=${toString config.ids.gids.tty}" ]; };
+
+      # To hold secrets that shouldn't be written to disk (generally used for NixOps, harmless elsewhere)
+      "/run/keys" = { fsType = "ramfs"; options = [ "nosuid" "nodev" "mode=750" "gid=${toString config.ids.gids.keys}" ]; };
     } // optionalAttrs (!config.boot.isContainer) {
       # systemd-nspawn populates /sys by itself, and remounting it causes all
       # kinds of weird issues (most noticeably, waiting for host disk device
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index d1b62e0fd4e4..6a8f20bab5b6 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -54,16 +54,22 @@ in
         networkSetup =
           { description = "Networking Setup";
 
-            after = [ "network-interfaces.target" "network-pre.target" ];
-            before = [ "network.target" ];
-            wantedBy = [ "network.target" ];
+            after = [ "network-pre.target" "systemd-udevd.service" "systemd-sysctl.service" ];
+            before = [ "network.target" "shutdown.target" ];
+            wants = [ "network.target" ];
+            conflicts = [ "shutdown.target" ];
+            wantedBy = [ "multi-user.target" ];
 
             unitConfig.ConditionCapability = "CAP_NET_ADMIN";
 
             path = [ pkgs.iproute ];
 
-            serviceConfig.Type = "oneshot";
-            serviceConfig.RemainAfterExit = true;
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+            };
+
+            unitConfig.DefaultDependencies = false;
 
             script =
               ''
@@ -108,8 +114,12 @@ in
           in
           nameValuePair "network-addresses-${i.name}"
           { description = "Address configuration of ${i.name}";
-            wantedBy = [ "network-interfaces.target" ];
-            before = [ "network-interfaces.target" ];
+            wantedBy = [ "network-setup.service" ];
+            # propagate stop and reload from network-setup
+            partOf = [ "network-setup.service" ];
+            # order before network-setup because the routes that are configured
+            # there may need ip addresses configured
+            before = [ "network-setup.service" ];
             bindsTo = [ (subsystemDevice i.name) ];
             after = [ (subsystemDevice i.name) "network-pre.target" ];
             serviceConfig.Type = "oneshot";
@@ -129,20 +139,11 @@ in
                   echo "checking ip ${address}..."
                   if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then
                     echo "added ip ${address}..."
-                    restart_network_setup=true
                   elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
                     echo "failed to add ${address}"
                     exit 1
                   fi
-                '')
-              + optionalString (ips != [ ])
-                ''
-                  if [ "$restart_network_setup" = "true" ]; then
-                    # Ensure that the default gateway remains set.
-                    # (Flushing this interface may have removed it.)
-                    ${config.systemd.package}/bin/systemctl try-restart --no-block network-setup.service
-                  fi
-                '';
+                '');
             preStop = flip concatMapStrings (ips) (ip:
                 let
                   address = "${ip.address}/${toString ip.prefixLength}";
@@ -156,10 +157,11 @@ in
 
         createTunDevice = i: nameValuePair "${i.name}-netdev"
           { description = "Virtual Network Interface ${i.name}";
-            requires = [ "dev-net-tun.device" ];
+            bindsTo = [ "dev-net-tun.device" ];
             after = [ "dev-net-tun.device" "network-pre.target" ];
-            wantedBy = [ "network.target" (subsystemDevice i.name) ];
-            before = [ "network-interfaces.target" (subsystemDevice i.name) ];
+            wantedBy = [ "network-setup.service" (subsystemDevice i.name) ];
+            partOf = [ "network-setup.service" ];
+            before = [ "network-setup.service" (subsystemDevice i.name) ];
             path = [ pkgs.iproute ];
             serviceConfig = {
               Type = "oneshot";
@@ -180,12 +182,12 @@ in
             deps = map subsystemDevice v.interfaces;
           in
           { description = "Bridge Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
+            wantedBy = [ "network-setup.service" (subsystemDevice n) ];
             bindsTo = deps ++ optional v.rstp "mstpd.service";
-            partOf = optional v.rstp "mstpd.service";
+            partOf = [ "network-setup.service" ] ++ optional v.rstp "mstpd.service";
             after = [ "network-pre.target" "mstpd.service" ] ++ deps
               ++ concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) v.interfaces;
-            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            before = [ "network-setup.service" (subsystemDevice n) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute ];
@@ -222,11 +224,11 @@ in
             ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
           in
           { description = "Open vSwitch Interface ${n}";
-            wantedBy = [ "network.target" "vswitchd.service" ] ++ deps;
+            wantedBy = [ "network-setup.service" "vswitchd.service" ] ++ deps;
             bindsTo =  [ "vswitchd.service" (subsystemDevice n) ] ++ deps;
-            partOf = [ "vswitchd.service" ];
+            partOf = [ "network-setup.service" "vswitchd.service" ];
             after = [ "network-pre.target" "vswitchd.service" ] ++ deps;
-            before = [ "network-interfaces.target" ];
+            before = [ "network-setup.service" ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute config.virtualisation.vswitch.package ];
@@ -254,11 +256,12 @@ in
             deps = map subsystemDevice v.interfaces;
           in
           { description = "Bond Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
+            wantedBy = [ "network-setup.service" (subsystemDevice n) ];
             bindsTo = deps;
+            partOf = [ "network-setup.service" ];
             after = [ "network-pre.target" ] ++ deps
               ++ concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) v.interfaces;
-            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            before = [ "network-setup.service" (subsystemDevice n) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute pkgs.gawk ];
@@ -291,10 +294,11 @@ in
             deps = [ (subsystemDevice v.interface) ];
           in
           { description = "Vlan Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
+            wantedBy = [ "network-setup.service" (subsystemDevice n) ];
             bindsTo = deps;
+            partOf = [ "network-setup.service" ];
             after = [ "network-pre.target" ] ++ deps;
-            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            before = [ "network-setup.service" (subsystemDevice n) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute ];
@@ -315,10 +319,11 @@ in
             deps = optional (v.dev != null) (subsystemDevice v.dev);
           in
           { description = "6-to-4 Tunnel Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
+            wantedBy = [ "network-setup.service" (subsystemDevice n) ];
             bindsTo = deps;
+            partOf = [ "network-setup.service" ];
             after = [ "network-pre.target" ] ++ deps;
-            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            before = [ "network-setup.service" (subsystemDevice n) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute ];
@@ -342,10 +347,11 @@ in
             deps = [ (subsystemDevice v.interface) ];
           in
           { description = "Vlan Interface ${n}";
-            wantedBy = [ "network.target" (subsystemDevice n) ];
+            wantedBy = [ "network-setup.service" (subsystemDevice n) ];
             bindsTo = deps;
+            partOf = [ "network-setup.service" ];
             after = [ "network-pre.target" ] ++ deps;
-            before = [ "network-interfaces.target" (subsystemDevice n) ];
+            before = [ "network-setup.service" (subsystemDevice n) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute ];
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 9042418b7234..cac7e6b02eba 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -97,21 +97,22 @@ let
 
   addrOpts = v:
     assert v == 4 || v == 6;
-    {
-      address = mkOption {
-        type = types.str;
-        description = ''
-          IPv${toString v} address of the interface.  Leave empty to configure the
-          interface using DHCP.
-        '';
-      };
+    { options = {
+        address = mkOption {
+          type = types.str;
+          description = ''
+            IPv${toString v} address of the interface.  Leave empty to configure the
+            interface using DHCP.
+          '';
+        };
 
-      prefixLength = mkOption {
-        type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128));
-        description = ''
-          Subnet mask of the interface, specified as the number of
-          bits in the prefix (<literal>${if v == 4 then "24" else "64"}</literal>).
-        '';
+        prefixLength = mkOption {
+          type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128));
+          description = ''
+            Subnet mask of the interface, specified as the number of
+            bits in the prefix (<literal>${if v == 4 then "24" else "64"}</literal>).
+          '';
+        };
       };
     };
 
@@ -141,8 +142,7 @@ let
           { address = "10.0.0.1"; prefixLength = 16; }
           { address = "192.168.1.1"; prefixLength = 24; }
         ];
-        type = types.listOf types.optionSet;
-        options = addrOpts 4;
+        type = with types; listOf (submodule (addrOpts 4));
         description = ''
           List of IPv4 addresses that will be statically assigned to the interface.
         '';
@@ -154,8 +154,7 @@ let
           { address = "fdfd:b3f0:482::1"; prefixLength = 48; }
           { address = "2001:1470:fffd:2098::e006"; prefixLength = 64; }
         ];
-        type = types.listOf types.optionSet;
-        options = addrOpts 6;
+        type = with types; listOf (submodule (addrOpts 6));
         description = ''
           List of IPv6 addresses that will be statically assigned to the interface.
         '';
@@ -415,8 +414,7 @@ in
         <option>networking.useDHCP</option> is true, then every
         interface not listed here will be configured using DHCP.
       '';
-      type = types.loaOf types.optionSet;
-      options = [ interfaceOpts ];
+      type = with types; loaOf (submodule interfaceOpts);
     };
 
     networking.vswitches = mkOption {
@@ -434,53 +432,55 @@ in
           interface.
         '';
 
-      type = types.attrsOf types.optionSet;
+      type = with types; attrsOf (submodule {
 
-      options = {
+        options = {
 
-        interfaces = mkOption {
-          example = [ "eth0" "eth1" ];
-          type = types.listOf types.str;
-          description =
-            "The physical network interfaces connected by the vSwitch.";
-        };
+          interfaces = mkOption {
+            example = [ "eth0" "eth1" ];
+            type = types.listOf types.str;
+            description =
+              "The physical network interfaces connected by the vSwitch.";
+          };
 
-        controllers = mkOption {
-          type = types.listOf types.str;
-          default = [];
-          example = [ "ptcp:6653:[::1]" ];
-          description = ''
-            Specify the controller targets. For the allowed options see <literal>man 8 ovs-vsctl</literal>.
-          '';
-        };
+          controllers = mkOption {
+            type = types.listOf types.str;
+            default = [];
+            example = [ "ptcp:6653:[::1]" ];
+            description = ''
+              Specify the controller targets. For the allowed options see <literal>man 8 ovs-vsctl</literal>.
+            '';
+          };
 
-        openFlowRules = mkOption {
-          type = types.lines;
-          default = "";
-          example = ''
-            actions=normal
-          '';
-          description = ''
-            OpenFlow rules to insert into the Open vSwitch. All <literal>openFlowRules</literal> are
-            loaded with <literal>ovs-ofctl</literal> within one atomic operation.
-          '';
-        };
+          openFlowRules = mkOption {
+            type = types.lines;
+            default = "";
+            example = ''
+              actions=normal
+            '';
+            description = ''
+              OpenFlow rules to insert into the Open vSwitch. All <literal>openFlowRules</literal> are
+              loaded with <literal>ovs-ofctl</literal> within one atomic operation.
+            '';
+          };
+
+          extraOvsctlCmds = mkOption {
+            type = types.lines;
+            default = "";
+            example = ''
+              set-fail-mode <switch_name> secure
+              set Bridge <switch_name> stp_enable=true
+            '';
+            description = ''
+              Commands to manipulate the Open vSwitch database. Every line executed with <literal>ovs-vsctl</literal>.
+              All commands are bundled together with the operations for adding the interfaces
+              into one atomic operation.
+            '';
+          };
 
-        extraOvsctlCmds = mkOption {
-          type = types.lines;
-          default = "";
-          example = ''
-            set-fail-mode <switch_name> secure
-            set Bridge <switch_name> stp_enable=true
-          '';
-          description = ''
-            Commands to manipulate the Open vSwitch database. Every line executed with <literal>ovs-vsctl</literal>.
-            All commands are bundled together with the operations for adding the interfaces
-            into one atomic operation.
-          '';
         };
 
-      };
+      });
 
     };
 
@@ -499,25 +499,27 @@ in
           bridge's network interface.
         '';
 
-      type = types.attrsOf types.optionSet;
+      type = with types; attrsOf (submodule {
 
-      options = {
+        options = {
 
-        interfaces = mkOption {
-          example = [ "eth0" "eth1" ];
-          type = types.listOf types.str;
-          description =
-            "The physical network interfaces connected by the bridge.";
-        };
+          interfaces = mkOption {
+            example = [ "eth0" "eth1" ];
+            type = types.listOf types.str;
+            description =
+              "The physical network interfaces connected by the bridge.";
+          };
+
+          rstp = mkOption {
+            example = true;
+            default = false;
+            type = types.bool;
+            description = "Whether the bridge interface should enable rstp.";
+          };
 
-        rstp = mkOption {
-          example = true;
-          default = false;
-          type = types.bool;
-          description = "Whether the bridge interface should enable rstp.";
         };
 
-      };
+      });
 
     };
 
@@ -538,65 +540,66 @@ in
         name specifying the name of the bond's network interface
       '';
 
-      type = types.attrsOf types.optionSet;
+      type = with types; attrsOf (submodule {
 
-      options = {
+        options = {
 
-        interfaces = mkOption {
-          example = [ "enp4s0f0" "enp4s0f1" "wlan0" ];
-          type = types.listOf types.str;
-          description = "The interfaces to bond together";
-        };
+          interfaces = mkOption {
+            example = [ "enp4s0f0" "enp4s0f1" "wlan0" ];
+            type = types.listOf types.str;
+            description = "The interfaces to bond together";
+          };
 
-        lacp_rate = mkOption {
-          default = null;
-          example = "fast";
-          type = types.nullOr types.str;
-          description = ''
-            Option specifying the rate in which we'll ask our link partner
-            to transmit LACPDU packets in 802.3ad mode.
-          '';
-        };
-
-        miimon = mkOption {
-          default = null;
-          example = 100;
-          type = types.nullOr types.int;
-          description = ''
-            Miimon is the number of millisecond in between each round of polling
-            by the device driver for failed links. By default polling is not
-            enabled and the driver is trusted to properly detect and handle
-            failure scenarios.
-          '';
-        };
-
-        mode = mkOption {
-          default = null;
-          example = "active-backup";
-          type = types.nullOr types.str;
-          description = ''
-            The mode which the bond will be running. The default mode for
-            the bonding driver is balance-rr, optimizing for throughput.
-            More information about valid modes can be found at
-            https://www.kernel.org/doc/Documentation/networking/bonding.txt
-          '';
-        };
+          lacp_rate = mkOption {
+            default = null;
+            example = "fast";
+            type = types.nullOr types.str;
+            description = ''
+              Option specifying the rate in which we'll ask our link partner
+              to transmit LACPDU packets in 802.3ad mode.
+            '';
+          };
+
+          miimon = mkOption {
+            default = null;
+            example = 100;
+            type = types.nullOr types.int;
+            description = ''
+              Miimon is the number of millisecond in between each round of polling
+              by the device driver for failed links. By default polling is not
+              enabled and the driver is trusted to properly detect and handle
+              failure scenarios.
+            '';
+          };
+
+          mode = mkOption {
+            default = null;
+            example = "active-backup";
+            type = types.nullOr types.str;
+            description = ''
+              The mode which the bond will be running. The default mode for
+              the bonding driver is balance-rr, optimizing for throughput.
+              More information about valid modes can be found at
+              https://www.kernel.org/doc/Documentation/networking/bonding.txt
+            '';
+          };
+
+          xmit_hash_policy = mkOption {
+            default = null;
+            example = "layer2+3";
+            type = types.nullOr types.str;
+            description = ''
+              Selects the transmit hash policy to use for slave selection in
+              balance-xor, 802.3ad, and tlb modes.
+            '';
+          };
 
-        xmit_hash_policy = mkOption {
-          default = null;
-          example = "layer2+3";
-          type = types.nullOr types.str;
-          description = ''
-            Selects the transmit hash policy to use for slave selection in
-            balance-xor, 802.3ad, and tlb modes.
-          '';
         };
 
-      };
+      });
     };
 
     networking.macvlans = mkOption {
-      type = types.attrsOf types.optionSet;
       default = { };
       example = literalExample {
         wan = {
@@ -608,26 +611,28 @@ in
         This option allows you to define macvlan interfaces which should
         be automatically created.
       '';
-      options = {
+      type = with types; attrsOf (submodule {
+        options = {
+
+          interface = mkOption {
+            example = "enp4s0";
+            type = types.str;
+            description = "The interface the macvlan will transmit packets through.";
+          };
+
+          mode = mkOption {
+            default = null;
+            type = types.nullOr types.str;
+            example = "vepa";
+            description = "The mode of the macvlan device.";
+          };
 
-        interface = mkOption {
-          example = "enp4s0";
-          type = types.str;
-          description = "The interface the macvlan will transmit packets through.";
         };
 
-        mode = mkOption {
-          default = null;
-          type = types.nullOr types.str;
-          example = "vepa";
-          description = "The mode of the macvlan device.";
-        };
-
-      };
+      });
     };
 
     networking.sits = mkOption {
-      type = types.attrsOf types.optionSet;
       default = { };
       example = literalExample {
         hurricane = {
@@ -644,46 +649,49 @@ in
       description = ''
         This option allows you to define 6-to-4 interfaces which should be automatically created.
       '';
-      options = {
-
-        remote = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "10.0.0.1";
-          description = ''
-            The address of the remote endpoint to forward traffic over.
-          '';
-        };
-
-        local = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "10.0.0.22";
-          description = ''
-            The address of the local endpoint which the remote
-            side should send packets to.
-          '';
-        };
-
-        ttl = mkOption {
-          type = types.nullOr types.int;
-          default = null;
-          example = 255;
-          description = ''
-            The time-to-live of the connection to the remote tunnel endpoint.
-          '';
-        };
+      type = with types; attrsOf (submodule {
+        options = {
+
+          remote = mkOption {
+            type = types.nullOr types.str;
+            default = null;
+            example = "10.0.0.1";
+            description = ''
+              The address of the remote endpoint to forward traffic over.
+            '';
+          };
+
+          local = mkOption {
+            type = types.nullOr types.str;
+            default = null;
+            example = "10.0.0.22";
+            description = ''
+              The address of the local endpoint which the remote
+              side should send packets to.
+            '';
+          };
+
+          ttl = mkOption {
+            type = types.nullOr types.int;
+            default = null;
+            example = 255;
+            description = ''
+              The time-to-live of the connection to the remote tunnel endpoint.
+            '';
+          };
+
+          dev = mkOption {
+            type = types.nullOr types.str;
+            default = null;
+            example = "enp4s0f0";
+            description = ''
+              The underlying network device on which the tunnel resides.
+            '';
+          };
 
-        dev = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "enp4s0f0";
-          description = ''
-            The underlying network device on which the tunnel resides.
-          '';
         };
 
-      };
+      });
     };
 
     networking.vlans = mkOption {
@@ -706,23 +714,26 @@ in
           specifying the name of the vlan interface.
         '';
 
-      type = types.attrsOf types.optionSet;
+      type = with types; attrsOf (submodule {
 
-      options = {
+        options = {
 
-        id = mkOption {
-          example = 1;
-          type = types.int;
-          description = "The vlan identifier";
-        };
+          id = mkOption {
+            example = 1;
+            type = types.int;
+            description = "The vlan identifier";
+          };
+
+          interface = mkOption {
+            example = "enp4s0";
+            type = types.str;
+            description = "The interface the vlan will transmit packets through.";
+          };
 
-        interface = mkOption {
-          example = "enp4s0";
-          type = types.str;
-          description = "The interface the vlan will transmit packets through.";
         };
 
-      };
+      });
+
     };
 
     networking.wlanInterfaces = mkOption {
@@ -760,73 +771,76 @@ in
           would have to be created explicitly.
         '';
 
-      type = types.attrsOf types.optionSet;
-
-      options = {
+      type = with types; attrsOf (submodule {
 
-        device = mkOption {
-          type = types.string;
-          example = "wlp6s0";
-          description = "The name of the underlying hardware WLAN device as assigned by <literal>udev</literal>.";
-        };
+        options = {
 
-        type = mkOption {
-          type = types.string;
-          default = "managed";
-          example = "ibss";
-          description = ''
-            The type of the WLAN interface. The type has to be either <literal>managed</literal>,
-            <literal>ibss</literal>, <literal>monitor</literal>, <literal>mesh</literal> or <literal>wds</literal>.
-            Also, the type has to be supported by the underlying hardware of the device.
-          '';
-        };
+          device = mkOption {
+            type = types.string;
+            example = "wlp6s0";
+            description = "The name of the underlying hardware WLAN device as assigned by <literal>udev</literal>.";
+          };
 
-        meshID = mkOption {
-          type = types.nullOr types.string;
-          default = null;
-          description = "MeshID of interface with type <literal>mesh</literal>.";
-        };
-
-        flags = mkOption {
-          type = types.nullOr types.string;
-          default = null;
-          example = "control";
-          description = ''
-            Flags for interface of type <literal>monitor</literal>. The valid flags are:
-            none:     no special flags
-            fcsfail:  show frames with FCS errors
-            control:  show control frames
-            otherbss: show frames from other BSSes
-            cook:     use cooked mode
-            active:   use active mode (ACK incoming unicast packets)
-          '';
-        };
+          type = mkOption {
+            type = types.string;
+            default = "managed";
+            example = "ibss";
+            description = ''
+              The type of the WLAN interface. The type has to be either <literal>managed</literal>,
+              <literal>ibss</literal>, <literal>monitor</literal>, <literal>mesh</literal> or <literal>wds</literal>.
+              Also, the type has to be supported by the underlying hardware of the device.
+            '';
+          };
+
+          meshID = mkOption {
+            type = types.nullOr types.string;
+            default = null;
+            description = "MeshID of interface with type <literal>mesh</literal>.";
+          };
+
+          flags = mkOption {
+            type = types.nullOr types.string;
+            default = null;
+            example = "control";
+            description = ''
+              Flags for interface of type <literal>monitor</literal>. The valid flags are:
+              none:     no special flags
+              fcsfail:  show frames with FCS errors
+              control:  show control frames
+              otherbss: show frames from other BSSes
+              cook:     use cooked mode
+              active:   use active mode (ACK incoming unicast packets)
+            '';
+          };
+
+          fourAddr = mkOption {
+            type = types.nullOr types.bool;
+            default = null;
+            description = "Whether to enable <literal>4-address mode</literal> with type <literal>managed</literal>.";
+          };
+
+          mac = mkOption {
+            type = types.nullOr types.str;
+            default = null;
+            example = "02:00:00:00:00:01";
+            description = ''
+              MAC address to use for the device. If <literal>null</literal>, then the MAC of the
+              underlying hardware WLAN device is used.
+
+              INFO: Locally administered MAC addresses are of the form:
+              <itemizedlist>
+              <listitem><para>x2:xx:xx:xx:xx:xx</para></listitem>
+              <listitem><para>x6:xx:xx:xx:xx:xx</para></listitem>
+              <listitem><para>xA:xx:xx:xx:xx:xx</para></listitem>
+              <listitem><para>xE:xx:xx:xx:xx:xx</para></listitem>
+              </itemizedlist>
+            '';
+          };
 
-        fourAddr = mkOption {
-          type = types.nullOr types.bool;
-          default = null;
-          description = "Whether to enable <literal>4-address mode</literal> with type <literal>managed</literal>.";
         };
 
-        mac = mkOption {
-          type = types.nullOr types.str;
-          default = null;
-          example = "02:00:00:00:00:01";
-          description = ''
-            MAC address to use for the device. If <literal>null</literal>, then the MAC of the
-            underlying hardware WLAN device is used.
-
-            INFO: Locally administered MAC addresses are of the form:
-            <itemizedlist>
-            <listitem><para>x2:xx:xx:xx:xx:xx</para></listitem>
-            <listitem><para>x6:xx:xx:xx:xx:xx</para></listitem>
-            <listitem><para>xA:xx:xx:xx:xx:xx</para></listitem>
-            <listitem><para>xE:xx:xx:xx:xx:xx</para></listitem>
-            </itemizedlist>
-          '';
-        };
+      });
 
-      };
     };
 
     networking.useDHCP = mkOption {
@@ -932,8 +946,10 @@ in
       ]
       ++ bridgeStp;
 
+    # The network-interfaces target is kept for backwards compatibility.
+    # New modules must NOT use it.
     systemd.targets."network-interfaces" =
-      { description = "All Network Interfaces";
+      { description = "All Network Interfaces (deprecated)";
         wantedBy = [ "network.target" ];
         before = [ "network.target" ];
         after = [ "network-pre.target" ];
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index f9c3f2e53adc..17e69b311b48 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -138,7 +138,7 @@ let cfg = config.ec2; in
     # Allow root logins only using the SSH key that the user specified
     # at instance creation time.
     services.openssh.enable = true;
-    services.openssh.permitRootLogin = "without-password";
+    services.openssh.permitRootLogin = "prohibit-password";
 
     # Force getting the hostname from EC2.
     networking.hostName = mkDefault "";
diff --git a/nixos/modules/virtualisation/azure-common.nix b/nixos/modules/virtualisation/azure-common.nix
index 70a3d752f6d1..5cd2304a2953 100644
--- a/nixos/modules/virtualisation/azure-common.nix
+++ b/nixos/modules/virtualisation/azure-common.nix
@@ -24,7 +24,7 @@ with lib;
   # Allow root logins only using the SSH key that the user specified
   # at instance creation time, ping client connections to avoid timeouts
   services.openssh.enable = true;
-  services.openssh.permitRootLogin = "without-password";
+  services.openssh.permitRootLogin = "prohibit-password";
   services.openssh.extraConfig = ''
     ClientAliveInterval 180
   '';
diff --git a/nixos/modules/virtualisation/brightbox-image.nix b/nixos/modules/virtualisation/brightbox-image.nix
index e2905913b6c5..7f45f0f34f71 100644
--- a/nixos/modules/virtualisation/brightbox-image.nix
+++ b/nixos/modules/virtualisation/brightbox-image.nix
@@ -103,7 +103,7 @@ in
   # Allow root logins only using the SSH key that the user specified
   # at instance creation time.
   services.openssh.enable = true;
-  services.openssh.permitRootLogin = "without-password";
+  services.openssh.permitRootLogin = "prohibit-password";
 
   # Force getting the hostname from Google Compute.
   networking.hostName = mkDefault "";
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index eaa4d828afb6..5e1cfcdfc6fb 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -129,6 +129,9 @@ let
         --setenv HOST_ADDRESS6="$HOST_ADDRESS6" \
         --setenv LOCAL_ADDRESS6="$LOCAL_ADDRESS6" \
         --setenv PATH="$PATH" \
+        ${if cfg.additionalCapabilities != null then
+          ''--capability="${concatStringsSep " " cfg.additionalCapabilities}"'' else ""
+        } \
         ${containerInit cfg} "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init"
     '';
 
@@ -159,7 +162,7 @@ let
             fi
           ''
         else
-          ''${ipcmd} add ${cfg.attribute} dev $ifaceHost'';
+          ''${ipcmd} add ${cfg.${attribute}} dev $ifaceHost'';
       renderExtraVeth = name: cfg:
         if cfg.hostBridge != null then
           ''
@@ -205,6 +208,41 @@ let
       ''
   );
 
+  serviceDirectives = cfg: {
+    ExecReload = pkgs.writeScript "reload-container"
+      ''
+        #! ${pkgs.stdenv.shell} -e
+        ${pkgs.nixos-container}/bin/nixos-container run "$INSTANCE" -- \
+          bash --login -c "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/bin/switch-to-configuration test"
+      '';
+
+    SyslogIdentifier = "container %i";
+
+    EnvironmentFile = "-/etc/containers/%i.conf";
+
+    Type = "notify";
+
+    # Note that on reboot, systemd-nspawn returns 133, so this
+    # unit will be restarted. On poweroff, it returns 0, so the
+    # unit won't be restarted.
+    RestartForceExitStatus = "133";
+    SuccessExitStatus = "133";
+
+    Restart = "on-failure";
+
+    # Hack: we don't want to kill systemd-nspawn, since we call
+    # "machinectl poweroff" in preStop to shut down the
+    # container cleanly. But systemd requires sending a signal
+    # (at least if we want remaining processes to be killed
+    # after the timeout). So send an ignored signal.
+    KillMode = "mixed";
+    KillSignal = "WINCH";
+
+    DevicePolicy = "closed";
+    DeviceAllow = map (d: "${d.node} ${d.modifier}") cfg.allowedDevices;
+  };
+
+
   system = config.nixpkgs.system;
 
   bindMountOpts = { name, config, ... }: {
@@ -235,6 +273,27 @@ let
 
   };
 
+  allowedDeviceOpts = { name, config, ... }: {
+    options = {
+      node = mkOption {
+        example = "/dev/net/tun";
+        type = types.str;
+        description = "Path to device node";
+      };
+      modifier = mkOption {
+        example = "rw";
+        type = types.str;
+        description = ''
+          Device node access modifier. Takes a combination
+          <literal>r</literal> (read), <literal>w</literal> (write), and
+          <literal>m</literal> (mknod). See the
+          <literal>systemd.resource-control(5)</literal> man page for more
+          information.'';
+      };
+    };
+  };
+
+
   mkBindFlag = d:
                let flagPrefix = if d.isReadOnly then " --bind-ro=" else " --bind=";
                    mountstr = if d.hostPath != null then "${d.hostPath}:${d.mountPoint}" else "${d.mountPoint}";
@@ -302,6 +361,8 @@ let
   dummyConfig =
     {
       extraVeths = {};
+      additionalCapabilities = [];
+      allowedDevices = [];
       hostAddress = null;
       hostAddress6 = null;
       localAddress = null;
@@ -368,6 +429,26 @@ in
               '';
             };
 
+            additionalCapabilities = mkOption {
+              type = types.listOf types.str;
+              default = [];
+              example = [ "CAP_NET_ADMIN" "CAP_MKNOD" ];
+              description = ''
+                Grant additional capabilities to the container.  See the
+                capabilities(7) and systemd-nspawn(1) man pages for more
+                information.
+              '';
+            };
+            enableTun = mkOption {
+              type = types.bool;
+              default = false;
+              description = ''
+                Allows the container to create and setup tunnel interfaces
+                by granting the <literal>NET_ADMIN</literal> capability and
+                enabling access to <literal>/dev/net/tun</literal>.
+              '';
+            };
+
             privateNetwork = mkOption {
               type = types.bool;
               default = false;
@@ -392,9 +473,8 @@ in
             };
 
             extraVeths = mkOption {
-              type = types.attrsOf types.optionSet;
+              type = with types; attrsOf (submodule networkOptions);
               default = {};
-              options = networkOptions;
               description = ''
                 Extra veth-pairs to be created for the container
               '';
@@ -409,8 +489,7 @@ in
             };
 
             bindMounts = mkOption {
-              type = types.loaOf types.optionSet;
-              options = [ bindMountOpts ];
+              type = with types; loaOf (submodule bindMountOpts);
               default = {};
               example = { "/home" = { hostPath = "/home/alice";
                                       isReadOnly = false; };
@@ -422,6 +501,15 @@ in
                 '';
             };
 
+            allowedDevices = mkOption {
+              type = with types; listOf (submodule allowedDeviceOpts);
+              default = [];
+              example = [ { node = "/dev/net/tun"; modifier = "rw"; } ];
+              description = ''
+                A list of device nodes to which the containers has access to.
+              '';
+            };
+
           } // networkOptions;
 
           config = mkMerge
@@ -488,59 +576,39 @@ in
 
       restartIfChanged = false;
 
-      serviceConfig = {
-        ExecReload = pkgs.writeScript "reload-container"
-          ''
-            #! ${pkgs.stdenv.shell} -e
-            ${pkgs.nixos-container}/bin/nixos-container run "$INSTANCE" -- \
-              bash --login -c "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/bin/switch-to-configuration test"
-          '';
-
-        SyslogIdentifier = "container %i";
-
-        EnvironmentFile = "-/etc/containers/%i.conf";
-
-        Type = "notify";
-
-        # Note that on reboot, systemd-nspawn returns 133, so this
-        # unit will be restarted. On poweroff, it returns 0, so the
-        # unit won't be restarted.
-        RestartForceExitStatus = "133";
-        SuccessExitStatus = "133";
-
-        Restart = "on-failure";
-
-        # Hack: we don't want to kill systemd-nspawn, since we call
-        # "machinectl poweroff" in preStop to shut down the
-        # container cleanly. But systemd requires sending a signal
-        # (at least if we want remaining processes to be killed
-        # after the timeout). So send an ignored signal.
-        KillMode = "mixed";
-        KillSignal = "WINCH";
-
-        DevicePolicy = "closed";
-      };
+      serviceConfig = serviceDirectives dummyConfig;
     };
   in {
     systemd.services = listToAttrs (filter (x: x.value != null) (
       # The generic container template used by imperative containers
       [{ name = "container@"; value = unit; }]
       # declarative containers
-      ++ (mapAttrsToList (name: cfg: nameValuePair "container@${name}" (
-        unit // {
-          preStart = preStartScript cfg;
-          script = startScript cfg;
-          postStart = postStartScript cfg;
-        } // (
-        if cfg.autoStart then
-          {
-            wantedBy = [ "multi-user.target" ];
-            wants = [ "network.target" ];
-            after = [ "network.target" ];
-            restartTriggers = [ cfg.path ];
-            reloadIfChanged = true;
-          }
-        else {})
+      ++ (mapAttrsToList (name: cfg: nameValuePair "container@${name}" (let
+          config = cfg // (
+          if cfg.enableTun then
+            {
+              allowedDevices = cfg.allowedDevices
+                ++ [ { node = "/dev/net/tun"; modifier = "rw"; } ];
+              additionalCapabilities = cfg.additionalCapabilities
+                ++ [ "CAP_NET_ADMIN" ];
+            }
+          else {});
+        in
+          unit // {
+            preStart = preStartScript config;
+            script = startScript config;
+            postStart = postStartScript config;
+            serviceConfig = serviceDirectives config;
+          } // (
+          if config.autoStart then
+            {
+              wantedBy = [ "multi-user.target" ];
+              wants = [ "network.target" ];
+              after = [ "network.target" ];
+              restartTriggers = [ config.path ];
+              reloadIfChanged = true;
+            }
+          else {})
       )) config.containers)
     ));
 
diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix
index bdf6ed4dcd29..ffd1cbec3ce3 100644
--- a/nixos/modules/virtualisation/ec2-amis.nix
+++ b/nixos/modules/virtualisation/ec2-amis.nix
@@ -1,4 +1,4 @@
-{
+let self = {
   "14.04".ap-northeast-1.hvm-ebs = "ami-71c6f470";
   "14.04".ap-northeast-1.pv-ebs = "ami-4dcbf84c";
   "14.04".ap-northeast-1.pv-s3 = "ami-8fc4f68e";
@@ -134,4 +134,52 @@
   "16.03".us-west-2.hvm-s3 = "ami-925c9ff2";
   "16.03".us-west-2.pv-ebs = "ami-5e61a23e";
   "16.03".us-west-2.pv-s3 = "ami-734c8f13";
-}
+
+  # 16.09.666.3738950
+  "16.09".ap-northeast-1.hvm-ebs = "ami-35578954";
+  "16.09".ap-northeast-1.hvm-s3 = "ami-d6528cb7";
+  "16.09".ap-northeast-1.pv-ebs = "ami-07548a66";
+  "16.09".ap-northeast-1.pv-s3 = "ami-f1548a90";
+  "16.09".ap-northeast-2.hvm-ebs = "ami-d48753ba";
+  "16.09".ap-northeast-2.hvm-s3 = "ami-4c865222";
+  "16.09".ap-northeast-2.pv-ebs = "ami-ca8551a4";
+  "16.09".ap-northeast-2.pv-s3 = "ami-9c8551f2";
+  "16.09".ap-south-1.hvm-ebs = "ami-922450fd";
+  "16.09".ap-south-1.hvm-s3 = "ami-6d3a4e02";
+  "16.09".ap-south-1.pv-ebs = "ami-4d394d22";
+  "16.09".ap-south-1.pv-s3 = "ami-17384c78";
+  "16.09".ap-southeast-1.hvm-ebs = "ami-f824809b";
+  "16.09".ap-southeast-1.hvm-s3 = "ami-f924809a";
+  "16.09".ap-southeast-1.pv-ebs = "ami-af2480cc";
+  "16.09".ap-southeast-1.pv-s3 = "ami-5826823b";
+  "16.09".ap-southeast-2.hvm-ebs = "ami-40fecd23";
+  "16.09".ap-southeast-2.hvm-s3 = "ami-48fecd2b";
+  "16.09".ap-southeast-2.pv-ebs = "ami-dffecdbc";
+  "16.09".ap-southeast-2.pv-s3 = "ami-e0fccf83";
+  "16.09".eu-central-1.hvm-ebs = "ami-1d8b7472";
+  "16.09".eu-central-1.hvm-s3 = "ami-1c8b7473";
+  "16.09".eu-central-1.pv-ebs = "ami-8c8d72e3";
+  "16.09".eu-central-1.pv-s3 = "ami-3488775b";
+  "16.09".eu-west-1.hvm-ebs = "ami-15662766";
+  "16.09".eu-west-1.hvm-s3 = "ami-476b2a34";
+  "16.09".eu-west-1.pv-ebs = "ami-876928f4";
+  "16.09".eu-west-1.pv-s3 = "ami-70682903";
+  "16.09".sa-east-1.hvm-ebs = "ami-27bc2e4b";
+  "16.09".sa-east-1.hvm-s3 = "ami-e4b92b88";
+  "16.09".sa-east-1.pv-ebs = "ami-4dbe2c21";
+  "16.09".sa-east-1.pv-s3 = "ami-77fc6e1b";
+  "16.09".us-east-1.hvm-ebs = "ami-93347684";
+  "16.09".us-east-1.hvm-s3 = "ami-5e347649";
+  "16.09".us-east-1.pv-ebs = "ami-b0387aa7";
+  "16.09".us-east-1.pv-s3 = "ami-51357746";
+  "16.09".us-west-1.hvm-ebs = "ami-06337a66";
+  "16.09".us-west-1.hvm-s3 = "ami-76307916";
+  "16.09".us-west-1.pv-ebs = "ami-fd327b9d";
+  "16.09".us-west-1.pv-s3 = "ami-cc347dac";
+  "16.09".us-west-2.hvm-ebs = "ami-49fe2729";
+  "16.09".us-west-2.hvm-s3 = "ami-93fc25f3";
+  "16.09".us-west-2.pv-ebs = "ami-14fe2774";
+  "16.09".us-west-2.pv-s3 = "ami-74f12814";
+
+  latest = self."16.09";
+}; in self
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index 489b612f1675..90dbd3b6d632 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -111,7 +111,7 @@ in
   # Allow root logins only using the SSH key that the user specified
   # at instance creation time.
   services.openssh.enable = true;
-  services.openssh.permitRootLogin = "without-password";
+  services.openssh.permitRootLogin = "prohibit-password";
   services.openssh.passwordAuthentication = mkDefault false;
 
   # Force getting the hostname from Google Compute.
diff --git a/nixos/modules/virtualisation/nova-image.nix b/nixos/modules/virtualisation/nova-image.nix
index 7971212b47c5..e253c77ebb4f 100644
--- a/nixos/modules/virtualisation/nova-image.nix
+++ b/nixos/modules/virtualisation/nova-image.nix
@@ -31,7 +31,7 @@ with lib;
 
   # Allow root logins
   services.openssh.enable = true;
-  services.openssh.permitRootLogin = "without-password";
+  services.openssh.permitRootLogin = "prohibit-password";
 
   # Put /tmp and /var on /ephemeral0, which has a lot more space.
   # Unfortunately we can't do this with the `fileSystems' option