summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-10-07 00:09:37 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-10-07 00:09:37 +0200
commita85dcf4a00c1ac354eda3b84209b8fa6b2133259 (patch)
tree16bbf46e3cd5d7ea259783ee8b1ea8d5c7048e0d /nixos
parent4b2ce84872a0903b9800d3ed23915f48ecedc565 (diff)
parent46a9e805efeee40d360605fa5987866ca45fed23 (diff)
downloadnixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.tar
nixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.tar.gz
nixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.tar.bz2
nixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.tar.lz
nixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.tar.xz
nixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.tar.zst
nixlib-a85dcf4a00c1ac354eda3b84209b8fa6b2133259.zip
Merge remote-tracking branch 'origin/master' into staging
Conflicts:
	pkgs/development/libraries/libav/default.nix
	pkgs/shells/bash/bash-4.2-patches.nix
	pkgs/stdenv/generic/default.nix
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/x-windows.xml19
-rw-r--r--nixos/lib/test-driver/Machine.pm2
-rw-r--r--nixos/lib/testing.nix6
-rw-r--r--nixos/modules/config/fonts/fontconfig.nix5
-rw-r--r--nixos/modules/config/pulseaudio.nix23
-rw-r--r--nixos/modules/config/users-groups.nix4
-rw-r--r--nixos/modules/hardware/opengl.nix20
-rw-r--r--nixos/modules/hardware/video/ati.nix37
-rw-r--r--nixos/modules/misc/ids.nix11
-rwxr-xr-xnixos/modules/module-list.nix5
-rw-r--r--nixos/modules/programs/environment.nix1
-rw-r--r--nixos/modules/programs/uim.nix4
-rw-r--r--nixos/modules/rename.nix1
-rw-r--r--nixos/modules/services/audio/mpd.nix54
-rw-r--r--nixos/modules/services/databases/postgresql.nix4
-rw-r--r--nixos/modules/services/misc/cpuminer-cryptonight.nix66
-rw-r--r--nixos/modules/services/misc/gitolite.nix13
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix49
-rw-r--r--nixos/modules/services/network-filesystems/yandex-disk.nix4
-rw-r--r--nixos/modules/services/networking/atftpd.nix4
-rw-r--r--nixos/modules/services/networking/btsync.nix2
-rw-r--r--nixos/modules/services/networking/cjdns.nix4
-rw-r--r--nixos/modules/services/networking/consul.nix166
-rw-r--r--nixos/modules/services/networking/mailpile.nix76
-rw-r--r--nixos/modules/services/networking/nat.nix27
-rw-r--r--nixos/modules/services/web-servers/lighttpd/cgit.nix3
-rw-r--r--nixos/modules/services/web-servers/lighttpd/default.nix95
-rw-r--r--nixos/modules/services/web-servers/lighttpd/gitweb.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4_next.nix163
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix3
-rw-r--r--nixos/modules/services/x11/window-managers/afterstep.nix28
-rw-r--r--nixos/modules/services/x11/window-managers/ratpoison.nix28
-rw-r--r--nixos/modules/services/x11/window-managers/windowmaker.nix28
-rw-r--r--nixos/modules/services/x11/xserver.nix12
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix10
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl5
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh21
-rw-r--r--nixos/modules/system/boot/stage-1.nix16
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix4
-rw-r--r--nixos/modules/system/boot/systemd.nix2
-rw-r--r--nixos/modules/tasks/network-interfaces.nix46
-rw-r--r--nixos/release-combined.nix16
-rw-r--r--nixos/release.nix15
-rw-r--r--nixos/tests/installer.nix7
-rw-r--r--nixos/tests/jenkins.nix2
-rw-r--r--nixos/tests/kde4.nix2
-rw-r--r--nixos/tests/munin.nix2
-rw-r--r--nixos/tests/nat.nix130
49 files changed, 1016 insertions, 234 deletions
diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml
index 4008e89fceac..95e66f0c70c0 100644
--- a/nixos/doc/manual/configuration/x-windows.xml
+++ b/nixos/doc/manual/configuration/x-windows.xml
@@ -73,6 +73,25 @@ hardware.opengl.driSupport32Bit = true;
 
 </simplesect>
 
+<simplesect><title>AMD Graphics Cards</title>
+
+<para>AMD provides a proprietary driver for its graphics cards that
+has better 3D performance than the X.org drivers.  It is not enabled
+by default because it’s not free software.  You can enable it as follows:
+<programlisting>
+services.xserver.videoDrivers = [ "ati_unfree" ];
+</programlisting>
+You will need to reboot after enabling this driver to prevent a clash
+with other kernel modules.</para>
+
+<para>On 64-bit systems, if you want full acceleration for 32-bit
+programs such as Wine, you should also set the following:
+<programlisting>
+hardware.opengl.driSupport32Bit = true;
+</programlisting>
+</para>
+
+</simplesect>
 
 <simplesect><title>Touchpads</title>
 
diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm
index e2bd3393d872..85c2bfa88e1a 100644
--- a/nixos/lib/test-driver/Machine.pm
+++ b/nixos/lib/test-driver/Machine.pm
@@ -482,7 +482,7 @@ sub screenshot {
     my $name = basename($filename);
     $self->nest("making screenshot ‘$name’", sub {
         $self->sendMonitorCommand("screendump $tmp");
-        system("convert $tmp ${filename}") == 0
+        system("pnmtopng $tmp > ${filename}") == 0
             or die "cannot convert screenshot";
         unlink $tmp;
     }, { image => $name } );
diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix
index 75e9c3977763..73b55ed6c060 100644
--- a/nixos/lib/testing.nix
+++ b/nixos/lib/testing.nix
@@ -27,7 +27,7 @@ rec {
         cp ${./test-driver/Logger.pm} $libDir/Logger.pm
 
         wrapProgram $out/bin/nixos-test-driver \
-          --prefix PATH : "${pkgs.qemu_kvm}/bin:${pkgs.vde2}/bin:${imagemagick}/bin:${coreutils}/bin" \
+          --prefix PATH : "${qemu_kvm}/bin:${vde2}/bin:${netpbm}/bin:${coreutils}/bin" \
           --prefix PERL5LIB : "${lib.makePerlPath [ perlPackages.TermReadLineGnu perlPackages.XMLWriter perlPackages.IOTty ]}:$out/lib/perl5/site_perl"
       '';
   };
@@ -41,7 +41,7 @@ rec {
 
       requiredSystemFeatures = [ "kvm" "nixos-test" ];
 
-      buildInputs = [ pkgs.libxslt ];
+      buildInputs = [ libxslt ];
 
       buildCommand =
         ''
@@ -153,7 +153,7 @@ rec {
         startAll;
         $client->waitForUnit("multi-user.target");
         ${preBuild}
-        $client->succeed("env -i ${pkgs.bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2");
+        $client->succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2");
         ${postBuild}
         $client->succeed("sync"); # flush all data before pulling the plug
       '';
diff --git a/nixos/modules/config/fonts/fontconfig.nix b/nixos/modules/config/fonts/fontconfig.nix
index cf70ca264d6a..7516d7ddf1a6 100644
--- a/nixos/modules/config/fonts/fontconfig.nix
+++ b/nixos/modules/config/fonts/fontconfig.nix
@@ -47,11 +47,6 @@ with lib;
         </fontconfig>
       '';
 
-    # FIXME: This variable is no longer needed, but we'll keep it
-    # around for a while for applications linked against old
-    # fontconfig builds.
-    environment.variables.FONTCONFIG_FILE = "/etc/fonts/fonts.conf";
-
     environment.systemPackages = [ pkgs.fontconfig ];
 
   };
diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix
index 297b3a82d6c1..737f0abc52f0 100644
--- a/nixos/modules/config/pulseaudio.nix
+++ b/nixos/modules/config/pulseaudio.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, pkgs_i686, ... }:
 
 with pkgs;
 with lib;
@@ -10,6 +10,10 @@ let
   systemWide = cfg.enable && cfg.systemWide;
   nonSystemWide = cfg.enable && !cfg.systemWide;
 
+  # Forces 32bit pulseaudio and alsaPlugins to be built/supported for apps
+  # using 32bit alsa on 64bit linux.
+  enable32BitAlsaPlugins = stdenv.isx86_64 && (pkgs_i686.alsaLib != null);
+
   ids = config.ids;
 
   uid = ids.uids.pulseaudio;
@@ -28,21 +32,25 @@ let
   # Write an /etc/asound.conf that causes all ALSA applications to
   # be re-routed to the PulseAudio server through ALSA's Pulse
   # plugin.
-  alsaConf = writeText "asound.conf" ''
+  alsaConf = writeText "asound.conf" (''
     pcm_type.pulse {
-      lib ${alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so
+      libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so ;
+      ${lib.optionalString enable32BitAlsaPlugins
+     "libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_pcm_pulse.so ;"}
     }
     pcm.!default {
       type pulse
       hint.description "Default Audio Device (via PulseAudio)"
     }
     ctl_type.pulse {
-      lib ${alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so
+      libs.native = ${alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;
+      ${lib.optionalString enable32BitAlsaPlugins
+     "libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;"}
     }
     ctl.!default {
       type pulse
     }
-  '';
+  '');
 
 in {
 
@@ -116,7 +124,10 @@ in {
     }
 
     (mkIf cfg.enable {
-      environment.systemPackages = [ cfg.package ];
+      environment.systemPackages = [
+        cfg.package
+        (lib.optional enable32BitAlsaPlugins pkgs_i686.pulseaudio)
+      ];
 
       environment.etc = singleton {
         target = "asound.conf";
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 7d0498c10cc5..0d3273fe0539 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -310,9 +310,9 @@ let
       }) cfg.extraUsers;
     groups = mapAttrsToList (n: g:
       { inherit (g) name gid;
-        members = mapAttrsToList (n: u: u.name) (
+        members = g.members ++ (mapAttrsToList (n: u: u.name) (
           filterAttrs (n: u: elem g.name u.extraGroups) cfg.extraUsers
-        );
+        ));
       }) cfg.extraGroups;
   });
 
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index f894c830eb6c..1777c200dd11 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -46,7 +46,8 @@ in
       description = ''
         On 64-bit systems, whether to support Direct Rendering for
         32-bit applications (such as Wine).  This is currently only
-        supported for the <literal>nvidia</literal> driver and for
+        supported for the <literal>nvidia</literal> and 
+        <literal>ati_unfree</literal> drivers, as well as
         <literal>Mesa</literal>.
       '';
     };
@@ -104,22 +105,9 @@ in
     environment.sessionVariables.LD_LIBRARY_PATH =
       [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ];
 
-    # FIXME: move this into card-specific modules.
-    hardware.opengl.package = mkDefault
-      (if elem "ati_unfree" videoDrivers then
-        kernelPackages.ati_drivers_x11
-      else
-        makePackage pkgs);
-
+    hardware.opengl.package = mkDefault (makePackage pkgs);
     hardware.opengl.package32 = mkDefault (makePackage pkgs_i686);
 
-    boot.extraModulePackages =
-      optional (elem "virtualbox" videoDrivers) kernelPackages.virtualboxGuestAdditions ++
-      optional (elem "ati_unfree" videoDrivers) kernelPackages.ati_drivers_x11;
-
-    environment.etc =
-      optionalAttrs (elem "ati_unfree" videoDrivers) {
-        "ati".source = "${kernelPackages.ati_drivers_x11}/etc/ati";
-      };
+    boot.extraModulePackages = optional (elem "virtualbox" videoDrivers) kernelPackages.virtualboxGuestAdditions;
   };
 }
diff --git a/nixos/modules/hardware/video/ati.nix b/nixos/modules/hardware/video/ati.nix
new file mode 100644
index 000000000000..033e49d2233e
--- /dev/null
+++ b/nixos/modules/hardware/video/ati.nix
@@ -0,0 +1,37 @@
+# This module provides the proprietary ATI X11 / OpenGL drivers.
+
+{ config, lib, pkgs, pkgs_i686, ... }:
+
+with lib;
+
+let
+
+  drivers = config.services.xserver.videoDrivers;
+
+  enabled = elem "ati_unfree" drivers;
+
+  ati_x11 = config.boot.kernelPackages.ati_drivers_x11;
+
+in
+
+{
+
+  config = mkIf enabled {
+
+    services.xserver.drivers = singleton
+      { name = "fglrx"; modules = [ ati_x11 ]; libPath = [ "${ati_x11}/lib" ]; };
+
+    hardware.opengl.package = ati_x11;
+    hardware.opengl.package32 = pkgs_i686.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; };
+
+    environment.systemPackages = [ ati_x11 ];
+
+    boot.extraModulePackages = [ ati_x11 ];
+
+    boot.blacklistedKernelModules = [ "radeon" ];
+
+    environment.etc."ati".source = "${ati_x11}/etc/ati";
+
+  };
+
+}
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index cdce7d1a893e..fa51f831481a 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -82,7 +82,7 @@
       statsd = 69;
       transmission = 70;
       postgres = 71;
