Server

LUKS Full-Disk Encryption

By Prabath Thalangama· October 24, 2026· 4 min read
#linux#encryption#security

Introduction

LUKS (Linux Unified Key Setup) is the standard for block-device encryption on Linux, implemented via dm-crypt. It encrypts a whole partition/disk; the filesystem lives inside the unlocked mapping. The master key never changes — passphrases and keyfiles just unwrap it, so you can add/remove/rotate them freely.

Concepts

  • Master Volume Key (MVK) — the actual encryption key, random, generated at format time. Encrypts the data.
  • Key slots — up to 8 (LUKS1) / 32 (LUKS2). Each holds the MVK encrypted by a passphrase or keyfile. Unlocking tries your input against each slot.
  • Header — metadata + key slots, at the start of the device. If the header is destroyed, the data is unrecoverable even with the passphrase. Back it up.
  • LUKS2 (default now) — JSON header, Argon2id KDF (memory-hard, better against brute force), redundant header copies, supports online reencryption.

Set up a new encrypted volume

cryptsetup luksFormat --type luks2 /dev/sdb1        # prompts, wipes the device
cryptsetup open /dev/sdb1 cryptdata                  # asks passphrase -> /dev/mapper/cryptdata
mkfs.ext4 /dev/mapper/cryptdata
mount /dev/mapper/cryptdata /mnt/data

# on shutdown / unmount
umount /mnt/data
cryptsetup close cryptdata

Persistent mount via /etc/crypttab + /etc/fstab:

# /etc/crypttab :  name  device  key  options
cryptdata  UUID=<luks-uuid>  none  luks
# /etc/fstab
/dev/mapper/cryptdata  /mnt/data  ext4  defaults  0 2

none = prompt for passphrase at boot.

Unattended unlock

You don't want to type a passphrase on every headless server reboot.

Keyfile (simple, lower security)

dd if=/dev/urandom of=/root/.cryptdata.key bs=512 count=8
chmod 400 /root/.cryptdata.key
cryptsetup luksAddKey /dev/sdb1 /root/.cryptdata.key
# crypttab:
cryptdata  UUID=<uuid>  /root/.cryptdata.key  luks

The keyfile must live on an already-decrypted volume (the root FS) — so this protects a data disk if the disk alone is stolen, not the whole machine.

TPM binding with clevis (better for servers)

dnf install clevis clevis-luks clevis-dracut
clevis luks bind -d /dev/sdb1 tpm2 '{"pcr_ids":"7"}'
dracut -f        # rebuild initramfs to include clevis

Now the disk auto-unlocks only on this machine, in this boot state (PCR 7 = secure boot state). Move the disk elsewhere → it won't unlock, falls back to the passphrase. clevis luks bind ... tang binds to a network key server instead (unlock only when on your network).

Add, rotate, remove keys

cryptsetup luksAddKey /dev/sdb1                 # add a new passphrase (needs an existing one)
cryptsetup luksChangeKey /dev/sdb1             # change one slot's passphrase
cryptsetup luksRemoveKey /dev/sdb1            # remove by passphrase
cryptsetup luksKillSlot /dev/sdb1 2          # remove slot 2 by number (needs another slot's key)
cryptsetup luksDump /dev/sdb1                 # show slots, KDF, header layout

To truly rotate the master key (e.g. after a suspected compromise), you must luksFormat a new device and copy data, or use LUKS2 online reencryption:

cryptsetup reencrypt /dev/sdb1               # LUKS2, online, resumable

Header backup — do this

cryptsetup luksHeaderBackup /dev/sdb1 --header-backup-file /secure/offsite/sdb1-luks.img
# restore:
cryptsetup luksHeaderRestore /dev/sdb1 --header-backup-file /secure/offsite/sdb1-luks.img

Store it somewhere other than the encrypted disk. A corrupted header (bad sector, a stray dd, a partition tool) with no backup = total data loss.

Verification and troubleshooting

cryptsetup status cryptdata
cryptsetup luksDump /dev/sdb1
lsblk -f                                       # see the crypt mapping and fs inside
systemd-cryptsetup attach cryptdata /dev/sdb1  # manual attach for debugging
journalctl -b | grep -i crypt
  • Boot hangs asking for a passphrase you don't want to give — crypttab keyfile path wrong, keyfile not in the initramfs (for root disk — dracut -f / update-initramfs -u), or clevis binding failed (TPM state changed after a firmware/secure-boot update → PCR mismatch; re-bind).
  • No key available with this passphrase — wrong slot / passphrase, or you're pointing at the wrong device (luksDump to confirm it's a LUKS device and which version).
  • Device already exists / Device or resource busy — the mapping is already open, or a process holds it. cryptsetup status, lsof /dev/mapper/....
  • Header corrupted — luksHeaderRestore from your backup. No backup → the data is gone.
  • Slow unlock — Argon2id KDF memory cost; on a low-RAM box or in a minimal initramfs it can be slow or OOM. Tune with --pbkdf-memory at format time.
  • Performance overhead — AES-NI makes it near-free on modern CPUs; check cryptsetup benchmark. Old CPUs without AES-NI take a real hit.
  • Disk cloned/imaged, clone won't unlock — same header/keys, should work; if TPM-bound, the clone on another machine won't (by design).
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.