about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2014-09-06 16:51:14 +0200
committerVladimír Čunát <vcunat@gmail.com>2014-09-06 16:52:45 +0200
commit06fea81c6e3d71689b59df6e2bbc11fe01ce9056 (patch)
tree5849b904bf1eb3bc8cb28b29729d83a4d0337542 /nixos
parent20be024d1bae622409fa56844b2f8799bbf29bb0 (diff)
parent0c398f60405090743fbdcf14faf1193c642b6328 (diff)
downloadnixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar
nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.gz
nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.bz2
nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.lz
nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.xz
nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.zst
nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.zip
Merge recent master into staging
Hydra: ?compare=1150594
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/man-nixos-option.xml66
-rw-r--r--nixos/modules/config/pulseaudio.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl45
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh5
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh74
-rw-r--r--nixos/modules/installer/tools/tools.nix1
-rw-r--r--nixos/modules/installer/virtualbox-demo.nix3
-rw-r--r--nixos/modules/misc/ids.nix1
-rwxr-xr-x[-rw-r--r--]nixos/modules/module-list.nix5
-rw-r--r--nixos/modules/services/misc/mesos-master.nix103
-rw-r--r--nixos/modules/services/misc/mesos-slave.nix93
-rw-r--r--nixos/modules/services/misc/phd.nix52
-rw-r--r--nixos/modules/services/network-filesystems/diod.nix159
-rw-r--r--nixos/modules/services/network-filesystems/yandex-disk.nix104
-rw-r--r--nixos/modules/services/networking/copy-com.nix53
-rw-r--r--nixos/modules/services/networking/dnsmasq.nix19
-rw-r--r--nixos/modules/services/networking/nat.nix19
-rw-r--r--nixos/modules/services/networking/unbound.nix32
-rw-r--r--nixos/modules/services/printing/cupsd.nix24
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/phabricator.nix61
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix37
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl145
-rw-r--r--nixos/modules/tasks/cpu-freq.nix4
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix6
-rw-r--r--nixos/modules/tasks/network-interfaces.nix94
-rw-r--r--nixos/modules/virtualisation/docker.nix1
-rw-r--r--nixos/release-combined.nix5
-rw-r--r--nixos/release.nix3
-rw-r--r--nixos/tests/installer.nix40
-rw-r--r--nixos/tests/phabricator.nix7
31 files changed, 1032 insertions, 245 deletions
diff --git a/nixos/doc/manual/man-nixos-option.xml b/nixos/doc/manual/man-nixos-option.xml
index 7952847d4db5..554b29691805 100644
--- a/nixos/doc/manual/man-nixos-option.xml
+++ b/nixos/doc/manual/man-nixos-option.xml
@@ -17,11 +17,6 @@
 <refsynopsisdiv>
   <cmdsynopsis>
     <command>nixos-option</command>
-    <group choice="opt">
-      <option>-v</option>
-      <option>-d</option>
-      <option>-l</option>
-    </group>
     <arg choice='plain'><replaceable>option.name</replaceable></arg>
   </cmdsynopsis>
 </refsynopsisdiv>
@@ -31,50 +26,13 @@
 
 <para>This command evaluates the configuration specified in
 <filename>/etc/nixos/configuration.nix</filename> and returns the properties
-of the option name given as argument.  By default, it returns the value of
-the option.</para>
+of the option name given as argument.</para>
 
 <para>When the option name is not an option, the command prints the list of
 attributes contained in the attribute set.</para>
 
 </refsection>
 
-<refsection><title>Options</title>
-
-<para>This command accepts the following options:</para>
-
-<variablelist>
-
-  <varlistentry>
-    <term><option>--value</option>, <option>-v</option></term>
-    <listitem>
-      <para>Returns the value of the option.  This is the default operation
-      if no other options are defined.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>--description</option>, <option>-d</option></term>
-    <listitem>
-      <para>Return the default value, the example and the description of the
-      option when available.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><option>--lookup</option>, <option>-l</option></term>
-    <listitem>
-      <para>Return the locations where the option is declared and where it
-      is defined.  This is extremely useful to find sources of errors in
-      your configuration.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-</refsection>
-
-
 <refsection><title>Environment</title>
 
 <variablelist>
@@ -103,27 +61,21 @@ grub
 initScript
 
 $ nixos-option boot.loader.grub.enable
-true</screen></para>
+Value:
+true
 
-<para>Prints option information:
+Default: 
+true
 
-<screen>$ nixos-option -d networking.hostName
-Default: "nixos"
 Description:
-The name of the machine. Leave it empty if you want to obtain
-it from a DHCP server (if using DHCP).</screen></para>
-
-<para>Find the locations which are declaring and defining an option:
+Whether to enable the GNU GRUB boot loader.
 
-<screen>$ nixos-option -l hardware.firmware
 Declared by:
-  /mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix
+  "/path/to/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
 
 Defined by:
-  /path/to/nixpkgs/nixos/modules/system/boot/kernel.nix
-  /path/to/nixpkgs/nixos/modules/hardware/network/rt73.nix
-  /path/to/nixpkgs/nixos/modules/hardware/network/intel-3945abg.nix
-  /path/to/nixpkgs/nixos/modules/hardware/network/intel-2200bg.nix</screen></para>
+  "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
+</screen></para>
 
 </refsection>
 
diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix
index 1b84bbaf10c5..fb5715022b78 100644
--- a/nixos/modules/config/pulseaudio.nix
+++ b/nixos/modules/config/pulseaudio.nix
@@ -10,10 +10,12 @@ let
   systemWide = cfg.enable && cfg.systemWide;
   nonSystemWide = cfg.enable && !cfg.systemWide;
 
-  uid = config.ids.uids.pulseaudio;
-  gid = config.ids.gids.pulseaudio;
+  ids = config.ids;
 
-  stateDir = "/run/pulse";
+  uid = ids.uids.pulseaudio;
+  gid = ids.gids.pulseaudio;
+
+  stateDir = "/var/run/pulse";
 
   # Create pulse/client.conf even if PulseAudio is disabled so
   # that we can disable the autospawn feature in programs that
@@ -138,6 +140,8 @@ in {
         group = "pulse";
         extraGroups = [ "audio" ];
         description = "PulseAudio system service user";
+        home = stateDir;
+        createHome = true;
       };
 
       users.extraGroups.pulse.gid = gid;
