summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorRobin Gloster <mail@glob.in>2016-02-07 11:17:57 +0000
committerRobin Gloster <mail@glob.in>2016-02-07 11:17:57 +0000
commit9229e9c6563d88f1b9413ce128e022921089413f (patch)
treecc1ce2eda51dd7cebe7a75e342cfcaf88c45e2f5 /nixos
parent051662610104c2c57b89783084b9f31f5e978c71 (diff)
parent6205f17ea43fd74e4aff14a24a5734ec33415fd7 (diff)
downloadnixlib-9229e9c6563d88f1b9413ce128e022921089413f.tar
nixlib-9229e9c6563d88f1b9413ce128e022921089413f.tar.gz
nixlib-9229e9c6563d88f1b9413ce128e022921089413f.tar.bz2
nixlib-9229e9c6563d88f1b9413ce128e022921089413f.tar.lz
nixlib-9229e9c6563d88f1b9413ce128e022921089413f.tar.xz
nixlib-9229e9c6563d88f1b9413ce128e022921089413f.tar.zst
nixlib-9229e9c6563d88f1b9413ce128e022921089413f.zip
Merge remote-tracking branch 'upstream/master' into hardened-stdenv
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/config-file.xml2
-rw-r--r--nixos/doc/manual/man-nixos-generate-config.xml4
-rw-r--r--nixos/doc/manual/release-notes/rl-unstable.xml18
-rw-r--r--nixos/modules/config/zram.nix6
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix8
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl4
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh7
-rw-r--r--nixos/modules/module-list.nix8
-rw-r--r--nixos/modules/programs/ssh.nix3
-rw-r--r--nixos/modules/services/hardware/acpid.nix174
-rw-r--r--nixos/modules/services/hardware/udev.nix87
-rw-r--r--nixos/modules/services/mail/opensmtpd.nix21
-rw-r--r--nixos/modules/services/misc/sundtek.nix2
-rw-r--r--nixos/modules/services/networking/connman.nix6
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix13
-rw-r--r--nixos/modules/services/security/haka.nix156
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix8
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde4.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix10
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix3
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix2
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl2
-rw-r--r--nixos/modules/system/boot/initrd-network.nix178
-rw-r--r--nixos/modules/system/boot/initrd-ssh.nix124
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh4
-rw-r--r--nixos/modules/system/boot/stage-1.nix20
-rw-r--r--nixos/modules/tasks/filesystems.nix18
-rw-r--r--nixos/modules/tasks/network-interfaces.nix2
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix29
-rw-r--r--nixos/modules/virtualisation/amazon-init.nix23
-rw-r--r--nixos/modules/virtualisation/ec2-data.nix38
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix12
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/chromium.nix4
-rw-r--r--nixos/tests/ec2.nix12
-rw-r--r--nixos/tests/haka.nix24
-rw-r--r--nixos/tests/initrd-network.nix22
-rw-r--r--nixos/tests/misc.nix2
-rw-r--r--nixos/tests/nfs.nix2
40 files changed, 697 insertions, 370 deletions
diff --git a/nixos/doc/manual/configuration/config-file.xml b/nixos/doc/manual/configuration/config-file.xml
index b613c7f06cc8..9b240979273d 100644
--- a/nixos/doc/manual/configuration/config-file.xml
+++ b/nixos/doc/manual/configuration/config-file.xml
@@ -157,7 +157,7 @@ boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
 fileSystems."/boot" =
   { device = "/dev/sda1";
     fsType = "ext4";
-    options = "rw,data=ordered,relatime";
+    options = [ "rw" "data=ordered" "relatime" ];
   };
 </programlisting>
       </para>
diff --git a/nixos/doc/manual/man-nixos-generate-config.xml b/nixos/doc/manual/man-nixos-generate-config.xml
index e4fba4a40a97..140642bc9c9c 100644
--- a/nixos/doc/manual/man-nixos-generate-config.xml
+++ b/nixos/doc/manual/man-nixos-generate-config.xml
@@ -165,13 +165,13 @@ look like this:
   fileSystems."/" =
     { device = "/dev/disk/by-label/nixos";
       fsType = "ext3";
-      options = "rw,data=ordered,relatime";
+      options = [ "rw" "data=ordered" "relatime" ];
     };
 
   fileSystems."/boot" =
     { device = "/dev/sda1";
       fsType = "ext3";
-      options = "rw,errors=continue,user_xattr,acl,barrier=1,data=writeback,relatime";
+      options = [ "rw" "errors=continue" "user_xattr" "acl" "barrier=1" "data=writeback" "relatime" ];
     };
 
   swapDevices =
diff --git a/nixos/doc/manual/release-notes/rl-unstable.xml b/nixos/doc/manual/release-notes/rl-unstable.xml
index 6099b5218714..c814d61bcf4c 100644
--- a/nixos/doc/manual/release-notes/rl-unstable.xml
+++ b/nixos/doc/manual/release-notes/rl-unstable.xml
@@ -42,6 +42,7 @@ nixos.path = ./nixpkgs-unstable-2015-12-06/nixos;
   <itemizedlist>
     <listitem><para><literal>services/monitoring/longview.nix</literal></para></listitem>
     <listitem><para><literal>services/web-apps/pump.io.nix</literal></para></listitem>
+    <listitem><para><literal>services/security/haka.nix</literal></para></listitem>
   </itemizedlist>
 </para>
 
@@ -154,6 +155,23 @@ nginx.override {
     rights, new <literal>aliasFiles</literal> and <literal>mapFiles</literal>
     options and more.</para>
   </listitem>
+
+  <listitem>
+    <para>Filesystem options should now be configured as a list of strings, not
+    a comma-separated string. The old style will continue to work, but print a
+    warning, until the 16.09 release. An example of the new style:
+
+<programlisting>
+fileSystems."/example" = {
+  device = "/dev/sdc";
+  fsType = "btrfs";
+  options = [ "noatime" "compress=lzo" "space_cache" "autodefrag" ];
+};
+</programlisting>
+
+    </para>
+  </listitem>
+
 </itemizedlist>
 
 
diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix
index 22b74847f871..019932b04e8d 100644
--- a/nixos/modules/config/zram.nix
+++ b/nixos/modules/config/zram.nix
@@ -98,11 +98,9 @@ in
             script = ''
               set -u
               set -o pipefail
-
-              PATH=${pkgs.procps}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin
-
+              
               # Calculate memory to use for zram
-              totalmem=$(free | grep -e "^Mem:" | sed -e 's/^Mem: *//' -e 's/  *.*//')
+              totalmem=$(${pkgs.gnugrep}/bin/grep 'MemTotal: ' /proc/meminfo | ${pkgs.gawk}/bin/awk '{print $2}')
               mem=$(((totalmem * ${toString cfg.memoryPercent} / 100 / ${toString cfg.numDevices}) * 1024))
 
               echo $mem > /sys/class/block/${dev}/disksize
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 248b0f00283c..5702e2d9a1e5 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -249,7 +249,7 @@ in
 
     fileSystems."/" =
       { fsType = "tmpfs";
-        options = "mode=0755";
+        options = [ "mode=0755" ];
       };
 
     # Note that /dev/root is a symlink to the actual root device
@@ -266,20 +266,20 @@ in
     fileSystems."/nix/.ro-store" =
       { fsType = "squashfs";
         device = "/iso/nix-store.squashfs";
-        options = "loop";
+        options = [ "loop" ];
         neededForBoot = true;
       };
 
     fileSystems."/nix/.rw-store" =
       { fsType = "tmpfs";
-        options = "mode=0755";
+        options = [ "mode=0755" ];
         neededForBoot = true;
       };
 
     fileSystems."/nix/store" =
       { fsType = "unionfs-fuse";
         device = "unionfs";
-        options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro";
+        options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
       };
 
     boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" ];
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 2284eba07a2d..ec880e084726 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -349,7 +349,7 @@ foreach my $fs (read_file("/proc/self/mountinfo")) {
   fileSystems.\"$mountPoint\" =
     { device = \"$base$path\";
       fsType = \"none\";
-      options = \"bind\";
+      options = \[ \"bind\" \];
     };
 
 EOF
@@ -409,7 +409,7 @@ EOF
 
     if (scalar @extraOptions > 0) {
       $fileSystems .= <<EOF;
-      options = \"${\join ",", uniq(@extraOptions)}\";
+      options = \[ ${\join " ", map { "\"" . $_ . "\"" } uniq(@extraOptions)} \];
 EOF
     }
 
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 105d1cd16252..e0e79f63fab7 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -149,10 +149,11 @@ nixBuild() {
                 local j="$1"; shift 1
                 instArgs+=("$i" "$j")
                 ;;
-              -I)
-                # We don't want this in buildArgs
+              -I) # We don't want this in buildArgs
                 shift 1
                 ;;
+              --no-out-link) # We don't want this in buildArgs
+                ;;
               "<"*) # nix paths
                 instArgs+=("$i")
                 ;;
