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/i18n.nix2
-rw-r--r--nixos/modules/config/shells-environment.nix7
-rw-r--r--nixos/modules/config/system-environment.nix56
-rw-r--r--nixos/modules/config/timezone.nix2
-rw-r--r--nixos/modules/config/zram.nix138
-rw-r--r--nixos/modules/hardware/opengl.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-new-kernel.nix (renamed from nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix)3
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix3
-rw-r--r--nixos/modules/installer/tools/nixos-build-vms/build-vms.nix2
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl2
-rw-r--r--nixos/modules/misc/ids.nix2
-rw-r--r--nixos/modules/module-list.nix8
-rw-r--r--nixos/modules/programs/environment.nix9
-rw-r--r--nixos/modules/programs/shadow.nix1
-rw-r--r--nixos/modules/security/ca.nix8
-rw-r--r--nixos/modules/security/grsecurity.nix21
-rw-r--r--nixos/modules/security/pam.nix1
-rw-r--r--nixos/modules/security/sudo.nix10
-rw-r--r--nixos/modules/services/audio/mpd.nix2
-rw-r--r--nixos/modules/services/desktops/accountsservice.nix (renamed from nixos/modules/services/desktops/accountservice.nix)6
-rw-r--r--nixos/modules/services/hardware/sane.nix10
-rw-r--r--nixos/modules/services/misc/disnix.nix3
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/misc/synergy.nix6
-rw-r--r--nixos/modules/services/monitoring/graphite.nix43
-rw-r--r--nixos/modules/services/monitoring/nagios.nix (renamed from nixos/modules/services/monitoring/nagios/default.nix)122
-rw-r--r--nixos/modules/services/monitoring/nagios/commands.cfg34
-rw-r--r--nixos/modules/services/monitoring/nagios/host-templates.cfg27
-rw-r--r--nixos/modules/services/monitoring/nagios/service-templates.cfg32
-rw-r--r--nixos/modules/services/monitoring/nagios/timeperiods.cfg11
-rw-r--r--nixos/modules/services/monitoring/statsd.nix4
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix2
-rw-r--r--nixos/modules/services/networking/nsd.nix751
-rw-r--r--nixos/modules/services/search/elasticsearch.nix11
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/default.nix4
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix5
-rw-r--r--nixos/modules/services/web-servers/phpfpm.nix8
-rw-r--r--nixos/modules/system/activation/top-level.nix33
-rw-r--r--nixos/modules/system/boot/systemd.nix20
-rw-r--r--nixos/modules/tasks/network-interfaces.nix10
-rw-r--r--nixos/modules/tasks/trackpoint.nix66
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix33
43 files changed, 1264 insertions, 262 deletions
diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix
index 8182b8ae808..d3f24e280c7 100644
--- a/nixos/modules/config/i18n.nix
+++ b/nixos/modules/config/i18n.nix
@@ -76,7 +76,7 @@ in
 
     environment.systemPackages = [ glibcLocales ];
 
-    environment.variables =
+    environment.sessionVariables =
       { LANG = config.i18n.defaultLocale;
         LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
       };
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index 9e212847e48..cc079cdc585 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -19,6 +19,7 @@ in
       default = {};
       description = ''
         A set of environment variables used in the global environment.
+        These variables will be set on shell initialisation.
         The value of each variable can be either a string or a list of
         strings.  The latter is concatenated, interspersed with colon
         characters.
@@ -148,6 +149,12 @@ in
 
     system.build.binsh = pkgs.bashInteractive;
 
+    # Set session variables in the shell as well. This is usually
+    # unnecessary, but it allows changes to session variables to take
+    # effect without restarting the session (e.g. by opening a new
+    # terminal instead of logging out of X11).
+    environment.variables = config.environment.sessionVariables;
+
     environment.etc."shells".text =
       ''
         ${concatStringsSep "\n" cfg.shells}
diff --git a/nixos/modules/config/system-environment.nix b/nixos/modules/config/system-environment.nix
new file mode 100644
index 00000000000..3ab32f00fd1
--- /dev/null
+++ b/nixos/modules/config/system-environment.nix
@@ -0,0 +1,56 @@
+# This module defines a system-wide environment that will be
+# initialised by pam_env (that is, not only in shells).
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.environment;
+
+in
+
+{
+
+  options = {
+
+    environment.sessionVariables = mkOption {
+      default = {};
+      description = ''
+        A set of environment variables used in the global environment.
+        These variables will be set by PAM.
+        The value of each variable can be either a string or a list of
+        strings.  The latter is concatenated, interspersed with colon
+        characters.
+      '';
+      type = types.attrsOf (mkOptionType {
+        name = "a string or a list of strings";
+        merge = loc: defs:
+          let
+            defs' = filterOverrides defs;
+            res = (head defs').value;
+          in
+          if isList res then concatLists (getValues defs')
+          else if lessThan 1 (length defs') then
+            throw "The option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
+          else if !isString res then
+            throw "The option `${showOption loc}' does not have a string value, in ${showFiles (getFiles defs)}."
+          else res;
+      });
+      apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v);
+    };
+
+  };
+
+  config = {
+
+    system.build.pamEnvironment = pkgs.writeText "pam-environment"
+       ''
+         ${concatStringsSep "\n" (
+           (mapAttrsToList (n: v: ''${n}="${concatStringsSep ":" v}"'')
+             (zipAttrsWith (const concatLists) ([ (mapAttrs (n: v: [ v ]) cfg.sessionVariables) ]))))}
+       '';
+
+  };
+
+}
diff --git a/nixos/modules/config/timezone.nix b/nixos/modules/config/timezone.nix
index 65703d8bb08..c8592284077 100644
--- a/nixos/modules/config/timezone.nix
+++ b/nixos/modules/config/timezone.nix
@@ -30,7 +30,7 @@ in
 
   config = {
 
-    environment.variables.TZDIR = "/etc/zoneinfo";
+    environment.sessionVariables.TZDIR = "/etc/zoneinfo";
 
     systemd.globalEnvironment.TZDIR = tzdir;
 
diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix
new file mode 100644
index 00000000000..22b74847f87
--- /dev/null
+++ b/nixos/modules/config/zram.nix
@@ -0,0 +1,138 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.zramSwap;
+
+  devices = map (nr: "zram${toString nr}") (range 0 (cfg.numDevices - 1));
+
+  modprobe = "${config.system.sbin.modprobe}/sbin/modprobe";
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    zramSwap = {
+
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Enable in-memory compressed swap space provided by the zram kernel
+          module. It is recommended to enable only for kernel 3.14 or higher.
+        '';
+      };
+
+      numDevices = mkOption {
+        default = 4;
+        type = types.int;
+        description = ''
+          Number of zram swap devices to create. It should be equal to the
+          number of CPU cores your system has.
+        '';
+      };
+
+      memoryPercent = mkOption {
+        default = 50;
+        type = types.int;
+        description = ''
+          Maximum amount of memory that can be used by the zram swap devices
+          (as a percentage of your total memory). Defaults to 1/2 of your total
+          RAM.
+        '';
+      };
+
+      priority = mkOption {
+        default = 5;
+        type = types.int;
+        description = ''
+          Priority of the zram swap devices. It should be a number higher than
+          the priority of your disk-based swap devices (so that the system will
+          fill the zram swap devices before falling back to disk swap).
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    system.requiredKernelConfig = with config.lib.kernelConfig; [
+      (isModule "ZRAM")
+    ];
+
+    # Disabling this for the moment, as it would create and mkswap devices twice,
+    # once in stage 2 boot, and again when the zram-reloader service starts.
+    # boot.kernelModules = [ "zram" ];
+
+    boot.extraModprobeConfig = ''
+      options zram num_devices=${toString cfg.numDevices}
+    '';
+
+    services.udev.extraRules = ''
+      KERNEL=="zram[0-9]*", ENV{SYSTEMD_WANTS}="zram-init-%k.service", TAG+="systemd"
+    '';
+
+    systemd.services =
+      let
+        createZramInitService = dev:
+          nameValuePair "zram-init-${dev}" {
+            description = "Init swap on zram-based device ${dev}";
+            bindsTo = [ "dev-${dev}.swap" ];
+            after = [ "dev-${dev}.device" "zram-reloader.service" ];
+            requires = [ "dev-${dev}.device" "zram-reloader.service" ];
+            before = [ "dev-${dev}.swap" ];
+            requiredBy = [ "dev-${dev}.swap" ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+              ExecStop = "${pkgs.stdenv.shell} -c 'echo 1 > /sys/class/block/${dev}/reset'";
+            };
+            script = ''
+              set -u
+              set -o pipefail
+
+              PATH=${pkgs.procps}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin
+
+              # Calculate memory to use for zram
+              totalmem=$(free | grep -e "^Mem:" | sed -e 's/^Mem: *//' -e 's/  *.*//')
+              mem=$(((totalmem * ${toString cfg.memoryPercent} / 100 / ${toString cfg.numDevices}) * 1024))
+
+              echo $mem > /sys/class/block/${dev}/disksize
+              ${pkgs.utillinux}/sbin/mkswap /dev/${dev}
+            '';
+            restartIfChanged = false;
+          };
+      in listToAttrs ((map createZramInitService devices) ++ [(nameValuePair "zram-reloader"
+        {
+          description = "Reload zram kernel module when number of devices changes";
+          serviceConfig = {
+            Type = "oneshot";
+            RemainAfterExit = true;
+            ExecStartPre = "${modprobe} -r zram";
+            ExecStart = "${modprobe} zram";
+            ExecStop = "${modprobe} -r zram";
+          };
+          restartTriggers = [ cfg.numDevices ];
+          restartIfChanged = true;
+        })]);
+
+    swapDevices =
+      let
+        useZramSwap = dev:
+          {
+            device = "/dev/${dev}";
+            priority = cfg.priority;
+          };
+      in map useZramSwap devices;
+
+  };
+
+}
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index 096f7e2c097..ab5c309bd42 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -16,7 +16,7 @@ let
       [ p.mesa_drivers
         p.mesa_noglu # mainly for libGL
         (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc)
-	p.udev
+        p.udev
       ];
   };
 
@@ -101,7 +101,7 @@ in
         ''}
       '';
 