@@ -147,10 +151,6 @@ in {
         wantedBy = [ "sound.target" ];
         before = [ "sound.target" ];
         environment.PULSE_RUNTIME_PATH = stateDir;
-        preStart = ''
-          mkdir -p --mode 755 ${stateDir}
-          chown -R pulse:pulse ${stateDir}
-        '';
         serviceConfig = {
           ExecStart = "${cfg.package}/bin/pulseaudio -D --log-level=${cfg.daemon.logLevel} --system --use-pid-file -n --file=${cfg.configFile}";
           PIDFile = "${stateDir}/pid";
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 623cfdedd269..22f31c460802 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -11,7 +11,7 @@ let
   # The Grub image.
   grubImage = pkgs.runCommand "grub_eltorito" {}
     ''
-      ${pkgs.grub2}/bin/grub-mkimage -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
+      ${pkgs.grub2}/bin/grub-mkimage -p /boot/grub -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
       cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out
     ''; # */
 
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index c507f7f979fa..e8f100d64984 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -20,6 +20,13 @@ sub uniq {
     return @res;
 }
 
+sub runCommand {
+    my ($cmd) = @_;
+    open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n";
+    my @ret = <FILE>;
+    close FILE;
+    return ($?, @ret);
+}
 
 # Process the command line.
 my $outDir = "/etc/nixos";
@@ -304,10 +311,13 @@ foreach my $fs (read_file("/proc/self/mountinfo")) {
 
     # Maybe this is a bind-mount of a filesystem we saw earlier?
     if (defined $fsByDev{$fields[2]}) {
-        my $path = $fields[3]; $path = "" if $path eq "/";
-        my $base = $fsByDev{$fields[2]};
-        $base = "" if $base eq "/";
-        $fileSystems .= <<EOF;
+        # Make sure this isn't a btrfs subvolume
+        my ($status, @msg) = runCommand("btrfs subvol show $rootDir$mountPoint");
+        if (join("", @msg) =~ /ERROR:/) {
+            my $path = $fields[3]; $path = "" if $path eq "/";
+            my $base = $fsByDev{$fields[2]};
+            $base = "" if $base eq "/";
+            $fileSystems .= <<EOF;
   fileSystems.\"$mountPoint\" =
     { device = \"$base$path\";
       fsType = \"none\";
@@ -315,7 +325,8 @@ foreach my $fs (read_file("/proc/self/mountinfo")) {
     };
 
 EOF
-        next;
+            next;
+        }
     }
     $fsByDev{$fields[2]} = $mountPoint;
 
@@ -337,6 +348,30 @@ EOF
         }
     }
 
+    # Is this a btrfs filesystem?
+    if ($fsType eq "btrfs") {
+        my ($status, @id_info) = runCommand("btrfs subvol show $rootDir$mountPoint");
+        if ($status != 0 || join("", @msg) =~ /ERROR:/) {
+            die "Failed to retreive subvolume info for $mountPoint\n";
+        }
+        my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/;
+        if ($#ids > 0) {
+            die "Btrfs subvol name for $mountPoint listed multiple times in mount\n"
+        } elsif ($#ids == 0) {
+            my ($status, @path_info) = runCommand("btrfs subvol list $rootDir$mountPoint");
+            if ($status != 0) {
+                die "Failed to find $mountPoint subvolume id from btrfs\n";
+            }
+            my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/;
+            if ($#paths > 0) {
+                die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n";
+            } elsif ($#paths != 0) {
+                die "Btrfs did not return a path for the subvolume at $mountPoint\n";
+            }
+            push @extraOptions, "subvol=$paths[0]";
+        }
+    }
+
     # Emit the filesystem.
     $fileSystems .= <<EOF;
   fileSystems.\"$mountPoint\" =
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
index 86952486ade0..bd334c2a3cb4 100644
--- a/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -7,6 +7,9 @@
 #   * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration>
 #   * install the boot loader
 
+# Ensure a consistent umask.
+umask 0022
+
 # Re-exec ourselves in a private mount namespace so that our bind
 # mounts get cleaned up automatically.
 if [ "$(id -u)" = 0 ]; then
@@ -243,7 +246,7 @@ chroot $mountPoint /nix/var/nix/profiles/system/activate
 # Ask the user to set a root password.
 if [ -t 0 ] ; then
     echo "setting root password..."
-    chroot $mountPoint passwd
+    chroot $mountPoint /var/setuid-wrappers/passwd
 fi
 
 
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
index edc94d732084..d995787c76fe 100644
--- a/nixos/modules/installer/tools/nixos-option.sh
+++ b/nixos/modules/installer/tools/nixos-option.sh
@@ -11,9 +11,6 @@ usage () {
 # Process Arguments #
 #####################
 
-desc=false
-defs=false
-value=false
 xml=false
 verbose=false
 
@@ -24,14 +21,11 @@ for arg; do
   if test -z "$argfun"; then
     case $arg in
       -*)
-        longarg=""
         sarg="$arg"
+        longarg=""
         while test "$sarg" != "-"; do
           case $sarg in
             --*) longarg=$arg; sarg="--";;
-            -d*) longarg="$longarg --description";;
-            -v*) longarg="$longarg --value";;
-            -l*) longarg="$longarg --lookup";;
             -*) usage;;
           esac
           # remove the first letter option
@@ -42,9 +36,6 @@ for arg; do
     esac
     for larg in $longarg; do
       case $larg in
-        --description) desc=true;;
-        --value) value=true;;
-        --lookup) defs=true;;
         --xml) xml=true;;
         --verbose) verbose=true;;
         --help) usage;;
@@ -67,16 +58,6 @@ for arg; do
   fi
 done
 
-if $xml; then
-  value=true
-  desc=true
-  defs=true
-fi
-
-if ! $defs && ! $desc; then
-  value=true
-fi
-
 if $verbose; then
   set -x
 else
@@ -95,8 +76,7 @@ evalAttr(){
   local prefix="$1"
   local strict="$2"
   local suffix="$3"
-  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" |
-    evalNix ${strict:+--strict}
+  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" | evalNix ${strict:+--strict}
 }
 
 evalOpt(){
@@ -189,35 +169,35 @@ EOF
 fi
 
 if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then
-  $value && evalCfg 1
-
-  if $desc; then
-    $value && echo;
-
-    if default=$(evalOpt "default" - 2> /dev/null); then
-      echo "Default: $default"
-    else
-      echo "Default: <None>"
-    fi
-    if example=$(evalOpt "example" - 2> /dev/null); then
-      echo "Example: $example"
-    fi
-    echo "Description:"
-    eval printf $(evalOpt "description")
+  echo "Value:"
+  evalCfg 1
+
+  echo
+
+  echo "Default:"
+  if default=$(evalOpt "default" - 2> /dev/null); then
+    echo "$default"
+  else
+    echo "<None>"
+  fi
+  echo
+  if example=$(evalOpt "example" - 2> /dev/null); then
+    echo "Example: $example"
   fi
+  echo "Description:"
+  echo
+  eval printf $(evalOpt "description")
 
-  if $defs; then
-    $desc || $value && echo;
+  echo $desc;
 
-    printPath () { echo "  $1"; }
+  printPath () { echo "  $1"; }
 
-    echo "Declared by:"
-    nixMap printPath "$(findSources "declarations")"
-    echo ""
-    echo "Defined by:"
-    nixMap printPath "$(findSources "files")"
-    echo ""
-  fi
+  echo "Declared by:"
+  nixMap printPath "$(findSources "declarations")"
+  echo
+  echo "Defined by:"
+  nixMap printPath "$(findSources "files")"
+  echo
 
 else
   # echo 1>&2 "Warning: This value is not an option."
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 39da2f1f0be6..91a30695a7a5 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -38,6 +38,7 @@ let
   nixos-generate-config = makeProg {
     name = "nixos-generate-config";
     src = ./nixos-generate-config.pl;
+    path = [ pkgs.btrfsProgs ];
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
   };
 
diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix
index f68f8dc40aa8..49ec08996104 100644
--- a/nixos/modules/installer/virtualbox-demo.nix
+++ b/nixos/modules/installer/virtualbox-demo.nix
@@ -10,6 +10,9 @@ with lib;
       ../profiles/clone-config.nix
     ];
 
+  # FIXME: UUID detection is currently broken
+  boot.loader.grub.fsIdentifier = "provided";
+
   # Allow mounting of shared folders.
   users.extraUsers.demo.extraGroups = [ "vboxsf" ];
 
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index efd8b253cd4c..37531ad1cdfd 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -150,6 +150,7 @@
       zookeeper = 140;
       dnsmasq = 141;
       uhub = 142;
+      yandexdisk=143;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 76d1ed8a9d43..61a98ca12ffb 100644..100755
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -161,10 +161,13 @@
   ./services/misc/folding-at-home.nix
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
+  ./services/misc/mesos-master.nix
+  ./services/misc/mesos-slave.nix
   ./services/misc/nix-daemon.nix
   ./services/misc/nix-gc.nix
   ./services/misc/nixos-manual.nix
   ./services/misc/nix-ssh-serve.nix
+  ./services/misc/phd.nix
   ./services/misc/rippled.nix
   ./services/misc/rogue.nix
   ./services/misc/siproxd.nix
@@ -192,6 +195,8 @@
   ./services/network-filesystems/openafs-client/default.nix
   ./services/network-filesystems/rsyncd.nix
   ./services/network-filesystems/samba.nix
+  ./services/network-filesystems/diod.nix
+  ./services/network-filesystems/yandex-disk.nix
   ./services/networking/amuled.nix
   ./services/networking/atftpd.nix
   ./services/networking/avahi-daemon.nix
