diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md index a352fae45ad0..1720dfea3525 100644 --- a/nixos/doc/manual/release-notes/rl-2411.section.md +++ b/nixos/doc/manual/release-notes/rl-2411.section.md @@ -34,9 +34,6 @@ Users that want to keep PulseAudio will want to set `services.pipewire.enable = false;` and `hardware.pulseaudio.enable = true;`. There is currently no plan to fully deprecate and remove PulseAudio, however, PipeWire should generally be preferred for new installs. -- Support for mounting filesystems from block devices protected with [dm-verity](https://docs.kernel.org/admin-guide/device-mapper/verity.html) - was added through the `boot.initrd.systemd.dmVerity` option. - ## New Modules {#sec-release-24.11-new-modules} - [TaskChampion Sync-Server](https://github.com/GothenburgBitFactory/taskchampion-sync-server), a [Taskwariror 3](https://taskwarrior.org/docs/upgrade-3/) sync server, replacing Taskwarrior 2's sync server named [`taskserver`](https://github.com/GothenburgBitFactory/taskserver). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index f94b1368ac69..dff961f3f55b 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1622,7 +1622,6 @@ ./system/boot/stage-2.nix ./system/boot/systemd.nix ./system/boot/systemd/coredump.nix - ./system/boot/systemd/dm-verity.nix ./system/boot/systemd/initrd-secrets.nix ./system/boot/systemd/initrd.nix ./system/boot/systemd/journald.nix diff --git a/nixos/modules/system/boot/systemd/dm-verity.nix b/nixos/modules/system/boot/systemd/dm-verity.nix deleted file mode 100644 index eea048126be0..000000000000 --- a/nixos/modules/system/boot/systemd/dm-verity.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ config, lib, ... }: - -let - cfg = config.boot.initrd.systemd.dmVerity; -in -{ - options = { - boot.initrd.systemd.dmVerity = { - enable = lib.mkEnableOption "dm-verity" // { - description = '' - Mount verity-protected block devices in the initrd. - - Enabling this option allows to use `systemd-veritysetup` and - `systemd-veritysetup-generator` in the initrd. - ''; - }; - }; - }; - - config = lib.mkIf cfg.enable { - assertions = [ - { - assertion = cfg.enable -> config.boot.initrd.systemd.enable; - message = '' - 'boot.initrd.systemd.dmVerity.enable' requires 'boot.initrd.systemd.enable' to be enabled. - ''; - } - ]; - - boot.initrd = { - availableKernelModules = [ - # For documentation, see https://docs.kernel.org/admin-guide/device-mapper/dm-init.html - "dm_mod" - # For documentation, see: - # - https://docs.kernel.org/admin-guide/device-mapper/verity.html - # - https://gitlab.com/cryptsetup/cryptsetup/-/wikis/DMVerity - "dm_verity" - ]; - - # dm-verity needs additional udev rules from LVM to work. - services.lvm.enable = true; - - # The additional targets and store paths allow users to integrate verity-protected devices - # through the systemd tooling. - systemd = { - additionalUpstreamUnits = [ - # https://github.com/systemd/systemd/blob/main/units/veritysetup-pre.target - "veritysetup-pre.target" - # https://github.com/systemd/systemd/blob/main/units/veritysetup.target - "veritysetup.target" - # https://github.com/systemd/systemd/blob/main/units/remote-veritysetup.target - "remote-veritysetup.target" - ]; - - storePaths = [ - # These are the two binaries mentioned in https://github.com/systemd/systemd/blob/main/src/veritysetup/meson.build; there are no others. - "${config.boot.initrd.systemd.package}/lib/systemd/systemd-veritysetup" - "${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-veritysetup-generator" - ]; - }; - }; - }; - - meta.maintainers = [ lib.maintainers.msanft ]; -} diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index 2ad114d6a1d3..2ccc964820fe 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -218,7 +218,7 @@ in { }; root = lib.mkOption { - type = lib.types.nullOr (lib.types.enum [ "fstab" "gpt-auto" ]); + type = lib.types.enum [ "fstab" "gpt-auto" ]; default = "fstab"; example = "gpt-auto"; description = '' @@ -227,9 +227,6 @@ in { allow specifying the root file system itself this way. Instead, the `fstab` value is used in order to interpret the root file system specified with the `fileSystems` option. - - If the root FS is mounted by other means, such as systemd generators other than - `fstab`, `gpt-auto` or a custom generator, set this to `null`. ''; }; @@ -401,9 +398,9 @@ in { ++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb" ++ lib.optional cfg.package.withEfi "efivarfs"; - boot.kernelParams = - lib.optional (config.boot.initrd.systemd.root != null) "root=${config.boot.initrd.systemd.root}" - ++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}" + boot.kernelParams = [ + "root=${config.boot.initrd.systemd.root}" + ] ++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}" # `systemd` mounts root in initrd as read-only unless "rw" is on the kernel command line. # For NixOS activation to succeed, we need to have root writable in initrd. ++ lib.optional (config.boot.initrd.systemd.root == "gpt-auto") "rw"; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 44ab2d445841..f8e0eb190bf5 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -259,7 +259,6 @@ in { dhparams = handleTest ./dhparams.nix {}; disable-installer-tools = handleTest ./disable-installer-tools.nix {}; discourse = handleTest ./discourse.nix {}; - dm-verity = runTest ./dm-verity.nix; dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {}; dnscrypt-wrapper = runTestOn ["x86_64-linux"] ./dnscrypt-wrapper; dnsdist = import ./dnsdist.nix { inherit pkgs runTest; }; diff --git a/nixos/tests/dm-verity.nix b/nixos/tests/dm-verity.nix deleted file mode 100644 index cf20dbe66f59..000000000000 --- a/nixos/tests/dm-verity.nix +++ /dev/null @@ -1,245 +0,0 @@ -# Tests a NixOS system with a read-only root filesystem that's integrity-protected -# through DM-verity. The root filesystem is mounted read-only, and for NixOS activation -# to succeed, an overlay `tmpfs` is mounted on top of it. -# This test uses systemd-repart to create a bootable disk image, as it supplies handy -# utilities for creating verity partitions, but it can also be setup manually through -# `systemd-veritysetup`. - -{ lib, pkgs, ... }: - -let - imageId = "verity-root-image"; - imageVersion = "1-rc1"; - - # Use a random, but fixed root hash placeholder to allow us specifying the "real" root hash - # after the image is first built. - roothashPlaceholder = "61fe0f0c98eff2a595dd2f63a5e481a0a25387261fa9e34c37e3a4910edf32b8"; -in -{ - name = "verity-root"; - - meta.maintainers = with lib.maintainers; [ msanft ]; - - nodes.machine = - { - lib, - pkgs, - config, - modulesPath, - ... - }: - { - - imports = [ "${modulesPath}/image/repart.nix" ]; - - virtualisation.directBoot.enable = false; - virtualisation.mountHostNixStore = false; - virtualisation.useEFIBoot = true; - - # Disable boot loaders, as a UKI is used, which contains systemd-stub. - # TODO(raitobezarius): revisit this when #244907 lands - boot.loader.grub.enable = false; - - system.image.id = imageId; - system.image.version = imageVersion; - - # systemd-veritysetup-generator takes care of setting up the root filesystem. - fileSystems = lib.mkForce { }; - virtualisation.fileSystems = lib.mkForce { }; - - # Provides 'veritysetup' to check if the verity-protected device - # has been mapped correctly. - environment.systemPackages = with pkgs; [ cryptsetup ]; - - boot.initrd = { - kernelModules = [ "overlay" ]; - supportedFilesystems = [ "erofs" ]; - - systemd = { - enable = true; - dmVerity.enable = true; - root = null; # systemd-veritysetup-generator takes care of mounting / - - tmpfiles.settings = { - "10-mountpoints" = - let - conf = { - mode = "0755"; - user = "root"; - group = "root"; - }; - in - { - "/run/etc/upper".d = conf; - "/run/etc/work".d = conf; - "/run/var/upper".d = conf; - "/run/var/work".d = conf; - "/run/tmp/upper".d = conf; - "/run/tmp/work".d = conf; - }; - }; - - # We directly define the mount units here, as we need to specify dependencies very - # granularly, and systemd-fstab-generator doesn't give us that flexibility. - mounts = [ - { - where = "/sysroot/etc"; - what = "overlay"; - type = "overlay"; - options = "lowerdir=/sysroot${config.system.build.etc}/etc,upperdir=/run/etc/upper,workdir=/run/etc/work"; - wantedBy = [ - "initrd-fs.target" - "initrd-switch-root.target" - "default.target" - ]; - before = [ "initrd-fs.target" ]; - after = [ "systemd-tmpfiles-setup.service" ]; - unitConfig.RequiresMountsFor = "/sysroot/nix/store"; - unitConfig.DefaultDependencies = false; - } - { - where = "/sysroot/var"; - what = "overlay"; - type = "overlay"; - options = "lowerdir=/sysroot/var,upperdir=/run/var/upper,workdir=/run/var/work"; - wantedBy = [ - "initrd-fs.target" - "initrd-switch-root.target" - "default.target" - ]; - before = [ "initrd-fs.target" ]; - after = [ "systemd-tmpfiles-setup.service" ]; - unitConfig.RequiresMountsFor = "/sysroot/nix/store"; - unitConfig.DefaultDependencies = false; - } - { - where = "/sysroot/tmp"; - what = "overlay"; - type = "overlay"; - options = "lowerdir=/sysroot/tmp,upperdir=/run/tmp/upper,workdir=/run/tmp/work"; - wantedBy = [ - "initrd-fs.target" - "initrd-switch-root.target" - "default.target" - ]; - before = [ "initrd-fs.target" ]; - after = [ "systemd-tmpfiles-setup.service" ]; - unitConfig.RequiresMountsFor = "/sysroot/nix/store"; - unitConfig.DefaultDependencies = false; - } - ]; - }; - }; - - boot.kernelParams = [ - "systemd.verity=yes" - "roothash=${roothashPlaceholder}" - ]; - - image.repart = { - name = imageId; - # OVMF does not work with the default repart sector size of 4096 - sectorSize = 512; - partitions = { - # ESP - "00-esp" = { - contents = - let - efiArch = config.nixpkgs.hostPlatform.efiArch; - in - { - "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source = "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi"; - - "/EFI/Linux/${config.system.boot.loader.ukiFile}".source = "${config.system.build.uki}/${config.system.boot.loader.ukiFile}"; - }; - repartConfig = { - Type = "esp"; - Format = "vfat"; - # Minimize = "guess" seems to not work very well for vfat - # partitions. It's better to set a sensible default instead. The - # aarch64 kernel seems to generally be a little bigger than the - # x86_64 kernel. To stay on the safe side, leave some more slack - # for every platform other than x86_64. - SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M"; - }; - }; - - # Root Partition - "10-root" = { - storePaths = [ config.system.build.toplevel ]; - repartConfig = { - Type = "root"; - Format = "erofs"; - Label = "root"; - Verity = "data"; - VerityMatchKey = "root"; - Minimize = "best"; - # We need to ensure that mountpoints are available. - MakeDirectories = "/bin /boot /dev /etc /home /lib /lib64 /mnt /nix /opt /proc /root /run /srv /sys /tmp /usr /var"; - }; - }; - - # Verity hashtree for the root partition - "20-root-verity" = { - repartConfig = { - Type = "root-verity"; - Label = "root-verity"; - Verity = "hash"; - VerityMatchKey = "root"; - Minimize = "best"; - }; - }; - }; - }; - }; - - testScript = - let - # We override the build of the image by extending it with code to replace the placeholder with the real root hash. - # This way, we can build the image first and then set the root hash afterwards in a single derivation. - buildOverride = oldAttrs: { - nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ pkgs.jq ]; - postInstall = '' - # Replace the placeholder with the real root hash. - realRoothash=$(${pkgs.jq}/bin/jq -r "[.[] | select(.roothash != null)] | .[0].roothash" $out/repart-output.json) - sed -i "0,/${roothashPlaceholder}/ s/${roothashPlaceholder}/$realRoothash/" $out/${oldAttrs.pname}_${oldAttrs.version}.raw - ''; - }; - in - { nodes, ... }: - '' - import os, subprocess, tempfile - - tmp_disk_image = tempfile.NamedTemporaryFile() - - subprocess.run([ - "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", - "create", - "-f", - "qcow2", - "-b", - "${nodes.machine.system.build.image.overrideAttrs buildOverride}/${nodes.machine.image.repart.imageFile}", - "-F", - "raw", - tmp_disk_image.name, - ]) - - # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image. - os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name - - os_release = machine.succeed("cat /etc/os-release") - assert 'IMAGE_ID="${imageId}"' in os_release - assert 'IMAGE_VERSION="${imageVersion}"' in os_release - - bootctl_status = machine.succeed("bootctl status") - assert "Boot Loader Specification Type #2 (.efi)" in bootctl_status - - verity_status = machine.succeed("veritysetup status root") - assert "type: VERITY" in verity_status - assert "status: verified" in verity_status - - commandline = machine.succeed("cat /proc/cmdline") - roothash = commandline.split("roothash=")[1].split(" ")[0] - assert roothash in verity_status - ''; -}