TPM2 auto-unlock does not add a second lock to your LUKS disk. It replaces the passphrase you type at boot with a check the TPM runs on its own, and what that check looks at is your choice, not a default you can rely on. Bind it to the right measurements and a stolen disk stays unreadable while your own machine boots unattended. Skip that choice and you’ve only moved the key from your head into the chip.
This guide follows one Fedora install from the passphrase prompt the installer leaves you with to a TPM2 key bound to PCR 7, then adds a PIN and a recovery key, and finally changes the firmware’s Secure Boot data to prove the binding refuses to unlock when it should. You’ll use systemd-cryptenroll, /etc/crypttab and dracut, nothing third party. Every step ran in October 2026 on a Fedora 45 Server VM with an encrypted root, Secure Boot on and a virtual TPM 2.0, and the boot screens below are real captures from it.
The installer leaves a passphrase-only disk
When you tick “Encrypt my data” in Anaconda (the Fedora install guide shows the screen), or use autopart --encrypted in a kickstart, Fedora Server gives you LUKS2 under LVM and exactly one way in: the passphrase. Workstation and most spins put Btrfs on LUKS instead, so your lsblk and crypttab will look different there, but the enrollment works the same way. Every boot stops here until someone types it:

Check what the installer actually set up before you change anything. You need the device name for every command that follows, and lsblk shows it as the crypto_LUKS partition:
lsblk -o NAME,TYPE,FSTYPE,SIZE,MOUNTPOINTS
On our VM the encrypted partition is /dev/sda3, opened as a device named after its UUID, with the root logical volume inside it. Every command below takes it from a variable, so set it once to your own partition and re-set it if you open a new shell:
NAME TYPE FSTYPE SIZE MOUNTPOINTS
sda disk 30G
├─sda1 part vfat 600M /boot/efi
├─sda2 part xfs 2G /boot
└─sda3 part crypto_LUKS 27.4G
└─luks-db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd crypt LVM2_member 27.4G
└─fedora_probe-root lvm xfs 15G /
Set the variable now:
DISK=/dev/sda3
The installer also wrote one line to /etc/crypttab for that volume, and this is the file you’ll change later:
sudo cat /etc/crypttab
Four fields: the mapped name, the LUKS UUID, the key file and the options:
luks-db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd UUID=db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd none discard,x-initrd.attach
The none in the third column of crypttab means no key file, so systemd asks for a password. /boot and /boot/efi are not encrypted, which is normal on Fedora: the kernel and initramfs have to be readable before anything is unlocked. Then confirm the TPM is there:
systemd-cryptenroll --tpm2-device=list
One TPM 2.0 device, exposed through the resource manager node:
PATH DEVICE DRIVER
/dev/tpmrm0 MSFT0101:00 tpm_tis
If the list comes back empty, the TPM is off in the firmware setup or the machine has none, and nothing below will work until that changes. On a Proxmox VM, add one under VM, Hardware, Add, TPM State, with version v2.0; on libvirt, add a TPM device of model CRB or TIS.
PCRs decide what the TPM trusts
The TPM only hands back the disk key if a set of Platform Configuration Registers (PCRs) hold the same values they held at enrollment. Each PCR is a running hash of something measured during boot. The ones that matter for this choice, from the systemd-cryptenroll man page:
- PCR 0: firmware code, changes on every firmware update
- PCR 4: the boot loader and the binaries it loads, which with shim and GRUB can include the kernel, so it can change on kernel updates too
- PCR 7: Secure Boot state and the PK, KEK, db and dbx certificates
- PCR 11: the kernel image and initrd, when booted as a unified kernel image
- PCR 14: the MOK certificates and hashes that shim keeps
PCR 7 is the usual choice on Fedora because it only moves when Secure Boot itself changes, not on every kernel or GRUB update. It still moves when the firmware’s certificate lists change, and with fwupd now shipping those updates, that happens about as often as firmware updates, which you’ll see at the end of this guide. That is why upstream systemd stopped defaulting to PCR 7 and points to systemd-pcrlock as the longer-term alternative, as its release notes explain; this guide sticks to PCR 7 because it is what most Fedora systems can use today. One thing the man page is explicit about: if you leave out --tpm2-pcrs, the enrollment binds to no PCRs at all, and the TPM unlocks the disk for any boot of that machine. Always pass the PCR list.
Enrollment adds a key slot
Enrolling the TPM does not touch your passphrase. LUKS2 keeps several key slots, and systemd-cryptenroll adds a new one whose key is sealed by the TPM. It asks for the current passphrase first, because it needs an existing slot to unlock the volume key:
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 "${DISK}"
After the passphrase it reports the new slot:
New TPM2 token enrolled as key slot 1.
List the slots to see both ways in:
sudo systemd-cryptenroll "${DISK}"
Slot 0 is still your passphrase, and slot 1 is the TPM:
SLOT TYPE
0 password
1 tpm2
Keep slot 0. It is your way back in when the TPM refuses, and removing it before you have a recovery key leaves a disk that only one chip can open.
The initramfs has to know
Your disk is unlocked inside the initramfs, before your root filesystem exists, so the token in the LUKS header is useless until the initramfs knows to try it. Two changes do that: a crypttab option that states the intent to use the TPM, and a rebuilt initramfs that carries the TPM token plugin. The initramfs the installer built had none, as you’ll see below. Back up crypttab, then add tpm2-device=auto to the options of the root volume:
sudo cp /etc/crypttab /etc/crypttab.bak
sudo sed -i 's/discard,x-initrd.attach/discard,x-initrd.attach,tpm2-device=auto/' /etc/crypttab
sudo cat /etc/crypttab
That sed matches the options our installer wrote; if your line differs, edit it with sudo vim /etc/crypttab instead. The line should end with the new option:
luks-db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd UUID=db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd none discard,x-initrd.attach,tpm2-device=auto
Reboot into your newest kernel first if you updated since the last boot, because dracut -f only rebuilds the initramfs for the running kernel. Then rebuild it and check that the TPM pieces made it in:
sudo dracut -f
sudo lsinitrd | grep -E 'libtss2-tcti-device|systemd-cryptsetup$|crypttab' | awk '{print $NF}'
You want the crypttab copy, systemd-cryptsetup and the TPM device library:
systemd-cryptsetup
etc/crypttab
usr/bin/systemd-cryptsetup
usr/lib64/libtss2-tcti-device.so.0.0.0
libtss2-tcti-device.so.0.0.0
../../bin/systemd-cryptsetup
dracut -f took 19 seconds here. Future kernel updates rebuild their initramfs with the same crypttab, so you only run it by hand this once; kernels installed before this change keep their old initramfs. On our VM the older kernel’s image and the rescue image contained no TPM token files at all (lsinitrd counted zero matches for token-systemd-tpm2 or libtss2-tcti-device), so if you boot an older kernel or the rescue entry, expect the passphrase prompt. If the TPM library is missing from the list, the initramfs cannot use the token. Check that the crypttab line really ends in tpm2-device=auto and that rpm -q tpm2-tools succeeds, because dracut’s TPM module needs the tpm2 binary, then rebuild with sudo dracut -f --add tpm2-tss to ask for the module explicitly. If the TPM refuses for any reason, the normal passphrase prompt appears, as you’ll see later, so this step cannot lock you out.
Boot unlocks without a prompt
Reboot. No prompt should appear: the initramfs asks the TPM, the TPM compares PCR 7, and the root volume opens. When you’re back in, the boot log shows the cryptsetup unit running without any password:
sudo journalctl -b -o short-monotonic --no-pager | grep -E 'systemd-cryptsetup@|cryptsetup' | head -5
systemd-analyze | head -1
With nobody at the console, the unit started at 2.3 seconds and finished at 26.7:
[ 1.523366] probe systemd[1]: Created slice system-systemd\x2dcryptsetup.slice - Slice /system/systemd-cryptsetup.
[ 2.341700] probe systemd[1]: Starting systemd-cryptsetup@luks\x2ddb0ce8e8\x2d2b03\x2d4cba\x2dbda9\x2d74e8b0d5a9dd.service - Cryptography Setup for luks-db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd...
[ 25.266811] probe systemd-cryptsetup[414]: Set cipher aes, mode xts-plain64, key size 512 bits for device /dev/disk/by-uuid/db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd.
[ 26.676011] probe systemd[1]: Finished systemd-cryptsetup@luks\x2ddb0ce8e8\x2d2b03\x2d4cba\x2dbda9\x2d74e8b0d5a9dd.service - Cryptography Setup for luks-db0ce8e8-2b03-4cba-bda9-74e8b0d5a9dd.
[ 26.679599] probe systemd[1]: Reached target cryptsetup.target - Local Encrypted Volumes.
Startup finished in 1.198s (kernel) + 26.721s (initrd) + 4.013s (userspace) = 31.933s
Those 24 seconds are long, and they are not the TPM token’s own cost. Testing the token by hand with sudo cryptsetup open --test-passphrase --token-only "${DISK}" unlocked key slot 1 in 0.34 seconds. We didn’t trace where the boot spent the rest on this nested VM’s software TPM, so measure your own hardware before you plan around it.
Now be clear about what you have. The disk is safe if it leaves the machine, because no other TPM can unseal its key. It is not protected from someone who can boot this machine with Secure Boot intact, because the TPM sees a boot it recognises and unlocks. PCR 7 also says nothing about the kernel command line or the initramfs on /boot, so anyone at the console can change what that unlocked boot runs. If that matters for your threat model, and on a laptop it usually does, the next section closes it. The rest of a laptop’s exposure, from SSH to firewall zones, is covered in our Fedora hardening guide.
A PIN makes it two factors
Only do this on a machine you can reach at the console, through a screen, IPMI or a VM console, because every boot will now wait for the PIN. With --tpm2-with-pin=yes, the TPM still checks PCR 7, but it also wants a PIN, so unlocking needs this machine in its expected state and something you know. Replace the existing TPM slot instead of adding a second one, because an old slot without a PIN would still unlock on its own. --wipe-slot=tpm2 removes it once the new one is in place, and the command asks for the current passphrase and the new PIN:
sudo systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes "${DISK}"
The PIN is stretched with Argon2id before it reaches the TPM, a format new in this systemd release, so systemd benchmarks the machine first. Older systemd on rescue or live media cannot use that token, which is one more reason to keep the passphrase and add a recovery key:
Argon2id benchmark: 2 iterations, 1177 MiB, 2 lanes, ~2114ms.
New TPM2 token enrolled as key slot 2.
Wiped slot 1.
On the next boot the prompt changes from a disk passphrase to a token PIN:

A PIN is short to type, but don’t treat wrong guesses as free. Each wrong PIN counts against the TPM’s dictionary attack protection, which is a property of the whole chip, and enough failures lock it for a long time. Use a PIN you won’t mistype, and keep the passphrase and recovery key for the days you do.
A recovery key for when the TPM says no
Will the TPM ever refuse your own machine? Yes, and sooner than you think. Any of these changes what it measures or holds:
- a Secure Boot certificate or dbx update
- turning Secure Boot off, even briefly
- clearing or resetting the TPM in firmware setup
- a replaced motherboard, which takes the TPM with it
- a shim update that changes the SBAT level, which shim measures into PCR 7
- a BIOS update that resets the Secure Boot keys or clears a firmware TPM
The passphrase in slot 0 still works then, but a generated recovery key is stronger than most passphrases and easy to type from paper. Add one:
sudo systemd-cryptenroll --recovery-key "${DISK}"
It prints the key once. We replaced ours with a placeholder here:
A secret recovery key has been generated for this volume:
🔐 <RECOVERY-KEY-REDACTED>
Please save this secret recovery key at a secure location. It may be used to
regain access to the volume if the other configured access credentials have
been lost or forgotten. The recovery key may be entered in place of a password
whenever authentication is requested.
New recovery key enrolled as key slot 1.
Write it down or put it in a password manager that does not live on this disk. The slot list now shows three ways in:
SLOT TYPE
0 password
1 recovery
2 tpm2
That’s the layout we’d keep on any machine: the passphrase you know, the recovery key on paper, and the TPM with a PIN for daily boots. Once the recovery key is stored safely you can remove slot 0 with --wipe-slot=password, but there’s little to gain, and we kept it.
Prove the binding refuses
A binding you never saw refuse is a binding you are trusting blind. The cleanest real change to PCR 7 is a Secure Boot update, and fwupd had one waiting: a new dbx revocation list. This is the same kind of update many Fedora machines get, so it doubles as a preview of what that day looks like. Before you run it, take a snapshot if this is a VM, make sure you have console access, and fetch the BitLocker recovery key first if the machine also boots Windows, because the change is permanent and Windows sees it too. List what fwupd offers:
sudo dnf install -y fwupd
sudo fwupdmgr refresh --force
sudo fwupdmgr get-updates --no-unreported-check | grep -E "Device ID|Current version|New version"
Ours had a dbx update waiting:
│ Device ID: 362301da643102b9f38477387e2193e57abaa590
│ Current version: 20250902
│ New version: 20260707
New version: 20260402
Install it with the device ID from your own list. If yours shows nothing pending, the man page lists turning Secure Boot off as another PCR 7 change, which we did not test here; turn it back on afterwards, and expect BitLocker to react to that change too. With an update on offer, install it:
sudo fwupdmgr update 362301da643102b9f38477387e2193e57abaa590 -y --no-reboot-check --no-unreported-check
It installed cleanly:
Successfully installed firmware
Devices with no available firmware updates:
• KEK CA
• SBAT
• UEFI Secure Boot (PK/KEK key)
On the next boot the PIN prompt appeared as usual, and we typed the correct PIN. The TPM refused anyway, because PCR 7 no longer matched, and the boot moved on to the fallback prompt:

