summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/configuration.xml1
-rw-r--r--nixos/doc/manual/default.nix6
-rw-r--r--nixos/modules/config/update-users-groups.pl4
-rw-r--r--nixos/modules/security/hidepid.nix19
-rw-r--r--nixos/modules/security/setuid-wrappers.nix26
-rw-r--r--nixos/modules/services/editors/emacs.nix2
-rw-r--r--nixos/modules/services/misc/gitit.nix2
-rw-r--r--nixos/modules/services/networking/zerotierone.nix16
-rw-r--r--nixos/modules/system/activation/activation-script.nix12
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh26
-rw-r--r--nixos/modules/system/boot/stage-1.nix4
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh29
-rw-r--r--nixos/modules/system/boot/stage-2.nix3
-rw-r--r--nixos/modules/tasks/filesystems.nix63
-rw-r--r--nixos/modules/virtualisation/amazon-grow-partition.nix24
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix4
-rw-r--r--nixos/modules/virtualisation/grow-partition.nix43
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix7
18 files changed, 178 insertions, 113 deletions
diff --git a/nixos/doc/manual/configuration/configuration.xml b/nixos/doc/manual/configuration/configuration.xml
index 9589f3c6276f..448e2a932e91 100644
--- a/nixos/doc/manual/configuration/configuration.xml
+++ b/nixos/doc/manual/configuration/configuration.xml
@@ -24,7 +24,6 @@ effect after you run <command>nixos-rebuild</command>.</para>
 <xi:include href="networking.xml" />
 <xi:include href="linux-kernel.xml" />
 
-<xi:include href="emacs.xml" />
 <xi:include href="modules.xml" xpointer="xpointer(//section[@id='modules']/*)" />
 
 <!-- Apache; libvirtd virtualisation -->
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 0f0c6e66e4c0..13668dfd8ebc 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -63,12 +63,6 @@ let
     ''
       cp -prd $sources/* . # */
       chmod -R u+w .
-      cp ${../../modules/services/databases/postgresql.xml} configuration/postgresql.xml
-      cp ${../../modules/services/misc/gitlab.xml} configuration/gitlab.xml
-      cp ${../../modules/services/misc/taskserver/doc.xml} configuration/taskserver.xml
-      cp ${../../modules/security/acme.xml} configuration/acme.xml
-      cp ${../../modules/i18n/input-method/default.xml} configuration/input-methods.xml
-      cp ${../../modules/services/editors/emacs.xml} configuration/emacs.xml
       ln -s ${modulesDoc} configuration/modules.xml
       ln -s ${optionsDocBook} options-db.xml
       echo "${version}" > version
diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl
index 967f427374b1..cbbe216e5a17 100644
--- a/nixos/modules/config/update-users-groups.pl
+++ b/nixos/modules/config/update-users-groups.pl
@@ -52,8 +52,8 @@ foreach my $g (@{$spec->{groups}}) {
     $gidsUsed{$g->{gid}} = 1 if defined $g->{gid};
 }
 
-foreach my $u (@{$spec->{groups}}) {
-    $uidsUsed{$u->{u}} = 1 if defined $u->{uid};
+foreach my $u (@{$spec->{users}}) {
+    $uidsUsed{$u->{uid}} = 1 if defined $u->{uid};
 }
 
 # Read the current /etc/group.
diff --git a/nixos/modules/security/hidepid.nix b/nixos/modules/security/hidepid.nix
index 8271578c55d6..4917327d617c 100644
--- a/nixos/modules/security/hidepid.nix
+++ b/nixos/modules/security/hidepid.nix
@@ -20,23 +20,6 @@ with lib;
   config = mkIf config.security.hideProcessInformation {
     users.groups.proc.gid = config.ids.gids.proc;
 
-    systemd.services.hidepid = {
-      wantedBy = [ "local-fs.target" ];
-      after = [ "systemd-remount-fs.service" ];
-      before = [ "local-fs-pre.target" "local-fs.target" "shutdown.target" ];
-      wants = [ "local-fs-pre.target" ];
-
-      serviceConfig = {
-        Type = "oneshot";
-        RemainAfterExit = true;
-        ExecStart = ''${pkgs.utillinux}/bin/mount -o remount,hidepid=2,gid=${toString config.ids.gids.proc} /proc'';
-        ExecStop = ''${pkgs.utillinux}/bin/mount -o remount,hidepid=0,gid=0 /proc'';
-      };
-
-      unitConfig = {
-        DefaultDependencies = false;
-        Conflicts = "shutdown.target";
-      };
-    };
+    fileSystems."/proc".options = [ "hidepid=2" "gid=${toString config.ids.gids.proc}" ];
   };
 }
diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix
index 99dd514feea3..162b3a2cec7d 100644
--- a/nixos/modules/security/setuid-wrappers.nix
+++ b/nixos/modules/security/setuid-wrappers.nix
@@ -102,11 +102,11 @@ in
                 source=/nix/var/nix/profiles/default/bin/${program}
             fi
 
-            cp ${setuidWrapper}/bin/setuid-wrapper ${wrapperDir}/${program}
-            echo -n "$source" > ${wrapperDir}/${program}.real
-            chmod 0000 ${wrapperDir}/${program} # to prevent races
-            chown ${owner}.${group} ${wrapperDir}/${program}
-            chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" ${wrapperDir}/${program}
+            cp ${setuidWrapper}/bin/setuid-wrapper $wrapperDir/${program}
+            echo -n "$source" > $wrapperDir/${program}.real
+            chmod 0000 $wrapperDir/${program} # to prevent races
+            chown ${owner}.${group} $wrapperDir/${program}
+            chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" $wrapperDir/${program}
           '';
 
       in stringAfter [ "users" ]
@@ -115,9 +115,23 @@ in
           # programs to be wrapped.
           SETUID_PATH=${config.system.path}/bin:${config.system.path}/sbin
 
-          rm -f ${wrapperDir}/* # */
+          mkdir -p /run/setuid-wrapper-dirs
+          wrapperDir=$(mktemp --directory --tmpdir=/run/setuid-wrapper-dirs setuid-wrappers.XXXXXXXXXX)
 
           ${concatMapStrings makeSetuidWrapper setuidPrograms}
+
+          if [ -d ${wrapperDir} ]; then
+            mv --no-target-directory ${wrapperDir} ${wrapperDir}-old
+            ln --symbolic $wrapperDir ${wrapperDir}
+            rm --force --recursive ${wrapperDir}-old
+          elif [ -L ${wrapperDir} ]; then
+            ln --symbolic --force --no-dereference $wrapperDir ${wrapperDir}-tmp
+            old=$(readlink ${wrapperDir})
+            mv --no-target-directory ${wrapperDir}-tmp ${wrapperDir}
+            rm --force --recursive $old
+          else
+            ln --symbolic $wrapperDir ${wrapperDir}
+          fi
         '';
 
   };
diff --git a/nixos/modules/services/editors/emacs.nix b/nixos/modules/services/editors/emacs.nix
index 43b4219c51dd..6795ec52fe4d 100644
--- a/nixos/modules/services/editors/emacs.nix
+++ b/nixos/modules/services/editors/emacs.nix
@@ -83,4 +83,6 @@ in {
       EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor";
     } else {};
   };
+
+  meta.doc = ./emacs.xml;
 }
diff --git a/nixos/modules/services/misc/gitit.nix b/nixos/modules/services/misc/gitit.nix
index befd8c628f16..44880ebeda14 100644
--- a/nixos/modules/services/misc/gitit.nix
+++ b/nixos/modules/services/misc/gitit.nix
@@ -663,7 +663,7 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       path = with pkgs; [ curl ]
-             ++ optional cfg.pdfExport texLiveFull
+             ++ optional cfg.pdfExport texlive.combined.scheme-basic
 	     ++ optional (cfg.repositoryType == "darcs") darcs
 	     ++ optional (cfg.repositoryType == "mercurial") mercurial
 	     ++ optional (cfg.repositoryType == "git") git;
