NixOS does not natively support Secure Boot. Lanzaboote bridges this gap by replacing systemd-boot with a signed UEFI stub that chainloads NixOS generations.
This guide covers initial setup, how the NixOS module works, and recovery after BIOS updates.
UEFI Firmware (Secure Boot ON)
└── Lanzaboote stub (signed EFI binary)
└── Unified Kernel Image (signed)
└── initrd → NixOS system
- sbctl generates your own Secure Boot keys (PK, KEK, db) and stores them at
/var/lib/sbctl - Lanzaboote hooks into
nixos-rebuildand signs all EFI binaries (bootloader + kernel images) with your keys - The UEFI firmware verifies signatures on boot — only your signed binaries can execute
The flake integrates Lanzaboote via:
# Host flake-module.nix imports:
inputs.lanzaboote.nixosModules.lanzaboote
# Host default.nix enables:
myModules.boot.boot = {
enable = true;
loader = "systemd-boot";
secureBoot.enable = true; # Activates Lanzaboote
plymouth.enable = true; # Works with Secure Boot
};When secureBoot.enable = true:
boot.lanzaboote.enableis set, replacing rawsystemd-bootboot.lanzaboote.pkiBundlepoints to/var/lib/sbctl(configurable viasecureBoot.pkiBundle)sbctlis added to system packages for key managementsystemd-boot.enableis automatically disabled (Lanzaboote takes over)
Secure Boot key creation cannot be automated by Nix because it requires writing to UEFI firmware variables, which is a one-time hardware operation.
- UEFI firmware (not legacy BIOS)
- Secure Boot set to Setup Mode in BIOS (usually: disable Secure Boot → clear keys → it enters Setup Mode)
- A working NixOS installation with this flake applied
sudo sbctl statusYou should see:
Installed: ✓ sbctl is installed
Owner GUID: <none>
Setup Mode: ✓ Enabled ← Required
Secure Boot: ✗ Disabled
If Setup Mode shows ✗ Disabled, you need to enter BIOS and clear the Secure Boot keys first.
sudo sbctl create-keysThis generates:
/var/lib/sbctl/keys/PK/— Platform Key (root of trust)/var/lib/sbctl/keys/KEK/— Key Exchange Key/var/lib/sbctl/keys/db/— Signature Database key (signs binaries)/var/lib/sbctl/GUID— Your unique Owner GUID
sudo sbctl enroll-keys --microsoftThe --microsoft flag includes Microsoft's keys alongside yours. This is required for:
- GPU firmware (VBIOS) to load — most GPUs have Microsoft-signed Option ROMs
- USB device firmware during early boot
- Any third-party UEFI drivers
Without --microsoft, your system may not POST or display video output.
Troubleshooting: If you get an error about "immutable files":
sudo chattr -i /sys/firmware/efi/efivars/PK-* sudo chattr -i /sys/firmware/efi/efivars/KEK-* sudo chattr -i /sys/firmware/efi/efivars/db-* sudo sbctl enroll-keys --microsoft
nrbOr manually:
sudo nixos-rebuild switch --flake ".#<hostname>"Lanzaboote signs during activation:
Installing Lanzaboote to "/boot"...
Collecting garbage...
Successfully installed Lanzaboote.
sudo sbctl verifyExpected output (all green):
✓ /boot/EFI/BOOT/BOOTX64.EFI is signed
✓ /boot/EFI/systemd/systemd-bootx64.efi is signed
✓ /boot/EFI/Linux/nixos-generation-*.efi is signed
- Reboot and enter BIOS/UEFI
- Navigate to Boot or Security section
- Set Secure Boot to Enabled (on ASUS boards: "Windows UEFI mode")
- Save and exit
After booting into NixOS:
sudo sbctl statusExpected:
Installed: ✓ sbctl is installed
Owner GUID: <your-guid>
Setup Mode: ✗ Disabled
Secure Boot: ✓ Enabled
Vendor Keys: microsoft
You can also verify via the kernel:
bootctl status | grep "Secure Boot"BIOS updates typically wipe Secure Boot variables (PK, KEK, db, dbx), putting the motherboard back into Setup Mode. Your keys still exist at /var/lib/sbctl — they just need to be re-enrolled.
sudo sbctl statusYou should see:
Owner GUID: (your existing GUID — keys are intact)Setup Mode: ✓ Enabled (firmware was wiped)Secure Boot: ✗ Disabled
sudo sbctl enroll-keys --microsoftnrbThis re-signs all boot binaries.
sudo sbctl verifyThen reboot into BIOS and re-enable Secure Boot (Step 6 from initial setup).
sudo sbctl statusShould show Secure Boot: ✓ Enabled again.
Your Secure Boot keys at /var/lib/sbctl are not managed by Nix and not in your flake. If you lose them, you must create new keys and re-enroll.
Back them up:
sudo tar -czf sbctl-keys-backup.tar.gz -C /var/lib sbctl
# Store securely (encrypted drive, password manager, etc.)Restore on a new install:
sudo tar -xzf sbctl-keys-backup.tar.gz -C /var/lib
sudo sbctl enroll-keys --microsoft
nrbYou likely enrolled without --microsoft. Boot from a USB, mount your system, and:
sudo chattr -i /sys/firmware/efi/efivars/{PK,KEK,db}-*
sudo sbctl enroll-keys --microsoftOr clear Secure Boot keys in BIOS to get back to Setup Mode.
Old generations may have unsigned kernels. Lanzaboote boots unified images, so these are harmless. To clean up:
# Remove old generations
sudo nix-collect-garbage -d
# Rebuild to update boot entries
nrb
sudo sbctl verifyCheck if your BIOS has separate "Secure Boot" and "Secure Boot Mode" settings. Some boards require setting the mode to "Custom" or "Standard" after enabling.
Plymouth requires early KMS. Ensure your GPU driver is in the initrd:
# This flake handles it automatically when both are enabled:
myModules.boot.boot.plymouth.enable = true;
myModules.hardware.gpuAmd.enable = true; # Loads amdgpu in initrd