summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/x-windows.xml6
-rw-r--r--nixos/doc/manual/installation/upgrading.xml26
-rw-r--r--nixos/doc/manual/release-notes/release-notes.xml1
-rw-r--r--nixos/doc/manual/release-notes/rl-unstable.xml27
-rw-r--r--nixos/lib/eval-config.nix5
-rw-r--r--nixos/modules/config/i18n.nix16
-rw-r--r--nixos/modules/config/system-path.nix9
-rw-r--r--nixos/modules/config/users-groups.nix53
-rw-r--r--nixos/modules/misc/extra-arguments.nix5
-rw-r--r--nixos/modules/misc/ids.nix6
-rw-r--r--nixos/modules/misc/version.nix2
-rw-r--r--nixos/modules/module-list.nix3
-rw-r--r--nixos/modules/programs/cdemu.nix17
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.nix4
-rw-r--r--nixos/modules/programs/command-not-found/command-not-found.pl6
-rw-r--r--nixos/modules/rename.nix3
-rw-r--r--nixos/modules/security/prey.nix17
-rw-r--r--nixos/modules/services/backup/bacula.nix15
-rw-r--r--nixos/modules/services/backup/sitecopy-backup.nix12
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix8
-rw-r--r--nixos/modules/services/databases/mysql.nix6
-rw-r--r--nixos/modules/services/hardware/brltty.nix28
-rw-r--r--nixos/modules/services/hardware/freefall.nix56
-rw-r--r--nixos/modules/services/hardware/udev.nix4
-rw-r--r--nixos/modules/services/logging/logstash.nix1
-rw-r--r--nixos/modules/services/mail/mlmmj.nix16
-rw-r--r--nixos/modules/services/misc/gitit.nix47
-rw-r--r--nixos/modules/services/misc/nix-gc.nix2
-rw-r--r--nixos/modules/services/monitoring/bosun.nix3
-rw-r--r--nixos/modules/services/monitoring/grafana.nix2
-rw-r--r--nixos/modules/services/network-filesystems/nfsd.nix5
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix4
-rw-r--r--nixos/modules/services/networking/bitlbee.nix20
-rw-r--r--nixos/modules/services/networking/connman.nix24
-rw-r--r--nixos/modules/services/networking/dnschain.nix110
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix2
-rw-r--r--nixos/modules/services/networking/namecoind.nix150
-rw-r--r--nixos/modules/services/networking/ntpd.nix12
-rw-r--r--nixos/modules/services/networking/openvpn.nix6
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix2
-rw-r--r--nixos/modules/services/networking/syncthing.nix12
-rw-r--r--nixos/modules/services/search/elasticsearch.nix10
-rw-r--r--nixos/modules/services/torrent/deluge.nix2
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/wordpress.nix21
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/kodi.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix10
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix31
-rw-r--r--nixos/modules/services/x11/redshift.nix73
-rw-r--r--nixos/modules/services/x11/window-managers/wmii.nix28
-rw-r--r--nixos/modules/services/x11/xserver.nix1
-rw-r--r--nixos/modules/system/boot/modprobe.nix6
-rw-r--r--nixos/modules/system/boot/stage-1.nix3
-rw-r--r--nixos/modules/system/boot/systemd.nix4
-rw-r--r--nixos/modules/virtualisation/containers.nix8
-rw-r--r--nixos/modules/virtualisation/docker.nix15
-rw-r--r--nixos/modules/virtualisation/lxd.nix64
-rw-r--r--nixos/modules/virtualisation/nixos-container-completion.sh33
-rw-r--r--nixos/modules/virtualisation/nixos-container.pl3
-rw-r--r--nixos/modules/virtualisation/parallels-guest.nix2
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix5
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/chromium.nix6
-rw-r--r--nixos/tests/docker.nix1
-rw-r--r--nixos/tests/etcd.nix6
-rw-r--r--nixos/tests/gnome3-gdm.nix39
-rw-r--r--nixos/tests/gnome3.nix11
-rw-r--r--nixos/tests/logstash.nix4
-rw-r--r--nixos/tests/nfs.nix2
-rw-r--r--nixos/tests/proxy.nix1
-rw-r--r--nixos/tests/virtualbox.nix119
72 files changed, 1005 insertions, 263 deletions
diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml
index 95e66f0c70c0..7f43acab2c38 100644
--- a/nixos/doc/manual/configuration/x-windows.xml
+++ b/nixos/doc/manual/configuration/x-windows.xml
@@ -61,6 +61,12 @@ by default because it’s not free software.  You can enable it as follows:
 <programlisting>
 services.xserver.videoDrivers = [ "nvidia" ];
 </programlisting>
+Or if you have an older card, you may have to use one of the legacy drivers:
+<programlisting>
+services.xserver.videoDrivers = [ "nvidiaLegacy340" ];
+services.xserver.videoDrivers = [ "nvidiaLegacy304" ];
+services.xserver.videoDrivers = [ "nvidiaLegacy173" ];
+</programlisting>
 You may need to reboot after enabling this driver to prevent a clash
 with other kernel modules.</para>
 
diff --git a/nixos/doc/manual/installation/upgrading.xml b/nixos/doc/manual/installation/upgrading.xml
index 5a9d1f24f7c7..c4812cc637c3 100644
--- a/nixos/doc/manual/installation/upgrading.xml
+++ b/nixos/doc/manual/installation/upgrading.xml
@@ -107,4 +107,30 @@ newer Nix version, which may involve an upgrade of Nix’s database
 schema.  This cannot be undone easily, so in that case you will not be
 able to go back to your original channel.</para></warning>
 
+
+<section><title>Automatic Upgrades</title>
+
+<para>You can keep a NixOS system up-to-date automatically by adding
+the following to <filename>configuration.nix</filename>:
+
+<programlisting>
+system.autoUpgrade.enable = true;
+</programlisting>
+
+This enables a periodically executed systemd service named
+<literal>nixos-upgrade.service</literal>. It runs
+<command>nixos-rebuild switch --upgrade</command> to upgrade NixOS to
+the latest version in the current channel. (To see when the service
+runs, see <command>systemctl list-timers</command>.)  You can also
+specify a channel explicitly, e.g.
+
+<programlisting>
+system.autoUpgrade.channel = https://nixos.org/channels/nixos-15.09;
+</programlisting>
+
+</para>
+
+</section>
+
+
 </chapter>
diff --git a/nixos/doc/manual/release-notes/release-notes.xml b/nixos/doc/manual/release-notes/release-notes.xml
index e326f89d4f40..6ed99315a7af 100644
--- a/nixos/doc/manual/release-notes/release-notes.xml
+++ b/nixos/doc/manual/release-notes/release-notes.xml
@@ -9,6 +9,7 @@
 <para>This section lists the release notes for each stable version of NixOS
 and current unstable revision.</para>
 
+<xi:include href="rl-unstable.xml" />
 <xi:include href="rl-1509.xml" />
 <xi:include href="rl-1412.xml" />
 <xi:include href="rl-1404.xml" />
diff --git a/nixos/doc/manual/release-notes/rl-unstable.xml b/nixos/doc/manual/release-notes/rl-unstable.xml
new file mode 100644
index 000000000000..2781cee36148
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-unstable.xml
@@ -0,0 +1,27 @@
+<section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-release-unstable">
+
+<title>Unstable</title>
+
+<para>When upgrading from a previous release, please be aware of the
+  following incompatible changes:
+
+  <itemizedlist>
+    <listitem><para>
+        <command>wmiiSnap</command> has been replaced with
+        <command>wmii_hg</command>, but
+        <command>services.xserver.windowManager.wmii.enable</command>
+        has been updated respectively so this only affects you if you
+        have explicitly installed <command>wmiiSnap</command>.
+    </para></listitem>
+    <listitem><para>
+        <command>wmiimenu</command> is removed, as it has been removed by
+        the developers upstream. Use <command>wimenu</command> from the
+        <command>wmii-hg</command> package.
+    </para></listitem>
+  </itemizedlist>
+</para>
+</section>
diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix
index 3e07df6c0860..a87b285c5b7b 100644
--- a/nixos/lib/eval-config.nix
+++ b/nixos/lib/eval-config.nix
@@ -54,11 +54,6 @@ in rec {
 
   # These are the extra arguments passed to every module.  In
   # particular, Nixpkgs is passed through the "pkgs" argument.
-  # FIXME: we enable config.allowUnfree to make packages like
-  # nvidia-x11 available. This isn't a problem because if the user has
-  # ‘nixpkgs.config.allowUnfree = false’, then evaluation will fail on
-  # the 64-bit package anyway. However, it would be cleaner to respect
-  # nixpkgs.config here.
   extraArgs = extraArgs_ // {
     inherit modules baseModules;
   };
diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix
index 3622b21626b3..f58e540a6e5c 100644
--- a/nixos/modules/config/i18n.nix
+++ b/nixos/modules/config/i18n.nix
@@ -52,6 +52,15 @@ in
         '';
       };
 
+      consoleUseXkbConfig = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If set, configure the console keymap from the xserver keyboard
+          settings.
+        '';
+      };
+
       consoleKeyMap = mkOption {
         type = mkOptionType {
           name = "string or path";
@@ -74,6 +83,13 @@ in
 
   config = {
 
+    i18n.consoleKeyMap = with config.services.xserver;
+      mkIf config.i18n.consoleUseXkbConfig
+        (pkgs.runCommand "xkb-console-keymap" { preferLocalBuild = true; } ''
+          '${pkgs.ckbcomp}/bin/ckbcomp' -model '${xkbModel}' -layout '${layout}' \
+            -option '${xkbOptions}' -variant '${xkbVariant}' > "$out"
+        '');
+
     environment.systemPackages =
       optional (config.i18n.supportedLocales != []) glibcLocales;
 
diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix
index 3a9a09ee87c1..748ada99be69 100644
--- a/nixos/modules/config/system-path.nix
+++ b/nixos/modules/config/system-path.nix
@@ -103,16 +103,23 @@ in
       [ "/bin"
         "/etc/xdg"
         "/info"
-        "/lib"
+        "/lib" # FIXME: remove
+        #"/lib/debug/.build-id" # enables GDB to find separated debug info
         "/man"
         "/sbin"
+        "/share/applications"
+        "/share/desktop-directories"
         "/share/doc"
         "/share/emacs"
+        "/share/icons"
         "/share/info"
         "/share/man"
+        "/share/menus"
+        "/share/mime"
         "/share/nano"
         "/share/org"
         "/share/terminfo"
+        "/share/themes"
         "/share/vim-plugins"
       ];
 
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 478f433b431c..adc014eed415 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -216,7 +216,7 @@ let
           exist. If <option>users.mutableUsers</option> is true, the
           password can be changed subsequently using the
           <command>passwd</command> command. Otherwise, it's
-          equivalent to setting the <option>password</option> option.
+          equivalent to setting the <option>hashedPassword</option> option.
 
           ${hashedPasswordDescription}
         '';
@@ -336,13 +336,13 @@ let
     map (range: "${user.name}:${toString range.startUid}:${toString range.count}\n")
       user.subUidRanges);
 
-  subuidFile = concatStrings (map mkSubuidEntry (attrValues cfg.extraUsers));
+  subuidFile = concatStrings (map mkSubuidEntry (attrValues cfg.users));
 
   mkSubgidEntry = user: concatStrings (
     map (range: "${user.name}:${toString range.startGid}:${toString range.count}\n")
         user.subGidRanges);
 
-  subgidFile = concatStrings (map mkSubgidEntry (attrValues cfg.extraUsers));
+  subgidFile = concatStrings (map mkSubgidEntry (attrValues cfg.users));
 
   idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }:
     let
@@ -354,8 +354,8 @@ let
       else { dup = false; acc = newAcc; }
     ) { dup = false; acc = {}; } (builtins.attrNames set)).dup;
 
