LUKS Full-Disk Encryption
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 —
crypttabkeyfile 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 (luksDumpto 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 —
luksHeaderRestorefrom 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-memoryat 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).
Related tools and reading¶
- On-site: Password generator.
- Related posts: Choosing a Linux filesystem, mdadm software RAID.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Linux & Sysadmin
resolv.conf and systemd-resolved
On modern distros /etc/resolv.conf points at a stub resolver managed by systemd-resolved. Editing it directly usually does nothing — here's the real model.
October 24, 2026Tuning Open File Limits on Linux
Four different limits control how many files a process can open. 'Too many open files' means you're hitting one specific one — here's how to find and raise it.
October 24, 2026ss and conntrack for Connection Debugging
ss shows you every socket and its send/receive queues; conntrack shows what the firewall is tracking. Together they explain most 'connection refused' and 'no buffer space' problems.
October 24, 2026