-      smbguest = 74;
+      smbguest = 74;  # unused
       varnish = 75;
       datadog = 76;
       lighttpd = 77;
@@ -150,8 +150,10 @@
       zookeeper = 140;
       dnsmasq = 141;
       uhub = 142;
-      yandexdisk=143;
-      collectd=144;
+      yandexdisk = 143;
+      collectd = 144;
+      consul = 145;
+      mailpile = 146;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -220,7 +222,7 @@
       postgres = 71;
       vboxusers = 72;
       vboxsf = 73;
-      smbguest = 74;
+      smbguest = 74;  # unused
       varnish = 75;
       datadog = 76;
       lighttpd = 77;
@@ -272,6 +274,7 @@
       riemann = 137;
       riemanndash = 138;
       uhub = 142;
+      mailpile = 146;
 
       # 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 25827656608d..3db44a4d8de5 100755
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -38,6 +38,7 @@
   ./hardware/pcmcia.nix
   ./hardware/video/bumblebee.nix
   ./hardware/video/nvidia.nix
+  ./hardware/video/ati.nix
   ./installer/tools/nixos-checkout.nix
   ./installer/tools/tools.nix
   ./misc/assertions.nix
@@ -142,6 +143,7 @@
   ./services/hardware/udev.nix
   ./services/hardware/udisks2.nix
   ./services/hardware/upower.nix
+  ./services/hardware/thermald.nix
   ./services/logging/klogd.nix
   ./services/logging/logcheck.nix
   ./services/logging/logrotate.nix
@@ -157,6 +159,7 @@
   ./services/mail/postfix.nix
   ./services/mail/spamassassin.nix
   #./services/misc/autofs.nix
+  ./services/misc/cpuminer-cryptonight.nix
   ./services/misc/cgminer.nix
   ./services/misc/dictd.nix
   ./services/misc/disnix.nix
@@ -211,6 +214,7 @@
   ./services/networking/cjdns.nix
   ./services/networking/cntlm.nix
   ./services/networking/connman.nix
+  ./services/networking/consul.nix
   ./services/networking/ddclient.nix
   ./services/networking/dhcpcd.nix
   ./services/networking/dhcpd.nix
@@ -229,6 +233,7 @@
   ./services/networking/iodined.nix
   ./services/networking/ircd-hybrid/default.nix
   ./services/networking/kippo.nix
+  ./services/networking/mailpile.nix
   ./services/networking/minidlna.nix
   ./services/networking/murmur.nix
   ./services/networking/nat.nix
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index 623a428fc1a6..d79aff5dc553 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -45,7 +45,6 @@ in
         PKG_CONFIG_PATH = [ "/lib/pkgconfig" ];
         TERMINFO_DIRS = [ "/share/terminfo" ];
         PERL5LIB = [ "/lib/perl5/site_perl" ];
-        ALSA_PLUGIN_DIRS = [ "/lib/alsa-lib" ];
         KDEDIRS = [ "" ];
         STRIGI_PLUGIN_PATH = [ "/lib/strigi/" ];
         QT_PLUGIN_PATH = [ "/lib/qt4/plugins" "/lib/kde4/plugins" ];
diff --git a/nixos/modules/programs/uim.nix b/nixos/modules/programs/uim.nix
index 237da3415dc3..fc25ba6f9694 100644
--- a/nixos/modules/programs/uim.nix
+++ b/nixos/modules/programs/uim.nix
@@ -1,6 +1,6 @@
-{ config, pkgs, ... }:
+{ config, pkgs, lib, ... }:
 
-with pkgs.lib;
+with lib;
 
 let
   cfg = config.uim;
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 0ee2caa28ea4..019fbc721b17 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -129,5 +129,6 @@ in zipModules ([]
 ++ obsolete' [ "boot" "loader" "grub" "bootDevice" ]
 ++ obsolete' [ "boot" "initrd" "luks" "enable" ]
 ++ obsolete' [ "programs" "bash" "enable" ]
+++ obsolete' [ "services" "samba" "defaultShare" ]
 
 )
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 53542e34b14b..e6b525c4b1ba 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -16,52 +16,76 @@ let
     sticker_file        "${cfg.dataDir}/sticker.sql"
     log_file            "syslog"
     user                "mpd"
+    ${if cfg.network.host != "any" then
+   "bind_to_address     ${cfg.network.host}" else ""}
+    ${if cfg.network.port != 6600 then
+   "port                ${toString cfg.network.port}" else ""}
     ${cfg.extraConfig}
-  ''; 
+  '';
 
 in {
 
   ###### interface
 
-  options = { 
+  options = {
 
-    services.mpd = { 
+    services.mpd = {
 
       enable = mkOption {
         default = false;
         description = ''
           Whether to enable MPD, the music player daemon.
-        ''; 
-      };  
+        '';
+      };
 
       musicDirectory = mkOption {
         default = "${cfg.dataDir}/music";
         description = ''
           Extra configuration added to the end of MPD's
           configuration file, mpd.conf.
-        ''; 
-      };  
+        '';
+      };
 
       extraConfig = mkOption {
-        default = ""; 
+        default = "";
         description = ''
           Extra directives added to to the end of MPD's configuration file,
           mpd.conf. Basic configuration like file location and uid/gid
           is added automatically to the beginning of the file.
-        ''; 
-      };  
+        '';
+      };
 
       dataDir = mkOption {
         default = "/var/lib/mpd";
         description = ''
           The directory where MPD stores its state, tag cache,
           playlists etc.
-        ''; 
-      };  
-
-    };  
+        '';
+      };
+
+      network = {
+
+        host = mkOption {
+          default = "any";
+          description = ''
+            This setting sets the address for the daemon to listen on. Careful attention
+            should be paid if this is assigned to anything other then the default, any.
+            This setting can deny access to control of the daemon.
+          '';
+        };
+
+        port = mkOption {
+          default = 6600;
+          description = ''
+            This setting is the TCP port that is desired for the daemon to get assigned
+            to.
+          '';
+        };
+
+      };
+    };
 