-  uidsAreUnique = idsAreUnique (filterAttrs (n: u: u.uid != null) cfg.extraUsers) "uid";
-  gidsAreUnique = idsAreUnique (filterAttrs (n: g: g.gid != null) cfg.extraGroups) "gid";
+  uidsAreUnique = idsAreUnique (filterAttrs (n: u: u.uid != null) cfg.users) "uid";
+  gidsAreUnique = idsAreUnique (filterAttrs (n: g: g.gid != null) cfg.groups) "gid";
 
   spec = pkgs.writeText "users-groups.json" (builtins.toJSON {
     inherit (cfg) mutableUsers;
@@ -364,13 +364,13 @@ let
           name uid group description home shell createHome isSystemUser
           password passwordFile hashedPassword
           initialPassword initialHashedPassword;
-      }) cfg.extraUsers;
+      }) cfg.users;
     groups = mapAttrsToList (n: g:
       { inherit (g) name gid;
         members = g.members ++ (mapAttrsToList (n: u: u.name) (
-          filterAttrs (n: u: elem g.name u.extraGroups) cfg.extraUsers
+          filterAttrs (n: u: elem g.name u.extraGroups) cfg.users
         ));
-      }) cfg.extraGroups;
+      }) cfg.groups;
   });
 
 in {
@@ -388,10 +388,10 @@ in {
         <literal>groupadd</literal> commands. On system activation, the
         existing contents of the <literal>/etc/passwd</literal> and
         <literal>/etc/group</literal> files will be merged with the
-        contents generated from the <literal>users.extraUsers</literal> and
-        <literal>users.extraGroups</literal> options.
+        contents generated from the <literal>users.users</literal> and
+        <literal>users.groups</literal> options.
         The initial password for a user will be set
-        according to <literal>users.extraUsers</literal>, but existing passwords
+        according to <literal>users.users</literal>, but existing passwords
         will not be changed.
 
         <warning><para>
@@ -399,7 +399,7 @@ in {
         group files will simply be replaced on system activation. This also
         holds for the user passwords; all changed
         passwords will be reset according to the
-        <literal>users.extraUsers</literal> configuration on activation.
+        <literal>users.users</literal> configuration on activation.
         </para></warning>
       '';
     };
@@ -412,7 +412,7 @@ in {
       '';
     };
 
-    users.extraUsers = mkOption {
+    users.users = mkOption {
       default = {};
       type = types.loaOf types.optionSet;
       example = {
@@ -433,7 +433,7 @@ in {
       options = [ userOpts ];
     };
 
-    users.extraGroups = mkOption {
+    users.groups = mkOption {
       default = {};
       example =
         { students.gid = 1001;
@@ -461,7 +461,7 @@ in {
 
   config = {
 
-    users.extraUsers = {
+    users.users = {
       root = {
         uid = ids.uids.root;
         description = "System administrator";
@@ -478,7 +478,7 @@ in {
       };
     };
 
-    users.extraGroups = {
+    users.groups = {
       root.gid = ids.gids.root;
       wheel.gid = ids.gids.wheel;
       disk.gid = ids.gids.disk;
@@ -525,6 +525,27 @@ in {
       { assertion = !cfg.enforceIdUniqueness || (uidsAreUnique && gidsAreUnique);
         message = "UIDs and GIDs must be unique!";
       }
+      { # If mutableUsers is false, to prevent users creating a
+        # configuration that locks them out of the system, ensure that
+        # there is at least one "privileged" account that has a
+        # password or an SSH authorized key. Privileged accounts are
+        # root and users in the wheel group.
+        assertion = !cfg.mutableUsers ->
+          any id (mapAttrsToList (name: cfg:
+            (name == "root"
+             || cfg.group == "wheel"
+             || elem "wheel" cfg.extraGroups)
+            &&
+            ((cfg.hashedPassword != null && cfg.hashedPassword != "!")
+             || cfg.password != null
+             || cfg.passwordFile != null
+             || cfg.openssh.authorizedKeys.keys != []
+             || cfg.openssh.authorizedKeys.keyFiles != [])
+          ) cfg.users);
+        message = ''
+          Neither the root account nor any wheel user has a password or SSH authorized key.
+          You must set one to prevent being locked out of your system.'';
+      }
     ];
 
   };
diff --git a/nixos/modules/misc/extra-arguments.nix b/nixos/modules/misc/extra-arguments.nix
index 02ac6e7a59dc..19002b17dace 100644
--- a/nixos/modules/misc/extra-arguments.nix
+++ b/nixos/modules/misc/extra-arguments.nix
@@ -4,6 +4,11 @@
   _module.args = {
     pkgs_i686 = import ../../.. {
       system = "i686-linux";
+      # FIXME: we enable config.allowUnfree to make packages like
+      # nvidia-x11 available. This isn't a problem because if the user has
+      # ‘nixpkgs.config.allowUnfree = false’, then evaluation will fail on
+      # the 64-bit package anyway. However, it would be cleaner to respect
+      # nixpkgs.config here.
       config.allowUnfree = true;
     };
 
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 1e5393f26b54..195d22f455c5 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -229,6 +229,9 @@
       riak = 205;
       shout = 206;
       gateone = 207;
+      namecoin = 208;
+      dnschain = 209;
+      #lxd = 210; # unused
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -436,6 +439,9 @@
       riak = 205;
       #shout = 206; #unused
       gateone = 207;
+      namecoin = 208;
+      #dnschain = 209; #unused
+      lxd = 210; # unused
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index dc8eb4e88329..b4b0281fe587 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -75,7 +75,7 @@ with lib;
       mkDefault (if pathExists fn then readFile fn else "master");
 
     # Note: code names must only increase in alphabetical order.
-    system.nixosCodeName = "Dingo";
+    system.nixosCodeName = "Emu";
 
     # Generate /etc/os-release.  See
     # http://0pointer.de/public/systemd-man/os-release.html for the
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 8ee54ce7ef4b..82e0cdc69266 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -275,6 +275,7 @@
   ./services/networking/ddclient.nix
   ./services/networking/dhcpcd.nix
   ./services/networking/dhcpd.nix
+  ./services/networking/dnschain.nix
   ./services/networking/dnscrypt-proxy.nix
   ./services/networking/dnsmasq.nix
   ./services/networking/docker-registry-server.nix
@@ -303,6 +304,7 @@
   ./services/networking/minidlna.nix
   ./services/networking/mstpd.nix
   ./services/networking/murmur.nix
+  ./services/networking/namecoind.nix
   ./services/networking/nat.nix
   ./services/networking/networkmanager.nix
   ./services/networking/ngircd.nix
@@ -485,6 +487,7 @@
   ./virtualisation/docker.nix
   ./virtualisation/libvirtd.nix
   ./virtualisation/lxc.nix
+  ./virtualisation/lxd.nix
   ./virtualisation/amazon-options.nix
   ./virtualisation/openvswitch.nix
   ./virtualisation/parallels-guest.nix
diff --git a/nixos/modules/programs/cdemu.nix b/nixos/modules/programs/cdemu.nix
index d1b1915eea91..98df9b94380f 100644
--- a/nixos/modules/programs/cdemu.nix
+++ b/nixos/modules/programs/cdemu.nix
@@ -9,19 +9,28 @@ in {
     programs.cdemu = {
       enable = mkOption {
         default = false;
-        description = "Whether to enable cdemu for users of appropriate group (default cdrom)";
+        description = ''
+          <command>cdemu</command> for members of
+          <option>programs.cdemu.group</option>.
+        '';
       };
       group = mkOption {
         default = "cdrom";
-        description = "Required group for users of cdemu";
+        description = ''
+          Group that users must be in to use <command>cdemu</command>.
+        '';
       };
       gui = mkOption {
         default = true;
-        description = "Whether to install cdemu GUI (gCDEmu)";
+        description = ''
+          Whether to install the <command>cdemu</command> GUI (gCDEmu).
+        '';
       };
       image-analyzer = mkOption {
         default = true;
-        description = "Whether to install image analyzer";
+        description = ''
+          Whether to install the image analyzer.
+        '';
       };
     };
   };
diff --git a/nixos/modules/programs/command-not-found/command-not-found.nix b/nixos/modules/programs/command-not-found/command-not-found.nix
index bead2dcdcf90..9524d91ea3bc 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.nix
+++ b/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -57,9 +57,9 @@ in
           if [ $? = 126 ]; then
             "$@"
           fi
-	else
+        else
           # Indicate than there was an error so ZSH falls back to its default handler
-	  return 127
+          return 127
         fi
       }
     '';
diff --git a/nixos/modules/programs/command-not-found/command-not-found.pl b/nixos/modules/programs/command-not-found/command-not-found.pl
index 916649059d37..b233d973a4ab 100644
--- a/nixos/modules/programs/command-not-found/command-not-found.pl
+++ b/nixos/modules/programs/command-not-found/command-not-found.pl
@@ -30,11 +30,11 @@ The program ‘$program’ is currently not installed. It is provided by
 the package ‘$package’, which I will now install for you.
 EOF
         ;
-        exit 126 if system("nix-env", "-i", $package) == 0;
+        exit 126 if system("nix-env", "-iA", "nixos.$package") == 0;
     } else {
         print STDERR <<EOF;
 The program ‘$program’ is currently not installed. You can install it by typing:
-  nix-env -i $package
+  nix-env -iA nixos.$package
 EOF
     }
 } else {
@@ -42,7 +42,7 @@ EOF
 The program ‘$program’ is currently not installed. It is provided by
 several packages. You can install it by typing one of the following:
 EOF
-    print STDERR "  nix-env -i $_->{package}\n" foreach @$res;
+    print STDERR "  nix-env -iA nixos.$_->{package}\n" foreach @$res;
 }
 
 exit 127;
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 6f7dcb837a07..62be7dc6cae2 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -77,6 +77,8 @@ in zipModules ([]
 ++ obsolete [ "environment" "nix" ] [ "nix" "package" ]
 ++ obsolete [ "fonts" "enableFontConfig" ] [ "fonts" "fontconfig" "enable" ]
 ++ obsolete [ "fonts" "extraFonts" ] [ "fonts" "fonts" ]
+++ alias [ "users" "extraUsers" ] [ "users" "users" ]
+++ alias [ "users" "extraGroups" ] [ "users" "groups" ]
 
 ++ obsolete [ "security" "extraSetuidPrograms" ] [ "security" "setuidPrograms" ]
 ++ obsolete [ "networking" "enableWLAN" ] [ "networking" "wireless" "enable" ]
@@ -163,5 +165,6 @@ in zipModules ([]
 ++ obsolete' [ "services" "syslog-ng" "serviceName" ]
 ++ obsolete' [ "services" "syslog-ng" "listenToJournal" ]
 ++ obsolete' [ "ec2" "metadata" ]
+++ obsolete' [ "services" "openvpn" "enable" ]
 
 )
diff --git a/nixos/modules/security/prey.nix b/nixos/modules/security/prey.nix
index e29fa5395a1a..d7d438103a2c 100644
--- a/nixos/modules/security/prey.nix
+++ b/nixos/modules/security/prey.nix
@@ -16,19 +16,28 @@ in {
         default = false;
         type = types.bool;
         description = ''
-          Enables http://preyproject.com/ bash client. Be sure to specify api and device keys.
-          Once setup, cronjob will run evert 15 minutes and report status.
+          Enables the <link xlink:href="http://preyproject.com/" />
+          shell client. Be sure to specify both API and device keys.
+          Once enabled, a <command>cron</command> job will run every 15
+          minutes to report status information.
         '';
       };
 
       deviceKey = mkOption {
         type = types.string;
-        description = "Device Key obtained from https://panel.preyproject.com/devices (and clicking on the device)";
+        description = ''
+          <literal>Device key</literal> obtained by visiting
+          <link xlink:href="https://panel.preyproject.com/devices" />
+          and clicking on your device.
+        '';
       };
 
       apiKey = mkOption {
         type = types.string;
-        description = "API key obtained from https://panel.preyproject.com/profile";
+        description = ''
+          <literal>API key</literal> obtained from
+          <link xlink:href="https://panel.preyproject.com/profile" />.
+        '';
       };
     };
 
diff --git a/nixos/modules/services/backup/bacula.nix b/nixos/modules/services/backup/bacula.nix
index 9e3ae66f808b..69f3c3f8a758 100644
--- a/nixos/modules/services/backup/bacula.nix
+++ b/nixos/modules/services/backup/bacula.nix
@@ -169,14 +169,17 @@ in {
         type = types.bool;
         default = false;
         description = ''
-          Whether to enable Bacula File Daemon.
+          Whether to enable the Bacula File Daemon.
         '';
       };
  
       name = mkOption {
         default = "${config.networking.hostName}-fd";
         description = ''
-        	The client name that must be used by the Director when connecting. Generally, it is a good idea to use a name related to the machine so that error messages can be easily identified if you have multiple Clients. This directive is required.
+          The client name that must be used by the Director when connecting.
+          Generally, it is a good idea to use a name related to the machine
+          so that error messages can be easily identified if you have multiple
+          Clients. This directive is required.
         '';
       };
  
@@ -184,7 +187,9 @@ in {
         default = 9102;
         type = types.int;
         description = ''
-        	This specifies the port number on which the Client listens for Director connections. It must agree with the FDPort specified in the Client resource of the Director's configuration file. The default is 9102.
+          This specifies the port number on which the Client listens for
+          Director connections. It must agree with the FDPort specified in
+          the Client resource of the Director's configuration file.
         '';
       };
  
@@ -202,7 +207,7 @@ in {
         description = ''
           Extra configuration to be passed in Client directive.
         '';
-        example = ''
+        example = literalExample ''
           Maximum Concurrent Jobs = 20;
           Heartbeat Interval = 30;
         '';
@@ -213,7 +218,7 @@ in {
         description = ''
           Extra configuration to be passed in Messages directive.
         '';
-        example = ''
+        example = literalExample ''
           console = all
         '';
       };
diff --git a/nixos/modules/services/backup/sitecopy-backup.nix b/nixos/modules/services/backup/sitecopy-backup.nix
index 5f2b4e76aeeb..6e4721ded68b 100644
--- a/nixos/modules/services/backup/sitecopy-backup.nix
+++ b/nixos/modules/services/backup/sitecopy-backup.nix
@@ -21,15 +21,16 @@ in
       enable = mkOption {
         default = false;
         description = ''
-          Whether to enable sitecopy backups of specified directories.
+          Whether to enable <command>sitecopy</command> backups of specified
+          directories.
         '';
       };
 
       period = mkOption {
         default = "15 04 * * *";
         description = ''
-          This option defines (in the format used by cron) when the
-          sitecopy backup are being run.
+          This option defines (in the format used by <command>cron</command>)
+          when the <command>sitecopy</command> backups are to be run.
           The default is to update at 04:15 (at night) every day.
         '';
       };
@@ -47,9 +48,10 @@ in
         ];
         default = [];
         description = ''
-           List of attributesets describing the backups.
+           List of attribute sets describing the backups.
 
-           Username/password are extracted from <filename>${stateDir}/sitecopy.secrets</filename> at activation
+           Username/password are extracted from
+           <filename>${stateDir}/sitecopy.secrets</filename> at activation
            time. The secrets file lines should have the following structure:
            <screen>
              server username password
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index ba09f04d502b..a06384e27139 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -73,7 +73,7 @@ in {
       };
 
       port = mkOption {
-        description = "Kubernets apiserver listening port.";
+        description = "Kubernetes apiserver listening port.";
         default = 8080;
         type = types.int;
       };
@@ -211,7 +211,7 @@ in {
       };
 
       port = mkOption {
-        description = "Kubernets scheduler listening port.";
+        description = "Kubernetes scheduler listening port.";
         default = 10251;
         type = types.int;
       };
@@ -243,7 +243,7 @@ in {
       };
 
       port = mkOption {
-        description = "Kubernets controller manager listening port.";
+        description = "Kubernetes controller manager listening port.";
         default = 10252;
         type = types.int;
       };
@@ -299,7 +299,7 @@ in {
       };
 
       port = mkOption {
-        description = "Kubernets kubelet info server listening port.";
+        description = "Kubernetes kubelet info server listening port.";
         default = 10250;
         type = types.int;
       };
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix
index 1cdecedfc772..efc52e917b00 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -167,6 +167,12 @@ in
 
         unitConfig.RequiresMountsFor = "${cfg.dataDir}";
 
+        path = [
+          # Needed for the mysql_install_db command in the preStart script
+          # which calls the hostname command.
+          pkgs.nettools
+        ];
+
         preStart =
           ''
             if ! test -e ${cfg.dataDir}/mysql; then
diff --git a/nixos/modules/services/hardware/brltty.nix b/nixos/modules/services/hardware/brltty.nix
index d6c05a3d620c..03e530b2c96d 100644
--- a/nixos/modules/services/hardware/brltty.nix
+++ b/nixos/modules/services/hardware/brltty.nix
@@ -4,10 +4,6 @@ with lib;
 
 let
   cfg = config.services.brltty;
-  
-  stateDir = "/run/brltty";
-
-  pidFile = "${stateDir}/brltty.pid";
 
 in {
 
@@ -24,14 +20,24 @@ in {
   config = mkIf cfg.enable {
 
     systemd.services.brltty = {
-      description = "Braille console driver";
-      preStart = ''
-        mkdir -p ${stateDir}
-      '';
+      description = "Braille Device Support";
+      unitConfig = {
+        Documentation = "http://mielke.cc/brltty/";
+        DefaultDependencies = "no";
+        RequiresMountsFor = "${pkgs.brltty}/var/lib/brltty";
+      };
       serviceConfig = {
-        ExecStart = "${pkgs.brltty}/bin/brltty --pid-file=${pidFile}";
-        Type = "forking";
-        PIDFile = pidFile;
+        ExecStart = "${pkgs.brltty}/bin/brltty --no-daemon";
+        Type = "simple";        # Change to notidy after next releae
+        TimeoutStartSec = 5;
+        TimeoutStopSec = 10;
+        Restart = "always";
+        RestartSec = 30;
+        Nice = -10;
+        OOMScoreAdjust = -900;
+        ProtectHome = "read-only";
+        ProtectSystem = "full";
+        SystemCallArchitectures = "native";
       };
       before = [ "sysinit.target" ];
       wantedBy = [ "sysinit.target" ];
diff --git a/nixos/modules/services/hardware/freefall.nix b/nixos/modules/services/hardware/freefall.nix
index 7867956c1ab0..2be339766069 100644
--- a/nixos/modules/services/hardware/freefall.nix
+++ b/nixos/modules/services/hardware/freefall.nix
@@ -2,40 +2,42 @@
 
 with lib;
 
-{
+let
 
-  ###### interface
+  cfg = config.services.freefall;
 
-  options = with types; {
+in {
 
-    services.freefall = {
+  options.services.freefall = {
 
-      enable = mkOption {
-        default = false;
-        description = ''
-          Whether to protect HP/Dell laptop hard drives (not SSDs) in free fall.
-        '';
-        type = bool;
-      };
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to protect HP/Dell laptop hard drives (not SSDs) in free fall.
+      '';
+    };
 
-      devices = mkOption {
-        default = [ "/dev/sda" ];
-        description = ''
-          Device paths to all internal spinning hard drives.
-        '';
-        type = listOf string;
-      };
+    package = mkOption {
+      type = types.package;
+      default = pkgs.freefall;
+      description = ''
+        freefall derivation to use.
+      '';
+    };
 
+    devices = mkOption {
+      type = types.listOf types.string;
+      default = [ "/dev/sda" ];
+      description = ''
+        Device paths to all internal spinning hard drives.
+      '';
     };
 
   };
 
-  ###### implementation
-
   config = let
 
-    cfg = config.services.freefall;
-
     mkService = dev:
       assert dev != "";
       let dev' = utils.escapeSystemdPath dev; in
@@ -43,12 +45,8 @@ with lib;
         description = "Free-fall protection for ${dev}";
         after = [ "${dev'}.device" ];
         wantedBy = [ "${dev'}.device" ];
-        path = [ pkgs.freefall ];
-        unitConfig = {
-          DefaultDependencies = false;
-        };
         serviceConfig = {
-          ExecStart = "${pkgs.freefall}/bin/freefall ${dev}";
+          ExecStart = "${cfg.package}/bin/freefall ${dev}";
           Restart = "on-failure";
           Type = "forking";
         };
@@ -56,9 +54,9 @@ with lib;
 
   in mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.freefall ];
+    environment.systemPackages = [ cfg.package ];
 
-    systemd.services = listToAttrs (map mkService cfg.devices);
+    systemd.services = builtins.listToAttrs (map mkService cfg.devices);
 
   };
 
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 513eb27b4069..c747c24db67d 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -180,9 +180,7 @@ in
         firmware to function).  If multiple packages contain firmware
         files with the same name, the first package in the list takes
         precedence.  Note that you must rebuild your system if you add
-        files to any of these directories.  For quick testing,
-        put firmware files in <filename>/root/test-firmware</filename>
-        and add that directory to the list.
+        files to any of these directories.
       '';
       apply = list: pkgs.buildEnv {
         name = "firmware";
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index 117ee1c900f5..aec45d9286d8 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -132,6 +132,7 @@ in
       description = "Logstash Daemon";
       wantedBy = [ "multi-user.target" ];
       environment = { JAVA_HOME = jre; };
+      path = [ pkgs.bash ];
       serviceConfig = {
         ExecStart =
           "${cfg.package}/bin/logstash agent " +
diff --git a/nixos/modules/services/mail/mlmmj.nix b/nixos/modules/services/mail/mlmmj.nix
index 5843a6745f58..e2b37522cb16 100644
--- a/nixos/modules/services/mail/mlmmj.nix
+++ b/nixos/modules/services/mail/mlmmj.nix
@@ -14,7 +14,7 @@ let
   alias = domain: list: "${list}: \"|${pkgs.mlmmj}/bin/mlmmj-receive -L ${listDir domain list}/\"";
   subjectPrefix = list: "[${list}]";
   listAddress = domain: list: "${list}@${domain}";
-  customHeaders = list: domain: [ "List-Id: ${list}" "Reply-To: ${list}@${domain}" ];
+  customHeaders = domain: list: [ "List-Id: ${list}" "Reply-To: ${list}@${domain}" ];
   footer = domain: list: "To unsubscribe send a mail to ${list}+unsubscribe@${domain}";
   createList = d: l: ''
     ${pkgs.coreutils}/bin/mkdir -p ${listCtl d l}
@@ -90,14 +90,15 @@ in
       enable = true;
       recipientDelimiter= "+";
       extraMasterConf = ''
-        mlmmj unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj}/bin/mlmmj-receive -F -L ${spoolDir}/$nextHop
+        mlmmj unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj}/bin/mlmmj-receive -F -L ${spoolDir}/$nexthop
       '';
 
       extraAliases = concatMapStrings (alias cfg.listDomain) cfg.mailLists;
 
       extraConfig = ''
-        transport = hash:${stateDir}/transports
-        virtual = hash:${stateDir}/virtuals
+        transport_maps = hash:${stateDir}/transports
+        virtual_alias_maps = hash:${stateDir}/virtuals
+        propagate_unmatched_extensions = virtual
       '';
     };
 
@@ -108,9 +109,10 @@ in
           ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${spoolDir}
           ${lib.concatMapStrings (createList cfg.listDomain) cfg.mailLists}
           echo ${lib.concatMapStrings (virtual cfg.listDomain) cfg.mailLists} > ${stateDir}/virtuals
-          echo ${cfg.listDomain} mailman: > ${stateDir}/transports
-          echo ${lib.concatMapStrings (transport cfg.listDomain) cfg.mailLists} >> ${stateDir}/transports
-    '';
+          echo ${lib.concatMapStrings (transport cfg.listDomain) cfg.mailLists} > ${stateDir}/transports
+          ${pkgs.postfix}/bin/postmap ${stateDir}/virtuals
+          ${pkgs.postfix}/bin/postmap ${stateDir}/transports
+      '';
 
     systemd.services."mlmmj-maintd" = {
       description = "mlmmj maintenance daemon";
diff --git a/nixos/modules/services/misc/gitit.nix b/nixos/modules/services/misc/gitit.nix
index 10a706fbd71d..8e9e761b6092 100644
--- a/nixos/modules/services/misc/gitit.nix
+++ b/nixos/modules/services/misc/gitit.nix
@@ -99,7 +99,7 @@ let
       };
 
       authenticationMethod = mkOption {
-        type = types.enum [ "form" "http" "generic"];
+        type = types.enum [ "form" "http" "generic" "github" ];
         default = "form";
         description = ''
           'form' means that users will be logged in and registered using forms
@@ -537,6 +537,42 @@ video/x-ms-wmx  wmx
           through xss-sanitize.  Set to no only if you trust all of your users.
         '';
       };
+
+      oauthClientId = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "OAuth client ID";
+      };
+
+      oauthClientSecret = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "OAuth client secret";
+      };
+
+      oauthCallback = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "OAuth callback URL";
+      };
+
+      oauthAuthorizeEndpoint = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "OAuth authorize endpoint";
+      };
+
+      oauthAccessTokenEndpoint = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "OAuth access token endpoint";
+      };
+
+      githubOrg = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = "Github organization";
+      };
   };
 
   configFile = pkgs.writeText "gitit.conf" ''
@@ -587,6 +623,14 @@ video/x-ms-wmx  wmx
     pdf-export: ${toYesNo cfg.pdfExport}
     pandoc-user-data: ${toString cfg.pandocUserData}
     xss-sanitize: ${toYesNo cfg.xssSanitize}
+
+    [Github]
+    oauthclientid: ${toString cfg.oauthClientId}
+    oauthclientsecret: ${toString cfg.oauthClientSecret}
+    oauthcallback: ${toString cfg.oauthCallback}
+    oauthauthorizeendpoint: ${toString cfg.oauthAuthorizeEndpoint}
+    oauthaccesstokenendpoint: ${toString cfg.oauthAccessTokenEndpoint}
+    github-org: ${toString cfg.githubOrg}
   '';
 
 in
@@ -681,4 +725,3 @@ NAMED
     };
   };
 }
-
diff --git a/nixos/modules/services/misc/nix-gc.nix b/nixos/modules/services/misc/nix-gc.nix
index 981299352575..6a7a7f4cee72 100644
--- a/nixos/modules/services/misc/nix-gc.nix
+++ b/nixos/modules/services/misc/nix-gc.nix
@@ -52,7 +52,7 @@ in
 
     systemd.services.nix-gc =
       { description = "Nix Garbage Collector";
-        script = "exec ${config.nix.package}/bin/nix-store --gc ${cfg.options}";
+        script = "exec ${config.nix.package}/bin/nix-collect-garbage ${cfg.options}";
         startAt = optionalString cfg.automatic cfg.dates;
       };
 
diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix
index 7a53ce174542..7e8dea4ec024 100644
--- a/nixos/modules/services/monitoring/bosun.nix
+++ b/nixos/modules/services/monitoring/bosun.nix
@@ -30,6 +30,7 @@ in {
 
       package = mkOption {
         type = types.package;
+        default = pkgs.bosun;
         example = literalExample "pkgs.bosun";
         description = ''
           bosun binary to use.
@@ -95,8 +96,6 @@ in {
 
   config = mkIf cfg.enable {
   
-    services.bosun.package = mkDefault pkgs.bosun; 
-
     systemd.services.bosun = {
       description = "bosun metrics collector (part of Bosun)";
       wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix
index f987c4792e93..0393d01054d1 100644
--- a/nixos/modules/services/monitoring/grafana.nix
+++ b/nixos/modules/services/monitoring/grafana.nix
@@ -206,7 +206,7 @@ in {
 
     package = mkOption {
       description = "Package to use.";
-      default = pkgs.grafana-backend;
+      default = pkgs.grafana;
       type = types.package;
     };
 
diff --git a/nixos/modules/services/network-filesystems/nfsd.nix b/nixos/modules/services/network-filesystems/nfsd.nix
index 33b7ec3d9f1c..f1838224098b 100644
--- a/nixos/modules/services/network-filesystems/nfsd.nix
+++ b/nixos/modules/services/network-filesystems/nfsd.nix
@@ -88,10 +88,7 @@ in
 
     environment.systemPackages = [ pkgs.nfs-utils ];
 
-    environment.etc = singleton
-      { source = exports;
-        target = "exports";
-      };
+    environment.etc.exports.source = exports;
 
     boot.kernelModules = [ "nfsd" ];
 
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index bbf21634c368..72e9b6144d4b 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -97,8 +97,8 @@ in
         description = ''
           Enabling this will add a line directly after pam_unix.so.
           Whenever a password is changed the samba password will be updated as well.
-          However you still yave to add the samba password once using smbpasswd -a user
-          If you don't want to maintain an extra pwd database you still can send plain text
+          However, you still have to add the samba password once, using smbpasswd -a user.
+          If you don't want to maintain an extra password database, you still can send plain text
           passwords which is not secure.
         '';
       };
diff --git a/nixos/modules/services/networking/bitlbee.nix b/nixos/modules/services/networking/bitlbee.nix
index 27b7dd71d9e5..5e6847097a94 100644
--- a/nixos/modules/services/networking/bitlbee.nix
+++ b/nixos/modules/services/networking/bitlbee.nix
@@ -16,11 +16,12 @@ let
     ''
     [settings]
     RunMode = Daemon
-    User = bitlbee  
+    User = bitlbee
     ConfigDir = ${cfg.configDir}
     DaemonInterface = ${cfg.interface}
     DaemonPort = ${toString cfg.portNumber}
     AuthMode = ${cfg.authMode}
+    Plugindir = ${pkgs.bitlbee-plugins cfg.plugins}/lib/bitlbee
     ${lib.optionalString (cfg.hostName != "") "HostName = ${cfg.hostName}"}
     ${lib.optionalString (cfg.protocols != "") "Protocols = ${cfg.protocols}"}
     ${cfg.extraSettings}
@@ -72,7 +73,7 @@ in
             Open -- Accept connections from anyone, use NickServ for user authentication.
             Closed -- Require authorization (using the PASS command during login) before allowing the user to connect at all.
             Registered -- Only allow registered users to use this server; this disables the register- and the account command until the user identifies himself.
-        ''; 
+        '';
       };
 
       hostName = mkOption {
@@ -85,6 +86,15 @@ in
         '';
       };
 
+      plugins = mkOption {
+        type = types.listOf types.package;
+        default = [];
+        example = literalExample "[ pkgs.bitlbee-facebook ]";
+        description = ''
+          The list of bitlbee plugins to install.
+        '';
+      };
+
       configDir = mkOption {
         default = "/var/lib/bitlbee";
         type = types.path;
@@ -107,14 +117,14 @@ in
         default = "";
         description = ''
           Will be inserted in the Settings section of the config file.
-        ''; 
+        '';
       };
 
       extraDefaults = mkOption {
         default = "";
         description = ''
           Will be inserted in the Default section of the config file.
-        ''; 
+        '';
       };
 
     };
@@ -138,7 +148,7 @@ in
         gid = config.ids.gids.bitlbee;
       };
 
-    systemd.services.bitlbee = 
+    systemd.services.bitlbee =
       { description = "BitlBee IRC to other chat networks gateway";
         after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/networking/connman.nix b/nixos/modules/services/networking/connman.nix
index 482b61997ae1..deb1cbfc1858 100644
--- a/nixos/modules/services/networking/connman.nix
+++ b/nixos/modules/services/networking/connman.nix
@@ -5,7 +5,12 @@ with lib;
 
 let
   cfg = config.networking.connman;
+  configFile = pkgs.writeText "connman.conf" ''
+    [General]
+    NetworkInterfaceBlacklist=${concatStringsSep "," cfg.networkInterfaceBlacklist}
 
+    ${cfg.extraConfig}
+  '';
 in {
 
   ###### interface
@@ -22,6 +27,23 @@ in {
         '';
       };
 
+      extraConfig = mkOption {
+        type = types.lines;
+        default = ''
+        '';
+        description = ''
+          Configuration lines appended to the generated connman configuration file.
+        '';
+      };
+
+      networkInterfaceBlacklist = mkOption {
+        type = with types; listOf string;
+        default = [ "vmnet" "vboxnet" "virbr" "ifb" "ve" ];
+        description = ''
+          Default blacklisted interfaces, this includes NixOS containers interfaces (ve).
+        '';
+      };
+
     };
 
   };
@@ -51,7 +73,7 @@ in {
         Type = "dbus";
         BusName = "net.connman";
         Restart = "on-failure";
-        ExecStart = "${pkgs.connman}/sbin/connmand --nodaemon";
+        ExecStart = "${pkgs.connman}/sbin/connmand --config=${configFile} --nodaemon";
         StandardOutput = "null";
       };
     };
diff --git a/nixos/modules/services/networking/dnschain.nix b/nixos/modules/services/networking/dnschain.nix
new file mode 100644
index 000000000000..f17f8c832ee4
--- /dev/null
+++ b/nixos/modules/services/networking/dnschain.nix
@@ -0,0 +1,110 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services;
+
+  dnschainConf = pkgs.writeText "dnschain.conf" ''
+    [log]
+    level=info
+
+    [dns]
+    host = 127.0.0.1
+    port = 5333
+    oldDNSMethod = NO_OLD_DNS
+    # TODO: check what that address is acutally used for
+    externalIP = 127.0.0.1
+
+    [http]
+    host = 127.0.0.1
+    port=8088
+    tlsPort=4443
+  '';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.dnschain = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run dnschain. That implies running
+          namecoind as well, so make sure to configure
+          it appropriately.
+        '';
+      };
+
+    };
+
+    services.dnsmasq = {
+      resolveDnschainQueries = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Resolve <literal>.bit</literal> top-level domains
+          with dnschain and namecoind.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.dnschain.enable {
+
+    services.namecoind.enable = true;
+
+    services.dnsmasq.servers = optionals cfg.dnsmasq.resolveDnschainQueries [ "/.bit/127.0.0.1#5333" ];
+
+    users.extraUsers = singleton
+      { name = "dnschain";
+        uid = config.ids.uids.dnschain;
+        extraGroups = [ "namecoin" ];
+        description = "Dnschain daemon user";
+        home = "/var/lib/dnschain";
+        createHome = true;
+      };
+
+    systemd.services.dnschain = {
+        description = "Dnschain Daemon";
+        after = [ "namecoind.target" ];
+        wantedBy = [ "multi-user.target" ];
+        path = [ pkgs.openssl ];
+        preStart = ''
+          # Link configuration file into dnschain HOME directory
+          if [ "$(${pkgs.coreutils}/bin/realpath /var/lib/dnschain/.dnschain.conf)" != "${dnschainConf}" ]; then
+              rm -rf /var/lib/dnschain/.dnschain.conf
+              ln -s ${dnschainConf} /var/lib/dnschain/.dnschain.conf
+          fi
+
+          # Create empty namecoin.conf so that dnschain is not
+          # searching for /etc/namecoin/namecoin.conf
+          if [ ! -e /var/lib/dnschain/.namecoin/namecoin.conf ]; then
+              mkdir -p /var/lib/dnschain/.namecoin
+              touch /var/lib/dnschain/.namecoin/namecoin.conf
+          fi
+        '';
+        serviceConfig = {
+          Type = "simple";
+          User = "dnschain";
+          EnvironmentFile = config.services.namecoind.userFile;
+          ExecStart = "${pkgs.dnschain}/bin/dnschain --rpcuser=\${USER} --rpcpassword=\${PASSWORD} --rpcport=8336";
+          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+          ExecStop = "${pkgs.coreutils}/bin/kill -KILL $MAINPID";
+        };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index eb3551515723..6907d63d7611 100644
--- a/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixos/modules/services/networking/dnsmasq.nix
@@ -96,7 +96,7 @@ in
           Type = "dbus";
           BusName = "uk.org.thekelleys.dnsmasq";
           ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}";
-          ExecReload = "${dnsmasq}/bin/kill -HUP $MAINPID";
+          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         };
         restartTriggers = [ config.environment.etc.hosts.source ];
     };
diff --git a/nixos/modules/services/networking/namecoind.nix b/nixos/modules/services/networking/namecoind.nix
new file mode 100644
index 000000000000..83fc1ec66679
--- /dev/null
+++ b/nixos/modules/services/networking/namecoind.nix
@@ -0,0 +1,150 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.namecoind;
+
+  namecoinConf =
+  let
+    useSSL = (cfg.rpcCertificate != null) && (cfg.rpcKey != null);
+  in
+  pkgs.writeText "namecoin.conf" ''
+    server=1
+    daemon=0
+    rpcallowip=127.0.0.1
+    walletpath=${cfg.wallet}
+    gen=${if cfg.generate then "1" else "0"}
+    rpcssl=${if useSSL then "1" else "0"}
+    ${optionalString useSSL "rpcsslcertificatechainfile=${cfg.rpcCertificate}"}
+    ${optionalString useSSL "rpcsslprivatekeyfile=${cfg.rpcKey}"}
+    ${optionalString useSSL "rpcsslciphers=TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH"}
+    txindex=1
+    txprevcache=1
+  '';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.namecoind = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to run namecoind.
+        '';
+      };
+
+      wallet = mkOption {
+        type = types.path;
+        example = "/etc/namecoin/wallet.dat";
+        description = ''
+          Wallet file. The ownership of the file has to be
+          namecoin:namecoin, and the permissions must be 0640.
+        '';
+      };
+
+      userFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/etc/namecoin/user";
+        description = ''
+          File containing the user name and user password to
+          authenticate RPC connections to namecoind.
+          The content of the file is of the form:
+          <literal>
+          USER=namecoin
+          PASSWORD=secret
+          </literal>
+          The ownership of the file has to be namecoin:namecoin,
+          and the permissions must be 0640.
+        '';
+      };
+
+      generate = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to generate (mine) Namecoins.
+        '';
+      };
+
+      rpcCertificate = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/etc/namecoin/server.cert";
+        description = ''
+          Certificate file for securing RPC connections.
+        '';
+      };
+
+      rpcKey = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/etc/namecoin/server.pem";
+        description = ''
+          Key file for securing RPC connections.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = singleton
+      { name = "namecoin";
+        uid = config.ids.uids.namecoin;
+        description = "Namecoin daemon user";
+        home = "/var/lib/namecoin";
+        createHome = true;
+      };
+
+    users.extraGroups = singleton
+      { name = "namecoin";
+        gid = config.ids.gids.namecoin;
+      };
+
+    systemd.services.namecoind = {
+        description = "Namecoind Daemon";
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        preStart = ''
+          if [  "$(stat --printf '%u' ${cfg.userFile})" != "${toString config.ids.uids.namecoin}" \
+             -o "$(stat --printf '%g' ${cfg.userFile})" != "${toString config.ids.gids.namecoin}" \
+             -o "$(stat --printf '%a' ${cfg.userFile})" != "640" ]; then
+             echo "ERROR: bad ownership or rights on ${cfg.userFile}" >&2
+             exit 1
+          fi
+          if [  "$(stat --printf '%u' ${cfg.wallet})" != "${toString config.ids.uids.namecoin}" \
+             -o "$(stat --printf '%g' ${cfg.wallet})" != "${toString config.ids.gids.namecoin}" \
+             -o "$(stat --printf '%a' ${cfg.wallet})" != "640" ]; then
+             echo "ERROR: bad ownership or rights on ${cfg.wallet}" >&2
+             exit 1
+          fi
+        '';
+        serviceConfig = {
+          Type = "simple";
+          User = "namecoin";
+          EnvironmentFile = cfg.userFile;
+          ExecStart = "${pkgs.altcoins.namecoind}/bin/namecoind -conf=${namecoinConf} -rpcuser=\${USER} -rpcpassword=\${PASSWORD} -printtoconsole";
+          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+          ExecStop = "${pkgs.coreutils}/bin/kill -KILL $MAINPID";
+          StandardOutput = "null";
+          Nice = "10";
+        };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/ntpd.nix b/nixos/modules/services/networking/ntpd.nix
index a9183577d0a2..5256fc9bc071 100644
--- a/nixos/modules/services/networking/ntpd.nix
+++ b/nixos/modules/services/networking/ntpd.nix
@@ -6,6 +6,8 @@ let
 
   inherit (pkgs) ntp;
 
+  cfg = config.services.ntp;
+
   stateDir = "/var/lib/ntp";
 
   ntpUser = "ntp";
@@ -16,10 +18,10 @@ let
     restrict 127.0.0.1
     restrict -6 ::1
 
-    ${toString (map (server: "server " + server + " iburst\n") config.services.ntp.servers)}
+    ${toString (map (server: "server " + server + " iburst\n") cfg.servers)}
   '';
 
-  ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup";
+  ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup ${toString cfg.extraFlags}";
 
 in
 
@@ -51,6 +53,12 @@ in
         '';
       };
 
