about summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/config/debug-info.nix2
-rw-r--r--nixos/modules/config/timezone.nix5
-rw-r--r--nixos/modules/hardware/video/amdgpu-pro.nix56
-rw-r--r--nixos/modules/installer/tools/auto-upgrade.nix2
-rw-r--r--nixos/modules/misc/ids.nix2
-rw-r--r--nixos/modules/module-list.nix17
-rw-r--r--nixos/modules/programs/oblogout.nix160
-rw-r--r--nixos/modules/programs/vim.nix24
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/security/acme.xml21
-rw-r--r--nixos/modules/security/audit.nix6
-rw-r--r--nixos/modules/security/ca.nix28
-rw-r--r--nixos/modules/security/grsecurity.nix6
-rw-r--r--nixos/modules/services/audio/mpd.nix2
-rw-r--r--nixos/modules/services/backup/bacula.nix1
-rw-r--r--nixos/modules/services/databases/mysql.nix3
-rw-r--r--nixos/modules/services/databases/neo4j.nix92
-rw-r--r--nixos/modules/services/databases/openldap.nix9
-rw-r--r--nixos/modules/services/desktops/gnome3/evolution-data-server.nix2
-rw-r--r--nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix44
-rw-r--r--nixos/modules/services/desktops/gnome3/gvfs.nix2
-rw-r--r--nixos/modules/services/desktops/gnome3/tracker.nix2
-rw-r--r--nixos/modules/services/editors/emacs.xml56
-rw-r--r--nixos/modules/services/hardware/brltty.nix2
-rw-r--r--nixos/modules/services/hardware/tlp.nix2
-rw-r--r--nixos/modules/services/mail/dovecot.nix2
-rw-r--r--nixos/modules/services/mail/opensmtpd.nix20
-rw-r--r--nixos/modules/services/misc/bepasty.nix2
-rw-r--r--nixos/modules/services/misc/docker-registry.nix66
-rw-r--r--nixos/modules/services/misc/errbot.nix101
-rw-r--r--nixos/modules/services/misc/gitlab.nix1
-rw-r--r--nixos/modules/services/misc/nix-gc.nix2
-rw-r--r--nixos/modules/services/misc/nix-optimise.nix2
-rw-r--r--nixos/modules/services/misc/redmine.nix2
-rw-r--r--nixos/modules/services/misc/taskserver/default.nix2
-rw-r--r--nixos/modules/services/monitoring/bosun.nix2
-rw-r--r--nixos/modules/services/monitoring/graphite.nix2
-rw-r--r--nixos/modules/services/monitoring/munin.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/default.nix4
-rw-r--r--nixos/modules/services/monitoring/riemann-tools.nix1
-rw-r--r--nixos/modules/services/monitoring/zabbix-agent.nix1
-rw-r--r--nixos/modules/services/network-filesystems/cachefilesd.nix59
-rw-r--r--nixos/modules/services/network-filesystems/xtreemfs.nix5
-rw-r--r--nixos/modules/services/networking/atftpd.nix24
-rw-r--r--nixos/modules/services/networking/avahi-daemon.nix15
-rw-r--r--nixos/modules/services/networking/bind.nix1
-rw-r--r--nixos/modules/services/networking/chrony.nix1
-rw-r--r--nixos/modules/services/networking/cjdns-hosts.sh11
-rw-r--r--nixos/modules/services/networking/cjdns.nix55
-rw-r--r--nixos/modules/services/networking/cntlm.nix1
-rw-r--r--nixos/modules/services/networking/ddclient.nix2
-rw-r--r--nixos/modules/services/networking/dhcpd.nix10
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix6
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.xml13
-rw-r--r--nixos/modules/services/networking/firewall.nix13
-rw-r--r--nixos/modules/services/networking/hostapd.nix2
-rw-r--r--nixos/modules/services/networking/ircd-hybrid/builder.sh4
-rw-r--r--nixos/modules/services/networking/kippo.nix8
-rw-r--r--nixos/modules/services/networking/murmur.nix2
-rw-r--r--nixos/modules/services/networking/networkmanager.nix3
-rw-r--r--nixos/modules/services/networking/openfire.nix2
-rw-r--r--nixos/modules/services/networking/prayer.nix1
-rw-r--r--nixos/modules/services/networking/prosody.nix1
-rw-r--r--nixos/modules/services/networking/smokeping.nix105
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix40
-rw-r--r--nixos/modules/services/networking/supplicant.nix3
-rw-r--r--nixos/modules/services/networking/syncthing.nix115
-rw-r--r--nixos/modules/services/networking/tftpd.nix3
-rw-r--r--nixos/modules/services/networking/unbound.nix2
-rw-r--r--nixos/modules/services/networking/wireguard.nix225
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix6
-rw-r--r--nixos/modules/services/networking/xinetd.nix2
-rw-r--r--nixos/modules/services/networking/znc.nix174
-rw-r--r--nixos/modules/services/search/hound.nix123
-rw-r--r--nixos/modules/services/torrent/deluge.nix57
-rw-r--r--nixos/modules/services/web-apps/atlassian/confluence.nix141
-rw-r--r--nixos/modules/services/web-apps/atlassian/crowd.nix147
-rw-r--r--nixos/modules/services/web-apps/atlassian/jira.nix149
-rw-r--r--nixos/modules/services/web-apps/nixbot.nix149
-rw-r--r--nixos/modules/services/web-apps/quassel-webserver.nix99
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/mediawiki.nix1
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/moodle.nix1
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/trac.nix1
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/wordpress.nix1
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix5
-rw-r--r--nixos/modules/services/web-servers/phpfpm/default.nix11
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/lxqt.nix83
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix7
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix3
-rw-r--r--nixos/modules/services/x11/display-managers/sddm.nix4
-rw-r--r--nixos/modules/services/x11/urxvtd.nix49
-rw-r--r--nixos/modules/services/x11/window-managers/bspwm-unstable.nix48
-rw-r--r--nixos/modules/services/x11/window-managers/default.nix1
-rw-r--r--nixos/modules/services/x11/xserver.nix5
-rw-r--r--nixos/modules/system/activation/activation-script.nix1
-rw-r--r--nixos/modules/system/activation/top-level.nix2
-rw-r--r--nixos/modules/system/boot/kernel.nix20
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh3
-rw-r--r--nixos/modules/system/boot/stage-1.nix2
-rw-r--r--nixos/modules/system/boot/systemd-nspawn.nix122
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix3
-rw-r--r--nixos/modules/system/boot/systemd.nix4
-rw-r--r--nixos/modules/system/etc/etc.nix2
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix33
-rw-r--r--nixos/modules/tasks/network-interfaces.nix13
-rw-r--r--nixos/modules/virtualisation/containers.nix2
109 files changed, 2574 insertions, 398 deletions
diff --git a/nixos/modules/config/debug-info.nix b/nixos/modules/config/debug-info.nix
index 17cb862d2916..671a59f52f6d 100644
--- a/nixos/modules/config/debug-info.nix
+++ b/nixos/modules/config/debug-info.nix
@@ -20,7 +20,7 @@ with lib;
         <!-- FIXME: ugly, see #10721 -->
         <programlisting>
         nixpkgs.config.packageOverrides = pkgs: {
-          hello = overrideDerivation pkgs.hello (attrs: {
+          hello = pkgs.lib.overrideDerivation pkgs.hello (attrs: {
             outputs = attrs.outputs or ["out"] ++ ["debug"];
             buildInputs = attrs.buildInputs ++ [&lt;nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh>];
           });
diff --git a/nixos/modules/config/timezone.nix b/nixos/modules/config/timezone.nix
index b9844b4adade..39a45042c6cc 100644
--- a/nixos/modules/config/timezone.nix
+++ b/nixos/modules/config/timezone.nix
@@ -37,14 +37,15 @@ in
 
     environment.sessionVariables.TZDIR = "/etc/zoneinfo";
 
+    # This way services are restarted when tzdata changes.
     systemd.globalEnvironment.TZDIR = tzdir;
 
     environment.etc.localtime =
-      { source = "${tzdir}/${config.time.timeZone}";
+      { source = "/etc/zoneinfo/${config.time.timeZone}";
         mode = "direct-symlink";
       };
 
-    environment.etc.zoneinfo.source = "${pkgs.tzdata}/share/zoneinfo";
+    environment.etc.zoneinfo.source = tzdir;
 
   };
 
diff --git a/nixos/modules/hardware/video/amdgpu-pro.nix b/nixos/modules/hardware/video/amdgpu-pro.nix
new file mode 100644
index 000000000000..3723d7690dc6
--- /dev/null
+++ b/nixos/modules/hardware/video/amdgpu-pro.nix
@@ -0,0 +1,56 @@
+# This module provides the proprietary AMDGPU-PRO drivers.
+
+{ config, lib, pkgs, pkgs_i686, ... }:
+
+with lib;
+
+let
+
+  drivers = config.services.xserver.videoDrivers;
+
+  enabled = elem "amdgpu-pro" drivers;
+
+  package = config.boot.kernelPackages.amdgpu-pro;
+  package32 = pkgs_i686.linuxPackages.amdgpu-pro.override { libsOnly = true; kernel = null; };
+
+  opengl = config.hardware.opengl;
+
+in
+
+{
+
+  config = mkIf enabled {
+
+    services.xserver.drivers = singleton
+      { name = "amdgpu"; modules = [ package ]; libPath = [ package ]; };
+
+    hardware.opengl.package = package;
+    hardware.opengl.package32 = package32;
+
+    boot.extraModulePackages = [ package ];
+
+    boot.blacklistedKernelModules = [ "radeon" ];
+
+    hardware.firmware = [ package ];
+
+    system.activationScripts.setup-amdgpu-pro = ''
+      mkdir -p /run/lib
+      ln -sfn ${package}/lib ${package.libCompatDir}
+    '' + optionalString opengl.driSupport32Bit ''
+      ln -sfn ${package32}/lib ${package32.libCompatDir}
+    '';
+
+    environment.etc = {
+      "amd/amdrc".source = package + "/etc/amd/amdrc";
+      "amd/amdapfxx.blb".source = package + "/etc/amd/amdapfxx.blb";
+      "gbm/gbm.conf".source = package + "/etc/gbm/gbm.conf";
+      "OpenCL/vendors/amdocl64.icd".source = package + "/etc/OpenCL/vendors/amdocl64.icd";
+      "vulkan/icd.d/amd_icd64.json".source = package + "/etc/vulkan/icd.d/amd_icd64.json";
+    } // optionalAttrs opengl.driSupport32Bit {
+      "OpenCL/vendors/amdocl32.icd".source = package32 + "/etc/OpenCL/vendors/amdocl32.icd";
+      "vulkan/icd.d/amd_icd32.json".source = package32 + "/etc/vulkan/icd.d/amd_icd32.json";
+    };
+
+  };
+
+}
diff --git a/nixos/modules/installer/tools/auto-upgrade.nix b/nixos/modules/installer/tools/auto-upgrade.nix
index b21b80c666aa..dfb43d1a1db9 100644
--- a/nixos/modules/installer/tools/auto-upgrade.nix
+++ b/nixos/modules/installer/tools/auto-upgrade.nix
@@ -84,7 +84,7 @@ let cfg = config.system.autoUpgrade; in
         ${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch ${toString cfg.flags}
       '';
 
-      startAt = optionalString cfg.enable cfg.dates;
+      startAt = optional cfg.enable cfg.dates;
     };
 
   };
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 2881d843760d..8c0f0c2624b1 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -276,6 +276,7 @@
       telegraf = 256;
       gitlab-runner = 257;
       postgrey = 258;
+      hound = 259;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -522,6 +523,7 @@
       #telegraf = 256; # unused
       gitlab-runner = 257;
       postgrey = 258;
+      hound = 259;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index d1a786d8f629..61596265124a 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -38,6 +38,7 @@
   ./hardware/opengl.nix
   ./hardware/pcmcia.nix
   ./hardware/video/amdgpu.nix
+  ./hardware/video/amdgpu-pro.nix
   ./hardware/video/ati.nix
   ./hardware/video/bumblebee.nix
   ./hardware/video/displaylink.nix
@@ -76,6 +77,7 @@
   ./programs/man.nix
   ./programs/mosh.nix
   ./programs/nano.nix
+  ./programs/oblogout.nix
   ./programs/screen.nix
   ./programs/shadow.nix
   ./programs/shell.nix
@@ -84,6 +86,7 @@
   ./programs/ssmtp.nix
   ./programs/tmux.nix
   ./programs/venus.nix
+  ./programs/vim.nix
   ./programs/wvdial.nix
   ./programs/xfs_quota.nix
   ./programs/xonsh.nix
@@ -164,6 +167,7 @@
   ./services/desktops/gnome3/gnome-keyring.nix
   ./services/desktops/gnome3/gnome-online-accounts.nix
   ./services/desktops/gnome3/gnome-online-miners.nix
+  ./services/desktops/gnome3/gnome-terminal-server.nix
   ./services/desktops/gnome3/gnome-user-share.nix
   ./services/desktops/gnome3/gvfs.nix
   ./services/desktops/gnome3/seahorse.nix
@@ -234,7 +238,9 @@
   ./services/misc/dictd.nix
   ./services/misc/dysnomia.nix
   ./services/misc/disnix.nix
+  ./services/misc/docker-registry.nix
   ./services/misc/emby.nix
+  ./services/misc/errbot.nix
   ./services/misc/etcd.nix
   ./services/misc/felix.nix
   ./services/misc/folding-at-home.nix
@@ -308,6 +314,7 @@
   ./services/monitoring/uptime.nix
   ./services/monitoring/zabbix-agent.nix
   ./services/monitoring/zabbix-server.nix
+  ./services/network-filesystems/cachefilesd.nix
   ./services/network-filesystems/drbd.nix
   ./services/network-filesystems/netatalk.nix
   ./services/network-filesystems/nfsd.nix
@@ -437,6 +444,7 @@
   ./services/networking/wakeonlan.nix
   ./services/networking/websockify.nix
   ./services/networking/wicd.nix
+  ./services/networking/wireguard.nix
   ./services/networking/wpa_supplicant.nix
   ./services/networking/xinetd.nix
   ./services/networking/xl2tpd.nix
@@ -450,6 +458,7 @@
   ./services/scheduling/fcron.nix
   ./services/scheduling/marathon.nix
   ./services/search/elasticsearch.nix
+  ./services/search/hound.nix
   ./services/search/kibana.nix
   ./services/search/solr.nix
   ./services/security/clamav.nix
@@ -479,10 +488,15 @@
   ./services/ttys/agetty.nix
   ./services/ttys/gpm.nix
   ./services/ttys/kmscon.nix
+  ./services/web-apps/atlassian/confluence.nix
+  ./services/web-apps/atlassian/crowd.nix
+  ./services/web-apps/atlassian/jira.nix
   ./services/web-apps/mattermost.nix
+  ./services/web-apps/nixbot.nix
   ./services/web-apps/pump.io.nix
   ./services/web-apps/tt-rss.nix
   ./services/web-apps/selfoss.nix
+  ./services/web-apps/quassel-webserver.nix
   ./services/web-servers/apache-httpd/default.nix
   ./services/web-servers/caddy.nix
   ./services/web-servers/fcgiwrap.nix
@@ -515,12 +529,14 @@
   ./services/x11/hardware/synaptics.nix
   ./services/x11/hardware/wacom.nix
   ./services/x11/redshift.nix
+  ./services/x11/urxvtd.nix
   ./services/x11/window-managers/awesome.nix
   #./services/x11/window-managers/compiz.nix
   ./services/x11/window-managers/default.nix
   ./services/x11/window-managers/fluxbox.nix
   ./services/x11/window-managers/icewm.nix
   ./services/x11/window-managers/bspwm.nix
+  ./services/x11/window-managers/bspwm-unstable.nix
   ./services/x11/window-managers/metacity.nix
   ./services/x11/window-managers/none.nix
   ./services/x11/window-managers/twm.nix
@@ -557,6 +573,7 @@
   ./system/boot/stage-1.nix
   ./system/boot/stage-2.nix
   ./system/boot/systemd.nix
+  ./system/boot/systemd-nspawn.nix
   ./system/boot/timesyncd.nix
   ./system/boot/tmp.nix
   ./system/etc/etc.nix
diff --git a/nixos/modules/programs/oblogout.nix b/nixos/modules/programs/oblogout.nix
new file mode 100644
index 000000000000..79a8ddb7ce37
--- /dev/null
+++ b/nixos/modules/programs/oblogout.nix
@@ -0,0 +1,160 @@
+# Global configuration for oblogout.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.programs.oblogout;
+
+in
+{
+  ###### interface
+
+  options = {
+
+    programs.oblogout = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to install OBLogout and create <filename>/etc/oblogout.conf</filename>.
+          See <filename>${pkgs.oblogout}/share/doc/README</filename>.
+        '';
+      };
+
+      opacity = mkOption {
+        type = types.int;
+        default = 70;
+        description = ''
+        '';
+      };
+
+      bgcolor = mkOption {
+        type = types.str;
+        default = "black";
+        description = ''
+        '';
+      };
+
+      buttontheme = mkOption {
+        type = types.str;
+        default = "simplistic";
+        description = ''
+        '';
+      };
+
+      buttons = mkOption {
+        type = types.str;
+        default =  "cancel, logout, restart, shutdown, suspend, hibernate";
+        description = ''
+        '';
+      };
+
+      cancel = mkOption {
+        type = types.str;
+        default =  "Escape";
+        description = ''
+        '';
+      };
+
+      shutdown = mkOption {
+        type = types.str;
+        default = "S";
+        description = ''
+        '';
+      };
+
+      restart = mkOption {
+        type = types.str;
+        default = "R";
+        description = ''
+        '';
+      };
+
+      suspend = mkOption {
+        type = types.str;
+        default = "U";
+        description = ''
+        '';
+      };
+
+      logout = mkOption {
+        type = types.str;
+        default = "L";
+        description = ''
+        '';
+      };
+
+      lock = mkOption {
+        type = types.str;
+        default = "K";
+        description = ''
+        '';
+      };
+
+      hibernate = mkOption {
+        type = types.str;
+        default =  "H";
+        description = ''
+        '';
+      };
+
+      clogout = mkOption {
+        type = types.str;
+        default = "openbox --exit";
+        description = ''
+        '';
+      };
+
+      clock = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+        '';
+      };
+
+      cswitchuser = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.oblogout ];
+
+    environment.etc."oblogout.conf".text = ''
+      [settings]
+      usehal = false
+
+      [looks]
+      opacity = ${toString cfg.opacity}
+      bgcolor = ${cfg.bgcolor}
+      buttontheme = ${cfg.buttontheme}
+      buttons = ${cfg.buttons}
+
+      [shortcuts]
+      cancel = ${cfg.cancel}
+      shutdown = ${cfg.shutdown}
+      restart = ${cfg.restart}
+      suspend = ${cfg.suspend}
+      logout = ${cfg.logout}
+      lock = ${cfg.lock}
+      hibernate = ${cfg.hibernate}
+
+      [commands]
+      shutdown = systemctl poweroff
+      restart = systemctl reboot
+      suspend = systemctl suspend
+      hibernate = systemctl hibernate
+      logout = ${cfg.clogout}
+      lock = ${cfg.clock}
+      switchuser = ${cfg.cswitchuser}
+    '';
+  };
+}
diff --git a/nixos/modules/programs/vim.nix b/nixos/modules/programs/vim.nix
new file mode 100644
index 000000000000..8476c1accd31
--- /dev/null
+++ b/nixos/modules/programs/vim.nix
@@ -0,0 +1,24 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.vim;
+in {
+  options.programs.vim = {
+    defaultEditor = mkOption {
+      type = types.bool;
+      default = false;
+      example = true;
+      description = ''
+        When enabled, installs vim and configures vim to be the default editor
+        using the EDITOR environment variable.
+      '';
+    };
+  };
+
+  config = mkIf cfg.defaultEditor {
+        environment.systemPackages = [ pkgs.vim ];
+        environment.variables = { EDITOR = mkOverride 900 "vim"; };
+  };
+}
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 9abe7d450c93..44e07f4618de 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -156,7 +156,5 @@ with lib;
       "See the 16.09 release notes for more information.")
     (mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "")
     (mkRemovedOptionModule [ "services" "dovecot2" "package" ] "")