-  };  
+  };
 
 
   ###### implementation
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 01c55479b2b4..de14c56f7971 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -225,14 +225,14 @@ in
         # Wait for PostgreSQL to be ready to accept connections.
         postStart =
           ''
-            while ! psql postgres -c "" 2> /dev/null; do
+            while ! psql --port=${toString cfg.port} postgres -c "" 2> /dev/null; do
                 if ! kill -0 "$MAINPID"; then exit 1; fi
                 sleep 0.1
             done
 
             if test -e "${cfg.dataDir}/.first_startup"; then
               ${optionalString (cfg.initialScript != null) ''
-                cat "${cfg.initialScript}" | psql postgres
+                cat "${cfg.initialScript}" | psql --port=${toString cfg.port} postgres
               ''}
               rm -f "${cfg.dataDir}/.first_startup"
             fi
diff --git a/nixos/modules/services/misc/cpuminer-cryptonight.nix b/nixos/modules/services/misc/cpuminer-cryptonight.nix
new file mode 100644
index 000000000000..f31526f8d107
--- /dev/null
+++ b/nixos/modules/services/misc/cpuminer-cryptonight.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.cpuminer-cryptonight;
+
+  json = builtins.toJSON (
+    cfg // {
+       enable = null;
+       threads =
+         if cfg.threads == 0 then null else toString cfg.threads;
+    }
+  );
+
+  confFile = builtins.toFile "cpuminer.json" json;
+in
+{
+
+  options = {
+
+    services.cpuminer-cryptonight = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable the cpuminer cryptonight miner.
+        '';
+      };
+      url = mkOption {
+        type = types.string;
+        description = "URL of mining server";
+      };
+      user = mkOption {
+        type = types.string;
+        description = "Username for mining server";
+      };
+      pass = mkOption {
+        type = types.string;
+        default = "x";
+        description = "Password for mining server";
+      };
+      threads = mkOption {
+        type = types.int;
+        default = 0;
+        description = "Number of miner threads, defaults to available processors";
+      };
+    };
+
+  };
+
+  config = mkIf config.services.cpuminer-cryptonight.enable {
+
+    systemd.services.cpuminer-cryptonight = {
+      description = "Cryptonight cpuminer";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.cpuminer-multi}/bin/minerd --syslog --config=${confFile}";
+        User = "nobody";
+      };
+    };
+
+  };
+
+}
\ No newline at end of file
diff --git a/nixos/modules/services/misc/gitolite.nix b/nixos/modules/services/misc/gitolite.nix
index 84435f92c11d..961af48e0f86 100644
--- a/nixos/modules/services/misc/gitolite.nix
+++ b/nixos/modules/services/misc/gitolite.nix
@@ -5,6 +5,7 @@ with lib;
 let
   cfg = config.services.gitolite;
   pubkeyFile = pkgs.writeText "gitolite-admin.pub" cfg.adminPubkey;
+  hooks = lib.concatMapStrings (hook: "${hook} ") cfg.commonHooks;
 in
 {
   options = {
@@ -30,6 +31,14 @@ in
           once, upon the first initialization of the Gitolite user.
         '';
       };
+
+      commonHooks = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          A list of custom git hooks that get copied to <literal>~/.gitolite/hooks/common</literal>.
+        '';
+      };
     };
   };
 
@@ -57,6 +66,10 @@ in
         if [ ! -d repositories ]; then
           gitolite setup -pk ${pubkeyFile}
         fi