+      extraFlags = mkOption {
+        type = types.listOf types.str;
+        description = "Extra flags passed to the ntpd command.";
+        default = [];
+      };
+
     };
 
   };
diff --git a/nixos/modules/services/networking/openvpn.nix b/nixos/modules/services/networking/openvpn.nix
index 9dc88e61865d..a96888dec864 100644
--- a/nixos/modules/services/networking/openvpn.nix
+++ b/nixos/modules/services/networking/openvpn.nix
@@ -67,12 +67,6 @@ in
 
   options = {
 
-    /* !!! Obsolete. */
-    services.openvpn.enable = mkOption {
-      default = true;
-      description = "Whether to enable OpenVPN.";
-    };
-
     services.openvpn.servers = mkOption {
       default = {};
 
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 4c7e4d8d088c..5baea4bc6aea 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -214,7 +214,7 @@ in
 
     };
 
-    users.extraUsers = mkOption {
+    users.users = mkOption {
       options = [ userOptions ];
     };
 
diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix
index 02572c1e27d2..d5accfef1cb5 100644
--- a/nixos/modules/services/networking/syncthing.nix
+++ b/nixos/modules/services/networking/syncthing.nix
@@ -36,9 +36,7 @@ in
       dataDir = mkOption {
         default = "/var/lib/syncthing";
         description = ''
-          Path where the `.syncthing` (settings and keys) and `Sync`
-          (your synced files) directories will exist. This can be your home
-          directory.
+          Path where the settings and keys will exist.
         '';
       };
 
@@ -57,18 +55,12 @@ in
         after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
         environment.STNORESTART = "placeholder";  # do not self-restart
-        environment.HOME = "${cfg.dataDir}";
         serviceConfig = {
           User = "${cfg.user}";
           PermissionsStartOnly = true;
           Restart = "always";
-          ExecStart = "${pkgs.syncthing}/bin/syncthing -home=${cfg.dataDir}/.syncthing";
+          ExecStart = "${pkgs.syncthing}/bin/syncthing -no-browser -home=${cfg.dataDir}";
         };
-        preStart = ''
-          mkdir -p ${cfg.dataDir}
-          chown ${cfg.user} ${cfg.dataDir}
-        '';
-
       };
 
     environment.systemPackages = [ pkgs.syncthing ];
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index 64620bf16041..3436bd01d848 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -37,6 +37,12 @@ in {
       type = types.bool;
     };
 
+    package = mkOption {
+      description = "Elasticsearch package to use.";
+      default = pkgs.elasticsearch;
+      type = types.package;
+    };
+
     host = mkOption {
       description = "Elasticsearch listen address.";
       default = "127.0.0.1";
@@ -123,7 +129,7 @@ in {
       after = [ "network-interfaces.target" ];
       environment = { ES_HOME = cfg.dataDir; };
       serviceConfig = {
-        ExecStart = "${pkgs.elasticsearch}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}";
+        ExecStart = "${cfg.package}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}";
         User = "elasticsearch";
         PermissionsStartOnly = true;
       };
@@ -142,7 +148,7 @@ in {
       '';
     };
 
-    environment.systemPackages = [ pkgs.elasticsearch ];
+    environment.systemPackages = [ cfg.package ];
 
     users.extraUsers = singleton {
       name = "elasticsearch";
diff --git a/nixos/modules/services/torrent/deluge.nix b/nixos/modules/services/torrent/deluge.nix
index 00df4042d890..becd57055d41 100644
--- a/nixos/modules/services/torrent/deluge.nix
+++ b/nixos/modules/services/torrent/deluge.nix
@@ -36,6 +36,8 @@ in {
       wantedBy = [ "multi-user.target" ];
       path = [ pkgs.pythonPackages.deluge ];
       serviceConfig.ExecStart = "${pkgs.pythonPackages.deluge}/bin/deluged -d";
+      # To prevent "Quit & shutdown daemon" from working; we want systemd to manage it!
+      serviceConfig.Restart = "on-success";
       serviceConfig.User = "deluge";
       serviceConfig.Group = "deluge";
     };
diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
index 8884569c7bc8..921f774bcaa0 100644
--- a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix
@@ -5,8 +5,8 @@ with lib;
 
 let
 
-  version = "4.2";
-  fullversion = "${version}.2";
+  version = "4.3";
+  fullversion = "${version}";
 
   # Our bare-bones wp-config.php file using the above settings
   wordpressConfig = pkgs.writeText "wp-config.php" ''
@@ -40,6 +40,8 @@ let
     RewriteRule ^(.*\.php)$ $1 [L]
     RewriteRule . index.php [L]
     </IfModule>
+
+    ${config.extraHtaccess}
   '';
 
   # WP translation can be found here:
@@ -72,7 +74,7 @@ let
       owner = "WordPress";
       repo = "WordPress";
       rev = "${fullversion}";
-      sha256 = "0gq1j9b0d0rykql3jzdb2yn4adj0rrcsvqrmj3dzx11ir57ilsgc";
+      sha256 = "0sz5jjhjpwqis8336gyq9a77cr4sf8zahd1y4pzmpvpzn9cn503y";
     };
     installPhase = ''
       mkdir -p $out
@@ -220,7 +222,18 @@ in
         settings, see <link xlink:href='http://codex.wordpress.org/Editing_wp-config.php'/>.
       '';
     };
-  }; 
+    extraHtaccess = mkOption {
+      default = "";
+      example =
+        ''
+          php_value upload_max_filesize 20M
+          php_value post_max_size 20M
+        '';
+      description = ''
+        Any additional text to be appended to Wordpress's .htaccess file.
+      '';
+    };
+  };
 
   documentRoot = wordpressRoot;
 
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index fe50c182bfe5..25816446e999 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -8,9 +8,12 @@ let
   configFile = pkgs.writeText "nginx.conf" ''
     user ${cfg.user} ${cfg.group};
     daemon off;
