]> git.scottworley.com Git - nixos-qemu-vm-isolation/blob - modules/qemu-vm-isolation.nix
Restore squashfs support with a dubious kludge
[nixos-qemu-vm-isolation] / modules / qemu-vm-isolation.nix
1 { config, lib, modulesPath, pkgs, ... }:
2 let
3 inherit (lib)
4 escapeShellArg mkForce mkIf mkMerge mkOption mkVMOverride optional;
5
6 cfg = config.virtualisation.qemu.isolation;
7
8 storeMountPath = if config.virtualisation.writableStore then
9 "/nix/.ro-store"
10 else
11 "/nix/store";
12
13 hostPkgs = config.virtualisation.host.pkgs;
14
15 storeContents =
16 hostPkgs.closureInfo { rootPaths = config.virtualisation.additionalPaths; };
17
18 nixStoreImages = {
19 ext4 = "${
20 import (modulesPath + "/../lib/make-disk-image.nix") {
21 inherit pkgs config lib;
22 additionalPaths = [ storeContents ];
23 onlyNixStore = true;
24 label = "nix-store";
25 partitionTableType = "none";
26 installBootLoader = false;
27 diskSize = "auto";
28 additionalSpace = "0M";
29 copyChannel = false;
30 }
31 }/nixos.img";
32 erofs = "${
33 hostPkgs.runCommand "nix-store-image" { } ''
34 mkdir $out
35 cd ${builtins.storeDir}
36 ${hostPkgs.erofs-utils}/bin/mkfs.erofs \
37 --force-uid=0 \
38 --force-gid=0 \
39 -L nix-store \
40 -U eb176051-bd15-49b7-9e6b-462e0b467019 \
41 -T 0 \
42 --exclude-regex="$(
43 <${storeContents}/store-paths \
44 sed -e 's^.*/^^g' \
45 | cut -c -10 \
46 | ${hostPkgs.python3}/bin/python -c ${
47 escapeShellArg (builtins.readFile
48 (modulesPath + "/virtualisation/includes-to-excludes.py"))
49 } )" \
50 $out/nix-store.img \
51 .
52 ''
53 }/nix-store.img";
54 squashfs =
55 "${hostPkgs.callPackage (modulesPath + "/../lib/make-squashfs.nix") {
56 storeContents = config.virtualisation.additionalPaths;
57 }}";
58 };
59
60 in {
61 options = {
62 virtualisation.qemu.isolation.nixStoreFilesystemType = mkOption {
63 description = ''
64 What filesystem to use for the guest's Nix store.
65
66 erofs is more compact than ext4, but less mature.
67
68 squashfs support currently requires a dubious kludge that results in these
69 VMs not being able to mount any other squashfs volumes besides the nix store.
70 '';
71 type = lib.types.enum [ "ext4" "erofs" "squashfs" ];
72 default = "ext4";
73 };
74 };
75 config = mkMerge [
76 {
77 boot.initrd.kernelModules =
78 optional (cfg.nixStoreFilesystemType == "erofs") "erofs";
79
80 nixpkgs.overlays = optional (cfg.nixStoreFilesystemType == "squashfs")
81 (final: prev: {
82 util-linux = prev.util-linux.overrideAttrs (old: {
83 patches = (old.patches or [ ])
84 ++ [ ./libblkid-squashfs-nix-store-kludge.patch ];
85 });
86 });
87
88 fileSystems = mkVMOverride {
89 "${storeMountPath}" = {
90 fsType = cfg.nixStoreFilesystemType;
91 options = [ "ro" ];
92 neededForBoot = true;
93 label = "nix-store";
94 };
95 };
96
97 system.build.nixStoreImage =
98 nixStoreImages."${cfg.nixStoreFilesystemType}";
99
100 virtualisation = {
101
102 sharedDirectories = mkForce { };
103
104 qemu.drives = [{
105 file = config.system.build.nixStoreImage;
106 driveExtraOpts = {
107 format = "raw";
108 read-only = "on";
109 werror = "report";
110 };
111 }];
112
113 };
114 }
115 (mkIf (cfg.nixStoreFilesystemType == "ext4") {
116 # We use this to disable fsck runs on the ext4 nix store image because stage-1
117 # fsck crashes (maybe because the device is read-only?), halting boot.
118 boot.initrd.checkJournalingFS = false;
119 })
120 ];
121 }