Repository navigation
Secure Boot
modules/secureboot.nix adds lanzaboote
(pinned to a release tag in flake.nix): systemd-boot's signed stub and signed
unified kernel images, with your own keys in /var/lib/sbctl. The desktop host
configuration enables lanzaboote; Secure Boot still needs its keys enrolled in
firmware and enabled in the firmware menu. sbctl is installed either way.
The disks are already LUKS-encrypted; Secure Boot adds that only boot files you
signed will run, so nobody can swap the kernel or initrd on the unencrypted
/boot to capture the passphrase.
The cachyos kernel doesn't force lockdown under Secure Boot
(LOCK_DOWN_KERNEL_FORCE_NONE, no MODULE_SIG_FORCE), so the unsigned NVIDIA
modules keep loading.
-
Keys. If keys are not already present, run
sudo sbctl create-keys(into/var/lib/sbctl, root-only). Switching with the option on but no keys fails at the bootloader step (the running generation keeps booting). -
Sign. Set
dots.secureBoot.enable = true;, thennh os switch. -
Check.
sudo sbctl verify:EFI/Boot/bootx64.efi,EFI/systemd/systemd-bootx64.efiand everyEFI/Linux/nixos-generation-*.efimust show as signed.EFI/nixos/kernel-*.efistays unsigned on purpose: the signed generation stubs hash-check the kernel and initrd before booting them. Leftovers from plain systemd-boot (*bzImage.efi,EFI/systemd/systemd-boot-fallbackx64.efi) can be deleted. -
Setup Mode.
systemctl reboot --firmware-setup, then in the firmware's Secure Boot menu reset or delete the keys so it enters Setup Mode (on ASUS boards: Key Management → Clear Secure Boot keys). Keep Secure Boot off for now. -
Enroll. Back in NixOS:
sudo sbctl enroll-keys --microsoft. Keep--microsoft: the RTX 3060's option ROM is Microsoft-signed, and without those keys the card can show nothing before Linux starts. -
Enable.
systemctl reboot --firmware-setup, turn Secure Boot on, boot.bootctl statusshould saySecure Boot: enabled (user).
With Secure Boot on, the TPM can unlock the root disk at boot without the passphrase. The key is sealed to two PCRs (TPM measurement registers):
- PCR 7, the Secure Boot state and keys. If Secure Boot is turned off, the keys change, or something signed only by Microsoft boots (a live USB), it won't unseal.
-
PCR 15 = 0. With
tpm2-measure-pcr=yesthe initrd extends PCR 15 as soon as it opens a volume. That stops a decoy volume (same UUID, attacker's passphrase) from being opened first and then used to unseal the real key.
Because the disk opens by itself, root's password is locked (users.users.root.hashedPassword = "!" in the host): a boot that drops to emergency mode refuses to open a shell instead of handing one to whoever is at the keyboard. Recover a machine that won't boot from the installer ISO; sudo is unaffected.
The passphrase keyslot stays as the fallback. A firmware update or a change to the Secure Boot settings changes PCR 7: you get the passphrase prompt, then re-enroll.
-
Find the root container.
hosts/nixos/disk.nixnames it: today's install is/dev/disk/by-uuid/bd950db0-dc83-432a-bec6-0bc1a72bd76e; after adots-installreinstall (useDisko = true) it is/dev/disk/by-partlabel/disk-main-root. Use those stable paths: the kernel names (nvme0n1/nvme1n1) swap between boots on this board, and the other NVMe holds Windows. The swap partition next to it is re-keyed randomly every boot and has nothing to enroll. -
Initrd.
dots.secureBoot.tpmUnlock(set inhosts/nixos/disk.nix, per layout) lists theboot.initrd.luks.devicesnames the initrd tries the TPM for. It needsdots.secureBoot.enable = true;. With no TPM keyslot yet, boot still asks for the passphrase. -
Enroll. After Secure Boot is enabled in firmware, enroll the TPM key on
the root container (
$root= the path from step 1):Addsudo systemd-cryptenroll "$root" --tpm2-device=auto \ --tpm2-pcrs=7+15:sha256=0000000000000000000000000000000000000000000000000000000000000000--tpm2-with-pin=yesto still type a short PIN at boot; the TPM rate-limits guesses. - Reboot. Root should unlock without a prompt.
Re-enroll after a PCR 7 change, or after a reinstall (a new LUKS header has
no TPM slot): sudo systemd-cryptenroll "$root" --wipe-slot=tpm2, then
step 3. Check the path with lsblk -f before wiping or enrolling any slot.
To drop it, wipe the slot and empty the list.
Turn Secure Boot off in the firmware: everything still boots. To drop
lanzaboote too, set the option back to false and switch.
Source: docs/secure-boot.md
Generated from docs/. Edits made here are overwritten on the next push — change the repo instead.
Start
Reference
Help
More