Loading nixos/modules/image/repart-verity-store.nix +13 −5 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ in Verity = "hash"; VerityMatchKey = lib.mkDefault verityMatchKey; Label = lib.mkDefault "store-verity"; Minimize = lib.mkDefault "best"; }; # dm-verity data partition that contains the nix store ${cfg.partitionIds.store} = { Loading @@ -106,23 +107,29 @@ in Format = lib.mkDefault "erofs"; VerityMatchKey = lib.mkDefault verityMatchKey; Label = lib.mkDefault "store"; Minimize = lib.mkDefault "best"; }; }; }; system.build = { finalImage = lib.warn "system.build.finalImage has been renamed to system.build.image" config.system.build.image; # intermediate system image without ESP intermediateImage = (config.system.build.image.override { (config.image.repart.image.override { # always disable compression for the intermediate image compression.enable = false; }).overrideAttrs ( _: previousAttrs: { # make it easier to identify the intermediate image in build logs pname = "${previousAttrs.pname}-intermediate"; name = if previousAttrs ? pname then "${previousAttrs.pname}-${previousAttrs.version}-intermediate" else "${previousAttrs.name}-intermediate"; # do not prepare the ESP, this is done in the final image systemdRepartFlags = previousAttrs.systemdRepartFlags ++ [ "--defer-partitions=esp" ]; Loading Loading @@ -162,8 +169,8 @@ in ); # final system image that is created from the intermediate image by injecting the UKI from above finalImage = (config.system.build.image.override { image = lib.mkOverride 99 ( (config.image.repart.image.override { # continue building with existing intermediate image createEmpty = false; }).overrideAttrs Loading Loading @@ -216,6 +223,7 @@ in rm -v repart-output_orig.json ''; } ) ); }; }; Loading nixos/modules/image/repart.nix +41 −30 Original line number Diff line number Diff line Loading @@ -282,6 +282,15 @@ in ''; }; image = lib.mkOption { type = lib.types.package; internal = true; readOnly = true; description = '' The image built by this module. Used as the default for `system.build.image`. ''; }; assertions = lib.mkOption { type = options.assertions.type; default = [ ]; Loading Loading @@ -356,6 +365,37 @@ in finalPartitions = lib.mapAttrs addClosure cfg.partitions; image = let fileSystems = lib.filter (f: f != null) ( lib.mapAttrsToList (_n: v: v.repartConfig.Format or null) cfg.partitions ); format = pkgs.formats.ini { listsAsDuplicateKeys = true; }; definitionsDirectory = utils.systemdUtils.lib.definitions "repart.d" format ( lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) cfg.finalPartitions ); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; val = pkgs.callPackage ./repart-image.nix { systemd = cfg.package; inherit (config.image) baseName; inherit (cfg) name version compression split seed imageSize sectorSize finalPartitions ; inherit fileSystems definitionsDirectory mkfsEnv; }; in lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val; assertions = lib.mapAttrsToList ( fileName: partitionConfig: let Loading Loading @@ -401,36 +441,7 @@ in ); }; system.build.image = let fileSystems = lib.filter (f: f != null) ( lib.mapAttrsToList (_n: v: v.repartConfig.Format or null) cfg.partitions ); format = pkgs.formats.ini { listsAsDuplicateKeys = true; }; definitionsDirectory = utils.systemdUtils.lib.definitions "repart.d" format ( lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) cfg.finalPartitions ); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; val = pkgs.callPackage ./repart-image.nix { systemd = cfg.package; inherit (config.image) baseName; inherit (cfg) name version compression split seed imageSize sectorSize finalPartitions ; inherit fileSystems definitionsDirectory mkfsEnv; }; in lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val; system.build.image = cfg.image; }; meta.maintainers = with lib.maintainers; [ Loading nixos/tests/appliance-repart-image-verity-store.nix +52 −42 Original line number Diff line number Diff line Loading @@ -10,13 +10,8 @@ willibutz ]; nodes.machine = { config, lib, pkgs, ... }: defaults = { config, lib, ... }: let inherit (config.image.repart.verityStore) partitionIds; in Loading Loading @@ -55,12 +50,6 @@ SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M"; }; }; ${partitionIds.store-verity}.repartConfig = { Minimize = "best"; }; ${partitionIds.store}.repartConfig = { Minimize = "best"; }; }; }; Loading @@ -75,10 +64,7 @@ initrd.systemd.enable = true; }; system.image = { id = "nixos-appliance"; version = "1"; }; system.image.id = "nixos-appliance"; # don't create /usr/bin/env # this would require some extra work on read-only /usr Loading @@ -86,6 +72,12 @@ system.activationScripts.usrbinenv = lib.mkForce ""; }; nodes.machine = { system.image.version = "1"; }; nodes.without-version = { }; testScript = { nodes, ... }: # python '' Loading @@ -93,24 +85,22 @@ import subprocess import tempfile tmp_disk_image = tempfile.NamedTemporaryFile() def create_disk_image(qemu_img, backing_file): tmp = tempfile.NamedTemporaryFile() subprocess.run([ "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", qemu_img, "create", "-f", "qcow2", "-b", "${nodes.machine.system.build.finalImage}/${nodes.machine.image.repart.imageFile}", backing_file, "-F", "raw", tmp_disk_image.name, ]) os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name machine.wait_for_unit("default.target") tmp.name, ], check=True) return tmp def run_verity_tests(machine): with subtest("Running with volatile root"): machine.succeed("findmnt --kernel --type tmpfs /") Loading @@ -119,6 +109,26 @@ assert "ACTIVE" in verity_info, f"unexpected verity info: {verity_info}" backing_device = machine.succeed("df --output=source /nix/store | tail -n1").strip() assert "/dev/mapper/usr" == backing_device,"unexpected backing device: {backing_device}" assert "/dev/mapper/usr" == backing_device, f"unexpected backing device: {backing_device}" tmp_disk_machine = create_disk_image( "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", "${nodes.machine.system.build.image}/${nodes.machine.image.filePath}", ) os.environ['NIX_DISK_IMAGE'] = tmp_disk_machine.name machine.wait_for_unit("default.target") run_verity_tests(machine) with subtest("Image version is set"): machine.succeed("grep IMAGE_VERSION=1 /etc/os-release") tmp_disk_without_version = create_disk_image( "${nodes."without-version".virtualisation.qemu.package}/bin/qemu-img", "${nodes."without-version".system.build.image}/${nodes."without-version".image.filePath}", ) os.environ['NIX_DISK_IMAGE'] = tmp_disk_without_version.name without_version.wait_for_unit("default.target") run_verity_tests(without_version) with subtest("Image version is not set"): without_version.succeed('grep IMAGE_VERSION="" /etc/os-release') ''; } nixos/tests/appliance-repart-image.nix +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ in "-f", "qcow2", "-b", "${nodes.machine.system.build.image}/${nodes.machine.image.repart.imageFile}", "${nodes.machine.system.build.image}/${nodes.machine.image.filePath}", "-F", "raw", tmp_disk_image.name, Loading Loading
nixos/modules/image/repart-verity-store.nix +13 −5 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ in Verity = "hash"; VerityMatchKey = lib.mkDefault verityMatchKey; Label = lib.mkDefault "store-verity"; Minimize = lib.mkDefault "best"; }; # dm-verity data partition that contains the nix store ${cfg.partitionIds.store} = { Loading @@ -106,23 +107,29 @@ in Format = lib.mkDefault "erofs"; VerityMatchKey = lib.mkDefault verityMatchKey; Label = lib.mkDefault "store"; Minimize = lib.mkDefault "best"; }; }; }; system.build = { finalImage = lib.warn "system.build.finalImage has been renamed to system.build.image" config.system.build.image; # intermediate system image without ESP intermediateImage = (config.system.build.image.override { (config.image.repart.image.override { # always disable compression for the intermediate image compression.enable = false; }).overrideAttrs ( _: previousAttrs: { # make it easier to identify the intermediate image in build logs pname = "${previousAttrs.pname}-intermediate"; name = if previousAttrs ? pname then "${previousAttrs.pname}-${previousAttrs.version}-intermediate" else "${previousAttrs.name}-intermediate"; # do not prepare the ESP, this is done in the final image systemdRepartFlags = previousAttrs.systemdRepartFlags ++ [ "--defer-partitions=esp" ]; Loading Loading @@ -162,8 +169,8 @@ in ); # final system image that is created from the intermediate image by injecting the UKI from above finalImage = (config.system.build.image.override { image = lib.mkOverride 99 ( (config.image.repart.image.override { # continue building with existing intermediate image createEmpty = false; }).overrideAttrs Loading Loading @@ -216,6 +223,7 @@ in rm -v repart-output_orig.json ''; } ) ); }; }; Loading
nixos/modules/image/repart.nix +41 −30 Original line number Diff line number Diff line Loading @@ -282,6 +282,15 @@ in ''; }; image = lib.mkOption { type = lib.types.package; internal = true; readOnly = true; description = '' The image built by this module. Used as the default for `system.build.image`. ''; }; assertions = lib.mkOption { type = options.assertions.type; default = [ ]; Loading Loading @@ -356,6 +365,37 @@ in finalPartitions = lib.mapAttrs addClosure cfg.partitions; image = let fileSystems = lib.filter (f: f != null) ( lib.mapAttrsToList (_n: v: v.repartConfig.Format or null) cfg.partitions ); format = pkgs.formats.ini { listsAsDuplicateKeys = true; }; definitionsDirectory = utils.systemdUtils.lib.definitions "repart.d" format ( lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) cfg.finalPartitions ); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; val = pkgs.callPackage ./repart-image.nix { systemd = cfg.package; inherit (config.image) baseName; inherit (cfg) name version compression split seed imageSize sectorSize finalPartitions ; inherit fileSystems definitionsDirectory mkfsEnv; }; in lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val; assertions = lib.mapAttrsToList ( fileName: partitionConfig: let Loading Loading @@ -401,36 +441,7 @@ in ); }; system.build.image = let fileSystems = lib.filter (f: f != null) ( lib.mapAttrsToList (_n: v: v.repartConfig.Format or null) cfg.partitions ); format = pkgs.formats.ini { listsAsDuplicateKeys = true; }; definitionsDirectory = utils.systemdUtils.lib.definitions "repart.d" format ( lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) cfg.finalPartitions ); mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions; val = pkgs.callPackage ./repart-image.nix { systemd = cfg.package; inherit (config.image) baseName; inherit (cfg) name version compression split seed imageSize sectorSize finalPartitions ; inherit fileSystems definitionsDirectory mkfsEnv; }; in lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val; system.build.image = cfg.image; }; meta.maintainers = with lib.maintainers; [ Loading
nixos/tests/appliance-repart-image-verity-store.nix +52 −42 Original line number Diff line number Diff line Loading @@ -10,13 +10,8 @@ willibutz ]; nodes.machine = { config, lib, pkgs, ... }: defaults = { config, lib, ... }: let inherit (config.image.repart.verityStore) partitionIds; in Loading Loading @@ -55,12 +50,6 @@ SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M"; }; }; ${partitionIds.store-verity}.repartConfig = { Minimize = "best"; }; ${partitionIds.store}.repartConfig = { Minimize = "best"; }; }; }; Loading @@ -75,10 +64,7 @@ initrd.systemd.enable = true; }; system.image = { id = "nixos-appliance"; version = "1"; }; system.image.id = "nixos-appliance"; # don't create /usr/bin/env # this would require some extra work on read-only /usr Loading @@ -86,6 +72,12 @@ system.activationScripts.usrbinenv = lib.mkForce ""; }; nodes.machine = { system.image.version = "1"; }; nodes.without-version = { }; testScript = { nodes, ... }: # python '' Loading @@ -93,24 +85,22 @@ import subprocess import tempfile tmp_disk_image = tempfile.NamedTemporaryFile() def create_disk_image(qemu_img, backing_file): tmp = tempfile.NamedTemporaryFile() subprocess.run([ "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", qemu_img, "create", "-f", "qcow2", "-b", "${nodes.machine.system.build.finalImage}/${nodes.machine.image.repart.imageFile}", backing_file, "-F", "raw", tmp_disk_image.name, ]) os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name machine.wait_for_unit("default.target") tmp.name, ], check=True) return tmp def run_verity_tests(machine): with subtest("Running with volatile root"): machine.succeed("findmnt --kernel --type tmpfs /") Loading @@ -119,6 +109,26 @@ assert "ACTIVE" in verity_info, f"unexpected verity info: {verity_info}" backing_device = machine.succeed("df --output=source /nix/store | tail -n1").strip() assert "/dev/mapper/usr" == backing_device,"unexpected backing device: {backing_device}" assert "/dev/mapper/usr" == backing_device, f"unexpected backing device: {backing_device}" tmp_disk_machine = create_disk_image( "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", "${nodes.machine.system.build.image}/${nodes.machine.image.filePath}", ) os.environ['NIX_DISK_IMAGE'] = tmp_disk_machine.name machine.wait_for_unit("default.target") run_verity_tests(machine) with subtest("Image version is set"): machine.succeed("grep IMAGE_VERSION=1 /etc/os-release") tmp_disk_without_version = create_disk_image( "${nodes."without-version".virtualisation.qemu.package}/bin/qemu-img", "${nodes."without-version".system.build.image}/${nodes."without-version".image.filePath}", ) os.environ['NIX_DISK_IMAGE'] = tmp_disk_without_version.name without_version.wait_for_unit("default.target") run_verity_tests(without_version) with subtest("Image version is not set"): without_version.succeed('grep IMAGE_VERSION="" /etc/os-release') ''; }
nixos/tests/appliance-repart-image.nix +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ in "-f", "qcow2", "-b", "${nodes.machine.system.build.image}/${nodes.machine.image.repart.imageFile}", "${nodes.machine.system.build.image}/${nodes.machine.image.filePath}", "-F", "raw", tmp_disk_image.name, Loading