diff --git a/nixos/modules/services/misc/mesos-master.nix b/nixos/modules/services/misc/mesos-master.nix
new file mode 100644
index 000000000000..bdf88d427c5d
--- /dev/null
+++ b/nixos/modules/services/misc/mesos-master.nix
@@ -0,0 +1,103 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mesos.master;
+  
+in {
+
+  options.services.mesos = {
+    
+    master = {
+      enable = mkOption {
+        description = "Whether to enable the Mesos Master.";
+        default = false;
+        type = types.uniq types.bool;
+      };
+
+      port = mkOption {
+        description = "Mesos Master port";
+        default = 5050;
+        type = types.int;
+      };
+
+      zk = mkOption {
+        description = ''
+          ZooKeeper URL (used for leader election amongst masters).
+          May be one of:
+            zk://host1:port1,host2:port2,.../mesos
+            zk://username:password@host1:port1,host2:port2,.../mesos
+        '';
+        type = types.str;
+      };
+      
+      workDir = mkOption {
+        description = "The Mesos work directory.";
+        default = "/var/lib/mesos/master";
+        type = types.str;
+      };
+      
+      extraCmdLineOptions = mkOption {
+        description = ''
+	  Extra command line options for Mesos Master.
+	  
+	  See https://mesos.apache.org/documentation/latest/configuration/
+	'';
+        default = [ "" ];
+        type = types.listOf types.string;
+        example = [ "--credentials=VALUE" ];
+      };
+      
+      quorum = mkOption {
+        description = ''
+          The size of the quorum of replicas when using 'replicated_log' based
+          registry. It is imperative to set this value to be a majority of
+          masters i.e., quorum > (number of masters)/2.
+          
+          If 0 will fall back to --registry=in_memory.
+        '';
+        default = 0;
+        type = types.int;
+      };
+      
+      logLevel = mkOption {
+        description = ''
+          The logging level used. Possible values:
+            'INFO', 'WARNING', 'ERROR'
+        '';
+        default = "INFO";
+        type = types.str;
+      };
+
+    };
+
+
+  };
+
+
+  config = mkIf cfg.enable {
+    systemd.services.mesos-master = {
+      description = "Mesos Master";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      serviceConfig = {
+	ExecStart = ''
+	  ${pkgs.mesos}/bin/mesos-master \
+	    --port=${toString cfg.port} \
+	    --zk=${cfg.zk} \
+	    ${if cfg.quorum == 0 then "--registry=in_memory" else "--registry=replicated_log --quorum=${cfg.quorum}"} \
+	    --work_dir=${cfg.workDir} \
+	    --logging_level=${cfg.logLevel} \
+	    ${toString cfg.extraCmdLineOptions}
+	'';
+	PermissionsStartOnly = true;
+      };
+      preStart = ''
+	mkdir -m 0700 -p ${cfg.workDir}
+      '';
+    };
+  };
+  
+}
+
diff --git a/nixos/modules/services/misc/mesos-slave.nix b/nixos/modules/services/misc/mesos-slave.nix
new file mode 100644
index 000000000000..e9a898167161
--- /dev/null
+++ b/nixos/modules/services/misc/mesos-slave.nix
@@ -0,0 +1,93 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mesos.slave;
+  
+in {
+
+  options.services.mesos = {
+    slave = {
+      enable = mkOption {
+        description = "Whether to enable the Mesos Slave.";
+        default = false;
+        type = types.uniq types.bool;
+      };
+
+      port = mkOption {
+        description = "Mesos Slave port";
+        default = 5051;
+        type = types.int;
+      };
+
+      master = mkOption {
+        description = ''
+          May be one of:
+            zk://host1:port1,host2:port2,.../path
+            zk://username:password@host1:port1,host2:port2,.../path
+        '';
+        type = types.str;
+      };
+      
+      withHadoop = mkOption {
+	description = "Add the HADOOP_HOME to the slave.";
+	default = false;
+	type = types.bool;
+      };
+      
+      workDir = mkOption {
+        description = "The Mesos work directory.";
+        default = "/var/lib/mesos/slave";
+        type = types.str;
+      };
+      
+      extraCmdLineOptions = mkOption {
+        description = ''
+	  Extra command line options for Mesos Slave.
+	  
+	  See https://mesos.apache.org/documentation/latest/configuration/
+	'';
+        default = [ "" ];
+        type = types.listOf types.string;
+        example = [ "--gc_delay=3days" ];
+      };
+      
+      logLevel = mkOption {
+        description = ''
+          The logging level used. Possible values:
+            'INFO', 'WARNING', 'ERROR'
+        '';
+        default = "INFO";
+        type = types.str;
+      };
+
+    };
+
+  };
+
+
+  config = mkIf cfg.enable {
+    systemd.services.mesos-slave = {
+      description = "Mesos Slave";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-interfaces.target" ];
+      serviceConfig = {
+	ExecStart = ''
+	  ${pkgs.mesos}/bin/mesos-slave \
+	    --port=${toString cfg.port} \
+	    --master=${cfg.master} \
+	    ${optionalString cfg.withHadoop "--hadoop-home=${pkgs.hadoop}"} \
+	    --work_dir=${cfg.workDir} \
+	    --logging_level=${cfg.logLevel} \
+	    ${toString cfg.extraCmdLineOptions}
+	'';
+	PermissionsStartOnly = true;
+      };
+      preStart = ''
+	mkdir -m 0700 -p ${cfg.workDir}
+      '';
+    };
+  };
+  
+}
\ No newline at end of file
diff --git a/nixos/modules/services/misc/phd.nix b/nixos/modules/services/misc/phd.nix
new file mode 100644
index 000000000000..e605ce5de16e
--- /dev/null
+++ b/nixos/modules/services/misc/phd.nix
@@ -0,0 +1,52 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.phd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.phd = {
+
+      enable = mkOption {
+        default = false;
+        description = "
+          Enable daemons for phabricator.
+        ";
+      };
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.phd = {
+      path = [ pkgs.phabricator pkgs.php pkgs.mercurial pkgs.git pkgs.subversion ];
+
+      after = [ "httpd.service" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.phabricator}/phabricator/bin/phd start";
+        ExecStop = "${pkgs.phabricator}/phabricator/bin/phd stop";
+        User = "wwwrun";
+        RestartSec = "30s";
+        Restart = "always";
+        StartLimitInterval = "1m";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/network-filesystems/diod.nix b/nixos/modules/services/network-filesystems/diod.nix
new file mode 100644
index 000000000000..1ab5f52d438c
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/diod.nix
@@ -0,0 +1,159 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  cfg = config.services.diod;
+
+  diodBool = b: if b then "1" else "0";
+
+  diodConfig = pkgs.writeText "diod.conf" ''
+    allsquash = ${diodBool cfg.allsquash}
+    auth_required = ${diodBool cfg.authRequired}
+    exportall = ${diodBool cfg.exportall}
+    exportopts = "${concatStringsSep "," cfg.exportopts}"
+    exports = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.exports)} }
+    listen = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.listen)} }
+    logdest = "${cfg.logdest}"
+    nwthreads = ${toString cfg.nwthreads}
+    squashuser = "${cfg.squashuser}"
+    statfs_passthru = ${diodBool cfg.statfsPassthru}
+    userdb = ${diodBool cfg.userdb}
+    ${cfg.extraConfig}
+  '';
+in
+{
+  options = {
+    services.diod = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the diod 9P file server.";
+      };
+
+      listen = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        description = ''
+          [ "IP:PORT" [,"IP:PORT",...] ]
+          List the interfaces and ports that diod should listen on.
+        '';
+      };
+
+      exports = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          List the file systems that clients will be allowed to mount. All paths should
+          be fully qualified. The exports table can include two types of element:
+          a string element (as above),
+          or an alternate table element form { path="/path", opts="ro" }.
+          In the alternate form, the (optional) opts attribute is a comma-separated list
+          of export options. The two table element forms can be mixed in the exports
+          table. Note that although diod will not traverse file system boundaries for a
+          given mount due to inode uniqueness constraints, subdirectories of a file
+          system can be separately exported.
+        '';
+      };
+
+      exportall = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Export all file systems listed in /proc/mounts. If new file systems are mounted
+          after diod has started, they will become immediately mountable. If there is a
+          duplicate entry for a file system in the exports list, any options listed in
+          the exports entry will apply.
+        '';
+      };
+
+      exportopts = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          Establish a default set of export options. These are overridden, not appended
+          to, by opts attributes in an "exports" entry.
+        '';
+      };
+
+      nwthreads = mkOption {
+        type = types.int;
+        default = 16;
+        description = ''
+          Sets the (fixed) number of worker threads created to handle 9P
+          requests for a unique aname.
+        '';
+      };
+
+      authRequired = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Allow clients to connect without authentication, i.e. without a valid MUNGE credential.
+        '';
+      };
+
+      userdb = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          This option disables password/group lookups. It allows any uid to attach and
+          assumes gid=uid, and supplementary groups contain only the primary gid.
+        '';
+      };
+
+      allsquash = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Remap all users to "nobody". The attaching user need not be present in the
+          password file.
+        '';
+      };
+
+      squashuser = mkOption {
+        type = types.str;
+        default = "nobody";
+        description = ''
+          Change the squash user. The squash user must be present in the password file.
+        '';
+      };
+
+      logdest = mkOption {
+        type = types.str;
+        default = "syslog:daemon:err";
+        description = ''
+          Set the destination for logging.
+          The value has the form of "syslog:facility:level" or "filename".
+        '';
+      };
+
+
+      statfsPassthru = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          This option configures statfs to return the host file system's type
+          rather than V9FS_MAGIC.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = "Extra configuration options for diod.conf.";
+      };
+    };
+  };
+
+  config = mkIf config.services.diod.enable {
+    environment.systemPackages = [ pkgs.diod ];
+
+    systemd.services.diod = {
+      description = "diod 9P file server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.diod}/sbin/diod -c ${diodConfig}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/yandex-disk.nix b/nixos/modules/services/network-filesystems/yandex-disk.nix
new file mode 100644
index 000000000000..df9626d17c92
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/yandex-disk.nix
@@ -0,0 +1,104 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.services.yandex-disk;
+
+  dir = "/var/lib/yandex-disk";
+
+  u = if cfg.user != null then cfg.user else "yandexdisk";
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.yandex-disk = {
+
+      enable = mkOption {
+        default = false;
+        description = "
+          Whether to enable Yandex-disk client. See https://disk.yandex.ru/
+        ";
+      };
+
+      username = mkOption {
+        default = "";
+        type = types.string;
+        description = ''
+          Your yandex.com login name.
+        '';
+      };
+
+      password = mkOption {
+        default = "";
+        type = types.string;
+        description = ''
+          Your yandex.com password. Warning: it will be world-readable in /nix/store.
+        '';
+      };
+
+      user = mkOption {
+        default = null;
+        description = ''
+          The user the yandex-disk daemon should run as.
+        '';
+      };
+
+      directory = mkOption {
+        default = "/home/Yandex.Disk";
+        description = "The directory to use for Yandex.Disk storage";
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = mkIf (cfg.user == null) [ {
+      name = u;
+      uid = config.ids.uids.yandexdisk;
+      group = "nogroup";
+      home = dir;
+    } ];
+
+    systemd.services.yandex-disk = {
+      description = "Yandex-disk server";
+
+      after = [ "network.target" ];
+
+      wantedBy = [ "multi-user.target" ];
+
+      # FIXME: have to specify ${directory} here as well
+      unitConfig.RequiresMountsFor = dir;
+
+      script = ''
+        mkdir -p -m 700 ${dir}
+        chown ${u} ${dir}
+
+        if ! test -d "${cfg.directory}" ; then
+          mkdir -p -m 755 ${cfg.directory} ||
+            exit 1
+        fi
+
+        ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \
+          -c '${pkgs.yandex-disk}/bin/yandex-disk token -p ${cfg.password} ${cfg.username} ${dir}/token'
+
+        ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \
+          -c '${pkgs.yandex-disk}/bin/yandex-disk start --no-daemon -a ${dir}/token -d ${cfg.directory}'
+      '';
+
+    };
+  };
+
+}
+
diff --git a/nixos/modules/services/networking/copy-com.nix b/nixos/modules/services/networking/copy-com.nix
new file mode 100644
index 000000000000..36bd29109b8a
--- /dev/null
+++ b/nixos/modules/services/networking/copy-com.nix
@@ -0,0 +1,53 @@
+{ config, lib, pkgs, ... }:

+

+with lib;

+

+let

+  

+  cfg = config.services.copy-com;

+

+in 

+

+{

+  options = {

+

+    services.copy-com = {

+	  

+	  enable = mkOption {

+          default = false;

+          description = "

+            Enable the copy.com client.

+

+            The first time copy.com is run, it needs to be configured. Before enabling run 

+            copy_console manually.

+          ";

+      };

+

+      user = mkOption {

+        description = "The user for which copy should run.";

+      };

+

+      debug = mkOption {

+        default = false;

+        description = "Output more.";

+      };

+	  };

+  };

+

+  config = mkIf cfg.enable {

+    environment.systemPackages = [ pkgs.postfix ];

+

+    systemd.services."copy-com-${cfg.user}" = {

+      description = "Copy.com Client";

+      after = [ "network.target" "local-fs.target" ];

+      wantedBy = [ "multi-user.target" ];

+      serviceConfig = {

+        ExecStart = "${pkgs.copy-com}/bin/copy_console ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}";

+        User = "${cfg.user}";

+      };

+

+    };

+  };

+

+}

+

diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix
index d2a8af6ac8b1..5c68dd89fb12 100644
--- a/nixos/modules/services/networking/dnsmasq.nix
+++ b/nixos/modules/services/networking/dnsmasq.nix
@@ -11,7 +11,10 @@ let
       conf-file=/etc/dnsmasq-conf.conf
       resolv-file=/etc/dnsmasq-resolv.conf
     ''}
-      ${cfg.extraConfig}
+    ${flip concatMapStrings cfg.servers (server: ''
+      server=${server}
+    '')}
+    ${cfg.extraConfig}
   '';
 
 in
@@ -43,12 +46,10 @@ in
         default = [];
         example = [ "8.8.8.8" "8.8.4.4" ];
         description = ''
-          The parameter to dnsmasq -S.
+          The DNS servers which dnsmasq should query.
         '';
       };
 