Typed at that prompt, the recovery key opened the disk. Once logged in, the cryptsetup log names the reason in plain words:
sudo journalctl -b -t systemd-cryptsetup --no-pager -o cat
Its first line is the TPM rejecting the new PCR 7 value:
TPM policy does not match current system state. Either system has been tampered with or policy out-of-date: Operation not permitted
That is the behaviour you want: a change to Secure Boot data the TPM can’t tell apart from tampering, so it stops and asks a human. After a legitimate update, re-seal the TPM slot against the new value with the same command as before. Do it from the first boot after the change, as here; re-sealing in the same session you applied the update would seal the old value and fail again on the next boot:
sudo systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes "${DISK}"
sudo systemd-cryptenroll "${DISK}"
Your TPM slot moves to a new number, and the passphrase and recovery key stay where they were:
Argon2id benchmark: 2 iterations, 1163 MiB, 2 lanes, ~2047ms.
New TPM2 token enrolled as key slot 3.
Wiped slot 2.
SLOT TYPE
0 password
1 recovery
3 tpm2
Did it work? The next boot took the PIN and unlocked normally. Plan for this on every machine you enroll: Secure Boot updates and firmware certificate changes, like the ones in our Secure Boot on Fedora guide, will each cost you one recovery-key boot and one re-enrollment. If the machine also boots Windows, BitLocker sees the same PCR change, which the Fedora and Windows dual boot guide covers from the Windows side.