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 { };
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} ]]")
'';
{ 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)
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";
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;
+ })
+ ];
}