-    (mkRemovedOptionModule [ "services" "dockerRegistry" ]
-      "docker-registry has been deprecated upstream since a long time.")
   ];
 }
diff --git a/nixos/modules/security/acme.xml b/nixos/modules/security/acme.xml
index 15ed4c04a23d..226cf0382da7 100644
--- a/nixos/modules/security/acme.xml
+++ b/nixos/modules/security/acme.xml
@@ -74,9 +74,30 @@ options for the <literal>security.acme</literal> module.</para>
 </para>
 
 <programlisting>
+security.acme.certs."foo.example.com" = {
+  webroot = "/var/www/challenges";
+  email = "foo@example.com";
+  user = "nginx";
+  group = "nginx";
+  postRun = "systemctl restart nginx.service";
+};
 services.nginx.httpConfig = ''
   server {
     server_name foo.example.com;
+    listen 80;
+    listen [::]:80;
+
+    location /.well-known/acme-challenge {
+      root /var/www/challenges;
+    }
+
+    location / {
+      return 301 https://$host$request_uri;
+    }
+  }
+
+  server {
+    server_name foo.example.com;
     listen 443 ssl;
     ssl_certificate     ${config.security.acme.directory}/foo.example.com/fullchain.pem;
     ssl_certificate_key ${config.security.acme.directory}/foo.example.com/key.pem;
diff --git a/nixos/modules/security/audit.nix b/nixos/modules/security/audit.nix
index ebfe594d0c71..7ac21fd96507 100644
--- a/nixos/modules/security/audit.nix
+++ b/nixos/modules/security/audit.nix
@@ -104,7 +104,11 @@ in {
       description = "Kernel Auditing";
       wantedBy = [ "basic.target" ];
 
-      unitConfig.ConditionVirtualization = "!container";
+      unitConfig = {
+        ConditionVirtualization = "!container";
+        ConditionSecurity = [ "audit" ];
+      };
+
 
       path = [ pkgs.audit ];
 
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index 849530238e7e..67469be18b41 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -4,10 +4,16 @@ with lib;
 
 let
 
+  cfg = config.security.pki;
+
+  cacertPackage = pkgs.cacert.override {
+    blacklist = cfg.caCertificateBlacklist;
+  };
+
   caCertificates = pkgs.runCommand "ca-certificates.crt"
     { files =
-        config.security.pki.certificateFiles ++
-        [ (builtins.toFile "extra.crt" (concatStringsSep "\n" config.security.pki.certificates)) ];
+        cfg.certificateFiles ++
+        [ (builtins.toFile "extra.crt" (concatStringsSep "\n" cfg.certificates)) ];
      }
     ''
       cat $files > $out
@@ -52,11 +58,27 @@ in
       '';
     };
 
+    security.pki.caCertificateBlacklist = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [
+        "WoSign" "WoSign China"
+        "CA WoSign ECC Root"
+        "Certification Authority of WoSign G2"
+      ];
+      description = ''
+        A list of blacklisted CA certificate names that won't be imported from
+        the Mozilla Trust Store into
+        <filename>/etc/ssl/certs/ca-certificates.crt</filename>. Use the
+        names from that file.
+      '';
+    };
+
   };
 
   config = {
 
-    security.pki.certificateFiles = [ "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ];
+    security.pki.certificateFiles = [ "${cacertPackage}/etc/ssl/certs/ca-bundle.crt" ];
 
     # NixOS canonical location + Debian/Ubuntu/Arch/Gentoo compatibility.
     environment.etc."ssl/certs/ca-certificates.crt".source = caCertificates;
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index 7ba25f866f24..53c2ace784ef 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -67,9 +67,9 @@ in
     system.requiredKernelConfig = with config.lib.kernelConfig;
       [ (isEnabled "GRKERNSEC")
         (isEnabled "PAX")
-        (isYES "GRKERNSEC_SYSCTL")
-        (isYES "GRKERNSEC_SYSCTL_DISTRO")
-        (isNO "GRKERNSEC_NO_RBAC")
+        (isYes "GRKERNSEC_SYSCTL")
+        (isYes "GRKERNSEC_SYSCTL_DISTRO")
+        (isNo "GRKERNSEC_NO_RBAC")
       ];
 
     nixpkgs.config.grsecurity = true;
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 85e0a7d2ac4e..5ec2e2c26232 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -49,7 +49,7 @@ in {
       };
 
       extraConfig = mkOption {
-        type = types.str;
+        type = types.lines;
         default = "";
         description = ''
           Extra directives added to to the end of MPD's configuration file,
diff --git a/nixos/modules/services/backup/bacula.nix b/nixos/modules/services/backup/bacula.nix
index ef8e5e55edef..340b0cf07234 100644
--- a/nixos/modules/services/backup/bacula.nix
+++ b/nixos/modules/services/backup/bacula.nix
@@ -340,6 +340,7 @@ in {
 
       extraConfig = mkOption {
         default = "";
+        type = types.lines;
         description = ''
           Extra configuration for Bacula Director Daemon.
         '';
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix
index e5e8a57f4b0e..1180531248f9 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -53,7 +53,8 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.mysql;
-        example = literalExample "pkgs.mysql";
+        defaultText = "pkgs.mysql";
+        example = literalExample "pkgs.mysql55";
         description = "
           Which MySQL derivation to use.
         ";
diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
index 146a604adb2f..7b51f1af6899 100644
--- a/nixos/modules/services/databases/neo4j.nix
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -5,34 +5,34 @@ with lib;
 let
   cfg = config.services.neo4j;
 
-  serverConfig = pkgs.writeText "neo4j-server.properties" ''
-    org.neo4j.server.database.location=${cfg.dataDir}/data/graph.db
-    org.neo4j.server.webserver.address=${cfg.listenAddress}
-    org.neo4j.server.webserver.port=${toString cfg.port}
+  serverConfig = pkgs.writeText "neo4j.conf" ''
+    dbms.directories.data=${cfg.dataDir}/data
+    dbms.directories.certificates=${cfg.certDir}
+    dbms.directories.logs=${cfg.dataDir}/logs
+    dbms.directories.plugins=${cfg.dataDir}/plugins
+    dbms.connector.http.type=HTTP
+    dbms.connector.http.enabled=true
+    dbms.connector.http.address=${cfg.listenAddress}:${toString cfg.port}
+    ${optionalString cfg.enableBolt ''
+      dbms.connector.bolt.type=BOLT
+      dbms.connector.bolt.enabled=true
+      dbms.connector.bolt.tls_level=OPTIONAL
+      dbms.connector.bolt.address=${cfg.listenAddress}:${toString cfg.boltPort}
+    ''}
     ${optionalString cfg.enableHttps ''
-      org.neo4j.server.webserver.https.enabled=true
-      org.neo4j.server.webserver.https.port=${toString cfg.httpsPort}
-      org.neo4j.server.webserver.https.cert.location=${cfg.cert}
-      org.neo4j.server.webserver.https.key.location=${cfg.key}
-      org.neo4j.server.webserver.https.keystore.location=${cfg.dataDir}/data/keystore
+      dbms.connector.https.type=HTTP
+      dbms.connector.https.enabled=true
+      dbms.connector.https.encryption=TLS
+      dbms.connector.https.address=${cfg.listenAddress}:${toString cfg.httpsPort}
     ''}
-    org.neo4j.server.webadmin.rrdb.location=${cfg.dataDir}/data/rrd
-    org.neo4j.server.webadmin.data.uri=/db/data/
-    org.neo4j.server.webadmin.management.uri=/db/manage/
-    org.neo4j.server.db.tuning.properties=${cfg.package}/share/neo4j/conf/neo4j.properties
-    org.neo4j.server.manage.console_engines=shell
+    dbms.shell.enabled=true
     ${cfg.extraServerConfig}
   '';
 
-  loggingConfig = pkgs.writeText "logging.properties" cfg.loggingConfig;
-
   wrapperConfig = pkgs.writeText "neo4j-wrapper.conf" ''
-    wrapper.java.additional=-Dorg.neo4j.server.properties=${serverConfig}
-    wrapper.java.additional=-Djava.util.logging.config.file=${loggingConfig}
-    wrapper.java.additional=-XX:+UseConcMarkSweepGC
-    wrapper.java.additional=-XX:+CMSClassUnloadingEnabled
-    wrapper.pidfile=${cfg.dataDir}/neo4j-server.pid
-    wrapper.name=neo4j
+    dbms.jvm.additional=-Dunsupported.dbms.udc.source=tarball
+    dbms.jvm.additional=-XX:+UseConcMarkSweepGC
+    dbms.jvm.additional=-XX:+CMSClassUnloadingEnabled
   '';
 
 in {
@@ -65,6 +65,18 @@ in {
       type = types.int;
     };
 
+    enableBolt = mkOption {
+      description = "Enable bolt for Neo4j.";
+      default = true;
+      type = types.bool;
+    };
+
+    boltPort = mkOption {
+      description = "Neo4j port to listen for BOLT traffic.";
+      default = 7687;
+      type = types.int;
+    };
+
     enableHttps = mkOption {
       description = "Enable https for Neo4j.";
       default = false;
@@ -77,15 +89,9 @@ in {
       type = types.int;
     };
 
-    cert = mkOption {
-      description = "Neo4j https certificate.";
-      default = "${cfg.dataDir}/conf/ssl/neo4j.cert";
-      type = types.path;
-    };
-
-    key = mkOption {
-      description = "Neo4j https certificate key.";
-      default = "${cfg.dataDir}/conf/ssl/neo4j.key";
+    certDir = mkOption {
+      description = "Neo4j TLS certificates directory.";
+      default = "${cfg.dataDir}/certificates";
       type = types.path;
     };
 
@@ -95,26 +101,11 @@ in {
       type = types.path;
     };
 
-    loggingConfig = mkOption {
-      description = "Neo4j logging configuration.";
-      default = ''
-        handlers=java.util.logging.ConsoleHandler
-        .level=INFO
-        org.neo4j.server.level=INFO
-
-        java.util.logging.ConsoleHandler.level=INFO
-        java.util.logging.ConsoleHandler.formatter=org.neo4j.server.logging.SimpleConsoleFormatter
-        java.util.logging.ConsoleHandler.filter=org.neo4j.server.logging.NeoLogFilter
-      '';
-      type = types.lines;
-    };
-
     extraServerConfig = mkOption {
       description = "Extra configuration for neo4j server.";
       default = "";
       type = types.lines;
     };
-
   };
 
   ###### implementation
@@ -124,14 +115,18 @@ in {
       description = "Neo4j Daemon";
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
-      environment = { NEO4J_INSTANCE = cfg.dataDir; };
+      environment = {
+        NEO4J_HOME = "${cfg.package}/share/neo4j";
+        NEO4J_CONF = "${cfg.dataDir}/conf";
+      };
       serviceConfig = {
         ExecStart = "${cfg.package}/bin/neo4j console";
         User = "neo4j";
         PermissionsStartOnly = true;
       };
       preStart = ''
-        mkdir -m 0700 -p ${cfg.dataDir}/{data/graph.db,conf}
+        mkdir -m 0700 -p ${cfg.dataDir}/{data/graph.db,conf,logs}
+        ln -fs ${serverConfig} ${cfg.dataDir}/conf/neo4j.conf
         ln -fs ${wrapperConfig} ${cfg.dataDir}/conf/neo4j-wrapper.conf
         if [ "$(id -u)" = 0 ]; then chown -R neo4j ${cfg.dataDir}; fi
       '';
@@ -146,5 +141,4 @@ in {
       home = cfg.dataDir;
     };
   };
-
 }
diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix
index 9f22aa7c92b2..b8e6c0cec3dc 100644
--- a/nixos/modules/services/databases/openldap.nix
+++ b/nixos/modules/services/databases/openldap.nix
@@ -53,6 +53,13 @@ in
         description = "The database directory.";
       };
 
+      configDir = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = "Use this optional config directory instead of using slapd.conf";
+        example = "/var/db/slapd.d";
+      };
+
       extraConfig = mkOption {
         type = types.lines;
         default = "";
@@ -96,7 +103,7 @@ in
         mkdir -p ${cfg.dataDir}
         chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}
       '';
-      serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -h \"${concatStringsSep " " cfg.urlList}\" -f ${configFile}";
+      serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -h \"${concatStringsSep " " cfg.urlList}\" ${if cfg.configDir == null then "-f "+configFile else "-F "+cfg.configDir}";
     };
 
     users.extraUsers.openldap =
diff --git a/nixos/modules/services/desktops/gnome3/evolution-data-server.nix b/nixos/modules/services/desktops/gnome3/evolution-data-server.nix
index a8f8da0eed56..2db2e2fe1c34 100644
--- a/nixos/modules/services/desktops/gnome3/evolution-data-server.nix
+++ b/nixos/modules/services/desktops/gnome3/evolution-data-server.nix
@@ -37,6 +37,8 @@ in
 
     services.dbus.packages = [ gnome3.evolution_data_server ];
 
+    systemd.packages = [ gnome3.evolution_data_server ];
+
   };
 
 }
diff --git a/nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix b/nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix
new file mode 100644
index 000000000000..384cede679c6
--- /dev/null
+++ b/nixos/modules/services/desktops/gnome3/gnome-terminal-server.nix
@@ -0,0 +1,44 @@
+# GNOME Documents daemon.
+
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  gnome3 = config.environment.gnome3.packageSet;
+in
+{
+
+  ###### interface
+
+  options = {
+
+    services.gnome3.gnome-terminal-server = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable GNOME Terminal server service,
+          needed for gnome-terminal.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.services.gnome3.gnome-terminal-server.enable {
+
+    environment.systemPackages = [ gnome3.gnome_terminal ];
+
+    services.dbus.packages = [ gnome3.gnome_terminal ];
+
+    systemd.packages = [ gnome3.gnome_terminal ];
+
+  };
+
+}
diff --git a/nixos/modules/services/desktops/gnome3/gvfs.nix b/nixos/modules/services/desktops/gnome3/gvfs.nix
index a07cdadbb12b..6bbabe8d3c56 100644
--- a/nixos/modules/services/desktops/gnome3/gvfs.nix
+++ b/nixos/modules/services/desktops/gnome3/gvfs.nix
@@ -37,6 +37,8 @@ in
 
     services.dbus.packages = [ gnome3.gvfs ];
 
+    systemd.packages = [ gnome3.gvfs ];
+
     services.udev.packages = [ pkgs.libmtp.bin ];
 
   };
diff --git a/nixos/modules/services/desktops/gnome3/tracker.nix b/nixos/modules/services/desktops/gnome3/tracker.nix
index 8c5935a5ee3c..dcaa60103a3b 100644
--- a/nixos/modules/services/desktops/gnome3/tracker.nix
+++ b/nixos/modules/services/desktops/gnome3/tracker.nix
@@ -37,6 +37,8 @@ in
 
     services.dbus.packages = [ gnome3.tracker ];
 
+    systemd.packages = [ gnome3.tracker ];
+
   };
 
 }
diff --git a/nixos/modules/services/editors/emacs.xml b/nixos/modules/services/editors/emacs.xml
index 544e4a1076f4..bcaa8b8df3d8 100644
--- a/nixos/modules/services/editors/emacs.xml
+++ b/nixos/modules/services/editors/emacs.xml
@@ -43,9 +43,10 @@
     <title>Installing <application>Emacs</application></title>
 
     <para>
-      Emacs can installed in the normal way for Nix (see <xref
-      linkend="sec-package-management" />). In addition, a NixOS
-      <emphasis>service</emphasis> can be enabled.
+      Emacs can be installed in the normal way for Nix (see
+      <xref linkend="sec-package-management" />).
+      In addition, a NixOS <emphasis>service</emphasis>
+      can be enabled.
     </para>
 
     <section>
@@ -564,6 +565,55 @@ services.emacs.install = true;
       &lt;RET&gt; nixos-rebuild &lt;RET&gt;.</literal>
     </para>
   </section>