-
-
       extraConfig = mkOption {
         type = types.string;
         default = "";
@@ -67,8 +68,8 @@ in
 
   config = mkIf config.services.dnsmasq.enable {
 
-    environment.systemPackages = [ dnsmasq ]
-      ++ (if cfg.resolveLocalQueries then [ pkgs.openresolv ] else []);
+    networking.nameservers =
+      optional cfg.resolveLocalQueries "127.0.0.1";
 
     services.dbus.packages = [ dnsmasq ];
 
@@ -83,10 +84,14 @@ in
         description = "dnsmasq daemon";
         after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
+        path = [ dnsmasq ];
+        preStart = ''
+          touch /etc/dnsmasq-{conf,resolv}.conf
+          dnsmasq --test
+        '';
         serviceConfig = {
           Type = "dbus";
           BusName = "uk.org.thekelleys.dnsmasq";
-          ExecStartPre = "${dnsmasq}/bin/dnsmasq --test";
           ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}";
           ExecReload = "${dnsmasq}/bin/kill -HUP $MAINPID";
         };
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index e8d9d00cc0a2..b6fa3b79eb2f 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -75,6 +75,17 @@ in
         '';
     };
 
+    networking.nat.forwardPorts = mkOption {
+      type = types.listOf types.attrs;
+      default = [];
+      example = [ { sourcePort = 8080; destination = "10.0.0.1:80"; } ];
+      description =
+        ''
+          List of forwarded ports from the external interface to
+          internal destinations by using DNAT.
+        '';
+    };
+
   };
 
 
