Guide to systemd-cryptenroll and YubiKey on Fedora: Unlock LUKS2 with FIDO2

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

Background & Why You Need It

It’s 2:00 AM. Your server reboots after an automatic kernel update and halts at a black screen: Please enter passphrase for disk.... Over a sluggish web console with a full second of latency, mistyping a random 35-character passphrase for the fourth time triggers a temporary lockout. Anyone who has ever debugged a production incident half-asleep on their laptop knows this pain all too well.

On my ThinkPad running Fedora Workstation, every reboot for a new kernel required re-entering the disk passphrase. Some take a more convenient route: storing a raw keyfile on a permanently attached USB flash drive and mounting it via /etc/crypttab. Convenient, sure, but the security risk is enormous. Anyone who grabs that USB drive gets unrestricted access to all data on the disk.

Similar to using TPM 2.0 to unlock LUKS automatically, FIDO2 paired with systemd-cryptenroll offers a much more balanced solution. Instead of keeping a static keyfile on disk, it leverages the hmac-secret extension of the hardware FIDO2 standard. The mechanism is airtight: LUKS2 creates a new keyslot bound to the secure element inside the YubiKey.

At boot, systemd-cryptsetup sends a random salt to the key. The token uses an internal hardware secret to compute an HMAC and returns the decryption key. All you need to do is insert the YubiKey, enter a short 4–6 digit PIN, and touch the metal contact. Once unplugged, nobody can extract or clone your master key.

Prerequisites & Package Installation

Before proceeding, verify that your current partition uses the LUKS2 standard. systemd-cryptenroll will not work with the legacy LUKS1 format.

List the disk partitions on your system:

lsblk -f

Assuming your encrypted partition is /dev/nvme0n1p3 (FSTYPE is crypto_LUKS), check the header version:

sudo cryptsetup luksDump /dev/nvme0n1p3 | head -n 5

If you see Version: 2, you are ready to go. If your system was upgraded from an older Fedora release and is still on Version: 1, convert it first: sudo cryptsetup convert /dev/nvme0n1p3 --type luks2.

Install the required FIDO2 libraries on Fedora:

sudo dnf install -y libfido2 fido2-tools cryptsetup

Insert your YubiKey into a USB port and verify device detection:

systemd-cryptenroll --fido2-device=list

The output will show a path like /dev/hidrawX along with the device name (for instance: Yubico YubiKey OTP+FIDO+CCID). If the list is empty, try a different USB port or restart the pcscd service.

Configuration Steps

Directly modifying a LUKS header always carries a risk of corrupting the keyslot table if power is interrupted. Back up your header to an external drive first:

sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file ~/luks2-header-backup.img

Step 1: Enroll the YubiKey into a LUKS2 Keyslot

Run systemd-cryptenroll to enroll a new decryption key into an empty keyslot. I strongly recommend enabling both layers of protection: a PIN (User Verification) and a touch prompt (User Presence):

sudo systemd-cryptenroll --fido2-device=auto \
  --fido2-with-client-pin=yes \
  --fido2-with-user-presence=yes \
  /dev/nvme0n1p3

The terminal will guide you through three authentication steps:

  1. Enter your current disk passphrase to authorize writing a new keyslot.
  2. Enter your YubiKey’s FIDO2 PIN (the PIN configured on the hardware token).
  3. When the YubiKey LED blinks, touch the metal sensor to complete enrollment.

Once completed, a new keyslot (typically slot 1) is bound to your YubiKey.

Step 2: Update /etc/crypttab

Next, configure the boot process to query the FIDO2 token first:

sudo nano /etc/crypttab

The entry for your root partition typically looks similar to this:

luks-4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID=4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx none discard

Append the fido2-device=auto option to the fourth column:

luks-4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID=4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx none discard,fido2-device=auto

It is best practice to configure a timeout as well. If you forget to insert your YubiKey, the system will wait 15 seconds before automatically falling back to the standard passphrase prompt:

luks-4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx UUID=4a1b2c3d-xxxx-xxxx-xxxx-xxxxxxxxxxxx none discard,fido2-device=auto,fido2-device-timeout=15s

Step 3: Rebuild the Initramfs with Dracut

Fedora decrypts the root partition during the early initramfs stage. Therefore, your initramfs image must include FIDO2 drivers and the systemd-cryptsetup binary. Without them, boot will freeze at a black screen.

Instruct Dracut to load the required FIDO2 modules:

echo 'add_dracutmodules+=" crypt fido2 "' | sudo tee /etc/dracut.conf.d/fido2.conf

Rebuild the initramfs for all installed kernels:

sudo dracut -f --regenerate-all

This process takes about 30–60 seconds. Ensure the command finishes without any error messages.

Testing & Troubleshooting

Verify that the keyslot properly registered the hardware token:

sudo cryptsetup luksDump /dev/nvme0n1p3

Under the Tokens: section in the output, you should see systemd-fido2 assigned to the corresponding keyslot. The text passphrase in Keyslot 0 remains intact as an emergency fallback whenever your key is not available.

Real-World Boot Scenarios

Reboot your machine to test the setup:

sudo systemctl reboot

Two scenarios will occur:

  • YubiKey plugged in: The PIN prompt appears. Once entered, the YubiKey LED blinks; touch the sensor, and Fedora loads to the desktop within 2–3 seconds.
  • YubiKey not plugged in: After the 15-second timeout expires, the familiar prompt appears: Please enter passphrase for disk.... Enter your original passphrase as usual.

Recovering from a Dracut Emergency Shell

If missing drivers or a misconfigured initramfs drops you into the dracut:/# emergency shell, resolve it calmly:

  1. Unlock the partition manually using your original passphrase:
    cryptsetup luksOpen /dev/nvme0n1p3 root_crypt
    exit

    (Replace root_crypt with the mapper name declared in the first column of your crypttab file).

  2. Once booted back into the OS, inspect the systemd logs to diagnose why FIDO2 was not recognized:
    sudo journalctl -b -u systemd-cryptsetup*
  3. If you lose your YubiKey or want to replace it, wipe the old FIDO2 slot using:
    sudo systemd-cryptenroll --wipe-slot=fido2 /dev/nvme0n1p3

This setup saves you valuable time typing passphrases every single day. More importantly, you no longer have to worry about shoulder surfers catching your lengthy disk passphrase when working in public places, significantly reinforcing your overall Fedora system security.

Share: