From b82163310a951f75baaee52c0b62527214a95441 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Sun, 27 Apr 2025 16:30:16 +0200 Subject: [PATCH] fix: Use and configure grub for mirrored efi partitions --- example/btrfs-raid-mirrored-boot.nix | 81 ++++++++++++++++++++++++++++ lib/default.nix | 38 ++++++++++--- lib/make-disk-image.nix | 2 + lib/tests.nix | 2 +- tests/btrfs-raid-mirrored-boot.nix | 16 ++++++ 5 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 example/btrfs-raid-mirrored-boot.nix create mode 100644 tests/btrfs-raid-mirrored-boot.nix diff --git a/example/btrfs-raid-mirrored-boot.nix b/example/btrfs-raid-mirrored-boot.nix new file mode 100644 index 00000000..b60ad649 --- /dev/null +++ b/example/btrfs-raid-mirrored-boot.nix @@ -0,0 +1,81 @@ +{ + disko.devices.disk = { + one = { + type = "disk"; + device = "/dev/vda"; + + content = { + type = "gpt"; + + partitions = { + boot = { + size = "1M"; + type = "EF02"; + }; + + esp = { + size = "1G"; + type = "EF00"; + + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot0"; + mountOptions = [ "umask=0077" ]; + }; + }; + + root = { + size = "100%"; + + content = { + type = "btrfs"; + }; + }; + }; + }; + }; + + two = { + type = "disk"; + device = "/dev/vdb"; + + content = { + type = "gpt"; + + partitions = { + boot = { + size = "1M"; + type = "EF02"; + }; + + esp = { + size = "1G"; + type = "EF00"; + + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot1"; + mountOptions = [ "umask=0077" ]; + }; + }; + + root = { + size = "100%"; + + content = { + type = "btrfs"; + mountpoint = "/"; + extraArgs = [ + "-f" + "-d raid1" + "/dev/disk/by-partlabel/disk-one-root" + ]; + }; + }; + }; + }; + }; + }; +} diff --git a/lib/default.nix b/lib/default.nix index f12a70bd..733d4bc3 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1033,13 +1033,37 @@ let ''; default = with lib; - let - configKeys = flatten ( - map attrNames (flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))))) - ); - collectedConfigs = flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices)))); - in - genAttrs configKeys (key: mkMerge (catAttrs key collectedConfigs)); + ( + let + configKeys = flatten ( + map attrNames (flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))))) + ); + collectedConfigs = flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices)))); + in + genAttrs configKeys (key: mkMerge (catAttrs key collectedConfigs)) + ) + // ( + let + efi_partitions = builtins.filter (part: part.type == "EF00") ( + flatten ( + map (disk: map (part: part // { device = disk.device; }) (attrValues disk.content.partitions)) ( + flatten (map attrValues (attrValues devices)) + ) + ) + ); + in + (optionalAttrs (builtins.length efi_partitions >= 2) { + # Mirrored boot partitions are not supported on systemd-boot. + boot.loader.grub.enable = mkForce true; + boot.loader.grub.devices = mkForce [ ]; + boot.loader.grub.mirroredBoots = mkForce ( + map (part: { + devices = [ part.device ]; + path = part.content.mountpoint; + }) efi_partitions + ); + }) + ); }; }; } diff --git a/lib/make-disk-image.nix b/lib/make-disk-image.nix index e3c0c3d5..447efb9f 100644 --- a/lib/make-disk-image.nix +++ b/lib/make-disk-image.nix @@ -61,6 +61,7 @@ let disko.testMode = true; disko.devices = lib.mkForce cleanedConfig.disko.devices; boot.loader.grub.devices = lib.mkForce cleanedConfig.boot.loader.grub.devices; + boot.loader.grub.mirroredBoots = lib.mkForce cleanedConfig.boot.loader.grub.mirroredBoots; } ]; }; @@ -73,6 +74,7 @@ let disko.testMode = true; disko.devices = lib.mkForce cleanedConfig.disko.devices; boot.loader.grub.devices = lib.mkForce cleanedConfig.boot.loader.grub.devices; + boot.loader.grub.mirroredBoots = lib.mkForce cleanedConfig.boot.loader.grub.mirroredBoots; nixpkgs.hostPlatform = lib.mkForce pkgs.stdenv.hostPlatform; nixpkgs.buildPlatform = lib.mkForce pkgs.stdenv.hostPlatform; } diff --git a/lib/tests.nix b/lib/tests.nix index fcdefbb9..94bcf488 100644 --- a/lib/tests.nix +++ b/lib/tests.nix @@ -182,7 +182,7 @@ let boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms # grub will install to these devices, we need to force those or we are offset by 1 - # we use mkOveride 70, so that users can override this with mkForce in case they are testing grub mirrored boots + # we use mkOverride 70, so that users can override this with mkForce in case they are testing grub mirrored boots boot.loader.grub.devices = lib.mkOverride 70 testConfigInstall.boot.loader.grub.devices; assertions = [ diff --git a/tests/btrfs-raid-mirrored-boot.nix b/tests/btrfs-raid-mirrored-boot.nix new file mode 100644 index 00000000..889aa7fa --- /dev/null +++ b/tests/btrfs-raid-mirrored-boot.nix @@ -0,0 +1,16 @@ +{ + pkgs ? import { }, + diskoLib ? pkgs.callPackage ../lib { }, +}: +diskoLib.testLib.makeDiskoTest { + inherit pkgs; + name = "btrfs-raid-mirrored-boot"; + disko-config = ../example/btrfs-raid-mirrored-boot.nix; + extraTestScript = '' + machine.succeed("mountpoint /"); + ''; + extraSystemConfig = { + # Mirrored boot partitions are not supported on systemd-boot. + boot.loader.systemd-boot.enable = false; + }; +}