@@ -329,7 +330,7 @@ fi
 if [ -z "$rollback" ]; then
     echo "building the system configuration..." >&2
     if [ "$action" = switch -o "$action" = boot ]; then
-        pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system "${extraBuildFlags[@]}")"
+        pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")"
         copyToTarget "$pathToConfig"
         targetHostCmd nix-env -p "$profile" --set "$pathToConfig"
     elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index fda28fcf27b2..fc806db5c463 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -394,6 +394,7 @@
   ./services/security/fprintd.nix
   ./services/security/fprot.nix
   ./services/security/frandom.nix
+  ./services/security/haka.nix
   ./services/security/haveged.nix
   ./services/security/hologram.nix
   ./services/security/munge.nix
@@ -459,10 +460,10 @@
   ./system/boot/coredump.nix
   ./system/boot/emergency-mode.nix
   ./system/boot/initrd-network.nix
+  ./system/boot/initrd-ssh.nix
   ./system/boot/kernel.nix
   ./system/boot/kexec.nix
   ./system/boot/loader/efi.nix
-  ./system/boot/loader/loader.nix
   ./system/boot/loader/generations-dir/generations-dir.nix
   ./system/boot/loader/generic-extlinux-compatible
   ./system/boot/loader/grub/grub.nix
@@ -470,15 +471,16 @@
   ./system/boot/loader/grub/memtest.nix
   ./system/boot/loader/gummiboot/gummiboot.nix
   ./system/boot/loader/init-script/init-script.nix
+  ./system/boot/loader/loader.nix
   ./system/boot/loader/raspberrypi/raspberrypi.nix
   ./system/boot/luksroot.nix
   ./system/boot/modprobe.nix
+  ./system/boot/networkd.nix
+  ./system/boot/resolved.nix
   ./system/boot/shutdown.nix
   ./system/boot/stage-1.nix
   ./system/boot/stage-2.nix
   ./system/boot/systemd.nix
-  ./system/boot/networkd.nix
-  ./system/boot/resolved.nix
   ./system/boot/timesyncd.nix
   ./system/boot/tmp.nix
   ./system/etc/etc.nix
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index 2da8ff738fbc..169c6a38e75b 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -186,6 +186,9 @@ in
 
         ForwardX11 ${if cfg.forwardX11 then "yes" else "no"}
 
+        # Allow DSA keys for now. (These were deprecated in OpenSSH 7.0.)
+        PubkeyAcceptedKeyTypes +ssh-dss
+
         ${cfg.extraConfig}
       '';
 
diff --git a/nixos/modules/services/hardware/acpid.nix b/nixos/modules/services/hardware/acpid.nix
index 48b2b6be09ed..bb17c8859d84 100644
--- a/nixos/modules/services/hardware/acpid.nix
+++ b/nixos/modules/services/hardware/acpid.nix
@@ -4,111 +4,38 @@ with lib;
 
 let
 
-  acpiConfDir = pkgs.runCommand "acpi-events" {}
-    ''
-      mkdir -p $out
-      ${
-        # Generate a configuration file for each event. (You can't have
-        # multiple events in one config file...)
-        let f = event:
-          ''
-            fn=$out/${event.name}
-            echo "event=${event.event}" > $fn
-            echo "action=${pkgs.writeScript "${event.name}.sh" event.action}" >> $fn
-          '';
-        in lib.concatMapStrings f events
-      }
-    '';
-
-  events = [powerEvent lidEvent acEvent muteEvent volumeDownEvent volumeUpEvent cdPlayEvent cdNextEvent cdPrevEvent];
-
-  # Called when the power button is pressed.
-  powerEvent =
-    { name = "power-button";
+  canonicalHandlers = {
+    powerEvent = {
       event = "button/power.*";
-      action =
-        ''
-          #! ${pkgs.bash}/bin/sh
-          ${config.services.acpid.powerEventCommands}
-        '';
+      action = config.services.acpid.powerEventCommands;
     };
 
-  # Called when the laptop lid is opened/closed.
-  lidEvent =
-    { name = "lid";
+    lidEvent = {
       event = "button/lid.*";
-      action =
-        ''
-          #! ${pkgs.bash}/bin/sh
-          ${config.services.acpid.lidEventCommands}
-        '';
+      action = config.services.acpid.lidEventCommands;
     };
 
-  # Called when the AC power is connected or disconnected.
-  acEvent =
-    { name = "ac-power";
+    acEvent = {
       event = "ac_adapter.*";
-      action =
-        ''
-          #! ${pkgs.bash}/bin/sh
-          ${config.services.acpid.acEventCommands}
-        '';
+      action = config.services.acpid.acEventCommands;
     };
-
-  muteEvent = {
-    name = "mute";
-    event = "button/mute.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.muteCommands}
-    '';
-  };
-
-  volumeDownEvent = {
-    name = "volume-down";
-    event = "button/volumedown.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.volumeDownEventCommands}
-    '';
   };
 
-  volumeUpEvent = {
-    name = "volume-up";
-    event = "button/volumeup.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.volumeUpEventCommands}
-    '';
-  };
-
-  cdPlayEvent = {
-    name = "cd-play";
-    event = "cd/play.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.cdPlayEventCommands}
-    '';
-  };
-
-  cdNextEvent = {
-    name = "cd-next";
-    event = "cd/next.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.cdNextEventCommands}
-    '';
-  };
-
-  cdPrevEvent = {
-    name = "cd-prev";
-    event = "cd/prev.*";
-    action = ''
-      #! ${pkgs.bash}/bin/sh
-      ${config.services.acpid.cdPrevEventCommands}
+  acpiConfDir = pkgs.runCommand "acpi-events" {}
+    ''
+      mkdir -p $out
+      ${
+        # Generate a configuration file for each event. (You can't have
+        # multiple events in one config file...)
+        let f = name: handler:
+          ''
+            fn=$out/${name}
+            echo "event=${handler.event}" > $fn
+            echo "action=${pkgs.writeScript "${name}.sh" (concatStringsSep "\n" [ "#! ${pkgs.bash}/bin/sh" handler.action ])}" >> $fn
+          '';
+        in concatStringsSep "\n" (mapAttrsToList f (canonicalHandlers // config.services.acpid.handlers))
+      }
     '';
-  };
-
 
 in
 
@@ -126,58 +53,45 @@ in
         description = "Whether to enable the ACPI daemon.";
       };
 
-      powerEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on a button/power.* event.";
-      };
+      handlers = mkOption {
+        type = types.attrsOf (types.submodule {
+          options = {
+            event = mkOption {
+              type = types.str;
+              example = [ "button/power.*" "button/lid.*" "ac_adapter.*" "button/mute.*" "button/volumedown.*" "cd/play.*" "cd/next.*" ];
+              description = "Event type.";
+            };
 
-      lidEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on a button/lid.* event.";
-      };
+            action = mkOption {
+              type = types.lines;
+              description = "Shell commands to execute when the event is triggered.";
+            };
+          };
+        });
 
-      acEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an ac_adapter.* event.";
-      };
-
-      muteCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an button/mute.* event.";
-      };
+        description = "Event handlers.";
+        default = {};
+        example = { mute = { event = "button/mute.*"; action = "amixer set Master toggle"; }; };
 
-      volumeDownEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an button/volumedown.* event.";
-      };
 
-      volumeUpEventCommands = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Shell commands to execute on an button/volumeup.* event.";
       };
 