-    environment.variables.LD_LIBRARY_PATH =
+    environment.sessionVariables.LD_LIBRARY_PATH =
       [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ];
 
     # FIXME: move this into card-specific modules.
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
index eb7c4026857..4d87c20559d 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -19,7 +19,7 @@ with lib;
   # ISO naming.
   isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixosVersion}-${pkgs.stdenv.system}.iso";
 
-  isoImage.volumeID = substring 0 11 "NIXOS_${config.system.nixosVersion}";
+  isoImage.volumeID = substring 0 11 "NIXOS_ISO";
 
   # Make the installer more likely to succeed in low memory
   # environments.  The kernel's overcommit heustistics bite us
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-new-kernel.nix
index 93bcbf00b25..506b9292b01 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-new-kernel.nix
@@ -3,6 +3,5 @@
 {
   imports = [ ./installation-cd-graphical.nix ];
 
-  boot.kernelPackages = pkgs.linuxPackages_3_10;
-  boot.vesa = false;
+  boot.kernelPackages = pkgs.linuxPackages_latest;
 }
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix
index 38d02ffd162..4363c8e6c93 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix
@@ -3,6 +3,5 @@
 {
   imports = [ ./installation-cd-minimal.nix ];
 
-  boot.kernelPackages = pkgs.linuxPackages_3_10;
-  boot.vesa = false;
+  boot.kernelPackages = pkgs.linuxPackages_latest;
 }
diff --git a/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
index 5e77b701ff5..4372d196261 100644
--- a/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
+++ b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
@@ -6,4 +6,4 @@ let nodes = import networkExpr; in
 
 with import ../../../../lib/testing.nix { inherit system; };
 
-(complete { inherit nodes; testScript = ""; }).driver
+(makeTest { inherit nodes; testScript = ""; }).driver
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index ab058efc709..66a8152a3a6 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -466,7 +466,7 @@ $bootLoaderConfig
   # };
 
   # List packages installed in system profile. To search by name, run:
-  # $ nix-env -qaP | grep wget
+  # \$ nix-env -qaP | grep wget
   # environment.systemPackages = with pkgs; [
   #   wget
   # ];
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index db50a010e7d..f1028a479df 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -133,6 +133,7 @@
       spiped = 123;
       teamspeak = 124;
       influxdb = 125;
+      nsd = 126;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -240,6 +241,7 @@
       spiped = 123;
       teamspeak = 124;
       influxdb = 125;
+      nsd = 126;
 
       # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399!
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 7fa705a5ae3..13f2656c287 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -14,12 +14,14 @@
   ./config/power-management.nix
   ./config/pulseaudio.nix
   ./config/shells-environment.nix
+  ./config/system-environment.nix
   ./config/swap.nix
   ./config/sysctl.nix
   ./config/system-path.nix
   ./config/timezone.nix
   ./config/unix-odbc-drivers.nix
   ./config/users-groups.nix
+  ./config/zram.nix
   ./hardware/all-firmware.nix
   ./hardware/cpu/intel-microcode.nix
   ./hardware/cpu/amd-microcode.nix
@@ -99,7 +101,7 @@
   ./services/databases/virtuoso.nix
   ./services/databases/monetdb.nix
   ./services/databases/influxdb.nix
-  ./services/desktops/accountservice.nix
+  ./services/desktops/accountsservice.nix
   ./services/desktops/geoclue2.nix
   ./services/desktops/gnome3/at-spi2-core.nix
   ./services/desktops/gnome3/evolution-data-server.nix
@@ -158,7 +160,7 @@
   ./services/monitoring/graphite.nix
   ./services/monitoring/monit.nix
   ./services/monitoring/munin.nix
-  ./services/monitoring/nagios/default.nix
+  ./services/monitoring/nagios.nix
   ./services/monitoring/smartd.nix
   ./services/monitoring/statsd.nix
   ./services/monitoring/systemhealth.nix
@@ -205,6 +207,7 @@
   ./services/networking/networkmanager.nix
   ./services/networking/ngircd.nix
   ./services/networking/notbit.nix
+  ./services/networking/nsd.nix
   ./services/networking/ntopng.nix
   ./services/networking/ntpd.nix
   ./services/networking/oidentd.nix
@@ -323,6 +326,7 @@
   ./tasks/network-interfaces.nix
   ./tasks/scsi-link-power-management.nix
   ./tasks/swraid.nix
+  ./tasks/trackpoint.nix
   ./testing/service-runner.nix
   ./virtualisation/container-config.nix
   ./virtualisation/containers.nix
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index aa9aec07834..2ff1db48757 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -19,13 +19,16 @@ in
     environment.variables =
       { LOCATE_PATH = "/var/cache/locatedb";
         NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix";
-        NIX_PATH =
+        PAGER = "less -R";
+        EDITOR = "nano";
+      };
+
+    environment.sessionVariables =
+      { NIX_PATH =
           [ "/nix/var/nix/profiles/per-user/root/channels/nixos"
             "nixpkgs=/etc/nixos/nixpkgs"
             "nixos-config=/etc/nixos/configuration.nix"
           ];
-        PAGER = "less -R";
-        EDITOR = "nano";
       };
 
     environment.profiles =
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 27a18c726a3..5fcd2133a7e 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -48,6 +48,7 @@ in
         Rather, it should be the path of a symlink that points to the
         actual shell in the Nix store.
       '';
+      example = "/run/current-system/sw/bin/zsh";
       type = types.path;
     };
 
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index f159e359f96..dd4b0c529e5 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -12,9 +12,11 @@ with lib;
         }
       ];
 
-    environment.variables.OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
-    environment.variables.CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt";
-    environment.variables.GIT_SSL_CAINFO = "/etc/ssl/certs/ca-bundle.crt";
+    environment.sessionVariables =
+      { OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
+        CURL_CA_BUNDLE         = "/etc/ssl/certs/ca-bundle.crt";
+        GIT_SSL_CAINFO         = "/etc/ssl/certs/ca-bundle.crt";
+      };
 
   };
 
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index f4af04247fe..3bd58218c99 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -6,12 +6,10 @@ let
   cfg = config.security.grsecurity;
 
   customGrsecPkg =
-    (import ../../../pkgs/build-support/grsecurity
-      {
-        inherit lib pkgs;
-        grsecOptions = cfg;
-      }
-    ).grsecPackage;
+    (import ../../../pkgs/build-support/grsecurity {
+      grsecOptions = cfg;
+      inherit pkgs lib;
+    }).grsecPackage;
 in
 {
   options = {
@@ -36,14 +34,6 @@ in
         '';
       };
 
-      vserver = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enable the stable grsecurity/vserver patches, based on Linux 3.2.
-        '';
-      };
-
       testing = mkOption {
         type = types.bool;
         default = false;
@@ -246,9 +236,6 @@ in
             both.
           '';
         }
-        { assertion = (cfg.testing -> !cfg.vserver);
-          message   = "The vserver patches are only supported in the stable kernel.";
-        }
         { assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) ||
                       (cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc);
           message   = "You cannot enable both restrictProc and restrictProcWithGroup";
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 6a5eb4c720f..02340fd78e8 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -186,6 +186,7 @@ let
               "password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass"}
 
           # Session management.
+          session required pam_env.so envfile=${config.system.build.pamEnvironment}
           session required pam_unix.so
           ${optionalString cfg.setLoginUid
               "session required pam_loginuid.so"}
diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix
index 6cfeac0d7dc..cbd1628caae 100644
--- a/nixos/modules/security/sudo.nix
+++ b/nixos/modules/security/sudo.nix
@@ -58,9 +58,6 @@ in
         # Don't edit this file. Set the NixOS option ‘security.sudo.configFile’ instead.
 
         # Environment variables to keep for root and %wheel.
-        Defaults:root,%wheel env_keep+=LOCALE_ARCHIVE
-        Defaults:root,%wheel env_keep+=NIX_CONF_DIR
-        Defaults:root,%wheel env_keep+=NIX_PATH
         Defaults:root,%wheel env_keep+=TERMINFO_DIRS
         Defaults:root,%wheel env_keep+=TERMINFO
 
@@ -81,10 +78,13 @@ in
     security.pam.services.sudo = { sshAgentAuth = true; };
 
     environment.etc = singleton
