summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorParnell Springmeyer <parnell@digitalmentat.com>2017-02-13 17:16:28 -0600
committerParnell Springmeyer <parnell@digitalmentat.com>2017-02-13 17:16:28 -0600
commit9e36a58649199a16a15cba3c78966ab0538a6fd7 (patch)
tree289d50ecf1068cfac80bdeabdd34d2d42ecbd755 /nixos/modules
parent128bdac94fe8173845e162c61ddb83cb4b8ed8de (diff)
parent486b9be579fc1f046671ddaf1157f084ba956bdd (diff)
downloadnixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar
nixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.gz
nixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.bz2
nixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.lz
nixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.xz
nixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.zst
nixpkgs-9e36a58649199a16a15cba3c78966ab0538a6fd7.zip
Merging against upstream master
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/hardware/opengl.nix9
-rw-r--r--nixos/modules/hardware/video/amdgpu-pro.nix5
-rw-r--r--nixos/modules/hardware/video/ati.nix2
-rw-r--r--nixos/modules/hardware/video/bumblebee.nix4
-rw-r--r--nixos/modules/hardware/video/nvidia.nix19
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-aarch64.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix4
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl20
-rw-r--r--nixos/modules/misc/ids.nix10
-rw-r--r--nixos/modules/misc/nixpkgs.nix16
-rw-r--r--nixos/modules/module-list.nix14
-rw-r--r--nixos/modules/profiles/all-hardware.nix3
-rw-r--r--nixos/modules/profiles/graphical.nix4
-rw-r--r--nixos/modules/rename.nix4
-rw-r--r--nixos/modules/security/grsecurity.xml38
-rw-r--r--nixos/modules/security/pam.nix4
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix2
-rw-r--r--nixos/modules/services/continuous-integration/buildbot/master.nix30
-rw-r--r--nixos/modules/services/continuous-integration/buildbot/worker.nix128
-rw-r--r--nixos/modules/services/editors/emacs.xml4
-rw-r--r--nixos/modules/services/hardware/bluetooth.nix53
-rw-r--r--nixos/modules/services/hardware/illum.nix35
-rw-r--r--nixos/modules/services/hardware/sane.nix2
-rw-r--r--nixos/modules/services/hardware/trezord.nix54
-rw-r--r--nixos/modules/services/mail/postfix.nix2
-rw-r--r--nixos/modules/services/misc/geoip-updater.nix300
-rw-r--r--nixos/modules/services/misc/gitlab.nix4
-rw-r--r--nixos/modules/services/misc/gogs.nix1
-rw-r--r--nixos/modules/services/misc/ihaskell.nix12
-rw-r--r--nixos/modules/services/misc/ssm-agent.nix45
-rw-r--r--nixos/modules/services/misc/taskserver/default.nix8
-rw-r--r--nixos/modules/services/monitoring/grafana.nix9
-rw-r--r--nixos/modules/services/network-filesystems/glusterfs.nix84
-rw-r--r--nixos/modules/services/network-filesystems/ipfs.nix62
-rw-r--r--nixos/modules/services/network-filesystems/nfsd.nix97
-rw-r--r--nixos/modules/services/networking/asterisk.nix20
-rw-r--r--nixos/modules/services/networking/chrony.nix47
-rw-r--r--nixos/modules/services/networking/cjdns.nix5
-rw-r--r--nixos/modules/services/networking/dnschain.nix177
-rw-r--r--nixos/modules/services/networking/firewall.nix4
-rw-r--r--nixos/modules/services/networking/i2pd.nix2
-rw-r--r--nixos/modules/services/networking/libreswan.nix2
-rw-r--r--nixos/modules/services/networking/namecoind.nix211
-rw-r--r--nixos/modules/services/networking/nylon.nix74
-rw-r--r--nixos/modules/services/networking/quassel.nix6
-rw-r--r--nixos/modules/services/networking/redsocks.nix270
-rw-r--r--nixos/modules/services/networking/rpcbind.nix52
-rw-r--r--nixos/modules/services/networking/searx.nix10
-rw-r--r--nixos/modules/services/networking/supplicant.nix3
-rw-r--r--nixos/modules/services/security/hologram-agent.nix57
-rw-r--r--nixos/modules/services/security/hologram-server.nix (renamed from nixos/modules/services/security/hologram.nix)0
-rw-r--r--nixos/modules/services/system/dbus.nix24
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix2
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/moodle.nix198
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/wordpress.nix4
-rw-r--r--nixos/modules/services/web-servers/caddy.nix1
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix17
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix5
-rw-r--r--nixos/modules/services/x11/desktop-managers/enlightenment.nix5
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix7
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4.nix190
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix9
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix8
-rw-r--r--nixos/modules/services/x11/display-managers/kdm.nix158
-rw-r--r--nixos/modules/services/x11/terminal-server.nix14
-rw-r--r--nixos/modules/services/x11/xserver.nix26
-rw-r--r--nixos/modules/system/activation/top-level.nix3
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix14
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl11
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/builder.sh12
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix2
-rw-r--r--nixos/modules/system/boot/networkd.nix6
-rw-r--r--nixos/modules/system/boot/resolved.nix4
-rw-r--r--nixos/modules/system/boot/systemd-lib.nix8
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix6
-rw-r--r--nixos/modules/system/boot/systemd.nix41
-rw-r--r--nixos/modules/tasks/filesystems.nix2
-rw-r--r--nixos/modules/tasks/filesystems/glusterfs.nix11
-rw-r--r--nixos/modules/tasks/filesystems/nfs.nix97
-rw-r--r--nixos/modules/tasks/kbd.nix5
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix20
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix10
-rw-r--r--nixos/modules/tasks/network-interfaces.nix49
-rw-r--r--nixos/modules/testing/test-instrumentation.nix9
-rw-r--r--nixos/modules/virtualisation/azure-image.nix2
-rw-r--r--nixos/modules/virtualisation/ecs-agent.nix45
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix11
-rw-r--r--nixos/modules/virtualisation/vmware-guest.nix13
89 files changed, 1895 insertions, 1190 deletions
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index 5e38a988096..486fe7c1cd8 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -133,13 +133,10 @@ in
       '';
 
     environment.sessionVariables.LD_LIBRARY_PATH =
-      [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ];
+      [ "/run/opengl-driver/lib" ] ++ optional cfg.driSupport32Bit "/run/opengl-driver-32/lib";
 
-    environment.extraInit = ''
-      export XDG_DATA_DIRS=$XDG_DATA_DIRS:/run/opengl-driver/share
-    '' + optionalString cfg.driSupport32Bit ''
-      export XDG_DATA_DIRS=$XDG_DATA_DIRS:/run/opengl-driver-32/share
-    '';
+    environment.variables.XDG_DATA_DIRS =
+      [ "/run/opengl-driver/share" ] ++ optional cfg.driSupport32Bit "/run/opengl-driver-32/share";
 
     hardware.opengl.package = mkDefault (makePackage pkgs);
     hardware.opengl.package32 = mkDefault (makePackage pkgs_i686);
diff --git a/nixos/modules/hardware/video/amdgpu-pro.nix b/nixos/modules/hardware/video/amdgpu-pro.nix
index 979810abf90..5cc96d8bd07 100644
--- a/nixos/modules/hardware/video/amdgpu-pro.nix
+++ b/nixos/modules/hardware/video/amdgpu-pro.nix
@@ -21,6 +21,8 @@ in
 
   config = mkIf enabled {
 
+    nixpkgs.config.xorg.abiCompat = "1.18";
+
     services.xserver.drivers = singleton
       { name = "amdgpu"; modules = [ package ]; libPath = [ package ]; };
 
@@ -44,9 +46,6 @@ in
       "amd/amdrc".source = package + "/etc/amd/amdrc";
       "amd/amdapfxx.blb".source = package + "/etc/amd/amdapfxx.blb";
       "gbm/gbm.conf".source = package + "/etc/gbm/gbm.conf";
-      "OpenCL/vendors/amdocl64.icd".source = package + "/etc/OpenCL/vendors/amdocl64.icd";
-    } // optionalAttrs opengl.driSupport32Bit {
-      "OpenCL/vendors/amdocl32.icd".source = package32 + "/etc/OpenCL/vendors/amdocl32.icd";
     };
 
   };
diff --git a/nixos/modules/hardware/video/ati.nix b/nixos/modules/hardware/video/ati.nix
index bf91bcf0776..022fdea0a0a 100644
--- a/nixos/modules/hardware/video/ati.nix
+++ b/nixos/modules/hardware/video/ati.nix
@@ -18,7 +18,7 @@ in
 
   config = mkIf enabled {
 
-    nixpkgs.config.xorg.fglrxCompat = true;
+    nixpkgs.config.xorg.abiCompat = "1.17";
 
     services.xserver.drivers = singleton
       { name = "fglrx"; modules = [ ati_x11 ]; libPath = [ "${ati_x11}/lib" ]; };
diff --git a/nixos/modules/hardware/video/bumblebee.nix b/nixos/modules/hardware/video/bumblebee.nix
index 3ce97ad31c2..3967137fcf8 100644
--- a/nixos/modules/hardware/video/bumblebee.nix
+++ b/nixos/modules/hardware/video/bumblebee.nix
@@ -76,8 +76,8 @@ in
 
   config = mkIf cfg.enable {
     boot.blacklistedKernelModules = [ "nvidia-drm" "nvidia" "nouveau" ];
-    boot.kernelModules = optional useBbswitch [ "bbswitch" ];
-    boot.extraModulePackages = optional useBbswitch kernel.bbswitch ++ optional useNvidia kernel.nvidia_x11;
+    boot.kernelModules = optional useBbswitch "bbswitch";
+    boot.extraModulePackages = optional useBbswitch kernel.bbswitch ++ optional useNvidia kernel.nvidia_x11.bin;
 
     environment.systemPackages = [ bumblebee primus ];
 
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 8514f765e61..cf723d53269 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -27,6 +27,13 @@ let
   nvidia_x11 = nvidiaForKernel config.boot.kernelPackages;
   nvidia_libs32 = (nvidiaForKernel pkgs_i686.linuxPackages).override { libsOnly = true; kernel = null; };
 
+  nvidiaPackage = nvidia: pkgs:
+    if !nvidia.useGLVND then nvidia
+    else pkgs.buildEnv {
+      name = "nvidia-libs";
+      paths = [ pkgs.libglvnd nvidia.out ];
+    };
+
   enabled = nvidia_x11 != null;
 in
 
@@ -35,19 +42,19 @@ in
   config = mkIf enabled {
 
     services.xserver.drivers = singleton
-      { name = "nvidia"; modules = [ nvidia_x11 ]; libPath = [ nvidia_x11 ]; };
+      { name = "nvidia"; modules = [ nvidia_x11.bin ]; libPath = [ nvidia_x11 ]; };
 
     services.xserver.screenSection =
       ''
         Option "RandRRotation" "on"
       '';
 
-    hardware.opengl.package = nvidia_x11;
-    hardware.opengl.package32 = nvidia_libs32;
+    hardware.opengl.package = nvidiaPackage nvidia_x11 pkgs;
+    hardware.opengl.package32 = nvidiaPackage nvidia_libs32 pkgs_i686;
 
-    environment.systemPackages = [ nvidia_x11 ];
+    environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings nvidia_x11.persistenced ];
 
-    boot.extraModulePackages = [ nvidia_x11 ];
+    boot.extraModulePackages = [ nvidia_x11.bin ];
 
     # nvidia-uvm is required by CUDA applications.
     boot.kernelModules = [ "nvidia-uvm" ];
@@ -62,8 +69,6 @@ in
 
     services.acpid.enable = true;
 
-    environment.etc."OpenCL/vendors/nvidia.icd".source = "${nvidia_x11}/lib/vendors/nvidia.icd";
-
   };
 
 }
diff --git a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
index 8cf349fbd07..c769bc80a48 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
@@ -52,9 +52,7 @@ in
         enable_uart=1
       '';
       in ''
-        for f in bootcode.bin fixup.dat start.elf; do
-          cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/$f boot/
-        done
+        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
         cp ${patchedUboot}/u-boot.bin boot/u-boot-rpi3.bin
         cp ${configTxt} boot/config.txt
         ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
diff --git a/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
index 76f5d4bf647..0b858746ff0 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
@@ -44,9 +44,7 @@ in
         enable_uart=1
       '';
       in ''
-        for f in bootcode.bin fixup.dat start.elf; do
-          cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/$f boot/
-        done
+        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
         cp ${pkgs.ubootRaspberryPi2}/u-boot.bin boot/u-boot-rpi2.bin
         cp ${pkgs.ubootRaspberryPi3_32bit}/u-boot.bin boot/u-boot-rpi3.bin
         cp ${configTxt} boot/config.txt
