Day 68 — Secure Boot & TPM path
Day 68 — Secure Boot & TPM path
Stage VI · ~4h (hardware-dependent)
Goal: Document and, if hardware allows, implement a Lanzaboote Secure Boot path and/or TPM-backed LUKS unlock—or produce a lab-limits dossier that is honest about what you cannot do on VMs.
Copy-paste without the upstream guide bricks boots. Treat this day as process + documentation first; enable on a disposable machine second. Recovery USB and recovery keys before enrollment.
Why this day exists
Fleet images and metal boxes increasingly expect Secure Boot and disk encryption that does not beg for a passphrase at every reboot in a datacenter. NixOS’s community answer for SB is primarily Lanzaboote (uki/systemd-boot + signed generations). TPM2 unlock pairs with LUKS (Day 57 Disko often declares the encrypted volumes).
Capstone B (stretch) lists SB/TPM; Capstone A does not require full enablement—but Stage VI experts must know the path and the failure modes.
Theory 1 — Problem statement
| Threat | Control |
|---|---|
| Evil maid bootloader swap | Secure Boot + enrolled keys |
| Disk theft | LUKS (or vendor disk encryption—know the difference) |
| Passphrase at scale | TPM2 PCR-bound unlock (with enrollment process) |
| Unsigned kernel modules policies | SB + your key hierarchy |
| Silent rollback to unsigned attacker kernel | Sign each generation you boot |
NixOS’s generation model must sign new boots—not only ship a distro shim forever. That is why Lanzaboote exists relative to “turn on SB and hope.”
Theory 2 — Lanzaboote overview (2026)
Lanzaboote integrates Secure Boot with NixOS (systemd-boot oriented flows).
Typical story (always verify against current README for your pin):
- Enable Secure Boot in firmware (setup mode / enroll keys carefully)
- Generate or enroll machine keys (PK/KEK/db as relevant to the guide)
- Import Lanzaboote NixOS modules so boots are signed
- Keep recovery path (USB installer + known recovery keys)
- Re-test boot after each major change before trusting prod
# Conceptual only — follow current Lanzaboote README for 26.05-compatible paths
{
imports = [ lanzaboote.nixosModules.lanzaboote ];
boot.loader.systemd-boot.enable = lib.mkForce false; # lanzaboote replaces aspects
boot.lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot"; # path patterns per docs
};
}Flake input sketch:
# inputs.lanzaboote.url = "github:nix-community/lanzaboote/…";
# inputs.lanzaboote.inputs.nixpkgs.follows = "nixpkgs";Firmware Setup Mode, key enrollment, and Microsoft/3rd-party key politics vary by vendor. Laptop OEM SB is not the same as a server you control end-to-end.
Theory 3 — TPM2 + LUKS
Goals:
- Unlock root (or data) volume without typing a passphrase every boot
- Still retain a recovery passphrase or recovery key file offline
- Survive policy: which PCRs bind the sealed key
# Sketch — systemd-cryptenroll / auto-unlock patterns evolve
{
boot.initrd.systemd.enable = true; # often required for modern enroll flows
# boot.initrd.luks.devices."crypted".crypttabExtraOpts = [ "tpm2-device=auto" ];
# Exact options: verify on your nixpkgs 26.05 pin and systemd version
}Manual enrollment often looks like:
# list TPM
systemd-cryptenroll --tpm2-device=list
ls /sys/class/tpm
# enroll (EXAMPLE — adjust device + PCR set per threat model)
# systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/nvme0n1p2PCR trade-offs
| Choice | Security | Fragility |
|---|---|---|
| Fewer PCRs | Weaker binding | Survives more firmware changes |
| PCR 7 (Secure Boot state) common | Ties to SB | Firmware/SB policy changes may require re-enroll |
| Many PCRs | Stronger | Breaks after BIOS updates more often |
Document which PCRs and the re-enroll procedure after BIOS updates. Never TPM-only without recovery credentials.
Theory 4 — VM lab limits
| Environment | Secure Boot | TPM |
|---|---|---|
| Bare metal modern laptop | Often yes | Often yes |
| Cloud VM | Sometimes virtual SB/TPM | Vendor-specific |
| libvirt QEMU | Emulated possible | swtpm possible |
| Nested cheap VPS | Often no | Often no |
QEMU/swtpm note (advanced lab)
You can practice pieces with OVMF Secure Boot and swtpm—but it is a project of its own. Stage VI accepts a document-only track if hardware refuses you. Do not fake “SB enabled” in notes without evidence.
Theory 5 — Recovery & break-glass
| Asset | Storage |
|---|---|
| Disk recovery key / passphrase | Password manager / sealed paper / offline encrypted store |
| SB setup mode knowledge | Runbook steps |
| Unsigned rescue ISO / installer USB | Physical media |
| Age/sops keys | Separate from disk encryption keys |
| Old generation unsigned | Know when SB will reject boot |
Failure Friday scenario:
BIOS update → PCR mismatch → TPM unlock fails
→ boot installer USB
→ unlock with recovery key
→ re-enroll TPM
→ document time-to-recover
Never enroll TPM-only without a recovery passphrase backup you have tested.
Theory 6 — Relation to Disko, deploy, and images
| Concern | Link |
|---|---|
| LUKS layout | Day 57 Disko declares partitions; TPM enroll often post-install |
| Impermanence | Day 58: encrypted root + persist datasets |
| Images | Day 62 generators may not equal metal SB story |
| Deploy | Remote deploy does not replace firmware SB enrollment |
| Capstone B | Fleet policy: which classes require SB |
Write one paragraph: which host classes require SB vs best-effort.
Worked example — dossier template
# SECUREBOOT-TPM.md
## Hardware
- Machine:
- Firmware vendor/version:
- Firmware SB state: SetupMode / User / Disabled / Unknown
- TPM: 2.0 visible? (commands + output summary)
- Lab type: metal / libvirt / cloud
## Goals
- [ ] Secure Boot with Lanzaboote
- [ ] LUKS passphrase only
- [ ] LUKS + TPM2
- [ ] Document-only (limits)
## Upstream sources
- Lanzaboote README URL + commit/date consulted:
- NixOS wiki / manual notes:
## Steps performed
1. …
2. …
## Recovery
- Recovery key location (not the key itself):
- USB installer location:
- Re-enroll after BIOS update:
- Estimated RTO if TPM fails:
## Residual risks
- …
## Fleet policy
- Host classes requiring SB:
- Best-effort only:Lab — multi-step
Suggested notes: ~/lab/90daysofx/02-nixos/day68
Step 1 — Probe hardware
mkdir -p ~/lab/90daysofx/02-nixos/day68
bootctl status 2>/dev/null | tee ~/lab/90daysofx/02-nixos/day68/bootctl.txt || true
efi-readvar 2>/dev/null | tee ~/lab/90daysofx/02-nixos/day68/efi-vars.txt || true
ls -la /sys/class/tpm 2>&1 | tee ~/lab/90daysofx/02-nixos/day68/tpm-sysfs.txt
systemd-cryptenroll --tpm2-device=list 2>&1 | tee ~/lab/90daysofx/02-nixos/day68/tpm-list.txt || trueStep 2 — Choose track
| Track | Criteria |
|---|---|
| A | Metal + SB available → Lanzaboote guided enable on disposable |
| B | TPM + LUKS available → enroll with recovery key tested |
| C | VM only → emulate with swtpm or document-only dossier |
Write the track choice first; do not improvise on your daily driver.
Step 3 — Read upstream (required even for Track C)
Open current Lanzaboote README + Secure Boot notes relevant to your generation. Save URLs in the dossier. Take notes—do not invent key enrollment sequences from memory.
Step 4 — Recovery assets first
Before any enrollment:
- Confirm installer USB or rescue media boots
- Confirm LUKS recovery key unlocks (lab disk)
- Write locations in dossier
Step 5 — Implement or simulate
If A/B: snapshot/backup first; proceed carefully; capture commands and outcomes.
If C: write why cloud images still matter (signed provenance vs local SB) and what you would do on metal.
Step 6 — Failure plan drill (written)
Write the exact steps to boot installer and decrypt disk if TPM fails after firmware update. Include who holds recovery keys.
Step 7 — Link Disko / LUKS
Map where LUKS is declared and whether TPM enroll is post-install only. Note declarative limits honestly.
Step 8 — Fleet policy paragraph
Which host classes require SB? Which are best-effort? Capstone A vs B expectations.
Step 9 — Tabletop: evil maid + firmware update
Write answers in the dossier (no need to re-brick hardware):
- Attacker replaces bootloader on stolen laptop with SB off historically—what changes with Lanzaboote enrolled?
- After OEM BIOS update, TPM unlock fails at initrd—ordered recovery steps?
- How do age/sops keys relate to disk recovery keys (separate custody)?
- Can deploy-rs fix a machine that will not boot? (Usually no—firmware/recovery path first.)
Step 10 — Capstone A vs B honesty line
One sentence each:
- Capstone A: SB/TPM not required—document limits OK.
- Capstone B: which pieces become mandatory for your stretch goals?
Worked example — recovery USB checklist
## Recovery USB
- [ ] Boots on target hardware (tested date: …)
- [ ] Contains or can fetch flake tools / nix installer as needed
- [ ] Operator knows LUKS recovery unlock command
- [ ] Network plan if flake must be cloned (ethernet? Wi-Fi firmware?)
- [ ] Time estimate from power-on to decrypted root shell: …If you never tested the USB on this machine, Track A/B is incomplete even if enrollment “worked once.”
Common gotchas
| Symptom / mistake | What to do |
|---|---|
| Bricked boot | Installer USB; setup mode; recover keys |
| PCR mismatch after update | Re-enroll; reconsider PCR set |
| Lost recovery key | Undecryptable disk; prevention only |
| Enabled SB without signing new gens | Use Lanzaboote properly |
| Assumed cloud disk encryption = LUKS | Understand vendor encryption separately |
| Experiment on only laptop | Use disposable or accept data-loss risk consciously |
| Docs lag code | Date-stamp upstream guide you followed |
Checkpoint
- Hardware probed with saved outputs
- Track A/B/C completed with artifacts
SECUREBOOT-TPM.mdfilled
- Recovery path written and assets exist
- No production host left without recovery keys
- Upstream sources recorded
- Tabletop answers written
- Recovery USB checklist honest
- Three personal gotchas
Commit
git add .
git commit -m "day68: secure boot / TPM path dossier"Write three personal gotchas before continuing.
Tomorrow
Day 69 — Backup story: Borg/Restic/ZFS—pick one; restore drill of state.