How to Set Up TPM2-Backed LUKS Unlocking with systemd-cryptenroll
Typing a LUKS passphrase at every boot is the correct default, but it gets old fast on a machine that never leaves your desk. A TPM2 chip can hold that unlock key instead and release it automatically, on the condition that the machine boots into a state it recognises. If someone swaps your bootloader, boots a different kernel, or moves the disk into another machine, the TPM refuses to release the key and you fall back to the passphrase. That fallback behaviour is the entire point: it's not a way to skip authentication, it's a way to make authentication conditional on the boot environment being unchanged.
This is a companion to a different problem than the one covered in the earlier post on LUKS2 with a detached header on a USB key, which is about hiding the fact that a device is encrypted at all. Here the disk is openly a LUKS volume; we're just outsourcing the "did anything about this boot look wrong" check to hardware that's much harder to lie to than a script.
What you need
You need a real TPM2 chip (fTPM/PTT firmware implementations count) and a distribution with a recent enough systemd. systemd-cryptenroll's TPM2 support landed in systemd 248, and the PIN option (--tpm2-with-pin) needs 250 or later.
systemd-cryptenroll --version
ls /dev/tpmrm0
If /dev/tpmrm0 exists, the kernel has a TPM resource manager talking to the chip. Check the volume itself is LUKS2, not LUKS1, since token-based enrolment is a LUKS2 metadata feature:
sudo cryptsetup luksDump /dev/sdaX | head -n5
If it says version 1, you'll need to convert or recreate the volume before any of this works.
Enrolling the TPM
The basic command adds a new keyslot sealed to the TPM, in addition to your existing passphrase slot (it does not remove the passphrase, and you should not remove it):
sudo systemd-cryptenroll /dev/sdaX --tpm2-device=auto --tpm2-pcrs=7
You'll be prompted for an existing passphrase to authorise the change, then the tool creates a new key, seals it to the TPM against the given PCR values, and stores a LUKS2 token describing how to unseal it. cryptsetup luksDump afterwards will show a new systemd-tpm2 token and keyslot.
Which PCRs, and why this is the fiddly part
Platform Configuration Registers accumulate measurements of the boot chain: firmware, option ROMs, bootloader, kernel command line, and so on, each extended (never overwritten) as boot progresses. Binding a TPM seal to a PCR means "only release this key if that register has exactly this value right now". Bind to too few and you get weak protection; bind to too many and a routine firmware or kernel update locks you out of your own disk, because the update legitimately changed a measurement you were pinning against.
PCR 7 alone (Secure Boot policy state) is the common, relatively stable choice: it changes only when Secure Boot is toggled or the key database is modified, not on every kernel or firmware patch. PCR 0 (firmware) and PCR 2 (option ROMs) are more brittle, since a UEFI firmware update changes them.
Here's the bit worth knowing about if you're using Secure Boot with a unified kernel image (a kernel, initramfs and command line combined into one signed EFI binary, which systemd-boot and sd-stub both support): systemd does its own measurement independent of the standard firmware PCRs. The stub extends PCR 11 with a hash of the UKI itself before handing control to the kernel. Binding to PCR 11 instead of, or alongside, PCR 7 means the seal tracks the exact kernel and initramfs you booted, which is stronger, but it also means every kernel update changes PCR 11 and invalidates the seal. If you go this route, re-enrolling the TPM slot needs to happen as part of your kernel upgrade process (a pacman/dnf/apt hook, or systemd-boot-update.service style automation), not as an afterthought after you're already locked out at a passphrase prompt wondering why.
For most desktop use, PCR 7 on its own is a reasonable balance. If you want the stronger UKI-measurement guarantee, budget for the re-enrolment automation up front.
Updating crypttab
Add tpm2-device=auto to the volume's entry in /etc/crypttab so the boot-time unlock generator knows to try the TPM before falling back to a prompt:
luks-root UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx none tpm2-device=auto
The fourth field can carry other options too (discard, nofail, and so on), comma-separated. Leave the key field as none; the key material comes from the TPM-sealed token in the LUKS header, not a file.
Rebuilding the initramfs
The early-boot environment needs the TPM2 tools and systemd's cryptsetup generator baked in.
On dracut-based distributions (Fedora, RHEL, openSUSE), make sure the systemd and tpm2-tss dracut modules are included, then regenerate:
sudo dracut --regenerate-all --force
On Arch with mkinitcpio, add the sd-encrypt hook (replacing the older plain encrypt hook) to /etc/mkinitcpio.conf, since it's the systemd-based hook that understands crypttab's tpm2-device option, then rebuild:
sudo mkinitcpio -P
Debian/Ubuntu with dracut or systemd-boot follow the dracut path above; if you're still on the classic cryptsetup initramfs hook without systemd in the initramfs, TPM2 unlock won't work until you switch to the systemd-based generator.
Testing it
Reboot. You should see no passphrase prompt at all if the PCR state matches what you enrolled against. To confirm the TPM path is actually what unlocked it rather than a cached key, check the boot log:
journalctl -b | grep -i tpm2
Deliberately break the binding to see the fallback work: change something covered by your chosen PCR (toggle Secure Boot off and back on if you bound to PCR 7, for instance) and reboot. You should land back at a normal passphrase prompt rather than being locked out silently, which is the behaviour you're relying on.
Adding a PIN
TPM-only unlock means physical possession of the running, correctly-booted machine is sufficient, since the TPM releases the key without human input. If you want a second factor, enrol with a PIN as well:
sudo systemd-cryptenroll /dev/sdaX --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes
This asks for a short PIN at boot in addition to the TPM check, and the PIN is rate-limited by the TPM's own dictionary-attack lockout counter rather than a software timer, which is a meaningfully stronger guarantee than an application-level retry limit.
Cleaning up and recovering
List enrolled slots and tokens at any time with cryptsetup luksDump. To remove a TPM2 enrolment (say, before selling the machine, or after deciding the PCR policy was wrong):
sudo systemd-cryptenroll /dev/sdaX --wipe-slot=tpm2
Keep at least one passphrase slot enrolled permanently. A TPM binding is a convenience layered on top of the passphrase, not a replacement for it; if the chip fails, the firmware gets reflashed, or you migrate the disk to different hardware entirely, the passphrase is the only thing that still works.