Revert "nixos: support dm-verity"
This commit is contained in:
parent
8edc668914
commit
5a575e88b6
@ -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).
|
||||
|
@ -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
|
||||
|
@ -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 ];
|
||||
}
|
@ -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";
|
||||
|
@ -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; };
|
||||
|
@ -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
|
||||
'';
|
||||
}
|
Loading…
Reference in New Issue
Block a user