From f78c24af1d3a186131093427d1b454600e9aa973 Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Fri, 21 Jul 2023 02:46:41 -0700 Subject: [PATCH] Offer option of an erofs nix store image Size of the simple test's nix store image: 240M squashfs (no longer available) 684M erofs 1.3G ext4 --- checks/mount-grep.nix | 8 ++- modules/qemu-vm-isolation.nix | 113 ++++++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 35 deletions(-) diff --git a/checks/mount-grep.nix b/checks/mount-grep.nix index f7eb3a3..5354d26 100644 --- a/checks/mount-grep.nix +++ b/checks/mount-grep.nix @@ -8,6 +8,10 @@ pkgs: { nodes = { shared = _: { }; private = _: { imports = [ ../modules/qemu-vm-isolation.nix ]; }; + privateErofs = _: { + imports = [ ../modules/qemu-vm-isolation.nix ]; + virtualisation.qemu.isolation.nixStoreFilesystemType = "erofs"; + }; useNixStoreImage = { virtualisation = { sharedDirectories = pkgs.lib.mkForce { }; @@ -18,13 +22,13 @@ pkgs: { testScript = '' start_all() - for machine in [shared, private, useNixStoreImage]: + for machine in [shared, private, privateErofs, useNixStoreImage]: machine.wait_for_unit("multi-user.target") shared.succeed("[[ $(mount | grep -c virt) -gt 0 ]]") shared.succeed("[[ -e ${pkgs.pv} ]]") - for machine in [private, useNixStoreImage]: + for machine in [private, privateErofs, useNixStoreImage]: machine.succeed("[[ $(mount | grep -c virt) -eq 0 ]]") machine.fail("[[ -e ${pkgs.pv} ]]") ''; diff --git a/modules/qemu-vm-isolation.nix b/modules/qemu-vm-isolation.nix index 260e9fe..bdf95e6 100644 --- a/modules/qemu-vm-isolation.nix +++ b/modules/qemu-vm-isolation.nix @@ -1,6 +1,10 @@ { config, lib, modulesPath, pkgs, ... }: let - inherit (lib) findSingle mkForce mkIf mkMerge mkVMOverride; + inherit (lib) + escapeShellArg findSingle mkForce mkIf mkMerge mkOption mkVMOverride + optional; + + cfg = config.virtualisation.qemu.isolation; lookupDriveDeviceName = driveName: driveList: (findSingle (drive: drive.name == driveName) @@ -12,30 +16,15 @@ let 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 +33,78 @@ 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}" = { + device = + lookupDriveDeviceName "nixstore" config.virtualisation.qemu.drives; + fsType = cfg.nixStoreFilesystemType; + options = [ "ro" ]; + neededForBoot = true; + }; }; - }]; - }; + system.build.nixStoreImage = + nixStoreImages."${cfg.nixStoreFilesystemType}"; + + virtualisation = { + + sharedDirectories = mkForce { }; + + qemu.drives = [{ + name = "nixstore"; + 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; + }) + ]; } -- 2.44.1