-      cdPlayEventCommands = mkOption {
+      powerEventCommands = mkOption {
         type = types.lines;
         default = "";
-        description = "Shell commands to execute on an cd/play.* event.";
+        description = "Shell commands to execute on a button/power.* event.";
       };
 
-      cdNextEventCommands = mkOption {
+      lidEventCommands = mkOption {
         type = types.lines;
         default = "";
-        description = "Shell commands to execute on an cd/next.* event.";
+        description = "Shell commands to execute on a button/lid.* event.";
       };
 
-      cdPrevEventCommands = mkOption {
+      acEventCommands = mkOption {
         type = types.lines;
         default = "";
-        description = "Shell commands to execute on an cd/prev.* event.";
+        description = "Shell commands to execute on an ac_adapter.* event.";
       };
 
     };
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index c747c24db67d..2d6630389b2b 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -16,6 +16,12 @@ let
     destination = "/etc/udev/rules.d/10-local.rules";
   };
 
+  extraHwdbFile = pkgs.writeTextFile {
+    name = "extra-hwdb-file";
+    text = cfg.extraHwdb;
+    destination = "/etc/udev/hwdb.d/10-local.hwdb";
+  };
+
   nixosRules = ''
     # Miscellaneous devices.
     KERNEL=="kvm",                  MODE="0666"
@@ -55,7 +61,9 @@ let
           --replace \"/sbin/modprobe \"${config.system.sbin.modprobe}/sbin/modprobe \
           --replace \"/sbin/mdadm \"${pkgs.mdadm}/sbin/mdadm \
           --replace \"/sbin/blkid \"${pkgs.utillinux}/sbin/blkid \
-          --replace \"/bin/mount \"${pkgs.utillinux}/bin/mount
+          --replace \"/bin/mount \"${pkgs.utillinux}/bin/mount \
+          --replace /usr/bin/readlink ${pkgs.coreutils}/bin/readlink \
+          --replace /usr/bin/basename ${pkgs.coreutils}/bin/basename
       done
 
       echo -n "Checking that all programs called by relative paths in udev rules exist in ${udev}/lib/udev... "
@@ -86,10 +94,30 @@ let
       done
       echo "OK"
 
-      echo "Consider fixing the following udev rules:"
-      for i in ${toString cfg.packages}; do
-        grep -l '\(RUN+\|IMPORT{program}\)="\(/usr\)\?/s\?bin' $i/*/udev/rules.d/* || true
-      done
+      filesToFixup="$(for i in "$out"/*; do
+        grep -l '\B\(/usr\)\?/s\?bin' "$i" || :
+      done)"
+
+      if [ -n "$filesToFixup" ]; then
+        echo "Consider fixing the following udev rules:"
+        echo "$filesToFixup" | while read localFile; do
+          remoteFile="origin unknown"
+          for i in ${toString cfg.packages}; do
+            for j in "$i"/*/udev/rules.d/*; do
+              [ -e "$out/$(basename "$j")" ] || continue
+              [ "$(basename "$j")" = "$(basename "$localFile")" ] || continue
+              remoteFile="originally from $j"
+              break 2
+            done
+          done
+          refs="$(
+            grep -o '\B\(/usr\)\?/s\?bin/[^ "]\+' "$localFile" \
+              | sed -e ':r;N;''${s/\n/ and /;br};s/\n/, /g;br'
+          )"
+          echo "$localFile ($remoteFile) contains references to $refs."
+        done
+        exit 1
+      fi
 
       ${optionalString config.networking.usePredictableInterfaceNames ''
         cp ${./80-net-setup-link.rules} $out/80-net-setup-link.rules
@@ -104,6 +132,27 @@ let
     ''; # */
   };
 