+        if [ -n "${hooks}" ]; then
+          cp ${hooks} .gitolite/hooks/common/
+          chmod +x .gitolite/hooks/common/*
+        fi
         gitolite setup # Upgrade if needed
       '';
     };
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 4218b965cd9e..fd1e83d9f3e7 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -6,9 +6,6 @@ let
 
   cfg = config.services.samba;
 
-  user = "smbguest";
-  group = "smbguest";
-
   logDir = "/var/log/samba";
   privateDir = "/var/samba/private";
 
@@ -16,12 +13,6 @@ let
 
   setupScript =
     ''
-      if ! test -d /home/smbd ; then
-        mkdir -p /home/smbd
-        chown ${user} /home/smbd
-        chmod a+rwx /home/smbd
-      fi
-
       if ! test -d /var/samba ; then
         mkdir -p /var/samba/locks /var/samba/cores/nmbd  /var/samba/cores/smbd /var/samba/cores/winbindd
       fi
@@ -37,21 +28,15 @@ let
     '';
 
   configFile = pkgs.writeText "smb.conf"
+    (if cfg.configText != null then cfg.configText else
     ''
       [ global ]
       log file = ${logDir}/log.%m
       private dir = ${privateDir}
       ${optionalString cfg.syncPasswordsByPam "pam password change = true"}
 
-      ${if cfg.defaultShare.enable then ''
-      [default]
-      path = /home/smbd
-      read only = ${if cfg.defaultShare.writeable then "no" else "yes"}
-      guest ok = ${if cfg.defaultShare.guest then "yes" else "no"}
-      ''else ""}
-
       ${cfg.extraConfig}
-    '';
+    '');
 
   # This may include nss_ldap, needed for samba if it has to use ldap.
   nssModulesPath = config.system.nssModules.path;
@@ -149,19 +134,13 @@ in
         ";
       };
 
-      defaultShare = {
-        enable = mkOption {
-          description = "Whether to share /home/smbd as 'default'.";
-          default = false;
-        };
-        writeable = mkOption {
-          description = "Whether to allow write access to default share.";
-          default = false;
-        };
-        guest = mkOption {
-          description = "Whether to allow guest access to default share.";
-          default = true;
-        };
+      configText = mkOption {
+        type = types.nullOr types.lines;
+        default = null;
+        description = "
+          Verbatim contents of smb.conf. If null (default), use the
+          autogenerated file from NixOS instead.
+        ";
       };
 
       securityType = mkOption {
@@ -199,14 +178,6 @@ in
 
       (mkIf config.services.samba.enable {
 
-        users.extraUsers.smbguest = {
-          description = "Samba service user";
-          group = group;
-          uid = config.ids.uids.smbguest;
-        };
-
-        users.extraGroups.smbguest.gid = config.ids.uids.smbguest;
-
         system.nssModules = optional cfg.nsswins samba;
 
         systemd = {
@@ -224,7 +195,7 @@ in
             "samba-setup" = {
               description = "Samba Setup Task";
               script = setupScript;
-              unitConfig.RequiresMountsFor = "/home/smbd /var/samba /var/log/samba";
+              unitConfig.RequiresMountsFor = "/var/samba /var/log/samba";
             };
           };
         };
diff --git a/nixos/modules/services/network-filesystems/yandex-disk.nix b/nixos/modules/services/network-filesystems/yandex-disk.nix
index df9626d17c92..982b6ca5ea7b 100644
--- a/nixos/modules/services/network-filesystems/yandex-disk.nix
+++ b/nixos/modules/services/network-filesystems/yandex-disk.nix
@@ -1,6 +1,6 @@
-{ config, pkgs, ... }:
+{ config, pkgs, lib, ... }:
 
-with pkgs.lib;
+with lib;
 
 let
 
diff --git a/nixos/modules/services/networking/atftpd.nix b/nixos/modules/services/networking/atftpd.nix
index ab9f8650f0f8..47465ba948a9 100644
--- a/nixos/modules/services/networking/atftpd.nix
+++ b/nixos/modules/services/networking/atftpd.nix
@@ -1,8 +1,8 @@
 # NixOS module for atftpd TFTP server
 
-{ config, pkgs, ... }:
+{ config, pkgs, lib, ... }:
 
-with pkgs.lib;
+with lib;
 
 let
 
diff --git a/nixos/modules/services/networking/btsync.nix b/nixos/modules/services/networking/btsync.nix
index 5d0e17c293e3..7ddc9e1045e4 100644
--- a/nixos/modules/services/networking/btsync.nix
+++ b/nixos/modules/services/networking/btsync.nix
@@ -57,7 +57,7 @@ let
     ''
       {
         "device_name":     "${cfg.deviceName}",
-        "storage_path":    "/var/lib/btsync",
+        "storage_path":    "/var/lib/btsync/",
         "listening_port":  ${toString cfg.listeningPort},
         "use_gui":         false,
 
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 0519172db914..7192b8b7a0e0 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -190,7 +190,7 @@ in
         echo '${cjdrouteConf}' | sed \
 	  -e "s/@CJDNS_ADMIN_PASSWORD@/$CJDNS_ADMIN_PASSWORD/g" \
           -e "s/@CJDNS_PRIVATE_KEY@/$CJDNS_PRIVATE_KEY/g" \
-            | ${pkgs.cjdns}/sbin/cjdroute
+            | ${pkgs.cjdns}/bin/cjdroute
       '';
 
       serviceConfig = {
@@ -201,7 +201,7 @@ in
 
     system.activationScripts.cjdns = ''
       grep -q "CJDNS_PRIVATE_KEY=" /etc/cjdns.keys || \
-        echo "CJDNS_PRIVATE_KEY=$(${pkgs.cjdns}/sbin/makekey)" \
+        echo "CJDNS_PRIVATE_KEY=$(${pkgs.cjdns}/bin/makekey)" \
 	  >> /etc/cjdns.keys
 
       grep -q "CJDNS_ADMIN_PASSWORD=" /etc/cjdns.keys || \
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
new file mode 100644
index 000000000000..ebc836814089
--- /dev/null
+++ b/nixos/modules/services/networking/consul.nix
@@ -0,0 +1,166 @@
+{ config, lib, pkgs, utils, ... }:
+
+with lib;
+let
+
+  dataDir = "/var/lib/consul";
+  cfg = config.services.consul;
+
+  configOptions = {
+    data_dir = dataDir;
+    rejoin_after_leave = true;
+  }
+  // (if cfg.webUi then { ui_dir = "${pkgs.consul.ui}"; } else { })
+  // cfg.extraConfig;
+
+  configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ]
+    ++ cfg.extraConfigFiles;
+
+  devices = attrValues (filterAttrs (_: i: i != null) cfg.interface);
+  systemdDevices = flip map devices
+    (i: "sys-subsystem-net-devices-${utils.escapeSystemdPath i}.device");
+in
+{
+  options = {
+
+    services.consul = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enables the consul daemon.
+        '';
+      };
+
+      webUi = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enables the web interface on the consul http port.
+        '';
+      };
+
+      interface = {
+
+        advertise = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          description = ''
+            The name of the interface to pull the advertise_addr from.
+          '';
+        };
+
+        bind = mkOption {
+          type = types.nullOr types.str;
+          default = null;
+          description = ''
+            The name of the interface to pull the bind_addr from.
+          '';
+        };
+
+      };
+
+      forceIpv4 = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether we should force the interfaces to only pull ipv4 addresses.
+        '';
+      };
+
+      dropPrivileges = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether the consul agent should be run as a non-root consul user.
+        '';
+      };
+
+      extraConfig = mkOption {
+        default = { };
+        description = ''
+          Extra configuration options which are serialized to json and added
+          to the config.json file.
+        '';
+      };
+
+      extraConfigFiles = mkOption {
+        default = [ ];
+        type = types.listOf types.str;
+        description = ''
+          Additional configuration files to pass to consul
+          NOTE: These will not trigger the service to be restarted when altered.
+        '';
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers."consul" = {
+      description = "Consul agent daemon user";
+      uid = config.ids.uids.consul;
+    };
+
+    environment = {
+      etc."consul.json".text = builtins.toJSON configOptions;
+      systemPackages = with pkgs; [ consul ];
+    };
+
+    systemd.services.consul = {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ] ++ systemdDevices;
+      bindsTo = systemdDevices;
+      restartTriggers = [ config.environment.etc."consul.json".source ];
+
+      serviceConfig = {
+        ExecStart = "@${pkgs.consul}/bin/consul consul agent"
+          + concatMapStrings (n: " -config-file ${n}") configFiles;
+        ExecStop = "${pkgs.consul}/bin/consul leave";
+        ExecReload = "${pkgs.consul}/bin/consul reload";
+        PermissionsStartOnly = true;
+        User = if cfg.dropPrivileges then "consul" else null;
+      };
+
+      path = with pkgs; [ iproute gnugrep gawk ];
+      preStart = ''
+        mkdir -m 0700 -p ${dataDir}
+        chown -R consul ${dataDir}
+
+        # Determine interface addresses
+        getAddrOnce () {
+          ip addr show dev "$1" \
+            | grep 'inet${optionalString (cfg.forceIpv4) " "}.*scope global' \
+            | awk -F '[ /\t]*' '{print $3}' | head -n 1
+        }
+        getAddr () {
+          ADDR="$(getAddrOnce $1)"
+          LEFT=60 # Die after 1 minute
+          while [ -z "$ADDR" ]; do
+            sleep 1
+            LEFT=$(expr $LEFT - 1)
+            if [ "$LEFT" -eq "0" ]; then
+              echo "Address lookup timed out"
+              exit 1
+            fi
+            ADDR="$(getAddrOnce $1)"
+          done
+          echo "$ADDR"
+        }
+        echo "{" > /etc/consul-addrs.json
+      ''
+      + concatStrings (flip mapAttrsToList cfg.interface (name: i:
+        optionalString (i != null) ''
+          echo "    \"${name}_addr\": \"$(getAddr "${i}")\"," >> /etc/consul-addrs.json
+        ''))
+      + ''
+        echo "    \"\": \"\"" >> /etc/consul-addrs.json
+        echo "}" >> /etc/consul-addrs.json
+      '';
+    };
+
+  };
+}
diff --git a/nixos/modules/services/networking/mailpile.nix b/nixos/modules/services/networking/mailpile.nix
new file mode 100644
index 000000000000..e164d41483c7
--- /dev/null
+++ b/nixos/modules/services/networking/mailpile.nix
@@ -0,0 +1,76 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.mailpile;
+
+  hostname = cfg.hostname;
+  port = cfg.port;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.mailpile = {
+      enable = mkOption {
+        default = false;
+        description = "
+          Whether to enable Mailpile the mail client.
+        ";
+      };
+      hostname = mkOption {
+        default = "localhost";
+        description = "Listen to this hostname or ip.";
+      };
+      port = mkOption {
+        default = "33411";
+        description = "Listen on this port.";
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.services.mailpile.enable {
+
+    users.extraUsers.mailpile =
+      { uid = config.ids.uids.mailpile;
+        description = "Mailpile user";
+        createHome = true;
+        home = "/var/lib/mailpile";
+      };
+
+    users.extraGroups.mailpile =
+      { gid = config.ids.gids.mailpile;
+      };
+
+    systemd.services.mailpile =
+      {
+        description = "Mailpile server.";
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          User = "mailpile";
+          ExecStart = "${pkgs.mailpile}/bin/mailpile --www ${hostname}:${port} --wait";
+          # mixed - first send SIGINT to main process,
+          # then after 2min send SIGKILL to whole group if neccessary
+          KillMode = "mixed";
+          KillSignal = "SIGINT";  # like Ctrl+C - safe mailpile shutdown
+          TimeoutSec = 120;  # wait 2min untill SIGKILL
+        };
+        environment.MAILPILE_HOME = "/var/lib/mailpile/.local/share/Mailpile";
+      };
+
+    environment.systemPackages = [ pkgs.mailpile ];
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index 35e376e7b3a6..bdb79ce2a901 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -13,38 +13,49 @@ let
   dest = if cfg.externalIP == null then "-j MASQUERADE" else "-j SNAT --to-source ${cfg.externalIP}";
 
   flushNat = ''
-    iptables -w -t nat -F PREROUTING
-    iptables -w -t nat -F POSTROUTING
-    iptables -w -t nat -X
+    iptables -w -t nat -D PREROUTING -j nixos-nat-pre 2>/dev/null|| true
+    iptables -w -t nat -F nixos-nat-pre 2>/dev/null || true
+    iptables -w -t nat -X nixos-nat-pre 2>/dev/null || true
+    iptables -w -t nat -D POSTROUTING -j nixos-nat-post 2>/dev/null || true
+    iptables -w -t nat -F nixos-nat-post 2>/dev/null || true
+    iptables -w -t nat -X nixos-nat-post 2>/dev/null || true
   '';
 
   setupNat = ''
+    # Create subchain where we store rules
+    iptables -w -t nat -N nixos-nat-pre
+    iptables -w -t nat -N nixos-nat-post
+
     # We can't match on incoming interface in POSTROUTING, so
     # mark packets coming from the external interfaces.
     ${concatMapStrings (iface: ''
-      iptables -w -t nat -A PREROUTING \
+      iptables -w -t nat -A nixos-nat-pre \
         -i '${iface}' -j MARK --set-mark 1
     '') cfg.internalInterfaces}
 
     # NAT the marked packets.
     ${optionalString (cfg.internalInterfaces != []) ''
-      iptables -w -t nat -A POSTROUTING -m mark --mark 1 \
+      iptables -w -t nat -A nixos-nat-post -m mark --mark 1 \
         -o ${cfg.externalInterface} ${dest}
     ''}
 
     # NAT packets coming from the internal IPs.
     ${concatMapStrings (range: ''
-      iptables -w -t nat -A POSTROUTING \
+      iptables -w -t nat -A nixos-nat-post \
         -s '${range}' -o ${cfg.externalInterface} ${dest}
     '') cfg.internalIPs}
 
     # NAT from external ports to internal ports.
     ${concatMapStrings (fwd: ''
-      iptables -w -t nat -A PREROUTING \
+      iptables -w -t nat -A nixos-nat-pre \
         -i ${cfg.externalInterface} -p tcp \
         --dport ${builtins.toString fwd.sourcePort} \
         -j DNAT --to-destination ${fwd.destination}
     '') cfg.forwardPorts}
+
+    # Append our chains to the nat tables
+    iptables -w -t nat -A PREROUTING -j nixos-nat-pre
+    iptables -w -t nat -A POSTROUTING -j nixos-nat-post
   '';
 
 in
@@ -157,7 +168,7 @@ in
       extraStopCommands = flushNat;
     };
 
-    systemd.services =  mkIf (!config.networking.firewall.enable) { nat = {
+    systemd.services = mkIf (!config.networking.firewall.enable) { nat = {
       description = "Network Address Translation";
       wantedBy = [ "network.target" ];
       after = [ "network-interfaces.target" "systemd-modules-load.service" ];
diff --git a/nixos/modules/services/web-servers/lighttpd/cgit.nix b/nixos/modules/services/web-servers/lighttpd/cgit.nix
index d4663781fd84..34b2fa600ad9 100644
--- a/nixos/modules/services/web-servers/lighttpd/cgit.nix
+++ b/nixos/modules/services/web-servers/lighttpd/cgit.nix
@@ -44,6 +44,9 @@ in
     # make the cgitrc manpage available
     environment.systemPackages = [ pkgs.cgit ];
 
+    # declare module dependencies
+    services.lighttpd.enableModules = [ "mod_cgi" "mod_alias" "mod_setenv" ];
+
     services.lighttpd.extraConfig = ''
       $HTTP["url"] =~ "^/cgit" {
           cgi.assign = (
diff --git a/nixos/modules/services/web-servers/lighttpd/default.nix b/nixos/modules/services/web-servers/lighttpd/default.nix
index fc9487ab4859..06f310eeb933 100644
--- a/nixos/modules/services/web-servers/lighttpd/default.nix
+++ b/nixos/modules/services/web-servers/lighttpd/default.nix
@@ -8,12 +8,54 @@ let
 
   cfg = config.services.lighttpd;
 
-  needModRedirect = cfg.gitweb.enable;
-  needModAlias = cfg.cgit.enable || cfg.gitweb.enable;
-  needModSetenv = cfg.cgit.enable || cfg.gitweb.enable;
-  needModCgi = cfg.cgit.enable || cfg.gitweb.enable;
-  needModStatus = cfg.mod_status;
-  needModUserdir = cfg.mod_userdir;
+  # List of known lighttpd modules, ordered by how the lighttpd documentation
+  # recommends them being imported:
+  # http://redmine.lighttpd.net/projects/1/wiki/Server_modulesDetails
+  #
+  # Some modules are always imported and should not appear in the config:
+  # disallowedModules = [ "mod_indexfile" "mod_dirlisting" "mod_staticfile" ];
+  #
+  # Get full module list: "ls -1 $lighttpd/lib/*.so"
+  allKnownModules = [
+    "mod_rewrite"
+    "mod_redirect"
+    "mod_alias"
+    "mod_access"
+    "mod_auth"
+    "mod_status"
+    "mod_simple_vhost"
+    "mod_evhost"
+    "mod_userdir"
+    "mod_secdownload"
+    "mod_fastcgi"
+    "mod_proxy"
+    "mod_cgi"
+    "mod_ssi"
+    "mod_compress"
+    "mod_usertrack"
+    "mod_expire"
+    "mod_rrdtool"
+    "mod_accesslog"
+    # Remaining list of modules, order assumed to be unimportant.
+    "mod_cml"
+    "mod_dirlisting"
+    "mod_evasive"
+    "mod_extforward"
+    "mod_flv_streaming"
+    "mod_magnet"
+    "mod_mysql_vhost"
+    "mod_rewrite"
+    "mod_scgi"
+    "mod_setenv"
+    "mod_trigger_b4_dl"
+    "mod_webdav"
+  ];
+
+  maybeModuleString = moduleName:
+    if elem moduleName cfg.enableModules then ''"${moduleName}"'' else "";
+
+  modulesIncludeString = concatStringsSep ",\n"
+    (filter (x: x != "") (map maybeModuleString allKnownModules));
 
   configFile = if cfg.configText != "" then
     pkgs.writeText "lighttpd.conf" ''
@@ -38,13 +80,7 @@ let
       # been loaded already. So if two services were to put the same module in
       # server.modules += (), that would break the lighttpd configuration.
       server.modules = (
-          ${optionalString needModRedirect ''"mod_redirect",''}
-          ${optionalString needModAlias ''"mod_alias",''}
-          ${optionalString needModSetenv ''"mod_setenv",''}
-          ${optionalString needModCgi ''"mod_cgi",''}
-          ${optionalString needModStatus ''"mod_status",''}
-          ${optionalString needModUserdir ''"mod_userdir",''}
-          "mod_accesslog"
+          ${modulesIncludeString}
       )
 
       # Logging (logs end up in systemd journal)
@@ -117,6 +153,19 @@ in
         '';
       };
 
+      enableModules = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        example = [ "mod_cgi" "mod_status" ];
+        description = ''
+          List of lighttpd modules to enable. Sub-services take care of
+          enabling modules as needed, so this option is mainly for when you
+          want to add custom stuff to
+          <option>services.lighttpd.extraConfig</option> that depends on a
+          certain module.
+        '';
+      };
+
       mod_status = mkOption {
         default = false;
         type = types.uniq types.bool;
@@ -152,6 +201,26 @@ in
 
   config = mkIf cfg.enable {
 
+    assertions = [
+      { assertion = all (x: elem x allKnownModules) cfg.enableModules;
+        message = ''
+          One (or more) modules in services.lighttpd.enableModules are
+          unrecognized.
+
+          Known modules: ${toString allKnownModules}
+
+          services.lighttpd.enableModules: ${toString cfg.enableModules}
+        '';
+      }
+    ];
+
+    services.lighttpd.enableModules = mkMerge
+      [ (mkIf cfg.mod_status [ "mod_status" ])
+        (mkIf cfg.mod_userdir [ "mod_userdir" ])
+        # always load mod_accesslog so that we can log to the journal
+        [ "mod_accesslog" ]
+      ];
+
     systemd.services.lighttpd = {
       description = "Lighttpd Web Server";
       after = [ "network.target" ];
diff --git a/nixos/modules/services/web-servers/lighttpd/gitweb.nix b/nixos/modules/services/web-servers/lighttpd/gitweb.nix
index c407a1d89778..ef7072ecba3a 100644
--- a/nixos/modules/services/web-servers/lighttpd/gitweb.nix
+++ b/nixos/modules/services/web-servers/lighttpd/gitweb.nix
@@ -44,6 +44,9 @@ in
 
   config = mkIf cfg.enable {
 
+    # declare module dependencies
+    services.lighttpd.enableModules = [ "mod_cgi" "mod_redirect" "mod_alias" "mod_setenv" ];
+
     services.lighttpd.extraConfig = ''
       $HTTP["url"] =~ "^/gitweb" {
           cgi.assign = (
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index ebdb2ad06491..43e04a3076c6 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -18,7 +18,7 @@ in
   # determines the default: later modules (if enabled) are preferred.
   # E.g., if KDE is enabled, it supersedes xterm.
   imports = [
-    ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix
+    ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix ./kde4_next.nix
     ./e17.nix ./e18.nix ./e19.nix ./gnome3.nix ./xbmc.nix
   ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/kde4_next.nix b/nixos/modules/services/x11/desktop-managers/kde4_next.nix
new file mode 100644
index 000000000000..568094358ba0
--- /dev/null
+++ b/nixos/modules/services/x11/desktop-managers/kde4_next.nix
@@ -0,0 +1,163 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  xcfg = config.services.xserver;
+  cfg = xcfg.desktopManager.kde4_next;
+  xorg = pkgs.xorg;
+  kde = pkgs.kde4_next;
+
+  # Disable Nepomuk and Strigi by default.  As of KDE 4.7, they don't
+  # really work very well (e.g. searching files often fails to find
+  # files), segfault sometimes and consume significant resources.
+  # They can be re-enabled in the KDE System Settings under "Desktop
+  # Search".
+  nepomukConfig = pkgs.writeTextFile
+    { name = "nepomuk-config";
+      destination = "/share/config/nepomukserverrc";
+      text =
+        ''
+          [Basic Settings]
+          Start Nepomuk=false
+
+          [Service-nepomukstrigiservice]
+          autostart=false
+        '';
+    };
+
+  phononBackends = {
+    gstreamer = [
+      pkgs.phonon_backend_gstreamer
+      pkgs.gst_all.gstPluginsBase
+      pkgs.gst_all.gstPluginsGood
+      pkgs.gst_all.gstPluginsUgly
+      pkgs.gst_all.gstPluginsBad
+      pkgs.gst_all.gstFfmpeg # for mp3 playback
+      pkgs.gst_all.gstreamer # needed?
+    ];
+
+    vlc = [pkgs.phonon_backend_vlc];
+  };
+
+  phononBackendPackages = flip concatMap cfg.phononBackends
+    (name: attrByPath [name] (throw "unknown phonon backend `${name}'") phononBackends);
+
+in
+
+{
+  options = {
+
+    services.xserver.desktopManager.kde4_next = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable the KDE 4 desktop environment.";
+      };
+
+      phononBackends = mkOption {
+        type = types.listOf types.str;
+        default = ["gstreamer"];
+        example = ["gstreamer" "vlc"];
+        description = "Which phonon multimedia backend kde should use";
+      };
+    };
+
+  };
+
+
+  config = mkIf (xcfg.enable && cfg.enable) {
+
+    # If KDE 4 is enabled, make it the default desktop manager (unless
+    # overridden by the user's configuration).
+    # !!! doesn't work yet ("Multiple definitions. Only one is allowed
+    # for this option.")
+    # services.xserver.desktopManager.default = mkOverride 900 "kde4";
+
+    services.xserver.desktopManager.session = singleton
+      { name = "kde4_next";
+        bgSupport = true;
+        start =
+          ''
+            # The KDE icon cache is supposed to update itself
+            # automatically, but it uses the timestamp on the icon
+            # theme directory as a trigger.  Since in Nix the
+            # timestamp is always the same, this doesn't work.  So as
+            # a workaround, nuke the icon cache on login.  This isn't
+            # perfect, since it may require logging out after
+            # installing new applications to update the cache.
+            # See http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
+            rm -fv $HOME/.kde/cache-*/icon-cache.kcache
+
+            # Qt writes a weird ‘libraryPath’ line to
+            # ~/.config/Trolltech.conf that causes the KDE plugin
+            # paths of previous KDE invocations to be searched.
+            # Obviously using mismatching KDE libraries is potentially
+            # disastrous, so here we nuke references to the Nix store
+            # in Trolltech.conf.  A better solution would be to stop
+            # Qt from doing this wackiness in the first place.
+            if [ -e $HOME/.config/Trolltech.conf ]; then
+                sed -e '/nix\\store\|nix\/store/ d' -i $HOME/.config/Trolltech.conf
+            fi
+
+            # Start KDE.
+            exec ${kde.kdebase_workspace}/bin/startkde
+          '';
+      };
+
+    security.setuidOwners = singleton
+      { program = "kcheckpass";
+        source = "${kde.kdebase_workspace}/lib/kde4/libexec/kcheckpass";
+        owner = "root";
+        group = "root";
+        setuid = true;
+      };
+
+    environment.systemPackages =
+        [ kde.kdelibs
+
+          kde.kde_baseapps # Splitted kdebase
+          kde.kde_workspace
+          kde.kde_runtime
+          kde.konsole
+          kde.kate
+
+          kde.kde_wallpapers # contains kdm's default background
+          kde.oxygen_icons
+          pkgs.virtuoso # to enable Nepomuk to find Virtuoso
+
+          # Starts KDE's Polkit authentication agent.
+          kde.polkit_kde_agent
+
+          # Miscellaneous runtime dependencies.
+          kde.qt4 # needed for qdbus
+          pkgs.shared_mime_info
+          xorg.xmessage # so that startkde can show error messages
+          xorg.xset # used by startkde, non-essential
+          xorg.xauth # used by kdesu
+          pkgs.shared_desktop_ontologies # used by nepomuk
+          pkgs.strigi # used by nepomuk
+          pkgs.mysql # used by akonadi
+        ]
+      ++ lib.optional config.hardware.pulseaudio.enable kde.kmix  # Perhaps this should always be enabled
+      ++ lib.optional config.hardware.bluetooth.enable kde.bluedevil
+      ++ lib.optional config.networking.networkmanager.enable kde.networkmanagement
+      ++ [ nepomukConfig ] ++ phononBackendPackages;
+
+    environment.pathsToLink = [ "/share" ];
+
+    environment.etc = singleton
+      { source = "${pkgs.xkeyboard_config}/etc/X11/xkb";
+        target = "X11/xkb";
+      };
+
+    # Enable helpful DBus services.
+    services.udisks2.enable = true;
+    services.upower.enable = config.powerManagement.enable;
+
+    security.pam.services.kde = { allowNullPassword = true; };
+
+  };
+
+}
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index f8ce06738fee..98e3fd6d6a5d 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -28,11 +28,10 @@ let
     buildCommand = ''
       mkdir -p $out/gtk-3.0/
 
-      # This wrapper ensures that we actually get fonts
+      # This wrapper ensures that we actually get ?? (fonts should be OK now)
       makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \
         $out/greeter \
         --set XDG_DATA_DIRS ${pkgs.gnome2.gnome_icon_theme}/share \
-        --set FONTCONFIG_FILE /etc/fonts/fonts.conf \
         --set XDG_CONFIG_HOME $out/
 
       # We need this to ensure that it actually tries to find icons from gnome-icon-theme
diff --git a/nixos/modules/services/x11/window-managers/afterstep.nix b/nixos/modules/services/x11/window-managers/afterstep.nix
new file mode 100644
index 000000000000..395dabb86b5e
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/afterstep.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.afterstep;
+in
+{
+  ###### interface
+  options = {
+    services.xserver.windowManager.afterstep.enable = mkOption {
+      default = false;
+      description = "Enable the Afterstep window manager.";
+    };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "afterstep";
+      start = ''
+        ${pkgs.afterstep}/bin/afterstep &
+        waitPID=$!
+      '';
+    };
+    environment.systemPackages = [ pkgs.afterstep ];
+  };
+}
diff --git a/nixos/modules/services/x11/window-managers/ratpoison.nix b/nixos/modules/services/x11/window-managers/ratpoison.nix
new file mode 100644
index 000000000000..c203c35cd1b7
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/ratpoison.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.ratpoison;
+in
+{
+  ###### interface
+  options = {
+    services.xserver.windowManager.ratpoison.enable = mkOption {
+      default = false;
+      description = "Enable the Ratpoison window manager.";
+    };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "ratpoison";
+      start = ''
+        ${pkgs.ratpoison}/bin/ratpoison &
+        waitPID=$!
+      '';
+    };
+    environment.systemPackages = [ pkgs.ratpoison ];
+  };
+}
diff --git a/nixos/modules/services/x11/window-managers/windowmaker.nix b/nixos/modules/services/x11/window-managers/windowmaker.nix
new file mode 100644
index 000000000000..27cedb7da0ca
--- /dev/null
+++ b/nixos/modules/services/x11/window-managers/windowmaker.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.xserver.windowManager.windowmaker;
+in
+{
+  ###### interface
+  options = {
+    services.xserver.windowManager.windowmaker.enable = mkOption {
+      default = false;
+      description = "Enable the Windowmaker window manager.";
+    };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    services.xserver.windowManager.session = singleton {
+      name = "windowmaker";
+      start = ''
+        ${pkgs.windowmaker}/bin/wmaker &
+        waitPID=$!
+      '';
+    };
+    environment.systemPackages = [ pkgs.windowmaker ];
+  };
+}
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 21eaf6bb6b76..f911d3c81f90 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -13,7 +13,6 @@ let
 
   # Map video driver names to driver packages. FIXME: move into card-specific modules.
   knownVideoDrivers = {
-    ati_unfree   = { modules = [ kernelPackages.ati_drivers_x11 ]; driverName = "fglrx"; };
     nouveau       = { modules = [ pkgs.xf86_video_nouveau ]; };
     unichrome    = { modules = [ pkgs.xorgVideoUnichrome ]; };
     virtualbox   = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; };