@@ -118,6 +129,14 @@ in
                 -s '${range}' -o ${cfg.externalInterface} ${dest}
             '') cfg.internalIPs}
 
+            # NAT from external ports to internal ports.
+            ${concatMapStrings (fwd: ''
+              iptables -w -t nat -A PREROUTING \
+                -i ${cfg.externalInterface} -p tcp \
+                --dport ${builtins.toString fwd.sourcePort} \
+                -j DNAT --to-destination ${fwd.destination}
+            '') cfg.forwardPorts}
+
             echo 1 > /proc/sys/net/ipv4/ip_forward
           '';
 
diff --git a/nixos/modules/services/networking/unbound.nix b/nixos/modules/services/networking/unbound.nix
index 415ff13bdda5..73b10c1d5611 100644
--- a/nixos/modules/services/networking/unbound.nix
+++ b/nixos/modules/services/networking/unbound.nix
@@ -6,8 +6,6 @@ let
 
   cfg = config.services.unbound;
 
-  username = "unbound";
-
   stateDir = "/var/lib/unbound";
 
   access = concatMapStrings (x: "  access-control: ${x} allow\n") cfg.allowedAccess;
@@ -21,21 +19,13 @@ let
   confFile = pkgs.writeText "unbound.conf" ''
     server:
       directory: "${stateDir}"
-      username: ${username}
-      # make sure unbound can access entropy from inside the chroot.
-      # e.g. on linux the use these commands (on BSD, devfs(8) is used):
-      #      mount --bind -n /dev/random /etc/unbound/dev/random
-      # and  mount --bind -n /dev/log /etc/unbound/dev/log
+      username: unbound
       chroot: "${stateDir}"
-      # logfile: "${stateDir}/unbound.log"  #uncomment to use logfile.
-      pidfile: "${stateDir}/unbound.pid"
-      verbosity: 1      # uncomment and increase to get more logging.
+      pidfile: ""
       ${interfaces}
       ${access}
-
-    ${forward}
-
     ${cfg.extraConfig}
+    ${forward}
   '';
 
 in
@@ -82,7 +72,7 @@ in
     environment.systemPackages = [ pkgs.unbound ];
 
     users.extraUsers = singleton {
-      name = username;
+      name = "unbound";
       uid = config.ids.uids.unbound;
       description = "unbound daemon user";
       home = stateDir;
@@ -96,8 +86,18 @@ in
       wants = [" nss-lookup.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      path = [ pkgs.unbound ];
-      serviceConfig.ExecStart = "${pkgs.unbound}/sbin/unbound -d -c ${confFile}";
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}/dev/
+	cp ${confFile} ${stateDir}/unbound.conf
+	chown unbound ${stateDir}
+	touch ${stateDir}/dev/random
+        ${pkgs.utillinux}/bin/mount --bind -n /dev/random ${stateDir}/dev/random
+      '';
+
+      serviceConfig = {
+        ExecStart = "${pkgs.unbound}/sbin/unbound -d -c ${stateDir}/unbound.conf";
+        ExecStopPost="${pkgs.utillinux}/bin/umount ${stateDir}/dev/random";
+      };
     };
 
   };
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index d229c610669f..8a8085cad280 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -35,7 +35,7 @@ let
   bindir = pkgs.buildEnv {
     name = "cups-progs";
     paths = cfg.drivers;
-    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" ];
+    pathsToLink = [ "/lib/cups" "/share/cups" "/bin" "/etc/cups" ];
     postBuild = cfg.bindirCmds;
   };
 
@@ -89,6 +89,20 @@ in
         '';
       };
 
+      clientConf = mkOption {
+        type = types.lines;
+        default = "";
+        example =
+          ''
+            ServerName server.example.com
+            Encryption Never
+          '';
+        description = ''
+          The contents of the client configuration.
+          (<filename>client.conf</filename>)
+        '';
+      };
+
       drivers = mkOption {
         type = types.listOf types.path;
         example = literalExample "[ pkgs.splix ]";
@@ -124,6 +138,14 @@ in
 
     environment.systemPackages = [ cups ];
 
+    environment.variables.CUPS_SERVERROOT = "/etc/cups";
+
+    environment.etc = [
+      { source = pkgs.writeText "client.conf" cfg.clientConf;
+        target = "cups/client.conf";
+      }
+    ];
+
     services.dbus.packages = [ cups ];
 
     # Cups uses libusb to talk to printers, and does not use the
diff --git a/nixos/modules/services/web-servers/apache-httpd/phabricator.nix b/nixos/modules/services/web-servers/apache-httpd/phabricator.nix
index c7a9bdf68c56..e4e3aac8d411 100644
--- a/nixos/modules/services/web-servers/apache-httpd/phabricator.nix
+++ b/nixos/modules/services/web-servers/apache-httpd/phabricator.nix
@@ -1,35 +1,30 @@
 { config, lib, pkgs, ... }:
+
+with lib;
+
 let
-  phabricatorRoot = pkgs.stdenv.mkDerivation rec {
-    version = "2014-05-12";
-    name = "phabricator-${version}";
-    srcLibphutil = pkgs.fetchgit {
-        url = git://github.com/facebook/libphutil.git;
-        rev = "2f3b5a1cf6ea464a0250d4b1c653a795a90d2716";
-        sha256 = "9598cec400984dc149162f1e648814a54ea0cd34fcd529973dc83f5486fdd9fd";
-    };
-    srcArcanist = pkgs.fetchgit {
-        url = git://github.com/facebook/arcanist.git;
-        rev = "54c377448db8dbc40f0ca86d43c837d30e493485";
-        sha256 = "086db3c0d1154fbad23e7c6def31fd913384ee20247b329515838b669c3028e0";
-    };
-    srcPhabricator = pkgs.fetchgit {
-        url = git://github.com/facebook/phabricator.git;
-        rev = "1644ef185ecf1e9fca3eb6b16351ef46b19d110f";
-        sha256 = "e1135e4ba76d53f48aad4161563035414ed7e878f39a8a34a875a01b41b2a084";
-    };
-    
-    buildCommand = ''
-      mkdir -p $out
-      cp -R ${srcLibphutil} $out/libphutil
-      cp -R ${srcArcanist} $out/arcanist
-      cp -R ${srcPhabricator} $out/phabricator
-    '';
-  };
+  phabricatorRoot = pkgs.phabricator;
 in {
+
   enablePHP = true;
   extraApacheModules = [ "mod_rewrite" ];
   DocumentRoot = "${phabricatorRoot}/phabricator/webroot";
+
+  options = {
+      git = mkOption {
+          default = true;
+          description = "Enable git repositories.";
+      };
+      mercurial = mkOption {
+          default = true;
+          description = "Enable mercurial repositories.";
+      };
+      subversion = mkOption {
+          default = true;
+          description = "Enable subversion repositories.";
+      };
+  };
+
   extraConfig = ''
       DocumentRoot ${phabricatorRoot}/phabricator/webroot
 
@@ -38,4 +33,18 @@ in {
       RewriteRule ^/favicon.ico - [L,QSA]
       RewriteRule ^(.*)$ /index.php?__path__=$1 [B,L,QSA]
   '';
+
+  extraServerPath = [
+      "${pkgs.which}"
+      "${pkgs.diffutils}"
+      ] ++
+      (if config.mercurial then ["${pkgs.mercurial}"] else []) ++
+      (if config.subversion then ["${pkgs.subversion}"] else []) ++
+      (if config.git then ["${pkgs.git}"] else []);
+
+  startupScript = pkgs.writeScript "activatePhabricator" ''
+      mkdir -p /var/repo
+      chown wwwrun /var/repo
+  '';
+
 }
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index 0cc060db8f90..bc9a155ac95b 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -6,7 +6,8 @@ let
 
   cfg = config.boot.loader.grub;
 
-  realGrub = if cfg.version == 1 then pkgs.grub else pkgs.grub2;
+  realGrub = if cfg.version == 1 then pkgs.grub
+    else pkgs.grub2.override { zfsSupport = cfg.zfsSupport; };
 
   grub =
     # Don't include GRUB if we're only generating a GRUB menu (e.g.,
@@ -25,11 +26,12 @@ let
       inherit (cfg)
         version extraConfig extraPerEntryConfig extraEntries
         extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout
-        default devices explicitBootRoot;
+        default devices fsIdentifier;
       path = (makeSearchPath "bin" [
-        pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils
+        pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfsProgs
+        pkgs.utillinux
       ]) + ":" + (makeSearchPath "sbin" [
-        pkgs.mdadm
+        pkgs.mdadm pkgs.utillinux
       ]);
     });
 
