about summary refs log tree commit diff
path: root/nixos/modules/services
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/services
parent128bdac94fe8173845e162c61ddb83cb4b8ed8de (diff)
parent486b9be579fc1f046671ddaf1157f084ba956bdd (diff)
downloadnixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar
nixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.gz
nixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.bz2
nixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.lz
nixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.xz
nixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.tar.zst
nixlib-9e36a58649199a16a15cba3c78966ab0538a6fd7.zip
Merging against upstream master
Diffstat (limited to 'nixos/modules/services')
-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
50 files changed, 1547 insertions, 993 deletions
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index 029b11ad98b7..a82802c32662 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 a40be4f546ea..512e09eb8041 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 000000000000..430fd4e53f1c
--- /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 e03f6046de8e..89f09ed08449 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 2c271b328179..de0d48032113 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 000000000000..ff73c99a6537
--- /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 8ddb9ef9c53b..d651ccaa5776 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 000000000000..38d0a3a1d752
--- /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 cdde41446224..caaa87b94d61 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 000000000000..021ee02782d2
--- /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 1fc3a5cc8691..36db4fb96606 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 09e5c4fe1ff1..ca8fc06e4835 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 d0e9b839e754..df7b9be0db50 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 000000000000..b04959a9686a
--- /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 ca82a733f6fc..d28c5dc7af85 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 b9e4015c2380..97806d5d83eb 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 000000000000..a2f2c0339515
--- /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 d43147a16f31..e6e04248854e 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 ddc7258ce0b4..7d127145101b 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 5c71a1d8ddae..514204db33fa 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 f2ff11633b1b..9bf266b38054 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 a10851c16523..12c2677c3368 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 f17f8c832ee4..b64929960576 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 34b731ad35c9..243cd04c96c2 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 abb7a4e9137c..c5b27350b3c2 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 3866b216f8ef..c87e738d2a23 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 83fc1ec66679..9df9f67cde83 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 da6487dbd499..4864ecf3f92f 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 edcc12170b20..9b06cccca79e 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 000000000000..a47a78f1005e
--- /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 eef1e8e8cd88..cddcb09054e0 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 b29db58af99b..b852e4e6dc86 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 0c459fb1dd0c..31d11548f195 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 000000000000..49b5c935267b
--- /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 e267fed27955..e267fed27955 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 fae5a55c5cef..33bc890a78c8 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 dc0ca501a484..ed77e0844769 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 d525348d5c7e..000000000000
--- 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 26f0bdec6559..a5b6548d3c53 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 619e0f90b124..a49838c876f9 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 c9eacdd85dcd..aa11a5d5e80a 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 144e4aada277..1f7a925ed054 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 9b4caafe3b39..d908553ccdf8 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 17e84b1d9a16..21453d1917e8 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 f810ffdfbb34..000000000000
--- 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 5874e080fd83..06f9f0a62ef8 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 c0daf30d04eb..e8b897fb6050 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 04701a1640cc..000000000000
--- 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 785394d9648c..09a7f386876f 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 8617a5fab03f..7ac776571a01 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