diff --git a/nixos/doc/manual/release-notes/rl-2511.section.md b/nixos/doc/manual/release-notes/rl-2511.section.md index 58f11b6a5e57..9a236172dfe8 100644 --- a/nixos/doc/manual/release-notes/rl-2511.section.md +++ b/nixos/doc/manual/release-notes/rl-2511.section.md @@ -34,6 +34,8 @@ - [Szurubooru](https://github.com/rr-/szurubooru), an image board engine inspired by services such as Danbooru, dedicated for small and medium communities. Available as [services.szurubooru](#opt-services.szurubooru.enable). +- [nix-store-veritysetup](https://github.com/nikstur/nix-store-veritysetup-generator), a systemd generator to unlock the Nix Store as a dm-verity protected block device. Available as [boot.initrd.nix-store-veritysetup](options.html#opt-boot.initrd.nix-store-veritysetup.enable). + - [SuiteNumérique Docs](https://github.com/suitenumerique/docs), a collaborative note taking, wiki and documentation web platform and alternative to Notion or Outline. Available as [services.lasuite-docs](#opt-services.lasuite-docs.enable). [dwl](https://codeberg.org/dwl/dwl), a compact, hackable compositor for Wayland based on wlroots. Available as [programs.dwl](#opt-programs.dwl.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 78cebbee8ca5..8b9c38d4ee71 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1786,6 +1786,7 @@ ./system/boot/luksroot.nix ./system/boot/modprobe.nix ./system/boot/networkd.nix + ./system/boot/nix-store-veritysetup.nix ./system/boot/plymouth.nix ./system/boot/resolved.nix ./system/boot/shutdown.nix diff --git a/nixos/modules/system/boot/nix-store-veritysetup.nix b/nixos/modules/system/boot/nix-store-veritysetup.nix new file mode 100644 index 000000000000..6a4d9bd9cc20 --- /dev/null +++ b/nixos/modules/system/boot/nix-store-veritysetup.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.boot.initrd.nix-store-veritysetup; +in +{ + meta.maintainers = with lib.maintainers; [ nikstur ]; + + options.boot.initrd.nix-store-veritysetup = { + enable = lib.mkEnableOption "nix-store-veritysetup"; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = config.boot.initrd.systemd.dmVerity.enable; + message = "nix-store-veritysetup requires dm-verity in the systemd initrd."; + } + ]; + + boot.initrd.systemd = { + contents = { + "/etc/systemd/system-generators/nix-store-veritysetup-generator".source = + "${lib.getExe pkgs.nix-store-veritysetup-generator}"; + }; + + storePaths = [ + "${config.boot.initrd.systemd.package}/bin/systemd-escape" + ]; + }; + + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 4de915a2570a..552fb324db76 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -938,6 +938,7 @@ in nix-required-mounts = runTest ./nix-required-mounts; nix-serve = runTest ./nix-serve.nix; nix-serve-ssh = runTest ./nix-serve-ssh.nix; + nix-store-veritysetup = runTest ./nix-store-veritysetup.nix; nixops = handleTest ./nixops/default.nix { }; nixos-generate-config = runTest ./nixos-generate-config.nix; nixos-rebuild-install-bootloader = handleTestOn [ diff --git a/nixos/tests/nix-store-veritysetup.nix b/nixos/tests/nix-store-veritysetup.nix new file mode 100644 index 000000000000..3b6a5e6a734f --- /dev/null +++ b/nixos/tests/nix-store-veritysetup.nix @@ -0,0 +1,108 @@ +{ lib, ... }: +{ + + name = "nix-store-veritysetup"; + + meta.maintainers = with lib.maintainers; [ nikstur ]; + + nodes.machine = + { config, modulesPath, ... }: + { + + imports = [ + "${modulesPath}/image/repart.nix" + ]; + + image.repart = { + name = "nix-store"; + partitions = { + "nix-store" = { + storePaths = [ config.system.build.toplevel ]; + stripNixStorePrefix = true; + repartConfig = { + Type = "linux-generic"; + Label = "nix-store"; + Format = "erofs"; + Minimize = "best"; + Verity = "data"; + VerityMatchKey = "nix-store"; + }; + }; + "nix-store-verity" = { + repartConfig = { + Type = "linux-generic"; + Label = "nix-store-verity"; + Verity = "hash"; + VerityMatchKey = "nix-store"; + Minimize = "best"; + }; + }; + }; + }; + + boot.initrd = { + systemd = { + enable = true; + dmVerity.enable = true; + }; + nix-store-veritysetup.enable = true; + }; + + virtualisation = { + mountHostNixStore = false; + qemu.drives = [ + { + name = "nix-store"; + file = ''"$NIX_STORE"''; + } + ]; + fileSystems = { + "/nix/store" = { + fsType = "erofs"; + device = "/dev/mapper/nix-store"; + }; + }; + }; + + }; + + testScript = + { nodes, ... }: + '' + import os + import json + import subprocess + import tempfile + + with open("${nodes.machine.system.build.image}/repart-output.json") as f: + data = json.load(f) + + storehash = data[0]["roothash"] + + os.environ["QEMU_KERNEL_PARAMS"] = f"storehash={storehash}" + + tmp_disk_image = tempfile.NamedTemporaryFile() + + subprocess.run([ + "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", + "create", + "-f", + "qcow2", + "-b", + "${nodes.machine.system.build.image}/${nodes.machine.image.repart.imageFile}", + "-F", + "raw", + tmp_disk_image.name, + ]) + + os.environ["NIX_STORE"] = tmp_disk_image.name + + machine.start() + + print(machine.succeed("findmnt")) + print(machine.succeed("dmsetup info nix-store")) + + machine.wait_for_unit("multi-user.target") + ''; + +} diff --git a/pkgs/by-name/ni/nix-store-veritysetup-generator/package.nix b/pkgs/by-name/ni/nix-store-veritysetup-generator/package.nix index 6a92ed47aba7..6c0ff9bc4428 100644 --- a/pkgs/by-name/ni/nix-store-veritysetup-generator/package.nix +++ b/pkgs/by-name/ni/nix-store-veritysetup-generator/package.nix @@ -40,5 +40,6 @@ rustPlatform.buildRustPackage rec { homepage = "https://github.com/nikstur/nix-store-veritysetup-generator"; license = licenses.mit; maintainers = with lib.maintainers; [ nikstur ]; + mainProgram = "nix-store-veritysetup-generator"; }; }