Skip to content

Secure_Boot

AmazinAxel edited this page Jul 12, 2026 · 2 revisions

This documentation was generated by Claude

1b. Import the module + bootloader (hosts/<host>/hardware-configuration.nix)

Make sure the file header is { lib, ... }: (not just {), import the module, and set the loader:

{ lib, ... }: {
  imports = [ inputs.lanzaboote.nixosModules.lanzaboote ];  # or add to default.nix imports

  boot = {
    # ... your existing hardware bits (luks, kernelModules, etc.) ...

    loader = {
      systemd-boot.enable = lib.mkForce false;   # lanzaboote replaces systemd-boot
      efi.canTouchEfiVariables = true;
    };

    lanzaboote = {
      enable = true;
      pkiBundle = "/var/lib/sbctl";   # the persisted sbctl key store
      configurationLimit = 2;         # <-- size to your ESP (see Step 0)
    };
  };
}
environment.persistence."/persist".directories = [
  # ...
  "/var/lib/sbctl"   # secure boot keys (already here)
];

Have sbctl available for the key steps below — either add it to systemPackages, or just use nix-shell -p sbctl ad hoc (shown inline below).

Do not rebuild yet


Step 2 — Create keys (bind mount is already live)

Because you're already booted with the /var/lib/sbctl bind mount active, keys created here land directly on persistent storage — just create them:

findmnt /var/lib/sbctl                                    # sanity: confirm it's a persist bind mount
sudo nix-shell -p sbctl --run 'sbctl create-keys'         # writes into the persisted store
sudo ls -la /persist/var/lib/sbctl/keys/                  # confirm PK, KEK, db exist under /persist

If findmnt shows the source as your persist device (e.g. cryptpersist[/var/lib/sbctl]) and keys/ contains PK, KEK, db, you're set.


Step 3 — Rebuild (Secure Boot still OFF in BIOS)

sudo nixos-rebuild switch --flake .#<host>

Lanzaboote builds a signed UKI per generation (in /boot/EFI/Linux/) and a signed systemd-boot stub. It boots normally because Secure Boot isn't enabled in firmware yet.

If it fails on No space left on device: the ESP is too small or has leftover boot files. Free space, then rebuild — do not reboot in between:

sudo sh -c 'du -sh /boot/EFI/* | sort -h'      # find what's eating it
sudo nix-collect-garbage -d                      # drop old generations
# remove stale UKIs / dead bootloader files only after confirming what they are
sudo nixos-rebuild switch --flake .#<host>

Lower configurationLimit if it still won't fit.


Step 4 — Verify signing

sudo sbctl verify

Every EFI image listed should be ✓ signed — the systemd-boot stub (/boot/EFI/systemd/… and the /boot/EFI/BOOT/BOOTX64.EFI fallback) and each per-generation UKI (/boot/EFI/Linux/*.efi). Unlike Limine, there's no standalone kernel on the ESP, so there should be no ✗ lines to hand-wave. If anything shows ✗, fix it before enabling Secure Boot.

Reboot now and confirm the machine boots normally via lanzaboote (Secure Boot still off). This checkpoints the boot-chain switch before you touch firmware.


⚠️ Dual-booting Windows — read before Step 5

This machine dual-boots Windows, which changes three things. Do the BitLocker step before you touch the BIOS.

  1. Back up your BitLocker recovery key first (critical). Windows 11 usually has BitLocker/Device Encryption on. Secure Boot state is measured into TPM PCR 7; clearing the firmware keys and enrolling your own changes PCR 7, breaks the TPM seal, and triggers a BitLocker recovery prompt on the next Windows boot. Before Step 5, either:

    • retrieve the 48-digit key from https://aka.ms/myrecoverykey (signed into your MS account), or
    • suspend BitLocker in Windows: manage-bde -protectors -disable C: -RebootCount 0 (re-enable with -enable after everything is stable), or
    • manage-bde -status to check whether it's even on.
  2. --microsoft is mandatory here (not optional). Windows Boot Manager (bootmgfw.efi) is signed with Microsoft's key. Enrolling only your own keys removes Microsoft's certs, so Windows would fail with a Secure Boot violation. In Step 6 you must keep --microsoft — the "try -f alone" tightening does not apply on a dual-boot machine.

  3. Make the boot menu reachable to select Windows. systemd-boot (used by lanzaboote) auto-detects Windows Boot Manager and lists it, but your common.nix sets boot.loader.timeout = lib.mkForce 0, hiding the menu (hold space at boot to show it). For convenience, consider a small timeout on this host, e.g.:

    boot.loader.timeout = lib.mkForce 5;

Also recommended: keep sbctl recent (Microsoft is rotating to the 2023 UEFI CA certs; older sbctl only enrolls the 2011 set, which can break a freshly-updated Windows), and disable Windows Fast Startup (Control Panel → Power → Choose what the power buttons do) so a shared NTFS partition isn't left in a hibernated/dirty state.


Step 5 — HP BIOS: enter Setup Mode

Enrolling your own keys requires the firmware in Setup Mode (no Platform Key enrolled).

  1. Power on and tap F10 repeatedly to enter BIOS Setup (or tap Esc for the Startup Menu, then F10). F9 is the one-time boot device menu.
  2. Find Secure Boot — usually under Advanced → Secure Boot Configuration, or System Configuration → Boot Options → Secure Boot (label varies by BIOS version).
  3. To reach Setup Mode, look for one of:
    • "Clear Secure Boot Keys" / "Erase all Secure Boot Settings", or
    • set Secure Boot mode to "Custom" (vs "Standard"), then clear/delete the existing keys.
  4. Leave Secure Boot itself disabled for now. Save & exit (HP will make you type a 4-digit confirmation code shown on screen, then Enter — that's normal).

⚠️ HP consumer caveat: if your BIOS only offers enable/disable + "Restore Factory Keys" and has no way to clear keys / no "Custom" mode, self-signed enrollment isn't possible on that firmware — you'd be stuck with Microsoft-signed shim instead. Check for the clear/custom option before proceeding. Most HP Insyde BIOSes have it.


Step 6 — Enroll your keys (back in NixOS)

sudo sbctl enroll-keys --microsoft --firmware-builtin
  • --firmware-builtin (-f): enrolls the certs already baked into your firmware — covers vendor-signed device option ROMs. Keep this.
  • --microsoft (-m): trusts Microsoft's certs. Required on this dual-boot machine — it's what keeps Windows Boot Manager bootable (it also covers MS-signed option ROMs and fwupd capsules). Do not drop it here; enrolling without it gives a Secure Boot violation when you try to boot Windows.

Step 7 — HP BIOS: enable Secure Boot

  1. F10 into BIOS again.
  2. Set Secure Boot = Enabled (same menu as Step 5). Save & exit (enter the 4-digit code again).

Step 8 — Confirm it's live (and out of Setup Mode)

sudo sbctl status

You want:

Setup Mode:   ✗ Disabled     <- out of setup mode
Secure Boot:  ✓ Enabled

Cross-check:

bootctl status

Look for Secure Boot: enabled (user)(user) means SB is on, your Platform Key is enrolled, and it's validating against your keys (only reachable out of setup mode). Since lanzaboote is a signed systemd-boot stub, bootctl will report systemd-boot as the current bootloader — that's expected here (it's the lanzaboote-signed variant).

TPM2 Support: no / Measured UKI: no are fine — you're doing key-based, not TPM-measured, boot.


Recovery (if it ever won't boot under Secure Boot)

Nothing here is permanent:

  • F10 into BIOS → disable Secure Boot (or "Clear Secure Boot Keys" / "Restore Factory Keys"), boot, fix, re-enroll.
  • systemd-boot (and thus lanzaboote) installs a signed stub at the removable fallback EFI/BOOT/BOOTX64.EFI as well as the NVRAM entry, so a wiped NVRAM boot entry still boots the signed stub — the common HP failure mode is covered.
  • Windows won't boot / "Secure Boot violation": you enrolled without --microsoft. Re-run sudo sbctl enroll-keys --microsoft --firmware-builtin (firmware back in Setup Mode). Windows demands a recovery key: that's the expected PCR 7 change — enter the key you backed up; it boots normally afterward and re-seals.


Quick reference — the whole flow

# 1. Config: add lanzaboote flake input; import the module;
#    boot.lanzaboote { enable; pkiBundle = "/var/lib/sbctl"; configurationLimit = 2; };
#    systemd-boot off. (persistence for /var/lib/sbctl already set up)  DON'T rebuild yet.

# 2. Keys (bind mount already live -> lands in /persist)
findmnt /var/lib/sbctl
sudo nix-shell -p sbctl --run 'sbctl create-keys'
sudo ls -la /persist/var/lib/sbctl/keys/

# 3. Build & sign (Secure Boot still OFF)
sudo nixos-rebuild switch --flake .#<host>
sudo sbctl verify          # all EFI images ✓ (stub + per-gen UKIs)
# reboot, confirm lanzaboote boots

# 4. BIOS (F10): clear keys -> Setup Mode, leave SB disabled
sudo sbctl enroll-keys --microsoft --firmware-builtin
# BIOS (F10): enable Secure Boot (4-digit confirm)

# 5. Confirm
sudo sbctl status          # Setup Mode: Disabled ; Secure Boot: Enabled
bootctl status             # Secure Boot: enabled (user)

This flake is a submission to Hack Club's Riceathon

Clone this wiki locally