+
     ${cfg.config}
+
     ${optionalString (cfg.httpConfig != "") ''
     http {
+      include ${cfg.package}/conf/mime.types;
       ${cfg.httpConfig}
     }
     ''}
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 507c2d2da139..fdee5fbc6c5b 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -99,7 +99,6 @@ in {
     networking.networkmanager.enable = mkDefault true;
     services.upower.enable = config.powerManagement.enable;
     hardware.bluetooth.enable = mkDefault true;
-    services.xserver.displayManager.desktopManagerHandlesLidAndPower = false; # true doesn't make sense here, GNOME just doesn't handle it anymore
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/kodi.nix b/nixos/modules/services/x11/desktop-managers/kodi.nix
index 1e30308a5139..de00ff93b17c 100644
--- a/nixos/modules/services/x11/desktop-managers/kodi.nix
+++ b/nixos/modules/services/x11/desktop-managers/kodi.nix
@@ -28,4 +28,4 @@ in
 
     environment.systemPackages = [ pkgs.kodi ];
   };
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 7e05cd84be64..fc0803f2acaf 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -62,7 +62,7 @@ let
         if [ -z "$_INHIBITION_LOCK_TAKEN" ]; then
           export _INHIBITION_LOCK_TAKEN=1
           if ! ${config.systemd.package}/bin/loginctl show-session $XDG_SESSION_ID | grep -q '^RemoteHost='; then
