pin the bootloader explicitly and bound the grub menu to 10 generations
grub.enable defaults to true, so adding a boot.loader block silently switched this host from the systemd-boot it was installed with over to grub. nixos removes neither the old bootloader's files nor its nvram entry, so both lived on the esp and the firmware kept booting a frozen systemd-boot menu. pinning both options means a conflicting definition elsewhere now fails loudly instead of quietly winning. note the pins delete nothing - stale EFI/systemd/, loader/ and the leftover nvram entry still have to be cleared by hand. done on shadow, not verified on t480. configurationLimit bounds esp usage for real, not just the menu: install-grub.pl unlinks any $boot/kernels/* that no kept generation references. sizing measured on shadow rather than assumed - 10 kept generations referenced 1 bzImage and 3 initrds for 114mib total, about 11mib per generation, because generations share aggressively. the worst case is higher, around 47mib each, since nixpkgs embeds /etc/modprobe.d/nixos.conf inside the initrd and so every kernel module parameter edit mints a fresh one. 10 therefore costs ~115mib typically and ~470mib worst case against a 1gib esp that also carries the grub modules, the catppuccin theme, and windows' own boot files. keeping it conservative matters because overflow fails as `copy ... or die` in install-grub.pl, which runs *after* the system profile has already been switched - the result is an activated but unbootable generation. t480 reaches this module too and its esp may be smaller.
This commit is contained in:
@@ -10,10 +10,67 @@
|
||||
efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
# Pinned explicitly. grub.enable defaults to true, so this host silently
|
||||
# switched from systemd-boot (used at install time) to GRUB when this
|
||||
# block was added. NixOS never removes the previous bootloader's files
|
||||
# or its NVRAM entry, so both lived on the ESP and the firmware kept
|
||||
# booting the frozen systemd-boot menu. Keep this explicit, and never
|
||||
# set systemd-boot.enable alongside it.
|
||||
#
|
||||
# Note what this does and does not do. Both of these lines are no-ops
|
||||
# against nixpkgs' defaults (grub.enable is already true,
|
||||
# systemd-boot.enable already false); their value is that a conflicting
|
||||
# definition elsewhere now fails loudly instead of silently winning. They
|
||||
# delete nothing — stale EFI/systemd/, loader/ and the leftover NVRAM
|
||||
# entry have to be removed by hand on any host installed with
|
||||
# systemd-boot. Done on shadow; NOT yet verified on t480.
|
||||
#
|
||||
# This is stock UEFI GRUB: NixOS installs EFI/<distro><esp>/grubx64.efi
|
||||
# (here EFI/NixOS-boot/grubx64.efi) and registers a matching NVRAM entry
|
||||
# via efibootmgr, because canTouchEfiVariables is true. That NVRAM entry
|
||||
# is what makes GRUB the default; NixOS does not manage the removable
|
||||
# fallback path EFI/BOOT/BOOTX64.EFI and we deliberately do not ask it to
|
||||
# (grub.efiInstallAsRemovable, which would need canTouchEfiVariables=false,
|
||||
# is only for firmware that ignores NVRAM entries — neither host needs it).
|
||||
#
|
||||
# On shadow that fallback path is NOT empty, though: bcdboot left a copy of
|
||||
# the *Windows* boot manager at EFI/BOOT/bootx64.efi (byte-identical to
|
||||
# EFI/Microsoft/Boot/bootmgfw.efi). Normal boots are unaffected because the
|
||||
# firmware follows its NVRAM entry to GRUB. But it does mean that if NVRAM
|
||||
# is ever cleared — CMOS reset, battery, firmware update — the fallback
|
||||
# lands on Windows rather than GRUB. Left as-is by choice; recover by
|
||||
# rerunning `nixos-rebuild boot` to reinstate the NVRAM entry.
|
||||
systemd-boot.enable = false;
|
||||
grub = {
|
||||
enable = true;
|
||||
efiSupport = true;
|
||||
device = "nodev";
|
||||
theme = pkgs.catppuccin-grub;
|
||||
# Bound the menu so the ESP cannot fill up with old kernels.
|
||||
# install-grub.pl unlinks any $boot/kernels/* not referenced by a kept
|
||||
# generation, so this genuinely caps ESP usage rather than just
|
||||
# trimming the menu.
|
||||
#
|
||||
# Sizing, measured on shadow rather than assumed. Generations share
|
||||
# aggressively in practice: 10 kept generations referenced 1 bzImage
|
||||
# (13.3MiB) and 3 initrds (~33.4MiB each) for 114MiB total, i.e. ~11MiB
|
||||
# per generation, not ~47MiB. Only a kernel or initrd change mints a new
|
||||
# file — and the initrd does change more often than you'd expect, since
|
||||
# nixpkgs embeds /etc/modprobe.d/nixos.conf inside it, so every kernel
|
||||
# module parameter edit produces a fresh one.
|
||||
#
|
||||
# So the real bound is between ~11MiB and ~47MiB per generation
|
||||
# depending on churn: 10 generations costs ~115MiB typically and ~470MiB
|
||||
# worst case, against a 1GiB ESP that also carries grub/x86_64-efi, the
|
||||
# catppuccin theme, and Windows' own boot files (bootmgfw.efi + BCD,
|
||||
# ~30-60MiB) since Windows was bcdboot'd onto this same ESP. 10 keeps
|
||||
# the worst case under half the partition.
|
||||
#
|
||||
# Keep this conservative: overflow fails as `copy ... or die` in
|
||||
# install-grub.pl, which runs *after* the system profile has already
|
||||
# been switched, so the result is an activated but unbootable
|
||||
# generation. t480 reaches this module too and its ESP may be smaller.
|
||||
configurationLimit = 10;
|
||||
};
|
||||
};
|
||||
plymouth = {
|
||||
|
||||
Reference in New Issue
Block a user