X-Git-Url: http://git.scottworley.com/nixos-qemu-vm-isolation/blobdiff_plain/68bdafb07183ce95311038842731769028f55712..HEAD:/modules/qemu-vm-isolation.nix diff --git a/modules/qemu-vm-isolation.nix b/modules/qemu-vm-isolation.nix index 260e9fe..bea4174 100644 --- a/modules/qemu-vm-isolation.nix +++ b/modules/qemu-vm-isolation.nix @@ -1,41 +1,24 @@ { config, lib, modulesPath, pkgs, ... }: let - inherit (lib) findSingle mkForce mkIf mkMerge mkVMOverride; + inherit (lib) + escapeShellArg mkForce mkIf mkMerge mkOption mkVMOverride optional; - lookupDriveDeviceName = driveName: driveList: - (findSingle (drive: drive.name == driveName) - (throw "Drive ${driveName} not found") - (throw "Multiple drives named ${driveName}") driveList).device; + cfg = config.virtualisation.qemu.isolation; storeMountPath = if config.virtualisation.writableStore then "/nix/.ro-store" else "/nix/store"; -in { - - fileSystems = mkVMOverride { - "${storeMountPath}" = { - device = - lookupDriveDeviceName "nixstore" config.virtualisation.qemu.drives; - fsType = "ext4"; - options = [ "ro" ]; - neededForBoot = true; - }; - }; + hostPkgs = config.virtualisation.host.pkgs; - # We use this to disable fsck runs on the ext4 nix store image because stage-1 - # fsck crashes (maybe because the device is read-only?), halting boot. - boot.initrd.checkJournalingFS = false; + storeContents = + hostPkgs.closureInfo { rootPaths = config.virtualisation.additionalPaths; }; - system.build.nixStoreImage = - import (modulesPath + "/../lib/make-disk-image.nix") { + nixStoreImages = { + ext4 = import (modulesPath + "/../lib/make-disk-image.nix") { inherit pkgs config lib; - additionalPaths = [ - (config.virtualisation.host.pkgs.closureInfo { - rootPaths = config.virtualisation.additionalPaths; - }) - ]; + additionalPaths = [ storeContents ]; onlyNixStore = true; label = "nix-store"; partitionTableType = "none"; @@ -44,20 +27,76 @@ in { additionalSpace = "0M"; copyChannel = false; }; + erofs = hostPkgs.runCommand "nix-store-image" { } '' + mkdir $out + cd ${builtins.storeDir} + ${hostPkgs.erofs-utils}/bin/mkfs.erofs \ + --force-uid=0 \ + --force-gid=0 \ + -L nix-store \ + -U eb176051-bd15-49b7-9e6b-462e0b467019 \ + -T 0 \ + --exclude-regex="$( + <${storeContents}/store-paths \ + sed -e 's^.*/^^g' \ + | cut -c -10 \ + | ${hostPkgs.python3}/bin/python -c ${ + escapeShellArg (builtins.readFile + (modulesPath + "/virtualisation/includes-to-excludes.py")) + } )" \ + $out/nixos.img \ + . + ''; + }; - virtualisation = { +in { + options = { + virtualisation.qemu.isolation.nixStoreFilesystemType = mkOption { + description = '' + What filesystem to use for the guest's Nix store. - sharedDirectories = mkForce { }; + erofs is more compact than ext4, but less mature. + ''; + type = lib.types.enum [ "ext4" "erofs" ]; + default = "ext4"; + }; + }; + config = mkMerge [ + { + boot.initrd.kernelModules = + optional (cfg.nixStoreFilesystemType == "erofs") "erofs"; - qemu.drives = [{ - name = "nixstore"; - file = "${config.system.build.nixStoreImage}/nixos.img"; - driveExtraOpts = { - format = "raw"; - read-only = "on"; - werror = "report"; + fileSystems = mkVMOverride { + "${storeMountPath}" = { + fsType = cfg.nixStoreFilesystemType; + options = [ "ro" ]; + neededForBoot = true; + label = "nix-store"; + }; }; - }]; - }; + system.build.nixStoreImage = + nixStoreImages."${cfg.nixStoreFilesystemType}"; + + virtualisation = { + + sharedDirectories = mkForce { }; + + qemu.drives = [{ + file = "${config.system.build.nixStoreImage}/nixos.img"; + driveExtraOpts = { + format = "raw"; + read-only = "on"; + werror = "report"; + }; + }]; + + }; + } + (mkIf (cfg.nixStoreFilesystemType == "ext4") { + # We use this to disable fsck runs on the ext4 nix store image because stage-1 + # fsck crashes (maybe because the device is read-only?), halting boot. + boot.initrd.checkJournalingFS = false; + }) + ]; }