-            exec ${config.systemd.package}/bin/systemd-inhibit --what=handle-lid-switch:handle-power-key --why="See NixOS configuration option 'services.xserver.displayManager.desktopManagerHandlesLidAndPower' for more information." "$0" "$sessionType"
+            exec ${config.systemd.package}/bin/systemd-inhibit --what=handle-lid-switch:handle-power-key --why="Desktop environment handles power events" "$0" "$sessionType"
           fi
         fi
 
@@ -161,7 +161,11 @@ let
       exit 0
     '';
 
-  mkDesktops = names: pkgs.runCommand "desktops" {}
+  mkDesktops = names: pkgs.runCommand "desktops"
+    { # trivial derivation
+      preferLocalBuild = true;
+      allowSubstitutes = false;
+    }
     ''
       mkdir -p $out
       ${concatMapStrings (n: ''
@@ -225,7 +229,7 @@ in
 
       desktopManagerHandlesLidAndPower = mkOption {
         type = types.bool;
-        default = true;
+        default = false;
         description = ''
           Whether the display manager should prevent systemd from handling
           lid and power events. This is normally handled by the desktop
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index b9808f1ffa69..887b6f88a741 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -23,6 +23,10 @@ in
         <emphasis>GDM is very experimental and may render system unusable.</emphasis>
       '';
 
+      debug = mkEnableOption ''
+        debugging messages in GDM
+      '';
+
       autoLogin = mkOption {
         default = {};
         description = ''
@@ -35,7 +39,7 @@ in
               type = types.bool;
               default = false;
               description = ''
-                Automatically log in as the sepecified <option>auto.user</option>.
+                Automatically log in as the sepecified <option>autoLogin.user</option>.
               '';
             };
 
@@ -68,6 +72,12 @@ in
 
   config = mkIf cfg.gdm.enable {
 
+    assertions = [
+      { assertion = cfg.gdm.autoLogin.enable -> cfg.gdm.autoLogin.user != null;
+        message = "GDM auto-login requires services.xserver.displayManager.gdm.autoLogin.user to be set";
+      }
+    ];
+
     services.xserver.displayManager.slim.enable = false;
 
     users.extraUsers.gdm =
@@ -102,13 +112,21 @@ in
 
     programs.dconf.profiles.gdm = "${gdm}/share/dconf/profile/gdm";
 
+    # Use AutomaticLogin if delay is zero, because it's immediate.
+    # Otherwise with TimedLogin with zero seconds the prompt is still
+    # presented and there's a little delay.
     environment.etc."gdm/custom.conf".text = ''
       [daemon]
-      ${optionalString cfg.gdm.autoLogin.enable ''
-      TimedLoginEnable=true
-      TimedLogin=${cfg.gdm.autoLogin.user}
-      TimedLoginDelay=${toString cfg.gdm.autoLogin.delay}
-      ''}
+      ${optionalString cfg.gdm.autoLogin.enable (
+        if cfg.gdm.autoLogin.delay > 0 then ''
+          TimedLoginEnable=true
+          TimedLogin=${cfg.gdm.autoLogin.user}
+          TimedLoginDelay=${toString cfg.gdm.autoLogin.delay}
+        '' else ''
+          AutomaticLoginEnable=true
+          AutomaticLogin=${cfg.gdm.autoLogin.user}
+        '')
+      }
 
       [security]
 
@@ -119,6 +137,7 @@ in
       [chooser]
 
       [debug]
+      ${optionalString cfg.gdm.debug "Enable=true"}
     '';
 
     # GDM LFS PAM modules, adapted somehow to NixOS
diff --git a/nixos/modules/services/x11/redshift.nix b/nixos/modules/services/x11/redshift.nix
index 4f39e05f0f8d..ffae22d2d670 100644
--- a/nixos/modules/services/x11/redshift.nix
+++ b/nixos/modules/services/x11/redshift.nix
@@ -1,58 +1,90 @@
 { config, lib, pkgs, ... }:
+
 with lib;
+
 let
+
   cfg = config.services.redshift;
 
 in {
-  options = {
-    services.redshift.enable = mkOption {
+
+  options.services.redshift = {
+    enable = mkOption {
       type = types.bool;
       default = false;
       example = true;
-      description = "Enable Redshift to change your screen's colour temperature depending on the time of day";
+      description = ''
+        Enable Redshift to change your screen's colour temperature depending on
+        the time of day.
+      '';
     };
 
-    services.redshift.latitude = mkOption {
-      description = "Your current latitude";
+    latitude = mkOption {
       type = types.str;
+      description = ''
+        Your current latitude.
+      '';
     };
 
-    services.redshift.longitude = mkOption {
-      description = "Your current longitude";
+    longitude = mkOption {
       type = types.str;
+      description = ''
+        Your current longitude.
+      '';
     };
 
-    services.redshift.temperature = {
+    temperature = {
       day = mkOption {
-        description = "Colour temperature to use during day time";
-        default = 5500;
         type = types.int;
+        default = 5500;
+        description = ''
+          Colour temperature to use during the day.
+        '';
       };
       night = mkOption {
-        description = "Colour temperature to use during night time";
-        default = 3700;
         type = types.int;
+        default = 3700;
+        description = ''
+          Colour temperature to use at night.
+        '';
       };
     };
 
-    services.redshift.brightness = {
+    brightness = {
       day = mkOption {
-        description = "Screen brightness to apply during the day (between 0.1 and 1.0)";
-        default = "1";
         type = types.str;
+        default = "1";
+        description = ''
+          Screen brightness to apply during the day,
+          between <literal>0.1</literal> and <literal>1.0</literal>.
+        '';
       };
       night = mkOption {
-        description = "Screen brightness to apply during the night (between 0.1 and 1.0)";
-        default = "1";
         type = types.str;
+        default = "1";
+        description = ''
+          Screen brightness to apply during the night,
+          between <literal>0.1</literal> and <literal>1.0</literal>.
+        '';
       };
     };
 
-    services.redshift.extraOptions = mkOption {
+    package = mkOption {
+      type = types.package;
+      default = pkgs.redshift;
+      description = ''
+        redshift derivation to use.
+      '';
+    };
+
+    extraOptions = mkOption {
       type = types.listOf types.str;
       default = [];
       example = [ "-v" "-m randr" ];
-      description = "Additional command-line arguments to pass to the redshift(1) command";
+      description = ''
+        Additional command-line arguments to pass to
+        <command>redshift</command>.
+      '';
     };
   };
 
@@ -63,7 +95,7 @@ in {
       after = [ "display-manager.service" ];
       wantedBy = [ "graphical.target" ];
       serviceConfig.ExecStart = ''
-        ${pkgs.redshift}/bin/redshift \
+        ${cfg.package}/bin/redshift \
           -l ${cfg.latitude}:${cfg.longitude} \
           -t ${toString cfg.temperature.day}:${toString cfg.temperature.night} \
           -b ${toString cfg.brightness.day}:${toString cfg.brightness.night} \
@@ -73,4 +105,5 @@ in {
       serviceConfig.Restart = "always";
     };
   };
+
 }
diff --git a/nixos/modules/services/x11/window-managers/wmii.nix b/nixos/modules/services/x11/window-managers/wmii.nix
index 75f6fdfe3bc4..e6f534a1be66 100644
--- a/nixos/modules/services/x11/window-managers/wmii.nix
+++ b/nixos/modules/services/x11/window-managers/wmii.nix
@@ -1,47 +1,43 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
+{ config, lib, pkgs, options, modulesPath }:
 
 let
-
+  inherit (lib) mkOption mkIf singleton;
   cfg = config.services.xserver.windowManager.wmii;
-
+  wmii = pkgs.wmii_hg;
 in
-
 {
   options = {
-
     services.xserver.windowManager.wmii.enable = mkOption {
       default = false;
       example = true;
       description = "Enable the wmii window manager.";
     };
-
   };
 
   config = mkIf cfg.enable {
-
     services.xserver.windowManager.session = singleton
       # stop wmii by
       #   $wmiir xwrite /ctl quit
       # this will cause wmii exiting with exit code 0
+      # (or "mod+a quit", which is bound to do the same thing in wmiirc
+      # by default)
       #
       # why this loop?
       # wmii crashes once a month here. That doesn't matter that much
-      # wmii can recover very well. However without loop the x session terminates and then your workspace setup is
-      # lost and all applications running on X will terminate.
+      # wmii can recover very well. However without loop the X session
+      # terminates and then your workspace setup is lost and all
+      # applications running on X will terminate.
       # Another use case is kill -9 wmii; after rotating screen.
-      # Note: we don't like kill for that purpose. But it works (-> subject "wmii and xrandr" on mailinglist)
+      # Note: we don't like kill for that purpose. But it works (->
+      # subject "wmii and xrandr" on mailinglist)
       { name = "wmii";
         start = ''
           while :; do
-            ${pkgs.wmiiSnap}/bin/wmii && break
+            ${wmii}/bin/wmii && break
           done
         '';
       };
 
-    environment.systemPackages = [ pkgs.wmiiSnap ];
-
+    environment.systemPackages = [ wmii ];
   };
-
 }
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 1ec098fded6e..3348e8d0582c 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 = {
-    nouveau       = { modules = [ pkgs.xf86_video_nouveau ]; };
     unichrome    = { modules = [ pkgs.xorgVideoUnichrome ]; };
     virtualbox   = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; };
     ati = { modules = [ pkgs.xorg.xf86videoati pkgs.xorg.glamoregl ]; };
diff --git a/nixos/modules/system/boot/modprobe.nix b/nixos/modules/system/boot/modprobe.nix
index c49380899664..9bb10eac9880 100644
--- a/nixos/modules/system/boot/modprobe.nix
+++ b/nixos/modules/system/boot/modprobe.nix
@@ -85,11 +85,7 @@ with lib;
         '')}
         ${config.boot.extraModprobeConfig}
       '';
-    environment.etc."modprobe.d/usb-load-ehci-first.conf".text =
-      ''
-        softdep uhci_hcd pre: ehci_hcd
-        softdep ohci_hcd pre: ehci_hcd
-      '';
+    environment.etc."modprobe.d/debian.conf".source = pkgs.kmod-debian-aliases;
 
     environment.systemPackages = [ config.system.sbin.modprobe pkgs.kmod ];
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 893861a2eed2..f782eca3f647 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -241,6 +241,9 @@ let
           };
           symlink = "/etc/modprobe.d/ubuntu.conf";
         }
+        { object = pkgs.kmod-debian-aliases;
+          symlink = "/etc/modprobe.d/debian.conf";
+        }
       ];
   };
 
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 05369da4f16b..4976dfe8eea4 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -643,6 +643,10 @@ in
         if ! [ -e /etc/machine-id ]; then
           ${systemd}/bin/systemd-machine-id-setup
         fi
+
+        # Keep a persistent journal. Note that systemd-tmpfiles will
+        # set proper ownership/permissions.
+        mkdir -m 0700 -p /var/log/journal
       '';
 
     users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 59f486ff78b7..8d12c5a57fd9 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -12,6 +12,12 @@ let
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
     su = "${pkgs.shadow.su}/bin/su";
     inherit (pkgs) utillinux;
+
+    postInstall = ''
+      t=$out/etc/bash_completion.d
+      mkdir -p $t
+      cp ${./nixos-container-completion.sh} $t/nixos-container
+    '';
   };
 
   # The container's init script, a small wrapper around the regular
@@ -299,7 +305,7 @@ in
             ''
               #! ${pkgs.stdenv.shell} -e
               ${nixos-container}/bin/nixos-container run "$INSTANCE" -- \
-                bash --login -c "/nix/var/nix/profiles/system/bin/switch-to-configuration test"
+                bash --login -c "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/bin/switch-to-configuration test"
             '';
 
           SyslogIdentifier = "container %i";
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index 2339cf7c6490..ba078cc0a11f 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -43,6 +43,17 @@ in
             in future.  So set this option explicitly to false if you wish.
           '';
       };
+    storageDriver =
+      mkOption {
+        type = types.enum ["aufs" "btrfs" "devicemapper" "overlay" "zfs"];
+        description =
+          ''
+            This option determines which Docker storage driver to use.
+            It is required but lacks a default value as its most
+            suitable value will depend the filesystems available on the
+            host.
+          '';
+      };
     extraOptions =
       mkOption {
         type = types.separatedString " ";
@@ -85,7 +96,7 @@ in
         after = [ "network.target" "docker.socket" ];
         requires = [ "docker.socket" ];
         serviceConfig = {
-          ExecStart = "${pkgs.docker}/bin/docker --daemon=true --host=fd:// --group=docker ${cfg.extraOptions}";
+          ExecStart = "${pkgs.docker}/bin/docker daemon --host=fd:// --group=docker --storage-driver=${cfg.storageDriver} ${cfg.extraOptions}";
           #  I'm not sure if that limits aren't too high, but it's what
           #  goes in config bundled with docker itself
           LimitNOFILE = 1048576;
@@ -111,7 +122,7 @@ in
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
         serviceConfig = {
-          ExecStart = "${pkgs.docker}/bin/docker --daemon=true --group=docker ${cfg.extraOptions}";
+          ExecStart = "${pkgs.docker}/bin/docker daemon --group=docker --storage-driver=${cfg.storageDriver} ${cfg.extraOptions}";
           #  I'm not sure if that limits aren't too high, but it's what
           #  goes in config bundled with docker itself
           LimitNOFILE = 1048576;
diff --git a/nixos/modules/virtualisation/lxd.nix b/nixos/modules/virtualisation/lxd.nix
new file mode 100644
index 000000000000..488153334bc1
--- /dev/null
+++ b/nixos/modules/virtualisation/lxd.nix
@@ -0,0 +1,64 @@
+# Systemd services for lxd.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.virtualisation.lxd;
+
+in
+
+{
+  ###### interface
+
+  options = {
+
+    virtualisation.lxd.enable =
+      mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            This option enables lxd, a daemon that manages
+            containers. Users in the "lxd" group can interact with
+            the daemon (e.g. to start or stop containers) using the
+            <command>lxc</command> command line tool, among others.
+          '';
+      };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages =
+      [ pkgs.lxd ];
+
+    systemd.services.lxd =
+      { description = "LXD Container Management Daemon";
+
+        wantedBy = [ "multi-user.target" ];
+        after = [ "systemd-udev-settle.service" ];
+
+        # TODO(wkennington): Add lvm2 and thin-provisioning-tools
+        path = with pkgs; [ acl rsync gnutar xz btrfsProgs ];
+
+        serviceConfig.ExecStart = "@${pkgs.lxd}/bin/lxd lxd --syslog --group lxd";
+        serviceConfig.Type = "simple";
+        serviceConfig.KillMode = "process"; # when stopping, leave the containers alone
+      };
+
+    users.extraGroups.lxd.gid = config.ids.gids.lxd;
+
+    users.extraUsers.root = {
+      subUidRanges = [ { startUid = 1000000; count = 65536; } ];
+      subGidRanges = [ { startGid = 1000000; count = 65536; } ];
+    };
+
+  };
+
+}
diff --git a/nixos/modules/virtualisation/nixos-container-completion.sh b/nixos/modules/virtualisation/nixos-container-completion.sh
new file mode 100644
index 000000000000..0fe8ab811a17
--- /dev/null
+++ b/nixos/modules/virtualisation/nixos-container-completion.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+_nixos-container() {
+    local cur prev opts
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+    opts="list create destroy start stop status update login root-login run show-ip show-host-key"
+    startstop_opts=$(nixos-container list)
+    update_opts="--config"
+
+    if [[ "$prev" == "nixos-container" ]]
+    then
+        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+        return 0
+    fi
+
+    if [[ $(echo "$opts" | grep "$prev") ]]
+    then
+        if [[ "$prev" == "start" || "$prev" == "stop" ]]
+        then
+            COMPREPLY=( $(compgen -W "${startstop_opts}" -- ${cur}) )
+            return 0
+        elif [[ "$prev" == "update" ]]
+        then
+            COMPREPLY=( $(compgen -W "${update_opts}" -- ${cur}) )
+            return 0
+        fi
+    fi
+}
+
+complete -F _nixos-container nixos-container
+
diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl
index f1d9e64ee38f..004385f728c6 100644
--- a/nixos/modules/virtualisation/nixos-container.pl
+++ b/nixos/modules/virtualisation/nixos-container.pl
@@ -290,7 +290,8 @@ elsif ($action eq "show-ip") {
 }
 
 elsif ($action eq "show-host-key") {
-    my $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub";
+    my $fn = "$root/etc/ssh/ssh_host_ed25519_key.pub";
+    $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub" unless -e $fn;
     exit 1 if ! -f $fn;
     print read_file($fn);
 }
diff --git a/nixos/modules/virtualisation/parallels-guest.nix b/nixos/modules/virtualisation/parallels-guest.nix
index 2f40283b3e1d..204ab0b0df67 100644
--- a/nixos/modules/virtualisation/parallels-guest.nix
+++ b/nixos/modules/virtualisation/parallels-guest.nix
@@ -17,7 +17,7 @@ in
         type = types.bool;
         default = false;
         description = ''
-          This enables Parallel Tools for Linux guests, along with provided
+          This enables Parallels Tools for Linux guests, along with provided
           video, mouse and other hardware drivers.
         '';
       };
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index 8232f6e50dfc..767a8c339a3e 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -109,7 +109,8 @@ in {
         VBoxManage createvm --name "$vmName" --register \
           --ostype ${if pkgs.stdenv.system == "x86_64-linux" then "Linux26_64" else "Linux26"}
         VBoxManage modifyvm "$vmName" \
-          --memory 1536 --acpi on --vram 10 \
+          --memory 1536 --acpi on --vram 32 \
+          ${optionalString (pkgs.stdenv.system == "i686-linux") "--pae on"} \
           --nictype1 virtio --nic1 nat \
           --audiocontroller ac97 --audio alsa \
           --rtcuseutc on \
@@ -128,6 +129,6 @@ in {
     boot.loader.grub.version = 2;
     boot.loader.grub.device = "/dev/sda";
   
-    services.virtualboxGuest.enable = true;
+    virtualisation.virtualbox.guest.enable = true;
   };
 }
diff --git a/nixos/release.nix b/nixos/release.nix
index 2dbc35c7d7bf..4492ee4046ea 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -226,6 +226,7 @@ in rec {
   tests.fleet = hydraJob (import tests/fleet.nix { system = "x86_64-linux"; });
   #tests.gitlab = callTest tests/gitlab.nix {};
   tests.gnome3 = callTest tests/gnome3.nix {};
+  tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {};
   tests.i3wm = callTest tests/i3wm.nix {};
   tests.installer.grub1 = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).grub1.test);
   tests.installer.lvm = forAllSystems (system: hydraJob (import tests/installer.nix { inherit system; }).lvm.test);
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
index 3624131b364e..213dd4ca43b3 100644
--- a/nixos/tests/chromium.nix
+++ b/nixos/tests/chromium.nix
@@ -44,6 +44,8 @@ import ./make-test.nix (
           search --onlyvisible --name "startup done"
           windowfocus --sync
           windowactivate --sync
+        ''}");
+        $machine->execute("${xdo "new-window" ''
           key Ctrl+n
         ''}");
       });
@@ -55,6 +57,8 @@ import ./make-test.nix (
           search --onlyvisible --name "new tab"
           windowfocus --sync
           windowactivate --sync
+        ''}");
+        $machine->execute("${xdo "close-window" ''
           key Ctrl+w
         ''}");
         for (1..20) {
@@ -155,6 +159,8 @@ import ./make-test.nix (
           $machine->succeed("${xdo "submit-url" ''
             search --sync --onlyvisible --name "sandbox status"
             windowfocus --sync
+          ''}");
+          $machine->succeed("${xdo "submit-url" ''
             key --delay 1000 Ctrl+a Ctrl+c
           ''}");
 
diff --git a/nixos/tests/docker.nix b/nixos/tests/docker.nix
index babb2b8e00eb..034dcb04adfd 100644
--- a/nixos/tests/docker.nix
+++ b/nixos/tests/docker.nix
@@ -11,6 +11,7 @@ import ./make-test.nix ({ pkgs, ...} : {
       { config, pkgs, ... }:
         {
           virtualisation.docker.enable = true;
+          virtualisation.docker.storageDriver = "overlay";
         };
     };
 
diff --git a/nixos/tests/etcd.nix b/nixos/tests/etcd.nix
index 8a4e7fffce0e..bac4ec6a918b 100644
--- a/nixos/tests/etcd.nix
+++ b/nixos/tests/etcd.nix
@@ -82,7 +82,7 @@ import ./make-test.nix ({ pkgs, ... } : {
     subtest "single node", sub {
       $simple->start();
       $simple->waitForUnit("etcd.service");
-      $simple->succeed("etcdctl set /foo/bar 'Hello world'");
+      $simple->waitUntilSucceeds("etcdctl set /foo/bar 'Hello world'");
       $simple->waitUntilSucceeds("etcdctl get /foo/bar | grep 'Hello world'");
     };
 
@@ -91,7 +91,7 @@ import ./make-test.nix ({ pkgs, ... } : {
       $node2->start();
       $node1->waitForUnit("etcd.service");
       $node2->waitForUnit("etcd.service");
-      $node1->succeed("etcdctl set /foo/bar 'Hello world'");
+      $node1->waitUntilSucceeds("etcdctl set /foo/bar 'Hello world'");
       $node2->waitUntilSucceeds("etcdctl get /foo/bar | grep 'Hello world'");
       $node1->shutdown();
       $node2->shutdown();
@@ -104,7 +104,7 @@ import ./make-test.nix ({ pkgs, ... } : {
       $discovery2->start();
       $discovery1->waitForUnit("etcd.service");
       $discovery2->waitForUnit("etcd.service");
-      $discovery1->succeed("etcdctl set /foo/bar 'Hello world'");
+      $discovery1->waitUntilSucceeds("etcdctl set /foo/bar 'Hello world'");
       $discovery2->waitUntilSucceeds("etcdctl get /foo/bar | grep 'Hello world'");
     };
   '';
diff --git a/nixos/tests/gnome3-gdm.nix b/nixos/tests/gnome3-gdm.nix
new file mode 100644
index 000000000000..1c07ddf79c2e
--- /dev/null
+++ b/nixos/tests/gnome3-gdm.nix
@@ -0,0 +1,39 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "gnome3-gdm";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ lethalman ];
+  };
+
+  machine =
+    { config, pkgs, ... }:
+
+    { imports = [ ./common/user-account.nix ];
+
+      services.xserver.enable = true;
+
+      services.xserver.displayManager.gdm = {
+        enable = true;
+        autoLogin = {
+          enable = true;
+          user = "alice";
+        };
+      };
+      services.xserver.desktopManager.gnome3.enable = true;
+
+      virtualisation.memorySize = 512;
+    };
+
+  testScript =
+    ''
+      $machine->waitForX;
+      $machine->sleep(15);
+
+      # Check that logging in has given the user ownership of devices.
+      $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
+
+      $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'");
+      $machine->waitForWindow(qr/Terminal/);
+      $machine->sleep(20);
+      $machine->screenshot("screen");
+    '';
+})
diff --git a/nixos/tests/gnome3.nix b/nixos/tests/gnome3.nix
index 3425ca09951c..f5e0159f1c7d 100644
--- a/nixos/tests/gnome3.nix
+++ b/nixos/tests/gnome3.nix
@@ -11,13 +11,8 @@ import ./make-test.nix ({ pkgs, ...} : {
 
       services.xserver.enable = true;
 
-      services.xserver.displayManager.gdm = {
-        enable = true;
-        autoLogin = {
-          enable = true;
-          user = "alice";
-        };
-      };
+      services.xserver.displayManager.auto.enable = true;
+      services.xserver.displayManager.auto.user = "alice";
       services.xserver.desktopManager.gnome3.enable = true;
 
       virtualisation.memorySize = 512;
@@ -26,7 +21,7 @@ import ./make-test.nix ({ pkgs, ...} : {
   testScript =
     ''
       $machine->waitForX;
-      $machine->sleep(60);
+      $machine->sleep(15);
 
       # Check that logging in has given the user ownership of devices.
       $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
diff --git a/nixos/tests/logstash.nix b/nixos/tests/logstash.nix
index 317ea063e17c..edece352cafe 100644
--- a/nixos/tests/logstash.nix
+++ b/nixos/tests/logstash.nix
@@ -19,8 +19,8 @@ import ./make-test.nix ({ pkgs, ...} : {
                 exec { command => "echo dragons" interval => 1 type => "test" }
               '';
               filterConfig = ''
-                if [type] == "test" {
-                  grep { match => ["message", "flowers"] drop => true }
+                if [message] =~ /dragons/ {
+                  drop {}
                 }
               '';
               outputConfig = ''
diff --git a/nixos/tests/nfs.nix b/nixos/tests/nfs.nix
index 963776dd2acf..24f6e0f2ed95 100644
--- a/nixos/tests/nfs.nix
+++ b/nixos/tests/nfs.nix
@@ -6,7 +6,7 @@ let
     { config, pkgs, ... }:
     { fileSystems = pkgs.lib.mkVMOverride
         [ { mountPoint = "/data";
-            device = "server:${if version == 4 then "/" else "/data"}";
+            device = "server:/data";
             fsType = "nfs";
             options = "vers=${toString version}";
           }
diff --git a/nixos/tests/proxy.nix b/nixos/tests/proxy.nix
index b43ce1b8e680..3fee1d325384 100644
--- a/nixos/tests/proxy.nix
+++ b/nixos/tests/proxy.nix
@@ -67,6 +67,7 @@ in
       $proxy->waitForUnit("httpd");
       $backend1->waitForUnit("httpd");
       $backend2->waitForUnit("httpd");
+      $client->waitForUnit("network.target");
 
       # With the back-ends up, the proxy should work.
       $client->succeed("curl --fail http://proxy/");
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index 83a8b2835dc2..1a5a6f7b5bbc 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -1,26 +1,41 @@
-import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
-
-  debug = false;
-
-  testVMConfig = vmName: attrs: { config, pkgs, ... }: {
-    boot.kernelParams = let
-      miniInit = ''
-        #!${pkgs.stdenv.shell} -xe
-        export PATH="${pkgs.coreutils}/bin:${pkgs.utillinux}/bin"
-
-        ${pkgs.linuxPackages.virtualboxGuestAdditions}/bin/VBoxService
-        ${(attrs.vmScript or (const "")) pkgs}
+{ debug ? false, ... } @ args:
 
-        i=0
-        while [ ! -e /mnt-root/shutdown ]; do
-          sleep 10
-          i=$(($i + 10))
-          [ $i -le 120 ] || fail
-        done
+import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
 
-        rm -f /mnt-root/boot-done /mnt-root/shutdown
-      '';
-    in [
+  testVMConfig = vmName: attrs: { config, pkgs, ... }: let
+    guestAdditions = pkgs.linuxPackages.virtualboxGuestAdditions;
+
+    miniInit = ''
+      #!${pkgs.stdenv.shell} -xe
+      export PATH="${pkgs.coreutils}/bin:${pkgs.utillinux}/bin"
+
+      mkdir -p /etc/dbus-1 /var/run/dbus
+      cat > /etc/passwd <<EOF
+      root:x:0:0::/root:/bin/false
+      messagebus:x:1:1::/var/run/dbus:/bin/false
+      EOF
+      cat > /etc/group <<EOF
+      root:x:0:
+      messagebus:x:1:
+      EOF
+      cp -v "${pkgs.dbus.daemon}/etc/dbus-1/system.conf" \
+        /etc/dbus-1/system.conf
+      "${pkgs.dbus.daemon}/bin/dbus-daemon" --fork --system
+
+      ${guestAdditions}/bin/VBoxService
+      ${(attrs.vmScript or (const "")) pkgs}
+
+      i=0
+      while [ ! -e /mnt-root/shutdown ]; do
+        sleep 10
+        i=$(($i + 10))
+        [ $i -le 120 ] || fail
+      done
+
+      rm -f /mnt-root/boot-done /mnt-root/shutdown
+    '';
+  in {
+    boot.kernelParams = [
       "console=tty0" "console=ttyS0" "ignore_loglevel"
       "boot.trace" "panic=1" "boot.panic_on_fail"
       "init=${pkgs.writeScript "mini-init.sh" miniInit}"
@@ -39,7 +54,7 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
     ];
 
     boot.initrd.extraUtilsCommands = ''
-      copy_bin_and_libs "${pkgs.linuxPackages.virtualboxGuestAdditions}/bin/mount.vboxsf"
+      copy_bin_and_libs "${guestAdditions}/bin/mount.vboxsf"
       copy_bin_and_libs "${pkgs.utillinux}/bin/unshare"
       ${(attrs.extraUtilsCommands or (const "")) pkgs}
     '';
@@ -156,30 +171,26 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
     ];
   in {
     machine = {
-      systemd.sockets = listToAttrs (singleton {
-        name = "vboxtestlog-${name}";
-        value = {
-          description = "VirtualBox Test Machine Log Socket";
-          wantedBy = [ "sockets.target" ];
-          before = [ "multi-user.target" ];
-          socketConfig.ListenStream = "/run/virtualbox-log-${name}.sock";
-          socketConfig.Accept = true;
-        };
-      });
-
-      systemd.services = listToAttrs (singleton {
-        name = "vboxtestlog-${name}@";
-        value = {
-          description = "VirtualBox Test Machine Log";
-          serviceConfig.StandardInput = "socket";
-          serviceConfig.StandardOutput = "syslog";
-          serviceConfig.SyslogIdentifier = "GUEST-${name}";
-          serviceConfig.ExecStart = "${pkgs.coreutils}/bin/cat";
-        };
-      });
+      systemd.sockets."vboxtestlog-${name}" = {
+        description = "VirtualBox Test Machine Log Socket For ${name}";
+        wantedBy = [ "sockets.target" ];
+        before = [ "multi-user.target" ];
+        socketConfig.ListenStream = "/run/virtualbox-log-${name}.sock";
+        socketConfig.Accept = true;
+      };
+
+      systemd.services."vboxtestlog-${name}@" = {
+        description = "VirtualBox Test Machine Log For ${name}";
+        serviceConfig.StandardInput = "socket";
+        serviceConfig.StandardOutput = "syslog";
+        serviceConfig.SyslogIdentifier = "GUEST-${name}";
+        serviceConfig.ExecStart = "${pkgs.coreutils}/bin/cat";
+      };
     };
 
     testSubs = ''
+      my ${"$" + name}_sharepath = '${sharePath}';
+
       sub checkRunning_${name} {
         my $cmd = 'VBoxManage list runningvms | grep -q "^\"${name}\""';
         my ($status, $out) = $machine->execute(ru $cmd);
@@ -286,9 +297,15 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.lib; let
     echo "$otherIP reachable" | ${pkgs.netcat}/bin/netcat -clp 5678 || :
   '';
 
+  sysdDetectVirt = pkgs: ''
+    ${pkgs.systemd}/bin/systemd-detect-virt > /mnt-root/result
+  '';
+
   vboxVMs = mapAttrs createVM {
     simple = {};
 
+    detectvirt.vmScript = sysdDetectVirt;
+
     test1.vmFlags = hostonlyVMFlags;
     test1.vmScript = dhcpScript;
 
@@ -307,7 +324,7 @@ in {
       mkVMConf = name: val: val.machine // { key = "${name}-config"; };
       vmConfigs = mapAttrsToList mkVMConf vboxVMs;
     in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs;
-    virtualisation.memorySize = 768;
+    virtualisation.memorySize = 1024;
     virtualisation.virtualbox.host.enable = true;
     users.extraUsers.alice.extraGroups = let
       inherit (config.virtualisation.virtualbox.host) enableHardening;
@@ -372,6 +389,18 @@ in {
 
     destroyVM_simple;
 
+    subtest "systemd-detect-virt", sub {
+      createVM_detectvirt;
+      vbm("startvm detectvirt");
+      waitForStartup_detectvirt;
+      waitForVMBoot_detectvirt;
+      shutdownVM_detectvirt;
+      my $result = $machine->succeed("cat '$detectvirt_sharepath/result'");
+      chomp $result;
+      die "systemd-detect-virt returned \"$result\" instead of \"oracle\""
+        if $result ne "oracle";
+    };
+
     subtest "net-hostonlyif", sub {
       createVM_test1;
       createVM_test2;
@@ -403,4 +432,4 @@ in {
       destroyVM_test2;
     };
   '';
-})
+}) args