@@ -209,12 +211,26 @@ in
         '';
       };
 
-      explicitBootRoot = mkOption {
-        default = "";
-        type = types.str;
+      fsIdentifier = mkOption {
+        default = "uuid";
+        type = types.addCheck types.str
+          (type: type == "uuid" || type == "label" || type == "provided");
         description = ''
-          The relative path of /boot within the parent volume. Leave empty
-          if /boot is not a btrfs subvolume.
+          Determines how grub will identify devices when generating the
+          configuration file. A value of uuid / label signifies that grub
+          will always resolve the uuid or label of the device before using
+          it in the configuration. A value of provided means that grub will
+          use the device name as show in <command>df</command> or
+          <command>mount</command>. Note, zfs zpools / datasets are ignored
+          and will always be mounted using their labels.
+        '';
+      };
+
+      zfsSupport = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether grub should be build against libzfs.
         '';
       };
 
@@ -260,6 +276,9 @@ in
           ${pkgs.coreutils}/bin/cp -pf "${v}" "/boot/${n}"
         '') config.boot.loader.grub.extraFiles);
 
+    assertions = [{ assertion = !cfg.zfsSupport || cfg.version == 2;
+                    message = "Only grub version 2 provides zfs support";}];
+
     })
 
   ];
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index b4900358a5dc..2dad8b36db32 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -1,5 +1,6 @@
 use strict;
 use warnings;
+use Class::Struct;
 use XML::LibXML;
 use File::Basename;
 use File::Path;
@@ -27,6 +28,14 @@ sub writeFile {
     close FILE or die;
 }
 
+sub runCommand {
+    my ($cmd) = @_;
+    open FILE, "$cmd 2>/dev/null |" or die "Failed to execute: $cmd\n";
+    my @ret = <FILE>;
+    close FILE;
+    return ($?, @ret);
+}
+
 my $grub = get("grub");
 my $grubVersion = int(get("version"));
 my $extraConfig = get("extraConfig");
@@ -39,7 +48,7 @@ my $configurationLimit = int(get("configurationLimit"));
 my $copyKernels = get("copyKernels") eq "true";
 my $timeout = int(get("timeout"));
 my $defaultEntry = int(get("default"));
-my $explicitBootRoot = get("explicitBootRoot");
+my $fsIdentifier = get("fsIdentifier");
 $ENV{'PATH'} = get("path");
 
 die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
@@ -48,23 +57,114 @@ print STDERR "updating GRUB $grubVersion menu...\n";
 
 mkpath("/boot/grub", 0, 0700);
 
-
 # Discover whether /boot is on the same filesystem as / and
 # /nix/store.  If not, then all kernels and initrds must be copied to