+  hwdbBin = stdenv.mkDerivation {
+    name = "hwdb.bin";
+
+    preferLocalBuild = true;
+    allowSubstitutes = false;
+
+    buildCommand = ''
+      mkdir -p etc/udev/hwdb.d
+      for i in ${toString ([udev] ++ cfg.packages)}; do
+        echo "Adding hwdb files for package $i"
+        for j in $i/{etc,lib}/udev/hwdb.d/*; do
+          ln -s $j etc/udev/hwdb.d/$(basename $j)
+        done
+      done
+
+      echo "Generating hwdb database..."
+      ${udev}/bin/udevadm hwdb --update --root=$(pwd)
+      mv etc/udev/hwdb.bin $out
+    '';
+  };
+
   # Udev has a 512-character limit for ENV{PATH}, so create a symlink
   # tree to work around this.
   udevPath = pkgs.buildEnv {
@@ -168,6 +217,21 @@ in
         '';
       };
 
+      extraHwdb = mkOption {
+        default = "";
+        example = ''
+          evdev:input:b0003v05AFp8277*
+            KEYBOARD_KEY_70039=leftalt
+            KEYBOARD_KEY_700e2=leftctrl
+        '';
+        type = types.lines;
+        description = ''
+          Additional <command>hwdb</command> files. They'll be written
+          into file <filename>10-local.hwdb</filename>. Thus they are
+          read before all other files.
+        '';
+      };
+
     };
 
     hardware.firmware = mkOption {
@@ -216,7 +280,7 @@ in
 
     services.udev.extraRules = nixosRules;
 
-    services.udev.packages = [ extraUdevRules ];
+    services.udev.packages = [ extraUdevRules extraHwdbFile ];
 
     services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.utillinux udev ];
 
@@ -224,6 +288,9 @@ in
       [ { source = udevRules;
           target = "udev/rules.d";
         }
+        { source = hwdbBin;
+          target = "udev/hwdb.bin";
+        }
       ];
 
     system.requiredKernelConfig = with config.lib.kernelConfig; [
@@ -241,13 +308,6 @@ in
           echo "" > /proc/sys/kernel/hotplug
         fi
 
-        # Regenerate the hardware database /var/lib/udev/hwdb.bin
-        # whenever systemd changes.
-        if [ ! -e /var/lib/udev/prev-systemd -o "$(readlink /var/lib/udev/prev-systemd)" != ${config.systemd.package} ]; then
-          echo "regenerating udev hardware database..."
-          ${config.systemd.package}/bin/udevadm hwdb --update && ln -sfn ${config.systemd.package} /var/lib/udev/prev-systemd
-        fi
-
         # Allow the kernel to find our firmware.
         if [ -e /sys/module/firmware_class/parameters/path ]; then
           echo -n "${config.hardware.firmware}/lib/firmware" > /sys/module/firmware_class/parameters/path
@@ -256,6 +316,7 @@ in
 
     systemd.services.systemd-udevd =
       { environment.MODULE_DIR = "/run/booted-system/kernel-modules/lib/modules";
+        restartTriggers = cfg.packages;
       };
 
   };
diff --git a/nixos/modules/services/mail/opensmtpd.nix b/nixos/modules/services/mail/opensmtpd.nix
index a1cfd84365a2..42a1244cde57 100644
--- a/nixos/modules/services/mail/opensmtpd.nix
+++ b/nixos/modules/services/mail/opensmtpd.nix
@@ -9,6 +9,11 @@ let
   conf = writeText "smtpd.conf" cfg.serverConfiguration;
   args = concatStringsSep " " cfg.extraServerArgs;
 
+  sendmail = pkgs.runCommand "opensmtpd-sendmail" {} ''
+    mkdir -p $out/bin
+    ln -s ${opensmtpd}/sbin/smtpctl $out/bin/sendmail
+  '';
+
 in {
 
   ###### interface
@@ -23,6 +28,15 @@ in {
         description = "Whether to enable the OpenSMTPD server.";
       };
 
+      addSendmailToSystemPath = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to add OpenSMTPD's sendmail binary to the
+          system path or not.
+        '';
+      };
+
       extraServerArgs = mkOption {
         type = types.listOf types.str;
         default = [];
@@ -64,7 +78,7 @@ in {
 
   ###### implementation
 
-  config = mkIf config.services.opensmtpd.enable {
+  config = mkIf cfg.enable {
     users.extraGroups = {
       smtpd.gid = config.ids.gids.smtpd;
       smtpq.gid = config.ids.gids.smtpq;
@@ -98,9 +112,6 @@ in {
       environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd";
     };
 
-    environment.systemPackages = [ (pkgs.runCommand "opensmtpd-sendmail" {} ''
-      mkdir -p $out/bin
-      ln -s ${opensmtpd}/sbin/smtpctl $out/bin/sendmail
-    '') ];
+    environment.systemPackages = mkIf cfg.addSendmailToSystemPath [ sendmail ];
   };
 }
diff --git a/nixos/modules/services/misc/sundtek.nix b/nixos/modules/services/misc/sundtek.nix
index 8438ef79904f..e3234518c940 100644
--- a/nixos/modules/services/misc/sundtek.nix
+++ b/nixos/modules/services/misc/sundtek.nix
@@ -23,7 +23,7 @@ in
         Type = "oneshot";
         ExecStart = ''
           ${pkgs.sundtek}/bin/mediasrv -d -v -p ${pkgs.sundtek}/bin ;\
-          ${pkgs.sundtek}/bin/mediaclient --start=5 --wait-for-devices
+          ${pkgs.sundtek}/bin/mediaclient --start --wait-for-devices
           '';
         ExecStop = "${pkgs.sundtek}/bin/mediaclient --shutdown";
         RemainAfterExit = true;
diff --git a/nixos/modules/services/networking/connman.nix b/nixos/modules/services/networking/connman.nix
index deb1cbfc1858..3fecfbb13a04 100644
--- a/nixos/modules/services/networking/connman.nix
+++ b/nixos/modules/services/networking/connman.nix
@@ -53,13 +53,13 @@ in {
   config = mkIf cfg.enable {
 
     assertions = [{
-      assertion = config.networking.useDHCP == false;
+      assertion = !config.networking.useDHCP;
       message = "You can not use services.networking.connman with services.networking.useDHCP";
     }{
-      assertion = config.networking.wireless.enable == true;
+      assertion = config.networking.wireless.enable;
       message = "You must use services.networking.connman with services.networking.wireless";
     }{
-      assertion = config.networking.networkmanager.enable == false;
+      assertion = !config.networking.networkmanager.enable;
       message = "You can not use services.networking.connman with services.networking.networkmanager";
     }];
 
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 5baea4bc6aea..ba3efc8c0c2a 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -52,6 +52,8 @@ let
     ));
   in listToAttrs (map mkAuthKeyFile usersWithKeys);
 
+  supportOldHostKeys = !versionAtLeast config.system.stateVersion "15.07";
+
 in
 
 {
@@ -177,7 +179,7 @@ in
         default =
           [ { type = "rsa"; bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; }
             { type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
-          ] ++ optionals (!versionAtLeast config.system.stateVersion "15.07")
+          ] ++ optionals supportOldHostKeys
           [ { type = "dsa"; path = "/etc/ssh/ssh_host_dsa_key"; }
             { type = "ecdsa"; bits = 521; path = "/etc/ssh/ssh_host_ecdsa_key"; }
           ];
@@ -347,6 +349,15 @@ in
         ${flip concatMapStrings cfg.hostKeys (k: ''
           HostKey ${k.path}
         '')}
+
+        # Allow DSA client keys for now. (These were deprecated
+        # in OpenSSH 7.0.)
+        PubkeyAcceptedKeyTypes +ssh-dss
+
+        # Re-enable DSA host keys for now.
+        ${optionalString supportOldHostKeys ''
+          HostKeyAlgorithms +ssh-dss
+        ''}
       '';
 
     assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
diff --git a/nixos/modules/services/security/haka.nix b/nixos/modules/services/security/haka.nix
new file mode 100644
index 000000000000..4f2bdd29cc49
--- /dev/null
+++ b/nixos/modules/services/security/haka.nix
@@ -0,0 +1,156 @@
+# This module defines global configuration for Haka.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.haka;
+
+  haka = cfg.package;
+
+  hakaConf = pkgs.writeText "haka.conf"
+  ''
+    [general]
+    configuration = ${if lib.strings.hasPrefix "/" cfg.configFile
+      then "${cfg.configFile}"
+      else "${haka}/share/haka/sample/${cfg.configFile}"}
+    ${optionalString (builtins.lessThan 0 cfg.threads) "thread = ${cfg.threads}"}
+
+    [packet]
+    ${optionalString cfg.pcap ''module = "packet/pcap"''}
+    ${optionalString cfg.nfqueue ''module = "packet/nqueue"''}
+    ${optionalString cfg.dump.enable ''dump = "yes"''}
+    ${optionalString cfg.dump.enable ''dump_input = "${cfg.dump.input}"''}
+    ${optionalString cfg.dump.enable ''dump_output = "${cfg.dump.output}"''}
+
+    interfaces = "${lib.strings.concatStringsSep "," cfg.interfaces}"
+
+    [log]
+    # Select the log module
+    module = "log/syslog"
+
+    # Set the default logging level
+    #level = "info,packet=debug"
+
+    [alert]
+    # Select the alert module
+    module = "alert/syslog"
+
+    # Disable alert on standard output
+    #alert_on_stdout = no
+
+    # alert/file module option
+    #file = "/dev/null"
+  '';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.haka = {
+
+      enable = mkEnableOption "Haka";
+
+      package = mkOption {
+        default = pkgs.haka;
+        type = types.package;
+        description = "
+          Which Haka derivation to use.
+        ";
+      };
+
+      configFile = mkOption {
+        default = "empty.lua";
+        example = "/srv/haka/myfilter.lua";
+        type = types.string;
+        description = ''
+          Specify which configuration file Haka uses.
+          It can be absolute path or a path relative to the sample directory of
+          the haka git repo.
+        '';
+      };
+
+      interfaces = mkOption {
+        default = [ "eth0" ];
+        example = [ "any" ];
+        type = with types; listOf string;
+        description = ''
+          Specify which interface(s) Haka listens to.
+          Use 'any' to listen to all interfaces.
+        '';
+      };
+
+      threads = mkOption {
+        default = 0;
+        example = 4;
+        type = types.int;
+        description = ''
+          The number of threads that will be used.
+          All system threads are used by default.
+        '';
+      };
+
+      pcap = mkOption {
+        default = true;
+        example = false;
+        type = types.bool;
+        description = "Whether to enable pcap";
+      };
+
+      nfqueue = mkEnableOption "nfqueue";
+
+      dump.enable = mkEnableOption "dump";
+      dump.input  = mkOption {
+        default = "/tmp/input.pcap";
+        example = "/path/to/file.pcap";
+        type = types.path;
+        description = "Path to file where incoming packets are dumped";
+      };
+
+      dump.output  = mkOption {
+        default = "/tmp/output.pcap";
+        example = "/path/to/file.pcap";
+        type = types.path;
+        description = "Path to file where outgoing packets are dumped";
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    assertions = [
+      { assertion = cfg.pcap != cfg.nfqueue;
+        message = "either pcap or nfqueue can be enabled, not both.";
+      }
+      { assertion = cfg.nfqueue -> !dump.enable;
+        message = "dump can only be used with nfqueue.";
+      }
+      { assertion = cfg.interfaces != [];
+        message = "at least one interface must be specified.";
+      }];
+
+
+    environment.systemPackages = [ haka ];
+
+    systemd.services.haka = {
+      description = "Haka";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        ExecStart = "${haka}/bin/haka -c ${hakaConf}";
+        ExecStop = "${haka}/bin/hakactl stop";
+        User = "root";
+        Type = "forking";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 998bcd354c53..3e91450a39d2 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -64,7 +64,13 @@ in
           else if any (w: w.name == defaultDM) cfg.session.list then
             defaultDM
           else
-            throw "Default desktop manager ($(defaultDM)) not found.";
+            throw ''
+              Default desktop manager (${defaultDM}) not found.
+              Probably you want to change
+                services.xserver.desktopManager.default = "${defaultDM}";
+              to one of
+                ${concatMapStringsSep "\n  " (w: "services.xserver.desktopManager.default = \"${w.name}\";") cfg.session.list}
+            '';
       };
 
     };
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index be2411b3c7ff..4dd631d87511 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -64,7 +64,7 @@ in {
     environment.gnome3.packageSet = mkOption {
       type = types.nullOr types.package;
       default = null;
-      example = literalExample "pkgs.gnome3_16";
+      example = literalExample "pkgs.gnome3_18";
       description = "Which GNOME 3 package set to use.";
       apply = p: if p == null then pkgs.gnome3 else p;
     };
diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix
index 29cca248cde3..80e408be4923 100644
--- a/nixos/modules/services/x11/desktop-managers/kde4.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde4.nix
@@ -108,6 +108,12 @@ in
                 sed -e '/nix\\store\|nix\/store/ d' -i $HOME/.config/Trolltech.conf
             fi
 
+            # Load PulseAudio module for routing support.
+            # See http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
+            ${optionalString config.hardware.pulseaudio.enable ''
+              ${config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
+            ''}
+
             # Start KDE.
             exec ${kde_workspace}/bin/startkde
           '';
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index e8c768e41fad..713a156d35ab 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -55,7 +55,15 @@ in
     services.xserver.desktopManager.session = singleton {
       name = "kde5";
       bgSupport = true;
-      start = ''exec ${kde5.plasma-workspace}/bin/startkde;'';
+      start = ''
+        # Load PulseAudio module for routing support.
+        # See http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
+        ${optionalString config.hardware.pulseaudio.enable ''
+          ${config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
+        ''}
+
+        exec ${kde5.plasma-workspace}/bin/startkde
+      '';
     };
 
     security.setuidOwners = singleton {
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index bad99ccd8696..87f3a4837a69 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -90,9 +90,6 @@ let
 
         # Publish access credentials in the root window.
         ${config.hardware.pulseaudio.package}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
-
-        # Keep track of devices.  Mostly useful for Phonon/KDE.
-        ${config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
       ''}
 
       # Tell systemd about our $DISPLAY. This is needed by the
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 9460395f86d6..3949bf01a316 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -86,7 +86,7 @@ in
       };
 
       background = mkOption {
-        type = types.path;
+        type = types.str;
         description = ''
           The background image or color to use.
         '';
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index 655fbab2a843..d9048427801f 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -323,7 +323,7 @@ foreach my $device (keys %$prevSwaps) {
 
 
 # Should we have systemd re-exec itself?
-my $prevSystemd = abs_path("/proc/1/exe") or die;
+my $prevSystemd = abs_path("/proc/1/exe") // "/unknown";
 my $newSystemd = abs_path("@systemd@/lib/systemd/systemd") or die;
 my $restartSystemd = $prevSystemd ne $newSystemd;
 
diff --git a/nixos/modules/system/boot/initrd-network.nix b/nixos/modules/system/boot/initrd-network.nix
index 6c6e2fafad43..6e226c190609 100644
--- a/nixos/modules/system/boot/initrd-network.nix
+++ b/nixos/modules/system/boot/initrd-network.nix
@@ -3,9 +3,28 @@
 with lib;
 
 let
+
   cfg = config.boot.initrd.network;
 
+  udhcpcScript = pkgs.writeScript "udhcp-script"
+    ''
+      #! /bin/sh
+      if [ "$1" = bound ]; then
+        ip address add "$ip/$mask" dev "$interface"
+        if [ -n "$router" ]; then
+          ip route add default via "$router" dev "$interface"
+        fi
+        if [ -n "$dns" ]; then
+          rm -f /etc/resolv.conf
+          for i in $dns; do
+            echo "nameserver $dns" >> /etc/resolv.conf
+          done
+        fi
+      fi
+    '';
+
 in
+
 {
 
   options = {
@@ -14,82 +33,25 @@ in
       type = types.bool;
       default = false;
       description = ''
-        Add network connectivity support to initrd.
-
-        Network options are configured via <literal>ip</literal> kernel
-        option, according to the kernel documentation.
-      '';
-    };
-
-    boot.initrd.network.ssh.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = ''
-        Start SSH service during initrd boot. It can be used to debug failing
-        boot on a remote server, enter pasphrase for an encrypted partition etc.
-        Service is killed when stage-1 boot is finished.
-      '';
-    };
-
-    boot.initrd.network.ssh.port = mkOption {
-      type = types.int;
-      default = 22;
-      description = ''
-        Port on which SSH initrd service should listen.
-      '';
-    };
-
-    boot.initrd.network.ssh.shell = mkOption {
-      type = types.str;
-      default = "/bin/ash";
-      description = ''
-        Login shell of the remote user. Can be used to limit actions user can do.
+        Add network connectivity support to initrd. The network may be
+        configured using the <literal>ip</literal> kernel parameter,
+        as described in <link
+        xlink:href="https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt">the
+        kernel documentation</link>.  Otherwise, if
+        <option>networking.useDHCP</option> is enabled, an IP address
+        is acquired using DHCP.
       '';
     };
 
-    boot.initrd.network.ssh.hostRSAKey = mkOption {
-      type = types.nullOr types.path;
-      default = null;
+    boot.initrd.network.postCommands = mkOption {
+      default = "";
+      type = types.lines;
       description = ''
-        RSA SSH private key file in the Dropbear format.
-
-        WARNING: This key is contained insecurely in the global Nix store. Do NOT
-        use your regular SSH host private keys for this purpose or you'll expose
-        them to regular users!
-      '';
-    };
-
-    boot.initrd.network.ssh.hostDSSKey = mkOption {
-      type = types.nullOr types.path;
-      default = null;
-      description = ''
-        DSS SSH private key file in the Dropbear format.
-
-        WARNING: This key is contained insecurely in the global Nix store. Do NOT
-        use your regular SSH host private keys for this purpose or you'll expose
-        them to regular users!
-      '';
-    };
-
-    boot.initrd.network.ssh.hostECDSAKey = mkOption {
-      type = types.nullOr types.path;
-      default = null;
-      description = ''
-        ECDSA SSH private key file in the Dropbear format.
-
-        WARNING: This key is contained insecurely in the global Nix store. Do NOT
-        use your regular SSH host private keys for this purpose or you'll expose
-        them to regular users!
+        Shell commands to be executed after stage 1 of the
+        boot has initialised the network.
       '';
     };
 
-    boot.initrd.network.ssh.authorizedKeys = mkOption {
-      type = types.listOf types.str;
-      default = config.users.extraUsers.root.openssh.authorizedKeys.keys;
-      description = ''
-        Authorized keys for the root user on initrd.
-      '';
-    };
 
   };
 
@@ -99,51 +61,43 @@ in
 
     boot.initrd.extraUtilsCommands = ''
       copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig
-    '' + optionalString cfg.ssh.enable ''
-      copy_bin_and_libs ${pkgs.dropbear}/bin/dropbear
-
-      cp -pv ${pkgs.glibc}/lib/libnss_files.so.* $out/lib
     '';
 
-    boot.initrd.extraUtilsCommandsTest = optionalString cfg.ssh.enable ''
-      $out/bin/dropbear -V
-    '';
-
-    boot.initrd.postEarlyDeviceCommands = ''
-      # Search for interface definitions in command line
-      for o in $(cat /proc/cmdline); do
-        case $o in
-          ip=*)
-            ipconfig $o && hasNetwork=1
-            ;;
-        esac
-      done
-    '' + optionalString cfg.ssh.enable ''
-      if [ -n "$hasNetwork" ]; then
-        mkdir /dev/pts
-        mount -t devpts devpts /dev/pts
-
-        mkdir -p /etc
-        echo 'root:x:0:0:root:/root:${cfg.ssh.shell}' > /etc/passwd
-        echo '${cfg.ssh.shell}' > /etc/shells
-        echo 'passwd: files' > /etc/nsswitch.conf
-
-        mkdir -p /var/log
-        touch /var/log/lastlog
-
-        mkdir -p /etc/dropbear
-        ${optionalString (cfg.ssh.hostRSAKey != null) "ln -s ${cfg.ssh.hostRSAKey} /etc/dropbear/dropbear_rsa_host_key"}
-        ${optionalString (cfg.ssh.hostDSSKey != null) "ln -s ${cfg.ssh.hostDSSKey} /etc/dropbear/dropbear_dss_host_key"}
-        ${optionalString (cfg.ssh.hostECDSAKey != null) "ln -s ${cfg.ssh.hostECDSAKey} /etc/dropbear/dropbear_ecdsa_host_key"}
-
-        mkdir -p /root/.ssh
-        ${concatStrings (map (key: ''
-          echo -n ${escapeShellArg key} >> /root/.ssh/authorized_keys
-        '') cfg.ssh.authorizedKeys)}
-
-        dropbear -s -j -k -E -m -p ${toString cfg.ssh.port}
-      fi
-    '';
+    boot.initrd.preLVMCommands = mkBefore (
+      # Search for interface definitions in command line.
+      ''
+        for o in $(cat /proc/cmdline); do
+          case $o in
+            ip=*)
+              ipconfig $o && hasNetwork=1
+              ;;
+          esac
+        done
+      ''
+
+      # Otherwise, use DHCP.
+      + optionalString config.networking.useDHCP ''
+        if [ -z "$hasNetwork" ]; then
+
+          # Bring up all interfaces.
+          for iface in $(cd /sys/class/net && ls); do
+            echo "bringing up network interface $iface..."
+            ip link set "$iface" up
+          done
+
+          # Acquire a DHCP lease.
+          echo "acquiring IP address via DHCP..."
+          udhcpc --quit --now --script ${udhcpcScript} && hasNetwork=1
+        fi
+      ''
+
+      + ''
+        if [ -n "$hasNetwork" ]; then
+          echo "networking is up!"
+          ${cfg.postCommands}
+        fi
+      '');
 
   };
+
 }
diff --git a/nixos/modules/system/boot/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix
new file mode 100644
index 000000000000..4cdc81541955
--- /dev/null
+++ b/nixos/modules/system/boot/initrd-ssh.nix
@@ -0,0 +1,124 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.boot.initrd.network.ssh;
+
+in
+
+{
+
+  options = {
+
+    boot.initrd.network.ssh.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Start SSH service during initrd boot. It can be used to debug failing
+        boot on a remote server, enter pasphrase for an encrypted partition etc.
+        Service is killed when stage-1 boot is finished.
+      '';
+    };
+
+    boot.initrd.network.ssh.port = mkOption {
+      type = types.int;
+      default = 22;
+      description = ''
+        Port on which SSH initrd service should listen.
+      '';
+    };
+
+    boot.initrd.network.ssh.shell = mkOption {
+      type = types.str;
+      default = "/bin/ash";
+      description = ''
+        Login shell of the remote user. Can be used to limit actions user can do.
+      '';
+    };
+
+    boot.initrd.network.ssh.hostRSAKey = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        RSA SSH private key file in the Dropbear format.
+
+        WARNING: This key is contained insecurely in the global Nix store. Do NOT
+        use your regular SSH host private keys for this purpose or you'll expose
+        them to regular users!
+      '';
+    };
+
+    boot.initrd.network.ssh.hostDSSKey = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        DSS SSH private key file in the Dropbear format.
+
+        WARNING: This key is contained insecurely in the global Nix store. Do NOT
+        use your regular SSH host private keys for this purpose or you'll expose
+        them to regular users!
+      '';
+    };
+
+    boot.initrd.network.ssh.hostECDSAKey = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        ECDSA SSH private key file in the Dropbear format.
+
+        WARNING: This key is contained insecurely in the global Nix store. Do NOT
+        use your regular SSH host private keys for this purpose or you'll expose
+        them to regular users!
+      '';
+    };
+
+    boot.initrd.network.ssh.authorizedKeys = mkOption {
+      type = types.listOf types.str;
+      default = config.users.extraUsers.root.openssh.authorizedKeys.keys;
+      description = ''
+        Authorized keys for the root user on initrd.
+      '';
+    };
+
+  };
+
+  config = mkIf (config.boot.initrd.network.enable && cfg.enable) {
+
+    boot.initrd.extraUtilsCommands = ''
+      copy_bin_and_libs ${pkgs.dropbear}/bin/dropbear
+      cp -pv ${pkgs.glibc}/lib/libnss_files.so.* $out/lib
+    '';
+
+    boot.initrd.extraUtilsCommandsTest = ''
+      $out/bin/dropbear -V
+    '';
+
+    boot.initrd.network.postCommands = ''
+      mkdir /dev/pts
+      mount -t devpts devpts /dev/pts
+
+      echo '${cfg.shell}' > /etc/shells
+      echo 'root:x:0:0:root:/root:${cfg.shell}' > /etc/passwd
+      echo 'passwd: files' > /etc/nsswitch.conf
+
+      mkdir -p /var/log
+      touch /var/log/lastlog
+
+      mkdir -p /etc/dropbear
+      ${optionalString (cfg.hostRSAKey != null) "ln -s ${cfg.hostRSAKey} /etc/dropbear/dropbear_rsa_host_key"}
+      ${optionalString (cfg.hostDSSKey != null) "ln -s ${cfg.hostDSSKey} /etc/dropbear/dropbear_dss_host_key"}
+      ${optionalString (cfg.hostECDSAKey != null) "ln -s ${cfg.hostECDSAKey} /etc/dropbear/dropbear_ecdsa_host_key"}
+
+      mkdir -p /root/.ssh
+      ${concatStrings (map (key: ''
+        echo -n ${escapeShellArg key} >> /root/.ssh/authorized_keys
+      '') cfg.authorizedKeys)}
+
+      dropbear -s -j -k -E -m -p ${toString cfg.port}
+    '';
+
+  };
+
+}
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 7fb368e8c44f..95df0ace1ca4 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -150,10 +150,6 @@ udevadm trigger --action=add
 udevadm settle
 
 
-# Additional devices initialization.
-@postEarlyDeviceCommands@
-
-
 # Load boot-time keymap before any LVM/LUKS initialization
 @extraUtils@/bin/busybox loadkmap < "@busyboxKeymap@"
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 694a5cfb6f85..f31620df1d85 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -66,10 +66,6 @@ let
         copy_bin_and_libs $BIN
       done
 
-      # Copy modprobe.
-      copy_bin_and_libs ${pkgs.kmod}/bin/kmod
-      ln -sf kmod $out/bin/modprobe
-
       # Copy resize2fs if needed.
       ${optionalString (any (fs: fs.autoResize) (attrValues config.fileSystems)) ''
         # We need mke2fs in the initrd.
@@ -161,7 +157,9 @@ let
             --replace /sbin/blkid ${extraUtils}/bin/blkid \
             --replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
             --replace /sbin/mdadm ${extraUtils}/bin/mdadm \
-            --replace /bin/sh ${extraUtils}/bin/sh
+            --replace /bin/sh ${extraUtils}/bin/sh \
+            --replace /usr/bin/readlink ${extraUtils}/bin/readlink \
+            --replace /usr/bin/basename ${extraUtils}/bin/basename
       done
 
       # Work around a bug in QEMU, which doesn't implement the "READ
@@ -203,13 +201,13 @@ let
     inherit (config.boot) resumeDevice devSize runSize;
 
     inherit (config.boot.initrd) checkJournalingFS
-      preLVMCommands preDeviceCommands postEarlyDeviceCommands postDeviceCommands postMountCommands kernelModules;
+      preLVMCommands preDeviceCommands postDeviceCommands postMountCommands kernelModules;
 
     resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}")
                     (filter (sd: (sd ? label || hasPrefix "/dev/" sd.device) && !sd.randomEncryption) config.swapDevices);
 
     fsInfo =
-      let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType fs.options ];
+      let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType (builtins.concatStringsSep "," fs.options) ];
       in pkgs.writeText "initrd-fsinfo" (concatStringsSep "\n" (concatMap f fileSystems));
 
     setHostId = optionalString (config.networking.hostId != null) ''
@@ -322,14 +320,6 @@ in
       '';
     };
 
-    boot.initrd.postEarlyDeviceCommands = mkOption {
-      default = "";
-      type = types.lines;
-      description = ''
-        Shell commands to be executed early after creation of device nodes.
-      '';
-    };
-
     boot.initrd.postMountCommands = mkOption {
       default = "";
       type = types.lines;
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index d0dd7670157e..4d1466db22d0 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -41,11 +41,15 @@ let
       };
 
       options = mkOption {
-        default = "defaults";
-        example = "data=journal";
-        type = types.commas; # FIXME: should be a list
+        default = [ "defaults" ];
+        example = [ "data=journal" ];
         description = "Options used to mount the file system.";
-      };
+      } // (if versionAtLeast lib.nixpkgsVersion "16.09" then {
+        type = types.listOf types.str;
+      } else {
+        type = types.either types.commas (types.listOf types.str);
+        apply = x: if isList x then x else lib.strings.splitString "," (builtins.trace "warning: passing a comma-separated string for filesystem options is deprecated; use a list of strings instead. This will become a hard error in 16.09." x);
+      });
 
       autoFormat = mkOption {
         default = false;
@@ -112,7 +116,7 @@ in
         "/data" = {
           device = "/dev/hda2";
           fsType = "ext3";
-          options = "data=journal";
+          options = [ "data=journal" ];
         };
         "/bigdisk".label = "bigdisk";
       };
@@ -127,7 +131,7 @@ in
         <command>mount</command>; defaults to
         <literal>"auto"</literal>), and <literal>options</literal>
         (the mount options passed to <command>mount</command> using the
-        <option>-o</option> flag; defaults to <literal>"defaults"</literal>).
+        <option>-o</option> flag; defaults to <literal>[ "defaults" ]</literal>).
 
         Instead of specifying <literal>device</literal>, you can also
         specify a volume label (<literal>label</literal>) for file
@@ -177,7 +181,7 @@ in
              else throw "No device specified for mount point ‘${fs.mountPoint}’.")
             + " " + fs.mountPoint
             + " " + fs.fsType
-            + " " + fs.options
+            + " " + builtins.concatStringsSep "," fs.options
             + " 0"
             + " " + (if skipCheck fs then "0" else
                      if fs.mountPoint == "/" then "1" else "2")
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index e72c0f8956ed..503d3813611f 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -927,7 +927,7 @@ in
         pkgs.nettools
         pkgs.openresolv
       ]
-      ++ optionals (!config.boot.isContainer) [
+      ++ optionals config.networking.wireless.enable [
         pkgs.wirelesstools # FIXME: obsolete?
         pkgs.iw
         pkgs.rfkill
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index 7ccc9df740e5..a895f66db8ef 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -20,8 +20,7 @@ let cfg = config.ec2; in
       autoResize = true;
     };
 
-    boot.initrd.kernelModules = [ "xen-blkfront" ];
-    boot.kernelModules = [ "xen-netfront" ];
+    boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ];
     boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ];
 
     # Prevent the nouveau kernel module from being loaded, as it
@@ -44,6 +43,8 @@ let cfg = config.ec2; in
         kill -9 -1
       '';
 
+    boot.initrd.network.enable = true;
+
     # Mount all formatted ephemeral disks and activate all swap devices.
     # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options
     # because the set of devices is dependent on the instance type
@@ -55,6 +56,28 @@ let cfg = config.ec2; in
     # Nix operations.
     boot.initrd.postMountCommands =
       ''
+        metaDir=$targetRoot/etc/ec2-metadata
+        mkdir -m 0755 -p "$metaDir"
+
+        echo "getting EC2 instance metadata..."
+
+        if ! [ -e "$metaDir/ami-manifest-path" ]; then
+          wget -q -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
+        fi
+
+        if ! [ -e "$metaDir/user-data" ]; then
+          wget -q -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data
+          chmod 600 "$metaDir/user-data"
+        fi
+
+        if ! [ -e "$metaDir/hostname" ]; then
+          wget -q -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname
+        fi
+
+        if ! [ -e "$metaDir/public-keys-0-openssh-key" ]; then
+          wget -q -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key
+        fi
+
         diskNr=0
         diskForUnionfs=
         for device in /dev/xvd[abcde]*; do
@@ -81,7 +104,7 @@ let cfg = config.ec2; in
             mkdir -m 1777 -p $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp
             mount --bind $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp
 
-            if [ ! -e $targetRoot/.ebs ]; then
+            if [ "$(cat "$metaDir/ami-manifest-path")" != "(unknown)" ]; then
                 mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/var $targetRoot/var
                 mount --bind $targetRoot/$diskForUnionfs/root/var $targetRoot/var
 
diff --git a/nixos/modules/virtualisation/amazon-init.nix b/nixos/modules/virtualisation/amazon-init.nix
index 96cd57e6db5d..886552f33c2c 100644
--- a/nixos/modules/virtualisation/amazon-init.nix
+++ b/nixos/modules/virtualisation/amazon-init.nix
@@ -4,18 +4,17 @@
 
 let
   bootScript = pkgs.writeScript "bootscript.sh" ''
-    #!${pkgs.stdenv.shell} -eux
+    #!${pkgs.stdenv.shell} -eu
 
-    echo "attempting to fetch configuration from user-data..."
+    echo "attempting to fetch configuration from EC2 user data..."
 
-    export PATH=${config.nix.package}/bin:${pkgs.wget}/bin:${pkgs.systemd}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin:${config.system.build.nixos-rebuild}/bin:$PATH
+    export PATH=${config.nix.package}/bin:${pkgs.systemd}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin:${config.system.build.nixos-rebuild}/bin:$PATH
     export NIX_PATH=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels
 
-    userData="$(mktemp)"
-    wget -q --wait=1 --tries=0 --retry-connrefused -O - http://169.254.169.254/2011-01-01/user-data > "$userData"
+    userData=/etc/ec2-metadata/user-data
+
+    if [ -s "$userData" ]; then
 
-    if [[ $? -eq 0 ]]; then
-      echo "user-data fetched"
       # If the user-data looks like it could be a nix expression,
       # copy it over. Also, look for a magic three-hash comment and set
       # that as the channel.
@@ -30,17 +29,17 @@ let
           nix-channel --update
         fi
 
-        echo "setting configuration"
+        echo "setting configuration from EC2 user data"
         cp "$userData" /etc/nixos/configuration.nix
       else
-        echo "user-data does not appear to be a nix expression; ignoring"
+        echo "user data does not appear to be a Nix expression; ignoring"
+        exit
       fi
     else
-      echo "failed to fetch user-data"
+      echo "no user data is available"
+      exit
     fi
 
-    type -f nixos-rebuild
-
     nixos-rebuild switch
   '';
 in {
diff --git a/nixos/modules/virtualisation/ec2-data.nix b/nixos/modules/virtualisation/ec2-data.nix
index 383750520ab7..bee262612680 100644
--- a/nixos/modules/virtualisation/ec2-data.nix
+++ b/nixos/modules/virtualisation/ec2-data.nix
@@ -1,6 +1,6 @@
-# This module defines a systemd service that obtains the SSH key and
-# host name of virtual machines running on Amazon EC2, Eucalyptus and
-# OpenStack Compute (Nova).
+# This module defines a systemd service that sets the SSH host key and
+# authorized client key and host name of virtual machines running on
+# Amazon EC2, Eucalyptus and OpenStack Compute (Nova).
 
 { config, lib, pkgs, ... }:
 
@@ -9,55 +9,49 @@ with lib;
 {
   config = {
 
-    systemd.services.fetch-ec2-data =
-      { description = "Fetch EC2 Data";
+    systemd.services.apply-ec2-data =
+      { description = "Apply EC2 Data";
 
         wantedBy = [ "multi-user.target" "sshd.service" ];
         before = [ "sshd.service" ];
-        wants = [ "ip-up.target" ];
-        after = [ "ip-up.target" ];
 
-        path = [ pkgs.wget pkgs.iproute ];
+        path = [ pkgs.iproute ];
 
         script =
           ''
-            wget="wget -q --retry-connrefused -O -"
-
             ${optionalString (config.networking.hostName == "") ''
               echo "setting host name..."
-              ${pkgs.nettools}/bin/hostname $($wget http://169.254.169.254/1.0/meta-data/hostname)
+              if [ -s /etc/ec2-metadata/hostname ]; then
+                  ${pkgs.nettools}/bin/hostname $(cat /etc/ec2-metadata/hostname)
+              fi
             ''}
 
-            # Don't download the SSH key if it has already been injected
-            # into the image (a Nova feature).
             if ! [ -e /root/.ssh/authorized_keys ]; then
                 echo "obtaining SSH key..."
                 mkdir -m 0700 -p /root/.ssh
-                $wget http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key > /root/key.pub
-                if [ $? -eq 0 -a -e /root/key.pub ]; then
-                    cat /root/key.pub >> /root/.ssh/authorized_keys
+                if [ -s /etc/ec2-metadata/public-keys-0-openssh-key ]; then
+                    cat /etc/ec2-metadata/public-keys-0-openssh-key >> /root/.ssh/authorized_keys
                     echo "new key added to authorized_keys"
                     chmod 600 /root/.ssh/authorized_keys
-                    rm -f /root/key.pub
                 fi
             fi
 
             # Extract the intended SSH host key for this machine from
             # the supplied user data, if available.  Otherwise sshd will
             # generate one normally.
-            $wget http://169.254.169.254/2011-01-01/user-data > /root/user-data || true
+            userData=/etc/ec2-metadata/user-data
 
             mkdir -m 0755 -p /etc/ssh
 
-            key="$(sed 's/|/\n/g; s/SSH_HOST_DSA_KEY://; t; d' /root/user-data)"
-            key_pub="$(sed 's/SSH_HOST_DSA_KEY_PUB://; t; d' /root/user-data)"
+            key="$(sed 's/|/\n/g; s/SSH_HOST_DSA_KEY://; t; d' $userData)"
+            key_pub="$(sed 's/SSH_HOST_DSA_KEY_PUB://; t; d' $userData)"
             if [ -n "$key" -a -n "$key_pub" -a ! -e /etc/ssh/ssh_host_dsa_key ]; then
                 (umask 077; echo "$key" > /etc/ssh/ssh_host_dsa_key)
                 echo "$key_pub" > /etc/ssh/ssh_host_dsa_key.pub
             fi
 
-            key="$(sed 's/|/\n/g; s/SSH_HOST_ED25519_KEY://; t; d' /root/user-data)"
-            key_pub="$(sed 's/SSH_HOST_ED25519_KEY_PUB://; t; d' /root/user-data)"
+            key="$(sed 's/|/\n/g; s/SSH_HOST_ED25519_KEY://; t; d' $userData)"
+            key_pub="$(sed 's/SSH_HOST_ED25519_KEY_PUB://; t; d' $userData)"
             if [ -n "$key" -a -n "$key_pub" -a ! -e /etc/ssh/ssh_host_ed25519_key ]; then
                 (umask 077; echo "$key" > /etc/ssh/ssh_host_ed25519_key)
                 echo "$key_pub" > /etc/ssh/ssh_host_ed25519_key.pub
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 82b58aa67a3d..6e0dc065387a 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -427,38 +427,38 @@ in
         ${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} =
           { device = "store";
             fsType = "9p";
-            options = "trans=virtio,version=9p2000.L,cache=loose";
+            options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
             neededForBoot = true;
           };
         "/tmp/xchg" =
           { device = "xchg";
             fsType = "9p";
-            options = "trans=virtio,version=9p2000.L,cache=loose";
+            options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
             neededForBoot = true;
           };
         "/tmp/shared" =
           { device = "shared";
             fsType = "9p";
-            options = "trans=virtio,version=9p2000.L";
+            options = [ "trans=virtio" "version=9p2000.L" ];
             neededForBoot = true;
           };
       } // optionalAttrs cfg.writableStore
       { "/nix/store" =
           { fsType = "unionfs-fuse";
             device = "unionfs";
-            options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro";
+            options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
           };
       } // optionalAttrs (cfg.writableStore && cfg.writableStoreUseTmpfs)
       { "/nix/.rw-store" =
           { fsType = "tmpfs";
-            options = "mode=0755";
+            options = [ "mode=0755" ];
             neededForBoot = true;
           };
       } // optionalAttrs cfg.useBootLoader
       { "/boot" =
           { device = "/dev/vdb2";
             fsType = "vfat";
-            options = "ro";
+            options = [ "ro" ];
             noCheck = true; # fsck fails on a r/o filesystem
           };
       });
diff --git a/nixos/release.nix b/nixos/release.nix
index 9c15b1ea0746..d9f3e46b27c0 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -248,6 +248,7 @@ in rec {
   tests.ipv6 = callTest tests/ipv6.nix {};
   tests.jenkins = callTest tests/jenkins.nix {};
   tests.kde4 = callTest tests/kde4.nix {};
+  tests.initrdNetwork = callTest tests/initrd-network.nix {};
   tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; });
   tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; };
   #tests.lightdm = callTest tests/lightdm.nix {};
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
index 1d1e12d0ee39..6c61087760dd 100644
--- a/nixos/tests/chromium.nix
+++ b/nixos/tests/chromium.nix
@@ -2,8 +2,8 @@ import ./make-test.nix (
 { pkgs
 , channelMap ? {
     stable = pkgs.chromium;
-    beta   = pkgs.chromiumBeta;
-    dev    = pkgs.chromiumDev;
+    #beta   = pkgs.chromiumBeta;
+    #dev    = pkgs.chromiumDev;
   }
 , ...
 }: rec {
diff --git a/nixos/tests/ec2.nix b/nixos/tests/ec2.nix
index 1925ab37419a..0a95d6cfeff4 100644
--- a/nixos/tests/ec2.nix
+++ b/nixos/tests/ec2.nix
@@ -10,9 +10,10 @@ let
       inherit system;
       modules = [
         ../maintainers/scripts/ec2/amazon-image.nix
-        ../../nixos/modules/testing/test-instrumentation.nix
-        { boot.initrd.kernelModules = [ "virtio" "virtio_blk" "virtio_pci" "virtio_ring" ];
-          ec2.hvm = true;
+        ../modules/testing/test-instrumentation.nix
+        ../modules/profiles/minimal.nix
+        ../modules/profiles/qemu-guest.nix
+        { ec2.hvm = true;
 
           # Hack to make the partition resizing work in QEMU.
           boot.initrd.postDeviceCommands = mkBefore
@@ -33,6 +34,7 @@ let
           ln -s ${pkgs.writeText "userData" userData} $out/2011-01-01/user-data
           mkdir -p $out/1.0/meta-data
           echo "${hostname}" > $out/1.0/meta-data/hostname
+          echo "(unknown)" > $out/1.0/meta-data/ami-manifest-path
         '' + optionalString (sshPublicKey != null) ''
           mkdir -p $out/1.0/meta-data/public-keys/0
           ln -s ${pkgs.writeText "sshPublicKey" sshPublicKey} $out/1.0/meta-data/public-keys/0/openssh-key
@@ -56,7 +58,7 @@ let
           # again when it deletes link-local addresses.) Ideally we'd
           # turn off the DHCP server, but qemu does not have an option
           # to do that.
-          my $startCommand = "qemu-kvm -m 768 -net nic -net 'user,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'";
+          my $startCommand = "qemu-kvm -m 768 -net nic,vlan=0,model=virtio -net 'user,vlan=0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'";
           $startCommand .= " -drive file=$diskImage,if=virtio,werror=report";
           $startCommand .= " \$QEMU_OPTS";
 
@@ -92,6 +94,8 @@ in {
       $machine->waitForFile("/root/user-data");
       $machine->waitForUnit("sshd.service");
 
+      $machine->succeed("grep unknown /etc/ec2-metadata/ami-manifest-path");
+
       # We have no keys configured on the client side yet, so this should fail
       $machine->fail("ssh -o BatchMode=yes localhost exit");
 
diff --git a/nixos/tests/haka.nix b/nixos/tests/haka.nix
new file mode 100644
index 000000000000..40548f34690f
--- /dev/null
+++ b/nixos/tests/haka.nix
@@ -0,0 +1,24 @@
+# This test runs haka and probes it with hakactl
+
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "haka";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ tvestelind ];
+  };
+
+  nodes = {
+    haka =
+      { config, pkgs, ... }:
+        {
+          services.haka.enable = true;
+        };
+    };
+
+  testScript = ''
+    startAll;
+
+    $haka->waitForUnit("haka.service");
+    $haka->succeed("hakactl status");
+    $haka->succeed("hakactl stop");
+  '';
+})
diff --git a/nixos/tests/initrd-network.nix b/nixos/tests/initrd-network.nix
new file mode 100644
index 000000000000..db9f572d3c2f
--- /dev/null
+++ b/nixos/tests/initrd-network.nix
@@ -0,0 +1,22 @@
+import ./make-test.nix ({ pkgs, ...} : {
+  name = "initrd-network";
+
+  meta.maintainers = [ pkgs.stdenv.lib.maintainers.eelco ];
+
+  machine = { config, pkgs, ... }: {
+    imports = [ ../modules/profiles/minimal.nix ];
+    boot.initrd.network.enable = true;
+    boot.initrd.network.postCommands =
+      ''
+        ip addr | grep 10.0.2.15 || exit 1
+        ping -c1 10.0.2.2 || exit 1
+      '';
+  };
+
+  testScript =
+    ''
+      startAll;
+      $machine->waitForUnit("multi-user.target");
+      $machine->succeed("ip link >&2");
+    '';
+})
diff --git a/nixos/tests/misc.nix b/nixos/tests/misc.nix
index 6297452df95e..73af0cfad21f 100644
--- a/nixos/tests/misc.nix
+++ b/nixos/tests/misc.nix
@@ -16,7 +16,7 @@ import ./make-test.nix ({ pkgs, ...} : {
       systemd.tmpfiles.rules = [ "d /tmp 1777 root root 10d" ];
       fileSystems = mkVMOverride { "/tmp2" =
         { fsType = "tmpfs";
-          options = "mode=1777,noauto";
+          options = [ "mode=1777" "noauto" ];
         };
       };
       systemd.automounts = singleton
diff --git a/nixos/tests/nfs.nix b/nixos/tests/nfs.nix
index 24f6e0f2ed95..36cd6a395779 100644
--- a/nixos/tests/nfs.nix
+++ b/nixos/tests/nfs.nix
@@ -8,7 +8,7 @@ let
         [ { mountPoint = "/data";
             device = "server:/data";
             fsType = "nfs";
-            options = "vers=${toString version}";
+            options = [ "vers=${toString version}" ];
           }
         ];
       networking.firewall.enable = false; # FIXME: only open statd