diff options
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/make-zfs-image.nix | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/packages/make-zfs-image.nix b/packages/make-zfs-image.nix new file mode 100644 index 0000000..90ce63f --- /dev/null +++ b/packages/make-zfs-image.nix @@ -0,0 +1,165 @@ +# This single-disk approach does not satisfy ZFS's requirements for autoexpand, +# however automation can expand it anyway. For example, with +# `services.zfs.expandOnBoot`. +{ + pkgs, + lib, + config, + + # size of the FAT partition, in MiB (1024x1024 bytes). + bootSize ? 1024, + + # memory allocated for virtualized build instance, in MiB (1024x1024 bytes). + memSize ? 2048, + + # The size of the root partition, in MiB (1024x1024 bytes). + rootSize ? 4096, + + # Shell code executed after the VM has finished. + postVM ? "", + + name ? "nixos-disk-image", + + # Disk image format, one of qcow2, qcow2-compressed, vdi, vpc, raw. + format ? "raw", +}: +let + formatOpt = if format == "qcow2-compressed" then "qcow2" else format; + + compress = lib.optionalString (format == "qcow2-compressed") "-c"; + + filenameSuffix = + "." + + { + qcow2 = "qcow2"; + vdi = "vdi"; + vpc = "vhd"; + raw = "img"; + } + .${formatOpt} or formatOpt; + rootFilename = "nixos.root${filenameSuffix}"; + + closureInfo = pkgs.closureInfo { + rootPaths = [ config.system.build.toplevel ]; + }; + + vmTools = pkgs.vmTools.override { + rootModules = [ + "virtio_blk" + "virtio_pci" + "virtiofs" + "zfs" + ]; + kernel = pkgs.aggregateModules ( + with config.boot; + [ + kernelPackages.kernel + (lib.getOutput "modules" kernelPackages.kernel) + kernelPackages.${pkgs.zfs.kernelModuleAttribute} + ] + ); + }; + + binPath = lib.makeBinPath ( + with pkgs; + [ + config.system.build.nixos-install + dosfstools + nix + parted + util-linux + zfs + ] + ++ stdenv.initialPath + ); + + image = vmTools.runInLinuxVM ( + pkgs.runCommand name + { + inherit memSize; + QEMU_OPTS = "-drive file=$rootDiskImage,if=virtio,cache=unsafe,werror=report"; + preVM = '' + mkdir $out + + rootDiskImage=root.raw + ${pkgs.qemu-utils}/bin/qemu-img create -f raw $rootDiskImage ${toString (bootSize + rootSize)}M + ''; + + postVM = '' + # truncate --size ${toString (bootSize + rootSize)} $rootDiskImage + ${ + if formatOpt == "raw" then + '' + mv $rootDiskImage $out/${rootFilename} + '' + else + '' + ${pkgs.qemu-utils}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $rootDiskImage $out/${rootFilename} + '' + } + rootDiskImage=$out/${rootFilename} + set -x + ${postVM} + ''; + } + '' + export PATH=${binPath} + + parted --script /dev/vda -- \ + mklabel gpt \ + mkpart ESP fat32 8MiB ${toString bootSize}MiB \ + set 1 esp on \ + align-check optimal 1 \ + mkpart primary ${toString bootSize}MiB 100% \ + align-check optimal 2 \ + print + + zpool create \ + -o ashift=12 -o autotrim=on -o autoexpand=on \ + -O acltype=posixacl -O atime=off -O compression=on \ + -O mountpoint=none -O normalization=formD -O relatime=off \ + -O xattr=sa -O canmount=off \ + zroot /dev/vda2 + + zfs create zroot/local + zfs create zroot/local/var -o mountpoint=/var -u + zfs create zroot/local/nix -o mountpoint=legacy + + mkdir -p /mnt/boot + mkfs.vfat -n ESP /dev/vda1 + mount /dev/vda1 /mnt/boot + + mkdir -p /mnt/nix + mount -t zfs zroot/local/nix /mnt/nix + + export HOME=$TMPDIR + + # Provide a Nix database so that nixos-install can copy closures. + export NIX_STATE_DIR=$TMPDIR/state + nix-store --load-db < ${closureInfo}/registration + + chmod 755 $TMPDIR + nixos-install \ + --root /mnt \ + --no-root-passwd \ + --system ${config.system.build.toplevel} \ + --substituters "" + + umount --recursive /mnt/boot + umount --recursive /mnt/nix + zpool export zroot + '' + ); + script = pkgs.writeShellScriptBin "runvm" '' + cp ${image}/nixos.root.qcow2 nixos.root.qcow2 + ${pkgs.qemu-utils}/bin/qemu-img resize nixos.root.qcow2 +10G + ${pkgs.qemu}/bin/qemu-system-x86_64 \ + -enable-kvm \ + -m 4G \ + -cpu host \ + -bios ${pkgs.OVMF.fd}/FV/OVMF.fd \ + -drive file=nixos.root.qcow2,format=qcow2,if=virtio \ + -boot order=c + ''; +in +script |