@@ -400,8 +399,8 @@ in
     services.xserver.drivers = flip concatMap cfg.videoDrivers (name:
       let driver =
         attrByPath [name]
-          (if (hasAttr ("xf86video" + name) xorg)
-           then { modules = [(getAttr ("xf86video" + name) xorg) ]; }
+          (if xorg ? ${"xf86video" + name}
+           then { modules = [xorg.${"xf86video" + name}]; }
            else null)
           knownVideoDrivers;
       in optional (driver != null) ({ inherit name; driverName = name; } // driver));
@@ -444,8 +443,7 @@ in
         pkgs.xterm
         pkgs.xdg_utils
       ]
-      ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh
-      ++ optional (elem "ati_unfree" cfg.videoDrivers) kernelPackages.ati_drivers_x11;
+      ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh;
 
     environment.pathsToLink =
       [ "/etc/xdg" "/share/xdg" "/share/applications" "/share/icons" "/share/pixmaps" ];
@@ -460,13 +458,11 @@ in
         restartIfChanged = false;
 
         environment =
-          { FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup
+          {
             XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension.
             XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime.
             LD_LIBRARY_PATH = concatStringsSep ":" (
               [ "${xorg.libX11}/lib" "${xorg.libXext}/lib" ]
-              ++ optionals (elem "ati_unfree" cfg.videoDrivers)
-                [ "${kernelPackages.ati_drivers_x11}/lib" "${kernelPackages.ati_drivers_x11}/X11R6/lib64/modules/linux" ]
               ++ concatLists (catAttrs "libPath" cfg.drivers));
           } // cfg.displayManager.job.environment;
 
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index c46b3ba705ad..3ea00e40c3b3 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -234,6 +234,15 @@ in
         '';
       };
 
+      enableCryptodisk = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Enable support for encrypted partitions. Grub should automatically
+          unlock the correct encrypted partition and look for filesystems.
+        '';
+      };
+
     };
 
   };
@@ -261,6 +270,7 @@ in
           throw "You must set the option ‘boot.loader.grub.device’ to make the system bootable."
         else
           "PERL5LIB=${makePerlPath (with pkgs.perlPackages; [ FileSlurp XMLLibXML XMLSAX ])} " +
+          (if cfg.enableCryptodisk then "GRUB_ENABLE_CRYPTODISK=y " else "") +
           "${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig}";
 
       system.build.grub = grub;
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index eef81d81484e..981b60c004c2 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -199,7 +199,10 @@ sub GrubFs {
     return Grub->new(path => $path, search => $search);
 }
 my $grubBoot = GrubFs("/boot");
-my $grubStore = GrubFs("/nix/store");
+my $grubStore;
+if ($copyKernels == 0) {
+    $grubStore = GrubFs("/nix/store");
+}
 
 # Generate the header.
 my $conf .= "# Automatically generated.  DO NOT EDIT THIS FILE!\n";
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 73fc6ce543cf..f14f105ef239 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -168,9 +168,24 @@ if test -e /sys/power/tuxonice/resume; then
     fi
 fi
 