+
+  <section xml:id="sec-emacs-docbook-xml">
+    <title>Editing DocBook 5 XML Documents</title>
+    <para>
+      Emacs includes <link
+      xlink:href="https://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Introduction.html">nXML</link>,
+      a major-mode for validating and editing XML documents.
+      When editing DocBook 5.0 documents, such as
+      <link linkend="book-nixos-manual">this one</link>,
+      nXML needs to be configured with the relevant schema, which is
+      not included.
+    </para>
+
+    <para>
+      To install the DocBook 5.0 schemas, either add
+      <varname>pkgs.docbook5</varname> to
+      <varname>environment.systemPackages</varname> (<link
+      linkend="sec-declarative-package-mgmt">NixOS</link>), or run
+      <literal>nix-env -i pkgs.docbook5</literal>
+      (<link linkend="sec-ad-hoc-packages">Nix</link>).
+    </para>
+
+    <para>
+      Then customize the variable <varname>rng-schema-locating-files</varname> to include <filename>~/.emacs.d/schemas.xml</filename> and put the following text into that file:
+      <example xml:id="ex-emacs-docbook-xml">
+        <title>nXML Schema Configuration (<filename>~/.emacs.d/schemas.xml</filename>)</title>
+        <programlisting language="xml"><![CDATA[
+<?xml version="1.0"?>
+<!--
+  To let emacs find this file, evaluate:
+  (add-to-list 'rng-schema-locating-files "~/.emacs.d/schemas.xml")
+-->
+<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
+  <!--
+    Use this variation if pkgs.docbook5 is added to environment.systemPackages
+  -->
+  <namespace ns="http://docbook.org/ns/docbook"
+             uri="/run/current-system/sw/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
+  <!--
+    Use this variation if installing schema with "nix-env -iA pkgs.docbook5".
+  <namespace ns="http://docbook.org/ns/docbook"
+             uri="../.nix-profile/share/xml/docbook-5.0/rng/docbookxi.rnc"/>
+  -->
+</locatingRules>
+]]></programlisting>
+    </example>
+  </para>
+
+  </section>
 </section>
 
 </chapter>
diff --git a/nixos/modules/services/hardware/brltty.nix b/nixos/modules/services/hardware/brltty.nix
index 03e530b2c96d..b416ba332222 100644
--- a/nixos/modules/services/hardware/brltty.nix
+++ b/nixos/modules/services/hardware/brltty.nix
@@ -28,7 +28,7 @@ in {
       };
       serviceConfig = {
         ExecStart = "${pkgs.brltty}/bin/brltty --no-daemon";
-        Type = "simple";        # Change to notidy after next releae
+        Type = "notify";
         TimeoutStartSec = 5;
         TimeoutStopSec = 10;
         Restart = "always";
diff --git a/nixos/modules/services/hardware/tlp.nix b/nixos/modules/services/hardware/tlp.nix
index 281d02a8c65e..f36a9e7b4596 100644
--- a/nixos/modules/services/hardware/tlp.nix
+++ b/nixos/modules/services/hardware/tlp.nix
@@ -40,7 +40,7 @@ in
       };
 
       extraConfig = mkOption {
-        type = types.str;
+        type = types.lines;
         default = "";
         description = "Additional configuration variables for TLP";
       };
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index e79d5dadd828..4c9df935debe 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -111,7 +111,7 @@ in
     };
 
     extraConfig = mkOption {
-      type = types.str;
+      type = types.lines;
       default = "";
       example = "mail_debug = yes";
       description = "Additional entries to put verbatim into Dovecot's config file.";
diff --git a/nixos/modules/services/mail/opensmtpd.nix b/nixos/modules/services/mail/opensmtpd.nix
index fb94560e10aa..53acdba42457 100644
--- a/nixos/modules/services/mail/opensmtpd.nix
+++ b/nixos/modules/services/mail/opensmtpd.nix
@@ -1,17 +1,16 @@
 { config, lib, pkgs, ... }:
 
-with pkgs;
 with lib;
 
 let
 
   cfg = config.services.opensmtpd;
-  conf = writeText "smtpd.conf" cfg.serverConfiguration;
+  conf = pkgs.writeText "smtpd.conf" cfg.serverConfiguration;
   args = concatStringsSep " " cfg.extraServerArgs;
 
   sendmail = pkgs.runCommand "opensmtpd-sendmail" {} ''
     mkdir -p $out/bin
-    ln -s ${opensmtpd}/sbin/smtpctl $out/bin/sendmail
+    ln -s ${pkgs.opensmtpd}/sbin/smtpctl $out/bin/sendmail
   '';
 
 in {
@@ -48,21 +47,19 @@ in {
       };
 
       serverConfiguration = mkOption {
-        type = types.string;
-        default = "";
+        type = types.lines;
         example = ''
           listen on lo
           accept for any deliver to lmtp localhost:24
-        ''; 
+        '';
         description = ''
           The contents of the smtpd.conf configuration file. See the
-          OpenSMTPD documentation for syntax information. If this option
-          is left empty, the OpenSMTPD server will not start.
+          OpenSMTPD documentation for syntax information.
         '';
       };
 
       procPackages = mkOption {
-        type = types.listOf types.path;
+        type = types.listOf types.package;
         default = [];
         description = ''
           Packages to search for filters, tables, queues, and schedulers.
@@ -100,12 +97,11 @@ in {
     systemd.services.opensmtpd = let
       procEnv = pkgs.buildEnv {
         name = "opensmtpd-procs";
-        paths = [ opensmtpd ] ++ cfg.procPackages;
+        paths = [ pkgs.opensmtpd ] ++ cfg.procPackages;
         pathsToLink = [ "/libexec/opensmtpd" ];
       };
     in {
       wantedBy = [ "multi-user.target" ];
-      wants = [ "network.target" ];
       after = [ "network.target" ];
       preStart = ''
         mkdir -p /var/spool/smtpd
@@ -119,7 +115,7 @@ in {
         chown smtpq.root /var/spool/smtpd/purge
         chmod 700 /var/spool/smtpd/purge
       '';
-      serviceConfig.ExecStart = "${opensmtpd}/sbin/smtpd -d -f ${conf} ${args}";
+      serviceConfig.ExecStart = "${pkgs.opensmtpd}/sbin/smtpd -d -f ${conf} ${args}";
       environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd";
     };
 
diff --git a/nixos/modules/services/misc/bepasty.nix b/nixos/modules/services/misc/bepasty.nix
index 5bda73ab64f0..52719222db66 100644
--- a/nixos/modules/services/misc/bepasty.nix
+++ b/nixos/modules/services/misc/bepasty.nix
@@ -53,7 +53,7 @@ in
           };
 
           extraConfig = mkOption {
-            type = types.str;
+            type = types.lines;
             description = ''
               Extra configuration for bepasty server to be appended on the
               configuration.
diff --git a/nixos/modules/services/misc/docker-registry.nix b/nixos/modules/services/misc/docker-registry.nix
new file mode 100644
index 000000000000..96ac2a1cf2c9
--- /dev/null
+++ b/nixos/modules/services/misc/docker-registry.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.dockerRegistry;
+
+in {
+  options.services.dockerRegistry = {
+    enable = mkEnableOption "Docker Registry";
+
+    listenAddress = mkOption {
+      description = "Docker registry host or ip to bind to.";
+      default = "127.0.0.1";
+      type = types.str;
+    };
+
+    port = mkOption {
+      description = "Docker registry port to bind to.";
+      default = 5000;
+      type = types.int;
+    };
+
+    storagePath = mkOption {
+      type = types.path;
+      default = "/var/lib/docker-registry";
+      description = "Docker registry storage path.";
+    };
+
+    extraConfig = mkOption {
+      description = ''
+        Docker extra registry configuration via environment variables.
+      '';
+      default = {};
+      type = types.attrsOf types.str;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.docker-registry = {
+      description = "Docker Container Registry";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      environment = {
+        REGISTRY_HTTP_ADDR = "${cfg.listenAddress}:${toString cfg.port}";
+        REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY = cfg.storagePath;
+      } // cfg.extraConfig;
+
+      script = ''
+        ${pkgs.docker-distribution}/bin/registry serve \
+          ${pkgs.docker-distribution.out}/share/go/src/github.com/docker/distribution/cmd/registry/config-example.yml
+      '';
+
+      serviceConfig = {
+        User = "docker-registry";
+        WorkingDirectory = cfg.storagePath;
+      };
+    };
+
+    users.extraUsers.docker-registry = {
+      createHome = true;
+      home = cfg.storagePath;
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/errbot.nix b/nixos/modules/services/misc/errbot.nix
new file mode 100644
index 000000000000..f573be69925c
--- /dev/null
+++ b/nixos/modules/services/misc/errbot.nix
@@ -0,0 +1,101 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.errbot;
+  pluginEnv = plugins: pkgs.buildEnv {
+    name = "errbot-plugins";
+    paths = plugins;
+  };
+  mkConfigFile = instanceCfg: dataDir: pkgs.writeText "errbot-config.py" ''
+    import logging
+    BACKEND = '${instanceCfg.backend}'
+    BOT_DATA_DIR = '${dataDir}'
+    BOT_EXTRA_PLUGIN_DIR = '${pluginEnv instanceCfg.plugins}'
+
+    BOT_LOG_LEVEL = logging.${instanceCfg.logLevel}
+    BOT_LOG_FILE = False
+
+    BOT_ADMINS = (${concatMapStringsSep "," (name: "'${name}'") instanceCfg.admins})
+
+    BOT_IDENTITY = ${builtins.toJSON instanceCfg.identity}
+
+    ${instanceCfg.extraConfig}
+  '';
+in {
+  options = {
+    services.errbot.instances = mkOption {
+      default = {};
+      description = "Errbot instance configs";
+      type = types.attrsOf (types.submodule {
+        options = {
+          dataDir = mkOption {
+            type = types.nullOr types.path;
+            default = null;
+            description = "Data directory for errbot instance.";
+          };
+
+          plugins = mkOption {
+            type = types.listOf types.package;
+            default = [];
+            description = "List of errbot plugin derivations.";
+          };
+
+          logLevel = mkOption {
+            type = types.str;
+            default = "INFO";
+            description = "Errbot log level";
+          };
+
+          admins = mkOption {
+            type = types.listOf types.str;
+            default = [];
+            description = "List of identifiers of errbot admins.";
+          };
+
+          backend = mkOption {
+            type = types.str;
+            default = "XMPP";
+            description = "Errbot backend name.";
+          };
+
+          identity = mkOption {
+            type = types.attrs;
+            description = "Errbot identity configuration";
+          };
+
+          extraConfig = mkOption {
+            type = types.lines;
+            default = "";
+            description = "String to be appended to the config verbatim";
+          };
+        };
+      });
+    };
+  };
+
+  config = mkIf (cfg.instances != {}) {
+    users.extraUsers.errbot.group = "errbot";
+    users.extraGroups.errbot = {};
+
+    systemd.services = mapAttrs' (name: instanceCfg: nameValuePair "errbot-${name}" (
+    let
+      dataDir = if !isNull instanceCfg.dataDir then instanceCfg.dataDir else
+        "/var/lib/errbot/${name}";
+    in {
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -p ${dataDir}
+        chown -R errbot:errbot ${dataDir}
+      '';
+      serviceConfig = {
+        User = "errbot";
+        Restart = "on-failure";
+        ExecStart = "${pkgs.errbot}/bin/errbot -c ${mkConfigFile instanceCfg dataDir}";
+        PermissionsStartOnly = true;
+      };
+    })) cfg.instances;
+  };
+}
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index f8881233dceb..3e4584c7a512 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -463,6 +463,7 @@ in {
 
     systemd.services.gitlab = {
       after = [ "network.target" "postgresql.service" "redis.service" ];
+      requires = [ "gitlab-sidekiq.service" ];
       wantedBy = [ "multi-user.target" ];
       environment = gitlabEnv;
       path = with pkgs; [
diff --git a/nixos/modules/services/misc/nix-gc.nix b/nixos/modules/services/misc/nix-gc.nix
index 5c13da6e83dd..304168c65b0b 100644
--- a/nixos/modules/services/misc/nix-gc.nix
+++ b/nixos/modules/services/misc/nix-gc.nix
@@ -53,7 +53,7 @@ in
     systemd.services.nix-gc =
       { description = "Nix Garbage Collector";
         script = "exec ${config.nix.package.out}/bin/nix-collect-garbage ${cfg.options}";
-        startAt = optionalString cfg.automatic cfg.dates;
+        startAt = optional cfg.automatic cfg.dates;
       };
 
   };
diff --git a/nixos/modules/services/misc/nix-optimise.nix b/nixos/modules/services/misc/nix-optimise.nix
index 87ce05c5a11b..a76bfd9f1f19 100644
--- a/nixos/modules/services/misc/nix-optimise.nix
+++ b/nixos/modules/services/misc/nix-optimise.nix
@@ -41,7 +41,7 @@ in
     systemd.services.nix-optimise =
       { description = "Nix Store Optimiser";
         serviceConfig.ExecStart = "${config.nix.package}/bin/nix-store --optimise";
-        startAt = optional cfg.automatic cfg.dates;
+        startAt = optionals cfg.automatic cfg.dates;
       };
 
   };
diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix
index 7c9483911f21..e3f1ec67cbb3 100644
--- a/nixos/modules/services/misc/redmine.nix
+++ b/nixos/modules/services/misc/redmine.nix
@@ -71,7 +71,7 @@ in {
       };
 
       extraConfig = mkOption {
-        type = types.str;
+        type = types.lines;
         default = "";
         description = "Extra configuration in configuration.yml";
       };
diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix
index 6d458feec345..233c47684b7d 100644
--- a/nixos/modules/services/misc/taskserver/default.nix
+++ b/nixos/modules/services/misc/taskserver/default.nix
@@ -154,7 +154,7 @@ let
 
   certtool = "${pkgs.gnutls.bin}/bin/certtool";
 
-  nixos-taskserver = pkgs.buildPythonPackage {
+  nixos-taskserver = pkgs.pythonPackages.buildPythonPackage {
     name = "nixos-taskserver";
     namePrefix = "";
 
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
index 9a1e790d3ab6..496838a131ba 100644
--- a/nixos/modules/services/monitoring/bosun.nix
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -107,7 +107,7 @@ in {
       };
 
       extraConfig = mkOption {
-        type = types.string;
+        type = types.lines;
         default = "";
         description = ''
           Extra configuration options for Bosun. You should describe your
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index 1de3320dc42c..b8be9296bc97 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -167,7 +167,7 @@ in {
             CACHE_TYPE: 'filesystem'
             CACHE_DIR: '/tmp/graphite-api-cache'
         '';
-        type = types.str;
+        type = types.lines;
       };
     };
 
diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix
index aaa041ad4cd6..57df16b58d9c 100644
--- a/nixos/modules/services/monitoring/munin.nix
+++ b/nixos/modules/services/monitoring/munin.nix
@@ -100,6 +100,7 @@ in
 
       extraConfig = mkOption {
         default = "";
+        type = types.lines;
         description = ''
           <filename>munin-node.conf</filename> extra configuration. See
           <link xlink:href='http://munin-monitoring.org/wiki/munin-node.conf' />
diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix
index e6817ee227ab..82b97bd92f87 100644
--- a/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixos/modules/services/monitoring/prometheus/default.nix
@@ -300,13 +300,14 @@ let
       };
       regex = mkOption {
         type = types.str;
+        default = "(.*)";
         description = ''
           Regular expression against which the extracted value is matched.
         '';
       };
       replacement = mkOption {
         type = types.str;
-        default = "";
+        default = "$1";
         description = ''
           Replacement value against which a regex replace is performed if the
           regular expression matches.
@@ -314,6 +315,7 @@ let
       };
       action = mkOption {
         type = types.enum ["replace" "keep" "drop"];
+        default = "replace";
         description = ''
           Action to perform based on regex matching.
         '';
diff --git a/nixos/modules/services/monitoring/riemann-tools.nix b/nixos/modules/services/monitoring/riemann-tools.nix
index ce277f09464a..de858813a762 100644
--- a/nixos/modules/services/monitoring/riemann-tools.nix
+++ b/nixos/modules/services/monitoring/riemann-tools.nix
@@ -50,6 +50,7 @@ in {
 
     systemd.services.riemann-health = {
       wantedBy = [ "multi-user.target" ];
+      path = [ procps ];
       serviceConfig = {
         User = "riemanntools";
         ExecStart = "${healthLauncher}/bin/riemann-health";
diff --git a/nixos/modules/services/monitoring/zabbix-agent.nix b/nixos/modules/services/monitoring/zabbix-agent.nix
index a943075be0c4..88a63b4bf161 100644
--- a/nixos/modules/services/monitoring/zabbix-agent.nix
+++ b/nixos/modules/services/monitoring/zabbix-agent.nix
@@ -53,6 +53,7 @@ in
 
       extraConfig = mkOption {
         default = "";
+        type = types.lines;
         description = ''
           Configuration that is injected verbatim into the configuration file.
         '';
diff --git a/nixos/modules/services/network-filesystems/cachefilesd.nix b/nixos/modules/services/network-filesystems/cachefilesd.nix
new file mode 100644
index 000000000000..619813408405
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/cachefilesd.nix
@@ -0,0 +1,59 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.cachefilesd;
+
+  cfgFile = pkgs.writeText "cachefilesd.conf" ''
+    dir ${cfg.cacheDir}
+    ${cfg.extraConfig}
+  '';
+
+in
+
+{
+  options = {
+    services.cachefilesd = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable cachefilesd network filesystems caching daemon.";
+      };
+
+      cacheDir = mkOption {
+        type = types.str;
+        default = "/var/cache/fscache";
+        description = "Directory to contain filesystem cache.";
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        example = "brun 10%";
+        description = "Additional configuration file entries. See cachefilesd.conf(5) for more information.";
+      };
+
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.cachefilesd = {
+      description = "Local network file caching management daemon";
+      wantedBy = [ "multi-user.target" ];
+      path = [ pkgs.kmod pkgs.cachefilesd ];
+      script = ''
+        modprobe -qab cachefiles
+        mkdir -p ${cfg.cacheDir}
+        chmod 700 ${cfg.cacheDir}
+        exec cachefilesd -n -f ${cfgFile}
+      '';
+    };
+
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/xtreemfs.nix b/nixos/modules/services/network-filesystems/xtreemfs.nix
index b051214e1d08..0c6714563d8a 100644
--- a/nixos/modules/services/network-filesystems/xtreemfs.nix
+++ b/nixos/modules/services/network-filesystems/xtreemfs.nix
@@ -153,6 +153,7 @@ in
           '';
         };
         extraConfig = mkOption {
+          type = types.lines;
           default = "";
           example = ''
             # specify whether SSL is required
@@ -173,6 +174,7 @@ in
         replication = {
           enable = mkEnableOption "XtreemFS DIR replication plugin";
           extraConfig = mkOption {
+            type = types.lines;
             example = ''
               # participants of the replication including this replica
               babudb.repl.participant.0 = 192.168.0.10
@@ -269,6 +271,7 @@ in
           '';
         };
         extraConfig = mkOption {
+          type = types.lines;
           example = ''
             osd_check_interval = 300
             no_atime = true
@@ -307,6 +310,7 @@ in
         replication = {
           enable = mkEnableOption "XtreemFS MRC replication plugin";
           extraConfig = mkOption {
+            type = types.lines;
             example = ''
               # participants of the replication including this replica
               babudb.repl.participant.0 = 192.168.0.10
@@ -385,6 +389,7 @@ in
           '';
         };
         extraConfig = mkOption {
+          type = types.lines;
           example = ''
             local_clock_renewal = 0
             remote_time_sync = 30000
diff --git a/nixos/modules/services/networking/atftpd.nix b/nixos/modules/services/networking/atftpd.nix
index d875ddc63528..e7fd48c99a85 100644
--- a/nixos/modules/services/networking/atftpd.nix
+++ b/nixos/modules/services/networking/atftpd.nix
@@ -20,13 +20,27 @@ in
         default = false;
         type = types.bool;
         description = ''
-          Whenever to enable the atftpd TFTP server.
+          Whether to enable the atftpd TFTP server. By default, the server
+          binds to address 0.0.0.0.
+        '';
+      };
+
+      extraOptions = mkOption {
+        default = [];
+        type = types.listOf types.str;
+        example = literalExample ''
+          [ "--bind-address 192.168.9.1"
+            "--verbose=7"
+          ]
+        '';
+        description = ''
+          Extra command line arguments to pass to atftp.
         '';
       };
 
       root = mkOption {
-        default = "/var/empty";
-        type = types.str;
+        default = "/srv/tftp";
+        type = types.path;
         description = ''
           Document root directory for the atftpd.
         '';
@@ -39,11 +53,11 @@ in
   config = mkIf cfg.enable {
 
     systemd.services.atftpd = {
-      description = "atftpd TFTP server";
+      description = "TFTP Server";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       # runs as nobody
-      serviceConfig.ExecStart = "${pkgs.atftp}/sbin/atftpd --daemon --no-fork --bind-address 0.0.0.0 ${cfg.root}";
+      serviceConfig.ExecStart = "${pkgs.atftp}/sbin/atftpd --daemon --no-fork ${lib.concatStringsSep " " cfg.extraOptions} ${cfg.root}";
     };
 
   };
diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix
index ecc091d1d03d..6a786e75bbc8 100644
--- a/nixos/modules/services/networking/avahi-daemon.nix
+++ b/nixos/modules/services/networking/avahi-daemon.nix
@@ -175,11 +175,20 @@ in
 
     environment.systemPackages = [ pkgs.avahi ];
 
+    systemd.sockets.avahi-daemon =
+      { description = "Avahi mDNS/DNS-SD Stack Activation Socket";
+        listenStreams = [ "/var/run/avahi-daemon/socket" ];
+        wantedBy = [ "sockets.target" ];
+      };
+
     systemd.services.avahi-daemon =
-      { description = "Avahi daemon";
+      { description = "Avahi mDNS/DNS-SD Stack";
         wantedBy = [ "multi-user.target" ];
-        # Receive restart event after resume
-        partOf = [ "post-resume.target" ];
+        requires = [ "avahi-daemon.socket" ];
+
+        serviceConfig."NotifyAccess" = "main";
+        serviceConfig."BusName" = "org.freedesktop.Avahi";
+        serviceConfig."Type" = "dbus";
 
         path = [ pkgs.coreutils pkgs.avahi ];
 
diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix
index 41d7128ec31e..72110e625766 100644
--- a/nixos/modules/services/networking/bind.nix
+++ b/nixos/modules/services/networking/bind.nix
@@ -113,6 +113,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "";
         description = "
           Extra lines to be added verbatim to the generated named configuration file.
diff --git a/nixos/modules/services/networking/chrony.nix b/nixos/modules/services/networking/chrony.nix
index a38142b4a08f..d40865ebbd5b 100644
--- a/nixos/modules/services/networking/chrony.nix
+++ b/nixos/modules/services/networking/chrony.nix
@@ -51,6 +51,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "";
         description = ''
           Extra configuration directives that should be added to
diff --git a/nixos/modules/services/networking/cjdns-hosts.sh b/nixos/modules/services/networking/cjdns-hosts.sh
deleted file mode 100644
index 8a2b47e52143..000000000000
--- a/nixos/modules/services/networking/cjdns-hosts.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-pubs=($pubs)
-hosts=($hosts)
-
-lines="''\n"
-for ((i = 0; i < ${#pubs[*]}; i++)); do
-    addr=$($cjdns/bin/publictoip6 ${pubs[i]})
-    lines="${lines}$addr ${hosts[i]}\n"
-done
-lines="${lines}''"
-
-echo -ne $lines > $out
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index cb00139c5f1c..5e15e40ea0c1 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -28,21 +28,18 @@ let
     };
   };
 
-  peers = mapAttrsToList (n: v: v) (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo);
-
-  pubs  = toString (map (p: if p.hostname == "" then "" else p.publicKey) peers);
-  hosts = toString (map (p: if p.hostname == "" then "" else p.hostname)  peers);
-
-  cjdnsHosts =
-    if hosts != "" then
-      import (pkgs.stdenv.mkDerivation {
-        name = "cjdns-hosts";
-        builder = ./cjdns-hosts.sh;
-
-        inherit (pkgs) cjdns;
-        inherit pubs hosts;
-      })
-    else "";
+  # Additional /etc/hosts entries for peers with an associated hostname
+  cjdnsExtraHosts = import (pkgs.runCommand "cjdns-hosts" {}
+    # Generate a builder that produces an output usable as a Nix string value
+    ''
+      exec >$out
+      echo \'\'
+      ${concatStringsSep "\n" (mapAttrsToList (k: v:
+          optionalString (v.hostname != "")
+            "echo $(${pkgs.cjdns}/bin/publictoip6 ${x.key}) ${x.host}")
+          (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
+      echo \'\'
+    '');
 
   parseModules = x:
     x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; };
@@ -95,8 +92,8 @@ in
       };
 
       confFile = mkOption {
-        type = types.str;
-        default = "";
+        type = types.nullOr types.path;
+        default = null;
         example = "/etc/cjdroute.conf";
         description = ''
           Ignore all other cjdns options and load configuration from this file.
@@ -112,14 +109,14 @@ in
           "49275fut6tmzu354pq70sr5b95qq0vj"
         ];
         description = ''
-          Any remote cjdns nodes that offer these passwords on 
+          Any remote cjdns nodes that offer these passwords on
           connection will be allowed to route through this node.
         '';
       };
-    
+
       admin = {
         bind = mkOption {
-          type = types.string;
+          type = types.str;
           default = "127.0.0.1:11234";
           description = ''
             Bind the administration port to this address and port.
@@ -129,7 +126,7 @@ in
 
       UDPInterface = {
         bind = mkOption {
-          type = types.string;
+          type = types.str;
           default = "";
           example = "192.168.1.32:43211";
           description = ''
@@ -154,6 +151,7 @@ in
 
       ETHInterface = {
         bind = mkOption {
+          type = types.str;
           default = "";
           example = "eth0";
           description =
@@ -201,7 +199,7 @@ in
 
   };
 
-  config = mkIf config.services.cjdns.enable {
+  config = mkIf cfg.enable {
 
     boot.kernelModules = [ "tun" ];
 
@@ -212,7 +210,7 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
 
-      preStart = if cfg.confFile != "" then "" else ''
+      preStart = if cfg.confFile != null then "" else ''
         [ -e /etc/cjdns.keys ] && source /etc/cjdns.keys
 
         if [ -z "$CJDNS_PRIVATE_KEY" ]; then
@@ -228,13 +226,13 @@ in
         fi
 
         if [ -z "$CJDNS_ADMIN_PASSWORD" ]; then
-            echo "CJDNS_ADMIN_PASSWORD=$(${pkgs.coreutils}/bin/head -c 96 /dev/urandom | ${pkgs.coreutils}/bin/tr -dc A-Za-z0-9)" \
+            echo "CJDNS_ADMIN_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 96)" \
                 >> /etc/cjdns.keys
         fi
       '';
 
       script = (
-        if cfg.confFile != "" then "${pkg}/bin/cjdroute < ${cfg.confFile}" else
+        if cfg.confFile != null then "${pkg}/bin/cjdroute < ${cfg.confFile}" else
           ''
             source /etc/cjdns.keys
             echo '${cjdrouteConf}' | sed \
@@ -247,13 +245,16 @@ in
       serviceConfig = {
         Type = "forking";
         Restart = "on-failure";
+
+        ProtectHome = true;
+        PrivateTmp = true;
       };
     };
 
-    networking.extraHosts = "${cjdnsHosts}";
+    networking.extraHosts = cjdnsExtraHosts;
 
     assertions = [
-      { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != "" );
+      { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != null );
         message = "Neither cjdns.ETHInterface.bind nor cjdns.UDPInterface.bind defined.";
       }
       { assertion = config.networking.enableIPv6;
diff --git a/nixos/modules/services/networking/cntlm.nix b/nixos/modules/services/networking/cntlm.nix
index 76c0fd7d0ea3..890ff5084078 100644
--- a/nixos/modules/services/networking/cntlm.nix
+++ b/nixos/modules/services/networking/cntlm.nix
@@ -61,6 +61,7 @@ in
       };
 
      extraConfig = mkOption {
+        type = types.lines;
         default = "";
         description = "Verbatim contents of <filename>cntlm.conf</filename>.";
      };
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index e74d68cad902..5050ecbd7492 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -89,7 +89,7 @@ in
 
       extraConfig = mkOption {
         default = "";
-        type = str;
+        type = lines;
         description = ''
           Extra configuration. Contents will be added verbatim to the configuration file.
         '';
diff --git a/nixos/modules/services/networking/dhcpd.nix b/nixos/modules/services/networking/dhcpd.nix
index 900df67b53aa..d2cd00e74a1f 100644
--- a/nixos/modules/services/networking/dhcpd.nix
+++ b/nixos/modules/services/networking/dhcpd.nix
@@ -47,6 +47,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "";
         example = ''
           option subnet-mask 255.255.255.0;
@@ -66,6 +67,14 @@ in
         ";
       };
 
+      extraFlags = mkOption {
+        default = "";
+        example = "-6";
+        description = "
+          Additional command line flags to be passed to the dhcpd daemon.
+        ";
+      };
+
       configFile = mkOption {
         default = null;
         description = "
@@ -138,6 +147,7 @@ in
           { ExecStart = "@${pkgs.dhcp}/sbin/dhcpd dhcpd"
               + " -pf /run/dhcpd/dhcpd.pid -cf ${configFile}"
               + " -lf ${stateDir}/dhcpd.leases -user dhcpd -group nogroup"
+              + " ${cfg.extraFlags}"
               + " ${toString cfg.interfaces}";
             Restart = "always";
             Type = "forking";
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index 2714e8d75993..5a24db8ccba0 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -35,7 +35,11 @@ in
 
   options = {
     services.dnscrypt-proxy = {
-      enable = mkEnableOption "DNSCrypt client proxy";
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Whether to enable the DNSCrypt client proxy";
+      };
 
       localAddress = mkOption {
         default = "127.0.0.1";
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.xml b/nixos/modules/services/networking/dnscrypt-proxy.xml
index e212a8d3e2c3..982961833ad2 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.xml
+++ b/nixos/modules/services/networking/dnscrypt-proxy.xml
@@ -49,8 +49,8 @@
   <para>
     <programlisting>
       {
-      services.dnsmasq.enable = true;
-      services.dnsmasq.servers = [ "127.0.0.1#43" ];
+        services.dnsmasq.enable = true;
+        services.dnsmasq.servers = [ "127.0.0.1#43" ];
       }
     </programlisting>
   </para>
@@ -60,12 +60,9 @@
   <para>
     <programlisting>
       {
-      networking.nameservers = [ "127.0.0.1" ];
-      services.unbound.enable = true;
-      services.unbound.forwardAddresses = [ "127.0.0.1@43" ];
-      services.unbound.extraConfig = ''
-        do-not-query-localhost: no
-      '';
+        networking.nameservers = [ "127.0.0.1" ];
+        services.unbound.enable = true;
+        services.unbound.forwardAddresses = [ "127.0.0.1@43" ];
       }
     </programlisting>
   </para>
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index 942fcc03f59b..1c0ea5034df3 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -100,13 +100,13 @@ let
 
     # Perform a reverse-path test to refuse spoofers
     # For now, we just drop, as the raw table doesn't have a log-refuse yet
-    ${optionalString (kernelHasRPFilter && cfg.checkReversePath) ''
+    ${optionalString (kernelHasRPFilter && (cfg.checkReversePath != false)) ''
       # Clean up rpfilter rules
       ip46tables -t raw -D PREROUTING -j nixos-fw-rpfilter 2> /dev/null || true
       ip46tables -t raw -F nixos-fw-rpfilter 2> /dev/null || true
       ip46tables -t raw -N nixos-fw-rpfilter 2> /dev/null || true
 
-      ip46tables -t raw -A nixos-fw-rpfilter -m rpfilter -j RETURN
+      ip46tables -t raw -A nixos-fw-rpfilter -m rpfilter ${optionalString (cfg.checkReversePath == "loose") "--loose"} -j RETURN
 
       # Allows this host to act as a DHCPv4 server
       iptables -t raw -A nixos-fw-rpfilter -s 0.0.0.0 -d 255.255.255.255 -p udp --sport 68 --dport 67 -j RETURN
@@ -200,7 +200,7 @@ let
     # Clean up after added ruleset
     ip46tables -D INPUT -j nixos-fw 2>/dev/null || true
 
-    ${optionalString (kernelHasRPFilter && cfg.checkReversePath) ''
+    ${optionalString (kernelHasRPFilter && (cfg.checkReversePath != false)) ''
       ip46tables -t raw -D PREROUTING -j nixos-fw-rpfilter 2>/dev/null || true
     ''}
 
@@ -373,7 +373,7 @@ in
 
     networking.firewall.checkReversePath = mkOption {
       default = kernelHasRPFilter;
-      type = types.bool;
+      type = types.either types.bool (types.enum ["strict" "loose"]);
       description =
         ''
           Performs a reverse path filter test on a packet.
@@ -381,7 +381,8 @@ in
           that the packet arrived on, it is refused.
 
           If using asymmetric routing or other complicated routing,
-          disable this setting and setup your own counter-measures.
+          set this option to loose mode or disable it and setup your
+          own counter-measures.
 
           (needs kernel 3.3+)
         '';
@@ -482,7 +483,7 @@ in
       options nf_conntrack nf_conntrack_helper=0
     '';
 
-    assertions = [ { assertion = ! cfg.checkReversePath || kernelHasRPFilter;
+    assertions = [ { assertion = (cfg.checkReversePath != false) || kernelHasRPFilter;
                      message = "This kernel does not support rpfilter"; }
                    { assertion = cfg.autoLoadConntrackHelpers || kernelCanDisableHelpers;
                      message = "This kernel does not support disabling conntrack helpers"; }
diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix
index 287964aab072..51f95af48029 100644
--- a/nixos/modules/services/networking/hostapd.nix
+++ b/nixos/modules/services/networking/hostapd.nix
@@ -140,7 +140,7 @@ in
           ieee80211n=1
           ht_capab=[HT40-][SHORT-GI-40][DSSS_CCK-40]
           '';
-        type = types.string;
+        type = types.lines;
         description = "Extra configuration options to put in hostapd.conf.";
       };
     };
diff --git a/nixos/modules/services/networking/ircd-hybrid/builder.sh b/nixos/modules/services/networking/ircd-hybrid/builder.sh
index f2c92878a4dc..38312210df25 100644
--- a/nixos/modules/services/networking/ircd-hybrid/builder.sh
+++ b/nixos/modules/services/networking/ircd-hybrid/builder.sh
@@ -12,7 +12,7 @@ for i in $scripts; do
     if test "$(echo $i | cut -c1-2)" = "=>"; then
         subDir=$(echo $i | cut -c3-)
     else
-        dst=$out/$subDir/$((stripHash $i; echo $strippedName) | sed 's/\.in//')
+        dst=$out/$subDir/$(stripHash $i | sed 's/\.in//')
         doSub $i $dst
         chmod +x $dst # !!!
     fi
@@ -23,7 +23,7 @@ for i in $substFiles; do
     if test "$(echo $i | cut -c1-2)" = "=>"; then
         subDir=$(echo $i | cut -c3-)
     else
-        dst=$out/$subDir/$((stripHash $i; echo $strippedName) | sed 's/\.in//')
+        dst=$out/$subDir/$(stripHash $i | sed 's/\.in//')
         doSub $i $dst
     fi
 done
diff --git a/nixos/modules/services/networking/kippo.nix b/nixos/modules/services/networking/kippo.nix
index 5f3efcd133a1..834de4fdc09f 100644
--- a/nixos/modules/services/networking/kippo.nix
+++ b/nixos/modules/services/networking/kippo.nix
@@ -46,7 +46,7 @@ rec {
       };
       extraConfig = mkOption {
         default = "";
-        type = types.string;
+        type = types.lines;
         description = ''Extra verbatim configuration added to the end of kippo.cfg.'';
       };
     };
@@ -54,7 +54,7 @@ rec {
   };
   config = mkIf cfg.enable {
     environment.systemPackages = with pkgs.pythonPackages; [
-      python twisted_11 pycrypto pyasn1 ];
+      python pkgs.kippo.twisted pycrypto pyasn1 ];
 
     environment.etc."kippo.cfg".text = ''
         # Automatically generated by NixOS.
@@ -84,7 +84,7 @@ rec {
       description = "Kippo Web Server";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      environment.PYTHONPATH = "${pkgs.kippo}/src/:${pkgs.pythonPackages.pycrypto}/lib/python2.7/site-packages/:${pkgs.pythonPackages.pyasn1}/lib/python2.7/site-packages/:${pkgs.pythonPackages.python}/lib/python2.7/site-packages/:${pkgs.pythonPackages.twisted_11}/lib/python2.7/site-packages/:.";
+      environment.PYTHONPATH = "${pkgs.kippo}/src/:${pkgs.pythonPackages.pycrypto}/lib/python2.7/site-packages/:${pkgs.pythonPackages.pyasn1}/lib/python2.7/site-packages/:${pkgs.pythonPackages.python}/lib/python2.7/site-packages/:${pkgs.kippo.twisted}/lib/python2.7/site-packages/:.";
       preStart = ''
         if [ ! -d ${cfg.varPath}/ ] ; then
             mkdir -p ${cfg.logPath}/tty
@@ -107,7 +107,7 @@ rec {
         fi
       '';
 
-      serviceConfig.ExecStart = "${pkgs.pythonPackages.twisted_11}/bin/twistd -y ${pkgs.kippo}/src/kippo.tac --syslog --rundir=${cfg.varPath}/ --pidfile=${cfg.pidPath}/kippo.pid --prefix=kippo -n";
+      serviceConfig.ExecStart = "${pkgs.kippo.twisted}/bin/twistd -y ${pkgs.kippo}/src/kippo.tac --syslog --rundir=${cfg.varPath}/ --pidfile=${cfg.pidPath}/kippo.pid --prefix=kippo -n";
       serviceConfig.PermissionsStartOnly = true;
       serviceConfig.User = "kippo"; 
       serviceConfig.Group = "kippo"; 
diff --git a/nixos/modules/services/networking/murmur.nix b/nixos/modules/services/networking/murmur.nix
index 134544cda681..81f968ae9fe1 100644
--- a/nixos/modules/services/networking/murmur.nix
+++ b/nixos/modules/services/networking/murmur.nix
@@ -230,7 +230,7 @@ in
       };
 
       extraConfig = mkOption {
-        type = types.str;
+        type = types.lines;
         default = "";
         description = "Extra configuration to put into mumur.ini.";
       };
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 65ffaece4772..8f353979d3fc 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -198,6 +198,9 @@ in {
       { source = "${networkmanager_l2tp}/etc/NetworkManager/VPN/nm-l2tp-service.name";
         target = "NetworkManager/VPN/nm-l2tp-service.name";
       }
+      { source = "${networkmanager_strongswan}/etc/NetworkManager/VPN/nm-strongswan-service.name";
+        target = "NetworkManager/VPN/nm-strongswan-service.name";
+      }
     ] ++ optional (cfg.appendNameservers == [] || cfg.insertNameservers == [])
            { source = overrideNameserversScript;
              target = "NetworkManager/dispatcher.d/02overridedns";
diff --git a/nixos/modules/services/networking/openfire.nix b/nixos/modules/services/networking/openfire.nix
index ed91b45ec945..454b504eda21 100644
--- a/nixos/modules/services/networking/openfire.nix
+++ b/nixos/modules/services/networking/openfire.nix
@@ -47,7 +47,7 @@ with lib;
         export HOME=/tmp
         mkdir /var/log/openfire || true
         mkdir /etc/openfire || true
-        for i in ${openfire}/conf.inst/*; do
+        for i in ${pkgs.openfire}/conf.inst/*; do
             if ! test -f /etc/openfire/$(basename $i); then
                 cp $i /etc/openfire/
             fi
diff --git a/nixos/modules/services/networking/prayer.nix b/nixos/modules/services/networking/prayer.nix
index cb8fe6bf4fe9..9d63f549b23a 100644
--- a/nixos/modules/services/networking/prayer.nix
+++ b/nixos/modules/services/networking/prayer.nix
@@ -56,6 +56,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = "" ;
         description = ''
           Extra configuration. Contents will be added verbatim to the configuration file.
diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix
index 247c4f1efb07..5682b506344c 100644
--- a/nixos/modules/services/networking/prosody.nix
+++ b/nixos/modules/services/networking/prosody.nix
@@ -195,6 +195,7 @@ in
       };
 
       extraConfig = mkOption {
+        type = types.lines;
         default = '''';
         description = "Additional prosody configuration";
       };
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index f7a5926dc64b..0c1f8d8cdb91 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -6,31 +6,39 @@ let
   cfg = config.services.smokeping;
   smokepingHome = "/var/lib/smokeping";
   smokepingPidDir = "/run";
-  configFile = ''
-    *** General ***
-    owner = ${cfg.owner}
-    contact = ${cfg.ownerEmail}
-    mailhost = ${cfg.mailHost}
-    #sendmail = /var/setuid-wrappers/sendmail
-    imgcache = ${smokepingHome}/cache
-    imgurl   = http://${cfg.hostName}:${builtins.toString cfg.port}/cache
-    datadir  = ${smokepingHome}/data
-    piddir  = ${smokepingPidDir}
-    cgiurl   = http://${cfg.hostName}:${builtins.toString cfg.port}/smokeping.cgi
-    smokemail = ${cfg.smokeMailTemplate}
-    *** Presentation ***
-    template = ${cfg.presentationTemplate}
-    ${cfg.presentationConfig}
-    #*** Alerts ***
-    #${cfg.alertConfig}
-    *** Database ***
-    ${cfg.databaseConfig}
-    *** Probes ***
-    ${cfg.probeConfig}
-    *** Targets ***
-    ${cfg.targetConfig}
-    ${cfg.extraConfig}
-  '';
+  configFile =
+    if cfg.config == null
+      then
+        ''
+          *** General ***
+          owner = ${cfg.owner}
+          contact = ${cfg.ownerEmail}
+          ${lib.optionalString (cfg.mailHost != "") "mailhost = ${cfg.mailHost}"}
+          ${lib.optionalString (cfg.sendmail != null) "sendmail = ${cfg.sendmail}"}
+          imgcache = ${smokepingHome}/cache
+          imgurl   = http://${cfg.hostName}:${builtins.toString cfg.port}/cache
+          datadir  = ${smokepingHome}/data
+          pagedir = ${smokepingHome}/cache
+          piddir  = ${smokepingPidDir}
+          cgiurl   = http://${cfg.hostName}:${builtins.toString cfg.port}/smokeping.cgi
+          linkstyle = ${cfg.linkStyle}
+          smokemail = ${cfg.smokeMailTemplate}
+          *** Presentation ***
+          template = ${cfg.presentationTemplate}
+          ${cfg.presentationConfig}
+          *** Alerts ***
+          ${cfg.alertConfig}
+          *** Database ***
+          ${cfg.databaseConfig}
+          *** Probes ***
+          ${cfg.probeConfig}
+          *** Targets ***
+          ${cfg.targetConfig}
+          ${cfg.extraConfig}
+        ''
+      else
+        cfg.config;
+
   configPath = pkgs.writeText "smokeping.conf" configFile;
   cgiHome = pkgs.writeScript "smokeping.fcgi" ''
     #!${pkgs.bash}/bin/bash
@@ -59,8 +67,15 @@ in
       };
       mailHost = mkOption {
         type = types.string;
-        default = "127.0.0.1";
-        description = "Use this SMTP server rather than localhost";
+        default = "";
+        example = "localhost";
+        description = "Use this SMTP server to send alerts";
+      };
+      sendmail = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/var/setuid-wrappers/sendmail";
+        description = "Use this sendmail compatible script to deliver alerts";
       };
       smokeMailTemplate = mkOption {
         type = types.string;
@@ -71,6 +86,7 @@ in
       package = mkOption {
         type = types.package;
         default = pkgs.smokeping;
+        defaultText = "pkgs.smokeping";
         description = "Specify a custom smokeping package";
       };
       owner = mkOption {
@@ -85,6 +101,12 @@ in
         example = "somewhere.example.com";
         description = "DNS name for the urls generated in the cgi.";
       };
+      linkStyle = mkOption {
+        type = types.enum ["original" "absolute" "relative"];
+        default = "relative";
+        example = "absolute";
+        description = "DNS name for the urls generated in the cgi.";
+      };
       port = mkOption {
         type = types.int;
         default = 8081;
@@ -132,7 +154,10 @@ in
       };
       alertConfig = mkOption {
         type = types.string;
-        default = "";
+        default = ''
+          to = root@localhost
+          from = smokeping@localhost
+        '';
         example = literalExample ''
           to = alertee@address.somewhere
           from = smokealert@company.xy
@@ -219,16 +244,30 @@ in
         description = "Target configuration";
       };
       extraConfig = mkOption {
-        type = types.string;
+        type = types.lines;
         default = "";
         description = "Any additional customization not already included.";
       };
+      config = mkOption {
+        type = types.nullOr types.string;
+        default = null;
+        description = "Full smokeping config supplied by the user. Overrides " +
+          "and replaces any other configuration supplied.";
+      };
 
     };
 
   };
 
   config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = !(cfg.sendmail != null && cfg.mailHost != "");
+        message = "services.smokeping: sendmail and Mailhost cannot both be enabled.";
+      }
+    ];
+    security.setuidPrograms = [ "fping" ];
+    environment.systemPackages = [ pkgs.fping ];
     users.extraUsers = singleton {
       name = cfg.user;
       isNormalUser = false;
@@ -243,9 +282,12 @@ in
       serviceConfig.PermissionsStartOnly = true;
       preStart = ''
         mkdir -m 0755 -p ${smokepingHome}/cache ${smokepingHome}/data
+        rm -f ${smokepingHome}/cropper
+        ln -s ${cfg.package}/htdocs/cropper ${smokepingHome}/cropper
         chown -R ${cfg.user} ${smokepingHome}
         cp ${cgiHome} ${smokepingHome}/smokeping.fcgi
         ${cfg.package}/bin/smokeping --check --config=${configPath}
+        ${cfg.package}/bin/smokeping --static --config=${configPath}
       '';
       script = ''${cfg.package}/bin/smokeping --config=${configPath} --nodaemon'';
     };
@@ -253,8 +295,9 @@ in
       wantedBy = [ "multi-user.target"];
       requires = [ "smokeping.service"];
       partOf = [ "smokeping.service"];
-      path = with pkgs; [ bash rrdtool smokeping ];
-      script = ''${pkgs.thttpd}/bin/thttpd -u ${cfg.user} -c "**.fcgi" -d ${smokepingHome} -p ${builtins.toString cfg.port} -D'';
+      path = with pkgs; [ bash rrdtool smokeping thttpd ];
+      script = ''thttpd -u ${cfg.user} -c "**.fcgi" -d ${smokepingHome} -p ${builtins.toString cfg.port} -D -nos'';
+      serviceConfig.Restart = "always";
     };
   };
 }
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 3e9fae35847e..81941ce1cfb6 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -242,7 +242,7 @@ in
 
     systemd =
       let
-        service =
+        sshd-service =
           { description = "SSH Daemon";
 
             wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target";
@@ -253,16 +253,8 @@ in
 
             environment.LD_LIBRARY_PATH = nssModulesPath;
 
-            preStart =
-              ''
-                mkdir -m 0755 -p /etc/ssh
-
-                ${flip concatMapStrings cfg.hostKeys (k: ''
-                  if ! [ -f "${k.path}" ]; then
-                      ssh-keygen -t "${k.type}" ${if k ? bits then "-b ${toString k.bits}" else ""} -f "${k.path}" -N ""
-                  fi
-                '')}
-              '';
+            wants = [ "sshd-keygen.service" ];
+            after = [ "sshd-keygen.service" ];
 
             serviceConfig =
               { ExecStart =
@@ -278,6 +270,26 @@ in
                 PIDFile = "/run/sshd.pid";
               });
           };
+
+        sshd-keygen-service =
+          { description = "SSH Host Key Generation";
+            path = [ cfgc.package ];
+            script =
+            ''
+              mkdir -m 0755 -p /etc/ssh
+              ${flip concatMapStrings cfg.hostKeys (k: ''
+                if ! [ -f "${k.path}" ]; then
+                  ssh-keygen -t "${k.type}" ${if k ? bits then "-b ${toString k.bits}" else ""} -f "${k.path}" -N ""
+                fi
+              '')}
+            '';
+
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = "yes";
+            };
+          };
+
       in
 
       if cfg.startWhenNeeded then {
@@ -289,11 +301,13 @@ in
             socketConfig.Accept = true;
           };
 
-        services."sshd@" = service;
+        services.sshd-keygen = sshd-keygen-service;
+        services."sshd@" = sshd-service;
 
       } else {
 
-        services.sshd = service;
+        services.sshd-keygen = sshd-keygen-service;
+        services.sshd = sshd-service;
 
       };
 
diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix
index e433ec7c5b9b..0c459fb1dd0c 100644
--- a/nixos/modules/services/networking/supplicant.nix
+++ b/nixos/modules/services/networking/supplicant.nix
@@ -34,7 +34,8 @@ let
       '';
     in
       { description = "Supplicant ${iface}${optionalString (iface=="WLAN"||iface=="LAN") " %I"}";
-        wantedBy = [ "network.target" ] ++ deps;
+        wantedBy = [ "multi-user.target" ] ++ deps;
+        wants = [ "network.target" ];
         bindsTo = deps;
         after = deps;
         before = [ "network.target" ];
diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix
index 8a430734319b..dcdc203bdc62 100644
--- a/nixos/modules/services/networking/syncthing.nix
+++ b/nixos/modules/services/networking/syncthing.nix
@@ -3,46 +3,11 @@
 with lib;
 
 let
-
   cfg = config.services.syncthing;
   defaultUser = "syncthing";
-
-  header = {
-    description = "Syncthing service";
-    after = [ "network.target" ];
-    environment = {
-      STNORESTART = "yes";
-      STNOUPGRADE = "yes";
-      inherit (cfg) all_proxy;
-    } // config.networking.proxy.envVars;
-  };
-
-  service = {
-    Restart = "on-failure";
-    SuccessExitStatus = "2 3 4";
-    RestartForceExitStatus="3 4";
-  };
-
-  iNotifyHeader = {
-    description = "Syncthing Inotify File Watcher service";
-    after = [ "network.target" "syncthing.service" ];
-    requires = [ "syncthing.service" ];
-  };
-
-  iNotifyService = {
-    SuccessExitStatus = "2";
-    RestartForceExitStatus = "3";
-    Restart = "on-failure";
-  };
-
-in
-
-{
-
+in {
   ###### interface
-
   options = {
-
     services.syncthing = {
 
       enable = mkEnableOption ''
@@ -100,6 +65,19 @@ in
         '';
       };
 
+      openDefaultPorts = mkOption {
+        type = types.bool;
+        default = false;
+        example = literalExample "true";
+        description = ''
+          Open the default ports in the firewall:
+            - TCP 22000 for transfers
+            - UDP 21027 for discovery
+          If multiple users are running syncthing on this machine, you will need to manually open a set of ports for each instance and leave this disabled.
+          Alternatively, if are running only a single instance on this machine using the default ports, enable this.
+        '';
+      };
+
       package = mkOption {
         type = types.package;
         default = pkgs.syncthing;
@@ -117,6 +95,14 @@ in
 
   config = mkIf cfg.enable {
 
+    networking.firewall = mkIf cfg.openDefaultPorts {
+      allowedTCPPorts = [ 22000 ];
+      allowedUDPPorts = [ 21027 ];
+    };
+
+    systemd.packages = [ pkgs.syncthing ]
+                       ++ lib.optional cfg.useInotify pkgs.syncthing-inotify;
+
     users = mkIf (cfg.user == defaultUser) {
       extraUsers."${defaultUser}" =
         { group = cfg.group;
@@ -131,39 +117,44 @@ in
     };
 
     systemd.services = {
-      syncthing = mkIf cfg.systemService (header // {
-          wants = mkIf cfg.useInotify [ "syncthing-inotify.service" ];
-          wantedBy = [ "multi-user.target" ];
-          serviceConfig = service // {
-            User = cfg.user;
-            Group = cfg.group;
-            PermissionsStartOnly = true;
-            ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}";
-          };
-      });
-
-      syncthing-inotify = mkIf (cfg.systemService && cfg.useInotify) (iNotifyHeader // {
+      syncthing = mkIf cfg.systemService {
+        description = "Syncthing service";
+        after = [ "network.target" ];
+        environment = {
+          STNORESTART = "yes";
+          STNOUPGRADE = "yes";
+          inherit (cfg) all_proxy;
+        } // config.networking.proxy.envVars;
+        wants = mkIf cfg.useInotify [ "syncthing-inotify.service" ];
         wantedBy = [ "multi-user.target" ];
-        serviceConfig = iNotifyService // {
+        serviceConfig = {
+          Restart = "on-failure";
+          SuccessExitStatus = "2 3 4";
+          RestartForceExitStatus="3 4";
           User = cfg.user;
-          ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -home=${cfg.dataDir} -logflags=0";
+          Group = cfg.group;
+          PermissionsStartOnly = true;
+          ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}";
         };
-      });
-    };
+      };
 
-    systemd.user.services = {
-      syncthing = header // {
-        serviceConfig = service // {
-          ExecStart = "${cfg.package}/bin/syncthing -no-browser";
-        };
+      syncthing-resume = {
+        wantedBy = [ "suspend.target" ];
       };
 
-      syncthing-inotify = mkIf cfg.useInotify (iNotifyHeader // {
-        serviceConfig = iNotifyService // {
-          ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -logflags=0";
+      syncthing-inotify = mkIf (cfg.systemService && cfg.useInotify) {
+        description = "Syncthing Inotify File Watcher service";
+        after = [ "network.target" "syncthing.service" ];
+        requires = [ "syncthing.service" ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          SuccessExitStatus = "2";
+          RestartForceExitStatus = "3";
+          Restart = "on-failure";
+          User = cfg.user;
+          ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -home=${cfg.dataDir} -logflags=0";
         };
-      });
+      };
     };
-
   };
 }
diff --git a/nixos/modules/services/networking/tftpd.nix b/nixos/modules/services/networking/tftpd.nix
index 9b3cc6b8ec4f..c9c0a2b321d5 100644
--- a/nixos/modules/services/networking/tftpd.nix
+++ b/nixos/modules/services/networking/tftpd.nix
@@ -13,12 +13,13 @@ with lib;
       default = false;
       description = ''
         Whether to enable tftpd, a Trivial File Transfer Protocol server.
+        The server will be run as an xinetd service.
       '';
     };
 
     services.tftpd.path = mkOption {
       type = types.path;
-      default = "/home/tftp";
+      default = "/srv/tftp";
       description = ''
         Where the tftp server files are stored.
       '';
diff --git a/nixos/modules/services/networking/unbound.nix b/nixos/modules/services/networking/unbound.nix
index 6375ebee3209..f3a04d97c98e 100644
--- a/nixos/modules/services/networking/unbound.nix
+++ b/nixos/modules/services/networking/unbound.nix
@@ -79,7 +79,7 @@ in
 
       extraConfig = mkOption {
         default = "";
-        type = types.str;
+        type = types.lines;
         description = ''
           Extra unbound config. See
           <citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix
new file mode 100644
index 000000000000..35918e42b402
--- /dev/null
+++ b/nixos/modules/services/networking/wireguard.nix
@@ -0,0 +1,225 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.networking.wireguard;
+
+  kernel = config.boot.kernelPackages;
+
+  # interface options
+
+  interfaceOpts = { name, ... }: {
+
+    options = {
+
+      ips = mkOption {
+        example = [ "192.168.2.1/24" ];
+        default = [];
+        type = with types; listOf str;
+        description = "The IP addresses of the interface.";
+      };
+
+      privateKey = mkOption {
+        example = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
+        type = types.str;
+        description = "Base64 private key generated by wg genkey.";
+      };
+
+      presharedKey = mkOption {
+        default = null;
+        example = "rVXs/Ni9tu3oDBLS4hOyAUAa1qTWVA3loR8eL20os3I=";
+        type = with types; nullOr str;
+        description = ''base64 preshared key generated by wg genpsk. Optional,
+        and may be omitted. This option adds an additional layer of
+        symmetric-key cryptography to be mixed into the already existing
+        public-key  cryptography, for post-quantum resistance.'';
+      };
+
+      listenPort = mkOption {
+        default = null;
+        type = with types; nullOr int;
+        example = 51820;
+        description = ''16-bit port for listening. Optional; if not specified,
+        automatically generated based on interface name.'';
+      };
+
+      preSetup = mkOption {
+        example = literalExample [''
+          ${pkgs.iproute}/bin/ip netns add foo
+        ''];
+        default = [];
+        type = with types; listOf str;
+        description = ''A list of commands called at the start of the interface
+        setup.'';
+      };
+
+      postSetup = mkOption {
+        example = literalExample [''
+          ${pkgs.bash} -c 'printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0'
+        ''];
+        default = [];
+        type = with types; listOf str;
+        description = "A list of commands called at the end of the interface setup.";
+      };
+
+      postShutdown = mkOption {
+        example = literalExample ["${pkgs.openresolv}/bin/resolvconf -d wg0"];
+        default = [];
+        type = with types; listOf str;
+        description = "A list of commands called after shutting down the interface.";
+      };
+
+      peers = mkOption {
+        default = [];
+        description = "Peers linked to the interface.";
+        type = with types; listOf (submodule peerOpts);
+      };
+
+    };
+
+  };
+
+  # peer options
+
+  peerOpts = {
+
+    options = {
+
+      publicKey = mkOption {
+        example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
+        type = types.str;
+        description = "The base64 public key the peer.";
+      };
+
+      allowedIPs = mkOption {
+        example = [ "10.192.122.3/32" "10.192.124.1/24" ];
+        type = with types; listOf str;
+        description = ''List of IP (v4 or v6) addresses with CIDR masks from
+        which this peer is allowed to send incoming traffic and to which
+        outgoing traffic for this peer is directed. The catch-all 0.0.0.0/0 may
+        be specified for matching all IPv4 addresses, and ::/0 may be specified
+        for matching all IPv6 addresses.'';
+      };
+
+      endpoint = mkOption {
+        default = null;
+        example = "demo.wireguard.io:12913";
+        type = with types; nullOr str;
+        description = ''Endpoint IP or hostname of the peer, followed by a colon,
+        and then a port number of the peer.'';
+      };
+
+      persistentKeepalive = mkOption {
+        default = null;
+        type = with types; nullOr int;
+        example = 25;
+        description = ''This is optional and is by default off, because most
+        users will not need it. It represents, in seconds, between 1 and 65535
+        inclusive, how often to send an authenticated empty packet to the peer,
+        for the purpose of keeping a stateful firewall or NAT mapping valid
+        persistently. For example, if the interface very rarely sends traffic,
+        but it might at anytime receive traffic from a peer, and it is behind
+        NAT, the interface might benefit from having a persistent keepalive
+        interval of 25 seconds; however, most users will not need this.'';
+      };
+
+    };
+
+  };
+
+  generateConf = name: values: pkgs.writeText "wireguard-${name}.conf" ''
+    [Interface]
+    PrivateKey = ${values.privateKey}
+    ${optionalString (values.presharedKey != null) "PresharedKey = ${values.presharedKey}"}
+    ${optionalString (values.listenPort != null)   "ListenPort = ${toString values.listenPort}"}
+
+    ${concatStringsSep "\n\n" (map (peer: ''
+    [Peer]
+    PublicKey = ${peer.publicKey}
+    ${optionalString (peer.allowedIPs != []) "AllowedIPs = ${concatStringsSep ", " peer.allowedIPs}"}
+    ${optionalString (peer.endpoint != null) "Endpoint = ${peer.endpoint}"}
+    ${optionalString (peer.persistentKeepalive != null) "PersistentKeepalive = ${toString peer.persistentKeepalive}"}
+    '') values.peers)}
+  '';
+
+  ipCommand = "${pkgs.iproute}/bin/ip";
+  wgCommand = "${pkgs.wireguard}/bin/wg";
+
+  generateUnit = name: values:
+    nameValuePair "wireguard-${name}"
+      {
+        description = "WireGuard Tunnel - ${name}";
+        wantedBy = [ "ip-up.target" ];
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = true;
+          ExecStart = lib.flatten([
+            values.preSetup
+
+            "-${ipCommand} link del dev ${name}"
+            "${ipCommand} link add dev ${name} type wireguard"
+            "${wgCommand} setconf ${name} ${generateConf name values}"
+
+            (map (ip:
+            ''${ipCommand} address add ${ip} dev ${name}''
+            ) values.ips)
+
+            "${ipCommand} link set up dev ${name}"
+
+            (flatten (map (peer: (map (ip:
+            "${ipCommand} route add ${ip} dev ${name}"
+            ) peer.allowedIPs)) values.peers))
+
+            values.postSetup
+          ]);
+
+          ExecStop = [ ''${ipCommand} link del dev "${name}"'' ] ++ values.postShutdown;
+        };
+      };
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    networking.wireguard = {
+
+      interfaces = mkOption {
+        description = "Wireguard interfaces.";
+        default = {};
+        example = {
+          wg0 = {
+            ips = [ "192.168.20.4/24" ];
+            privateKey = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
+            peers = [
+              { allowedIPs = [ "192.168.20.1/32" ];
+                publicKey  = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
+                endpoint   = "demo.wireguard.io:12913"; }
+            ];
+          };
+        };
+        type = with types; attrsOf (submodule interfaceOpts);
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf (cfg.interfaces != {}) {
+
+    boot.extraModulePackages = [ kernel.wireguard ];
+    environment.systemPackages = [ pkgs.wireguard ];
+
+    systemd.services = mapAttrs' generateUnit cfg.interfaces;
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index a344d7855463..5657b91c1e72 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -128,9 +128,11 @@ in {
     in {
       description = "WPA Supplicant";
 
-      after = [ "network.target" ] ++ lib.concatMap deviceUnit ifaces;
+      after = lib.concatMap deviceUnit ifaces;
+      before = [ "network.target" ];
+      wants = [ "network.target" ];
       requires = lib.concatMap deviceUnit ifaces;
-      wantedBy = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
 
       path = [ pkgs.wpa_supplicant ];
 
diff --git a/nixos/modules/services/networking/xinetd.nix b/nixos/modules/services/networking/xinetd.nix
index 270122ee659c..002245027804 100644
--- a/nixos/modules/services/networking/xinetd.nix
+++ b/nixos/modules/services/networking/xinetd.nix
@@ -124,7 +124,7 @@ in
           };
 
           extraConfig = mkOption {
-            type = types.string;
+            type = types.lines;
             default = "";
             description = "Extra configuration-lines added to the section of the service.";
           };
diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix
index 196a14dd40ed..676e82aa8937 100644
--- a/nixos/modules/services/networking/znc.nix
+++ b/nixos/modules/services/networking/znc.nix
@@ -26,53 +26,35 @@ let
   };
 
   # Keep znc.conf in nix store, then symlink or copy into `dataDir`, depending on `mutable`.
+  notNull = a: ! isNull a;
   mkZncConf = confOpts: ''
-    // Also check http://en.znc.in/wiki/Configuration
-    
-    AnonIPLimit = 10
-    ConnectDelay = 5
-    # Add `LoadModule = x` for each module...
+    Version = 1.6.3
     ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.modules}
-    MaxBufferSize = 500
-    ProtectWebSessions = true
-    SSLCertFile = ${cfg.dataDir}/znc.pem
-    ServerThrottle = 30
-    Skin = dark-clouds
-    StatusPrefix = *
-    Version = 1.2
-
-    <Listener listener0>
-            AllowIRC = true
-            AllowWeb = true
+
+    <Listener l>
+            Port = ${toString confOpts.port}
             IPv4 = true
-            IPv6 = false
-            Port = ${if confOpts.useSSL then "+" else ""}${toString confOpts.port}
+            IPv6 = true
             SSL = ${if confOpts.useSSL then "true" else "false"}
     </Listener>
     
     <User ${confOpts.userName}>
+            ${confOpts.passBlock}
             Admin = true
-            Allow = *
-            AltNick = ${confOpts.nick}_
-            AppendTimestamp = false
-            AutoClearChanBuffer = false
-            Buffer = 150
-            ChanModes = +stn
-            DenyLoadMod = false
-            DenySetBindHost = false
-            Ident = ident
-            JoinTries = 10
-            MaxJoins = 0
-            MaxNetworks = 1
-            MultiClients = true
             Nick = ${confOpts.nick}
-            PrependTimestamp = true
-            QuitMsg = Quit
+            AltNick = ${confOpts.nick}_
+            Ident = ${confOpts.nick}
             RealName = ${confOpts.nick}
-            TimestampFormat = [%H:%M:%S]
             ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.userModules}
-            
-            ${confOpts.passBlock}
+
+            ${ lib.concatStringsSep "\n" (lib.mapAttrsToList (name: net: ''
+              <Network ${name}>
+                  ${concatMapStrings (m: "LoadModule = ${m}\n") net.modules}
+                  Server = ${net.server} ${if net.useSSL then "+" else ""}${toString net.port}
+
+                  ${concatMapStrings (c: "<Chan #${c}>\n</Chan>\n") net.channels}
+              </Network>
+              '') confOpts.networks) }
     </User>
     ${confOpts.extraZncConf}
   '';
@@ -84,6 +66,62 @@ let
       else mkZncConf cfg.confOptions;
   };
 
+  networkOpts = { ... }: {
+    options = {
+      server = mkOption {
+        type = types.str;
+        example = "chat.freenode.net";
+        description = ''
+          IRC server address.
+        '';
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 6697;
+        example = 6697;
+        description = ''
+          IRC server port.
+        '';
+      };
+
+      useSSL = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to use SSL to connect to the IRC server.
+        '';
+      };
+
+      modulePackages = mkOption {
+        type = types.listOf types.package;
+        default = [];
+        example = [ "pkgs.zncModules.push" "pkgs.zncModules.fish" ];
+        description = ''
+          External ZNC modules to build.
+        '';
+      };
+
+      modules = mkOption {
+        type = types.listOf types.str;
+        default = [ "simple_away" ];
+        example = literalExample "[ simple_away sasl ]";
+        description = ''
+          ZNC modules to load.
+        '';
+      };
+
+      channels = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "nixos" ];
+        description = ''
+          IRC channels to join.
+        '';
+      };
+    };
+  };
+
 in
 
 {
@@ -111,6 +149,15 @@ in
         '';
       };
 
+      group = mkOption {
+        default = "";
+        example = "users";
+        type = types.string;
+        description = ''
+          Group to own the ZNCserver process.
+        '';
+      };
+
       dataDir = mkOption {
         default = "/var/lib/znc/";
         example = "/home/john/.znc/";
@@ -125,27 +172,16 @@ in
         example = "See: http://wiki.znc.in/Configuration";
         type = types.lines;
         description = ''
-          The contents of the `znc.conf` file to use when creating it.
+          Config file as generated with `znc --makeconf` to use for the whole ZNC configuration.
           If specified, `confOptions` will be ignored, and this value, as-is, will be used.
           If left empty, a conf file with default values will be used.
-          Recommended to generate with `znc --makeconf` command.
         '';
       };
 
-      /* TODO: add to the documentation of the current module:
-
-         Values to use when creating a `znc.conf` file.
-
-           confOptions = {
-             modules = [ "log" ];
-             userName = "john";
-             nick = "johntron";
-           };
-      */
       confOptions = {
         modules = mkOption {
           type = types.listOf types.str;
-          default = [ "partyline" "webadmin" "adminlog" "log" ];
+          default = [ "webadmin" "adminlog" ];
           example = [ "partyline" "webadmin" "adminlog" "log" ];
           description = ''
             A list of modules to include in the `znc.conf` file.
@@ -154,8 +190,8 @@ in
 
         userModules = mkOption {
           type = types.listOf types.str;
-          default = [ ];
-          example = [ "fish" "push" ];
+          default = [ "chansaver" "controlpanel" ];
+          example = [ "chansaver" "controlpanel" "fish" "push" ];
           description = ''
             A list of user modules to include in the `znc.conf` file.
           '';
@@ -166,9 +202,25 @@ in
           example = "johntron";
           type = types.string;
           description = ''
-            The user name to use when generating the `znc.conf` file.
-            This is the user name used by the user logging into the ZNC web admin.
+            The user name used to log in to the ZNC web admin interface.
+          '';
+        };
+
+        networks = mkOption {
+          default = { };
+          type = types.loaOf types.optionSet;
+          description = ''
+            IRC networks to connect the user to.
           '';
+          options = [ networkOpts ];
+          example = {
+            "freenode" = {
+              server = "chat.freenode.net";
+              port = 6697;
+              ssl = true;
+              modules = [ "simple_away" ];
+            };
+          };
         };
 
         nick = mkOption {
@@ -176,19 +228,16 @@ in
           example = "john";
           type = types.string;
           description = ''
-            The IRC nick to use when generating the `znc.conf` file.
+            The IRC nick.
           '';
         };
 
         passBlock = mkOption {
-          default = defaultPassBlock;
-          example = "Must be the block generated by the `znc --makepass` command.";
+          example = defaultPassBlock;
           type = types.string;
           description = ''
-            The pass block to use when generating the `znc.conf` file.
-            This is the password used by the user logging into the ZNC web admin.
-            This is the block generated by the `znc --makepass` command.
-            !!! If not specified, please change this after starting the service. !!!
+            Generate with znc --makepass.
+            This is the password used to log in to the ZNC web admin interface.
           '';
         };
 
@@ -206,7 +255,7 @@ in
           example = true;
           type = types.bool;
           description = ''
-            Indicates whether the ZNC server should use SSL when listening on the specified port.
+            Indicates whether the ZNC server should use SSL when listening on the specified port. A self-signed certificate will be generated.
           '';
         };
 
@@ -214,7 +263,7 @@ in
           default = "";
           type = types.lines;
           description = ''
-            Extra config to `znc.conf` file
+            Extra config to `znc.conf` file.
           '';
         };
       };
@@ -265,6 +314,7 @@ in
       after = [ "network.service" ];
       serviceConfig = {
         User = cfg.user;
+        Group = cfg.group;
         Restart = "always";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         ExecStop   = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
diff --git a/nixos/modules/services/search/hound.nix b/nixos/modules/services/search/hound.nix
new file mode 100644
index 000000000000..708f57a5eb7c
--- /dev/null
+++ b/nixos/modules/services/search/hound.nix
@@ -0,0 +1,123 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  cfg = config.services.hound;
+in {
+  options = {
+    services.hound = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable the hound code search daemon.
+        '';
+      };
+
+      user = mkOption {
+        default = "hound";
+        type = types.str;
+        description = ''
+          User the hound daemon should execute under.
+        '';
+      };
+
+      group = mkOption {
+        default = "hound";
+        type = types.str;
+        description = ''
+          Group the hound daemon should execute under.
+        '';
+      };
+
+      extraGroups = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        example = [ "dialout" ];
+        description = ''
+          List of extra groups that the "hound" user should be a part of.
+        '';
+      };
+
+      home = mkOption {
+        default = "/var/lib/hound";
+        type = types.path;
+        description = ''
+          The path to use as hound's $HOME. If the default user
+          "hound" is configured then this is the home of the "hound"
+          user.
+        '';
+      };
+
+      package = mkOption {
+        default = pkgs.hound;
+        description = ''
+          Package for running hound.
+        '';
+      };
+
+      config = mkOption {
+        type = types.str;
+        description = ''
+          The full configuration of the Hound daemon. Note the dbpath
+          should be an absolute path to a writable location on disk.
+        '';
+        example = ''
+          {
+             "max-concurrent-indexers" : 2,
+             "dbpath" : "''${services.hound.home}/data",
+             "repos" : {
+                "nixpkgs": {
+                   "url" : "https://www.github.com/NixOS/nixpkgs.git"
+                }
+             }
+          }
+        '';
+      };
+
+      listen = mkOption {
+        type = types.str;
+        default = "0.0.0.0:6080";
+        example = "127.0.0.1:6080 or just :6080";
+        description = ''
+          Listen on this IP:port / :port
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraGroups = optional (cfg.group == "hound") {
+      name = "hound";
+      gid = config.ids.gids.hound;
+    };
+
+    users.extraUsers = optional (cfg.user == "hound") {
+      name = "hound";
+      description = "hound code search";
+      createHome = true;
+      home = cfg.home;
+      group = cfg.group;
+      extraGroups = cfg.extraGroups;
+      uid = config.ids.uids.hound;
+    };
+
+    systemd.services.hound = {
+      description = "Hound Code Search";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        WorkingDirectory = cfg.home;
+        ExecStartPre = "${pkgs.git}/bin/git config --global --replace-all http.sslCAinfo /etc/ssl/certs/ca-certificates.crt";
+        ExecStart = "${cfg.package}/bin/houndd" +
+                    " -addr ${cfg.listen}" +
+                    " -conf ${pkgs.writeText "hound.json" cfg.config}";
+
+      };
+      path = [ pkgs.git ];
+    };
+  };
+
+}
diff --git a/nixos/modules/services/torrent/deluge.nix b/nixos/modules/services/torrent/deluge.nix
index becd57055d41..a9c08b66eb82 100644
--- a/nixos/modules/services/torrent/deluge.nix
+++ b/nixos/modules/services/torrent/deluge.nix
@@ -5,26 +5,36 @@ with lib;
 let
   cfg = config.services.deluge;
   cfg_web = config.services.deluge.web;
+  openFilesLimit = 4096;
+
 in {
   options = {
-    services.deluge = {
-      enable = mkOption {
-        default = false;
-        example = true;
-        description = ''
-          Start Deluge daemon.
-        ''; 
-      };  
-    };
+    services = {
+      deluge = {
+        enable = mkOption {
+          default = false;
+          example = true;
+          description = "Start the Deluge daemon";
+        };
+
+        openFilesLimit = mkOption {
+          default = openFilesLimit;
+          example = 8192;
+          description = ''
+            Number of files to allow deluged to open.
+          '';
+        };
+      };
 
-    services.deluge.web = {
-      enable = mkOption {
-        default = false;
-        example = true;
-        description = ''
-          Start Deluge Web daemon.
-        ''; 
-      };  
+      deluge.web = {
+        enable = mkOption {
+          default = false;
+          example = true;
+          description = ''
+            Start Deluge Web daemon.
+          '';
+        };
+      };
     };
   };
 
@@ -35,11 +45,14 @@ in {
       description = "Deluge BitTorrent Daemon";
       wantedBy = [ "multi-user.target" ];
       path = [ pkgs.pythonPackages.deluge ];
-      serviceConfig.ExecStart = "${pkgs.pythonPackages.deluge}/bin/deluged -d";
-      # To prevent "Quit & shutdown daemon" from working; we want systemd to manage it!
-      serviceConfig.Restart = "on-success";
-      serviceConfig.User = "deluge";
-      serviceConfig.Group = "deluge";
+      serviceConfig = {
+        ExecStart = "${pkgs.pythonPackages.deluge}/bin/deluged -d";
+        # To prevent "Quit & shutdown daemon" from working; we want systemd to manage it!
+        Restart = "on-success";
+        User = "deluge";
+        Group = "deluge";
+        LimitNOFILE = cfg.openFilesLimit;
+      };
     };
 
     systemd.services.delugeweb = mkIf cfg_web.enable {
diff --git a/nixos/modules/services/web-apps/atlassian/confluence.nix b/nixos/modules/services/web-apps/atlassian/confluence.nix
new file mode 100644
index 000000000000..2d9287577de8
--- /dev/null
+++ b/nixos/modules/services/web-apps/atlassian/confluence.nix
@@ -0,0 +1,141 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.confluence;
+
+  pkg = pkgs.atlassian-confluence;
+
+in
+
+{
+  options = {
+    services.confluence = {
+      enable = mkEnableOption "Atlassian Confluence service";
+
+      user = mkOption {
+        type = types.str;
+        default = "confluence";
+        description = "User which runs confluence.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "confluence";
+        description = "Group which runs confluence.";
+      };
+
+      home = mkOption {
+        type = types.str;
+        default = "/var/lib/confluence";
+        description = "Home directory of the confluence instance.";
+      };
+
+      listenAddress = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        description = "Address to listen on.";
+      };
+
+      listenPort = mkOption {
+        type = types.int;
+        default = 8090;
+        description = "Port to listen on.";
+      };
+
+      catalinaOptions = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "-Xms1024m" "-Xmx2048m" "-Dconfluence.disable.peopledirectory.all=true" ];
+        description = "Java options to pass to catalina/tomcat.";
+      };
+
+      proxy = {
+        enable = mkEnableOption "proxy support";
+
+        name = mkOption {
+          type = types.str;
+          example = "confluence.example.com";
+          description = "Virtual hostname at the proxy";
+        };
+
+        port = mkOption {
+          type = types.int;
+          default = 443;
+          example = 80;
+          description = "Port used at the proxy";
+        };
+
+        scheme = mkOption {
+          type = types.str;
+          default = "https";
+          example = "http";
+          description = "Protocol used at the proxy.";
+        };
+      };
+
+      jrePackage = let
+        jreSwitch = unfree: free: if config.nixpkgs.config.allowUnfree or false then unfree else free;
+      in mkOption {
+        type = types.package;
+        default = jreSwitch pkgs.oraclejre8 pkgs.openjdk8.jre;
+        defaultText = jreSwitch "pkgs.oraclejre8" "pkgs.openjdk8.jre";
+        example = literalExample "pkgs.openjdk8.jre";
+        description = "Java Runtime to use for Confluence. Note that Atlassian recommends the Oracle JRE.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers."${cfg.user}" = {
+      isSystemUser = true;
+      group = cfg.group;
+    };
+
+    users.extraGroups."${cfg.group}" = {};
+
+    systemd.services.confluence = {
+      description = "Atlassian Confluence";
+
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "postgresql.service" ];
+      after = [ "postgresql.service" ];
+
+      path = [ cfg.jrePackage ];
+
+      environment = {
+        CONF_USER = cfg.user;
+        JAVA_HOME = "${cfg.jrePackage}";
+        CATALINA_OPTS = concatStringsSep " " cfg.catalinaOptions;
+      };
+
+      preStart = ''
+        mkdir -p ${cfg.home}/{logs,work,temp,deploy}
+
+        mkdir -p /run/confluence
+        ln -sf ${cfg.home}/{logs,work,temp,server.xml} /run/confluence
+        ln -sf ${cfg.home} /run/confluence/home
+
+        chown -R ${cfg.user} ${cfg.home}
+
+        sed -e 's,port="8090",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
+        '' + (lib.optionalString cfg.proxy.enable ''
+          -e 's,protocol="org.apache.coyote.http11.Http11NioProtocol",protocol="org.apache.coyote.http11.Http11NioProtocol" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}",' \
+        '') + ''
+          ${pkg}/conf/server.xml.dist > ${cfg.home}/server.xml
+      '';
+
+      script = "${pkg}/bin/start-confluence.sh -fg";
+      stopScript  = "${pkg}/bin/stop-confluence.sh";
+
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        PrivateTmp = true;
+        PermissionsStartOnly = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/atlassian/crowd.nix b/nixos/modules/services/web-apps/atlassian/crowd.nix
new file mode 100644
index 000000000000..5e79678023da
--- /dev/null
+++ b/nixos/modules/services/web-apps/atlassian/crowd.nix
@@ -0,0 +1,147 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.crowd;
+
+  pkg = pkgs.atlassian-crowd;
+
+in
+
+{
+  options = {
+    services.crowd = {
+      enable = mkEnableOption "Atlassian Crowd service";
+
+      user = mkOption {
+        type = types.str;
+        default = "crowd";
+        description = "User which runs Crowd.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "crowd";
+        description = "Group which runs Crowd.";
+      };
+
+      home = mkOption {
+        type = types.str;
+        default = "/var/lib/crowd";
+        description = "Home directory of the Crowd instance.";
+      };
+
+      listenAddress = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        description = "Address to listen on.";
+      };
+
+      listenPort = mkOption {
+        type = types.int;
+        default = 8092;
+        description = "Port to listen on.";
+      };
+
+      catalinaOptions = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "-Xms1024m" "-Xmx2048m" ];
+        description = "Java options to pass to catalina/tomcat.";
+      };
+
+      proxy = {
+        enable = mkEnableOption "reverse proxy support";
+
+        name = mkOption {
+          type = types.str;
+          example = "crowd.example.com";
+          description = "Virtual hostname at the proxy";
+        };
+
+        port = mkOption {
+          type = types.int;
+          default = 443;
+          example = 80;
+          description = "Port used at the proxy";
+        };
+
+        scheme = mkOption {
+          type = types.str;
+          default = "https";
+          example = "http";
+          description = "Protocol used at the proxy.";
+        };
+
+        secure = mkOption {
+          type = types.bool;
+          default = true;
+          example = false;
+          description = "Whether the connections to the proxy should be considered secure.";
+        };
+      };
+
+      jrePackage = let
+        jreSwitch = unfree: free: if config.nixpkgs.config.allowUnfree or false then unfree else free;
+      in mkOption {
+        type = types.package;
+        default = jreSwitch pkgs.oraclejre8 pkgs.openjdk8.jre;
+        defaultText = jreSwitch "pkgs.oraclejre8" "pkgs.openjdk8.jre";
+        example = literalExample "pkgs.openjdk8.jre";
+        description = "Java Runtime to use for Crowd. Note that Atlassian recommends the Oracle JRE.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers."${cfg.user}" = {
+      isSystemUser = true;
+      group = cfg.group;
+    };
+
+    users.extraGroups."${cfg.group}" = {};
+
+    systemd.services.atlassian-crowd = {
+      description = "Atlassian Crowd";
+
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "postgresql.service" ];
+      after = [ "postgresql.service" ];
+
+      path = [ cfg.jrePackage ];
+
+      environment = {
+        JAVA_HOME = "${cfg.jrePackage}";
+        CATALINA_OPTS = concatStringsSep " " cfg.catalinaOptions;
+        CATALINA_TMPDIR = "/tmp";
+      };
+
+      preStart = ''
+        mkdir -p ${cfg.home}/{logs,work}
+
+        mkdir -p /run/atlassian-crowd
+        ln -sf ${cfg.home}/{work,server.xml} /run/atlassian-crowd
+
+        chown -R ${cfg.user} ${cfg.home}
+
+        sed -e 's,port="8095",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
+        '' + (lib.optionalString cfg.proxy.enable ''
+          -e 's,compression="on",compression="off" protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${toString cfg.proxy.secure}",' \
+        '') + ''
+          ${pkg}/apache-tomcat/conf/server.xml.dist > ${cfg.home}/server.xml
+      '';
+
+      script = "${pkg}/start_crowd.sh";
+      #stopScript  = "${pkg}/bin/stop_crowd.sh";
+
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        PrivateTmp = true;
+        PermissionsStartOnly = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/atlassian/jira.nix b/nixos/modules/services/web-apps/atlassian/jira.nix
new file mode 100644
index 000000000000..6e31d20d0681
--- /dev/null
+++ b/nixos/modules/services/web-apps/atlassian/jira.nix
@@ -0,0 +1,149 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.jira;
+
+  pkg = pkgs.atlassian-jira;
+
+in
+
+{
+  options = {
+    services.jira = {
+      enable = mkEnableOption "Atlassian JIRA service";
+
+      user = mkOption {
+        type = types.str;
+        default = "jira";
+        description = "User which runs JIRA.";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "jira";
+        description = "Group which runs JIRA.";
+      };
+
+      home = mkOption {
+        type = types.str;
+        default = "/var/lib/jira";
+        description = "Home directory of the JIRA instance.";
+      };
+
+      listenAddress = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        description = "Address to listen on.";
+      };
+
+      listenPort = mkOption {
+        type = types.int;
+        default = 8091;
+        description = "Port to listen on.";
+      };
+
+      catalinaOptions = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "-Xms1024m" "-Xmx2048m" ];
+        description = "Java options to pass to catalina/tomcat.";
+      };
+
+      proxy = {
+        enable = mkEnableOption "reverse proxy support";
+
+        name = mkOption {
+          type = types.str;
+          example = "jira.example.com";
+          description = "Virtual hostname at the proxy";
+        };
+
+        port = mkOption {
+          type = types.int;
+          default = 443;
+          example = 80;
+          description = "Port used at the proxy";
+        };
+
+        scheme = mkOption {
+          type = types.str;
+          default = "https";
+          example = "http";
+          description = "Protocol used at the proxy.";
+        };
+
+        secure = mkOption {
+          type = types.bool;
+          default = true;
+          example = false;
+          description = "Whether the connections to the proxy should be considered secure.";
+        };
+      };
+
+      jrePackage = let
+        jreSwitch = unfree: free: if config.nixpkgs.config.allowUnfree or false then unfree else free;
+      in mkOption {
+        type = types.package;
+        default = jreSwitch pkgs.oraclejre8 pkgs.openjdk8.jre;
+        defaultText = jreSwitch "pkgs.oraclejre8" "pkgs.openjdk8.jre";
+        example = literalExample "pkgs.openjdk8.jre";
+        description = "Java Runtime to use for JIRA. Note that Atlassian recommends the Oracle JRE.";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers."${cfg.user}" = {
+      isSystemUser = true;
+      group = cfg.group;
+    };
+
+    users.extraGroups."${cfg.group}" = {};
+
+    systemd.services.atlassian-jira = {
+      description = "Atlassian JIRA";
+
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "postgresql.service" ];
+      after = [ "postgresql.service" ];
+
+      path = [ cfg.jrePackage ];
+
+      environment = {
+        JIRA_USER = cfg.user;
+        JIRA_HOME = cfg.home;
+        JAVA_HOME = "${cfg.jrePackage}";
+        CATALINA_OPTS = concatStringsSep " " cfg.catalinaOptions;
+      };
+
+      preStart = ''
+        mkdir -p ${cfg.home}/{logs,work,temp,deploy}
+
+        mkdir -p /run/atlassian-jira
+        ln -sf ${cfg.home}/{logs,work,temp,server.xml} /run/atlassian-jira
+        ln -sf ${cfg.home} /run/atlassian-jira/home
+
+        chown -R ${cfg.user} ${cfg.home}
+
+        sed -e 's,port="8080",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
+        '' + (lib.optionalString cfg.proxy.enable ''
+          -e 's,protocol="HTTP/1.1",protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${toString cfg.proxy.secure}",' \
+        '') + ''
+          ${pkg}/conf/server.xml.dist > ${cfg.home}/server.xml
+      '';
+
+      script = "${pkg}/bin/start-jira.sh -fg";
+      stopScript  = "${pkg}/bin/stop-jira.sh";
+
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        PrivateTmp = true;
+        PermissionsStartOnly = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/nixbot.nix b/nixos/modules/services/web-apps/nixbot.nix
new file mode 100644
index 000000000000..0592d01bf369
--- /dev/null
+++ b/nixos/modules/services/web-apps/nixbot.nix
@@ -0,0 +1,149 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.nixbot;
+  pyramidIni = ''
+    ###
+    # app configuration
+    # http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
+    ###
+
+    [app:main]
+    use = egg:nixbot
+
+    nixbot.github_token = ${cfg.githubToken}
+    nixbot.bot_name = ${cfg.botName}
+    nixbot.repo = ${cfg.repo}
+    nixbot.pr_repo = ${cfg.prRepo}
+    nixbot.hydra_jobsets_repo = ${cfg.hydraJobsetsRepo}
+    nixbot.github_secret = justnotsorandom
+    nixbot.public_url = ${cfg.publicUrl}
+    nixbot.repo_dir = ${cfg.repoDir}
+
+    pyramid.reload_templates = false
+    pyramid.debug_authorization = false
+    pyramid.debug_notfound = false
+    pyramid.debug_routematch = false
+    pyramid.default_locale_name = en
+
+    # By default, the toolbar only appears for clients from IP addresses
+    # '127.0.0.1' and '::1'.
+    # debugtoolbar.hosts = 127.0.0.1 ::1
+
+    ###
+    # wsgi server configuration
+    ###
+
+    [server:main]
+    use = egg:waitress#main
+    host = 0.0.0.0
+    port = 6543
+
+    ###
+    # logging configuration
+    # http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
+    ###
+
+    [loggers]
+    keys = root, nixbot
+
+    [handlers]
+    keys = console
+
+    [formatters]
+    keys = generic
+
+    [logger_root]
+    level = INFO
+    handlers = console
+
+    [logger_nixbot]
+    level = INFO
+    handlers =
+    qualname = nixbot
+
+    [handler_console]
+    class = StreamHandler
+    args = (sys.stderr,)
+    level = NOTSET
+    formatter = generic
+
+    [formatter_generic]
+    format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
+  '';
+in {
+  options = {
+    services.nixbot = {
+      enable = mkEnableOption "nixbot";
+
+      botName = mkOption {
+        type = types.str;
+        description = "The bot's github user account name.";
+        default = "nixbot";
+      };
+
+      githubToken = mkOption {
+        type = types.str;
+        description = "The bot's github user account token.";
+        example = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+      };
+
+      repo = mkOption {
+        type = types.str;
+        description = "The github repository to check for PRs.";
+        example = "nixos/nixpkgs";
+      };
+
+      prRepo = mkOption {
+        type = types.str;
+        description = "The github repository to push the testing branches to.";
+        example = "nixos/nixpkgs-pr";
+      };
+
+      hydraJobsetsRepo = mkOption {
+        type = types.str;
+        description = "The github repository to push the hydra jobset definitions to.";
+        example = "nixos/hydra-jobsets";
+      };
+
+      publicUrl = mkOption {
+        type = types.str;
+        description = "The public URL the bot is reachable at (Github hook endpoint).";
+        example = "https://nixbot.nixos.org";
+      };
+
+      repoDir = mkOption {
+        type = types.path;
+        description = "The directory the repositories are stored in.";
+        default = "/var/lib/nixbot";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers.nixbot = {
+      createHome = true;
+      home = cfg.repoDir;
+    };
+
+    systemd.services.nixbot = let
+      env = pkgs.python3.buildEnv.override {
+        extraLibs = [ pkgs.nixbot ];
+      };
+    in {
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      script = ''
+        ${env}/bin/pserve ${pkgs.writeText "production.ini" pyramidIni}
+      '';
+
+      serviceConfig = {
+        User = "nixbot";
+        Group = "nogroup";
+        PermissionsStartOnly = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/quassel-webserver.nix b/nixos/modules/services/web-apps/quassel-webserver.nix
new file mode 100644
index 000000000000..7de9480d4c46
--- /dev/null
+++ b/nixos/modules/services/web-apps/quassel-webserver.nix
@@ -0,0 +1,99 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.quassel-webserver;
+  quassel-webserver = cfg.pkg;
+  settings = ''
+    module.exports = {
+      default: {
+        host: '${cfg.quasselCoreHost}',  // quasselcore host
+        port: ${toString cfg.quasselCorePort},  // quasselcore port
+        initialBacklogLimit: ${toString cfg.initialBacklogLimit},  // Amount of backlogs to fetch per buffer on connection
+        backlogLimit: ${toString cfg.backlogLimit},  // Amount of backlogs to fetch per buffer after first retrieval
+        securecore: ${if cfg.secureCore then "true" else "false"},  // Connect to the core using SSL
+        theme: '${cfg.theme}'  // Default UI theme
+      },
+      themes: ['default', 'darksolarized'],  //  Available themes
+      forcedefault: ${if cfg.forceHostAndPort then "true" else "false"},  // Will force default host and port to be used, and will hide the corresponding fields in the UI
+      prefixpath: '${cfg.prefixPath}'  // Configure this if you use a reverse proxy
+    };
+  '';
+  settingsFile = pkgs.writeText "settings-user.js" settings;
+in {
+  options = {
+    services.quassel-webserver = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Whether to enable the quassel webclient service";
+      };
+      pkg = mkOption {
+        default = pkgs.quassel-webserver;
+        description = "The quassel-webserver package";
+      };
+      quasselCoreHost = mkOption {
+        default = "";
+        type = types.str;
+        description = "The default host of the quassel core";
+      };
+      quasselCorePort = mkOption {
+        default = 4242;
+        type = types.int;
+        description = "The default quassel core port";
+      };
+      initialBacklogLimit = mkOption {
+        default = 20;
+        type = types.int;
+        description = "Amount of backlogs to fetch per buffer on connection";
+      };
+      backlogLimit = mkOption {
+        default = 100;
+        type = types.int;
+        description = "Amount of backlogs to fetch per buffer after first retrieval";
+      };
+      secureCore = mkOption {
+        default = true;
+        type = types.bool;
+        description = "Connect to the core using SSL";
+      };
+      theme = mkOption {
+        default = "default";
+        type = types.str;
+        description = "default or darksolarized";
+      };
+      prefixPath = mkOption {
+        default = "";
+        type = types.str;
+        description = "Configure this if you use a reverse proxy. Must start with a '/'";
+        example = "/quassel";
+      };
+      port = mkOption {
+        default = 60443;
+        type = types.int;
+        description = "The port the quassel webserver should listen on";
+      };
+      useHttps = mkOption {
+        default = true;
+        type = types.bool;
+        description = "Whether the quassel webserver connection should be a https connection";
+      };
+      forceHostAndPort = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Force the users to use the quasselCoreHost and quasselCorePort defaults";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.quassel-webserver = {
+      description = "A web server/client for Quassel";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = "${quassel-webserver}/lib/node_modules/quassel-webserver/bin/www -p ${toString cfg.port} -m ${if cfg.useHttps == true then "https" else "http"} -c ${settingsFile}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
index 4f9e9f52f9e0..1ed489bcb095 100644
--- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix
@@ -288,6 +288,7 @@ in
     };
 
     extraConfig = mkOption {
+      type = types.lines;
       default = "";
       example =
         ''
diff --git a/nixos/modules/services/web-servers/apache-httpd/moodle.nix b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
index aa00e89967db..d525348d5c7e 100644
--- a/nixos/modules/services/web-servers/apache-httpd/moodle.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/moodle.nix
@@ -164,6 +164,7 @@ in
 
 
     extraConfig = mkOption {
+      type = types.lines;
       default = "";
       example =
         ''
diff --git a/nixos/modules/services/web-servers/apache-httpd/trac.nix b/nixos/modules/services/web-servers/apache-httpd/trac.nix
index 3196edc2838b..87ed36e35305 100644
--- a/nixos/modules/services/web-servers/apache-httpd/trac.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/trac.nix
@@ -102,7 +102,6 @@ in
             pkgs.setuptools
             pkgs.pythonPackages.genshi
             pkgs.pythonPackages.psycopg2
-            pkgs.python.modules.sqlite3
             subversion
           ];
     };
diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
index 2315c4729aec..32dd4439675a 100644
--- a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
@@ -212,6 +212,7 @@ in
           example = "[ \"en_GB\" \"de_DE\" ];";
     };
     extraConfig = mkOption {
+      type = types.lines;
       default = "";
       example =
         ''
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 443bd8c10000..166e5a6b2cea 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -392,8 +392,13 @@ in
     security.acme.certs = filterAttrs (n: v: v != {}) (
       mapAttrs (vhostName: vhostConfig:
         optionalAttrs vhostConfig.enableACME {
+          user = cfg.user;
+          group = cfg.group;
           webroot = vhostConfig.acmeRoot;
           extraDomains = genAttrs vhostConfig.serverAliases (alias: null);
+          postRun = ''
+            systemctl reload nginx
+          '';
         }
       ) virtualHosts
     );
diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix
index a3a23b222fbb..ed537e7122a2 100644
--- a/nixos/modules/services/web-servers/phpfpm/default.nix
+++ b/nixos/modules/services/web-servers/phpfpm/default.nix
@@ -7,8 +7,6 @@ let
 
   stateDir = "/run/phpfpm";
 
-  pidFile = "${stateDir}/phpfpm.pid";
-
   mkPool = n: p: ''
     [${n}]
     listen = ${p.listen}
@@ -17,9 +15,8 @@ let
 
   cfgFile = pkgs.writeText "phpfpm.conf" ''
     [global]
-    pid = ${pidFile}
     error_log = syslog
-    daemonize = yes
+    daemonize = no
     ${cfg.extraConfig}
 
     ${concatStringsSep "\n" (mapAttrsToList mkPool cfg.pools)}
@@ -43,7 +40,7 @@ in {
         description = ''
           Extra configuration that should be put in the global section of
           the PHP-FPM configuration file. Do not specify the options
-          <literal>pid</literal>, <literal>error_log</literal> or
+          <literal>error_log</literal> or
           <literal>daemonize</literal> here, since they are generated by
           NixOS.
         '';
@@ -129,10 +126,10 @@ in {
         mkdir -p "${stateDir}"
       '';
       serviceConfig = {
+        Type = "notify";
         ExecStart = "${cfg.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${phpIni}";
-        PIDFile = pidFile;
+        ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID";
       };
     };
-
   };
 }
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 1ea7b5ccf16a..31412ae70142 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -19,7 +19,7 @@ in
   # E.g., if KDE is enabled, it supersedes xterm.
   imports = [
     ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix ./kde5.nix
-    ./enlightenment.nix ./gnome3.nix ./kodi.nix
+    ./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix
   ];
 
   options = {
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index dc71531759b8..5d1af09e7aa7 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -82,7 +82,7 @@ in {
 
     environment.gnome3.packageSet = mkOption {
       default = null;
-      example = literalExample "pkgs.gnome3_20";
+      example = literalExample "pkgs.gnome3_22";
       description = "Which GNOME 3 package set to use.";
       apply = p: if p == null then pkgs.gnome3 else p;
     };
@@ -108,6 +108,7 @@ in {
     services.gnome3.gnome-documents.enable = mkDefault true;
     services.gnome3.gnome-keyring.enable = true;
     services.gnome3.gnome-online-accounts.enable = mkDefault true;
+    services.gnome3.gnome-terminal-server.enable = mkDefault true;
     services.gnome3.gnome-user-share.enable = mkDefault true;
     services.gnome3.gvfs.enable = true;
     services.gnome3.seahorse.enable = mkDefault true;
diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix
new file mode 100644
index 000000000000..d13b7352c95e
--- /dev/null
+++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix
@@ -0,0 +1,83 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  xcfg = config.services.xserver;
+  cfg = xcfg.desktopManager.lxqt;
+
+in
+
+{
+  options = {
+
+    services.xserver.desktopManager.lxqt.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Enable the LXQt desktop manager";
+    };
+
+  };
+
+
+  config = mkIf (xcfg.enable && cfg.enable) {
+
+    services.xserver.desktopManager.session = singleton {
+      name = "lxqt";
+      start = ''
+        exec ${pkgs.lxqt.lxqt-common}/bin/startlxqt
+      '';
+    };
+
+    environment.systemPackages = [
+      pkgs.kde5.kwindowsystem # provides some QT5 plugins needed by lxqt-panel
+      pkgs.kde5.libkscreen # provides plugins for screen management software
+      pkgs.kde5.oxygen-icons5 # default icon theme
+      pkgs.libfm
+      pkgs.libfm-extra
+      pkgs.lxmenu-data
+      pkgs.lxqt.compton-conf
+      pkgs.lxqt.libfm-qt
+      pkgs.lxqt.liblxqt
+      pkgs.lxqt.libqtxdg
+      pkgs.lxqt.libsysstat
+      pkgs.lxqt.lximage-qt
+      pkgs.lxqt.lxqt-about
+      pkgs.lxqt.lxqt-admin
+      pkgs.lxqt.lxqt-common
+      pkgs.lxqt.lxqt-config
+      pkgs.lxqt.lxqt-globalkeys
+      pkgs.lxqt.lxqt-l10n
+      pkgs.lxqt.lxqt-notificationd
+      pkgs.lxqt.lxqt-openssh-askpass
+      pkgs.lxqt.lxqt-panel
+      pkgs.lxqt.lxqt-policykit
+      pkgs.lxqt.lxqt-powermanagement
+      pkgs.lxqt.lxqt-qtplugin
+      pkgs.lxqt.lxqt-runner
+      pkgs.lxqt.lxqt-session
+      pkgs.lxqt.lxqt-sudo
+      pkgs.lxqt.obconf-qt
+      pkgs.lxqt.pavucontrol-qt
+      pkgs.lxqt.pcmanfm-qt
+      pkgs.lxqt.qlipper
+      pkgs.lxqt.qps
+      pkgs.lxqt.qterminal
+      pkgs.lxqt.qtermwidget
+      pkgs.lxqt.screengrab
+      pkgs.menu-cache
+      pkgs.openbox # default window manager
+      pkgs.qt5.qtsvg # provides QT5 plugins for svg icons
+      pkgs.xscreensaver
+    ];
+
+    # Link some extra directories in /run/current-system/software/share
+    environment.pathsToLink = [
+      "/share/desktop-directories"
+      "/share/icons"
+      "/share/lxqt"
+    ];
+
+  };
+}
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 51d7d905d587..530468be5f96 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -69,7 +69,7 @@ in
     services.xserver.updateDbusEnvironment = true;
 
     environment.systemPackages =
-      [ pkgs.gtk2 # To get GTK+'s themes.
+      [ pkgs.gtk2.out # To get GTK+'s themes and gtk-update-icon-cache
         pkgs.hicolor_icon_theme
         pkgs.tango-icon-theme
         pkgs.shared_mime_info
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index 52847d2f8d2c..d3aa63fd4284 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -95,9 +95,8 @@ in
     services.xserver.displayManager.job =
       {
         environment = {
-          GDM_X_SERVER = "${cfg.xserverBin} ${cfg.xserverArgs}";
+          GDM_X_SERVER_EXTRA_ARGS = "${cfg.xserverArgs}";
           GDM_SESSIONS_DIR = "${cfg.session.desktops}";
-          XDG_CONFIG_DIRS = "${gnome3.gnome_settings_daemon}/etc/xdg";
           # Find the mouse
           XCURSOR_PATH = "~/.icons:${config.system.path}/share/icons";
         };
@@ -108,10 +107,12 @@ in
     systemd.services.display-manager.wants = [ "systemd-machined.service" ];
     systemd.services.display-manager.after = [ "systemd-machined.service" ];
 
-    systemd.services.display-manager.path = [ gnome3.gnome_shell gnome3.caribou pkgs.xorg.xhost pkgs.dbus_tools ];
+    systemd.services.display-manager.path = [ gnome3.gnome_session ];
 
     services.dbus.packages = [ gdm ];
 
+    systemd.user.services.dbus.wantedBy = [ "default.target" ];
+
     programs.dconf.profiles.gdm = "${gdm}/share/dconf/profile/gdm";
 
     # Use AutomaticLogin if delay is zero, because it's immediate.
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 33cd51f37c68..1d309aa34292 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -207,6 +207,9 @@ in
     services.dbus.enable = true;
     services.dbus.packages = [ lightdm ];
 
+    # lightdm uses the accounts daemon to rember language/window-manager per user
+    services.accounts-daemon.enable = true;
+
     security.pam.services.lightdm = {
       allowNullPassword = true;
       startSession = true;
diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix
index 4d2ddedca1ea..36daf55a36a5 100644
--- a/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixos/modules/services/x11/display-managers/sddm.nix
@@ -14,7 +14,7 @@ let
   xserverWrapper = pkgs.writeScript "xserver-wrapper" ''
     #!/bin/sh
     ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)}
-    exec ${dmcfg.xserverBin} ${dmcfg.xserverArgs} "$@"
+    exec systemd-cat ${dmcfg.xserverBin} ${dmcfg.xserverArgs} "$@"
   '';
 
   Xsetup = pkgs.writeScript "Xsetup" ''
@@ -86,7 +86,7 @@ in
       };
 
       extraConfig = mkOption {
-        type = types.str;
+        type = types.lines;
         default = "";
         example = ''
           [Autologin]
diff --git a/nixos/modules/services/x11/urxvtd.nix b/nixos/modules/services/x11/urxvtd.nix
new file mode 100644
index 000000000000..ab47f4547aea
--- /dev/null
+++ b/nixos/modules/services/x11/urxvtd.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+
+# maintainer: siddharthist
+
+with lib;
+
+let
+  cfg = config.services.urxvtd;
+in {
+
+  options.services.urxvtd.enable = mkOption {
+    type = types.bool;
+    default = false;
+    example = true;
+    description = ''
+      Enable urxvtd, the urxvt terminal daemon. To use urxvtd, run
+      "urxvtc".
+    '';
+  };
+
+  config = mkIf cfg.enable {
+    systemd.user = {
+      sockets.urxvtd = {
+        description = "socket for urxvtd, the urxvt terminal daemon";
+        after = [ "graphical.target" ];
+        wants = [ "graphical.target" ];
+        wantedBy = [ "sockets.target" ];
+        socketConfig = {
+          ListenStream = "%t/urxvtd-socket";
+        };
+      };
+
+      services.urxvtd = {
+        description = "urxvt terminal daemon";
+        serviceConfig = {
+          ExecStart = "${pkgs.rxvt_unicode-with-plugins}/bin/urxvtd -o";
+          Environment = "RXVT_SOCKET=%t/urxvtd-socket";
+          Restart = "on-failure";
+          RestartSec = "5s";
+        };
+      };
+
+    };
+
+    environment.systemPackages = [ pkgs.rxvt_unicode-with-plugins ];
+    environment.variables.RXVT_SOCKET = "/run/user/$(id -u)/urxvtd-socket";
+  };
+
+}
diff --git a/nixos/modules/services/x11/window-managers/bspwm-unstable.nix b/nixos/modules/services/x11/window-managers/bspwm-unstable.nix
new file mode 100644
index 000000000000..3282e0d0851f
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/bspwm-unstable.nix
@@ -0,0 +1,48 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.bspwm-unstable;
+in
+
+{
+  options = {
+    services.xserver.windowManager.bspwm-unstable = {
+        enable = mkEnableOption "bspwm-unstable";
+        startThroughSession = mkOption {
+            type = with types; bool;
+            default = false;
+            description = "
+                Start the window manager through the script defined in 
+                sessionScript. Defaults to the the bspwm-session script
+                provided by bspwm
+            ";
+        };
+        sessionScript = mkOption {
+            default = "${pkgs.bspwm-unstable}/bin/bspwm-session";
+            defaultText = "(pkgs.bspwm-unstable)/bin/bspwm-session";
+            description = "
+                The start-session script to use. Defaults to the
+                provided bspwm-session script from the bspwm package.
+
+                Does nothing unless `bspwm.startThroughSession` is enabled
+            ";
+        };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "bspwm-unstable";
+      start = if cfg.startThroughSession
+        then cfg.sessionScript
+        else ''
+            export _JAVA_AWT_WM_NONREPARENTING=1
+            SXHKD_SHELL=/bin/sh ${pkgs.sxhkd-unstable}/bin/sxhkd -f 100 &
+            ${pkgs.bspwm-unstable}/bin/bspwm
+        '';
+    };
+    environment.systemPackages = [ pkgs.bspwm-unstable ];
+  };
+}
diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix
index f005decfa33c..dabe2c26a72f 100644
--- a/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixos/modules/services/x11/window-managers/default.nix
@@ -10,6 +10,7 @@ in
   imports = [
     ./afterstep.nix
     ./bspwm.nix
+    ./bspwm-unstable.nix
     ./compiz.nix
     ./dwm.nix
     ./exwm.nix
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index ec2f3a4f8bb1..f5ed52338182 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -515,6 +515,7 @@ in
       { description = "X11 Server";
 
         after = [ "systemd-udev-settle.service" "local-fs.target" "acpid.service" "systemd-logind.service" ];
+        wants = [ "systemd-udev-settle.service" ];
 
         restartIfChanged = false;
 
@@ -539,6 +540,10 @@ in
           Restart = "always";
           RestartSec = "200ms";
           SyslogIdentifier = "display-manager";
+          # Stop restarting if the display manager stops (crashes) 2 times
+          # in one minute. Starting X typically takes 3-4s.
+          StartLimitInterval = "30s";
+          StartLimitBurst = "3";
         };
       };
 
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index 4a16a6762935..dcf105eb7844 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -145,6 +145,7 @@ in
         ${pkgs.e2fsprogs}/bin/chattr -f -i /var/empty || true
         find /var/empty -mindepth 1 -delete
         chmod 0555 /var/empty
+        chown root:root /var/empty
         ${pkgs.e2fsprogs}/bin/chattr -f +i /var/empty || true
       '';
 
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index 2d1b0ffb54ce..0c08375da646 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -98,7 +98,7 @@ let
   # `switch-to-configuration' that activates the configuration and
   # makes it bootable.
   baseSystem = showWarnings (
-    if [] == failed then pkgs.stdenv.mkDerivation {
+    if [] == failed then pkgs.stdenvNoCC.mkDerivation {
       name = let hn = config.networking.hostName;
                  nn = if (hn != "") then hn else "unnamed";
           in "nixos-system-${nn}-${config.system.nixosLabel}";
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index ba15d0318b17..e751ff141f70 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -4,7 +4,9 @@ with lib;
 
 let
 
-  kernel = config.boot.kernelPackages.kernel;
+  inherit (config.boot) kernelPatches;
+
+  inherit (config.boot.kernelPackages) kernel;
 
   kernelModulesConf = pkgs.writeText "nixos.conf"
     ''
@@ -21,6 +23,11 @@ in
 
     boot.kernelPackages = mkOption {
       default = pkgs.linuxPackages;
+      apply = kernelPackages: kernelPackages.extend (self: super: {
+        kernel = super.kernel.override {
+          kernelPatches = super.kernel.kernelPatches ++ kernelPatches;
+        };
+      });
       # We don't want to evaluate all of linuxPackages for the manual
       # - some of it might not even evaluate correctly.
       defaultText = "pkgs.linuxPackages";
@@ -39,6 +46,13 @@ in
       '';
     };
 
+    boot.kernelPatches = mkOption {
+      type = types.listOf types.attrs;
+      default = [];
+      example = literalExample "[ pkgs.kernelPatches.ubuntu_fan_4_4 ]";
+      description = "A list of additional patches to apply to the kernel.";
+    };
+
     boot.kernelParams = mkOption {
       type = types.listOf types.str;
       default = [ ];
@@ -200,8 +214,8 @@ in
         "hid_generic" "hid_lenovo"
         "hid_apple" "hid_logitech_dj" "hid_lenovo_tpkbd" "hid_roccat"
 
-        # Misc. stuff.
-        "pcips2" "atkbd"
+        # Misc. keyboard stuff.
+        "pcips2" "atkbd" "i8042"
 
         # Temporary fix for https://github.com/NixOS/nixpkgs/issues/18451
         # Remove as soon as upstream gets fixed - marking it:
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index abab5f20baac..7803f1bd1aaf 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -498,8 +498,7 @@ eval "exec $logOutFd>&- $logErrFd>&-"
 #
 # Storage daemons are distinguished by an @ in front of their command line:
 # https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/
-local pidsToKill="$(pgrep -v -f '^@')"
-for pid in $pidsToKill; do
+for pid in $(pgrep -v -f '^@'); do
     # Make sure we don't kill kernel processes, see #15226 and:
     # http://stackoverflow.com/questions/12213445/identifying-kernel-threads
     readlink "/proc/$pid/exe" &> /dev/null || continue
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 8d02cd81e0e1..61def24efd88 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -34,7 +34,7 @@ let
   # copy what we need.  Instead of using statically linked binaries,
   # we just copy what we need from Glibc and use patchelf to make it
   # work.
-  extraUtils = pkgs.runCommand "extra-utils"
+  extraUtils = pkgs.runCommandCC "extra-utils"
     { buildInputs = [pkgs.nukeReferences];
       allowedReferences = [ "out" ]; # prevent accidents like glibc being included in the initrd
     }
diff --git a/nixos/modules/system/boot/systemd-nspawn.nix b/nixos/modules/system/boot/systemd-nspawn.nix
new file mode 100644
index 000000000000..f765db275e79
--- /dev/null
+++ b/nixos/modules/system/boot/systemd-nspawn.nix
@@ -0,0 +1,122 @@
+{ config, lib , pkgs, ...}:
+
+with lib;
+with import ./systemd-unit-options.nix { inherit config lib; };
+with import ./systemd-lib.nix { inherit config lib pkgs; };
+
+let
+  cfg = config.systemd.nspawn;
+  assertions = [
+    # boot = true -> processtwo != true
+  ];
+
+  checkExec = checkUnitConfig "Exec" [
+    (assertOnlyFields [
+      "Boot" "ProcessTwo" "Parameters" "Environment" "User" "WorkingDirectory"
+      "Capability" "DropCapability" "KillSignal" "Personality" "MachineId"
+      "PrivateUsers"
+    ])
+    (assertValueOneOf "Boot" boolValues)
+    (assertValueOneOf "ProcessTwo" boolValues)
+    (assertValueOneOf "PrivateUsers" (boolValues ++ [ "pick" ]))
+  ];
+
+  checkFiles = checkUnitConfig "Files" [
+    (assertOnlyFields [
+      "ReadOnly" "Volatile" "Bind" "BindReadOnly" "TemporaryFileSystems"
+      "PrivateUsersChown"
+    ])
+    (assertValueOneOf "ReadOnly" boolValues)
+    (assertValueOneOf "Volatile" (boolValues ++ [ "state" ]))
+    (assertValueOneOf "PrivateUsersChown" boolValues)
+  ];
+
+  checkNetwork = checkUnitConfig "Network" [
+    (assertOnlyFields [
+      "Private" "VirtualEthernet" "VirtualEthernetExtra" "Interface" "MACVLAN"
+      "IPVLAN" "Bridge" "Zone" "Port"
+    ])
+    (assertValueOneOf "Private" boolValues)
+    (assertValueOneOf "VirtualEthernet" boolValues)
+  ];
+
+  instanceOptions = {
+    options = {
+
+      execConfig = mkOption {
+        default = {};
+        example = { Parameters = "/bin/sh"; };
+        type = types.addCheck (types.attrsOf unitOption) checkExec;
+        description = ''
+          Each attribute in this set specifies an option in the
+          <literal>[Exec]</literal> section of this unit. See
+          <citerefentry><refentrytitle>systemd.nspawn</refentrytitle>
+          <manvolnum>5</manvolnum></citerefentry> for details.
+        '';
+      };
+
+      filesConfig = mkOption {
+        default = {};
+        example = { Bind = [ "/home/alice" ]; };
+        type = types.addCheck (types.attrsOf unitOption) checkFiles;
+        description = ''
+          Each attribute in this set specifies an option in the
+          <literal>[Files]</literal> section of this unit. See
+          <citerefentry><refentrytitle>systemd.nspawn</refentrytitle>
+          <manvolnum>5</manvolnum></citerefentry> for details.
+        '';
+      };
+
+      networkConfig = mkOption {
+        default = {};
+        example = { Private = false; };
+        type = types.addCheck (types.attrsOf unitOption) checkNetwork;
+        description = ''
+          Each attribute in this set specifies an option in the
+          <literal>[Network]</literal> section of this unit. See
+          <citerefentry><refentrytitle>systemd.nspawn</refentrytitle>
+          <manvolnum>5</manvolnum></citerefentry> for details.
+        '';
+      };
+    };
+
+  };
+
+  instanceToUnit = name: def: 
+    { text = ''
+      [Exec]
+      ${attrsToSection def.execConfig}
+
+      [Files]
+      ${attrsToSection def.filesConfig}
+
+      [Network]
+      ${attrsToSection def.networkConfig}
+    '';
+    };
+
+in {
+
+  options = {
+
+    systemd.nspawn = mkOption {
+      default = {};
+      type = with types; attrsOf (submodule instanceOptions);
+      description = "Definition of systemd-nspawn configurations.";
+    };
+
+  };
+
+  config =
+    let
+      units = mapAttrs' (n: v: nameValuePair "${n}.nspawn" (instanceToUnit n v)) cfg.instances;
+    in mkIf (cfg != {}) {
+
+      environment.etc."systemd/nspawn".source = generateUnits "nspawn" units [] [];
+
+      systemd.services."systemd-nspawn@" = {
+        wantedBy = [ "machine.target" ];
+      };
+  };
+
+}
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 731b1701e00d..4c3fc30358c1 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -316,7 +316,7 @@ in rec {
 
     startAt = mkOption {
       type = with types; either str (listOf str);
-      default = "";
+      default = [];
       example = "Sun 14:00:00";
       description = ''
         Automatically start this unit at the given date/time, which
@@ -326,6 +326,7 @@ in rec {
         to adding a corresponding timer unit with
         <option>OnCalendar</option> set to the value given here.
       '';
+      apply = v: if isList v then v else [ v ];
     };
 
   };
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index d44c2e234b0f..d1f3f923e5e3 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -777,7 +777,7 @@ in
         { wantedBy = [ "timers.target" ];
           timerConfig.OnCalendar = service.startAt;
         })
-        (filterAttrs (name: service: service.enable && service.startAt != "") cfg.services);
+        (filterAttrs (name: service: service.enable && service.startAt != []) cfg.services);
 
     # Generate timer units for all services that have a ‘startAt’ value.
     systemd.user.timers =
@@ -785,7 +785,7 @@ in
         { wantedBy = [ "timers.target" ];
           timerConfig.OnCalendar = service.startAt;
         })
-        (filterAttrs (name: service: service.startAt != "") cfg.user.services);
+        (filterAttrs (name: service: service.startAt != []) cfg.user.services);
 
     systemd.sockets.systemd-journal-gatewayd.wantedBy =
       optional config.services.journald.enableHttpGateway "sockets.target";
diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix
index dac36229408f..fd6e58cd5b43 100644
--- a/nixos/modules/system/etc/etc.nix
+++ b/nixos/modules/system/etc/etc.nix
@@ -8,7 +8,7 @@ let
 
   etc' = filter (f: f.enable) (attrValues config.environment.etc);
 
-  etc = pkgs.stdenv.mkDerivation {
+  etc = pkgs.stdenvNoCC.mkDerivation {
     name = "etc";
 
     builder = ./make-etc.sh;
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index 6a8f20bab5b6..c50ea5c79643 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -46,6 +46,23 @@ in
     systemd.services =
       let
 
+        deviceDependency = dev:
+          if (config.boot.isContainer == false)
+          then
+            # Trust udev when not in the container
+            optional (dev != null) (subsystemDevice dev)
+          else
+            # When in the container, check whether the interface is built from other definitions
+            if (hasAttr dev cfg.bridges) ||
+               (hasAttr dev cfg.bonds) ||
+               (hasAttr dev cfg.macvlans) ||
+               (hasAttr dev cfg.sits) ||
+               (hasAttr dev cfg.vlans) ||
+               (hasAttr dev cfg.vswitches) ||
+               (hasAttr dev cfg.wlanInterfaces)
+            then [ "${dev}-netdev.service" ]
+            else [];
+
         networkLocalCommands = {
           after = [ "network-setup.service" ];
           bindsTo = [ "network-setup.service" ];
@@ -120,8 +137,8 @@ in
             # order before network-setup because the routes that are configured
             # there may need ip addresses configured
             before = [ "network-setup.service" ];
-            bindsTo = [ (subsystemDevice i.name) ];
-            after = [ (subsystemDevice i.name) "network-pre.target" ];
+            bindsTo = deviceDependency i.name;
+            after = [ "network-pre.target" ] ++ (deviceDependency i.name);
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute ];
@@ -179,7 +196,7 @@ in
 
         createBridgeDevice = n: v: nameValuePair "${n}-netdev"
           (let
-            deps = map subsystemDevice v.interfaces;
+            deps = concatLists (map deviceDependency v.interfaces);
           in
           { description = "Bridge Interface ${n}";
             wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@@ -220,7 +237,7 @@ in
 
         createVswitchDevice = n: v: nameValuePair "${n}-netdev"
           (let
-            deps = map subsystemDevice v.interfaces;
+            deps = concatLists (map deviceDependency v.interfaces);
             ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
           in
           { description = "Open vSwitch Interface ${n}";
@@ -253,7 +270,7 @@ in
 
         createBondDevice = n: v: nameValuePair "${n}-netdev"
           (let
-            deps = map subsystemDevice v.interfaces;
+            deps = concatLists (map deviceDependency v.interfaces);
           in
           { description = "Bond Interface ${n}";
             wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@@ -291,7 +308,7 @@ in
 
         createMacvlanDevice = n: v: nameValuePair "${n}-netdev"
           (let
-            deps = [ (subsystemDevice v.interface) ];
+            deps = deviceDependency v.interface;
           in
           { description = "Vlan Interface ${n}";
             wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@@ -316,7 +333,7 @@ in
 
         createSitDevice = n: v: nameValuePair "${n}-netdev"
           (let
-            deps = optional (v.dev != null) (subsystemDevice v.dev);
+            deps = deviceDependency v.dev;
           in
           { description = "6-to-4 Tunnel Interface ${n}";
             wantedBy = [ "network-setup.service" (subsystemDevice n) ];
@@ -344,7 +361,7 @@ in
 
         createVlanDevice = n: v: nameValuePair "${n}-netdev"
           (let
-            deps = [ (subsystemDevice v.interface) ];
+            deps = deviceDependency v.interface;
           in
           { description = "Vlan Interface ${n}";
             wantedBy = [ "network-setup.service" (subsystemDevice n) ];
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index cac7e6b02eba..aae4dc5fdadf 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -310,9 +310,9 @@ in
         generate a random 32-bit ID using the following commands:
 
         <literal>cksum /etc/machine-id | while read c rest; do printf "%x" $c; done</literal>
-        
+
         (this derives it from the machine-id that systemd generates) or
-        
+
         <literal>head -c4 /dev/urandom | od -A none -t x4</literal>
       '';
     };
@@ -972,12 +972,17 @@ in
         '';
       };
     } // (listToAttrs (flip map interfaces (i:
+      let
+        deviceDependency = if config.boot.isContainer
+          then []
+          else [ (subsystemDevice i.name) ];
+      in
       nameValuePair "network-link-${i.name}"
       { description = "Link configuration of ${i.name}";
         wantedBy = [ "network-interfaces.target" ];
         before = [ "network-interfaces.target" ];
-        bindsTo = [ (subsystemDevice i.name) ];
-        after = [ (subsystemDevice i.name) "network-pre.target" ];
+        bindsTo = deviceDependency;
+        after = [ "network-pre.target" ] ++ deviceDependency;
         path = [ pkgs.iproute ];
         serviceConfig = {
           Type = "oneshot";
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 5e1cfcdfc6fb..aa28a25be7ac 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -473,7 +473,7 @@ in
             };
 
             extraVeths = mkOption {
-              type = with types; attrsOf (submodule networkOptions);
+              type = with types; attrsOf (submodule { options = networkOptions; });
               default = {};
               description = ''
                 Extra veth-pairs to be created for the container