summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorKleidi Bujari <mail@4kb.net>2026-02-16 13:45:11 -0800
committerKleidi Bujari <mail@4kb.net>2026-02-16 13:45:11 -0800
commitd6d715c776beeb9fd3903cdd8473ab80f6af22fa (patch)
tree7d022dd71df870f1d0869d22f5618117608c59be /packages
parent54a787fbe4375102f742b8370120f4b51e3b079d (diff)
downloaddepot-d6d715c776beeb9fd3903cdd8473ab80f6af22fa.tar.gz
depot-d6d715c776beeb9fd3903cdd8473ab80f6af22fa.tar.bz2
depot-d6d715c776beeb9fd3903cdd8473ab80f6af22fa.zip
initial support for building ZFS system images
Diffstat (limited to 'packages')
-rw-r--r--packages/make-zfs-image.nix165
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