]> git.scottworley.com Git - nixos-qemu-vm-isolation/blob - modules/qemu-vm-isolation.nix
Quantify squashfs' efficiency
[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 ${hostPkgs.gnutar}/bin/tar --create \
36 --absolute-names \
37 --verbatim-files-from \
38 --transform 'flags=rSh;s|/nix/store/||' \
39 --files-from ${storeContents}/store-paths \
40 | ${hostPkgs.erofs-utils}/bin/mkfs.erofs \
41 --force-uid=0 \
42 --force-gid=0 \
43 -L nix-store \
44 -U eb176051-bd15-49b7-9e6b-462e0b467019 \
45 -T 0 \
46 --tar=f \
47 $out/nix-store.img
48 ''
49 }/nix-store.img";
50 squashfs =
51 "${hostPkgs.callPackage (modulesPath + "/../lib/make-squashfs.nix") {
52 squashfsTools =
53 (hostPkgs.extend (import ../overlays/squashfs-labels)).squashfsTools.overrideAttrs
54 (old: {
55 buildInputs = (old.buildInputs or [ ]) ++ [ hostPkgs.makeWrapper ];
56 postInstall = (old.postInstall or "") + ''
57 wrapProgram "$out/bin/mksquashfs" \
58 --append-flags "-label nix-store"
59 '';
60 });
61 storeContents = config.virtualisation.additionalPaths;
62 }}";
63 };
64
65 in {
66 options = {
67 virtualisation.qemu.isolation.nixStoreFilesystemType = mkOption {
68 description = ''
69 What filesystem to use for the guest's Nix store.
70
71 squashfs is best, but requires patches to set the filesystem label.
72
73 ext4 images are ~4x larger than squashfs images.
74
75 erofs images are only ~2.5x larger than squashfs images, but erofs is less mature than either squashfs or ext4.
76
77 '';
78 type = lib.types.enum [ "ext4" "erofs" "squashfs" ];
79 default = "ext4";
80 };
81 };
82 config = mkMerge [
83 {
84 boot.initrd.kernelModules =
85 optional (cfg.nixStoreFilesystemType == "erofs") "erofs";
86
87 nixpkgs.overlays = optional (cfg.nixStoreFilesystemType == "squashfs")
88 (import ../overlays/squashfs-labels);
89
90 fileSystems = mkVMOverride {
91 "${storeMountPath}" = {
92 fsType = cfg.nixStoreFilesystemType;
93 options = [ "ro" ];
94 neededForBoot = true;
95 label = "nix-store";
96 };
97 };
98
99 system.build.nixStoreImage =
100 nixStoreImages."${cfg.nixStoreFilesystemType}";
101
102 virtualisation = {
103
104 sharedDirectories = mkForce { };
105
106 qemu.drives = [{
107 file = config.system.build.nixStoreImage;
108 driveExtraOpts = {
109 format = "raw";
110 read-only = "on";
111 werror = "report";
112 };
113 }];
114
115 };
116 }
117 (mkIf (cfg.nixStoreFilesystemType == "ext4") {
118 # We use this to disable fsck runs on the ext4 nix store image because stage-1
119 # fsck crashes (maybe because the device is read-only?), halting boot.
120 boot.initrd.checkJournalingFS = false;
121 })
122 ];
123 }