-if test -n "@resumeDevice@" -a -e /sys/power/resume -a -e /sys/power/disk; then
-    echo "@resumeDevice@" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
-    echo shutdown > /sys/power/disk
+if test -e /sys/power/resume -a -e /sys/power/disk; then
+    if test -n "@resumeDevice@"; then
+        resumeDev="@resumeDevice@"
+    else
+        for sd in @resumeDevices@; do
+            # Try to detect resume device. According to Ubuntu bug:
+            # https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1
+            # When there are multiple swap devices, we can't know where will hibernate
+            # image reside. We can check all of them for swsuspend blkid.
+            if [ "$(udevadm info -q property "$sd" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then
+                resumeDev="$sd"
+                break
+            fi
+        done
+    fi
+    if test -n "$resumeDev"; then
+        echo "$resumeDev" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
+    fi
 fi
 
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 6977880fa284..1ec11e70e845 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -181,6 +181,9 @@ let
     inherit (config.boot.initrd) checkJournalingFS
       preLVMCommands postDeviceCommands postMountCommands kernelModules;
 
+    resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}")
+                    (filter (sd: sd ? label || hasPrefix "/dev/" sd.device) config.swapDevices);
+
     fsInfo =
       let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType fs.options ];
       in pkgs.writeText "initrd-fsinfo" (concatStringsSep "\n" (concatMap f fileSystems));
@@ -220,13 +223,14 @@ in
   options = {
 
     boot.resumeDevice = mkOption {
-      type = types.nullOr types.str;
-      default = null;
-      example = "8:2";
+      type = types.str;
+      default = "";
+      example = "/dev/sda3";
       description = ''
-        Device for manual resume attempt during boot, specified using
-        the device's major and minor number as
-        <literal><replaceable>major</replaceable>:<replaceable>minor</replaceable></literal>.
+        Device for manual resume attempt during boot. This should be used primarily
+        if you want to resume from file. Specify here the device where the file
+        resides. You should also use <varname>boot.kernelParams</varname> to specify
+        <literal><replaceable>resume_offset</replaceable></literal>.
       '';
     };
 
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 48c3564ba078..07f3cb9e952c 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -6,8 +6,8 @@ let
 
   checkService = v:
     let assertValueOneOf = name: values: attr:
-          let val = getAttr name attr;
-          in optional ( hasAttr name attr && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
+          let val = attr.${name};
+          in optional (attr ? ${name} && !elem val values) "Systemd service field `${name}' cannot have value `${val}'.";
         checkType = assertValueOneOf "Type" ["simple" "forking" "oneshot" "dbus" "notify" "idle"];
         checkRestart = assertValueOneOf "Restart" ["no" "on-success" "on-failure" "on-abort" "always"];
         errors = concatMap (c: c v) [checkType checkRestart];
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 13d6c6d7990a..e39f71cb7f7c 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -322,7 +322,7 @@ let
           [Service]
           ${let env = cfg.globalEnvironment // def.environment;
             in concatMapStrings (n:
-              let s = "Environment=\"${n}=${getAttr n env}\"\n";
+              let s = "Environment=\"${n}=${env.${n}}\"\n";
               in if stringLength s >= 2048 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env)}
           ${if def.reloadIfChanged then ''
             X-ReloadIfChanged=true
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 97b37b0714cd..6f6000cf3397 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -345,10 +345,20 @@ in
 
         interfaces = mkOption {
           example = [ "enp4s0f0" "enp4s0f1" "wlan0" ];
-          type = types.listOf types.string;
+          type = types.listOf types.str;
           description = "The interfaces to bond together";
         };
 
+        lacp_rate = mkOption {
+          default = null;
+          example = "fast";
+          type = types.nullOr types.str;
+          description = ''
+            Option specifying the rate in which we'll ask our link partner
+            to transmit LACPDU packets in 802.3ad mode.
+          '';
+        };
+
         miimon = mkOption {
           default = null;
           example = 100;
@@ -364,7 +374,7 @@ in
         mode = mkOption {
           default = null;
           example = "active-backup";
-          type = types.nullOr types.string;
+          type = types.nullOr types.str;
           description = ''
             The mode which the bond will be running. The default mode for
             the bonding driver is balance-rr, optimizing for throughput.
@@ -373,6 +383,16 @@ in
           '';
         };
 
+        xmit_hash_policy = mkOption {
+          default = null;
+          example = "layer2+3";
+          type = types.nullOr types.str;
+          description = ''
+            Selects the transmit hash policy to use for slave selection in
+            balance-xor, 802.3ad, and tlb modes.
+          '';
+        };
+
       };
     };
 
@@ -758,9 +778,11 @@ in
             path = [ pkgs.ifenslave pkgs.iproute ];
             script = ''
               # Remove Dead Interfaces
-              ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
+              ip link set "${n}" down >/dev/null 2>&1 || true
+              ifenslave -d "${n}" >/dev/null 2>&1 || true
+              ip link del "${n}" >/dev/null 2>&1 || true
 
-              ip link add "${n}" type bond
+              ip link add name "${n}" type bond
 
               # !!! There must be a better way to wait for the interface
               while [ ! -d /sys/class/net/${n} ]; do sleep 0.1; done;
@@ -770,17 +792,21 @@ in
                 "echo ${toString v.miimon} > /sys/class/net/${n}/bonding/miimon"}
               ${optionalString (v.mode != null)
                 "echo \"${v.mode}\" > /sys/class/net/${n}/bonding/mode"}
+              ${optionalString (v.lacp_rate != null)
+                "echo \"${v.lacp_rate}\" > /sys/class/net/${n}/bonding/lacp_rate"}
+              ${optionalString (v.xmit_hash_policy != null)
+                "echo \"${v.xmit_hash_policy}\" > /sys/class/net/${n}/bonding/xmit_hash_policy"}
 
-              # Bring up the bridge and enslave the specified interfaces
+              # Bring up the bond and enslave the specified interfaces
               ip link set "${n}" up
               ${flip concatMapStrings v.interfaces (i: ''
                 ifenslave "${n}" "${i}"
               '')}
             '';
             postStop = ''
-              ip link set "${n}" down
-              ifenslave -d "${n}"
-              ip link delete "${n}"
+              ip link set "${n}" down >dev/null 2>&1 || true
+              ifenslave -d "${n}" >/dev/null 2>&1 || true
+              ip link del "${n}" >/dev/null 2>&1 || true
             '';
           });
 
@@ -798,7 +824,7 @@ in
             script = ''
               # Remove Dead Interfaces
               ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