-      { source = pkgs.writeText "sudoers-in" cfg.configFile;
+      { source =
+          pkgs.runCommand "sudoers"
+	  {src = pkgs.writeText "sudoers-in" cfg.configFile; }
           # Make sure that the sudoers file is syntactically valid.
           # (currently disabled - NIXOS-66)
-          #"${pkgs.sudo}/sbin/visudo -f $src -c && cp $src $out";
+          "${pkgs.sudo}/sbin/visudo -f $src -c &&
+	      cp $src $out";
         target = "sudoers";
         mode = "0440";
       };
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 1b50f06bf30..53542e34b14 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -52,7 +52,7 @@ in {
       };  
 
       dataDir = mkOption {
-        default = "/var/lib/mpd/";
+        default = "/var/lib/mpd";
         description = ''
           The directory where MPD stores its state, tag cache,
           playlists etc.
diff --git a/nixos/modules/services/desktops/accountservice.nix b/nixos/modules/services/desktops/accountsservice.nix
index 386dfe98bd2..c28c2729576 100644
--- a/nixos/modules/services/desktops/accountservice.nix
+++ b/nixos/modules/services/desktops/accountsservice.nix
@@ -30,11 +30,11 @@ with lib;
 
   config = mkIf config.services.accounts-daemon.enable {
 
-    environment.systemPackages = [ pkgs.accountservice ];
+    environment.systemPackages = [ pkgs.accountsservice ];
 
-    services.dbus.packages = [ pkgs.accountservice ];
+    services.dbus.packages = [ pkgs.accountsservice ];
 
-    systemd.packages = [ pkgs.accountservice ];
+    systemd.packages = [ pkgs.accountsservice ];
   };
 
 }
diff --git a/nixos/modules/services/hardware/sane.nix b/nixos/modules/services/hardware/sane.nix
index f7b25c18787..3bf765c6f99 100644
--- a/nixos/modules/services/hardware/sane.nix
+++ b/nixos/modules/services/hardware/sane.nix
@@ -34,6 +34,12 @@ in
       description = "Packages providing extra SANE backends to enable.";
     };
 
+    hardware.sane.configDir = mkOption {
+      type = types.string;
+      default = "${saneConfig}/etc/sane.d";
+      description = "The value of SANE_CONFIG_DIR.";
+    };
+
   };
 
 