diff --git a/nixos/modules/services/networking/zerotierone.nix b/nixos/modules/services/networking/zerotierone.nix
index e66648f683f4..86e0204ec2f7 100644
--- a/nixos/modules/services/networking/zerotierone.nix
+++ b/nixos/modules/services/networking/zerotierone.nix
@@ -7,11 +7,19 @@ let
 in
 {
   options.services.zerotierone.enable = mkEnableOption "ZeroTierOne";
-  
+  options.services.zerotierone.package = mkOption {
+    default = pkgs.zerotierone;
+    defaultText = "pkgs.zerotierone";
+    type = types.package;
+    description = ''
+      ZeroTier One package to use.
+    '';
+  };
+
   config = mkIf cfg.enable {
     systemd.services.zerotierone = {
       description = "ZeroTierOne";
-      path = [ pkgs.zerotierone ];
+      path = [ cfg.package ];
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart =
@@ -21,7 +29,7 @@ in
         chown -R root:root /var/lib/zerotier-one
         '';
       serviceConfig = {
-        ExecStart = "${pkgs.zerotierone}/bin/zerotier-one";
+        ExecStart = "${cfg.package}/bin/zerotier-one";
         Restart = "always";
         KillMode = "process";
       };
@@ -30,6 +38,6 @@ in
     # ZeroTier does not issue DHCP leases, but some strangers might...
     networking.dhcpcd.denyInterfaces = [ "zt0" ];
 
-    environment.systemPackages = [ pkgs.zerotierone ];
+    environment.systemPackages = [ cfg.package ];
   };
 }
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index 4489e34831da..1c587413121e 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -154,9 +154,15 @@ in
 
     system.activationScripts.tmpfs =
       ''
-        ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.devSize}" none /dev
-        ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.devShmSize}" none /dev/shm
-        ${pkgs.utillinux}/bin/mount -o "remount,size=${config.boot.runSize}" none /run
+        specialMount() {
+          local device="$1"
+          local mountPoint="$2"
+          local options="$3"
+          local fsType="$4"
+
+          ${pkgs.utillinux}/bin/mount -t "$fsType" -o "remount,$options" "$device" "$mountPoint"
+        }
+        source ${config.system.build.earlyMountScript}
       '';
 
   };
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 65d1dcb61681..abab5f20baac 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -59,22 +59,24 @@ echo
 echo "<<< NixOS Stage 1 >>>"
 echo
 
-
-# Mount special file systems.
+# Make several required directories.
 mkdir -p /etc/udev
 touch /etc/fstab # to shut up mount
-touch /etc/mtab # to shut up mke2fs
+ln -s /proc/mounts /etc/mtab # to shut up mke2fs
 touch /etc/udev/hwdb.bin # to shut up udev
 touch /etc/initrd-release
-mkdir -p /proc
-mount -t proc proc /proc
-mkdir -p /sys
-mount -t sysfs sysfs /sys
-mount -t devtmpfs -o "size=@devSize@" devtmpfs /dev
-mkdir -p /run
-mount -t tmpfs -o "mode=0755,size=@runSize@" tmpfs /run
-mkdir /dev/pts
-mount -t devpts devpts /dev/pts
+
+# Mount special file systems.
+specialMount() {
+  local device="$1"
+  local mountPoint="$2"
+  local options="$3"
+  local fsType="$4"
+
+  mkdir -m 0755 -p "$mountPoint"
+  mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
+}
+source @earlyMountScript@
 
 # Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
 mkdir -p /tmp
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index a5c05f3dbbaf..513c121347b1 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -190,7 +190,9 @@ let
 
     inherit udevRules extraUtils modulesClosure;
 
-    inherit (config.boot) resumeDevice devSize runSize;
+    inherit (config.boot) resumeDevice;
+
+    inherit (config.system.build) earlyMountScript;
 
     inherit (config.boot.initrd) checkJournalingFS
       preLVMCommands preDeviceCommands postDeviceCommands postMountCommands preFailCommands kernelModules;
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index c5a14f0766d5..7de85209a159 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -37,12 +37,16 @@ fi
 # Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a
 # stage 1, we need to do that here.
 if [ ! -e /proc/1 ]; then
-    mkdir -m 0755 -p /proc
-    mount -n -t proc proc /proc
-    mkdir -m 0755 -p /dev
-    mount -t devtmpfs devtmpfs /dev
-    mkdir -m 0755 -p /sys
-    mount -t sysfs sysfs /sys
+    specialMount() {
+        local device="$1"
+        local mountPoint="$2"
+        local options="$3"
+        local fsType="$4"
+
+        mkdir -m 0755 -p "$mountPoint"
+        mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
+    }
+    source @earlyMountScript@
 fi
 
 
@@ -87,11 +91,6 @@ done
 
 
 # More special file systems, initialise required directories.