diff --git a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
index c7915b578d8..886ffd9a092 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
@@ -34,9 +34,7 @@ in
 
   sdImage = {
     populateBootCommands = ''
-      for f in bootcode.bin fixup.dat start.elf; do
-        cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/$f boot/
-      done
+      (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
       cp ${pkgs.ubootRaspberryPi}/u-boot.bin boot/u-boot-rpi.bin
       echo 'kernel u-boot-rpi.bin' > boot/config.txt
       ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 657c28f095d..a1b6cf53597 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -208,9 +208,6 @@ foreach my $path (glob "/sys/bus/pci/devices/*") {
     pciCheck $path;
 }
 
-push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver;
-
-
 # Idem for USB devices.
 
 sub usbCheck {
@@ -277,6 +274,12 @@ if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") {
     push @imports, "<nixpkgs/nixos/modules/profiles/qemu-guest.nix>";
 }
 
+# Also for Hyper-V.
+if ($virt eq "microsoft") {
+    push @initrdAvailableKernelModules, "hv_storvsc";
+    $videoDriver = "fbdev";
+}
+
 
 # Pull in NixOS configuration for containers.
 if ($virt eq "systemd-nspawn") {
@@ -307,6 +310,7 @@ sub findStableDevPath {
     return $dev;
 }
 
+push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver;
 
 # Generate the swapDevices option from the currently activated swap
 # devices.
@@ -588,6 +592,12 @@ $bootLoaderConfig
   # Enable the OpenSSH daemon.
   # services.openssh.enable = true;
 
+  # Open ports in the firewall.
+  # networking.firewall.allowedTCPPorts = [ ... ];
+  # networking.firewall.allowedUDPPorts = [ ... ];
+  # Or disable the firewall altogether.
+  # networking.firewall.enable = false;
+
   # Enable CUPS to print documents.
   # services.printing.enable = true;
 
@@ -597,8 +607,8 @@ $bootLoaderConfig
   # services.xserver.xkbOptions = "eurosign:e";
 
   # Enable the KDE Desktop Environment.
-  # services.xserver.displayManager.kdm.enable = true;
-  # services.xserver.desktopManager.kde4.enable = true;
+  # services.xserver.displayManager.sddm.enable = true;
+  # services.xserver.desktopManager.kde5.enable = true;
 
   # Define a user account. Don't forget to set a password with ‘passwd’.
   # users.extraUsers.guest = {
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 2005f2518ba..1566dbe1677 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -64,7 +64,7 @@
       cups = 36;
       foldingathome = 37;
       sabnzbd = 38;
-      kdm = 39;
+      #kdm = 39; # dropped in 17.03
       ghostone = 40;
       git = 41;
       fourstore = 42;
@@ -206,7 +206,7 @@
       ripple-data-api = 186;
       mediatomb = 187;
       rdnssd = 188;
-      ihaskell = 189;
+      # ihaskell = 189; # unused
       i2p = 190;
       lambdabot = 191;
       asterisk = 192;
@@ -286,6 +286,7 @@
       gogs = 268;
       pdns-recursor = 269;
       kresd = 270;
+      rpc = 271;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -332,7 +333,7 @@
       #cups = 36; # unused
       #foldingathome = 37; # unused
       #sabnzd = 38; # unused
-      #kdm = 39; # unused
+      #kdm = 39; # unused, even before 17.03
       ghostone = 40;
       git = 41;
       fourstore = 42;
@@ -469,7 +470,7 @@
       #ripple-data-api = 186; #unused
       mediatomb = 187;
       #rdnssd = 188; # unused
-      ihaskell = 189;
+      # ihaskell = 189; # unused
       i2p = 190;
       lambdabot = 191;
       asterisk = 192;
@@ -541,6 +542,7 @@
       couchpotato = 267;
       gogs = 268;
       kresd = 270;
+      #rpc = 271; # unused
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix
index 7451888484f..b8824e6374b 100644
--- a/nixos/modules/misc/nixpkgs.nix
+++ b/nixos/modules/misc/nixpkgs.nix
@@ -45,9 +45,8 @@ let
 in
 
 {
-  options = {
-
-    nixpkgs.config = mkOption {
+  options.nixpkgs = {
+    config = mkOption {
       default = {};
       example = literalExample
         ''
@@ -61,7 +60,7 @@ in
       '';
     };
 
-    nixpkgs.overlays = mkOption {
+    overlays = mkOption {
       default = [];
       example = literalExample
         ''
@@ -85,7 +84,7 @@ in
       '';
     };
 
-    nixpkgs.system = mkOption {
+    system = mkOption {
       type = types.str;
       example = "i686-linux";
       description = ''
@@ -95,14 +94,9 @@ in
         multi-platform deployment, or when building virtual machines.
       '';
     };
-
   };
 
   config = {
-    _module.args.pkgs = import ../../.. {
-      system = config.nixpkgs.system;
-
-      inherit (config.nixpkgs) config;
-    };
+    _module.args.pkgs = import ../../.. config.nixpkgs;
   };
 }
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 768e9d7a858..9dbc009a6e4 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -141,6 +141,7 @@
   ./services/computing/torque/mom.nix
   ./services/computing/slurm/slurm.nix
   ./services/continuous-integration/buildbot/master.nix
+  ./services/continuous-integration/buildbot/worker.nix
   ./services/continuous-integration/buildkite-agent.nix
   ./services/continuous-integration/hydra/default.nix
   ./services/continuous-integration/gitlab-runner.nix
@@ -197,6 +198,7 @@
   ./services/hardware/bluetooth.nix
   ./services/hardware/brltty.nix
   ./services/hardware/freefall.nix
+  ./services/hardware/illum.nix
   ./services/hardware/irqbalance.nix
   ./services/hardware/nvidia-optimus.nix
   ./services/hardware/pcscd.nix
@@ -205,6 +207,7 @@
   ./services/hardware/tcsd.nix
   ./services/hardware/tlp.nix
   ./services/hardware/thinkfan.nix
+  ./services/hardware/trezord.nix
   ./services/hardware/udev.nix
   ./services/hardware/udisks2.nix
   ./services/hardware/upower.nix
@@ -256,12 +259,13 @@
   ./services/misc/felix.nix
   ./services/misc/folding-at-home.nix
   ./services/misc/gammu-smsd.nix
+  ./services/misc/geoip-updater.nix
   #./services/misc/gitit.nix
   ./services/misc/gitlab.nix
   ./services/misc/gitolite.nix
   ./services/misc/gogs.nix
   ./services/misc/gpsd.nix
-  ./services/misc/ihaskell.nix
+  #./services/misc/ihaskell.nix
   ./services/misc/leaps.nix
   ./services/misc/mantisbt.nix
   ./services/misc/mathics.nix
@@ -290,6 +294,7 @@
   ./services/misc/siproxd.nix
   ./services/misc/sonarr.nix
   ./services/misc/spice-vdagentd.nix
+  ./services/misc/ssm-agent.nix
   ./services/misc/sssd.nix
   ./services/misc/subsonic.nix
   ./services/misc/sundtek.nix
@@ -339,6 +344,7 @@
   ./services/monitoring/zabbix-server.nix
   ./services/network-filesystems/cachefilesd.nix
   ./services/network-filesystems/drbd.nix
+  ./services/network-filesystems/glusterfs.nix
   ./services/network-filesystems/ipfs.nix
   ./services/network-filesystems/netatalk.nix
   ./services/network-filesystems/nfsd.nix
@@ -442,6 +448,7 @@
   ./services/networking/radicale.nix
   ./services/networking/radvd.nix
   ./services/networking/rdnssd.nix
+  ./services/networking/redsocks.nix
   ./services/networking/rpcbind.nix
   ./services/networking/sabnzbd.nix
   ./services/networking/searx.nix
@@ -498,7 +505,8 @@
   ./services/security/frandom.nix
   ./services/security/haka.nix
   ./services/security/haveged.nix
-  ./services/security/hologram.nix
+  ./services/security/hologram-server.nix
+  ./services/security/hologram-agent.nix
   ./services/security/munge.nix
   ./services/security/oauth2_proxy.nix
   ./services/security/physlock.nix
@@ -553,7 +561,6 @@
   ./services/x11/display-managers/auto.nix
   ./services/x11/display-managers/default.nix
   ./services/x11/display-managers/gdm.nix
-  ./services/x11/display-managers/kdm.nix
   ./services/x11/display-managers/lightdm.nix
   ./services/x11/display-managers/sddm.nix
   ./services/x11/display-managers/slim.nix
@@ -639,6 +646,7 @@
   ./virtualisation/container-config.nix
   ./virtualisation/containers.nix
   ./virtualisation/docker.nix
+  ./virtualisation/ecs-agent.nix
   ./virtualisation/libvirtd.nix
   ./virtualisation/lxc.nix
   ./virtualisation/lxcfs.nix
diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix
index 99b45228ce4..6b4d8c737eb 100644
--- a/nixos/modules/profiles/all-hardware.nix
+++ b/nixos/modules/profiles/all-hardware.nix
@@ -42,6 +42,9 @@
       # Virtio (QEMU, KVM etc.) support.
       "virtio_net" "virtio_pci" "virtio_blk" "virtio_scsi" "virtio_balloon" "virtio_console"
 
+      # Hyper-V support.
+      "hv_storvsc"
+
       # Keyboards
       "usbhid" "hid_apple" "hid_logitech_dj" "hid_lenovo_tpkbd" "hid_roccat"
     ];
diff --git a/nixos/modules/profiles/graphical.nix b/nixos/modules/profiles/graphical.nix
index 8ee1628f876..73dd2d4bc9f 100644
--- a/nixos/modules/profiles/graphical.nix
+++ b/nixos/modules/profiles/graphical.nix
@@ -6,8 +6,8 @@
 {
   services.xserver = {
     enable = true;
-    displayManager.kdm.enable = true;
-    desktopManager.kde4.enable = true;
+    displayManager.sddm.enable = true;
+    desktopManager.kde5.enable = true;
     synaptics.enable = true; # for touchpad support on many laptops
   };
 
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 84b30180ac7..e419474b3e3 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -171,6 +171,10 @@ with lib;
     (mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ])
     (mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths" )
 
+    # nfs
+    (mkRenamedOptionModule [ "services" "nfs" "lockdPort" ] [ "services" "nfs" "server" "lockdPort" ])
+    (mkRenamedOptionModule [ "services" "nfs" "statdPort" ] [ "services" "nfs" "server" "statdPort" ])
+
     # Options that are obsolete and have no replacement.
     (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "")
     (mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
diff --git a/nixos/modules/security/grsecurity.xml b/nixos/modules/security/grsecurity.xml
index a7bcf4924f0..ef0aab4a3f1 100644
--- a/nixos/modules/security/grsecurity.xml
+++ b/nixos/modules/security/grsecurity.xml
@@ -7,21 +7,20 @@
   <title>Grsecurity/PaX</title>
 
   <para>
-    Grsecurity/PaX is a set of patches against the Linux kernel that make it
-    harder to exploit bugs.  The patchset includes protections such as
-    enforcement of non-executable memory, address space layout randomization,
-    and chroot jail hardening.  These and other
+    Grsecurity/PaX is a set of patches against the Linux kernel that
+    implements an extensive suite of
     <link xlink:href="https://grsecurity.net/features.php">features</link>
-    render entire classes of exploits inert without additional efforts on the
-    part of the adversary.
+    designed to increase the difficulty of exploiting kernel and
+    application bugs.
   </para>
 
   <para>
     The NixOS grsecurity/PaX module is designed with casual users in mind and is
-    intended to be compatible with normal desktop usage, without unnecessarily
-    compromising security.  The following sections describe the configuration
-    and administration of a grsecurity/PaX enabled NixOS system.  For
-    more comprehensive coverage, please refer to the
+    intended to be compatible with normal desktop usage, without
+    <emphasis>unnecessarily</emphasis> compromising security.  The
+    following sections describe the configuration and administration of
+    a grsecurity/PaX enabled NixOS system.  For more comprehensive
+    coverage, please refer to the
     <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity">grsecurity wikibook</link>
     and the
     <link xlink:href="https://wiki.archlinux.org/index.php/Grsecurity">Arch
@@ -35,7 +34,7 @@
     and each configuration requires quite a bit of testing to ensure that the
     resulting packages work as advertised.  Defining additional package sets
     would likely result in a large number of functionally broken packages, to
-    nobody's benefit.</para></note>.
+    nobody's benefit.</para></note>
   </para>
 
   <sect1 xml:id="sec-grsec-enable"><title>Enabling grsecurity/PaX</title>
@@ -126,10 +125,10 @@
     The NixOS kernel is built using upstream's recommended settings for a
     desktop deployment that generally favours security over performance.  This
     section details deviations from upstream's recommendations that may
-    compromise operational security.
+    compromise security.
 
     <warning><para>There may be additional problems not covered here!</para>
-    </warning>.
+    </warning>
   </para>
 
   <itemizedlist>
@@ -159,8 +158,8 @@
     <listitem><para>
       The NixOS module conditionally weakens <command>chroot</command>
       restrictions to accommodate NixOS lightweight containers and sandboxed Nix
-      builds.  This is problematic if the deployment also runs a privileged
-      network facing process that <emphasis>relies</emphasis> on
+      builds.  This can be problematic if the deployment also runs privileged
+      network facing processes that <emphasis>rely</emphasis> on
       <command>chroot</command> for isolation.
     </para></listitem>
 
@@ -221,15 +220,18 @@
   </para>
 
   <para>
-    The wikibook provides an exhaustive listing of
+    The grsecurity/PaX wikibook provides an exhaustive listing of
     <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options">kernel configuration options</link>.
   </para>
 
   <para>
     The NixOS module makes several assumptions about the kernel and so
     may be incompatible with your customised kernel. Currently, the only way
-    to work around incompatibilities is to eschew the NixOS module.
+    to work around these incompatibilities is to eschew the NixOS
+    module.
+  </para>
 
+  <para>
     If not using the NixOS module, a custom grsecurity package set can
     be specified inline instead, as in
     <programlisting>
@@ -290,7 +292,7 @@
 
     <listitem><para>User initiated autoloading of modules (e.g., when
     using fuse or loop devices) is disallowed; either load requisite modules
-    as root or add them to<option>boot.kernelModules</option>.</para></listitem>
+    as root or add them to <option>boot.kernelModules</option>.</para></listitem>
 
     <listitem><para>Virtualization: KVM is the preferred virtualization
     solution. Xen, Virtualbox, and VMWare are
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 3cc5db2fb9b..e37c55aa1ac 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -253,6 +253,8 @@ let
               "auth sufficient ${pkgs.pam_u2f}/lib/security/pam_u2f.so"}
           ${optionalString cfg.usbAuth
               "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"}
+          ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth
+              "auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"}
         '' +
           # Modules in this block require having the password set in PAM_AUTHTOK.
           # pam_unix is marked as 'sufficient' on NixOS which means nothing will run
@@ -271,8 +273,6 @@ let
               "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
           ${optionalString cfg.otpwAuth
               "auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"}
-          ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth
-              "auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"}
           ${optionalString use_ldap
               "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"}
           ${optionalString config.services.sssd.enable
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index 029b11ad98b..a82802c3266 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -775,7 +775,7 @@ in {
             --bind-address=${cfg.proxy.address} \
             ${optionalString cfg.verbose "--v=6"} \
             ${optionalString cfg.verbose "--log-flush-frequency=1s"} \
-            ${cfg.controllerManager.extraOpts}
+            ${cfg.proxy.extraOpts}
           '';
           WorkingDirectory = cfg.dataDir;
         };
diff --git a/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixos/modules/services/continuous-integration/buildbot/master.nix
index a40be4f546e..512e09eb804 100644
--- a/nixos/modules/services/continuous-integration/buildbot/master.nix
+++ b/nixos/modules/services/continuous-integration/buildbot/master.nix
@@ -7,7 +7,7 @@ with lib;
 let
   cfg = config.services.buildbot-master;
   escapeStr = s: escape ["'"] s;
-  masterCfg = pkgs.writeText "master.cfg" ''
+  masterCfg = if cfg.masterCfg == null then pkgs.writeText "master.cfg" ''
     from buildbot.plugins import *
     factory = util.BuildFactory()
     c = BuildmasterConfig = dict(
@@ -27,9 +27,8 @@ let
       factory.addStep(step)
 
     ${cfg.extraConfig}
-  '';
-
-  configFile = if cfg.masterCfg == null then masterCfg else cfg.masterCfg;
+  ''
+  else pkgs.writeText "master.cfg" cfg.masterCfg;
 
 in {
   options = {
@@ -67,15 +66,13 @@ in {
       };
 
       masterCfg = mkOption {
-        type = with types; nullOr path;
+        type = types.str;
         description = ''
-          Optionally pass path to raw master.cfg file.
+          Optionally pass raw master.cfg file as string.
           Other options in this configuration will be ignored.
         '';
         default = null;
-        example = literalExample ''
-          pkgs.writeText "master.cfg" "BuildmasterConfig = c = {}"
-        '';
+        example = "BuildmasterConfig = c = {}";
       };
 
       schedulers = mkOption {
@@ -99,9 +96,9 @@ in {
         type = types.listOf types.str;
         description = "List of Workers.";
         default = [
-          "worker.Worker('default-worker', 'password')"
+          "worker.Worker('example-worker', 'pass')"
         ];
-        example = [ "worker.LocalWorker('default-worker')" ];
+        example = [ "worker.LocalWorker('example-worker')" ];
       };
 
       status = mkOption {
@@ -209,7 +206,7 @@ in {
 
     users.extraUsers = optional (cfg.user == "buildbot") {
       name = "buildbot";
-      description = "buildbot user";
+      description = "Buildbot User.";
       isNormalUser = true;
       createHome = true;
       home = cfg.home;
@@ -219,7 +216,7 @@ in {
     };
 
     systemd.services.buildbot-master = {
-      description = "Buildbot Continuous Integration Server";
+      description = "Buildbot Continuous Integration Server.";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       path = cfg.packages;
@@ -233,9 +230,8 @@ in {
       };
 
       preStart = ''
-        mkdir -vp ${cfg.buildbotDir}
-        chown -c ${cfg.user}:${cfg.group} ${cfg.buildbotDir}
-        ln -sf ${configFile} ${cfg.buildbotDir}/master.cfg
+        ${pkgs.coreutils}/bin/mkdir -vp ${cfg.buildbotDir}
+        ${pkgs.coreutils}/bin/ln -sfv ${masterCfg} ${cfg.buildbotDir}/master.cfg
         ${cfg.package}/bin/buildbot create-master ${cfg.buildbotDir}
       '';
 
@@ -247,4 +243,6 @@ in {
     };
   };
 
+  meta.maintainers = with lib.maintainers; [ nand0p Mic92 ];
+
 }
diff --git a/nixos/modules/services/continuous-integration/buildbot/worker.nix b/nixos/modules/services/continuous-integration/buildbot/worker.nix
new file mode 100644
index 00000000000..430fd4e53f1
--- /dev/null
+++ b/nixos/modules/services/continuous-integration/buildbot/worker.nix
@@ -0,0 +1,128 @@
+# NixOS module for Buildbot Worker.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.buildbot-worker;
+
+in {
+  options = {
+    services.buildbot-worker = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the Buildbot Worker.";
+      };
+
+      user = mkOption {
+        default = "bbworker";
+        type = types.str;
+        description = "User the buildbot Worker should execute under.";
+      };
+
+      group = mkOption {
+        default = "bbworker";
+        type = types.str;
+        description = "Primary group of buildbot Worker user.";
+      };
+
+      extraGroups = mkOption {
+        type = types.listOf types.str;
+        default = [ "nixbld" ];
+        description = "List of extra groups that the Buildbot Worker user should be a part of.";
+      };
+
+      home = mkOption {
+        default = "/home/bbworker";
+        type = types.path;
+        description = "Buildbot home directory.";
+      };
+
+      buildbotDir = mkOption {
+        default = "${cfg.home}/worker";
+        type = types.path;
+        description = "Specifies the Buildbot directory.";
+      };
+
+      workerUser = mkOption {
+        default = "example-worker";
+        type = types.str;
+        description = "Specifies the Buildbot Worker user.";
+      };
+
+      workerPass = mkOption {
+        default = "pass";
+        type = types.str;
+        description = "Specifies the Buildbot Worker password.";
+      };
+
+      masterUrl = mkOption {
+        default = "localhost:9989";
+        type = types.str;
+        description = "Specifies the Buildbot Worker connection string.";
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.buildbot-worker;
+        description = "Package to use for buildbot worker.";
+        example = pkgs.buildbot-worker;
+      };
+
+      packages = mkOption {
+        default = [ ];
+        example = [ pkgs.git ];
+        type = types.listOf types.package;
+        description = "Packages to add to PATH for the buildbot process.";
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraGroups = optional (cfg.group == "bbworker") {
+      name = "bbworker";
+    };
+
+    users.extraUsers = optional (cfg.user == "bbworker") {
+      name = "bbworker";
+      description = "Buildbot Worker User.";
+      isNormalUser = true;
+      createHome = true;
+      home = cfg.home;
+      group = cfg.group;
+      extraGroups = cfg.extraGroups;
+      useDefaultShell = true;
+    };
+
+    systemd.services.buildbot-worker = {
+      description = "Buildbot Worker.";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "buildbot-master.service" ];
+      path = cfg.packages;
+
+      preStart = ''
+        # NOTE: ensure master has time to start in case running on localhost
+        ${pkgs.coreutils}/bin/sleep 4
+        ${pkgs.coreutils}/bin/mkdir -vp ${cfg.buildbotDir}
+        ${cfg.package}/bin/buildbot-worker create-worker ${cfg.buildbotDir} ${cfg.masterUrl} ${cfg.workerUser} ${cfg.workerPass}
+      '';
+
+      serviceConfig = {
+        Type = "forking";
+        User = cfg.user;
+        Group = cfg.group;
+        WorkingDirectory = cfg.home;
+        ExecStart = "${cfg.package}/bin/buildbot-worker start ${cfg.buildbotDir}";
+      };
+
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ nand0p ];
+
+}
diff --git a/nixos/modules/services/editors/emacs.xml b/nixos/modules/services/editors/emacs.xml
index e03f6046de8..89f09ed0844 100644
--- a/nixos/modules/services/editors/emacs.xml
+++ b/nixos/modules/services/editors/emacs.xml
@@ -316,10 +316,10 @@ https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides
       <para>
         If you are not on NixOS or want to install this particular
         Emacs only for yourself, you can do so by adding it to your
-        <filename>~/.nixpkgs/config.nix</filename>
+        <filename>~/.config/nixpkgs/config.nix</filename>
         (see <link xlink:href="http://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides">Nixpkgs manual</link>):
         <example>
-          <title>Custom Emacs in <filename>~/.nixpkgs/system.nix</filename></title>
+          <title>Custom Emacs in <filename>~/.config/nixpkgs/config.nix</filename></title>
           <programlisting><![CDATA[
 {
   packageOverrides = super: let self = super.pkgs; in {
diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix
index 2c271b32817..de0d4803211 100644
--- a/nixos/modules/services/hardware/bluetooth.nix
+++ b/nixos/modules/services/hardware/bluetooth.nix
@@ -2,41 +2,7 @@
 
 with lib;
 let
-    bluez-bluetooth = if config.services.xserver.desktopManager.kde4.enable then pkgs.bluez else pkgs.bluez5;
-
-    configBluez = {
-        description = "Bluetooth Service";
-        serviceConfig = {
-          Type = "dbus";
-          BusName = "org.bluez";
-          ExecStart = "${getBin bluez-bluetooth}/bin/bluetoothd -n";
-        };
-        wantedBy = [ "bluetooth.target" ];
-    };
-
-    configBluez5 =  {
-        description = "Bluetooth Service";
-        serviceConfig = {
-          Type = "dbus";
-          BusName = "org.bluez";
-          ExecStart = "${getBin bluez-bluetooth}/bin/bluetoothd -n";
-          NotifyAccess="main";
-          CapabilityBoundingSet="CAP_NET_ADMIN CAP_NET_BIND_SERVICE";
-          LimitNPROC=1;
-        };
-        wantedBy = [ "bluetooth.target" ];
-    };
-
-    obexConfig = {
-        description = "Bluetooth OBEX service";
-        serviceConfig = {
-          Type = "dbus";
-          BusName = "org.bluez.obex";
-          ExecStart = "${getBin bluez-bluetooth}/bin/obexd";
-        };
-    };
-
-    bluezConfig = if config.services.xserver.desktopManager.kde4.enable then configBluez else configBluez5;
+  bluez-bluetooth = pkgs.bluez;
 in
 
 {
@@ -54,14 +20,25 @@ in
   };
 
   ###### implementation
-  
+
   config = mkIf config.hardware.bluetooth.enable {
 
     environment.systemPackages = [ bluez-bluetooth pkgs.openobex pkgs.obexftp ];
+
     services.udev.packages = [ bluez-bluetooth ];
+
     services.dbus.packages = [ bluez-bluetooth ];
-    systemd.services."dbus-org.bluez" = bluezConfig;
-    systemd.services."dbus-org.bluez.obex" = obexConfig;
+
+    systemd.packages = [ bluez-bluetooth ];
+
+    systemd.services.bluetooth = {
+      wantedBy = [ "bluetooth.target" ];
+      aliases = [ "dbus-org.bluez.service" ];
+    };
+
+    systemd.user.services.obex = {
+      aliases = [ "dbus-org.bluez.obex.service" ];
+    };
 
   };
 
diff --git a/nixos/modules/services/hardware/illum.nix b/nixos/modules/services/hardware/illum.nix
new file mode 100644
index 00000000000..ff73c99a653
--- /dev/null
+++ b/nixos/modules/services/hardware/illum.nix
@@ -0,0 +1,35 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.illum;
+in {
+
+  options = {
+
+    services.illum = {
+
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Enable illum, a daemon for controlling screen brightness with brightness buttons.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.illum = {
+      description = "Backlight Adjustment Service";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig.ExecStart = "${pkgs.illum}/bin/illum-d";
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/hardware/sane.nix b/nixos/modules/services/hardware/sane.nix
index 8ddb9ef9c53..d651ccaa577 100644
--- a/nixos/modules/services/hardware/sane.nix
+++ b/nixos/modules/services/hardware/sane.nix
@@ -51,7 +51,7 @@ in
         Enable support for SANE scanners.
 
         <note><para>
-          Users in the "scanner" group will gain access to the scanner.
+          Users in the "scanner" group will gain access to the scanner, or the "lp" group if it's also a printer.
         </para></note>
       '';
     };
diff --git a/nixos/modules/services/hardware/trezord.nix b/nixos/modules/services/hardware/trezord.nix
new file mode 100644
index 00000000000..38d0a3a1d75
--- /dev/null
+++ b/nixos/modules/services/hardware/trezord.nix
@@ -0,0 +1,54 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.trezord;
+in {
+  
+  ### interface
+
+  options = {
+    services.trezord = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable Trezor bridge daemon, for use with Trezor hardware bitcoin wallets.
+        '';
+      };
+    };
+  };
+  
+  ### implementation
+
+  config = mkIf cfg.enable {
+    services.udev.packages = lib.singleton (pkgs.writeTextFile {
+      name = "trezord-udev-rules";
+      destination = "/etc/udev/rules.d/51-trezor.rules";
+      text = ''
+        SUBSYSTEM=="usb", ATTR{idVendor}=="534c", ATTR{idProduct}=="0001", MODE="0666", GROUP="dialout", SYMLINK+="trezor%n"
+        KERNEL=="hidraw*", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001",  MODE="0666", GROUP="dialout"
+      '';
+    });
+
+    systemd.services.trezord = {
+      description = "TREZOR Bridge";
+      after = [ "systemd-udev-settle.service" "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      path = [];
+      serviceConfig = {
+        Type = "simple";
+        ExecStart = "${pkgs.trezord}/bin/trezord -f";
+        User = "trezord";
+      };
+    };
+
+    users.users.trezord = {
+      group = "trezord";
+      description = "Trezor bridge daemon user";
+    };
+
+    users.groups.trezord = {};
+  };
+}
+
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index cdde4144622..caaa87b94d6 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -79,8 +79,6 @@ let
       relay_domains = ${concatStringsSep ", " cfg.relayDomains}
     ''
     + ''
-      local_recipient_maps =
-
       relayhost = ${if cfg.lookupMX || cfg.relayHost == "" then
           cfg.relayHost
         else
diff --git a/nixos/modules/services/misc/geoip-updater.nix b/nixos/modules/services/misc/geoip-updater.nix
new file mode 100644
index 00000000000..021ee02782d
--- /dev/null
+++ b/nixos/modules/services/misc/geoip-updater.nix
@@ -0,0 +1,300 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.geoip-updater;
+
+  dbBaseUrl = "https://geolite.maxmind.com/download/geoip/database";
+
+  randomizedTimerDelaySec = "3600";
+
+  # Use writeScriptBin instead of writeScript, so that argv[0] (logged to the
+  # journal) doesn't include the long nix store path hash. (Prefixing the
+  # ExecStart= command with '@' doesn't work because we start a shell (new
+  # process) that creates a new argv[0].)
+  geoip-updater = pkgs.writeScriptBin "geoip-updater" ''
+    #!${pkgs.stdenv.shell}
+    skipExisting=0
+    debug()
+    {
+        echo "<7>$@"
+    }
+    info()
+    {
+        echo "<6>$@"
+    }
+    error()
+    {
+        echo "<3>$@"
+    }
+    die()
+    {
+        error "$@"
+        exit 1
+    }
+    waitNetworkOnline()
+    {
+        ret=1
+        for i in $(seq 6); do
+            curl_out=$("${pkgs.curl.bin}/bin/curl" \
+                --silent --fail --show-error --max-time 60 "${dbBaseUrl}" 2>&1)
+            if [ $? -eq 0 ]; then
+                debug "Server is reachable (try $i)"
+                ret=0
+                break
+            else
+                debug "Server is unreachable (try $i): $curl_out"
+                sleep 10
+            fi
+        done
+        return $ret
+    }
+    dbFnameTmp()
+    {
+        dburl=$1
+        echo "${cfg.databaseDir}/.$(basename "$dburl")"
+    }
+    dbFnameTmpDecompressed()
+    {
+        dburl=$1
+        echo "${cfg.databaseDir}/.$(basename "$dburl")" | sed 's/\.\(gz\|xz\)$//'
+    }
+    dbFname()
+    {
+        dburl=$1
+        echo "${cfg.databaseDir}/$(basename "$dburl")" | sed 's/\.\(gz\|xz\)$//'
+    }
+    downloadDb()
+    {
+        dburl=$1
+        curl_out=$("${pkgs.curl.bin}/bin/curl" \
+            --silent --fail --show-error --max-time 900 -L -o "$(dbFnameTmp "$dburl")" "$dburl" 2>&1)
+        if [ $? -ne 0 ]; then
+            error "Failed to download $dburl: $curl_out"
+            return 1
+        fi
+    }
+    decompressDb()
+    {
+        fn=$(dbFnameTmp "$1")
+        ret=0
+        case "$fn" in
+            *.gz)
+                cmd_out=$("${pkgs.gzip}/bin/gzip" --decompress --force "$fn" 2>&1)
+                ;;
+            *.xz)
+                cmd_out=$("${pkgs.xz.bin}/bin/xz" --decompress --force "$fn" 2>&1)
+                ;;
+            *)
+                cmd_out=$(echo "File \"$fn\" is neither a .gz nor .xz file")
+                false
+                ;;
+        esac
+        if [ $? -ne 0 ]; then
+            error "$cmd_out"
+            ret=1
+        fi
+    }
+    atomicRename()
+    {
+        dburl=$1
+        mv "$(dbFnameTmpDecompressed "$dburl")" "$(dbFname "$dburl")"
+    }
+    removeIfNotInConfig()
+    {
+        # Arg 1 is the full path of an installed DB.
+        # If the corresponding database is not specified in the NixOS config we
+        # remove it.
+        db=$1
+        for cdb in ${lib.concatStringsSep " " cfg.databases}; do
+            confDb=$(echo "$cdb" | sed 's/\.\(gz\|xz\)$//')
+            if [ "$(basename "$db")" = "$(basename "$confDb")" ]; then
+                return 0
+            fi
+        done
+        rm "$db"
+        if [ $? -eq 0 ]; then
+            debug "Removed $(basename "$db") (not listed in services.geoip-updater.databases)"
+        else
+            error "Failed to remove $db"
+        fi
+    }
+    removeUnspecifiedDbs()
+    {
+        for f in "${cfg.databaseDir}/"*; do
+            test -f "$f" || continue
+            case "$f" in
+                *.dat|*.mmdb|*.csv)
+                    removeIfNotInConfig "$f"
+                    ;;
+                *)
+                    debug "Not removing \"$f\" (unknown file extension)"
+                    ;;
+            esac
+        done
+    }
+    downloadAndInstall()
+    {
+        dburl=$1
+        if [ "$skipExisting" -eq 1 -a -f "$(dbFname "$dburl")" ]; then
+            debug "Skipping existing file: $(dbFname "$dburl")"
+            return 0
+        fi
+        downloadDb "$dburl" || return 1
+        decompressDb "$dburl" || return 1
+        atomicRename "$dburl" || return 1
+        info "Updated $(basename "$(dbFname "$dburl")")"
+    }
+    for arg in "$@"; do
+        case "$arg" in
+            --skip-existing)
+                skipExisting=1
+                info "Option --skip-existing is set: not updating existing databases"
+                ;;
+            *)
+                error "Unknown argument: $arg";;
+        esac
+    done
+    waitNetworkOnline || die "Network is down (${dbBaseUrl} is unreachable)"
+    test -d "${cfg.databaseDir}" || die "Database directory (${cfg.databaseDir}) doesn't exist"
+    debug "Starting update of GeoIP databases in ${cfg.databaseDir}"
+    all_ret=0
+    for db in ${lib.concatStringsSep " \\\n        " cfg.databases}; do
+        downloadAndInstall "${dbBaseUrl}/$db" || all_ret=1
+    done
+    removeUnspecifiedDbs || all_ret=1
+    if [ $all_ret -eq 0 ]; then
+        info "Completed GeoIP database update in ${cfg.databaseDir}"
+    else
+        error "Completed GeoIP database update in ${cfg.databaseDir}, with error(s)"
+    fi
+    # Hack to work around systemd journal race:
+    # https://github.com/systemd/systemd/issues/2913
+    sleep 2
+    exit $all_ret
+  '';
+
+in
+
+{
+  options = {
+    services.geoip-updater = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to enable periodic downloading of GeoIP databases from
+          maxmind.com. You might want to enable this if you, for instance, use
+          ntopng or Wireshark.
+        '';
+      };
+
+      interval = mkOption {
+        type = types.str;
+        default = "weekly";
+        description = ''
+          Update the GeoIP databases at this time / interval.
+          The format is described in
+          <citerefentry><refentrytitle>systemd.time</refentrytitle>
+          <manvolnum>7</manvolnum></citerefentry>.
+          To prevent load spikes on maxmind.com, the timer interval is
+          randomized by an additional delay of ${randomizedTimerDelaySec}
+          seconds. Setting a shorter interval than this is not recommended.
+        '';
+      };
+
+      databaseDir = mkOption {
+        type = types.path;
+        default = "/var/lib/geoip-databases";
+        description = ''
+          Directory that will contain GeoIP databases.
+        '';
+      };
+
+      databases = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "GeoLiteCountry/GeoIP.dat.gz"
+          "GeoIPv6.dat.gz"
+          "GeoLiteCity.dat.xz"
+          "GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz"
+          "asnum/GeoIPASNum.dat.gz"
+          "asnum/GeoIPASNumv6.dat.gz"
+          "GeoLite2-Country.mmdb.gz"
+          "GeoLite2-City.mmdb.gz"
+        ];
+        description = ''
+          Which GeoIP databases to update. The full URL is ${dbBaseUrl}/ +
+          <literal>the_database</literal>.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    assertions = [
+      { assertion = (builtins.filter
+          (x: builtins.match ".*\.(gz|xz)$" x == null) cfg.databases) == [];
+        message = ''
+          services.geoip-updater.databases supports only .gz and .xz databases.
+
+          Current value:
+          ${toString cfg.databases}
+
+          Offending element(s):
+          ${toString (builtins.filter (x: builtins.match ".*\.(gz|xz)$" x == null) cfg.databases)};
+        '';
+      }
+    ];
+
+    systemd.timers.geoip-updater =
+      { description = "GeoIP Updater Timer";
+        partOf = [ "geoip-updater.service" ];
+        wantedBy = [ "timers.target" ];
+        timerConfig.OnCalendar = cfg.interval;
+        timerConfig.Persistent = "true";
+        timerConfig.RandomizedDelaySec = randomizedTimerDelaySec;
+      };
+
+    systemd.services.geoip-updater = {
+      description = "GeoIP Updater";
+      after = [ "network-online.target" "nss-lookup.target" ];
+      wants = [ "network-online.target" ];
+      preStart = ''
+        mkdir -p "${cfg.databaseDir}"
+        chmod 755 "${cfg.databaseDir}"
+        chown nobody:root "${cfg.databaseDir}"
+      '';
+      serviceConfig = {
+        ExecStart = "${geoip-updater}/bin/geoip-updater";
+        User = "nobody";
+        PermissionsStartOnly = true;
+      };
+    };
+
+    systemd.services.geoip-updater-setup = {
+      description = "GeoIP Updater Setup";
+      after = [ "network-online.target" "nss-lookup.target" ];
+      wants = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      conflicts = [ "geoip-updater.service" ];
+      preStart = ''
+        mkdir -p "${cfg.databaseDir}"
+        chmod 755 "${cfg.databaseDir}"
+        chown nobody:root "${cfg.databaseDir}"
+      '';
+      serviceConfig = {
+        ExecStart = "${geoip-updater}/bin/geoip-updater --skip-existing";
+        User = "nobody";
+        PermissionsStartOnly = true;
+        # So it won't be (needlessly) restarted:
+        RemainAfterExit = true;
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index 1fc3a5cc869..36db4fb9660 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -528,8 +528,8 @@ in {
 
         if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
           if ! test -e "${cfg.statePath}/db-created"; then
-            psql postgres -c "CREATE ROLE gitlab WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'"
-            ${config.services.postgresql.package}/bin/createdb --owner gitlab gitlab || true
+            psql postgres -c "CREATE ROLE ${cfg.databaseUsername} WITH LOGIN NOCREATEDB NOCREATEROLE NOCREATEUSER ENCRYPTED PASSWORD '${cfg.databasePassword}'"
+            ${config.services.postgresql.package}/bin/createdb --owner ${cfg.databaseUsername} ${cfg.databaseName} || true
             touch "${cfg.statePath}/db-created"
           fi
         fi
diff --git a/nixos/modules/services/misc/gogs.nix b/nixos/modules/services/misc/gogs.nix
index 09e5c4fe1ff..ca8fc06e483 100644
--- a/nixos/modules/services/misc/gogs.nix
+++ b/nixos/modules/services/misc/gogs.nix
@@ -208,6 +208,7 @@ in
         group = "gogs";
         home = cfg.stateDir;
         createHome = true;
+        shell = pkgs.bash;
       };
       extraGroups.gogs.gid = config.ids.gids.gogs;
     };
diff --git a/nixos/modules/services/misc/ihaskell.nix b/nixos/modules/services/misc/ihaskell.nix
index d0e9b839e75..df7b9be0db5 100644
--- a/nixos/modules/services/misc/ihaskell.nix
+++ b/nixos/modules/services/misc/ihaskell.nix
@@ -20,18 +20,6 @@ in
         description = "Autostart an IHaskell notebook service.";
       };
 
-      haskellPackages = mkOption {
-        default = pkgs.haskellPackages;
-        defaultText = "pkgs.haskellPackages";
-        example = literalExample "pkgs.haskell.packages.ghc784";
-        description = ''
-          haskellPackages used to build IHaskell and other packages.
-          This can be used to change the GHC version used to build
-          IHaskell and the packages listed in
-          <varname>extraPackages</varname>.
-        '';
-      };
-
       extraPackages = mkOption {
         default = self: [];
         example = literalExample ''
diff --git a/nixos/modules/services/misc/ssm-agent.nix b/nixos/modules/services/misc/ssm-agent.nix
new file mode 100644
index 00000000000..b04959a9686
--- /dev/null
+++ b/nixos/modules/services/misc/ssm-agent.nix
@@ -0,0 +1,45 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+  cfg = config.services.ssm-agent;
+
+  # The SSM agent doesn't pay attention to our /etc/os-release yet, and the lsb-release tool
+  # in nixpkgs doesn't seem to work properly on NixOS, so let's just fake the two fields SSM
+  # looks for. See https://github.com/aws/amazon-ssm-agent/issues/38 for upstream fix.
+  fake-lsb-release = pkgs.writeScriptBin "lsb_release" ''
+    #!${pkgs.stdenv.shell}
+
+    case "$1" in
+      -i) echo "nixos";;
+      -r) echo "${config.system.nixosVersion}";;
+    esac
+  '';
+in {
+  options.services.ssm-agent = {
+    enable = mkEnableOption "AWS SSM agent";
+
+    package = mkOption {
+      type = types.path;
+      description = "The SSM agent package to use";
+      default = pkgs.ssm-agent;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.ssm-agent = {
+      inherit (cfg.package.meta) description;
+      after    = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      path = [ fake-lsb-release ];
+      serviceConfig = {
+        ExecStart = "${cfg.package.bin}/bin/agent";
+        KillMode = "process";
+        Restart = "on-failure";
+        RestartSec = "15min";
+      };
+    };
+  };
+}
+
diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix
index ca82a733f6f..d28c5dc7af8 100644
--- a/nixos/modules/services/misc/taskserver/default.nix
+++ b/nixos/modules/services/misc/taskserver/default.nix
@@ -125,10 +125,10 @@ let
       server.key = ${cfg.dataDir}/keys/server.key
       server.crl = ${cfg.dataDir}/keys/server.crl
     '' else ''
-      ca.cert = ${cfg.pki.ca.cert}
-      server.cert = ${cfg.pki.server.cert}
-      server.key = ${cfg.pki.server.key}
-      server.crl = ${cfg.pki.server.crl}
+      ca.cert = ${cfg.pki.manual.ca.cert}
+      server.cert = ${cfg.pki.manual.server.cert}
+      server.key = ${cfg.pki.manual.server.key}
+      server.crl = ${cfg.pki.manual.server.crl}
     ''}
   '' + cfg.extraConfig);
 
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index b9e4015c238..97806d5d83e 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ options, config, lib, pkgs, ... }:
 
 with lib;
 
@@ -232,9 +232,10 @@ in {
   };
 
   config = mkIf cfg.enable {
-    warnings = [
-      "Grafana passwords will be stored as plaintext in the Nix store!"
-    ];
+    warnings = optional (
+      cfg.database.password != options.services.grafana.database.password.default ||
+      cfg.security.adminPassword != options.services.grafana.security.adminPassword.default
+    ) "Grafana passwords will be stored as plaintext in the Nix store!";
 
     environment.systemPackages = [ cfg.package ];
 
diff --git a/nixos/modules/services/network-filesystems/glusterfs.nix b/nixos/modules/services/network-filesystems/glusterfs.nix
new file mode 100644
index 00000000000..a2f2c033951
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/glusterfs.nix
@@ -0,0 +1,84 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  inherit (pkgs) glusterfs;
+
+  cfg = config.services.glusterfs;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.glusterfs = {
+
+      enable = mkEnableOption "GlusterFS Daemon";
+
+      logLevel = mkOption {
+        type = types.enum ["DEBUG" "INFO" "WARNING" "ERROR" "CRITICAL" "TRACE" "NONE"];
+        description = "Log level used by the GlusterFS daemon";
+        default = "INFO";
+      };
+
+      extraFlags = mkOption {
+        type = types.listOf types.str;
+        description = "Extra flags passed to the GlusterFS daemon";
+        default = [];
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.glusterfs ];
+
+    services.rpcbind.enable = true;
+
+    systemd.services.glusterd = {
+
+      description = "GlusterFS, a clustered file-system server";
+
+      wantedBy = [ "multi-user.target" ];
+
+      requires = [ "rpcbind.service" ];
+      after = [ "rpcbind.service" "network.target" "local-fs.target" ];
+      before = [ "network-online.target" ];
+
+      preStart = ''
+        install -m 0755 -d /var/log/glusterfs
+      '';
+
+      serviceConfig = {
+        Type="forking";
+        PIDFile="/run/glusterd.pid";
+        LimitNOFILE=65536;
+        ExecStart="${glusterfs}/sbin/glusterd -p /run/glusterd.pid --log-level=${cfg.logLevel} ${toString cfg.extraFlags}";
+        KillMode="process";
+      };
+    };
+
+    systemd.services.glustereventsd = {
+
+      description = "Gluster Events Notifier";
+
+      wantedBy = [ "multi-user.target" ];
+
+      after = [ "syslog.target" "network.target" ];
+
+      serviceConfig = {
+        Type="simple";
+        Environment="PYTHONPATH=${glusterfs}/usr/lib/python2.7/site-packages";
+        PIDFile="/run/glustereventsd.pid";
+        ExecStart="${glusterfs}/sbin/glustereventsd --pid-file /run/glustereventsd.pid";
+        ExecReload="/bin/kill -SIGUSR2 $MAINPID";
+        KillMode="control-group";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix
index d43147a16f3..e6e04248854 100644
--- a/nixos/modules/services/network-filesystems/ipfs.nix
+++ b/nixos/modules/services/network-filesystems/ipfs.nix
@@ -104,31 +104,73 @@ in
       };
     };
 
-    systemd.services.ipfs = {
-      description = "IPFS Daemon";
+    systemd.services.ipfs-init = {
+      description = "IPFS Initializer";
+
+      after = [ "local-fs.target" ];
+      before = [ "ipfs.service" "ipfs-offline.service" ];
 
-      wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" "local-fs.target" ];
       path  = [ pkgs.ipfs pkgs.su pkgs.bash ];
 
       preStart = ''
         install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.dataDir}
+      '';
+
+      script =  ''
         if [[ ! -d ${cfg.dataDir}/.ipfs ]]; then
           cd ${cfg.dataDir}
-          ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c \
-             "${ipfs}/bin/ipfs init ${if cfg.emptyRepo then "-e" else ""}"
+          ${ipfs}/bin/ipfs init ${optionalString cfg.emptyRepo "-e"}
         fi
-        ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c \
-           "${ipfs}/bin/ipfs --local config Addresses.API ${cfg.apiAddress} && \
-            ${ipfs}/bin/ipfs --local config Addresses.Gateway ${cfg.gatewayAddress}"
+        ${ipfs}/bin/ipfs --local config Addresses.API ${cfg.apiAddress}
+        ${ipfs}/bin/ipfs --local config Addresses.Gateway ${cfg.gatewayAddress}
       '';
 
       serviceConfig = {
-        ExecStart = "${ipfs}/bin/ipfs daemon ${ipfsFlags}";
         User = cfg.user;
         Group = cfg.group;
+        Type = "oneshot";
+        RemainAfterExit = true;
         PermissionsStartOnly = true;
       };
     };
+
+    systemd.services.ipfs = {
+      description = "IPFS Daemon";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "local-fs.target" "ipfs-init.service" ];
+
+      conflicts = [ "ipfs-offline.service" ];
+      wants = [ "ipfs-init.service" ];
+
+      path  = [ pkgs.ipfs ];
+
+      serviceConfig = {
+        ExecStart = "${ipfs}/bin/ipfs daemon ${ipfsFlags}";
+        User = cfg.user;
+        Group = cfg.group;
+        Restart = "on-failure";
+        RestartSec = 1;
+      };
+    };
+
+    systemd.services.ipfs-offline = {
+      description = "IPFS Daemon (offline mode)";
+
+      after = [ "local-fs.target" "ipfs-init.service" ];
+
+      conflicts = [ "ipfs.service" ];
+      wants = [ "ipfs-init.service" ];
+
+      path  = [ pkgs.ipfs ];
+
+      serviceConfig = {
+        ExecStart = "${ipfs}/bin/ipfs daemon ${ipfsFlags} --offline";
+        User = cfg.user;
+        Group = cfg.group;
+        Restart = "on-failure";
+        RestartSec = 1;
+      };
+    };
   };
 }
diff --git a/nixos/modules/services/network-filesystems/nfsd.nix b/nixos/modules/services/network-filesystems/nfsd.nix
index ddc7258ce0b..7d127145101 100644
--- a/nixos/modules/services/network-filesystems/nfsd.nix
+++ b/nixos/modules/services/network-filesystems/nfsd.nix
@@ -20,6 +20,7 @@ in
 
       server = {
         enable = mkOption {
+          type = types.bool;
           default = false;
           description = ''
             Whether to enable the kernel's NFS server.
@@ -27,6 +28,7 @@ in
         };
 
         exports = mkOption {
+          type = types.lines;
           default = "";
           description = ''
             Contents of the /etc/exports file.  See
@@ -36,6 +38,7 @@ in
         };
 
         hostName = mkOption {
+          type = types.nullOr types.str;
           default = null;
           description = ''
             Hostname or address on which NFS requests will be accepted.
@@ -46,6 +49,7 @@ in
         };
 
         nproc = mkOption {
+          type = types.int;
           default = 8;
           description = ''
             Number of NFS server threads.  Defaults to the recommended value of 8.
@@ -53,11 +57,13 @@ in
         };
 
         createMountPoints = mkOption {
+          type = types.bool;
           default = false;
           description = "Whether to create the mount points in the exports file at startup time.";
         };
 
         mountdPort = mkOption {
+          type = types.nullOr types.int;
           default = null;
           example = 4002;
           description = ''
@@ -66,11 +72,26 @@ in
         };
 
         lockdPort = mkOption {
-          default = 0;
+          type = types.nullOr types.int;
+          default = null;
+          example = 4001;
+          description = ''
+            Use a fixed port for the NFS lock manager kernel module
+            (<literal>lockd/nlockmgr</literal>).  This is useful if the
+            NFS server is behind a firewall.
+          '';
+        };
+
+        statdPort = mkOption {
+          type = types.nullOr types.int;
+          default = null;
+          example = 4000;
           description = ''
-            Fix the lockd port number. This can help setting firewall rules for NFS.
+            Use a fixed port for <command>rpc.statd</command>. This is
+            useful if the NFS server is behind a firewall.
           '';
         };
+
       };
 
     };
@@ -82,60 +103,47 @@ in
 
   config = mkIf cfg.enable {
 
-    services.rpcbind.enable = true;
+    services.nfs.extraConfig = ''
+      [nfsd]
+      threads=${toString cfg.nproc}
+      ${optionalString (cfg.hostName != null) "host=${cfg.hostName}"}
 
-    boot.supportedFilesystems = [ "nfs" ]; # needed for statd and idmapd
-
-    environment.systemPackages = [ pkgs.nfs-utils ];
+      [mountd]
+      ${optionalString (cfg.mountdPort != null) "port=${toString cfg.mountdPort}"}
 
-    environment.etc.exports.source = exports;
+      [statd]
+      ${optionalString (cfg.statdPort != null) "port=${toString cfg.statdPort}"}
 
-    boot.kernelModules = [ "nfsd" ];
+      [lockd]
+      ${optionalString (cfg.lockdPort != null) ''
+        port=${toString cfg.lockdPort}
+        udp-port=${toString cfg.lockdPort}
+      ''}
+    '';
 
-    systemd.services.nfsd =
-      { description = "NFS Server";
+    services.rpcbind.enable = true;
 
-        wantedBy = [ "multi-user.target" ];
+    boot.supportedFilesystems = [ "nfs" ]; # needed for statd and idmapd
 
-        requires = [ "rpcbind.service" "mountd.service" ];
-        after = [ "rpcbind.service" "mountd.service" "idmapd.service" ];
-        before = [ "statd.service" ];
+    environment.etc.exports.source = exports;
 
-        path = [ pkgs.nfs-utils ];
+    systemd.services.nfs-server =
+      { enable = true;
+        wantedBy = [ "multi-user.target" ];
 
-        script =
+        preStart =
           ''
-            # Create a state directory required by NFSv4.
             mkdir -p /var/lib/nfs/v4recovery
-
-            ${pkgs.procps}/sbin/sysctl -w fs.nfs.nlm_tcpport=${builtins.toString cfg.lockdPort}
-            ${pkgs.procps}/sbin/sysctl -w fs.nfs.nlm_udpport=${builtins.toString cfg.lockdPort}
-
-            rpc.nfsd \
-              ${if cfg.hostName != null then "-H ${cfg.hostName}" else ""} \
-              ${builtins.toString cfg.nproc}
           '';
-
-        postStop = "rpc.nfsd 0";
-
-        serviceConfig.Type = "oneshot";
-        serviceConfig.RemainAfterExit = true;
       };
 
-    systemd.services.mountd =
-      { description = "NFSv3 Mount Daemon";
-
-        requires = [ "rpcbind.service" ];
-        after = [ "rpcbind.service" "local-fs.target" ];
-
-        path = [ pkgs.nfs-utils pkgs.sysvtools pkgs.utillinux ];
+    systemd.services.nfs-mountd =
+      { enable = true;
+        restartTriggers = [ exports ];
 
         preStart =
           ''
             mkdir -p /var/lib/nfs
-            touch /var/lib/nfs/rmtab
-
-            mountpoint -q /proc/fs/nfsd || mount -t nfsd none /proc/fs/nfsd
 
             ${optionalString cfg.createMountPoints
               ''
@@ -146,18 +154,7 @@ in
                 | xargs -d '\n' mkdir -p
               ''
             }
-
-            exportfs -rav
           '';
-
-        restartTriggers = [ exports ];
-
-        serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = ''
-          @${pkgs.nfs-utils}/sbin/rpc.mountd rpc.mountd \
-              ${if cfg.mountdPort != null then "-p ${toString cfg.mountdPort}" else ""}
-        '';
-        serviceConfig.Restart = "always";
       };
 
   };
diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix
index 5c71a1d8dda..514204db33f 100644
--- a/nixos/modules/services/networking/asterisk.nix
+++ b/nixos/modules/services/networking/asterisk.nix
@@ -17,7 +17,7 @@ let
   allConfFiles =
     cfg.confFiles //
     builtins.listToAttrs (map (x: { name = x;
-                                    value = builtins.readFile (pkgs.asterisk + "/etc/asterisk/" + x); })
+                                    value = builtins.readFile (cfg.package + "/etc/asterisk/" + x); })
                               defaultConfFiles);
 
   asteriskEtc = pkgs.stdenv.mkDerivation
@@ -38,7 +38,7 @@ let
     asteriskConf = ''
       [directories]
       astetcdir => /etc/asterisk
-      astmoddir => ${pkgs.asterisk}/lib/asterisk/modules
+      astmoddir => ${cfg.package}/lib/asterisk/modules
       astvarlibdir => /var/lib/asterisk
       astdbdir => /var/lib/asterisk
       astkeydir => /var/lib/asterisk
@@ -47,7 +47,7 @@ let
       astspooldir => /var/spool/asterisk
       astrundir => /var/run/asterisk
       astlogdir => /var/log/asterisk
-      astsbindir => ${pkgs.asterisk}/sbin
+      astsbindir => ${cfg.package}/sbin
     '';
     extraConf = cfg.extraConfig;
 
@@ -197,11 +197,17 @@ in
           Additional command line arguments to pass to Asterisk.
         '';
       };
+      package = mkOption {
+        type = types.package;
+        default = pkgs.asterisk;
+        defaultText = "pkgs.asterisk";
+        description = "The Asterisk package to use.";
+      };
     };
   };
 
   config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.asterisk ];
+    environment.systemPackages = [ cfg.package ];
 
     environment.etc.asterisk.source = asteriskEtc;
 
@@ -234,7 +240,7 @@ in
           # TODO: Make exceptions for /var directories that likely should be updated
           if [ ! -e "$d" ]; then
             mkdir -p "$d"
-            cp --recursive ${pkgs.asterisk}/"$d"/* "$d"/
+            cp --recursive ${cfg.package}/"$d"/* "$d"/
             chown --recursive ${asteriskUser}:${asteriskGroup} "$d"
             find "$d" -type d | xargs chmod 0755
           fi
@@ -247,8 +253,8 @@ in
             # FIXME: This doesn't account for arguments with spaces
             argString = concatStringsSep " " cfg.extraArguments;
           in
-          "${pkgs.asterisk}/bin/asterisk -U ${asteriskUser} -C /etc/asterisk/asterisk.conf ${argString} -F";
-        ExecReload = ''${pkgs.asterisk}/bin/asterisk -x "core reload"
+          "${cfg.package}/bin/asterisk -U ${asteriskUser} -C /etc/asterisk/asterisk.conf ${argString} -F";
+        ExecReload = ''${cfg.package}/bin/asterisk -x "core reload"
           '';
         Type = "forking";
         PIDFile = "/var/run/asterisk/asterisk.pid";
diff --git a/nixos/modules/services/networking/chrony.nix b/nixos/modules/services/networking/chrony.nix
index f2ff11633b1..9bf266b3805 100644
--- a/nixos/modules/services/networking/chrony.nix
+++ b/nixos/modules/services/networking/chrony.nix
@@ -12,6 +12,25 @@ let
 
   cfg = config.services.chrony;
 
+  configFile = pkgs.writeText "chrony.conf" ''
+    ${concatMapStringsSep "\n" (server: "server " + server) cfg.servers}
+
+    ${optionalString
+      cfg.initstepslew.enabled
+      "initstepslew ${toString cfg.initstepslew.threshold} ${concatStringsSep " " cfg.initstepslew.servers}"
+    }
+
+    driftfile ${stateDir}/chrony.drift
+
+    keyfile ${keyFile}
+
+    ${optionalString (!config.time.hardwareClockInLocalTime) "rtconutc"}
+
+    ${cfg.extraConfig}
+  '';
+
+  chronyFlags = "-n -m -u chrony -f ${configFile} ${toString cfg.extraFlags}";
+
 in
 
 {
@@ -58,6 +77,13 @@ in
           <literal>chrony.conf</literal>
         '';
       };
+
+      extraFlags = mkOption {
+        default = [];
+        example = [ "-s" ];
+        type = types.listOf types.str;
+        description = "Extra flags passed to the chronyd command.";
+      };
     };
 
   };
@@ -70,25 +96,6 @@ in
     # Make chronyc available in the system path
     environment.systemPackages = [ pkgs.chrony ];
 
-    environment.etc."chrony.conf".text =
-      ''
-        ${concatMapStringsSep "\n" (server: "server " + server) cfg.servers}
-
-        ${optionalString
-          cfg.initstepslew.enabled
-          "initstepslew ${toString cfg.initstepslew.threshold} ${concatStringsSep " " cfg.initstepslew.servers}"
-        }
-
-        driftfile ${stateDir}/chrony.drift
-
-        keyfile ${keyFile}
-        generatecommandkey
-
-        ${optionalString (!config.time.hardwareClockInLocalTime) "rtconutc"}
-
-        ${cfg.extraConfig}
-      '';
-
     users.extraGroups = singleton
       { name = "chrony";
         gid = config.ids.gids.chrony;
@@ -124,7 +131,7 @@ in
           '';
 
         serviceConfig =
-          { ExecStart = "${pkgs.chrony}/bin/chronyd -n -m -u chrony";
+          { ExecStart = "${pkgs.chrony}/bin/chronyd ${chronyFlags}";
           };
       };
 
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index a10851c1652..12c2677c336 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -258,9 +258,8 @@ in
         Restart = "always";
         StartLimitInterval = 0;
         RestartSec = 1;
-        CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW";
-        AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_RAW";
-        ProtectSystem = "full";
+        CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW CAP_SETUID";
+        ProtectSystem = true;
         MemoryDenyWriteExecute = true;
         ProtectHome = true;
         PrivateTmp = true;
diff --git a/nixos/modules/services/networking/dnschain.nix b/nixos/modules/services/networking/dnschain.nix
index f17f8c832ee..b6492996057 100644
--- a/nixos/modules/services/networking/dnschain.nix
+++ b/nixos/modules/services/networking/dnschain.nix
@@ -3,23 +3,28 @@
 with lib;
 
 let
-  cfg = config.services;
+  cfgs = config.services;
+  cfg  = cfgs.dnschain;
 
-  dnschainConf = pkgs.writeText "dnschain.conf" ''
+  dataDir  = "/var/lib/dnschain";
+  username = "dnschain";
+
+  configFile = pkgs.writeText "dnschain.conf" ''
     [log]
-    level=info
+    level = info
 
     [dns]
-    host = 127.0.0.1
-    port = 5333
+    host = ${cfg.dns.address}
+    port = ${toString cfg.dns.port}
     oldDNSMethod = NO_OLD_DNS
-    # TODO: check what that address is acutally used for
-    externalIP = 127.0.0.1
+    externalIP = ${cfg.dns.address}
 
     [http]
-    host = 127.0.0.1
-    port=8088
-    tlsPort=4443
+    host = ${cfg.api.hostname}
+    port = ${toString cfg.api.port}
+    tlsPort = ${toString cfg.api.tlsPort}
+
+    ${cfg.extraConfig}
   '';
 
 in
@@ -32,28 +37,81 @@ in
 
     services.dnschain = {
 
-      enable = mkOption {
-        type = types.bool;
-        default = false;
+      enable = mkEnableOption ''
+        DNSChain, a blockchain based DNS + HTTP server.
+        To resolve .bit domains set <literal>services.namecoind.enable = true;</literal>
+        and an RPC username/password.
+      '';
+
+      dns.address = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
         description = ''
-          Whether to run dnschain. That implies running
-          namecoind as well, so make sure to configure
-          it appropriately.
+          The IP address that will be used to reach this machine.
+          Leave this unchanged if you do not wish to directly expose the DNSChain resolver.
         '';
       };
 
-    };
+      dns.port = mkOption {
+        type = types.int;
+        default = 5333;
+        description = ''
+          The port the DNSChain resolver will bind to.
+        '';
+      };
+
+      api.hostname = mkOption {
+        type = types.str;
+        default = "0.0.0.0";
+        description = ''
+          The hostname (or IP address) the DNSChain API server will bind to.
+        '';
+      };
+
+      api.port = mkOption {
+        type = types.int;
+        default = 8080;
+        description = ''
+          The port the DNSChain API server (HTTP) will bind to.
+        '';
+      };
 
-    services.dnsmasq = {
-      resolveDnschainQueries = mkOption {
-        type = types.bool;
-        default = false;
+      api.tlsPort = mkOption {
+        type = types.int;
+        default = 4433;
         description = ''
-          Resolve <literal>.bit</literal> top-level domains
-          with dnschain and namecoind.
+          The port the DNSChain API server (HTTPS) will bind to.
         '';
       };
 
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        example = ''
+          [log]
+          level = debug
+        '';
+        description = ''
+          Additional options that will be appended to the configuration file.
+        '';
+      };
+
+    };
+
+    services.dnsmasq.resolveDNSChainQueries = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Resolve <literal>.bit</literal> top-level domains using DNSChain and namecoin.
+      '';
+    };
+
+    services.pdns-recursor.resolveDNSChainQueries = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Resolve <literal>.bit</literal> top-level domains using DNSChain and namecoin.
+      '';
     };
 
   };
@@ -61,48 +119,47 @@ in
 
   ###### implementation
 
-  config = mkIf cfg.dnschain.enable {
-
-    services.namecoind.enable = true;
+  config = mkIf cfg.enable {
 
-    services.dnsmasq.servers = optionals cfg.dnsmasq.resolveDnschainQueries [ "/.bit/127.0.0.1#5333" ];
+    services.dnsmasq.servers = optionals cfgs.dnsmasq.resolveDNSChainQueries
+      [ "/.bit/127.0.0.1#${toString cfg.dns.port}"
+        "/.dns/127.0.0.1#${toString cfg.dns.port}"
+      ];
 
-    users.extraUsers = singleton
-      { name = "dnschain";
-        uid = config.ids.uids.dnschain;
-        extraGroups = [ "namecoin" ];
-        description = "Dnschain daemon user";
-        home = "/var/lib/dnschain";
-        createHome = true;
+    services.pdns-recursor.forwardZones = mkIf cfgs.pdns-recursor.resolveDNSChainQueries
+      { bit = "127.0.0.1:${toString cfg.dns.port}";
+        dns = "127.0.0.1:${toString cfg.dns.port}";
       };
 
+    users.extraUsers = singleton {
+      name = username;
+      description = "DNSChain daemon user";
+      home = dataDir;
+      createHome = true;
+      uid = config.ids.uids.dnschain;
+      extraGroups = optional cfgs.namecoind.enable "namecoin";
+    };
+
     systemd.services.dnschain = {
-        description = "Dnschain Daemon";
-        after = [ "namecoind.target" ];
-        wantedBy = [ "multi-user.target" ];
-        path = [ pkgs.openssl ];
-        preStart = ''
-          # Link configuration file into dnschain HOME directory
-          if [ "$(${pkgs.coreutils}/bin/realpath /var/lib/dnschain/.dnschain.conf)" != "${dnschainConf}" ]; then
-              rm -rf /var/lib/dnschain/.dnschain.conf
-              ln -s ${dnschainConf} /var/lib/dnschain/.dnschain.conf
-          fi
-
-          # Create empty namecoin.conf so that dnschain is not
-          # searching for /etc/namecoin/namecoin.conf
-          if [ ! -e /var/lib/dnschain/.namecoin/namecoin.conf ]; then
-              mkdir -p /var/lib/dnschain/.namecoin
-              touch /var/lib/dnschain/.namecoin/namecoin.conf
-          fi
-        '';
-        serviceConfig = {
-          Type = "simple";
-          User = "dnschain";
-          EnvironmentFile = config.services.namecoind.userFile;
-          ExecStart = "${pkgs.dnschain}/bin/dnschain --rpcuser=\${USER} --rpcpassword=\${PASSWORD} --rpcport=8336";
-          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-          ExecStop = "${pkgs.coreutils}/bin/kill -KILL $MAINPID";
-        };
+      description = "DNSChain daemon";
+      after    = optional cfgs.namecoind.enable "namecoind.target";
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        User = "dnschain";
+        Restart = "on-failure";
+        ExecStart = "${pkgs.dnschain}/bin/dnschain";
+      };
+
+      preStart = ''
+        # Link configuration file into dnschain home directory
+        configPath=${dataDir}/.dnschain/dnschain.conf
+        mkdir -p ${dataDir}/.dnschain
+        if [ "$(realpath $configPath)" != "${configFile}" ]; then
+          rm -f $configPath
+          ln -s ${configFile} $configPath
+        fi
+      '';
     };
 
   };
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index 34b731ad35c..243cd04c96c 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -38,9 +38,9 @@ let
 
   cfg = config.networking.firewall;
 
-  kernelPackages = config.boot.kernelPackages;
+  inherit (config.boot.kernelPackages) kernel;
 
-  kernelHasRPFilter = kernelPackages.kernel.features.netfilterRPFilter or false;
+  kernelHasRPFilter = ((kernel.config.isEnabled or (x: false)) "IP_NF_MATCH_RPFILTER") || (kernel.features.netfilterRPFilter or false);
 
   helpers =
     ''
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index abb7a4e9137..c5b27350b3c 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -8,7 +8,7 @@ let
 
   homeDir = "/var/lib/i2pd";
 
-  extip = "EXTIP=\$(${pkgs.curl.bin}/bin/curl -sf \"http://jsonip.com\" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
+  extip = "EXTIP=\$(${pkgs.curl.bin}/bin/curl -sLf \"http://jsonip.com\" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
 
   toYesNo = b: if b then "true" else "false";
 
diff --git a/nixos/modules/services/networking/libreswan.nix b/nixos/modules/services/networking/libreswan.nix
index 3866b216f8e..c87e738d2a2 100644
--- a/nixos/modules/services/networking/libreswan.nix
+++ b/nixos/modules/services/networking/libreswan.nix
@@ -102,7 +102,7 @@ in
       serviceConfig = {
         Type = "simple";
         Restart = "always";
-        EnvironmentFile = "${pkgs.libreswan}/etc/sysconfig/pluto";
+        EnvironmentFile = "-${pkgs.libreswan}/etc/sysconfig/pluto";
         ExecStartPre = [
           "${libexec}/addconn --config ${configFile} --checkconfig"
           "${libexec}/_stackmanager start"
diff --git a/nixos/modules/services/networking/namecoind.nix b/nixos/modules/services/networking/namecoind.nix
index 83fc1ec6667..9df9f67cde8 100644
--- a/nixos/modules/services/networking/namecoind.nix
+++ b/nixos/modules/services/networking/namecoind.nix
@@ -3,25 +3,35 @@
 with lib;
 
 let
-  cfg = config.services.namecoind;
+  cfg     = config.services.namecoind;
+  dataDir = "/var/lib/namecoind";
+  useSSL  = (cfg.rpc.certificate != null) && (cfg.rpc.key != null);
+  useRPC  = (cfg.rpc.user != null) && (cfg.rpc.password != null);
 
-  namecoinConf =
-  let
-    useSSL = (cfg.rpcCertificate != null) && (cfg.rpcKey != null);
-  in
-  pkgs.writeText "namecoin.conf" ''
+  listToConf = option: list:
+    concatMapStrings (value :"${option}=${value}\n") list;
+
+  configFile = pkgs.writeText "namecoin.conf" (''
     server=1
     daemon=0
-    rpcallowip=127.0.0.1
-    walletpath=${cfg.wallet}
-    gen=${if cfg.generate then "1" else "0"}
-    rpcssl=${if useSSL then "1" else "0"}
-    ${optionalString useSSL "rpcsslcertificatechainfile=${cfg.rpcCertificate}"}
-    ${optionalString useSSL "rpcsslprivatekeyfile=${cfg.rpcKey}"}
-    ${optionalString useSSL "rpcsslciphers=TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH"}
     txindex=1
     txprevcache=1
-  '';
+    walletpath=${cfg.wallet}
+    gen=${if cfg.generate then "1" else "0"}
+    ${listToConf "addnode" cfg.extraNodes}
+    ${listToConf "connect" cfg.trustedNodes}
+  '' + optionalString useRPC ''
+    rpcbind=${cfg.rpc.address}
+    rpcport=${toString cfg.rpc.port}
+    rpcuser=${cfg.rpc.user}
+    rpcpassword=${cfg.rpc.password}
+    ${listToConf "rpcallowip" cfg.rpc.allowFrom}
+  '' + optionalString useSSL ''
+    rpcssl=1
+    rpcsslcertificatechainfile=${cfg.rpc.certificate}
+    rpcsslprivatekeyfile=${cfg.rpc.key}
+    rpcsslciphers=TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH
+  '');
 
 in
 
@@ -33,66 +43,102 @@ in
 
     services.namecoind = {
 
-      enable = mkOption {
+      enable = mkEnableOption "namecoind, Namecoin client.";
+
+      wallet = mkOption {
+        type = types.path;
+        default = "${dataDir}/wallet.dat";
+        description = ''
+          Wallet file. The ownership of the file has to be
+          namecoin:namecoin, and the permissions must be 0640.
+        '';
+      };
+
+      generate = mkOption {
         type = types.bool;
         default = false;
         description = ''
-          Whether to run namecoind.
+          Whether to generate (mine) Namecoins.
         '';
       };
 
-      wallet = mkOption {
-        type = types.path;
-        example = "/etc/namecoin/wallet.dat";
+      extraNodes = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
         description = ''
-          Wallet file. The ownership of the file has to be
-          namecoin:namecoin, and the permissions must be 0640.
+          List of additional peer IP addresses to connect to.
         '';
       };
 
-      userFile = mkOption {
-        type = types.nullOr types.path;
+      trustedNodes = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        description = ''
+          List of the only peer IP addresses to connect to. If specified
+          no other connection will be made.
+        '';
+      };
+
+      rpc.user = mkOption {
+        type = types.nullOr types.str;
         default = null;
-        example = "/etc/namecoin/user";
         description = ''
-          File containing the user name and user password to
-          authenticate RPC connections to namecoind.
-          The content of the file is of the form:
-          <literal>
-          USER=namecoin
-          PASSWORD=secret
-          </literal>
-          The ownership of the file has to be namecoin:namecoin,
-          and the permissions must be 0640.
+          User name for RPC connections.
         '';
       };
 
-      generate = mkOption {
-        type = types.bool;
-        default = false;
+      rpc.password = mkOption {
+        type = types.str;
+        default = null;
         description = ''
-          Whether to generate (mine) Namecoins.
+          Password for RPC connections.
         '';
       };
 
-      rpcCertificate = mkOption {
+      rpc.address = mkOption {
+        type = types.str;
+        default = "0.0.0.0";
+        description = ''
+          IP address the RPC server will bind to.
+        '';
+      };
+
+      rpc.port = mkOption {
+        type = types.int;
+        default = 8332;
+        description = ''
+          Port the RPC server will bind to.
+        '';
+      };
+
+      rpc.certificate = mkOption {
         type = types.nullOr types.path;
         default = null;
-        example = "/etc/namecoin/server.cert";
+        example = "/var/lib/namecoind/server.cert";
         description = ''
           Certificate file for securing RPC connections.
         '';
       };
 
-      rpcKey = mkOption {
+      rpc.key = mkOption {
         type = types.nullOr types.path;
         default = null;
-        example = "/etc/namecoin/server.pem";
+        example = "/var/lib/namecoind/server.pem";
         description = ''
           Key file for securing RPC connections.
         '';
       };
 
+
+      rpc.allowFrom = mkOption {
+        type = types.listOf types.str;
+        default = [ "127.0.0.1" ];
+        description = ''
+          List of IP address ranges allowed to use the RPC API.
+          Wiledcards (*) can be user to specify a range.
+        '';
+      };
+
     };
 
   };
@@ -102,47 +148,54 @@ in
 
   config = mkIf cfg.enable {
 
-    users.extraUsers = singleton
-      { name = "namecoin";
-        uid = config.ids.uids.namecoin;
-        description = "Namecoin daemon user";
-        home = "/var/lib/namecoin";
-        createHome = true;
-      };
+    services.dnschain.extraConfig = ''
+      [namecoin]
+      config = ${configFile}
+    '';
+
+    users.extraUsers = singleton {
+      name = "namecoin";
+      uid  = config.ids.uids.namecoin;
+      description = "Namecoin daemon user";
+      home = dataDir;
+      createHome = true;
+    };
 
-    users.extraGroups = singleton
-      { name = "namecoin";
-        gid = config.ids.gids.namecoin;
-      };
+    users.extraGroups = singleton {
+      name = "namecoin";
+      gid  = config.ids.gids.namecoin;
+    };
 
     systemd.services.namecoind = {
-        description = "Namecoind Daemon";
-        after = [ "network.target" ];
-        wantedBy = [ "multi-user.target" ];
-        preStart = ''
-          if [  "$(stat --printf '%u' ${cfg.userFile})" != "${toString config.ids.uids.namecoin}" \
-             -o "$(stat --printf '%g' ${cfg.userFile})" != "${toString config.ids.gids.namecoin}" \
-             -o "$(stat --printf '%a' ${cfg.userFile})" != "640" ]; then
-             echo "ERROR: bad ownership or rights on ${cfg.userFile}" >&2
-             exit 1
-          fi
-          if [  "$(stat --printf '%u' ${cfg.wallet})" != "${toString config.ids.uids.namecoin}" \
-             -o "$(stat --printf '%g' ${cfg.wallet})" != "${toString config.ids.gids.namecoin}" \
-             -o "$(stat --printf '%a' ${cfg.wallet})" != "640" ]; then
-             echo "ERROR: bad ownership or rights on ${cfg.wallet}" >&2
-             exit 1
-          fi
-        '';
-        serviceConfig = {
-          Type = "simple";
-          User = "namecoin";
-          EnvironmentFile = cfg.userFile;
-          ExecStart = "${pkgs.altcoins.namecoind}/bin/namecoind -conf=${namecoinConf} -rpcuser=\${USER} -rpcpassword=\${PASSWORD} -printtoconsole";
-          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-          ExecStop = "${pkgs.coreutils}/bin/kill -KILL $MAINPID";
-          StandardOutput = "null";
-          Nice = "10";
-        };
+      description = "Namecoind daemon";
+      after    = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        User  = "namecoin";
+        Griup = "namecoin";
+        ExecStart  = "${pkgs.altcoins.namecoind}/bin/namecoind -conf=${configFile} -datadir=${dataDir} -printtoconsole";
+        ExecStop   = "${pkgs.coreutils}/bin/kill -KILL $MAINPID";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        Nice = "10";
+        PrivateTmp = true;
+        TimeoutStopSec     = "60s";
+        TimeoutStartSec    = "2s";
+        Restart            = "always";
+        StartLimitInterval = "120s";
+        StartLimitBurst    = "5";
+      };
+
+      preStart = optionalString (cfg.wallet != "${dataDir}/wallet.dat")  ''
+        # check wallet file permissions
+        if [ "$(stat --printf '%u' ${cfg.wallet})" != "${toString config.ids.uids.namecoin}" \
+           -o "$(stat --printf '%g' ${cfg.wallet})" != "${toString config.ids.gids.namecoin}" \
+           -o "$(stat --printf '%a' ${cfg.wallet})" != "640" ]; then
+           echo "ERROR: bad ownership or rights on ${cfg.wallet}" >&2
+           exit 1
+        fi
+      '';
+
     };
 
   };
diff --git a/nixos/modules/services/networking/nylon.nix b/nixos/modules/services/networking/nylon.nix
index da6487dbd49..4864ecf3f92 100644
--- a/nixos/modules/services/networking/nylon.nix
+++ b/nixos/modules/services/networking/nylon.nix
@@ -8,7 +8,7 @@ let
 
   homeDir = "/var/lib/nylon";
 
-  configFile = pkgs.writeText "nylon.conf" ''
+  configFile = cfg: pkgs.writeText "nylon-${cfg.name}.conf" ''
     [General]
     No-Simultaneous-Conn=${toString cfg.nrConnections}
     Log=${if cfg.logging then "1" else "0"}
@@ -22,15 +22,9 @@ let
     Deny-IP=${concatStringsSep " " cfg.deniedIPRanges}
   '';
 
-in
-
-{
-
-  ###### interface
-
-  options = {
+  nylonOpts = { name, config, ... }: {
 
-    services.nylon = {
+    options = {
 
       enable = mkOption {
         type = types.bool;
@@ -40,6 +34,12 @@ in
         '';
       };
 
+      name = mkOption {
+        type = types.str;
+        default = "";
+        description = "The name of this nylon instance.";
+      };
+
       nrConnections = mkOption {
         type = types.int;
         default = 10;
@@ -107,13 +107,51 @@ in
         '';
       };
     };
+    config = { name = mkDefault name; };
+  };
+
+  mkNamedNylon = cfg: {
+    "nylon-${cfg.name}" = {
+      description = "Nylon, a lightweight SOCKS proxy server";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig =
+      {
+        User = "nylon";
+        Group = "nylon";
+        WorkingDirectory = homeDir;
+        ExecStart = "${pkgs.nylon}/bin/nylon -f -c ${configFile cfg}";
+      };
+    };
+  };
+
+  anyNylons = collect (p: p ? enable) cfg;
+  enabledNylons = filter (p: p.enable == true) anyNylons;
+  nylonUnits = map (nylon: mkNamedNylon nylon) enabledNylons;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.nylon = mkOption {
+      default = {};
+      description = "Collection of named nylon instances";
+      type = with types; loaOf (submodule nylonOpts);
+      internal = true;
+      options = [ nylonOpts ];
+    };
+
   };
 
   ###### implementation
 
-  config = mkIf cfg.enable {
+  config = mkIf (length(enabledNylons) > 0) {
 
-    users.extraUsers.nylon= {
+    users.extraUsers.nylon = {
       group = "nylon";
       description = "Nylon SOCKS Proxy";
       home = homeDir;
@@ -123,17 +161,7 @@ in
 
     users.extraGroups.nylon.gid = config.ids.gids.nylon;
 
-    systemd.services.nylon = {
-      description = "Nylon, a lightweight SOCKS proxy server";
-      after = [ "network.target" ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig =
-      {
-        User = "nylon";
-        Group = "nylon";
-        WorkingDirectory = homeDir;
-        ExecStart = "${pkgs.nylon}/bin/nylon -f -c ${configFile}";
-      };
-    };
+    systemd.services = fold (a: b: a // b) {} nylonUnits;
+
   };
 }
diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix
index edcc12170b2..9b06cccca79 100644
--- a/nixos/modules/services/networking/quassel.nix
+++ b/nixos/modules/services/networking/quassel.nix
@@ -25,12 +25,12 @@ in
 
       package = mkOption {
         type = types.package;
-        default = pkgs.kde4.quasselDaemon;
-        defaultText = "pkgs.kde4.quasselDaemon";
+        default = pkgs.quasselDaemon_qt5;
+        defaultText = "pkgs.quasselDaemon_qt5";
         description = ''
           The package of the quassel daemon.
         '';
-        example = literalExample "pkgs.quasselDaemon";
+        example = literalExample "pkgs.quasselDaemon_qt5";
       };
 
       interfaces = mkOption {
diff --git a/nixos/modules/services/networking/redsocks.nix b/nixos/modules/services/networking/redsocks.nix
new file mode 100644
index 00000000000..a47a78f1005
--- /dev/null
+++ b/nixos/modules/services/networking/redsocks.nix
@@ -0,0 +1,270 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.redsocks;
+in
+{
+  ##### interface
+  options = {
+    services.redsocks = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable redsocks.";
+      };
+
+      log_debug = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Log connection progress.";
+      };
+
+      log_info = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Log start and end of client sessions.";
+      };
+
+      log = mkOption {
+        type = types.str;
+        default = "stderr";
+        description =
+          ''
+            Where to send logs.
+
+            Possible values are:
+              - stderr
+              - file:/path/to/file
+              - syslog:FACILITY where FACILITY is any of "daemon", "local0",
+              etc.
+          '';
+      };
+
+      chroot = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description =
+          ''
+            Chroot under which to run redsocks. Log file is opened before
+            chroot, but if logging to syslog /etc/localtime may be required.
+          '';
+      };
+
+      redsocks = mkOption {
+        description =
+          ''
+            Local port to proxy associations to be performed.
+
+            The example shows how to configure a proxy to handle port 80 as HTTP
+            relay, and all other ports as HTTP connect.
+          '';
+        example = [
+          { port = 23456; proxy = "1.2.3.4:8080"; type = "http-relay";
+            redirectCondition = "--dport 80";
+            doNotRedirect = [ "-d 1.2.0.0/16" ];
+          }
+          { port = 23457; proxy = "1.2.3.4:8080"; type = "http-connect";
+            redirectCondition = true;
+            doNotRedirect = [ "-d 1.2.0.0/16" ];
+          }
+        ];
+        type = types.listOf (types.submodule { options = {
+          ip = mkOption {
+            type = types.str;
+            default = "127.0.0.1";
+            description =
+              ''
+                IP on which redsocks should listen. Defaults to 127.0.0.1 for
+                security reasons.
+              '';
+          };
+
+          port = mkOption {
+            type = types.int;
+            default = 12345;
+            description = "Port on which redsocks should listen.";
+          };
+
+          proxy = mkOption {
+            type = types.str;
+            description =
+              ''
+                Proxy through which redsocks should forward incoming traffic.
+                Example: "example.org:8080"
+              '';
+          };
+
+          type = mkOption {
+            type = types.enum [ "socks4" "socks5" "http-connect" "http-relay" ];
+            description = "Type of proxy.";
+          };
+
+          login = mkOption {
+            type = with types; nullOr str;
+            default = null;
+            description = "Login to send to proxy.";
+          };
+
+          password = mkOption {
+            type = with types; nullOr str;
+            default = null;
+            description =
+              ''
+                Password to send to proxy. WARNING, this will end up
+                world-readable in the store! Awaiting
+                https://github.com/NixOS/nix/issues/8 to be able to fix.
+              '';
+          };
+
+          disclose_src = mkOption {
+            type = types.enum [ "false" "X-Forwarded-For" "Forwarded_ip"
+                                "Forwarded_ipport" ];
+            default = "false";
+            description =
+              ''
+                Way to disclose client IP to the proxy.
+                  - "false": do not disclose
+                http-connect supports the following ways:
+                  - "X-Forwarded-For": add header "X-Forwarded-For: IP"
+                  - "Forwarded_ip": add header "Forwarded: for=IP" (see RFC7239)
+                  - "Forwarded_ipport": add header 'Forwarded: for="IP:port"'
+              '';
+          };
+
+          redirectInternetOnly = mkOption {
+            type = types.bool;
+            default = true;
+            description = "Exclude all non-globally-routable IPs from redsocks";
+          };
+
+          doNotRedirect = mkOption {
+            type = with types; listOf str;
+            default = [];
+            description =
+              ''
+                Iptables filters that if matched will get the packet off of
+                redsocks.
+              '';
+            example = [ "-d 1.2.3.4" ];
+          };
+
+          redirectCondition = mkOption {
+            type = with types; either bool str;
+            default = false;
+            description =
+              ''
+                Conditions to make outbound packets go through this redsocks
+                instance.
+
+                If set to false, no packet will be forwarded. If set to true,
+                all packets will be forwarded (except packets excluded by
+                redirectInternetOnly).
+
+                If set to a string, this is an iptables filter that will be
+                matched against packets before getting them into redsocks. For
+                example, setting it to "--dport 80" will only send
+                packets to port 80 to redsocks. Note "-p tcp" is always
+                implicitly added, as udp can only be proxied through redudp or
+                the like.
+              '';
+          };
+        };});
+      };
+
+      # TODO: Add support for redudp and dnstc
+    };
+  };
+
+  ##### implementation
+  config = let
+    redsocks_blocks = concatMapStrings (block:
+      let proxy = splitString ":" block.proxy; in
+      ''
+        redsocks {
+          local_ip = ${block.ip};
+          local_port = ${toString block.port};
+
+          ip = ${elemAt proxy 0};
+          port = ${elemAt proxy 1};
+          type = ${block.type};
+
+          ${optionalString (block.login != null) "login = \"${block.login}\";"}
+          ${optionalString (block.password != null) "password = \"${block.password}\";"}
+
+          disclose_src = ${block.disclose_src};
+        }
+      '') cfg.redsocks;
+    configfile = pkgs.writeText "redsocks.conf"
+      ''
+        base {
+          log_debug = ${if cfg.log_debug then "on" else "off" };
+          log_info = ${if cfg.log_info then "on" else "off" };
+          log = ${cfg.log};
+
+          daemon = off;
+          redirector = iptables;
+
+          user = redsocks;
+          group = redsocks;
+          ${optionalString (cfg.chroot != null) "chroot = ${cfg.chroot};"}
+        }
+
+        ${redsocks_blocks}
+      '';
+    internetOnly = [ # TODO: add ipv6-equivalent
+      "-d 0.0.0.0/8"
+      "-d 10.0.0.0/8"
+      "-d 127.0.0.0/8"
+      "-d 169.254.0.0/16"
+      "-d 172.16.0.0/12"
+      "-d 192.168.0.0/16"
+      "-d 224.168.0.0/4"
+      "-d 240.168.0.0/4"
+    ];
+    redCond = block:
+      optionalString (isString block.redirectCondition) block.redirectCondition;
+    iptables = concatImapStrings (idx: block:
+      let chain = "REDSOCKS${toString idx}"; doNotRedirect =
+        concatMapStringsSep "\n"
+          (f: "ip46tables -t nat -A ${chain} ${f} -j RETURN 2>/dev/null || true")
+          (block.doNotRedirect ++ (optionals block.redirectInternetOnly internetOnly));
+      in
+      optionalString (block.redirectCondition != false)
+        ''
+          ip46tables -t nat -F ${chain} 2>/dev/null || true
+          ip46tables -t nat -N ${chain} 2>/dev/null || true
+          ${doNotRedirect}
+          ip46tables -t nat -A ${chain} -p tcp -j REDIRECT --to-ports ${toString block.port}
+
+          # TODO: show errors, when it will be easily possible by a switch to
+          # iptables-restore
+          ip46tables -t nat -A OUTPUT -p tcp ${redCond block} -j ${chain} 2>/dev/null || true
+        ''
+    ) cfg.redsocks;
+  in
+    mkIf cfg.enable {
+      users.groups.redsocks = {};
+      users.users.redsocks = {
+        description = "Redsocks daemon";
+        group = "redsocks";
+        isSystemUser = true;
+      };
+
+      systemd.services.redsocks = {
+        description = "Redsocks";
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        script = "${pkgs.redsocks}/bin/redsocks -c ${configfile}";
+      };
+
+      networking.firewall.extraCommands = iptables;
+
+      networking.firewall.extraStopCommands =
+        concatImapStringsSep "\n" (idx: block:
+          let chain = "REDSOCKS${toString idx}"; in
+          optionalString (block.redirectCondition != false)
+            "ip46tables -t nat -D OUTPUT -p tcp ${redCond block} -j ${chain} 2>/dev/null || true"
+        ) cfg.redsocks;
+    };
+}
diff --git a/nixos/modules/services/networking/rpcbind.nix b/nixos/modules/services/networking/rpcbind.nix
index eef1e8e8cd8..cddcb09054e 100644
--- a/nixos/modules/services/networking/rpcbind.nix
+++ b/nixos/modules/services/networking/rpcbind.nix
@@ -2,35 +2,6 @@
 
 with lib;
 
-let
-
-  netconfigFile = {
-    target = "netconfig";
-    source = pkgs.writeText "netconfig" ''
-      #
-      # The network configuration file. This file is currently only used in
-      # conjunction with the TI-RPC code in the libtirpc library.
-      #
-      # Entries consist of:
-      #
-      #       <network_id> <semantics> <flags> <protofamily> <protoname> \
-      #               <device> <nametoaddr_libs>
-      #
-      # The <device> and <nametoaddr_libs> fields are always empty in this
-      # implementation.
-      #
-      udp        tpi_clts      v     inet     udp     -       -
-      tcp        tpi_cots_ord  v     inet     tcp     -       -
-      udp6       tpi_clts      v     inet6    udp     -       -
-      tcp6       tpi_cots_ord  v     inet6    tcp     -       -
-      rawip      tpi_raw       -     inet      -      -       -
-      local      tpi_cots_ord  -     loopback  -      -       -
-      unix       tpi_cots_ord  -     loopback  -      -       -
-    '';
-  };
-
-in
-
 {
 
   ###### interface
@@ -58,25 +29,18 @@ in
   ###### implementation
 
   config = mkIf config.services.rpcbind.enable {
-
     environment.systemPackages = [ pkgs.rpcbind ];
 
-    environment.etc = [ netconfigFile ];
-
-    systemd.services.rpcbind =
-      { description = "ONC RPC Directory Service";
+    systemd.packages = [ pkgs.rpcbind ];
 
-        wantedBy = [ "multi-user.target" ];
-
-        requires = [ "basic.target" ];
-        after = [ "basic.target" ];
-
-        unitConfig.DefaultDependencies = false; # don't stop during shutdown
-
-        serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = "@${pkgs.rpcbind}/bin/rpcbind rpcbind";
-      };
+    systemd.services.rpcbind = {
+      wantedBy = [ "multi-user.target" ];
+    };
 
+    users.extraUsers.rpc = {
+      group = "nogroup";
+      uid = config.ids.uids.rpc;
+    };
   };
 
 }
diff --git a/nixos/modules/services/networking/searx.nix b/nixos/modules/services/networking/searx.nix
index b29db58af99..b852e4e6dc8 100644
--- a/nixos/modules/services/networking/searx.nix
+++ b/nixos/modules/services/networking/searx.nix
@@ -34,6 +34,11 @@ in
         ";
       };
 
+      package = mkOption {
+        default = pkgs.pythonPackages.searx;
+        description = "searx package to use.";
+      };
+
     };
 
   };
@@ -61,14 +66,13 @@ in
         wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           User = "searx";
-          ExecStart = "${pkgs.pythonPackages.searx}/bin/searx-run";
+          ExecStart = "${cfg.package}/bin/searx-run";
         };
       } // (optionalAttrs (configFile != "") {
         environment.SEARX_SETTINGS_PATH = configFile;
       });
-        
 
-    environment.systemPackages = [ pkgs.pythonPackages.searx ];
+    environment.systemPackages = [ cfg.package ];
 
   };
 
diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix
index 0c459fb1dd0..31d11548f19 100644
--- a/nixos/modules/services/networking/supplicant.nix
+++ b/nixos/modules/services/networking/supplicant.nix
@@ -82,7 +82,8 @@ in
           configFile = {
   
             path = mkOption {
-              type = types.path;
+              type = types.nullOr types.path;
+              default = null;
               example = literalExample "/etc/wpa_supplicant.conf";
               description = ''
                 External <literal>wpa_supplicant.conf</literal> configuration file.
diff --git a/nixos/modules/services/security/hologram-agent.nix b/nixos/modules/services/security/hologram-agent.nix
new file mode 100644
index 00000000000..49b5c935267
--- /dev/null
+++ b/nixos/modules/services/security/hologram-agent.nix
@@ -0,0 +1,57 @@
+{pkgs, config, lib, ...}:
+
+with lib;
+
+let
+  cfg = config.services.hologram-agent;
+
+  cfgFile = pkgs.writeText "hologram-agent.json" (builtins.toJSON {
+    host = cfg.dialAddress;
+  });
+in {
+  options = {
+    services.hologram-agent = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the Hologram agent for AWS instance credentials";
+      };
+
+      dialAddress = mkOption {
+        type        = types.str;
+        default     = "localhost:3100";
+        description = "Hologram server and port.";
+      };
+
+      httpPort = mkOption {
+        type        = types.str;
+        default     = "80";
+        description = "Port for metadata service to listen on.";
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+    networking.interfaces.dummy0 = {
+      ipAddress = "169.254.169.254";
+      prefixLength = 32;
+    };
+
+    systemd.services.hologram-agent = {
+      description = "Provide EC2 instance credentials to machines outside of EC2";
+      after       = [ "network.target" ];
+      wantedBy    = [ "multi-user.target" ];
+      requires    = [ "network-link-dummy0.service" "network-addresses-dummy0.service" ]; 
+      preStart = ''
+        /run/current-system/sw/bin/rm -fv /var/run/hologram.sock
+      '';
+      serviceConfig = {
+        ExecStart = "${pkgs.hologram.bin}/bin/hologram-agent -debug -conf ${cfgFile} -port ${cfg.httpPort}";
+      };
+    };
+
+  };
+
+  meta.maintainers = with lib.maintainers; [ nand0p ];
+}
diff --git a/nixos/modules/services/security/hologram.nix b/nixos/modules/services/security/hologram-server.nix
index e267fed2795..e267fed2795 100644
--- a/nixos/modules/services/security/hologram.nix
+++ b/nixos/modules/services/security/hologram-server.nix
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index fae5a55c5ce..33bc890a78c 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -20,8 +20,6 @@ let
     "<includedir>${d}/etc/dbus-1/session.d</includedir>"
   ]));
 
-  daemonArgs = "--address=systemd: --nofork --nopidfile --systemd-activation";
-
   configDir = pkgs.runCommand "dbus-conf"
     { preferLocalBuild = true;
       allowSubstitutes = false;
@@ -29,11 +27,6 @@ let
     ''
       mkdir -p $out
 
-      cp ${pkgs.dbus.out}/share/dbus-1/{system,session}.conf $out
-
-      # 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},' \
@@ -95,6 +88,11 @@ in
 
     environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus ];
 
+    environment.etc = singleton
+      { source = configDir;
+        target = "dbus-1";
+      };
+
     users.extraUsers.messagebus = {
       uid = config.ids.uids.messagebus;
       description = "D-Bus system message bus daemon user";
@@ -124,10 +122,6 @@ in
       # Don't restart dbus-daemon. Bad things tend to happen if we do.
       reloadIfChanged = true;
       restartTriggers = [ configDir ];
-      serviceConfig.ExecStart = [
-        "" # Default dbus.service has two entries, we need to override both.
-        "${lib.getBin pkgs.dbus}/bin/dbus-daemon --config-file=/run/current-system/dbus/system.conf ${daemonArgs}"
-      ];
     };
 
     systemd.user = {
@@ -135,18 +129,10 @@ in
         # Don't restart dbus-daemon. Bad things tend to happen if we do.
         reloadIfChanged = true;
         restartTriggers = [ configDir ];
-        serviceConfig.ExecStart = [
-          "" # Default dbus.service has two entries, we need to override both.
-          "${lib.getBin pkgs.dbus}/bin/dbus-daemon --config-file=/run/current-system/dbus/session.conf ${daemonArgs}"
-        ];
       };
       sockets.dbus.wantedBy = mkIf cfg.socketActivated [ "sockets.target" ];
     };
 
     environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ];
-
-    system.extraSystemBuilderCmds = ''
-      ln -s ${configDir} $out/dbus
-    '';
   };
 }
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index dc0ca501a48..ed77e084476 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -63,6 +63,8 @@ let
       let
         svcFunction =
           if svc ? function then svc.function
+          # instead of using serviceType="mediawiki"; you can copy mediawiki.nix to any location outside nixpkgs, modify it at will, and use serviceExpression=./mediawiki.nix;
+          else if svc ? serviceExpression then import (toString svc.serviceExpression)
           else import (toString "${toString ./.}/${if svc ? serviceType then svc.serviceType else svc.serviceName}.nix");
         config = (evalModules
           { modules = [ { options = res.options; config = svc.config or svc; } ];
diff --git a/nixos/modules/services/web-servers/apache-httpd/moodle.nix b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
deleted file mode 100644
index d525348d5c7..00000000000
--- a/nixos/modules/services/web-servers/apache-httpd/moodle.nix
+++ /dev/null
@@ -1,198 +0,0 @@
-{ config, lib, pkgs, serverInfo, php, ... }:
-
-with lib;
-
-let
-
-  httpd = serverInfo.serverConfig.package;
-
-  version24 = !versionOlder httpd.version "2.4";
-
-  allGranted = if version24 then ''
-    Require all granted
-  '' else ''
-    Order allow,deny
-    Allow from all
-  '';
-
-  moodleConfig = pkgs.writeText "config.php"
-    ''
-      <?php
-      unset($CFG);
-      global $CFG;
-      $CFG = new stdClass();
-      $CFG->dbtype    = '${config.dbType}';
-      $CFG->dblibrary = 'native';
-      $CFG->dbhost    = '${config.dbHost}';
-      $CFG->dbname    = '${config.dbName}';
-      $CFG->dbuser    = '${config.dbUser}';
-      $CFG->dbpass    = '${config.dbPassword}';
-      $CFG->prefix    = '${config.dbPrefix}';
-      $CFG->dboptions = array(
-          'dbpersist' => false,
-          'dbsocket'  => false,
-          'dbport'    => "${config.dbPort}",
-      );
-      $CFG->wwwroot   = '${config.wwwRoot}';
-      $CFG->dataroot  = '${config.dataRoot}';
-      $CFG->directorypermissions = 02777;
-      $CFG->admin = 'admin';
-      ${optionalString (config.debug.noEmailEver == true) ''
-        $CFG->noemailever = true;
-      ''}
-
-      ${config.extraConfig}
-      require_once(dirname(__FILE__) . '/lib/setup.php'); // Do not edit
-    '';
-  # Unpack Moodle and put the config file in its root directory.
-  moodleRoot = pkgs.stdenv.mkDerivation rec {
-    name= "moodle-2.8.10";
-
-    src = pkgs.fetchurl {
-      url = "https://download.moodle.org/stable28/${name}.tgz";
-      sha256 = "0c3r5081ipcwc9s6shakllnrkd589y2ln5z5m1q09l4h6a7cy4z2";
-    };
-
-    buildPhase =
-      ''
-      '';
-
-    installPhase =
-      ''
-        mkdir -p $out
-        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
-
-{
-
-  extraConfig =
-  ''
-    # this should be config.urlPrefix instead of /
-    Alias / ${moodleRoot}/
-    <Directory ${moodleRoot}>
-      DirectoryIndex index.php
-    </Directory>
-  '';
-
-  documentRoot = moodleRoot; # TODO: fix this, should be config.urlPrefix
-
-  enablePHP = true;
-
-  options = {
-
-    id = mkOption {
-      default = "main";
-      description = ''
-        A unique identifier necessary to keep multiple Moodle server
-        instances on the same machine apart.
-      '';
-    };
-
-    dbType = mkOption {
-      default = "postgres";
-      example = "mysql";
-      description = "Database type.";
-    };
-
-    dbName = mkOption {
-      default = "moodle";
-      description = "Name of the database that holds the Moodle data.";
-    };
-
-    dbHost = mkOption {
-      default = "localhost";
-      example = "10.0.2.2";
-      description = ''
-        The location of the database server.
-      '';
-    };
-
-    dbPort = mkOption {
-      default = ""; # use the default port
-      example = "12345";
-      description = ''
-        The port that is used to connect to the database server.
-      '';
-    };
-
-    dbUser = mkOption {
-      default = "moodle";
-      description = "The user name for accessing the database.";
-    };
-
-    dbPassword = mkOption {
-      default = "";
-      example = "password";
-      description = ''
-        The password of the database user.  Warning: this is stored in
-        cleartext in the Nix store!
-      '';
-    };
-
-    dbPrefix = mkOption {
-      default = "mdl_";
-      example = "my_other_mdl_";
-      description = ''
-        A prefix for each table, if multiple moodles should run in a single database.
-      '';
-    };
-
-    wwwRoot = mkOption {
-      type = types.string;
-      example = "http://my.machine.com/my-moodle";
-      description = ''
-        The full web address where moodle has been installed.
-      '';
-    };
-
-    dataRoot = mkOption {
-      default = "/var/lib/moodledata";
-      example = "/var/lib/moodledata";
-      description = ''
-        The data directory for moodle. Needs to be writable!
-      '';
-      type = types.path;
-      };
-
-
-    extraConfig = mkOption {
-      type = types.lines;
-      default = "";
-      example =
-        ''
-        '';
-      description = ''
-        Any additional text to be appended to Moodle's
-        configuration file.  This is a PHP script.
-      '';
-    };
-
-    debug = {
-      noEmailEver = mkOption {
-        default = false;
-	example = "true";
-	description = ''
-	  Set this to true to prevent Moodle from ever sending any email.
-	'';
-	};
-    };
-  };
-
-  startupScript = pkgs.writeScript "moodle_startup.sh" ''
-  echo "Checking for existence of ${config.dataRoot}"
-  if [ ! -e "${config.dataRoot}" ]
-  then
-    mkdir -p "${config.dataRoot}"
-    chown ${serverInfo.serverConfig.user}.${serverInfo.serverConfig.group} "${config.dataRoot}"
-  fi
-  '';
-
-}
diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
index 26f0bdec655..a5b6548d3c5 100644
--- a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
@@ -6,7 +6,7 @@ with lib;
 let
 
   # Upgrading? We have a test! nix-build ./nixos/tests/wordpress.nix
-  version = "4.7.1";
+  version = "4.7.2";
   fullversion = "${version}";
 
   # Our bare-bones wp-config.php file using the above settings
@@ -75,7 +75,7 @@ let
       owner = "WordPress";
       repo = "WordPress";
       rev = "${fullversion}";
-      sha256 = "1wb4f4zn55d23qi0whsfpbpcd4sjvzswgmni6f5rzrmlawq9ssgr";
+      sha256 = "0vph12708drf8ww0xd05hpdvbyy7n5gj9ca598lhdhy2i1j6wy32";
     };
     installPhase = ''
       mkdir -p $out
diff --git a/nixos/modules/services/web-servers/caddy.nix b/nixos/modules/services/web-servers/caddy.nix
index 619e0f90b12..a49838c876f 100644
--- a/nixos/modules/services/web-servers/caddy.nix
+++ b/nixos/modules/services/web-servers/caddy.nix
@@ -61,6 +61,7 @@ in
         User = "caddy";
         Group = "caddy";
         AmbientCapabilities = "cap_net_bind_service";
+        LimitNOFILE = 8192;
       };
     };
 
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index c9eacdd85dc..aa11a5d5e80 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -16,7 +16,20 @@ let
   ) cfg.virtualHosts;
   enableIPv6 = config.networking.enableIPv6;
 
-  configFile = pkgs.writeText "nginx.conf" ''
+  configFile = pkgs.runCommand "nginx.conf" {
+    inherit configFileUnformatted;
+    passAsFile = [ "configFileUnformatted" ];
+    # configFileUnformatted is created locally, therefore so should this be.
+    preferLocalBuild = true;
+    allowSubstitutes = false;
+  } ''
+    cp ${configFileUnformatted} nginx.conf
+    chmod u+w nginx.conf
+    ${pkgs.nginx-config-formatter}/bin/nginxfmt nginx.conf
+    cp nginx.conf $out
+  '';
+
+  configFileUnformatted = pkgs.writeText "nginx.unformatted.conf" ''
     user ${cfg.user} ${cfg.group};
     error_log stderr;
     daemon off;
@@ -403,7 +416,7 @@ in
         acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME) vhostsConfigs;
         acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = {
             user = cfg.user;
-            group = cfg.group;
+            group = lib.mkDefault cfg.group;
             webroot = vhostConfig.acmeRoot;
             extraDomains = genAttrs vhostConfig.serverAliases (alias: null);
             postRun = ''
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 144e4aada27..1f7a925ed05 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -18,9 +18,8 @@ in
   # determines the default: later modules (if enabled) are preferred.
   # E.g., if KDE is enabled, it supersedes xterm.
   imports = [
-    ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix ./kde5.nix
-    ./lumina.nix ./lxqt.nix ./enlightenment.nix ./gnome3.nix
-    ./kodi.nix
+    ./none.nix ./xterm.nix ./xfce.nix ./kde5.nix ./lumina.nix
+    ./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix
   ];
 
   options = {
diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
index 9b4caafe3b3..d908553ccdf 100644
--- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix
+++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
@@ -64,7 +64,10 @@ in
 
     security.wrappers.e_freqset.source = "${e.enlightenment.out}/bin/e_freqset";
 
-    services.xserver.exportConfiguration = true;
+    environment.etc = singleton
+      { source = "${pkgs.xkeyboard_config}/etc/X11/xkb";
+        target = "X11/xkb";
+      };
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.ubuntu_font_family ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 17e84b1d9a1..21453d1917e 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -78,7 +78,7 @@ in {
       };
 
       debug = mkEnableOption "gnome-session debug messages";
-    };  
+    };
 
     environment.gnome3.packageSet = mkOption {
       default = null;
@@ -86,7 +86,7 @@ in {
       description = "Which GNOME 3 package set to use.";
       apply = p: if p == null then pkgs.gnome3 else p;
     };
-    
+
     environment.gnome3.excludePackages = mkOption {
       default = [];
       example = literalExample "[ pkgs.gnome3.totem ]";
@@ -125,6 +125,9 @@ in {
     services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
     services.udev.packages = [ pkgs.gnome3.gnome_settings_daemon ];
 
+    # If gnome3 is installed, build vim for gtk3 too.
+    nixpkgs.config.vim.gui = "gtk3";
+
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ];
 
     services.xserver.desktopManager.session = singleton
diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix
deleted file mode 100644
index f810ffdfbb3..00000000000
--- a/nixos/modules/services/x11/desktop-managers/kde4.nix
+++ /dev/null
@@ -1,190 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  xcfg = config.services.xserver;
-  cfg = xcfg.desktopManager.kde4;
-  xorg = pkgs.xorg;
-  kde_workspace = config.services.xserver.desktopManager.kde4.kdeWorkspacePackage;
-
-  # Disable Nepomuk and Strigi by default.  As of KDE 4.7, they don't
-  # really work very well (e.g. searching files often fails to find
-  # files), segfault sometimes and consume significant resources.
-  # They can be re-enabled in the KDE System Settings under "Desktop
-  # Search".
-  disableNepomuk = pkgs.writeTextFile
-    { name = "nepomuk-config";
-      destination = "/share/config/nepomukserverrc";
-      text =
-        ''
-          [Basic Settings]
-          Start Nepomuk=false
-
-          [Service-nepomukstrigiservice]
-          autostart=false
-        '';
-    };
-
-  phononBackends = {
-    gstreamer = [
-      pkgs.phonon-backend-gstreamer
-      pkgs.gst_all.gstPluginsBase
-      pkgs.gst_all.gstPluginsGood
-      pkgs.gst_all.gstPluginsUgly
-      pkgs.gst_all.gstPluginsBad
-      pkgs.gst_all.gstFfmpeg # for mp3 playback
-      pkgs.gst_all.gstreamer # needed?
-    ];
-
-    vlc = [pkgs.phonon-backend-vlc];
-  };
-
-  phononBackendPackages = flip concatMap cfg.phononBackends
-    (name: attrByPath [name] (throw "unknown phonon backend `${name}'") phononBackends);
-
-in
-
-{
-  options = {
-
-    services.xserver.desktopManager.kde4 = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Enable the KDE 4 desktop environment.";
-      };
-
-      phononBackends = mkOption {
-        type = types.listOf types.str;
-        default = ["gstreamer"];
-        example = ["gstreamer" "vlc"];
-        description = "Which phonon multimedia backend kde should use";
-      };
-
-      kdeWorkspacePackage = mkOption {
-        internal = true;
-        default = pkgs.kde4.kde_workspace;
-        defaultText = "pkgs.kde4.kde_workspace";
-        type = types.package;
-        description = "Custom kde-workspace, used for NixOS rebranding.";
-      };
-
-      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).";
-      };
-    };
-  };
-
-
-  config = mkIf (xcfg.enable && cfg.enable) {
-
-    # If KDE 4 is enabled, make it the default desktop manager (unless
-    # overridden by the user's configuration).
-    # !!! doesn't work yet ("Multiple definitions. Only one is allowed
-    # for this option.")
-    # services.xserver.desktopManager.default = mkOverride 900 "kde4";
-
-    services.xserver.desktopManager.session = singleton
-      { name = "kde4";
-        bgSupport = true;
-        start =
-          ''
-            # The KDE icon cache is supposed to update itself
-            # automatically, but it uses the timestamp on the icon
-            # theme directory as a trigger.  Since in Nix the
-            # timestamp is always the same, this doesn't work.  So as
-            # a workaround, nuke the icon cache on login.  This isn't
-            # perfect, since it may require logging out after
-            # installing new applications to update the cache.
-            # See http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
-            rm -fv $HOME/.kde/cache-*/icon-cache.kcache
-
-            # Qt writes a weird ‘libraryPath’ line to
-            # ~/.config/Trolltech.conf that causes the KDE plugin
-            # paths of previous KDE invocations to be searched.
-            # Obviously using mismatching KDE libraries is potentially
-            # disastrous, so here we nuke references to the Nix store
-            # in Trolltech.conf.  A better solution would be to stop
-            # Qt from doing this wackiness in the first place.
-            if [ -e $HOME/.config/Trolltech.conf ]; then
-                sed -e '/nix\\store\|nix\/store/ d' -i $HOME/.config/Trolltech.conf
-            fi
-
-            # Load PulseAudio module for routing support.
-            # See http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
-            ${optionalString config.hardware.pulseaudio.enable ''
-              ${getBin config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
-            ''}
-
-            # Start KDE.
-            exec ${kde_workspace}/bin/startkde
-          '';
-      };
-
-    security.wrappers.kcheckpass.source = "${kde_workspace}/lib/kde4/libexec/kcheckpass";
-
-    environment.systemPackages =
-        [ pkgs.kde4.kdelibs
-
-          pkgs.kde4.kde_baseapps # Splitted kdebase
-          kde_workspace
-          pkgs.kde4.kde_runtime
-          pkgs.kde4.konsole
-          pkgs.kde4.kate
-
-          pkgs.kde4.kde_wallpapers # contains kdm's default background
-          pkgs.kde4.oxygen_icons
-
-          # Starts KDE's Polkit authentication agent.
-          pkgs.kde4.polkit_kde_agent
-
-          # Miscellaneous runtime dependencies.
-          pkgs.kde4.qt4 # needed for qdbus
-          pkgs.shared_mime_info
-          xorg.xmessage # so that startkde can show error messages
-          xorg.xset # used by startkde, non-essential
-          xorg.xauth # used by kdesu
-        ]
-      ++ optionals cfg.enablePIM
-        [ pkgs.kde4.kdepim_runtime
-          pkgs.kde4.akonadi
-          pkgs.mysql # used by akonadi
-        ]
-      ++ (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 (elem "gstreamer" cfg.phononBackends) {
-      GST_PLUGIN_SYSTEM_PATH = [ "/lib/gstreamer-0.10" ];
-    };
-
-    services.xserver.exportConfiguration = true;
-
-    # Enable helpful DBus services.
-    services.udisks2.enable = true;
-    services.upower.enable = config.powerManagement.enable;
-
-    security.pam.services.kde = { allowNullPassword = true; };
-
-  };
-
-}
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index 5874e080fd8..06f9f0a62ef 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -50,10 +50,6 @@ in
     })
 
     (mkIf (xcfg.enable && cfg.enable) {
-
-      warnings = optional config.services.xserver.desktopManager.kde4.enable
-        "KDE 4 should not be enabled at the same time as KDE 5";
-
       services.xserver.desktopManager.session = singleton {
         name = "kde5";
         bgSupport = true;
@@ -188,7 +184,10 @@ in
 
       environment.pathsToLink = [ "/share" ];
 
-      services.xserver.exportConfiguration = true;
+      environment.etc = singleton {
+        source = "${pkgs.xkeyboard_config}/etc/X11/xkb";
+        target = "X11/xkb";
+      };
 
       environment.variables =
         {
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index c0daf30d04e..e8b897fb605 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -1,5 +1,5 @@
 # This module declares the options to define a *display manager*, the
-# program responsible for handling X logins (such as xdm, kdm, gdb, or
+# program responsible for handling X logins (such as xdm, gdb, or
 # SLiM).  The display manager allows the user to select a *session
 # type*.  When the user logs in, the display manager starts the
 # *session script* ("xsession" below) to launch the selected session
@@ -32,6 +32,9 @@ let
     ''
       #! ${pkgs.bash}/bin/bash
 
+      # Handle being called by SDDM.
+      if test "''${1:0:1}" = / ; then eval exec $1 $2 ; fi
+
       ${optionalString cfg.displayManager.logToJournal ''
         if [ -z "$_DID_SYSTEMD_CAT" ]; then
           _DID_SYSTEMD_CAT=1 exec ${config.systemd.package}/bin/systemd-cat -t xsession -- "$0" "$@"
@@ -55,9 +58,6 @@ let
         fi
       ''}
 
-      # Handle being called by kdm.
-      if test "''${1:0:1}" = /; then eval exec "$1"; fi
-
       # Start PulseAudio if enabled.
       ${optionalString (config.hardware.pulseaudio.enable) ''
         ${optionalString (!config.hardware.pulseaudio.systemWide)
diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix
deleted file mode 100644
index 04701a1640c..00000000000
--- a/nixos/modules/services/x11/display-managers/kdm.nix
+++ /dev/null
@@ -1,158 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  dmcfg = config.services.xserver.displayManager;
-  cfg = dmcfg.kdm;
-
-  inherit (pkgs.kde4) kdebase_workspace;
-
-  defaultConfig =
-    ''
-      [Shutdown]
-      HaltCmd=${config.systemd.package}/sbin/shutdown -h now
-      RebootCmd=${config.systemd.package}/sbin/shutdown -r now
-      ${optionalString (config.system.boot.loader.id == "grub") ''
-        BootManager=${if config.boot.loader.grub.version == 2 then "Grub2" else "Grub"}
-      ''}
-
-      [X-*-Core]
-      Xrdb=${pkgs.xorg.xrdb}/bin/xrdb
-      SessionsDirs=${dmcfg.session.desktops}
-      Session=${dmcfg.session.script}
-      FailsafeClient=${pkgs.xterm}/bin/xterm
-
-      [X-:*-Core]
-      ServerCmd=${dmcfg.xserverBin} ${toString dmcfg.xserverArgs}
-      # KDM calls `rm' somewhere to clean up some temporary directory.
-      SystemPath=${pkgs.coreutils}/bin
-      # The default timeout (15) is too short in a heavily loaded boot process.
-      ServerTimeout=60
-      # Needed to prevent the X server from dying on logout and not coming back:
-      TerminateServer=true
-      ${optionalString (cfg.setupScript != "")
-      ''
-        Setup=${cfg.setupScript}
-      ''} 
-
-      [X-*-Greeter]
-      HiddenUsers=root,${concatStringsSep "," dmcfg.hiddenUsers}
-      PluginsLogin=${kdebase_workspace}/lib/kde4/kgreet_classic.so
-      ${optionalString (cfg.themeDirectory != null)
-      ''
-        UseTheme=true
-        Theme=${cfg.themeDirectory}
-      ''
-      }
-
-      ${optionalString (cfg.enableXDMCP)
-      ''
-        [Xdmcp]
-        Enable=true
-      ''}
-    '';
-
-  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
-    '';
-
-in
-
-{
-
-  ###### interface
-
-  options = {
-
-    services.xserver.displayManager.kdm = {
-
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to enable the KDE display manager.
-        '';
-      };
-
-      enableXDMCP = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to enable XDMCP, which allows remote logins.
-        '';
-      };
-
-      themeDirectory = mkOption {
-        type = types.nullOr types.str;
-        default = null;
-        description = ''
-          The path to a KDM theme directory. This theme
-          will be used by the KDM greeter.
-        '';
-      };
-
-      setupScript = mkOption {
-        type = types.lines;
-        default = "";
-        description = ''
-          The path to a KDM setup script. This script is run as root just
-          before KDM starts. Can be used for setting up
-          monitors with xrandr, for example.
-        '';
-      };
-
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        description = ''
-          Options appended to <filename>kdmrc</filename>, the
-          configuration file of KDM.
-        '';
-      };
-
-    };
-
-  };
-
-
-  ###### implementation
-
-  config = mkIf cfg.enable {
-
-    services.xserver.displayManager.slim.enable = false;
-
-    services.xserver.displayManager.job =
-      { execCmd =
-          ''
-            mkdir -m 0755 -p /var/lib/kdm
-            chown kdm /var/lib/kdm
-            ${(optionalString (config.system.boot.loader.id == "grub" && config.system.build.grub != null) "PATH=${config.system.build.grub}/sbin:$PATH ") +
-              "KDEDIRS=/run/current-system/sw exec ${kdebase_workspace}/bin/kdm -config ${kdmrc} -nodaemon -logfile /dev/stderr"}
-          '';
-        logsXsession = true;
-      };
-
-    security.pam.services.kde = { allowNullPassword = true; startSession = true; };
-
-    users.extraUsers = singleton
-      { name = "kdm";
-        uid = config.ids.uids.kdm;
-        description = "KDM user";
-      };
-
-    environment.systemPackages =
-      [ pkgs.kde4.kde_wallpapers ]; # contains kdm's default background
-
-  };
-
-}
diff --git a/nixos/modules/services/x11/terminal-server.nix b/nixos/modules/services/x11/terminal-server.nix
index 785394d9648..09a7f386876 100644
--- a/nixos/modules/services/x11/terminal-server.nix
+++ b/nixos/modules/services/x11/terminal-server.nix
@@ -16,18 +16,8 @@ with lib;
     services.xserver.enable = true;
     services.xserver.videoDrivers = [];
 
-    # Enable KDM.  Any display manager will do as long as it supports XDMCP.
-    services.xserver.displayManager.kdm.enable = true;
-    services.xserver.displayManager.kdm.enableXDMCP = true;
-    services.xserver.displayManager.kdm.extraConfig =
-      ''
-        [General]
-        # We're headless, so don't bother starting an X server.
-        StaticServers=
-
-        [Xdmcp]
-        Xaccess=${pkgs.writeText "Xaccess" "localhost"}
-      '';
+    # Enable GDM.  Any display manager will do as long as it supports XDMCP.
+    services.xserver.displayManager.gdm.enable = true;
 
     systemd.sockets.terminal-server =
       { description = "Terminal Server Socket";
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 8617a5fab03..7ac776571a0 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -459,21 +459,31 @@ in
           knownVideoDrivers;
       in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver));
 
+    nixpkgs.config.xorg = optionalAttrs (elem "vboxvideo" cfg.videoDrivers) { abiCompat = "1.18"; };
+
     assertions =
       [ { assertion = config.security.polkit.enable;
           message = "X11 requires Polkit to be enabled (‘security.polkit.enable = true’).";
         }
       ];
 
-    environment.etc = mkMerge [
-      (mkIf cfg.exportConfiguration {
-        "X11/xorg.conf".source = configFile;
-        "X11/xkb".source = cfg.xkbDir;
-      })
+    environment.etc =
+      (optionals cfg.exportConfiguration
+        [ { source = "${configFile}";
+            target = "X11/xorg.conf";
+          }
+          # -xkbdir command line option does not seems to be passed to xkbcomp.
+          { source = "${cfg.xkbDir}";
+            target = "X11/xkb";
+          }
+        ])
       # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5
-      (let cfgPath = "X11/xorg.conf.d/10-evdev.conf"; in
-        { "${cfgPath}".source = xorg.xf86inputevdev.out + "/share" + cfgPath; })
-    ];
+      ++ (let cfgPath = "/X11/xorg.conf.d/10-evdev.conf"; in
+        [{
+          source = xorg.xf86inputevdev.out + "/share" + cfgPath;
+          target = cfgPath;
+        }]
+      );
 
     environment.systemPackages =
       [ xorg.xorgserver.out
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index 0c08375da64..84c23bed3e3 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -45,6 +45,9 @@ let
 
         ln -s ${kernelPath} $out/kernel
         ln -s ${config.system.modulesTree} $out/kernel-modules
+        ${optionalString (pkgs.stdenv.platform.kernelDTB or false) ''
+          ln -s ${config.boot.kernelPackages.kernel}/dtbs $out/dtbs
+        ''}
 
         echo -n "$kernelParams" > $out/kernel-params
 
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index 294fc1988e9..23b970186a3 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -53,12 +53,14 @@ let
       inherit (args) devices;
       inherit (efi) canTouchEfiVariables;
       inherit (cfg)
-        version extraConfig extraPerEntryConfig extraEntries forceInstall 
+        version extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber
         extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels
         default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios;
       path = (makeBinPath ([
         pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfs-progs
-        pkgs.utillinux ] ++ (if cfg.efiSupport && (cfg.version == 2) then [pkgs.efibootmgr ] else [])
+        pkgs.utillinux ]
+        ++ (optional (cfg.efiSupport && (cfg.version == 2)) pkgs.efibootmgr)
+        ++ (optionals cfg.useOSProber [pkgs.busybox pkgs.os-prober])
       )) + ":" + (makeSearchPathOutput "bin" "sbin" [
         pkgs.mdadm pkgs.utillinux
       ]);
@@ -265,6 +267,14 @@ in
         '';
       };
 
+      useOSProber = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          If set to true, append entries for other OSs detected by os-prober.
+        '';
+      };
+
       splashImage = mkOption {
         type = types.nullOr types.path;
         example = literalExample "./my-background.png";
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index 24442ca12a3..c9a51288747 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -256,8 +256,6 @@ else {
         # ‘grub-reboot’ sets a one-time saved entry, which we process here and
         # then delete.
         if [ \"\${next_entry}\" ]; then
-          # FIXME: KDM expects the next line to be present.
-          set default=\"\${saved_entry}\"
           set default=\"\${next_entry}\"
           set next_entry=
           save_env next_entry
@@ -426,10 +424,17 @@ if ($extraPrepareConfig ne "") {
   system((get("shell"), "-c", $extraPrepareConfig));
 }
 
-# Atomically update the GRUB config.
+# write the GRUB config.
 my $confFile = $grubVersion == 1 ? "$bootPath/grub/menu.lst" : "$bootPath/grub/grub.cfg";
 my $tmpFile = $confFile . ".tmp";
 writeFile($tmpFile, $conf);
+
+# Append entries detected by os-prober
+if (get("useOSProber") eq "true") {
+    system(get("shell"), "-c", "pkgdatadir=$grub/share/grub $grub/etc/grub.d/30_os-prober >> $tmpFile");
+}
+
+# Atomically switch to the new config
 rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile\n";
 
 
diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder.sh b/nixos/modules/system/boot/loader/raspberrypi/builder.sh
index ccb88ca1c52..f627d093eaf 100644
--- a/nixos/modules/system/boot/loader/raspberrypi/builder.sh
+++ b/nixos/modules/system/boot/loader/raspberrypi/builder.sh
@@ -61,12 +61,13 @@ addEntry() {
 
     local kernel=$(readlink -f $path/kernel)
     local initrd=$(readlink -f $path/initrd)
+    local dtb_path=$(readlink -f $path/kernel-modules/dtbs)
 
     if test -n "@copyKernels@"; then
         copyToKernelsDir $kernel; kernel=$result
         copyToKernelsDir $initrd; initrd=$result
     fi
-    
+
     echo $(readlink -f $path) > $outdir/$generation-system
     echo $(readlink -f $path/init) > $outdir/$generation-init
     cp $path/kernel-params $outdir/$generation-cmdline.txt
@@ -80,6 +81,11 @@ addEntry() {
         copyForced $kernel /boot/kernel7.img
       fi
       copyForced $initrd /boot/initrd
+      for dtb in $dtb_path/bcm*.dtb; do
+        dst="/boot/$(basename $dtb)"
+        copyForced $dtb "$dst"
+        filesCopied[$dst]=1
+      done
       cp "$(readlink -f "$path/init")" /boot/nixos-init
       echo "`cat $path/kernel-params` init=$path/init" >/boot/cmdline.txt
 
@@ -108,8 +114,8 @@ copyForced $fwdir/start_cd.elf  /boot/start_cd.elf
 copyForced $fwdir/start_db.elf  /boot/start_db.elf
 copyForced $fwdir/start_x.elf   /boot/start_x.elf
 
-# Remove obsolete files from /boot/old.
-for fn in /boot/old/*linux* /boot/old/*initrd*; do
+# Remove obsolete files from /boot and /boot/old.
+for fn in /boot/old/*linux* /boot/old/*initrd-initrd* /boot/bcm*.dtb; do
     if ! test "${filesCopied[$fn]}" = 1; then
         rm -vf -- "$fn"
     fi
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
index eb8ea613097..f246d04284c 100644
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
+++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
@@ -33,7 +33,7 @@ in
 
     boot.loader.raspberryPi.version = mkOption {
       default = 2;
-      type = types.enum [ 1 2 ];
+      type = types.enum [ 1 2 3 ];
       description = ''
       '';
     };
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index b828ad53dc5..be70bdbf0a9 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -667,8 +667,10 @@ in
 
   config = mkIf config.systemd.network.enable {
 
-    systemd.additionalUpstreamSystemUnits =
-      [ "systemd-networkd.service" "systemd-networkd-wait-online.service" ];
+    systemd.additionalUpstreamSystemUnits = [
+      "systemd-networkd.service" "systemd-networkd-wait-online.service"
+      "org.freedesktop.network1.busname"
+    ];
 
     systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
       // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix
index 4b7c545dcc0..a3fb733c289 100644
--- a/nixos/modules/system/boot/resolved.nix
+++ b/nixos/modules/system/boot/resolved.nix
@@ -71,7 +71,9 @@ in
 
   config = mkIf cfg.enable {
 
-    systemd.additionalUpstreamSystemUnits = [ "systemd-resolved.service" ];
+    systemd.additionalUpstreamSystemUnits = [
+      "systemd-resolved.service" "org.freedesktop.resolve1.busname"
+    ];
 
     systemd.services.systemd-resolved = {
       wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix
index 997770b8bec..7dbf3b25cdb 100644
--- a/nixos/modules/system/boot/systemd-lib.nix
+++ b/nixos/modules/system/boot/systemd-lib.nix
@@ -159,7 +159,13 @@ rec {
         fi
       done
 
-      # Created .wants and .requires symlinks from the wantedBy and
+      # Create service aliases from aliases option.
+      ${concatStrings (mapAttrsToList (name: unit:
+          concatMapStrings (name2: ''
+            ln -sfn '${name}' $out/'${name2}'
+          '') unit.aliases) units)}
+
+      # Create .wants and .requires symlinks from the wantedBy and
       # requiredBy options.
       ${concatStrings (mapAttrsToList (name: unit:
           concatMapStrings (name2: ''
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 69af2398148..904e41b019f 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -52,6 +52,12 @@ in rec {
       description = "Units that want (i.e. depend on) this unit.";
     };
 
+    aliases = mkOption {
+      default = [];
+      type = types.listOf types.str;
+      description = "Aliases of that unit.";
+    };
+
   };
 
   concreteUnitOptions = sharedOptions // {
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index a2ee5166971..904404e1e47 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -17,6 +17,7 @@ let
       "busnames.target"
       "sysinit.target"
       "sockets.target"
+      "exit.target"
       "graphical.target"
       "multi-user.target"
       "network.target"
@@ -41,11 +42,14 @@ let
       "systemd-udevd.service"
       "systemd-udev-settle.service"
       "systemd-udev-trigger.service"
+      # hwdb.bin is managed by NixOS
+      # "systemd-hwdb-update.service"
 
       # Consoles.
       "getty.target"
       "getty@.service"
       "serial-getty@.service"
+      "console-getty.service"
       "container-getty@.service"
       "systemd-vconsole-setup.service"
 
@@ -58,7 +62,6 @@ let
       # Login stuff.
       "systemd-logind.service"
       "autovt@.service"
-      #"systemd-vconsole-setup.service"
       "systemd-user-sessions.service"
       "dbus-org.freedesktop.login1.service"
       "dbus-org.freedesktop.machine1.service"
@@ -72,6 +75,7 @@ let
       "systemd-journal-flush.service"
       "systemd-journal-gatewayd.socket"
       "systemd-journal-gatewayd.service"
+      "systemd-journal-catalog-update.service"
       "systemd-journald-audit.socket"
       "systemd-journald-dev-log.socket"
       "syslog.socket"
@@ -104,6 +108,7 @@ let
       "systemd-random-seed.service"
       "systemd-backlight@.service"
       "systemd-rfkill.service"
+      "systemd-rfkill.socket"
 
       # Hibernate / suspend.
       "hibernate.target"
@@ -111,8 +116,8 @@ let
       "sleep.target"
       "hybrid-sleep.target"
       "systemd-hibernate.service"
-      "systemd-suspend.service"
       "systemd-hybrid-sleep.service"
+      "systemd-suspend.service"
 
       # Reboot stuff.
       "reboot.target"
@@ -136,10 +141,10 @@ let
 
       # Slices / containers.
       "slices.target"
-      "-.slice"
       "system.slice"
       "user.slice"
       "machine.slice"
+      "machines.target"
       "systemd-machined.service"
       "systemd-nspawn@.service"
 
@@ -162,12 +167,12 @@ let
       "systemd-localed.service"
       "systemd-hostnamed.service"
       "systemd-binfmt.service"
+      "systemd-exit.service"
     ]
     ++ cfg.additionalUpstreamSystemUnits;
 
   upstreamSystemWants =
-    [ #"basic.target.wants"
-      "sysinit.target.wants"
+    [ "sysinit.target.wants"
       "sockets.target.wants"
       "local-fs.target.wants"
       "multi-user.target.wants"
@@ -176,11 +181,18 @@ let
 
   upstreamUserUnits =
     [ "basic.target"
+      "bluetooth.target"
+      "busnames.target"
       "default.target"
       "exit.target"
+      "graphical-session-pre.target"
+      "graphical-session.target"
       "paths.target"
+      "printer.target"
       "shutdown.target"
+      "smartcard.target"
       "sockets.target"
+      "sound.target"
       "systemd-exit.service"
       "timers.target"
     ];
@@ -301,7 +313,7 @@ let
     '';
 
   targetToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text =
         ''
           [Unit]
@@ -310,7 +322,7 @@ let
     };
 
   serviceToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Service]
@@ -330,7 +342,7 @@ let
     };
 
   socketToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Socket]
@@ -340,7 +352,7 @@ let
     };
 
   timerToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Timer]
@@ -349,7 +361,7 @@ let
     };
 
   pathToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Path]
@@ -358,7 +370,7 @@ let
     };
 
   mountToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Mount]
@@ -367,7 +379,7 @@ let
     };
 
   automountToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Automount]
@@ -376,7 +388,7 @@ let
     };
 
   sliceToUnit = name: def:
-    { inherit (def) wantedBy requiredBy enable;
+    { inherit (def) aliases wantedBy requiredBy enable;
       text = commonUnitText def +
         ''
           [Slice]
@@ -741,7 +753,8 @@ in
 
         # Keep a persistent journal. Note that systemd-tmpfiles will
         # set proper ownership/permissions.
-        mkdir -m 0700 -p /var/log/journal
+        # FIXME: revert to 0700 with systemd v233.
+        mkdir -m 0750 -p /var/log/journal
       '';
 
     users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index 49ba66ad50a..8bd35385739 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -216,7 +216,7 @@ in
 
     environment.etc.fstab.text =
       let
-        fsToSkipCheck = [ "none" "btrfs" "zfs" "tmpfs" "nfs" "vboxsf" ];
+        fsToSkipCheck = [ "none" "btrfs" "zfs" "tmpfs" "nfs" "vboxsf" "glusterfs" ];
         skipCheck = fs: fs.noCheck || fs.device == "none" || builtins.elem fs.fsType fsToSkipCheck;
       in ''
         # This is a generated file.  Do not edit!
diff --git a/nixos/modules/tasks/filesystems/glusterfs.nix b/nixos/modules/tasks/filesystems/glusterfs.nix
new file mode 100644
index 00000000000..e8c7fa8efba
--- /dev/null
+++ b/nixos/modules/tasks/filesystems/glusterfs.nix
@@ -0,0 +1,11 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  config = mkIf (any (fs: fs == "glusterfs") config.boot.supportedFilesystems) {
+
+    system.fsPackages = [ pkgs.glusterfs ];
+
+  };
+}
diff --git a/nixos/modules/tasks/filesystems/nfs.nix b/nixos/modules/tasks/filesystems/nfs.nix
index e9a7ccc721a..73cf18384bd 100644
--- a/nixos/modules/tasks/filesystems/nfs.nix
+++ b/nixos/modules/tasks/filesystems/nfs.nix
@@ -24,6 +24,8 @@ let
     Method = nsswitch
   '';
 
+  nfsConfFile = pkgs.writeText "nfs.conf" cfg.extraConfig;
+
   cfg = config.services.nfs;
 
 in
@@ -32,23 +34,12 @@ in
   ###### interface
 
   options = {
-
     services.nfs = {
-      statdPort = mkOption {
-        default = null;
-        example = 4000;
-        description = ''
-          Use a fixed port for <command>rpc.statd</command>. This is
-          useful if the NFS server is behind a firewall.
-        '';
-      };
-      lockdPort = mkOption {
-        default = null;
-        example = 4001;
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
         description = ''
-          Use a fixed port for the NFS lock manager kernel module
-          (<literal>lockd/nlockmgr</literal>).  This is useful if the
-          NFS server is behind a firewall.
+          Extra nfs-utils configuration.
         '';
       };
     };
@@ -62,69 +53,49 @@ in
 
     system.fsPackages = [ pkgs.nfs-utils ];
 
-    boot.extraModprobeConfig = mkIf (cfg.lockdPort != null) ''
-      options lockd nlm_udpport=${toString cfg.lockdPort} nlm_tcpport=${toString cfg.lockdPort}
-    '';
-
-    boot.kernelModules = [ "sunrpc" ];
-
     boot.initrd.kernelModules = mkIf inInitrd [ "nfs" ];
 
-    # FIXME: should use upstream units from nfs-utils.
-
-    systemd.services.statd =
-      { description = "NFSv3 Network Status Monitor";
+    systemd.packages = [ pkgs.nfs-utils ];
+    systemd.generator-packages = [ pkgs.nfs-utils ];
 
-        path = [ pkgs.nfs-utils pkgs.sysvtools pkgs.utillinux ];
+    environment.etc = {
+      "idmapd.conf".source = idmapdConfFile;
+      "nfs.conf".source = nfsConfFile;
+    };
 
-        wants = [ "remote-fs-pre.target" ];
-        before = [ "remote-fs-pre.target" ];
-        wantedBy = [ "remote-fs.target" ];
-        requires = [ "basic.target" "rpcbind.service" ];
-        after = [ "basic.target" "rpcbind.service" ];
+    systemd.services.nfs-blkmap =
+      { restartTriggers = [ nfsConfFile ];
+      };
 
-        unitConfig.DefaultDependencies = false; # don't stop during shutdown
+    systemd.targets.nfs-client =
+      { wantedBy = [ "multi-user.target" "remote-fs.target" ];
+      };
 
-        preStart =
-          ''
-            mkdir -p ${nfsStateDir}/sm
-            mkdir -p ${nfsStateDir}/sm.bak
-            sm-notify -d
-          '';
+    systemd.services.nfs-idmapd =
+      { restartTriggers = [ idmapdConfFile ];
+      };
 
-        serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = ''
-          @${pkgs.nfs-utils}/sbin/rpc.statd rpc.statd --no-notify \
-              ${if cfg.statdPort != null then "-p ${toString cfg.statdPort}" else ""}
-        '';
-        serviceConfig.Restart = "always";
+    systemd.services.nfs-mountd =
+      { restartTriggers = [ nfsConfFile ];
+        enable = mkDefault false;
       };
 
-    systemd.services.idmapd =
-      { description = "NFSv4 ID Mapping Daemon";
+    systemd.services.nfs-server =
+      { restartTriggers = [ nfsConfFile ];
+        enable = mkDefault false;
+      };
 
-        path = [ pkgs.sysvtools pkgs.utillinux ];
+    systemd.services.rpc-gssd =
+      { restartTriggers = [ nfsConfFile ];
+      };
 
-        wants = [ "remote-fs-pre.target" ];
-        before = [ "remote-fs-pre.target" ];
-        wantedBy = [ "remote-fs.target" ];
-        requires = [ "rpcbind.service" ];
-        after = [ "rpcbind.service" ];
+    systemd.services.rpc-statd =
+      { restartTriggers = [ nfsConfFile ];
 
         preStart =
           ''
-            mkdir -p ${rpcMountpoint}
-            mount -t rpc_pipefs rpc_pipefs ${rpcMountpoint}
+            mkdir -p /var/lib/nfs/{sm,sm.bak}
           '';
-
-        postStop =
-          ''
-            umount ${rpcMountpoint}
-          '';
-
-        serviceConfig.Type = "forking";
-        serviceConfig.ExecStart = "@${pkgs.nfs-utils}/sbin/rpc.idmapd rpc.idmapd -c ${idmapdConfFile}";
-        serviceConfig.Restart = "always";
       };
 
   };
diff --git a/nixos/modules/tasks/kbd.nix b/nixos/modules/tasks/kbd.nix
index e001832ec2e..0af376a90bc 100644
--- a/nixos/modules/tasks/kbd.nix
+++ b/nixos/modules/tasks/kbd.nix
@@ -100,15 +100,12 @@ in
       }
 
       (mkIf (!config.boot.earlyVconsoleSetup) {
-        # This is identical to the systemd-vconsole-setup.service unit
-        # shipped with systemd, except that it uses /dev/tty1 instead of
-        # /dev/tty0 to prevent putting the X server in non-raw mode, and
-        # it has a restart trigger.
         systemd.services."systemd-vconsole-setup" =
           { wantedBy = [ "sysinit.target" ];
             before = [ "display-manager.service" ];
             after = [ "systemd-udev-settle.service" ];
             restartTriggers = [ vconsoleConf kbdEnv ];
+            restartIfChanged = false; # fails when tty is inactive
           };
       })
 
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index c50ea5c7964..062598de83e 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -102,17 +102,25 @@ in
                 EOF
 
                 # Set the default gateway.
-                ${optionalString (cfg.defaultGateway != null && cfg.defaultGateway != "") ''
+                ${optionalString (cfg.defaultGateway != null && cfg.defaultGateway.address != "") ''
                   # FIXME: get rid of "|| true" (necessary to make it idempotent).
-                  ip route add default via "${cfg.defaultGateway}" ${
+                  ip route add default ${optionalString (cfg.defaultGateway.metric != null)
+                      "metric ${toString cfg.defaultGateway.metric}"
+                    } via "${cfg.defaultGateway.address}" ${
                     optionalString (cfg.defaultGatewayWindowSize != null)
-                      "window ${toString cfg.defaultGatewayWindowSize}"} || true
+                      "window ${toString cfg.defaultGatewayWindowSize}"} ${
+                    optionalString (cfg.defaultGateway.interface != null)
+                      "dev ${cfg.defaultGateway.interface}"} || true
                 ''}
-                ${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6 != "") ''
+                ${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "") ''
                   # FIXME: get rid of "|| true" (necessary to make it idempotent).
-                  ip -6 route add ::/0 via "${cfg.defaultGateway6}" ${
+                  ip -6 route add ::/0 ${optionalString (cfg.defaultGateway6.metric != null)
+                      "metric ${toString cfg.defaultGateway6.metric}"
+                    } via "${cfg.defaultGateway6.address}" ${
                     optionalString (cfg.defaultGatewayWindowSize != null)
-                      "window ${toString cfg.defaultGatewayWindowSize}"} || true
+                      "window ${toString cfg.defaultGatewayWindowSize}"} ${
+                    optionalString (cfg.defaultGateway6.interface != null)
+                      "dev ${cfg.defaultGateway6.interface}"} || true
                 ''}
               '';
           };
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index 974041d7e1a..cd599d8b894 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -38,6 +38,12 @@ in
     } {
       assertion = cfg.vswitches == {};
       message = "networking.vswichtes are not supported by networkd.";
+    } {
+      assertion = cfg.defaultGateway == null || cfg.defaultGateway.interface == null;
+      message = "networking.defaultGateway.interface is not supported by networkd.";
+    } {
+      assertion = cfg.defaultGateway6 == null || cfg.defaultGateway6.interface == null;
+      message = "networking.defaultGateway6.interface is not supported by networkd.";
     } ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: {
       assertion = !rstp;
       message = "networking.bridges.${n}.rstp is not supported by networkd.";
@@ -56,9 +62,9 @@ in
         genericNetwork = override: {
           DHCP = override (dhcpStr cfg.useDHCP);
         } // optionalAttrs (cfg.defaultGateway != null) {
-          gateway = override [ cfg.defaultGateway ];
+          gateway = override [ cfg.defaultGateway.address ];
         } // optionalAttrs (cfg.defaultGateway6 != null) {
-          gateway = override [ cfg.defaultGateway6 ];
+          gateway = override [ cfg.defaultGateway6.address ];
         } // optionalAttrs (domains != [ ]) {
           domains = override domains;
         };
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index dc77a6a40f8..28c7b358093 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -116,6 +116,35 @@ let
       };
     };
 
+  gatewayCoerce = address: { inherit address; };
+
+  gatewayOpts = { ... }: {
+
+    options = {
+
+      address = mkOption {
+        type = types.str;
+        description = "The default gateway address.";
+      };
+
+      interface = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "enp0s3";
+        description = "The default gateway interface.";
+      };
+
+      metric = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        example = 42;
+        description = "The default gateway metric/preference.";
+      };
+
+    };
+
+  };
+
   interfaceOpts = { name, ... }: {
 
     options = {
@@ -327,19 +356,27 @@ in
 
     networking.defaultGateway = mkOption {
       default = null;
-      example = "131.211.84.1";
-      type = types.nullOr types.str;
+      example = {
+        address = "131.211.84.1";
+        device = "enp3s0";
+      };
+      type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts));
       description = ''
-        The default gateway.  It can be left empty if it is auto-detected through DHCP.
+        The default gateway. It can be left empty if it is auto-detected through DHCP.
+        It can be specified as a string or an option set along with a network interface.
       '';
     };
 
     networking.defaultGateway6 = mkOption {
       default = null;
-      example = "2001:4d0:1e04:895::1";
-      type = types.nullOr types.str;
+      example = {
+        address = "2001:4d0:1e04:895::1";
+        device = "enp3s0";
+      };
+      type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts));
       description = ''
-        The default ipv6 gateway.  It can be left empty if it is auto-detected through DHCP.
+        The default ipv6 gateway. It can be left empty if it is auto-detected through DHCP.
+        It can be specified as a string or an option set along with a network interface.
       '';
     };
 
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index 099ead3d846..7f5b55d5cca 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -123,15 +123,6 @@ let kernel = config.boot.kernelPackages.kernel; in
     users.extraUsers.root.initialHashedPassword = mkOverride 150 "";
 
     services.xserver.displayManager.logToJournal = true;
-
-    # Bump kdm's X server start timeout to account for heavily loaded
-    # VM host systems.
-    services.xserver.displayManager.kdm.extraConfig =
-      ''
-        [X-:*-Core]
-        ServerTimeout=240
-      '';
-
   };
 
 }
diff --git a/nixos/modules/virtualisation/azure-image.nix b/nixos/modules/virtualisation/azure-image.nix
index 9fac543b03d..33f84986cac 100644
--- a/nixos/modules/virtualisation/azure-image.nix
+++ b/nixos/modules/virtualisation/azure-image.nix
@@ -23,7 +23,7 @@ in
           postVM =
             ''
               mkdir -p $out
-              ${pkgs.vmTools.qemu-220}/bin/qemu-img convert -f raw -O vpc $diskImage $out/disk.vhd
+              ${pkgs.vmTools.qemu-220}/bin/qemu-img convert -f raw -o subformat=fixed -O vpc $diskImage $out/disk.vhd
               rm $diskImage
             '';
           diskImageBase = "nixos-image-${config.system.nixosLabel}-${pkgs.stdenv.system}.raw";
diff --git a/nixos/modules/virtualisation/ecs-agent.nix b/nixos/modules/virtualisation/ecs-agent.nix
new file mode 100644
index 00000000000..18e45e0b845
--- /dev/null
+++ b/nixos/modules/virtualisation/ecs-agent.nix
@@ -0,0 +1,45 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.ecs-agent;
+in {
+  options.services.ecs-agent = {
+    enable = mkEnableOption "Amazon ECS agent";
+
+    package = mkOption {
+      type = types.path;
+      description = "The ECS agent package to use";
+      default = pkgs.ecs-agent;
+    };
+
+    extra-environment = mkOption {
+      type = types.attrsOf types.str;
+      description = "The environment the ECS agent should run with. See the ECS agent documentation for keys that work here.";
+      default = {};
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    # This service doesn't run if docker isn't running, and unlike potentially remote services like e.g., postgresql, docker has
+    # to be running locally so `docker.enable` will always be set if the ECS agent is enabled.
+    virtualisation.docker.enable = true;
+
+    systemd.services.ecs-agent = {
+      inherit (cfg.package.meta) description;
+      after    = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      environment = cfg.extra-environment;
+
+      script = ''
+        if [ ! -z "$ECS_DATADIR" ]; then
+          mkdir -p "$ECS_DATADIR"
+        fi
+        ${cfg.package.bin}/bin/agent
+      '';
+    };
+  };
+}
+
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 586f5d9c0a3..56a05028b1d 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -440,13 +440,20 @@ in
         ${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} =
           { device = "store";
             fsType = "9p";
-            options = [ "trans=virtio" "version=9p2000.L" "veryloose" ];
+            options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
             neededForBoot = true;
           };
+        "/tmp" = mkIf config.boot.tmpOnTmpfs
+          { device = "tmpfs";
+            fsType = "tmpfs";
+            neededForBoot = true;
+            # Sync with systemd's tmp.mount;
+            options = [ "mode=1777" "strictatime" "nosuid" "nodev" ];
+          };
         "/tmp/xchg" =
           { device = "xchg";
             fsType = "9p";
-            options = [ "trans=virtio" "version=9p2000.L" "veryloose" ];
+            options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
             neededForBoot = true;
           };
         "/tmp/shared" =
diff --git a/nixos/modules/virtualisation/vmware-guest.nix b/nixos/modules/virtualisation/vmware-guest.nix
index ac5f87817fe..ce1224a8f13 100644
--- a/nixos/modules/virtualisation/vmware-guest.nix
+++ b/nixos/modules/virtualisation/vmware-guest.nix
@@ -4,12 +4,19 @@ with lib;
 
 let
   cfg = config.services.vmwareGuest;
-  open-vm-tools = pkgs.open-vm-tools;
+  open-vm-tools = if cfg.headless then pkgs.open-vm-tools-headless else pkgs.open-vm-tools;
   xf86inputvmmouse = pkgs.xorg.xf86inputvmmouse;
 in
 {
   options = {
-    services.vmwareGuest.enable = mkEnableOption "VMWare Guest Support";
+    services.vmwareGuest = {
+      enable = mkEnableOption "VMWare Guest Support";
+      headless = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to disable X11-related features.";
+      };
+    };
   };
 
   config = mkIf cfg.enable {
@@ -28,7 +35,7 @@ in
 
     environment.etc."vmware-tools".source = "${pkgs.open-vm-tools}/etc/vmware-tools/*";
 
-    services.xserver = {
+    services.xserver = mkIf (!cfg.headless) {
       videoDrivers = mkOverride 50 [ "vmware" ];
       modules = [ xf86inputvmmouse ];