-              ip link add "${n}" type sit \
+              ip link add name "${n}" type sit \
                 ${optionalString (v.remote != null) "remote \"${v.remote}\""} \
                 ${optionalString (v.local != null) "local \"${v.local}\""} \
                 ${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \
@@ -824,7 +850,7 @@ in
             script = ''
               # Remove Dead Interfaces
               ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
-              ip link add link "${v.interface}" "${n}" type vlan id "${toString v.id}"
+              ip link add link "${v.interface}" name "${n}" type vlan id "${toString v.id}"
               ip link set "${n}" up
             '';
             postStop = ''
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index 3a458f5e860b..ca7ca2afb65f 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -1,3 +1,7 @@
+# This jobset defines the main NixOS channels (such as nixos-unstable
+# and nixos-14.04). The channel is updated every time the ‘tested’ job
+# succeeds, and all other jobs have finished (they may fail).
+
 { nixpkgs ? { outPath = ./..; revCount = 56789; shortRev = "gfedcba"; }
 , stableBranch ? false
 , supportedSystems ? [ "x86_64-linux" "i686-linux" ]
@@ -18,7 +22,7 @@ let
 in rec {
 
   nixos = removeMaintainers (import ./release.nix {
-    inherit stableBranch;
+    inherit stableBranch supportedSystems;
     nixpkgs = nixpkgsSrc;
   });
 
@@ -30,12 +34,13 @@ in rec {
   tested = pkgs.releaseTools.aggregate {
     name = "nixos-${nixos.channel.version}";
     meta = {
-      description = "Release-critical builds for the NixOS unstable channel";
-      maintainers = [ pkgs.lib.maintainers.eelco pkgs.lib.maintainers.shlevy ];
+      description = "Release-critical builds for the NixOS channel";
+      maintainers = [ pkgs.lib.maintainers.eelco ];
     };
     constituents =
-      let all = x: map (p: x.${p}) supportedSystems; in
+      let all = x: map (system: x.${system}) supportedSystems; in
       [ nixos.channel
+        (all nixos.dummy)
         (all nixos.manual)
 
         (all nixos.iso_minimal)
@@ -61,7 +66,8 @@ in rec {
         (all nixos.tests.kde4)
         (all nixos.tests.login)
         (all nixos.tests.misc)
-        (all nixos.tests.nat)
+        (all nixos.tests.nat.firewall)
+        (all nixos.tests.nat.standalone)
         (all nixos.tests.nfs3)
         (all nixos.tests.openssh)
         (all nixos.tests.printing)
diff --git a/nixos/release.nix b/nixos/release.nix
index b3039afb18c1..7337ad7e3f45 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -11,7 +11,7 @@ let
 
   forAllSystems = pkgs.lib.genAttrs supportedSystems;
 
-  scrubDrv = drv: let res = { inherit (drv) drvPath outPath type name; outputName = "out"; out = res; }; in res;
+  scrubDrv = drv: let res = { inherit (drv) drvPath outPath type name system meta; outputName = "out"; out = res; }; in res;
 
   callTest = fn: args: forAllSystems (system: scrubDrv (import fn ({ inherit system; } // args)));
 
@@ -186,6 +186,16 @@ in rec {
   );
 
 
+  # Ensure that all packages used by the minimal NixOS config end up in the channel.
+  dummy = forAllSystems (system: pkgs.runCommand "dummy"
+    { propagatedBuildInputs = (import lib/eval-config.nix {
+        inherit system;
+        modules = lib.singleton ({ config, pkgs, ... }: { });
+      }).config.environment.systemPackages;
+    }
+    "mkdir $out; fixupPhase");
+
+
   # Provide a tarball that can be unpacked into an SD card, and easily
   # boot that system from uboot (like for the sheevaplug).
   # The pc variant helps preparing the expression for the system tarball
@@ -244,7 +254,8 @@ in rec {
   tests.munin = callTest tests/munin.nix {};
   tests.mysql = callTest tests/mysql.nix {};
   tests.mysqlReplication = callTest tests/mysql-replication.nix {};
-  tests.nat = callTest tests/nat.nix {};
+  tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; };
+  tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; };
   tests.nfs3 = callTest tests/nfs.nix { version = 3; };
   tests.nsd = callTest tests/nsd.nix {};
   tests.openssh = callTest tests/openssh.nix {};
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 3e29bc2a45b0..138a81ad8075 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -6,13 +6,13 @@ with pkgs.lib;
 
 let
 
-  # Build the ISO.  This is the regular installation CD but with test
-  # instrumentation.
+  # Build the ISO.  This is the regular minimal installation CD but
+  # with test instrumentation.
   iso =
     (import ../lib/eval-config.nix {
       inherit system;
       modules =
-        [ ../modules/installer/cd-dvd/installation-cd-graphical.nix
+        [ ../modules/installer/cd-dvd/installation-cd-minimal.nix
           ../modules/testing/test-instrumentation.nix
           { key = "serial";
             boot.loader.grub.timeout = mkOverride 0 0;
@@ -43,6 +43,7 @@ let
       { imports =
           [ ./hardware-configuration.nix
             <nixpkgs/nixos/modules/testing/test-instrumentation.nix>
+            <nixpkgs/nixos/modules/profiles/minimal.nix>
           ];
 
         ${if useEFI then ''
diff --git a/nixos/tests/jenkins.nix b/nixos/tests/jenkins.nix
index f0d3139d902c..3f4a197ebcc4 100644
--- a/nixos/tests/jenkins.nix
+++ b/nixos/tests/jenkins.nix
@@ -17,7 +17,7 @@ import ./make-test.nix {
 
         users.extraUsers.jenkins.extraGroups = [ "users" ];
 
-        systemd.services.jenkins.unitConfig.TimeoutSec = 240;
+        systemd.services.jenkins.serviceConfig.TimeoutStartSec = "3min";
       };
 
     slave =
diff --git a/nixos/tests/kde4.nix b/nixos/tests/kde4.nix
index 90c37397821e..fcc5101feb3d 100644
--- a/nixos/tests/kde4.nix
+++ b/nixos/tests/kde4.nix
@@ -32,7 +32,7 @@ import ./make-test.nix ({ pkgs, ... }: {
           pkgs.kde4.kdegraphics
           pkgs.kde4.kdeutils
           pkgs.kde4.kdegames
-          pkgs.kde4.kdeedu
+          #pkgs.kde4.kdeedu
           pkgs.kde4.kdeaccessibility
           pkgs.kde4.kdeadmin
           pkgs.kde4.kdenetwork
diff --git a/nixos/tests/munin.nix b/nixos/tests/munin.nix
index d18abd68ee0e..1e51453df83b 100644
--- a/nixos/tests/munin.nix
+++ b/nixos/tests/munin.nix
@@ -18,7 +18,7 @@ import ./make-test.nix {
              '';
            };
           };
-          systemd.services.munin-node.unitConfig.TimeoutSec = 240;
+          systemd.services.munin-node.serviceConfig.TimeoutStartSec = "3min";
         };
     };
 
diff --git a/nixos/tests/nat.nix b/nixos/tests/nat.nix
index 87ed974edad3..c4d2614f7852 100644
--- a/nixos/tests/nat.nix
+++ b/nixos/tests/nat.nix
@@ -3,77 +3,81 @@
 # client on the inside network, a server on the outside network, and a
 # router connected to both that performs Network Address Translation
 # for the client.
+import ./make-test.nix ({ withFirewall, ... }:
+  let
+    unit = if withFirewall then "firewall" else "nat";
+  in
+  {
+    name = "nat${if withFirewall then "WithFirewall" else "Standalone"}";
 
-import ./make-test.nix {
-  name = "nat";
+    nodes =
+      { client =
+          { config, pkgs, nodes, ... }:
+          { virtualisation.vlans = [ 1 ];
+            networking.firewall.allowPing = true;
+            networking.defaultGateway =
+              (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address;
+          };
 
-  nodes =
-    { client =
-        { config, pkgs, nodes, ... }:
-        { virtualisation.vlans = [ 1 ];
-          networking.firewall.allowPing = true;
-          networking.defaultGateway =
-            (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address;
-        };
+        router =
+          { config, pkgs, ... }:
+          { virtualisation.vlans = [ 2 1 ];
+            networking.firewall.enable = withFirewall;
+            networking.firewall.allowPing = true;
+            networking.nat.enable = true;
+            networking.nat.internalIPs = [ "192.168.1.0/24" ];
+            networking.nat.externalInterface = "eth1";
+          };
 
-      router =
-        { config, pkgs, ... }:
-        { virtualisation.vlans = [ 2 1 ];
-          networking.firewall.allowPing = true;
-          networking.nat.enable = true;
-          networking.nat.internalIPs = [ "192.168.1.0/24" ];
-          networking.nat.externalInterface = "eth1";
-        };
+        server =
+          { config, pkgs, ... }:
+          { virtualisation.vlans = [ 2 ];
+            networking.firewall.enable = false;
+            services.httpd.enable = true;
+            services.httpd.adminAddr = "foo@example.org";
+            services.vsftpd.enable = true;
+            services.vsftpd.anonymousUser = true;
+          };
+      };
 
-      server =
-        { config, pkgs, ... }:
-        { virtualisation.vlans = [ 2 ];
-          networking.firewall.enable = false;
-          services.httpd.enable = true;
-          services.httpd.adminAddr = "foo@example.org";
-          services.vsftpd.enable = true;
-          services.vsftpd.anonymousUser = true;
-        };
-    };
+    testScript =
+      { nodes, ... }:
+      ''
+        startAll;
 
-  testScript =
-    { nodes, ... }:
-    ''
-      startAll;
+        # The router should have access to the server.
+        $server->waitForUnit("network.target");
+        $server->waitForUnit("httpd");
+        $router->waitForUnit("network.target");
+        $router->succeed("curl --fail http://server/ >&2");
 
-      # The router should have access to the server.
-      $server->waitForUnit("network.target");
-      $server->waitForUnit("httpd");
-      $router->waitForUnit("network.target");
-      $router->succeed("curl --fail http://server/ >&2");
+        # The client should be also able to connect via the NAT router.
+        $router->waitForUnit("${unit}");
+        $client->waitForUnit("network.target");
+        $client->succeed("curl --fail http://server/ >&2");
+        $client->succeed("ping -c 1 server >&2");
 
-      # The client should be also able to connect via the NAT router.
-      $router->waitForUnit("nat");
-      $client->waitForUnit("network.target");
-      $client->succeed("curl --fail http://server/ >&2");
-      $client->succeed("ping -c 1 server >&2");
+        # Test whether passive FTP works.
+        $server->waitForUnit("vsftpd");
+        $server->succeed("echo Hello World > /home/ftp/foo.txt");
+        $client->succeed("curl -v ftp://server/foo.txt >&2");
 
-      # Test whether passive FTP works.
-      $server->waitForUnit("vsftpd");
-      $server->succeed("echo Hello World > /home/ftp/foo.txt");
-      $client->succeed("curl -v ftp://server/foo.txt >&2");
+        # Test whether active FTP works.
+        $client->succeed("curl -v -P - ftp://server/foo.txt >&2");
 
-      # Test whether active FTP works.
-      $client->succeed("curl -v -P - ftp://server/foo.txt >&2");
+        # Test ICMP.
+        $client->succeed("ping -c 1 router >&2");
+        $router->succeed("ping -c 1 client >&2");
 
-      # Test ICMP.
-      $client->succeed("ping -c 1 router >&2");
-      $router->succeed("ping -c 1 client >&2");
+        # If we turn off NAT, the client shouldn't be able to reach the server.
+        $router->succeed("iptables -t nat -D PREROUTING -j nixos-nat-pre");
+        $router->succeed("iptables -t nat -D POSTROUTING -j nixos-nat-post");
+        $client->fail("curl --fail --connect-timeout 5 http://server/ >&2");
+        $client->fail("ping -c 1 server >&2");
 
-      # If we turn off NAT, the client shouldn't be able to reach the server.
-      $router->stopJob("nat");
-      $client->fail("curl --fail --connect-timeout 5 http://server/ >&2");
-      $client->fail("ping -c 1 server >&2");
-
-      # And make sure that restarting the NAT job works.
-      $router->succeed("systemctl start nat");
-      $client->succeed("curl --fail http://server/ >&2");
-      $client->succeed("ping -c 1 server >&2");
-    '';
-
-}
+        # And make sure that reloading the NAT job works.
+        $router->succeed("systemctl restart ${unit}");
+        $client->succeed("curl --fail http://server/ >&2");
+        $client->succeed("ping -c 1 server >&2");
+      '';
+  })