-# /boot, and all paths in the GRUB config file must be relative to the
-# root of the /boot filesystem.  `$bootRoot' is the path to be
-# prepended to paths under /boot.
-my $bootRoot = "/boot";
-if (stat("/")->dev != stat("/boot")->dev) {
-    $bootRoot = "";
-    $copyKernels = 1;
-} elsif (stat("/boot")->dev != stat("/nix/store")->dev) {
+# /boot.
+if (stat("/boot")->dev != stat("/nix/store")->dev) {
     $copyKernels = 1;
 }
 
-if ($explicitBootRoot ne "") {
-    $bootRoot = $explicitBootRoot;
+# Discover information about the location of /boot
+struct(Fs => {
+    device => '$',
+    type => '$',
+    mount => '$',
+});
+sub GetFs {
+    my ($dir) = @_;
+    my ($status, @dfOut) = runCommand("df -T $dir");
+    if ($status != 0 || $#dfOut != 1) {
+        die "Failed to retrieve output about $dir from `df`";
+    }
+    my @boot = split(/[ \n\t]+/, $dfOut[1]);
+    return Fs->new(device => $boot[0], type => $boot[1], mount => $boot[6]);
 }
+struct (Grub => {
+    path => '$',
+    search => '$',
+});
+my $driveid = 1;
+sub GrubFs {
+    my ($dir) = @_;
+    my $fs = GetFs($dir);
+    my $path = "/" . substr($dir, length($fs->mount));
+    my $search = "";
+
+    if ($grubVersion > 1) {
+        # ZFS is completely separate logic as zpools are always identified by a label
+        # or custom UUID
+        if ($fs->type eq 'zfs') {
+            my $sid = index($fs->device, '/');
+
+            if ($sid < 0) {
+                $search = '--label ' . $fs->device;
+                $path = '/@' . $path;
+            } else {
+                $search = '--label ' . substr($fs->device, 0, $sid);
+                $path = '/' . substr($fs->device, $sid) . '/@' . $path;
+            }
+        } else {
+            my %types = ('uuid' => '--fs-uuid', 'label' => '--label');
+
+            if ($fsIdentifier eq 'provided') {
+                # If the provided dev is identifying the partition using a label or uuid,
+                # we should get the label / uuid and do a proper search
+                my @matches = $fs->device =~ m/\/dev\/disk\/by-(label|uuid)\/(.*)/;
+                if ($#matches > 1) {
+                    die "Too many matched devices"
+                } elsif ($#matches == 1) {
+                    $search = "$types{$matches[0]} $matches[1]"
+                }
+            } else {
+                # Determine the identifying type
+                $search = $types{$fsIdentifier} . ' ';
+
+                # Based on the type pull in the identifier from the system
+                my ($status, @devInfo) = runCommand("blkid -o export @{[$fs->device]}");
+                if ($status != 0) {
+                    die "Failed to get blkid info for @{[$fs->mount]} on @{[$fs->device]}";
+                }
+                my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/;
+                if ($#matches != 0) {
+                    die "Couldn't find a $types{$fsIdentifier} for @{[$fs->device]}\n"
+                }
+                $search .= $matches[0];
+            }
+
+            # BTRFS is a special case in that we need to fix the referrenced path based on subvolumes
+            if ($fs->type eq 'btrfs') {
+                my ($status, @id_info) = runCommand("btrfs subvol show @{[$fs->mount]}");
+                if ($status != 0) {
+                    die "Failed to retrieve subvolume info for @{[$fs->mount]}\n";
+                }
+                my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/;
+                if ($#ids > 0) {
+                    die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n"
+                } elsif ($#ids == 0) {
+                    my ($status, @path_info) = runCommand("btrfs subvol list @{[$fs->mount]}");
+                    if ($status != 0) {
+                        die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n";
+                    }
+                    my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/;
+                    if ($#paths > 0) {
+                        die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n";
+                    } elsif ($#paths != 0) {
+                        die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n";
+                    }
+                    $path = "/$paths[0]$path";
+                }
+            }
+        }
+        if (not $search eq "") {
+            $search = "search --set=drive$driveid " . $search;
+            $path = "(\$drive$driveid)$path";
+            $driveid += 1;
+        }
+    }
+    return Grub->new(path => $path, search => $search);
+}
+my $grubBoot = GrubFs("/boot");
+my $grubStore = GrubFs("/nix/store");
 
 # Generate the header.
 my $conf .= "# Automatically generated.  DO NOT EDIT THIS FILE!\n";
@@ -76,12 +176,17 @@ if ($grubVersion == 1) {
     ";
     if ($splashImage) {
         copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n";
-        $conf .= "splashimage $bootRoot/background.xpm.gz\n";
+        $conf .= "splashimage " . $grubBoot->path . "/background.xpm.gz\n";
     }
 }
 
 else {
+    if ($copyKernels == 0) {
+        $conf .= "
+            " . $grubStore->search;
+    }
     $conf .= "
+        " . $grubBoot->search . "
         if [ -s \$prefix/grubenv ]; then
           load_env
         fi
@@ -102,7 +207,7 @@ else {
           set timeout=$timeout
         fi
 
-        if loadfont $bootRoot/grub/fonts/unicode.pf2; then
+        if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then
           set gfxmode=640x480
           insmod gfxterm
           insmod vbe
@@ -116,7 +221,7 @@ else {
         copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n";
         $conf .= "
             insmod png
-            if background_image $bootRoot/background.png; then
+            if background_image " . $grubBoot->path . "/background.png; then
               set color_normal=white/black
               set color_highlight=black/white
             else
@@ -138,7 +243,7 @@ mkpath("/boot/kernels", 0, 0755) if $copyKernels;
 
 sub copyToKernelsDir {
     my ($path) = @_;
-    return $path unless $copyKernels;
+    return $grubStore->path . substr($path, length("/nix/store")) unless $copyKernels;
     $path =~ /\/nix\/store\/(.*)/ or die;
     my $name = $1; $name =~ s/\//-/g;
     my $dst = "/boot/kernels/$name";
@@ -151,7 +256,7 @@ sub copyToKernelsDir {
         rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
     }
     $copied{$dst} = 1;
-    return "$bootRoot/kernels/$name";
+    return $grubBoot->path . "/kernels/$name";
 }
 
 sub addEntry {
@@ -178,6 +283,10 @@ sub addEntry {
         $conf .= "  " . ($xen ? "module" : "initrd") . " $initrd\n\n";
     } else {
         $conf .= "menuentry \"$name\" {\n";
+        $conf .= $grubBoot->search . "\n";
+        if ($copyKernels == 0) {
+            $conf .= $grubStore->search . "\n";
+        }
         $conf .= "  $extraPerEntryConfig\n" if $extraPerEntryConfig;
         $conf .= "  multiboot $xen $xenParams\n" if $xen;
         $conf .= "  " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";
@@ -195,7 +304,7 @@ addEntry("NixOS - Default", $defaultConfig);
 $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
 
 # extraEntries could refer to @bootRoot@, which we have to substitute
-$conf =~ s/\@bootRoot\@/$bootRoot/g;
+$conf =~ s/\@bootRoot\@/$grubBoot->path/g;
 
 # Emit submenus for all system profiles.
 sub addProfile {
diff --git a/nixos/modules/tasks/cpu-freq.nix b/nixos/modules/tasks/cpu-freq.nix
index a8c63c134287..70bbee8474eb 100644
--- a/nixos/modules/tasks/cpu-freq.nix
+++ b/nixos/modules/tasks/cpu-freq.nix
@@ -30,9 +30,7 @@ in
 
   config = mkIf (!config.boot.isContainer && config.powerManagement.cpuFreqGovernor != null) {
 
-    boot.kernelModules = [ "acpi-cpufreq" "speedstep-lib" "pcc-cpufreq"
-      "cpufreq_${cfg.cpuFreqGovernor}"
-    ];
+    boot.kernelModules = [ "cpufreq_${cfg.cpuFreqGovernor}" ];
 
     environment.systemPackages = [ cpupower ];
 
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index d7deb44c407c..1c4bbc16b499 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -133,7 +133,7 @@ in
       };
 
       boot.initrd = mkIf inInitrd {
-        kernelModules = [ "spl" "zfs" ] ;
+        kernelModules = [ "spl" "zfs" ];
         extraUtilsCommands =
           ''
             cp -v ${zfsPkg}/sbin/zfs $out/bin
@@ -148,6 +148,10 @@ in
           '';
       };
 
+      boot.loader.grub = mkIf inInitrd {
+        zfsSupport = true;
+      };
+
       systemd.services."zpool-import" = {
         description = "Import zpools";
         after = [ "systemd-udev-settle.service" ];
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index 2adb4bcfabab..868039177d87 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -1,6 +1,7 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, utils, ... }:
 
 with lib;
+with utils;
 
 let
 
@@ -10,6 +11,10 @@ let
   hasSits = cfg.sits != { };
   hasBonds = cfg.bonds != { };
 
+  # We must escape interfaces due to the systemd interpretation
+  subsystemDevice = interface:
+    "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
+
   addrOpts = v:
     assert v == 4 || v == 6;
     {
@@ -138,8 +143,6 @@ let
           Whether this interface is virtual and should be created by tunctl.
           This is mainly useful for creating bridges between a host a virtual
           network such as VPN or a virtual machine.
-
-          Defaults to tap device, unless interface contains "tun" in its name.
         '';
       };
 
@@ -151,6 +154,15 @@ let
         '';
       };
 
+      virtualType = mkOption {
+        default = null;
+        type = types.nullOr (types.addCheck types.str (v: v == "tun" || v == "tap"));
+        description = ''
+          The explicit type of interface to create. Accepts tun or tap strings.
+          Also accepts null to implicitly detect the type of device.
+        '';
+      };
+
       proxyARP = mkOption {
         default = false;
         type = types.bool;
@@ -596,8 +608,8 @@ in
           nameValuePair "${i.name}-cfg"
           { description = "Configuration of ${i.name}";
             wantedBy = [ "network-interfaces.target" ];
-            bindsTo = [ "sys-subsystem-net-devices-${i.name}.device" ];
-            after = [ "sys-subsystem-net-devices-${i.name}.device" ];
+            bindsTo = [ (subsystemDevice i.name) ];
+            after = [ (subsystemDevice i.name) ];
             serviceConfig.Type = "oneshot";
             serviceConfig.RemainAfterExit = true;
             path = [ pkgs.iproute pkgs.gawk ];
@@ -673,26 +685,32 @@ in
                 '');
           };
 
-        createTunDevice = i: nameValuePair "${i.name}"
+        createTunDevice = i: nameValuePair "${i.name}-netdev"
           { description = "Virtual Network Interface ${i.name}";
             requires = [ "dev-net-tun.device" ];
             after = [ "dev-net-tun.device" ];
-            wantedBy = [ "network.target" ];
-            requiredBy = [ "sys-subsystem-net-devices-${i.name}.device" ];
-            serviceConfig =
-              { Type = "oneshot";
-                RemainAfterExit = true;
-                ExecStart = "${pkgs.tunctl}/bin/tunctl -t '${i.name}' -u '${i.virtualOwner}'";
-                ExecStop = "${pkgs.tunctl}/bin/tunctl -d '${i.name}'";
-              };
+            wantedBy = [ "network.target" (subsystemDevice i.name) ];
+            path = [ pkgs.iproute ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+            };
+            script = ''
+              ip tuntap add dev "${i.name}" \
+              ${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \
+              user "${i.virtualOwner}"
+            '';
+            postStop = ''
+              ip link del ${i.name}
+            '';
           };
 
-        createBridgeDevice = n: v:
-          let
-            deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces;
+        createBridgeDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = map subsystemDevice v.interfaces;
           in
           { description = "Bridge Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -725,14 +743,14 @@ in
                 ip link set "${n}" down
                 brctl delbr "${n}"
               '';
-          };
+          });
 
-        createBondDevice = n: v:
-          let
-            deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces;
+        createBondDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = map subsystemDevice v.interfaces;
           in
           { description = "Bond Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -764,14 +782,14 @@ in
               ifenslave -d "${n}"
               ip link delete "${n}"
             '';
-          };
+          });
 
-        createSitDevice = n: v:
-          let
-            deps = optional (v.dev != null) "sys-subsystem-net-devices-${v.dev}.device";
+        createSitDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = optional (v.dev != null) (subsystemDevice v.dev);
           in
           { description = "6-to-4 Tunnel Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -790,14 +808,14 @@ in
             postStop = ''
               ip link delete "${n}"
             '';
-          };
+          });
 
-        createVlanDevice = n: v:
-          let
-            deps = [ "sys-subsystem-net-devices-${v.interface}.device" ];
+        createVlanDevice = n: v: nameValuePair "${n}-netdev"
+          (let
+            deps = [ (subsystemDevice v.interface) ];
           in
           { description = "Vlan Interface ${n}";
-            wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ];
+            wantedBy = [ "network.target" (subsystemDevice n) ];
             bindsTo = deps;
             after = deps;
             serviceConfig.Type = "oneshot";
@@ -812,15 +830,15 @@ in
             postStop = ''
               ip link delete "${n}"
             '';
-          };
+          });
 
       in listToAttrs (
            map configureInterface interfaces ++
            map createTunDevice (filter (i: i.virtual) interfaces))