-if ! mountpoint -q /dev/shm; then
-    mkdir -m 0755 /dev/shm
-    mount -t tmpfs -o "rw,nosuid,nodev,size=@devShmSize@" tmpfs /dev/shm
-fi
-mkdir -m 0755 -p /dev/pts
 [ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
 mkdir -m 01777 -p /tmp
 mkdir -m 0755 -p /var /var/log /var/lib /var/db
@@ -112,14 +111,6 @@ rm -f /etc/{group,passwd,shadow}.lock
 rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots
 
 
-# Create a tmpfs on /run to hold runtime state for programs such as
-# udev (if stage 1 hasn't already done so).
-if ! mountpoint -q /run; then
-    rm -rf /run
-    mkdir -m 0755 -p /run
-    mount -t tmpfs -o "mode=0755,size=@runSize@" tmpfs /run
-fi
-
 # Create a ramfs on /run/keys to hold secrets that shouldn't be
 # written to disk (generally used for NixOps, harmless elsewhere).
 if ! mountpoint -q /run/keys; then
diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix
index b67f42a017e6..7e4ec2a4a670 100644
--- a/nixos/modules/system/boot/stage-2.nix
+++ b/nixos/modules/system/boot/stage-2.nix
@@ -20,10 +20,9 @@ let
     src = ./stage-2-init.sh;
     shellDebug = "${pkgs.bashInteractive}/bin/bash";
     isExecutable = true;
-    inherit (config.boot) devShmSize runSize;
     inherit (config.nix) readOnlyStore;
     inherit (config.networking) useHostResolvConf;
-    ttyGid = config.ids.gids.tty;
+    inherit (config.system.build) earlyMountScript;
     path =
       [ pkgs.coreutils
         pkgs.utillinux
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index f146448200f9..dd632437a78a 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -18,7 +18,9 @@ let
 
   prioOption = prio: optionalString (prio != null) " pri=${toString prio}";
 
-  fileSystemOpts = { name, config, ... }: {
+  specialFSTypes = [ "proc" "sysfs" "tmpfs" "devtmpfs" "devpts" ];
+
+  coreFileSystemOpts = { name, config, ... }: {
 
     options = {
 
@@ -35,13 +37,6 @@ let
         description = "Location of the device.";
       };
 
-      label = mkOption {
-        default = null;
-        example = "root-partition";
-        type = types.nullOr types.str;
-        description = "Label of the device (if any).";
-      };
-
       fsType = mkOption {
         default = "auto";
         example = "ext3";
@@ -60,6 +55,26 @@ let
         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);
       });
 
+    };
+
+    config = {
+      mountPoint = mkDefault name;
+      device = mkIf (elem config.fsType specialFSTypes) (mkDefault config.fsType);
+    };
+
+  };
+
+  fileSystemOpts = { config, ... }: {
+
+    options = {
+
+      label = mkOption {
+        default = null;
+        example = "root-partition";
+        type = types.nullOr types.str;
+        description = "Label of the device (if any).";
+      };
+
       autoFormat = mkOption {
         default = false;
         type = types.bool;
@@ -100,8 +115,6 @@ let
     };
 
     config = {
-      mountPoint = mkDefault name;
-      device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType);
       options = mkIf config.autoResize [ "x-nixos.autoresize" ];
 
       # -F needed to allow bare block device without partitions
@@ -110,6 +123,13 @@ let
 
   };
 
+  # Makes sequence of `specialMount device mountPoint options fsType` commands.
+  # `systemMount` should be defined in the sourcing script.
+  makeSpecialMounts = mounts:
+    pkgs.writeText "mounts.sh" (concatMapStringsSep "\n" (mount: ''
+      specialMount "${mount.device}" "${mount.mountPoint}" "${concatStringsSep "," mount.options}" "${mount.fsType}"
+    '') mounts);
+
 in
 
 {
@@ -131,8 +151,7 @@ in
           "/bigdisk".label = "bigdisk";
         }
       '';
-      type = types.loaOf types.optionSet;
-      options = [ fileSystemOpts ];
+      type = types.loaOf (types.submodule [coreFileSystemOpts fileSystemOpts]);
       description = ''
         The file systems to be mounted.  It must include an entry for
         the root directory (<literal>mountPoint = "/"</literal>).  Each
@@ -164,6 +183,15 @@ in
       description = "Names of supported filesystem types.";
     };
 
+    boot.specialFileSystems = mkOption {
+      default = {};
+      type = types.loaOf (types.submodule coreFileSystemOpts);
+      internal = true;
+      description = ''
+        Special filesystems that are mounted very early during boot.
+      '';
+    };
+
   };
 
 
@@ -181,6 +209,7 @@ in
 
     # Export for use in other modules
     system.build.fileSystems = fileSystems;
+    system.build.earlyMountScript = makeSpecialMounts (toposort fsBefore (attrValues config.boot.specialFileSystems)).result;
 
     boot.supportedFilesystems = map (fs: fs.fsType) fileSystems;
 
@@ -258,6 +287,16 @@ in
 
       in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems));
 