@@ -42,8 +48,8 @@ in
   config = mkIf config.hardware.sane.enable {
 
     environment.systemPackages = backends;
-    environment.variables = {
-      SANE_CONFIG_DIR = mkDefault "${saneConfig}/etc/sane.d";
+    environment.sessionVariables = {
+      SANE_CONFIG_DIR = config.hardware.sane.configDir;
       LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ];
     };
     services.udev.packages = backends;
diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix
index 94d0caaa76b..219c7ed9587 100644
--- a/nixos/modules/services/misc/disnix.nix
+++ b/nixos/modules/services/misc/disnix.nix
@@ -125,13 +125,14 @@ in
           after = [ "dbus.service" ]
             ++ optional config.services.httpd.enable "httpd.service"
             ++ optional config.services.mysql.enable "mysql.service"
+            ++ optional config.services.postgresql.enable "postgresql.service"
             ++ optional config.services.tomcat.enable "tomcat.service"
             ++ optional config.services.svnserve.enable "svnserve.service"
             ++ optional config.services.mongodb.enable "mongodb.service";
 
           restartIfChanged = false;
           
-          path = [ pkgs.nix pkgs.disnix pkgs.dysnomia ];
+          path = [ pkgs.nix pkgs.disnix dysnomia ];
           
           environment = {
             HOME = "/root";
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 4bfd6268234..1ebd3c3643d 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -318,7 +318,7 @@ in
       };
 
     # Set up the environment variables for running Nix.
-    environment.variables = cfg.envVars;
+    environment.sessionVariables = cfg.envVars;
 
     environment.extraInit =
       ''
diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix
index ec8ff426f0a..5338b25715c 100644
--- a/nixos/modules/services/misc/synergy.nix
+++ b/nixos/modules/services/misc/synergy.nix
@@ -83,7 +83,8 @@ in
 
   config = {
 
-    systemd.services."synergy-client" = mkIf cfgC.enable {
+    systemd.services."synergy-client" = {
+      enable = cfgC.enable;
       after = [ "network.target" ];
       description = "Synergy client";
       wantedBy = optional cfgC.autoStart "multi-user.target";
@@ -91,7 +92,8 @@ in
       serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}'';
     };
 
-    systemd.services."synergy-server" = mkIf cfgS.enable {
+    systemd.services."synergy-server" = {
+      enable = cfgS.enable;
       after = [ "network.target" ];
       description = "Synergy server";
       wantedBy = optional cfgS.autoStart "multi-user.target";
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index d543d15b34e..dbfe0ee182a 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -12,7 +12,7 @@ let
     name = "graphite-config";
     paths = lists.filter (el: el != null) [
       (writeTextOrNull "carbon.conf" cfg.carbon.config)
-      (writeTextOrNull "storage-agregation.conf" cfg.carbon.storageAggregation)
+      (writeTextOrNull "storage-aggregation.conf" cfg.carbon.storageAggregation)
       (writeTextOrNull "storage-schemas.conf" cfg.carbon.storageSchemas)
       (writeTextOrNull "blacklist.conf" cfg.carbon.blacklist)
       (writeTextOrNull "whitelist.conf" cfg.carbon.whitelist)
@@ -47,19 +47,19 @@ in {
 
     web = {
       enable = mkOption {
-        description = "Whether to enable graphite web frontend";
+        description = "Whether to enable graphite web frontend.";
         default = false;
         type = types.uniq types.bool;
       };
 
       host = mkOption {
-        description = "Graphite web frontend listen address";
+        description = "Graphite web frontend listen address.";
         default = "127.0.0.1";
         type = types.str;
       };
 
       port = mkOption {
-        description = "Graphite web frontend port";
+        description = "Graphite web frontend port.";
         default = 8080;
         type = types.int;
       };
@@ -67,7 +67,7 @@ in {
 
     carbon = {
       config = mkOption {
-        description = "Content of carbon configuration file";
+        description = "Content of carbon configuration file.";
         default = ''
           [cache]
           # Listen on localhost by default for security reasons
@@ -83,13 +83,13 @@ in {
       };
 
       enableCache = mkOption {
-        description = "Whether to enable carbon cache, the graphite storage daemon";
+        description = "Whether to enable carbon cache, the graphite storage daemon.";
         default = false;
         type = types.uniq types.bool;
       };
 
       storageAggregation = mkOption {
-        description = "Defines how to aggregate data to lower-precision retentions";
+        description = "Defines how to aggregate data to lower-precision retentions.";
         default = null;
         type = types.uniq (types.nullOr types.string);
         example = ''
@@ -101,7 +101,7 @@ in {
       };
 
       storageSchemas = mkOption {
-        description = "Defines retention rates for storing metrics";
+        description = "Defines retention rates for storing metrics.";
         default = "";
         type = types.uniq (types.nullOr types.string);
         example = ''
@@ -112,21 +112,24 @@ in {
       };
 
       blacklist = mkOption {
-        description = "Any metrics received which match one of the experssions will be dropped";
+        description = "Any metrics received which match one of the experssions will be dropped.";
         default = null;
         type = types.uniq (types.nullOr types.string);
         example = "^some\.noisy\.metric\.prefix\..*";
       };
 
       whitelist = mkOption {
-        description = "Only metrics received which match one of the experssions will be persisted";
+        description = "Only metrics received which match one of the experssions will be persisted.";
         default = null;
         type = types.uniq (types.nullOr types.string);
         example = ".*";
       };
 
       rewriteRules = mkOption {
-        description = "Regular expression patterns that can be used to rewrite metric names in a search and replace fashion";
+        description = ''
+          Regular expression patterns that can be used to rewrite metric names
+          in a search and replace fashion.
+        '';
         default = null;
         type = types.uniq (types.nullOr types.string);
         example = ''
@@ -137,7 +140,7 @@ in {
       };
 
       enableRelay = mkOption {
-        description = "Whether to enable carbon relay, the carbon replication and sharding service";
+        description = "Whether to enable carbon relay, the carbon replication and sharding service.";
         default = false;
         type = types.uniq types.bool;
       };
@@ -154,13 +157,13 @@ in {
       };
 
       enableAggregator = mkOption {
-        description = "Whether to enable carbon agregator, the carbon buffering service";
+        description = "Whether to enable carbon agregator, the carbon buffering service.";
         default = false;
         type = types.uniq types.bool;
       };
 
       aggregationRules = mkOption {
-        description = "Defines if and how received metrics will be agregated";
+        description = "Defines if and how received metrics will be agregated.";
         default = null;
         type = types.uniq (types.nullOr types.string);
         example = ''
@@ -188,10 +191,7 @@ in {
       };
       restartTriggers = [
         pkgs.pythonPackages.carbon
-        cfg.carbon.config
-        cfg.carbon.storageAggregation
-        cfg.carbon.storageSchemas
-        cfg.carbon.rewriteRules
+        configDir
       ];
       preStart = ''
         mkdir -p ${cfg.dataDir}/whisper
@@ -212,7 +212,8 @@ in {
         Group = "graphite";
       };
       restartTriggers = [
-        pkgs.pythonPackages.carbon cfg.carbon.config cfg.carbon.aggregationRules
+        pkgs.pythonPackages.carbon
+        configDir
       ];
     };
 
@@ -228,7 +229,8 @@ in {
         Group = "graphite";
       };
       restartTriggers = [
-        pkgs.pythonPackages.carbon cfg.carbon.config cfg.carbon.relayRules
+        pkgs.pythonPackages.carbon
+        configDir
       ];
     };
 
@@ -271,7 +273,6 @@ in {
       '';
       restartTriggers = [
         pkgs.python27Packages.graphite_web
-        pkgs.python27Packages.waitress
       ];
     };
 
diff --git a/nixos/modules/services/monitoring/nagios/default.nix b/nixos/modules/services/monitoring/nagios.nix
index 2eeddf78250..97d153153a5 100644
--- a/nixos/modules/services/monitoring/nagios/default.nix
+++ b/nixos/modules/services/monitoring/nagios.nix
@@ -4,21 +4,12 @@
 with lib;
 
 let
-
   cfg = config.services.nagios;
 
-  nagiosUser = "nagios";
-  nagiosGroup = "nogroup";
-
   nagiosState = "/var/lib/nagios";
   nagiosLogDir = "/var/log/nagios";
 
-  nagiosObjectDefs =
-    [ ./timeperiods.cfg
-      ./host-templates.cfg
-      ./service-templates.cfg
-      ./commands.cfg
-    ] ++ cfg.objectDefs;
+  nagiosObjectDefs = cfg.objectDefs;
 
   nagiosObjectDefsDir = pkgs.runCommand "nagios-objects" {inherit nagiosObjectDefs;}
     "ensureDir $out; ln -s $nagiosObjectDefs $out/";
@@ -30,19 +21,20 @@ let
       log_archive_path=${nagiosLogDir}/archive
       status_file=${nagiosState}/status.dat
       object_cache_file=${nagiosState}/objects.cache
-      comment_file=${nagiosState}/comment.dat
-      downtime_file=${nagiosState}/downtime.dat
       temp_file=${nagiosState}/nagios.tmp
       lock_file=/var/run/nagios.lock # Not used I think.
       state_retention_file=${nagiosState}/retention.dat
+      query_socket=${nagiosState}/nagios.qh
+      check_result_path=${nagiosState}
+      command_file=${nagiosState}/nagios.cmd
 
       # Configuration files.
       #resource_file=resource.cfg
       cfg_dir=${nagiosObjectDefsDir}
 
       # Uid/gid that the daemon runs under.
-      nagios_user=${nagiosUser}
-      nagios_group=${nagiosGroup}
+      nagios_user=nagios
+      nagios_group=nogroup
 
       # Misc. options.
       illegal_macro_output_chars=`~$&|'"<>
@@ -53,26 +45,24 @@ let
   # authentication.
   nagiosCGICfgFile = pkgs.writeText "nagios.cgi.conf"
     ''
-      main_config_file=${nagiosCfgFile}
+      main_config_file=${cfg.mainConfigFile}
       use_authentication=0
-      url_html_path=/nagios
+      url_html_path=${cfg.urlPath}
     '';
 
-  urlPath = cfg.urlPath;
-
   extraHttpdConfig =
     ''
-      ScriptAlias ${urlPath}/cgi-bin ${pkgs.nagios}/sbin
+      ScriptAlias ${cfg.urlPath}/cgi-bin ${pkgs.nagios}/sbin
 
       <Directory "${pkgs.nagios}/sbin">
         Options ExecCGI
         AllowOverride None
         Order allow,deny
         Allow from all
-        SetEnv NAGIOS_CGI_CONFIG ${nagiosCGICfgFile}
+        SetEnv NAGIOS_CGI_CONFIG ${cfg.cgiConfigFile}
       </Directory>
 
-      Alias ${urlPath} ${pkgs.nagios}/share
+      Alias ${cfg.urlPath} ${pkgs.nagios}/share
 
       <Directory "${pkgs.nagios}/share">
         Options None
@@ -83,14 +73,9 @@ let
     '';
 
 in
-
 {
-  ###### interface
-
   options = {
-
     services.nagios = {
-
       enable = mkOption {
         default = false;
         description = "
@@ -116,6 +101,21 @@ in
         ";
       };
 
+      mainConfigFile = mkOption {
+        default = nagiosCfgFile;
+        description = "
+          Derivation for the main configuration file of Nagios.
+        ";
+      };
+
+      cgiConfigFile = mkOption {
+        default = nagiosCGICfgFile;
+        description = "
+          Derivation for the configuration file of Nagios CGI scripts
+          that can be used in web servers for running the Nagios web interface.
+        ";
+      };
+
       enableWebInterface = mkOption {
         default = false;
         description = "
@@ -132,55 +132,53 @@ in
           <literal>http://<replaceable>server</replaceable>/<replaceable>urlPath</replaceable></literal>.
         ";
       };
-
     };
-
   };
 
 
-  ###### implementation
-
   config = mkIf cfg.enable {
-
-    users.extraUsers = singleton
-      { name = nagiosUser;
-        uid = config.ids.uids.nagios;
-        description = "Nagios monitoring daemon";
-        home = nagiosState;
-      };
+    users.extraUsers.nagios = {
+      description = "Nagios user ";
+      uid         = config.ids.uids.nagios;
+      home        = nagiosState;
+      createHome  = true;
+    };
 
     # This isn't needed, it's just so that the user can type "nagiostats
     # -c /etc/nagios.cfg".
-    environment.etc = singleton
-      { source = nagiosCfgFile;
+    environment.etc = [
+      { source = cfg.mainConfigFile;
         target = "nagios.cfg";
-      };
+      }
+    ];
 
     environment.systemPackages = [ pkgs.nagios ];
-
-    jobs.nagios =
-      { description = "Nagios monitoring daemon";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        preStart =
-          ''
-            mkdir -m 0755 -p ${nagiosState} ${nagiosLogDir}
-            chown ${nagiosUser} ${nagiosState} ${nagiosLogDir}
-          '';
-
-        script =
-          ''
-            for i in ${toString config.services.nagios.plugins}; do
-              export PATH=$i/bin:$i/sbin:$i/libexec:$PATH
-            done
-            exec ${pkgs.nagios}/bin/nagios ${nagiosCfgFile}
-          '';
+    systemd.services.nagios = {
+      description = "Nagios monitoring daemon";
+      path     = [ pkgs.nagios ];
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network-interfaces.target" ];
+
+      serviceConfig = {
+        User = "nagios";
+        Restart = "always";
+        RestartSec = 2;
+        PermissionsStartOnly = true;
       };
 
-    services.httpd.extraConfig = optionalString cfg.enableWebInterface extraHttpdConfig;
+      preStart = ''
+        mkdir -m 0755 -p ${nagiosState} ${nagiosLogDir}
+        chown nagios ${nagiosState} ${nagiosLogDir}
+      '';
+
+      script = ''
+        for i in ${toString cfg.plugins}; do
+          export PATH=$i/bin:$i/sbin:$i/libexec:$PATH
+        done
+        exec ${pkgs.nagios}/bin/nagios ${cfg.mainConfigFile}
+      '';
+    };
 
+    services.httpd.extraConfig = optionalString cfg.enableWebInterface extraHttpdConfig;
   };
-
 }
diff --git a/nixos/modules/services/monitoring/nagios/commands.cfg b/nixos/modules/services/monitoring/nagios/commands.cfg
deleted file mode 100644
index 6efdefcd37d..00000000000
--- a/nixos/modules/services/monitoring/nagios/commands.cfg
+++ /dev/null
@@ -1,34 +0,0 @@
-define command {
-    command_name host-notify-by-email
-    command_line printf "%b" "To: $CONTACTEMAIL$\nSubject: [Nagios] Host $HOSTSTATE$ alert for $HOSTNAME$\n\n***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | sendmail $CONTACTEMAIL$
-}
-
-
-define command {
-    command_name notify-by-email
-    command_line printf "%b" "To: $CONTACTEMAIL$\nSubject: [Nagios] $NOTIFICATIONTYPE$ alert - $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$\n\n***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$" | sendmail $CONTACTEMAIL$
-}
-
-
-define command {
-    command_name dummy-ok
-    command_line true
-}
-
-
-define command {
-    command_name check-host-alive
-    command_line check_ping -H $HOSTADDRESS$ -w 3000.0,80% -c 5000.0,100% -p 1
-}
-
-
-define command {
-    command_name check_local_disk
-    command_line check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$
-}
-
-
-define command {
-    command_name check_ssh
-    command_line check_ssh $HOSTADDRESS$
-}
diff --git a/nixos/modules/services/monitoring/nagios/host-templates.cfg b/nixos/modules/services/monitoring/nagios/host-templates.cfg
deleted file mode 100644
index 3a4c269e257..00000000000
--- a/nixos/modules/services/monitoring/nagios/host-templates.cfg
+++ /dev/null
@@ -1,27 +0,0 @@
-define host {
-    name                            generic-host
-    notifications_enabled           1
-    event_handler_enabled           1
-    flap_detection_enabled          1
-    failure_prediction_enabled      1
-    process_perf_data               1
-    retain_status_information       1
-    retain_nonstatus_information    1
-    notification_period             24x7
-    register                        0
-}
-
-
-define host {
-    name                            generic-server
-    use                             generic-host
-    check_period                    24x7
-    max_check_attempts              10
-    check_command                   check-host-alive
-    notification_period             24x7
-    notification_interval           120
-    notification_options            d,u,r
-    contact_groups                  admins
-    register                        0
-    #check_interval                 1
-}
diff --git a/nixos/modules/services/monitoring/nagios/service-templates.cfg b/nixos/modules/services/monitoring/nagios/service-templates.cfg
deleted file mode 100644
index e729ea77675..00000000000
--- a/nixos/modules/services/monitoring/nagios/service-templates.cfg
+++ /dev/null
@@ -1,32 +0,0 @@
-define service {
-    name                            generic-service
-    active_checks_enabled           1
-    passive_checks_enabled          1
-    parallelize_check               1
-    obsess_over_service             1
-    check_freshness                 0
-    notifications_enabled           1
-    event_handler_enabled           1
-    flap_detection_enabled          1
-    failure_prediction_enabled      1
-    process_perf_data               1
-    retain_status_information       1
-    retain_nonstatus_information    1
-    is_volatile                     0
-    register                        0
-}
-
-
-define service {
-    name                            local-service
-    use                             generic-service
-    check_period                    24x7
-    max_check_attempts              4
-    normal_check_interval           5
-    retry_check_interval            1
-    contact_groups                  admins
-    notification_options            w,u,c,r
-    notification_interval           0 # notify only once
-    notification_period             24x7
-    register                        0
-}
diff --git a/nixos/modules/services/monitoring/nagios/timeperiods.cfg b/nixos/modules/services/monitoring/nagios/timeperiods.cfg
deleted file mode 100644
index 2669be54d3d..00000000000
--- a/nixos/modules/services/monitoring/nagios/timeperiods.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-define timeperiod {
-    timeperiod_name 24x7
-    alias           24 Hours A Day, 7 Days A Week
-    sunday          00:00-24:00
-    monday          00:00-24:00
-    tuesday         00:00-24:00
-    wednesday       00:00-24:00
-    thursday        00:00-24:00
-    friday          00:00-24:00
-    saturday        00:00-24:00
-}
diff --git a/nixos/modules/services/monitoring/statsd.nix b/nixos/modules/services/monitoring/statsd.nix
index 05950639c1e..74f3deb4c29 100644
--- a/nixos/modules/services/monitoring/statsd.nix
+++ b/nixos/modules/services/monitoring/statsd.nix
@@ -69,8 +69,8 @@ in
     };
 
     graphitePort = mkOption {
-      description = "Port of Graphite server";
-      default = config.services.graphite.web.port;
+      description = "Port of Graphite server (i.e. carbon-cache).";
+      default = 2003;
       type = types.uniq types.int;
     };
 
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 51a4d193d50..4218b965cd9 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -59,7 +59,7 @@ let
   daemonService = appName: args:
     { description = "Samba Service Daemon ${appName}";
 
-      wantedBy = [ "samba.target" ];
+      requiredBy = [ "samba.target" ];
       partOf = [ "samba.target" ];
 
       environment = {
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
new file mode 100644
index 00000000000..adfee1caec5
--- /dev/null
+++ b/nixos/modules/services/networking/nsd.nix
@@ -0,0 +1,751 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+  cfg = config.services.nsd;
+
+  username = "nsd";
+  stateDir = "/var/lib/nsd";
+  pidFile  = stateDir + "/var/nsd.pid";
+
+  zoneFiles = pkgs.stdenv.mkDerivation {
+      preferLocalBuild = true;
+      name = "nsd-env";
+      buildCommand = concatStringsSep "\n"
+        [ "mkdir -p $out"
+          (concatStrings (mapAttrsToList (zoneName: zoneOptions: ''
+            cat > "$out/${zoneName}" <<_EOF_
+            ${zoneOptions.data}
+            _EOF_
+          '') zoneConfigs))
+        ];
+  };
+
+  configFile = pkgs.writeText "nsd.conf" ''
+    server:
+      username: ${username}
+      chroot:   "${stateDir}"
+
+      # The directory for zonefile: files. The daemon chdirs here.
+      zonesdir: "${stateDir}"
+
+      # the list of dynamically added zones.
+      zonelistfile: "${stateDir}/var/zone.list"
+      database:     "${stateDir}/var/nsd.db"
+      logfile:      "${stateDir}/var/nsd.log"
+      pidfile:      "${pidFile}"
+      xfrdfile:     "${stateDir}/var/xfrd.state"
+      xfrdir:       "${stateDir}/tmp"
+
+      # interfaces
+    ${forEach "  ip-address: " cfg.interfaces}
+
+      server-count:        ${toString cfg.serverCount}
+      ip-transparent:      ${yesOrNo  cfg.ipTransparent}
+      do-ip4:              ${yesOrNo  cfg.ipv4}
+      do-ip6:              ${yesOrNo  cfg.ipv6}
+      port:                ${toString cfg.port}
+      verbosity:           ${toString cfg.verbosity}
+      hide-version:        ${yesOrNo  cfg.hideVersion}
+      identity:            "${cfg.identity}"
+      ${maybeString "nsid: " cfg.nsid}
+      tcp-count:           ${toString cfg.tcpCount}
+      tcp-query-count:     ${toString cfg.tcpQueryCount}
+      tcp-timeout:         ${toString cfg.tcpTimeout}
+      ipv4-edns-size:      ${toString cfg.ipv4EDNSSize}
+      ipv6-edns-size:      ${toString cfg.ipv6EDNSSize}
+      ${if cfg.statistics == null then "" else "statistics:          ${toString cfg.statistics}"}
+      xfrd-reload-timeout: ${toString cfg.xfrdReloadTimeout}
+      zonefiles-check:     ${yesOrNo  cfg.zonefilesCheck}
+
+      rrl-size:                ${toString cfg.ratelimit.size}
+      rrl-ratelimit:           ${toString cfg.ratelimit.ratelimit}
+      rrl-whitelist-ratelimit: ${toString cfg.ratelimit.whitelistRatelimit}
+      ${maybeString "rrl-slip: "               cfg.ratelimit.slip}
+      ${maybeString "rrl-ipv4-prefix-length: " cfg.ratelimit.ipv4PrefixLength}
+      ${maybeString "rrl-ipv6-prefix-length: " cfg.ratelimit.ipv6PrefixLength}
+
+    ${keyConfigFile}
+
+    remote-control:
+      control-enable:    ${yesOrNo  cfg.remoteControl.enable}
+    ${forEach "  control-interface: " cfg.remoteControl.interfaces}
+      control-port:      ${toString cfg.port}
+      server-key-file:   "${cfg.remoteControl.serverKeyFile}"
+      server-cert-file:  "${cfg.remoteControl.serverCertFile}"
+      control-key-file:  "${cfg.remoteControl.controlKeyFile}"
+      control-cert-file: "${cfg.remoteControl.controlCertFile}"
+
+    # zone files reside in "${zoneFiles}" linked to "${stateDir}/zones"
+    ${concatStrings (mapAttrsToList zoneConfigFile zoneConfigs)}
+
+    ${cfg.extraConfig}
+  '';
+
+  yesOrNo     = b: if b then "yes" else "no";
+  maybeString = pre: s: if s == null then "" else ''${pre} "${s}"'';
+  forEach     = pre: l: concatMapStrings (x: pre + x + "\n") l;
+
+
+  keyConfigFile = concatStrings (mapAttrsToList (keyName: keyOptions: ''
+    key:
+      name:      "${keyName}"
+      algorithm: "${keyOptions.algorithm}"
+      include:   "${stateDir}/private/${keyName}"
+  '') cfg.keys);
+
+  copyKeys = concatStrings (mapAttrsToList (keyName: keyOptions: ''
+    secret=$(cat "${keyOptions.keyFile}")
+    dest="${stateDir}/private/${keyName}"
+    echo "  secret: \"$secret\"" > "$dest"
+    ${pkgs.coreutils}/bin/chown ${username}:${username} "$dest"
+    ${pkgs.coreutils}/bin/chmod 0400 "$dest"
+  '') cfg.keys);
+
+
+  zoneConfigFile = name: zone: ''
+        zone:
+          name:         "${name}"
+          zonefile:     "${stateDir}/zones/${name}"
+          ${maybeString "outgoing-interface: " zone.outgoingInterface}
+        ${forEach     "  rrl-whitelist: "      zone.rrlWhitelist}
+
+        ${forEach     "  allow-notify: "       zone.allowNotify}
+        ${forEach     "  request-xfr: "        zone.requestXFR}
+          allow-axfr-fallback: ${yesOrNo       zone.allowAXFRFallback}
+
+        ${forEach     "  notify: "             zone.notify}
+          notify-retry:                        ${toString zone.notifyRetry}
+        ${forEach     "  provide-xfr: "        zone.provideXFR}
+
+    '';
+
+  zoneConfigs = zoneConfigs' {} "" { children = cfg.zones; };
+
+  zoneConfigs' = parent: name: zone:
+    if !(zone ? children) || zone.children == null || zone.children == { }
+      # leaf -> actual zone
+      then listToAttrs [ (nameValuePair name (parent // zone)) ]
+
+      # fork -> pattern
+      else zipAttrsWith (name: head) (
+          mapAttrsToList (name: child: zoneConfigs' (parent // zone // { children = {}; }) name child)
+                         zone.children
+      );
+
+  # fighting infinite recursion
+  zoneOptions  = zoneOptionsRaw // childConfig zoneOptions1 true;
+  zoneOptions1 = zoneOptionsRaw // childConfig zoneOptions2 false;
+  zoneOptions2 = zoneOptionsRaw // childConfig zoneOptions3 false;
+  zoneOptions3 = zoneOptionsRaw // childConfig zoneOptions4 false;
+  zoneOptions4 = zoneOptionsRaw // childConfig zoneOptions5 false;
+  zoneOptions5 = zoneOptionsRaw // childConfig zoneOptions6 false;
+  zoneOptions6 = zoneOptionsRaw // childConfig null         false;
+
+  childConfig = x: v: { options.children = { type = types.attrsOf x; visible = v; }; };
+
+  zoneOptionsRaw = types.submodule (
+    { options, ... }:
+    { options = {
+        children = mkOption {
+            default     = {};
+            description = ''
+              Children zones inherit all options of their parents. Attributes
+              defined in a child will overwrite the ones of its parent. Only
+              leaf zones will be actually served. This way it's possible to
+              define maybe zones which share most attributes without
+              duplicating everything. This mechanism replaces nsd's patterns
+              in a save and functional way.
+            '';
+        };
+
+        allowNotify = mkOption {
+          type        = types.listOf types.str;
+          default     = [ ];
+          example     = [ "192.0.2.0/24 NOKEY" "10.0.0.1-10.0.0.5 my_tsig_key_name"
+                           "10.0.3.4&255.255.0.0 BLOCKED"
+                        ];
+          description = ''
+            Listed primary servers are allowed to notify this secondary server.
+            <screen><![CDATA[
+            Format: <ip> <key-name | NOKEY | BLOCKED>
+
+            <ip> either a plain IPv4/IPv6 address or range. Valid patters for ranges:
+            * 10.0.0.0/24            # via subnet size
+            * 10.0.0.0&255.255.255.0 # via subnet mask
+            * 10.0.0.1-10.0.0.254    # via range
+
+            A optional port number could be added with a '@':
+            * 2001:1234::1@1234
+
+            <key-name | NOKEY | BLOCKED>
+            * <key-name> will use the specified TSIG key
+            * NOKEY      no TSIG signature is required
+            * BLOCKED    notifies from non-listed or blocked IPs will be ignored
+            * ]]></screen>
+          '';
+        };
+
+        requestXFR = mkOption {
+          type        = types.listOf types.str;
+          default     = [];
+          example     = [];
+          description = ''
+            Format: <code>[AXFR|UDP] &lt;ip-address&gt; &lt;key-name | NOKEY&gt;</code>
+          '';
+        };
+
+        allowAXFRFallback = mkOption {
+          type        = types.bool;
+          default     = true;
+          description = ''
+            If NSD as secondary server should be allowed to AXFR if the primary
+            server does not allow IXFR.
+          '';
+        };
+
+        notify = mkOption {
+          type        = types.listOf types.str;
+          default     = [];
+          example     = [ "10.0.0.1@3721 my_key" "::5 NOKEY" ];
+          description = ''
+            This primary server will notify all given secondary servers about
+            zone changes.
+            <screen><![CDATA[
+            Format: <ip> <key-name | NOKEY>
+
+            <ip> a plain IPv4/IPv6 address with on optional port number (ip@port)
+
+            <key-name | NOKEY>
+            * <key-name> sign notifies with the specified key
+            * NOKEY      don't sign notifies
+            ]]></screen>
+          '';
+        };
+
+        notifyRetry = mkOption {
+          type        = types.int;
+          default     = 5;
+          description = ''
+            Specifies the number of retries for failed notifies. Set this along with notify.
+          '';
+        };
+
+        provideXFR = mkOption {
+          type        = types.listOf types.str;
+          default     = [];
+          example     = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ];
+          description = ''
+            Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
+            address range 192.0.2.0/24, 1.2.3.4&amp;255.255.0.0, 3.0.2.20-3.0.2.40
+          '';
+        };
+
+        outgoingInterface = mkOption {
+          type        = types.nullOr types.str;
+          default     = null;
+          example     = "2000::1@1234";
+          description = ''
+            This address will be used for zone-transfere requests if configured
+            as a secondary server or notifications in case of a primary server.
+            Supply either a plain IPv4 or IPv6 address with an optional port
+            number (ip@port).
+          '';
+        };
+
+        rrlWhitelist = mkOption {
+          type        = types.listOf types.str;
+          default     = [];
+          description = ''
+            Whitelists the given rrl-types.
+            The RRL classification types are:  nxdomain,  error, referral, any,
+            rrsig, wildcard, nodata, dnskey, positive, all
+          '';
+        };
+
+        data = mkOption {
+          type        = types.str;
+          default     = "";
+          example     = "";
+          description = ''
+            The actual zone data. This is the content of your zone file.
+            Use imports or pkgs.lib.readFile if you don't want this data in your config file.
+          '';
+        };
+
+      };
+    }
+  );
+
+in
+{
+  options = {
+    services.nsd = {
+
+      enable = mkOption {
+        type        = types.bool;
+        default     = false;
+        description = ''
+          Whether to enable the NSD authoritative domain name server.
+        '';
+      };
+
+      rootServer = mkOption {
+        type        = types.bool;
+        default     = false;
+        description = ''
+          Wheter if this server will be a root server (a DNS root server, you
+          usually don't want that).
+        '';
+      };
+
+      interfaces = mkOption {
+        type        = types.listOf types.str;
+        default     = [ "127.0.0.0" "::1" ];
+        description = ''
+          What addresses the server should listen to.
+        '';
+      };
+
+      serverCount = mkOption {
+        type        = types.int;
+        default     = 1;
+        description = ''
+          Number of NSD servers to fork. Put the number of CPUs to use here.
+        '';
+      };
+
+      ipTransparent = mkOption {
+        type        = types.bool;
+        default     = false;
+        description = ''
+          Allow binding to non local addresses.
+        '';
+      };
+
+      ipv4 = mkOption {
+        type        = types.bool;
+        default     = true;
+        description = ''
+          Wheter to listen on IPv4 connections.
+        '';
+      };
+
+      ipv6 = mkOption {
+        type        = types.bool;
+        default     = true;
+        description = ''
+          Wheter to listen on IPv6 connections.
+        '';
+      };
+
+      port = mkOption {
+        type        = types.int;
+        default     = 53;
+        description = ''
+          Port the service should bind do.
+        '';
+      };
+
+      verbosity = mkOption {
+        type        = types.int;
+        default     = 0;
+        description = ''
+          Verbosity level.
+        '';
+      };
+
+      hideVersion = mkOption {
+        type        = types.bool;
+        default     = true;
+        description = ''
+          Wheter NSD should answer VERSION.BIND and VERSION.SERVER CHAOS class queries.
+        '';
+      };
+
+      identity = mkOption {
+        type        = types.str;
+        default     = "unidentified server";
+        description = ''
+          Identify the server (CH TXT ID.SERVER entry).
+        '';
+      };
+
+      nsid = mkOption {
+        type        = types.nullOr types.str;
+        default     = null;
+        description = ''
+          NSID identity (hex string, or "ascii_somestring").
+        '';
+      };
+
+      tcpCount = mkOption {
+        type        = types.int;
+        default     = 100;
+        description = ''
+          Maximum number of concurrent TCP connections per server.
+        '';
+      };
+
+      tcpQueryCount = mkOption {
+        type        = types.int;
+        default     = 0;
+        description = ''
+          Maximum number of queries served on a single TCP connection.
+          0 means no maximum.
+        '';
+      };
+
+      tcpTimeout = mkOption {
+        type        = types.int;
+        default     = 120;
+        description = ''
+          TCP timeout in seconds.
+        '';
+      };
+
+      ipv4EDNSSize = mkOption {
+        type        = types.int;
+        default     = 4096;
+        description = ''
+          Preferred EDNS buffer size for IPv4.
+        '';
+      };
+
+      ipv6EDNSSize = mkOption {
+        type        = types.int;
+        default     = 4096;
+        description = ''
+          Preferred EDNS buffer size for IPv6.
+        '';
+      };
+
+      statistics = mkOption {
+        type        = types.nullOr types.int;
+        default     = null;
+        description = ''
+          Statistics are produced every number of seconds. Prints to log.
+          If null no statistics are logged.
+        '';
+      };
+
+      xfrdReloadTimeout = mkOption {
+        type        = types.int;
+        default     = 1;
+        description = ''
+          Number of seconds between reloads triggered by xfrd.
+        '';
+      };
+
+      zonefilesCheck = mkOption {
+        type        = types.bool;
+        default     = true;
+        description = ''
+          Wheter to check mtime of all zone files on start and sighup.
+        '';
+      };
+
+
+      extraConfig = mkOption {
+        type        = types.str;
+        default     = "";
+        description = ''
+          Extra nsd config.
+        '';
+      };
+
+
+      ratelimit = mkOption {
+        type = types.submodule (
+          { options, ... }:
+          { options = {
+
+              enable = mkOption {
+                type        = types.bool;
+                default     = false;
+                description = ''
+                  Enable ratelimit capabilities.
+                '';
+              };
+
+              size = mkOption {
+                type        = types.int;
+                default     = 1000000;
+                description = ''
+                  Size of the hashtable. More buckets use more memory but lower
+                  the chance of hash hash collisions.
+                '';
+              };
+
+              ratelimit = mkOption {
+                type        = types.int;
+                default     = 200;
+                description = ''
+                  Max qps allowed from any query source.
+                  0 means unlimited. With an verbosity of 2 blocked and
+                  unblocked subnets will be logged.
+                '';
+              };
+
+              whitelistRatelimit = mkOption {
+                type        = types.int;
+                default     = 2000;
+                description = ''
+                  Max qps allowed from whitelisted sources.
+                  0 means unlimited. Set the rrl-whitelist option for specific
+                  queries to apply this limit instead of the default to them.
+                '';
+              };
+
+              slip = mkOption {
+                type        = types.nullOr types.int;
+                default     = null;
+                description = ''
+                  Number of packets that get discarded before replying a SLIP response.
+                  0 disables SLIP responses. 1 will make every response a SLIP response.
+                '';
+              };
+
+              ipv4PrefixLength = mkOption {
+                type        = types.nullOr types.int;
+                default     = null;
+                description = ''
+                  IPv4 prefix length. Addresses are grouped by netblock.
+                '';
+              };
+
+              ipv6PrefixLength = mkOption {
+                type        = types.nullOr types.int;
+                default     = null;
+                description = ''
+                  IPv6 prefix length. Addresses are grouped by netblock.
+                '';
+              };
+
+            };
+          });
+        default = {
+        };
+        example = {};
+        description = ''
+        '';
+      };
+
+
+      remoteControl = mkOption {
+        type = types.submodule (
+          { config, options, ... }:
+          { options = {
+
+              enable = mkOption {
+                type        = types.bool;
+                default     = false;
+                description = ''
+                  Wheter to enable remote control via nsd-control(8).
+                '';
+              };
+
+              interfaces = mkOption {
+                type        = types.listOf types.str;
+                default     = [ "127.0.0.1" "::1" ];
+                description = ''
+                  Which interfaces NSD should bind to for remote control.
+                '';
+              };
+
+              port = mkOption {
+                type        = types.int;
+                default     = 8952;
+                description = ''
+                  Port number for remote control operations (uses TLS over TCP).
+                '';
+              };
+
+              serverKeyFile = mkOption {
+                type        = types.path;
+                default     = "/etc/nsd/nsd_server.key";
+                description = ''
+                  Path to the server private key, which is used by the server
+                  but not by nsd-control. This file is generated by nsd-control-setup.
+                '';
+              };
+
+              serverCertFile = mkOption {
+                type        = types.path;
+                default     = "/etc/nsd/nsd_server.pem";
+                description = ''
+                  Path to the server self signed certificate, which is used by the server
+                  but and by nsd-control. This file is generated by nsd-control-setup.
+                '';
+              };
+
+              controlKeyFile = mkOption {
+                type        = types.path;
+                default     = "/etc/nsd/nsd_control.key";
+                description = ''
+                  Path to the client private key, which is used by nsd-control
+                  but not by the server. This file is generated by nsd-control-setup.
+                '';
+              };
+
+              controlCertFile = mkOption {
+                type        = types.path;
+                default     = "/etc/nsd/nsd_control.pem";
+                description = ''
+                  Path to the client certificate signed with the server certificate.
+                  This file is used by nsd-control and generated by nsd-control-setup.
+                '';
+              };
+
+            };
+
+          });
+        default = {
+        };
+        example = {};
+        description = ''
+        '';
+      };
+
+
+      keys = mkOption {
+        type = types.attrsOf (types.submodule (
+          { options, ... }:
+          { options = {
+
+              algorithm = mkOption {
+                type        = types.str;
+                default     = "hmac-sha256";
+                description = ''
+                  Authentication algorithm for this key.
+                '';
+              };
+
+              keyFile = mkOption {
+                type        = types.path;
+                description = ''
+                  Path to the file which contains the actual base64 encoded
+                  key. The key will be copied into "${stateDir}/private" before
+                  NSD starts. The copied file is only accessibly by the NSD
+                  user.
+                '';
+              };
+
+            };
+          }));
+        default = {
+        };
+        example = {
+            "tsig.example.org" = {
+              algorithm = "hmac-md5";
+              secret    = "aaaaaabbbbbbccccccdddddd";
+            };
+        };
+        description = ''
+          Define your TSIG keys here.
+        '';
+      };
+
+      zones = mkOption {
+        type        = types.attrsOf zoneOptions;
+        default     = {};
+        example     = {
+            "serverGroup1" = {
+                provideXFR = [ "10.1.2.3 NOKEY" ];
+                children = {
+                    "example.com." = {
+                        data = ''
+                          $ORIGIN example.com.
+                          $TTL    86400
+                          @ IN SOA a.ns.example.com. admin.example.com. (
+                          ...
+                        '';
+                    };
+                    "example.org." = {
+                        data = ''
+                          $ORIGIN example.org.
+                          $TTL    86400
+                          @ IN SOA a.ns.example.com. admin.example.com. (
+                          ...
+                        '';
+                    };
+                };
+            };
+
+            "example.net." = {
+                provideXFR = [ "10.3.2.1 NOKEY" ];
+                data = ''...'';
+            };
+        };
+        description = ''
+          Define your zones here. Zones can cascade other zones and therefore
+          inherit settings from parent zones. Look at the definition of
+          children to learn about inheritance and child zones.
+          The given example will define 3 zones (example.(com|org|net).). Both
+          example.com. and example.org. inherit their configuration from
+          serverGroup1.
+        '';
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    # this is not working :(
+    nixpkgs.config.nsd = {
+        ipv6       = cfg.ipv6;
+        ratelimit  = cfg.ratelimit.enable;
+        rootServer = cfg.rootServer;
+    };
+
+    users.extraGroups = singleton {
+        name = username;
+        gid  = config.ids.gids.nsd;
+    };
+
+    users.extraUsers = singleton {
+        name        = username;
+        description = "NSD service user";
+        home        = stateDir;
+        createHome  = true;
+        uid         = config.ids.uids.nsd;
+        group       = username;
+    };
+
+    systemd.services.nsd = {
+      description = "NSD authoritative only domain name service";
+      wantedBy    = [ "multi-user.target" ];
+      after       = [ "network.target" ];
+
+      serviceConfig = {
+        Type      = "forking";
+        PIDFile   = pidFile;
+        Restart   = "always";
+        ExecStart = "${pkgs.nsd}/sbin/nsd -c ${configFile}";
+      };
+
+      preStart = ''
+        ${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/private"
+        ${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/tmp"
+        ${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/var"
+
+        ${pkgs.coreutils}/bin/touch "${stateDir}/don't touch anything in here"
+
+        ${pkgs.coreutils}/bin/rm -f "${stateDir}/private/"*
+        ${pkgs.coreutils}/bin/rm -f "${stateDir}/tmp/"*
+
+        ${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/private"
+        ${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/tmp"
+        ${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/var"
+
+        ${pkgs.coreutils}/bin/rm -rf "${stateDir}/zones"
+        ${pkgs.coreutils}/bin/cp -r  "${zoneFiles}" "${stateDir}/zones"
+
+        ${copyKeys}
+      '';
+    };
+
+  };
+}
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index b7a3566f95d..3c32e4a3dfe 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -93,6 +93,14 @@ in {
         Data directory for elasticsearch.
       '';
     };
+
+    extraCmdLineOptions = mkOption {
+      description = "Extra command line options for the elasticsearch launcher";
+      default = [];
+      type = types.listOf types.string;
+      example = [ "-Djava.net.preferIPv4Stack=true" ];
+    };
+
   };
 
   ###### implementation
@@ -104,8 +112,9 @@ in {
       after = [ "network-interfaces.target" ];
       environment = { ES_HOME = cfg.dataDir; };
       serviceConfig = {
-        ExecStart = "${pkgs.elasticsearch}/bin/elasticsearch -f -Des.path.conf=${configDir}";
+        ExecStart = "${pkgs.elasticsearch}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}";
         User = "elasticsearch";
+        PermissionsStartOnly = true;
       };
       preStart = ''
         mkdir -m 0700 -p ${cfg.dataDir}
diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix
index 75ec6671d15..b8359d4756b 100644
--- a/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -594,14 +594,14 @@ in
                      message = "SSL is enabled for HTTPD, but sslServerCert and/or sslServerKey haven't been specified."; }
                  ];
 
-    users.extraUsers = optionalAttrs (mainCfg.user == "wwwrun") singleton
+    users.extraUsers = optional (mainCfg.user == "wwwrun")
       { name = "wwwrun";
         group = "wwwrun";
         description = "Apache httpd user";
         uid = config.ids.uids.wwwrun;
       };
 
-    users.extraGroups = optionalAttrs (mainCfg.group == "wwwrun") singleton
+    users.extraGroups = optional (mainCfg.group == "wwwrun")
       { name = "wwwrun";
         gid = config.ids.gids.wwwrun;
       };
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index ff94ee42d28..7c2d3a42973 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -84,8 +84,6 @@ in
   };
 
   config = mkIf cfg.enable {
-    environment.systemPackages = [ nginx ];
-
     # TODO: test user supplied config file pases syntax test
 
     systemd.services.nginx = {
@@ -96,6 +94,7 @@ in
       preStart =
         ''
         mkdir -p ${cfg.stateDir}/logs
+        chmod 700 ${cfg.stateDir}
         chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
         '';
       serviceConfig = {
@@ -105,7 +104,7 @@ in
 
     users.extraUsers = optionalAttrs (cfg.user == "nginx") (singleton
       { name = "nginx";
-        group = "nginx";
+        group = cfg.group;
         uid = config.ids.uids.nginx;
       });
 
diff --git a/nixos/modules/services/web-servers/phpfpm.nix b/nixos/modules/services/web-servers/phpfpm.nix
index 4a14f9b41a4..8551e3ccdeb 100644
--- a/nixos/modules/services/web-servers/phpfpm.nix
+++ b/nixos/modules/services/web-servers/phpfpm.nix
@@ -42,6 +42,12 @@ in {
         '';
       };
 
+      phpIni = mkOption {
+        type = types.path;
+        default = "${cfg.phpPackage}/etc/php-recommended.ini";
+        description = "php.ini file to use.";
+      };
+
       poolConfigs = mkOption {
         type = types.attrsOf types.lines;
         default = {};
@@ -75,7 +81,7 @@ in {
         mkdir -p "${stateDir}"
       '';
       serviceConfig = {
-        ExecStart = "${cfg.phpPackage}/sbin/php-fpm -y ${cfgFile}";
+        ExecStart = "${cfg.phpPackage}/sbin/php-fpm -y ${cfgFile} -c ${cfg.phpIni}";
         PIDFile = pidFile;
       };
     };
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index b739ef693ce..62999dceee3 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -95,7 +95,7 @@ let
   # kernel, systemd units, init scripts, etc.) as well as a script
   # `switch-to-configuration' that activates the configuration and
   # makes it bootable.
-  system = showWarnings (
+  baseSystem = showWarnings (
     if [] == failed then pkgs.stdenv.mkDerivation {
       name = "nixos-${config.system.nixosVersion}";
       preferLocalBuild = true;
@@ -118,6 +118,10 @@ let
       perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
   } else throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failed)}");
 
+  # Replace runtime dependencies
+  system = fold ({ oldDependency, newDependency }: drv:
+      pkgs.replaceDependency { inherit oldDependency newDependency drv; }
+    ) baseSystem config.system.replaceRuntimeDependencies;
 
 in
 
@@ -184,6 +188,33 @@ in
       '';
     };
 
+    system.replaceRuntimeDependencies = mkOption {
+      default = [];
+      example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { ... }; }) ]";
+      type = types.listOf (types.submodule (
+        { options, ... }: {
+          options.original = mkOption {
+            type = types.package;
+            description = "The original package to override.";
+          };
+
+          options.replacement = mkOption {
+            type = types.package;
+            description = "The replacement package.";
+          };
+        })
+      );
+      apply = map ({ original, replacement, ... }: {
+        oldDependency = original;
+        newDependency = replacement;
+      });
+      description = ''
+        List of packages to override without doing a full rebuild.
+        The original derivation and replacement derivation must have the same
+        name length, and ideally should have close-to-identical directory layout.
+      '';
+    };
+
   };
 
 
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 761600f9e55..51ebca7dd43 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -15,13 +15,13 @@ let
       pkgs.runCommand "unit" { preferLocalBuild = true; inherit (unit) text; }
         ''
           mkdir -p $out
-          echo -n "$text" > $out/${name}
+          echo -n "$text" > $out/${shellEscape name}
         ''
     else
       pkgs.runCommand "unit" { preferLocalBuild = true; }
         ''
           mkdir -p $out
-          ln -s /dev/null $out/${name}
+          ln -s /dev/null $out/${shellEscape name}
         '';
 
   upstreamSystemUnits =
@@ -187,9 +187,11 @@ let
       "timers.target"
     ];
 
+  shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s);
+
   makeJobScript = name: text:
-    let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${name}"; inherit text; };
-    in "${x}/bin/${name}";
+    let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${shellEscape name}"; inherit text; };
+    in "${x}/bin/${shellEscape name}";
 
   unitConfig = { name, config, ... }: {
     config = {
@@ -681,6 +683,13 @@ in
       description = "Definition of systemd per-user service units.";
     };
 
+    systemd.user.sockets = mkOption {
+      default = {};
+      type = types.attrsOf types.optionSet;
+      options = [ socketOptions unitConfig ];
+      description = "Definition of systemd per-user socket units.";
+    };
+
   };
 
 
@@ -765,7 +774,8 @@ in
                        in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
 
     systemd.user.units =
-      mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services;
+      mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services
+      // mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.user.sockets;
 
     system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled
       [ "DEVTMPFS" "CGROUPS" "INOTIFY_USER" "SIGNALFD" "TIMERFD" "EPOLL" "NET"
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 9cc8b154324..991f9f26145 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -183,6 +183,15 @@ in
       '';
     };
 
+    networking.search = mkOption {
+      default = [];
+      example = [ "example.com" "local.domain" ];
+      type = types.listOf types.str;
+      description = ''
+        The list of search paths used when resolving domain names.
+      '';
+    };
+
     networking.domain = mkOption {
       default = "";
       example = "home";
@@ -424,6 +433,7 @@ in
                 ${optionalString (cfg.nameservers != [] && cfg.domain != "") ''
                   domain ${cfg.domain}
                 ''}
+                ${optionalString (cfg.search != []) ("search " + concatStringsSep " " cfg.search)}
                 ${flip concatMapStrings cfg.nameservers (ns: ''
                   nameserver ${ns}
                 '')}
diff --git a/nixos/modules/tasks/trackpoint.nix b/nixos/modules/tasks/trackpoint.nix
new file mode 100644
index 00000000000..4be2c3eb4c4
--- /dev/null
+++ b/nixos/modules/tasks/trackpoint.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  ###### interface
+
+  options = {
+
+    hardware.trackpoint = {
+
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Enable sensitivity and speed configuration for trackpoints.
+        '';
+      };
+  
+      sensitivity = mkOption {
+        default = 128;
+        example = 255;
+        type = types.int;
+        description = ''
+          Configure the trackpoint sensitivity. By default, the kernel
+          configures 128.
+        '';
+      };
+
+      speed = mkOption {
+        default = 97;
+        example = 255;
+        type = types.int;
+        description = ''
+          Configure the trackpoint sensitivity. By default, the kernel
+          configures 97.
+        '';
+      };
+      
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.hardware.trackpoint.enable {
+
+    jobs.trackpoint =
+      { description = "Initialize trackpoint";
+
+        startOn = "started udev";
+
+        task = true;
+
+        script = ''
+          echo -n ${toString config.hardware.trackpoint.sensitivity} \
+            > /sys/devices/platform/i8042/serio1/sensitivity
+          echo -n ${toString config.hardware.trackpoint.speed} \
+            > /sys/devices/platform/i8042/serio1/speed
+        '';
+      };
+         
+  };
+
+}
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index 9e64327c3ab..7d6109f212a 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -26,7 +26,7 @@ in
               ''
                 mkdir $out
                 diskImage=$out/nixos.img
-                ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "4G"
+                ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "8G"
                 mv closure xchg/
               '';
             buildInputs = [ pkgs.utillinux pkgs.perl ];
@@ -34,16 +34,32 @@ in
               [ "closure" config.system.build.toplevel ];
           }
           ''
-            # Create an empty filesystem and mount it.
-            ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda
-            ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda
-            mkdir /mnt
-            mount /dev/vda /mnt
+            ${if cfg.hvm then ''
+              # Create a single / partition.
+              ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos
+              ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s
+              . /sys/class/block/vda1/uevent
+              mknod /dev/vda1 b $MAJOR $MINOR
+
+              # Create an empty filesystem and mount it.
+              ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1
+              ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
+              mkdir /mnt
+              mount /dev/vda1 /mnt
+            '' else ''
+              # Create an empty filesystem and mount it.
+              ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda
+              ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda
+              mkdir /mnt
+              mount /dev/vda /mnt
+            ''}
 
             # The initrd expects these directories to exist.
             mkdir /mnt/dev /mnt/proc /mnt/sys
 
             mount -o bind /proc /mnt/proc
+            mount -o bind /dev /mnt/dev
+            mount -o bind /sys /mnt/sys
 
             # Copy all paths in the closure to the filesystem.
             storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure)
@@ -73,9 +89,10 @@ in
             cp ${./amazon-config.nix} /mnt/etc/nixos/configuration.nix
 
             # Generate the GRUB menu.
+            ln -s vda /dev/xvda
             chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot
 
-            umount /mnt/proc
+            umount /mnt/proc /mnt/dev /mnt/sys
             umount /mnt
           ''
       );
@@ -86,7 +103,7 @@ in
     boot.kernelModules = [ "xen-netfront" ];
 
     # Generate a GRUB menu.  Amazon's pv-grub uses this to boot our kernel/initrd.
-    boot.loader.grub.version = 1;
+    boot.loader.grub.version = if cfg.hvm then 2 else 1;
     boot.loader.grub.device = if cfg.hvm then "/dev/xvda" else "nodev";
     boot.loader.grub.timeout = 0;
     boot.loader.grub.extraPerEntryConfig = "root (hd0${lib.optionalString cfg.hvm ",0"})";