-         // mapAttrs createBridgeDevice cfg.bridges
-         // mapAttrs createBondDevice cfg.bonds
-         // mapAttrs createSitDevice cfg.sits
-         // mapAttrs createVlanDevice cfg.vlans
+         // mapAttrs' createBridgeDevice cfg.bridges
+         // mapAttrs' createBondDevice cfg.bonds
+         // mapAttrs' createSitDevice cfg.sits
+         // mapAttrs' createVlanDevice cfg.vlans
          // { "network-setup" = networkSetup; };
 
     # Set the host and domain names in the activation script.  Don't
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index a0aa61353269..1ce066cdc73d 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -59,6 +59,7 @@ in
 
   config = mkIf cfg.enable (mkMerge [
     { environment.systemPackages = [ pkgs.docker ];
+      users.extraGroups.docker.gid = config.ids.gids.docker;
     }
     (mkIf cfg.socketActivation {
 
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index dae3b9210a86..0c72bae35bbc 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -52,6 +52,11 @@ in rec {
         (all nixos.tests.installer.lvm)
         (all nixos.tests.installer.separateBoot)
         (all nixos.tests.installer.simple)
+        (all nixos.tests.installer.simpleLabels)
+        (all nixos.tests.installer.simpleProvided)
+        (all nixos.tests.installer.btrfsSimple)
+        (all nixos.tests.installer.btrfsSubvols)
+        (all nixos.tests.installer.btrfsSubvolDefault)
         (all nixos.tests.ipv6)
         (all nixos.tests.kde4)
         (all nixos.tests.login)
diff --git a/nixos/release.nix b/nixos/release.nix
index e2b93640f917..d4e1a3737e3b 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -231,7 +231,8 @@ in rec {
   tests.installer.simpleLabels = forAllSystems (system: (import tests/installer.nix { inherit system; }).simpleLabels.test);
   tests.installer.simpleProvided = forAllSystems (system: (import tests/installer.nix { inherit system; }).simpleProvided.test);
   tests.installer.btrfsSimple = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSimple.test);
-  #tests.installer.btrfsSubvols = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvols.test);
+  tests.installer.btrfsSubvols = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvols.test);
+  tests.installer.btrfsSubvolDefault = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test);
   tests.influxdb = callTest tests/influxdb.nix {};
   tests.ipv6 = callTest tests/ipv6.nix {};
   tests.jenkins = callTest tests/jenkins.nix {};
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 6ee52fd63d8b..66ab2567e197 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -35,8 +35,8 @@ let
 
 
   # The configuration to install.
-  makeConfig = { testChannel, useEFI, grubVersion, grubDevice }: pkgs.writeText "configuration.nix"
-    ''
+  makeConfig = { testChannel, useEFI, grubVersion, grubDevice, grubIdentifier }:
+    pkgs.writeText "configuration.nix" ''
       { config, pkgs, modulesPath, ... }:
 
       { imports =
@@ -54,6 +54,7 @@ let
           ''}
           boot.loader.grub.device = "${grubDevice}";
           boot.loader.grub.extraConfig = "serial; terminal_output.serial";
+          boot.loader.grub.fsIdentifier = "${grubIdentifier}";
         ''}
 
         environment.systemPackages = [ ${optionalString testChannel "pkgs.rlwrap"} ];
@@ -93,7 +94,7 @@ let
   # disk, and then reboot from the hard disk.  It's parameterized with
   # a test script fragment `createPartitions', which must create
   # partitions and filesystems.
-  testScriptFun = { createPartitions, testChannel, useEFI, grubVersion, grubDevice }:
+  testScriptFun = { createPartitions, testChannel, useEFI, grubVersion, grubDevice, grubIdentifier }:
     let
       # FIXME: OVMF doesn't boot from virtio http://www.mail-archive.com/edk2-devel@lists.sourceforge.net/msg01501.html
       iface = if useEFI || grubVersion == 1 then "scsi" else "virtio";
@@ -161,7 +162,7 @@ let
       $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2");
 
       $machine->copyFileFromHost(
-          "${ makeConfig { inherit testChannel useEFI grubVersion grubDevice; } }",
+          "${ makeConfig { inherit testChannel useEFI grubVersion grubDevice grubIdentifier; } }",
           "/mnt/etc/nixos/configuration.nix");
 
       # Perform the installation.
@@ -216,13 +217,13 @@ let
 
 
   makeInstallerTest = name:
-    { createPartitions, testChannel ? false, useEFI ? false, grubVersion ? 2, grubDevice ? "/dev/vda" }:
+    { createPartitions, testChannel ? false, useEFI ? false, grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid" }:
     makeTest {
       inherit iso;
       name = "installer-" + name;
       nodes = if testChannel then { inherit webserver; } else { };
       testScript = testScriptFun {
-        inherit createPartitions testChannel useEFI grubVersion grubDevice;
+        inherit createPartitions testChannel useEFI grubVersion grubDevice grubIdentifier;
       };
     };
 
@@ -461,11 +462,36 @@ in {
         "mount LABEL=root /mnt",
         "btrfs subvol create /mnt/boot",
         "btrfs subvol create /mnt/nixos",
+        "btrfs subvol create /mnt/nixos/default",
         "umount /mnt",
-        "mount -o defaults,subvol=nixos LABEL=root /mnt",
+        "mount -o defaults,subvol=nixos/default LABEL=root /mnt",
         "mkdir /mnt/boot",
         "mount -o defaults,subvol=boot LABEL=root /mnt/boot",
       );
     '';
   };
+
+  # Test to see if we can detect default and aux subvolumes correctly
+  btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" {
+    createPartitions = ''
+      $machine->succeed(
+        "sgdisk -Z /dev/vda",
+        "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+        "mkswap /dev/vda2 -L swap",
+        "swapon -L swap",
+        "mkfs.btrfs -L root /dev/vda3",
+        "btrfs device scan",
+        "mount LABEL=root /mnt",
+        "btrfs subvol create /mnt/badpath",
+        "btrfs subvol create /mnt/badpath/boot",
+        "btrfs subvol create /mnt/nixos",
+        "btrfs subvol set-default \$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt",
+        "umount /mnt",
+        "mount -o defaults LABEL=root /mnt",
+        "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism is actually looking up subvolumes
+        "mkdir /mnt/boot",
+        "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot",
+      );
+    '';
+  };
 }
diff --git a/nixos/tests/phabricator.nix b/nixos/tests/phabricator.nix
index 53038474c91a..0fe31f66502d 100644
--- a/nixos/tests/phabricator.nix
+++ b/nixos/tests/phabricator.nix
@@ -32,9 +32,16 @@ import ./make-test.nix ({ pkgs, ... }: {
             }];
           };
 
+          phd = {
+            enable = true;
+          };
+
           mysql = {
             enable = true;
             package = pkgs.mysql;
+            extraOptions = ''
+              sql_mode=STRICT_ALL_TABLES
+            '';
           };
         };