+    # Sync mount options with systemd's src/core/mount-setup.c: mount_table.
+    boot.specialFileSystems = {
+      "/proc" = { fsType = "proc"; options = [ "nosuid" "noexec" "nodev" ]; };
+      "/sys" = { fsType = "sysfs"; options = [ "nosuid" "noexec" "nodev" ]; };
+      "/run" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=755" "size=${config.boot.runSize}" ]; };
+      "/dev" = { fsType = "devtmpfs"; options = [ "nosuid" "strictatime" "mode=755" "size=${config.boot.devSize}" ]; };
+      "/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; };
+      "/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "gid=${toString config.ids.gids.tty}" ]; };
+    };
+
   };
 
 }
diff --git a/nixos/modules/virtualisation/amazon-grow-partition.nix b/nixos/modules/virtualisation/amazon-grow-partition.nix
deleted file mode 100644
index 69b80d900bad..000000000000
--- a/nixos/modules/virtualisation/amazon-grow-partition.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-# This module automatically grows the root partition on Amazon EC2 HVM
-# instances. This allows an instance to be created with a bigger root
-# filesystem than provided by the AMI.
-
-{ config, lib, pkgs, ... }:
-
-{
-  config = lib.mkIf config.ec2.hvm {
-    boot.initrd.extraUtilsCommands = ''
-      copy_bin_and_libs ${pkgs.gawk}/bin/gawk
-      copy_bin_and_libs ${pkgs.gnused}/bin/sed
-      copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk
-      cp -v ${pkgs.cloud-utils}/bin/growpart $out/bin/growpart
-      ln -s sed $out/bin/gnused
-    '';
-
-    boot.initrd.postDeviceCommands = ''
-      if [ -e /dev/xvda ] && [ -e /dev/xvda1 ]; then
-        TMPDIR=/run sh $(type -P growpart) /dev/xvda 1
-        udevadm settle
-      fi
-    '';
-  };
-}
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index ebf398fa266f..f9c3f2e53adc 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -11,10 +11,12 @@ with lib;
 let cfg = config.ec2; in
 
 {
-  imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-grow-partition.nix ./amazon-init.nix ];
+  imports = [ ../profiles/headless.nix ./ec2-data.nix ./grow-partition.nix ./amazon-init.nix ];
 
   config = {
 
+    virtualisation.growPartition = cfg.hvm;
+
     fileSystems."/" = {
       device = "/dev/disk/by-label/nixos";
       autoResize = true;
diff --git a/nixos/modules/virtualisation/grow-partition.nix b/nixos/modules/virtualisation/grow-partition.nix
new file mode 100644
index 000000000000..abc2e766959e
--- /dev/null
+++ b/nixos/modules/virtualisation/grow-partition.nix
@@ -0,0 +1,43 @@
+# This module automatically grows the root partition on virtual machines.
+# This allows an instance to be created with a bigger root filesystem
+# than provided by the machine image.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  options = {
+
+    virtualisation.growPartition = mkOption {
+      type = types.bool;
+      default = true;
+    };
+
+  };
+
+  config = mkIf config.virtualisation.growPartition {
+
+    boot.initrd.extraUtilsCommands = ''
+      copy_bin_and_libs ${pkgs.gawk}/bin/gawk
+      copy_bin_and_libs ${pkgs.gnused}/bin/sed
+      copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk
+      copy_bin_and_libs ${pkgs.utillinux}/sbin/lsblk
+      cp -v ${pkgs.cloud-utils}/bin/growpart $out/bin/growpart
+      ln -s sed $out/bin/gnused
+    '';
+
+    boot.initrd.postDeviceCommands = ''
+      rootDevice="${config.fileSystems."/".device}"
+      if [ -e "$rootDevice" ]; then
+        rootDevice="$(readlink -f "$rootDevice")"
+        parentDevice="$(lsblk -npo PKNAME "$rootDevice")"
+        TMPDIR=/run sh $(type -P growpart) "$parentDevice" "''${rootDevice#$parentDevice}"
+        udevadm settle
+      fi
+    '';
+
+  };
+
+}
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index 3a598a1c7dc5..b6a5b3e4788d 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -8,6 +8,8 @@ let
 
 in {
 
+  imports = [ ./grow-partition.nix ];
+
   options = {
     virtualbox = {
       baseImageSize = mkOption {
@@ -64,7 +66,10 @@ in {
         '';
     };
 
-    fileSystems."/".device = "/dev/disk/by-label/nixos";
+    fileSystems."/" = {
+      device = "/dev/disk/by-label/nixos";
+      autoResize = true;
+    };
 
     boot.loader.grub.device = "/dev/sda";