From 6ec6eae5864379145d5ba3121e13271d82cea1fd Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Fri, 28 Feb 2025 14:30:10 -0500 Subject: [PATCH] Revert "nixos/grub: generate BLS entries" --- .../manual/release-notes/rl-2505.section.md | 4 - .../modules/system/boot/loader/grub/grub.nix | 14 -- .../system/boot/loader/grub/install-grub.pl | 77 +------- nixos/tests/all-tests.nix | 2 +- nixos/tests/grub.nix | 169 ++++++------------ .../nixos-rebuild-install-bootloader.nix | 3 - 6 files changed, 56 insertions(+), 213 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index cdeb306cdc307..ce4f32d44903f 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -519,10 +519,6 @@ - `services.gitea` now supports CAPTCHA usage through the `services.gitea.captcha` variable. -- The GRUB bootloader (`boot.loader.grub`) now generates [boot loader entries](https://uapi-group.org/specifications/specs/boot_loader_specification/). - These files are used by userspace tools (for example, `bootctl`) to inspect the bootloader status, getting the default boot entry, the path of the kernel binary, etc. - As a consequence, `systemctl kexec` now works automatically: specifying the kernel and its arguments with `kexec --load` is no longer required. - - `bind.cacheNetworks` now only controls access for recursive queries, where it previously controlled access for all queries. - [`services.mongodb.enableAuth`](#opt-services.mongodb.enableAuth) now uses the newer [mongosh](https://github.com/mongodb-js/mongosh) shell instead of the legacy shell to configure the initial superuser. You can configure the mongosh package to use through the [`services.mongodb.mongoshPackage`](#opt-services.mongodb.mongoshPackage) option. diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index febd059033dd2..72e8e4c0d081f 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -50,10 +50,6 @@ let then realGrub.override { efiSupport = cfg.efiSupport; } else null; - bootPath = if cfg.mirroredBoots != [ ] - then (builtins.head cfg.mirroredBoots).path - else "/boot"; - f = x: optionalString (x != null) ("" + x); grubConfig = args: @@ -760,16 +756,6 @@ in environment.systemPackages = mkIf (grub != null) [ grub ]; - # Link /boot under /run/boot-loder-entries to make - # systemd happy even on non-EFI system - systemd.mounts = lib.optional (!cfg.efiSupport) { - what = bootPath; - where = "/run/boot-loader-entries"; - type = "none"; - options = "bind"; - requiredBy = [ "local-fs.target" ]; - }; - boot.loader.grub.extraPrepareConfig = concatStrings (mapAttrsToList (n: v: '' ${pkgs.coreutils}/bin/install -Dp "${v}" "${efi.efiSysMountPoint}/"${escapeShellArg n} diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 99b2a766a5d0d..f5ae844da21f9 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -99,15 +99,7 @@ sub runCommand { print STDERR "updating GRUB 2 menu...\n"; -# Make GRUB directory -make_path("$bootPath/grub", { mode => 0700 }); - -# Make BLS entries directory, see addBLSEntry -make_path("$bootPath/loader/entries", { mode => 0700 }); -writeFile("$bootPath/loader/entries.srel", "type1"); - -# and a temporary one for new entries -make_path("$bootPath/loader/entries.tmp", { mode => 0700 }); +make_path("$bootPath/grub", { mode => 0700 }); # Discover whether the bootPath is on the same filesystem as / and # /nix/store. If not, then all kernels and initrds must be copied to @@ -468,7 +460,6 @@ sub copyToKernelsDir { } sub addEntry { - # Creates a Grub menu entry for a given system my ($name, $path, $options, $current) = @_; return unless -e "$path/kernel" && -e "$path/initrd"; @@ -530,58 +521,6 @@ sub addEntry { $conf .= "}\n\n"; } -sub addBLSEntry { - # Creates a Boot Loader Specification[1] entry for a given system. - # The information contained in the entry mirrors a boot entry in GRUB menu. - # - # [1]: https://uapi-group.org/specifications/specs/boot_loader_specification - my ($prof, $spec, $gen, $link) = @_; - - # collect data from system - my %bootspec = %{decode_json(readFile("$link/boot.json"))->{"org.nixos.bootspec.v1"}}; - my $date = strftime("%F", localtime(lstat($link)->mtime)); - my $kernel = $bootspec{kernel} =~ s@$storePath/@@r =~ s@/@-@r; - my $initrd = $bootspec{initrd} =~ s@$storePath/@@r =~ s@/@-@r; - my $kernelParams = readFile("$link/kernel-params"); - my $machineId = readFile("/etc/machine-id"); - - if ($grubEfi eq "" && !$copyKernels) { - # workaround for https://github.com/systemd/systemd/issues/35729 - make_path("$bootPath/kernels", { mode => 0755 }); - symlink($bootspec{kernel}, "$bootPath/kernels/$kernel"); - symlink($bootspec{initrd}, "$bootPath/kernels/$initrd"); - $copied{"$bootPath/kernels/$kernel"} = 1; - $copied{"$bootPath/kernels/$initrd"} = 1; - } - - # fill in the entry - my $extras = join(' ', $prof = $prof ne "system" ? " [$prof] " : "", - $spec = $spec ne "" ? " ($spec) " : ""); - my $entry = <<~END; - title @distroName@$extras - sort-key nixos - version Generation $gen $bootspec{label}, built on $date - linux kernels/$kernel - initrd kernels/$initrd - options init=$bootspec{init} $kernelParams - END - $entry .= "machine-id $machineId" if defined $machineId; - - # entry file basename - my $name = join("-", grep { length $_ > 0 } - "nixos", $prof ne "system" ? $prof : "", - "generation", $gen, - $spec ? "specialisation-$spec" : ""); - - # write entry to the temp directory - writeFile("$bootPath/loader/entries.tmp/$name.conf", $entry); - - # mark the default entry - if (readlink($link) eq $defaultConfig) { - writeFile("$bootPath/loader/loader.conf", "default $name.conf"); - } -} - sub addGeneration { my ($name, $nameSuffix, $path, $options, $current) = @_; @@ -653,18 +592,12 @@ sub addProfile { warn "skipping corrupt system profile entry ‘$link’\n"; next; } - my $gen = nrFromGen($link); my $date = strftime("%F", localtime(lstat($link)->mtime)); my $version = -e "$link/nixos-version" ? readFile("$link/nixos-version") : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); - addGeneration("@distroName@ - Configuration " . $gen, " ($date - $version)", $link, $subEntryOptions, 0); - - addBLSEntry(basename($profile), "", $gen, $link); - foreach my $spec (glob "$link/specialisation/*") { - addBLSEntry(basename($profile), $spec, $gen, $spec); - } + addGeneration("@distroName@ - Configuration " . nrFromGen($link), " ($date - $version)", $link, $subEntryOptions, 0); } $conf .= "}\n"; @@ -678,12 +611,6 @@ sub addProfile { addProfile $profile, "@distroName@ - Profile '$name'"; } -# Atomically replace the BLS entries directory -my $entriesDir = "$bootPath/loader/entries"; -rename $entriesDir, "$entriesDir.bak" or die "cannot rename $entriesDir to $entriesDir.bak: $!\n"; -rename "$entriesDir.tmp", $entriesDir or die "cannot rename $entriesDir.tmp to $entriesDir: $!\n"; -rmtree "$entriesDir.bak" or die "cannot remove $entriesDir.bak: $!\n"; - # extraPrepareConfig could refer to @bootPath@, which we have to substitute $extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index f753795bc6298..7a26efbcf4ea4 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -463,7 +463,7 @@ in { greetd-no-shadow = handleTest ./greetd-no-shadow.nix {}; grocy = handleTest ./grocy.nix {}; grow-partition = runTest ./grow-partition.nix; - grub = import ./grub.nix { inherit pkgs runTest; }; + grub = handleTest ./grub.nix {}; guacamole-server = handleTest ./guacamole-server.nix {}; guix = handleTest ./guix {}; gvisor = handleTest ./gvisor.nix {}; diff --git a/nixos/tests/grub.nix b/nixos/tests/grub.nix index 3820eff4892ae..e0875e70f6a51 100644 --- a/nixos/tests/grub.nix +++ b/nixos/tests/grub.nix @@ -1,123 +1,60 @@ -{ pkgs, runTest }: +import ./make-test-python.nix ({ lib, ... }: { + name = "grub"; -{ - # Basic GRUB setup with BIOS and a password - basic = runTest { - name = "grub-basic"; - meta.maintainers = with pkgs.lib.maintainers; [ rnhmjoj ]; - - nodes.machine = { ... }: { - virtualisation.useBootLoader = true; - boot.loader.timeout = null; - boot.loader.grub = { - enable = true; - users.alice.password = "supersecret"; - # OCR is not accurate enough - extraConfig = "serial; terminal_output serial"; - }; - }; - - testScript = '' - def grub_login_as(user, password): - """ - Enters user and password to log into GRUB - """ - machine.wait_for_console_text("Enter username:") - machine.send_chars(user + "\n") - machine.wait_for_console_text("Enter password:") - machine.send_chars(password + "\n") - - - def grub_select_all_configurations(): - """ - Selects "All configurations" from the GRUB menu - to trigger a login request. - """ - machine.send_monitor_command("sendkey down") - machine.send_monitor_command("sendkey ret") - - - machine.start() - - # wait for grub screen - machine.wait_for_console_text("GNU GRUB") - - grub_select_all_configurations() - with subtest("Invalid credentials are rejected"): - grub_login_as("wronguser", "wrongsecret") - machine.wait_for_console_text("error: access denied.") - - grub_select_all_configurations() - with subtest("Valid credentials are accepted"): - grub_login_as("alice", "supersecret") - machine.send_chars("\n") # press enter to boot - machine.wait_for_console_text("Linux version") - - with subtest("Machine boots correctly"): - machine.wait_for_unit("multi-user.target") - ''; - }; - - # Test boot loader entries on EFI - bls-efi = runTest { - name = "grub-bls-efi"; - meta.maintainers = with pkgs.lib.maintainers; [ rnhmjoj ]; - - nodes.machine = { pkgs, ... }: { - virtualisation.useBootLoader = true; - virtualisation.useEFIBoot = true; - boot.loader.efi.canTouchEfiVariables = true; - boot.loader.grub.enable = true; - boot.loader.grub.efiSupport = true; - }; - - testScript = '' - with subtest("Machine boots correctly"): - machine.wait_for_unit("multi-user.target") - - with subtest("Boot entries are installed"): - entries = machine.succeed("bootctl list") - print(entries) - error = "NixOS boot entry not found in bootctl list." - assert "version: Generation 1" in entries, error - - with subtest("systemctl kexec can detect the kernel"): - machine.succeed("systemctl kexec --dry-run") - - with subtest("systemctl kexec really works"): - machine.execute("systemctl kexec", check_return=False) - machine.connected = False - machine.connect() - machine.wait_for_unit("multi-user.target") - ''; + meta = with lib.maintainers; { + maintainers = [ rnhmjoj ]; }; - # Test boot loader entries on BIOS - bls-bios = runTest { - name = "grub-bls-bios"; - meta.maintainers = with pkgs.lib.maintainers; [ rnhmjoj ]; - - nodes.machine = { pkgs, ... }: { - virtualisation.useBootLoader = true; - boot.loader.grub.enable = true; - }; - - testScript = '' - with subtest("Machine boots correctly"): - machine.wait_for_unit("multi-user.target") - - with subtest("Boot entries are installed"): - machine.succeed("test -f /boot/loader/entries/nixos-generation-1.conf") + nodes.machine = { ... }: { + virtualisation.useBootLoader = true; - with subtest("systemctl kexec can detect the kernel"): - machine.succeed("systemctl kexec --dry-run") + boot.loader.timeout = null; + boot.loader.grub = { + enable = true; + users.alice.password = "supersecret"; - with subtest("systemctl kexec really works"): - machine.execute("systemctl kexec", check_return=False) - machine.connected = False - machine.connect() - machine.wait_for_unit("multi-user.target") - ''; + # OCR is not accurate enough + extraConfig = "serial; terminal_output serial"; + }; }; -} + testScript = '' + def grub_login_as(user, password): + """ + Enters user and password to log into GRUB + """ + machine.wait_for_console_text("Enter username:") + machine.send_chars(user + "\n") + machine.wait_for_console_text("Enter password:") + machine.send_chars(password + "\n") + + + def grub_select_all_configurations(): + """ + Selects "All configurations" from the GRUB menu + to trigger a login request. + """ + machine.send_monitor_command("sendkey down") + machine.send_monitor_command("sendkey ret") + + + machine.start() + + # wait for grub screen + machine.wait_for_console_text("GNU GRUB") + + grub_select_all_configurations() + with subtest("Invalid credentials are rejected"): + grub_login_as("wronguser", "wrongsecret") + machine.wait_for_console_text("error: access denied.") + + grub_select_all_configurations() + with subtest("Valid credentials are accepted"): + grub_login_as("alice", "supersecret") + machine.send_chars("\n") # press enter to boot + machine.wait_for_console_text("Linux version") + + with subtest("Machine boots correctly"): + machine.wait_for_unit("multi-user.target") + ''; +}) diff --git a/nixos/tests/nixos-rebuild-install-bootloader.nix b/nixos/tests/nixos-rebuild-install-bootloader.nix index 64d978119d575..1e517871e7d17 100644 --- a/nixos/tests/nixos-rebuild-install-bootloader.nix +++ b/nixos/tests/nixos-rebuild-install-bootloader.nix @@ -71,8 +71,5 @@ import ./make-test-python.nix ({ pkgs, lib, withNg ? false, ... }: { # at this point we've tested regression #262724, but haven't tested the bootloader itself # TODO: figure out how to how to tell the test driver to start the bootloader instead of # booting into the kernel directly. - - with subtest("New boot entry has been added"): - machine.succeed("test -f /boot/loader/entries/nixos-generation-2.conf") ''; })