Follow-up to 2026-07-23-mains-power-shutdowns: telep-mainframe’s root filesystem is LUKS2 on LVM and was passphrase-only, so after any reboot — including the ones a mains event forces — the box sat at a passphrase prompt and never came back on its own. That prompt is unreachable over SSH (there is no dropbear-initramfs), so a box that reboots on power events needs the disk to unlock unattended. Goal here: TPM-sealed auto-unlock at boot, keeping the passphrase as a fallback. Done 2026-07-24 with clevis, and PROVEN IN PRODUCTION the same day: the box self-recovered the encrypted root through a 3-reboot storm with no passphrase (see 2026-07-24-psu-load-resets).
For Agents
Disk: root LUKS2 container on
/dev/nvme0n1p3(mappernvme1n1p3_crypt, UUIDa3a8e37d-79fa-484b-bc3f-40c56df95337) → LVM → root fs. (NVMe device nodes on this box flip across reboots — alwayslsblk -f; see the telep-mainframe drive gotcha.) TPM: TPM2 present,/dev/tpmrm0(MSFT0101). Secure Boot is OFF. Mechanism (working): clevis TPM2 binding. Keyslots after the work:0= passphrase (fallback, untouched),1= TPM2 (tpm2 '{"hash":"sha256","key":"ecc"}'). Check it:clevis luks list -d /dev/nvme0n1p3(shows the tpm2 binding on slot 1),sudo cryptsetup luksDump /dev/nvme0n1p3(both keyslots + the clevis token). Header backup taken first:~/telep/luks-header-nvme0n1p3-20260723.img(600) on the Mac. Reboot test: ✅ PASSED in production 2026-07-24 — the box auto-unlocked the root through 3 unattended reboots (a PSU-load reboot storm, 2026-07-24-psu-load-resets). Not a lab test any more. Caveat: auto-unlock only helps once the box boots — BIOSRestore on AC Power Lossis still stay-off, so a mains cut still needs a button press.
Why not systemd-cryptenroll
The obvious modern approach — systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs= <dev> — enrolls
a TPM keyslot fine, but Debian 13’s stock initramfs does not consume it. Debian uses
initramfs-tools with the classic cryptsetup hook, not systemd in the initramfs; it has no idea what
a systemd-tpm2 LUKS token is. update-initramfs -u prints
cryptsetup: WARNING: nvme1n1p3_crypt: ignoring unknown option 'tpm2-device'
and the box still prompts for the passphrase at boot. That approach was abandoned and the
systemd-tpm2 keyslot wiped (systemd-cryptenroll --wipe-slot=tpm2 <dev>, which needs no passphrase).
Debian stock initramfs (initramfs-tools) does NOT support systemd-cryptenroll TPM2 tokens
systemd-cryptenroll --tpm2-device=…enrolls a valid TPM keyslot, but on Debian’sinitramfs-toolsinitramfsupdate-initramfswarnsignoring unknown option 'tpm2-device'and the box still prompts at boot — the systemd-tpm2 token is never read. For TPM-based LUKS auto-unlock on Debian, use clevis (clevis-initramfs+clevis-tpm2), notsystemd-cryptenroll+ a crypttabtpm2-device=option. (The systemd path is the right one on a systemd-in-initramfs distro like Arch/Fedora; it is the wrong tool on Debian’s classic hook.)
What works: clevis
Installed clevis clevis-luks clevis-initramfs clevis-tpm2, then bound the TPM:
sudo clevis luks bind -d /dev/nvme0n1p3 tpm2 '{}'
sudo update-initramfs -u- Empty config
'{}'= no PCR binding — deliberate. Nopcr_idsmeans the unseal is not gated on measured-boot state, so a firmware or kernel update won’t silently break auto-unlock. With Secure Boot off the measured-boot chain isn’t trustworthy for gating anyway, so PCR binding would add fragility without meaningful assurance. (See the security tradeoff below.) - Result: a clevis token lands on the LUKS header and keyslot 1 becomes the TPM slot
(
1: tpm2 '{"hash":"sha256","key":"ecc"}'); keyslot 0 (the passphrase) is left intact as the fallback. update-initramfs -uinstalls the clevis unlock hooks (scripts/local-top/clevis) into the initramfs, soclevis-luks-unlockauto-unseals the volume key from the TPM at boot — no prompt.
The TPM unseal path itself was independently proven earlier on this hardware via a scratch
loopback LUKS test: enroll a TPM binding with empty PCRs, then systemd-cryptsetup attach unlocked
the loop device with no passphrase. So the hardware mechanism (TPM seal → unseal) is known-good on
this box; only the reboot-of-the-real-root test remains.
Hard-won gotchas
An orphaned
systemd-crypt*process survives holding the LUKS header lock AND /dev/tpmrm0A
systemd-cryptsetup attach/systemd-cryptenrollthat gets stuck at a passphrase prompt (e.g. because the caller’s SSH session was killed) does not die — it survives as an orphan that holds the LUKS header lock and/dev/tpmrm0, and it keeps re-broadcasting asystemd-ask-passwordrequest. That silently blocks any laterclevis luks bind(header locked) and confuses the controlling tty. Fix: SIGKILL the orphanedsystemd-crypt*PIDs (SIGTERM may not clear one mid-TPM-op), then confirmfuser /dev/nvme0n1p3andlsof /dev/tpmrm0are clear andcryptsetup luksDumpstill shows the passphrase slot, before retrying the bind.
- Adding any new keyslot needs the existing passphrase — it cannot be done for the user. Both
clevis luks bindandsystemd-cryptenrollauthorize the new slot against an existing keyslot, so the current passphrase must be typed by someone who knows it; an agent cannot supply it. And the operation is genuinely slow (argon2 KDF keyslot-add + TPM seal = tens of seconds) — an impatient Ctrl-C leaves a half-run process (see the orphan gotcha above). Let it finish. - Back up the LUKS header before touching keyslots. Done first here:
cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file …→~/telep/luks-header-nvme0n1p3-20260723.img(600, on the Mac). A corrupt header = an unrecoverable disk; the backup is cheap insurance. - Reversible. Remove the clevis binding with
sudo clevis luks unbind -d /dev/nvme0n1p3 -s 1; a systemd TPM slot (if one were ever used) wipes withsudo systemd-cryptenroll --wipe-slot=tpm2 <dev>(no passphrase needed for the wipe). The passphrase slot 0 is never touched by any of this.
Validated in production (2026-07-24 reboot storm)
The clevis TPM2 auto-unlock was proven in a real reboot storm on 2026-07-24: the PSU browned out
under load and hard-reset telep-mainframe ~3× in 30 minutes (see 2026-07-24-psu-load-resets).
The box self-recovered the encrypted root through all 3 unattended reboots —
systemd-cryptsetup@nvme1n1p3_crypt started on boot, root mounted, no passphrase. Every service
came back on its own: the knowledgebase, kb-qdrant
(2026-07-24-kb-vectorize-complete), the home + knowledgebase tailscale nodes
(2026-07-24-global-dashboard), the Frigate container, camwall, wifi-usage, and the intruder-alarm.
Reboot-test status therefore changes from “pending” to “PASSED in production”.
Incomplete / complementary (honest state)
- Auto-unlock only helps once the box actually BOOTS. telep-mainframe’s BIOS
Restore on AC Power Lossis still set to stay off, so after a mains cut the box stays powered off until someone presses the button — the clevis unlock never even runs. Full unattended power recovery still needs the BIOS flip toPower On(physical access) and ideally a UPS (the real fix). See 2026-07-23-mains-power-shutdowns. - Security posture — the accepted tradeoff. With empty PCRs + Secure Boot off, the disk auto-unlocks on this hardware. That protects against bare-drive theft (pull the NVMe → the TPM-sealed key isn’t on it, so it won’t unlock in another machine) but not whole-box theft (a thief who powers the whole machine on gets an unlocked disk). This was the deliberate tradeoff for unattended reboot; the passphrase slot remains as the human fallback.
Security hygiene note
During the keyslot work a passphrase-echo hygiene issue occurred (the LUKS passphrase was at risk of being echoed/logged); rotation of the passphrase was suggested as a precaution. No secret values are recorded in this vault — see the rotate-these list in SESSION-HANDOVER.
Related
- 2026-07-23-mains-power-shutdowns — the reason this exists; the box reboots on mains events, and
auto-unlock only matters once BIOS AC-loss is flipped to
Power On - 2026-07-24-psu-load-resets — the reboot storm that validated auto-unlock in production
- telep-mainframe — the host; root LUKS2-on-LVM disk, TPM2, Secure Boot off, unstable NVMe naming
- SESSION-HANDOVER
- homelab
- LOG
- TOPICS