Linux Unified Key Setup for full-disk and partition encryption with multiple key slot support and standardized on-disk format.
Table of Contents#
- Overview
- LUKS1 vs LUKS2
- How LUKS Works
- Setting Up LUKS Encryption
- Key Management
- Key Files
- Header Backup and Recovery
- Automating Decryption
- Initramfs Integration
- Performance Considerations
- Recovery Procedures
- Troubleshooting
- See Also
- Sources
1. Overview#
LUKS (Linux Unified Key Setup) is the standard for disk encryption on Linux. It provides a platform-independent, standardized on-disk format for encrypted volumes, managed through the cryptsetup utility. LUKS encrypts entire block devices (partitions, LVM logical volumes, or whole disks), making the data inaccessible without the correct passphrase or key file.
Key features:
- Standardized format - portable across Linux distributions
- Multiple key slots - up to 8 (LUKS1) or 32 (LUKS2) passphrases/keys per volume
- Strong encryption - AES-256-XTS by default, with configurable ciphers
- Header metadata - self-describing format stores all parameters needed for decryption
- Integration - works with LVM, systemd, initramfs, TPM, and FIDO2
2. LUKS1 vs LUKS2#
| Feature | LUKS1 | LUKS2 |
|---|---|---|
| Key slots | 8 | 32 |
| Header format | Binary | JSON metadata + binary keyslots |
| Header size | 2 MiB (fixed) | 4-16 MiB (flexible) |
| Key derivation | PBKDF2 | Argon2id (memory-hard, GPU-resistant) |
| Integrity (dm-integrity) | No | Yes (AEAD or separate integrity) |
| Token support | No | Yes (systemd tokens, FIDO2, TPM2) |
| Online reencryption | No | Yes (via cryptsetup reencrypt) |
| Metadata redundancy | Partial | Full (primary + secondary header areas) |
| Minimum cryptsetup version | 1.0 | 2.0 |
| GRUB support | Full | Partial (Argon2id requires GRUB 2.12+) |
Recommendation: use LUKS2 for all new setups. LUKS1 is only needed for compatibility with older bootloaders (GRUB < 2.06 with PBKDF2 requirement).
Convert LUKS1 to LUKS2#
# Backup header first
sudo cryptsetup luksHeaderBackup /dev/<device> --header-backup-file luks1-header-backup.bin
# Convert (volume must be closed)
sudo cryptsetup convert /dev/<device> --type luks23. How LUKS Works#
Encryption Architecture#
- A master key is randomly generated during
luksFormat. This key encrypts all data on the volume. - The master key is encrypted by each key slot using a passphrase-derived key (via PBKDF2 or Argon2id).
- When unlocking, the user provides a passphrase. Cryptsetup tries each key slot until one successfully decrypts the master key.
- The decrypted master key is passed to the kernel's dm-crypt subsystem, which handles transparent encryption/decryption of all I/O.
Default Cipher Configuration#
| Parameter | LUKS1 Default | LUKS2 Default |
|---|---|---|
| Cipher | aes-xts-plain64 | aes-xts-plain64 |
| Key size | 256 bits (512 for XTS = 2x256) | 256 bits (512 for XTS) |
| Hash | SHA-256 | SHA-256 |
| KDF | PBKDF2 | Argon2id |
4. Setting Up LUKS Encryption#
Prerequisites#
# Install cryptsetup
# Debian/Ubuntu
sudo apt install cryptsetup
# Fedora/RHEL
sudo dnf install cryptsetup
# Arch Linux
sudo pacman -S cryptsetupCreate a LUKS2 Encrypted Volume#
# Format the partition with LUKS2 (default)
sudo cryptsetup luksFormat /dev/<device>This prompts for a passphrase and creates the LUKS header with default settings.
Create with Custom Parameters#
# LUKS2 with explicit cipher, key size, and Argon2id parameters
sudo cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--iter-time 3000 \
/dev/<device>Create LUKS1 (For Legacy Compatibility)#
sudo cryptsetup luksFormat --type luks1 /dev/<device>Open (Unlock) the Volume#
sudo cryptsetup open /dev/<device> <name>
# The decrypted device appears at /dev/mapper/<name>Create Filesystem and Mount#
sudo mkfs.ext4 /dev/mapper/<name>
sudo mkdir -p /mnt/<name>
sudo mount /dev/mapper/<name> /mnt/<name>Close (Lock) the Volume#
sudo umount /mnt/<name>
sudo cryptsetup close <name>5. Key Management#
View Volume Information#
# Show LUKS header details
sudo cryptsetup luksDump /dev/<device>
# Check if a device is LUKS
sudo cryptsetup isLuks /dev/<device> && echo "LUKS" || echo "Not LUKS"Add a Passphrase#
# Add to next available key slot
sudo cryptsetup luksAddKey /dev/<device>
# Add to a specific key slot
sudo cryptsetup luksAddKey --key-slot 3 /dev/<device>Remove a Passphrase#
# Remove by providing the passphrase to remove
sudo cryptsetup luksRemoveKey /dev/<device>
# Kill a specific key slot (does not require the passphrase being removed)
sudo cryptsetup luksKillSlot /dev/<device> <slot-number>Change a Passphrase#
sudo cryptsetup luksChangeKey /dev/<device>6. Key Files#
Key files provide an alternative to passphrases. They can contain any data (random bytes are most secure).
Generate a Key File#
# Generate 4096 bytes of random data
dd if=/dev/urandom of=/root/luks-keyfile bs=4096 count=1
chmod 600 /root/luks-keyfileAdd a Key File to a LUKS Volume#
sudo cryptsetup luksAddKey /dev/<device> /root/luks-keyfileOpen with a Key File#
sudo cryptsetup open /dev/<device> <name> --key-file /root/luks-keyfileSecurity Considerations for Key Files#
- Store key files on an encrypted volume or with restrictive permissions (
600, owned by root) - Never store key files on the same volume they unlock
- For removable media (USB key), ensure the device is physically secured
- Consider using a key file on a separate partition that is itself encrypted with a passphrase
7. Header Backup and Recovery#
The LUKS header contains all the information needed to decrypt the volume. If the header is damaged or overwritten, all data is permanently lost. Header backup is critical.
Backup the Header#
sudo cryptsetup luksHeaderBackup /dev/<device> \
--header-backup-file /path/to/header-backup.binStore the backup securely, preferably:
- On a separate physical device
- Off-site (encrypted USB drive in a safe)
- Multiple copies in different locations
Restore a Header#
sudo cryptsetup luksHeaderRestore /dev/<device> \
--header-backup-file /path/to/header-backup.binWarning: restoring a header replaces all key slots. If you added new passphrases after the backup, they will be lost.
Header Size#
| Format | Typical Header Size |
|---|---|
| LUKS1 | ~2 MiB |
| LUKS2 | ~16 MiB |
Detached Headers#
LUKS supports storing the header on a separate device, adding an extra layer of security (the encrypted device looks like random data without the header):
# Create with detached header
sudo cryptsetup luksFormat /dev/<device> --header /path/to/header-file
# Open with detached header
sudo cryptsetup open /dev/<device> <name> --header /path/to/header-file8. Automating Decryption#
Using /etc/crypttab#
The crypttab file configures automatic decryption at boot.
# <name> <device> <key-file> <options>
data UUID=<device-uuid> none luks
storage UUID=<device-uuid> /root/luks-keyfile luks
backup UUID=<device-uuid> none luks,nofail,noautoThen add the corresponding mount entry in /etc/fstab:
/dev/mapper/data /data ext4 defaults,noatime 0 2
/dev/mapper/storage /storage ext4 defaults,noatime 0 2TPM2 Automatic Decryption (systemd-cryptenroll)#
LUKS2 supports binding to a TPM2 module for automatic decryption without user intervention:
# Enroll TPM2 with specific PCR values
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/<device>Update crypttab:
data UUID=<device-uuid> - tpm2-device=autoTPM2 with Clevis/Tang#
For network-bound disk encryption (NBDE):
# Install clevis
sudo apt install clevis clevis-luks clevis-tpm2 # Debian/Ubuntu
sudo dnf install clevis clevis-luks clevis-tpm2 # Fedora
# Bind to TPM2
sudo clevis luks bind -d /dev/<device> tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,7"}'
# Bind to a Tang server (network-based)
sudo clevis luks bind -d /dev/<device> tang '{"url":"http://<tang-server>"}'FIDO2 Key (LUKS2 + systemd-cryptenroll)#
sudo systemd-cryptenroll --fido2-device=auto /dev/<device>9. Initramfs Integration#
For encrypting the root filesystem, the initramfs must include cryptsetup and related modules.
Debian/Ubuntu (initramfs-tools)#
Ensure cryptsetup is included in the initramfs:
# Verify inclusion
dpkg -l | grep cryptsetup-initramfs
# Install if missing
sudo apt install cryptsetup-initramfs
# Rebuild initramfs
sudo update-initramfs -uConfigure in /etc/crypttab:
root_crypt UUID=<device-uuid> none luks,discardArch Linux (mkinitcpio)#
Edit /etc/mkinitcpio.conf:
# Add 'encrypt' hook (or 'sd-encrypt' for systemd-based initramfs)
HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block encrypt filesystems fsck)Rebuild:
sudo mkinitcpio -PKernel Command Line (GRUB)#
Edit /etc/default/grub:
GRUB_CMDLINE_LINUX="cryptdevice=UUID=<device-uuid>:root_crypt root=/dev/mapper/root_crypt"Regenerate GRUB config:
sudo grub-mkconfig -o /boot/grub/grub.cfgsystemd-boot#
Edit the loader entry (e.g., /boot/loader/entries/arch.conf):
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options cryptdevice=UUID=<device-uuid>:root_crypt root=/dev/mapper/root_crypt rw10. Performance Considerations#
Benchmark Cipher Performance#
cryptsetup benchmarkExample output on a modern x86_64 system:
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1 2200000 iterations per second for 256-bit key
PBKDF2-sha256 3200000 iterations per second for 256-bit key
# Algorithm | Key | Encryption | Decryption
aes-cbc 128b 1200.0 MiB/s 3800.0 MiB/s
aes-cbc 256b 930.0 MiB/s 3100.0 MiB/s
aes-xts 256b 3600.0 MiB/s 3700.0 MiB/s
aes-xts 512b 3100.0 MiB/s 3200.0 MiB/sPerformance Impact#
| Scenario | Typical Overhead |
|---|---|
| AES-NI hardware acceleration present | 1-5% (negligible) |
| AES-NI absent (software AES) | 15-30% |
| SSD with discard enabled | Same as above + minor TRIM overhead |
| HDD | Often I/O-bound; encryption overhead masked by disk speed |
Optimization Tips#
- Ensure AES-NI is enabled in BIOS/UEFI (most modern CPUs support it)
- Use
aes-xts-plain64(default) for best parallelism - Add
discardto crypttab options for SSD TRIM support (minor security trade-off: reveals which blocks are unused) - Verify AES-NI is active:
grep -o aes /proc/cpuinfo | head -1
# If "aes" is shown, AES-NI is available
# Check if aesni_intel module is loaded
lsmod | grep aesni11. Recovery Procedures#
Lost Passphrase#
If all passphrases are lost and no key file or header backup exists, the data is unrecoverable by design. This is the intended security property.
Mitigation strategies:
- Always have at least two key slots with different passphrases
- Always back up the LUKS header
- Consider using a key file stored in a secure location as a backup key slot
- Use a password manager for LUKS passphrases
Corrupted Header#
If the LUKS header is partially corrupted:
# Try to open with the backup header
sudo cryptsetup open /dev/<device> <name> --header /path/to/header-backup.bin
# If that works, restore the header to the device
sudo cryptsetup luksHeaderRestore /dev/<device> --header-backup-file /path/to/header-backup.binDamaged Partition Table#
If the partition table is damaged but the LUKS data is intact:
# If you know the exact offset and size, you can open the raw device
sudo cryptsetup open /dev/<device> <name> --offset <sector-offset> --size <sector-count>Repair Filesystem Inside LUKS#
# Open the LUKS volume
sudo cryptsetup open /dev/<device> <name>
# Run filesystem check
sudo fsck /dev/mapper/<name>
# Close
sudo cryptsetup close <name>Emergency Key Slot Recovery#
If a key slot is damaged but others work:
# Open with a working key slot
sudo cryptsetup open /dev/<device> <name>
# Add a new key slot
sudo cryptsetup luksAddKey /dev/<device>
# Remove the damaged slot
sudo cryptsetup luksKillSlot /dev/<device> <damaged-slot-number>Troubleshooting#
| Issue | Cause | Solution |
|---|---|---|
No key available with this passphrase | Wrong passphrase or corrupted key slot | Try other passphrases; restore from header backup |
Device already exists | Mapper name conflict | Choose a different name or cryptsetup close the existing one |
Cannot use device, permission denied | Not running as root, or device in use | Use sudo; check lsof /dev/<device> |
| Boot hangs at passphrase prompt | Missing encrypt hook in initramfs | Rebuild initramfs with the correct hooks |
LUKS header not detected | Wrong device, or header was overwritten | Check device path; try header backup |
| Poor performance | AES-NI not enabled or wrong cipher | Run cryptsetup benchmark; check /proc/cpuinfo for AES flag |
| SSD not trimming through LUKS | Missing discard option | Add discard to crypttab options |
| GRUB cannot unlock LUKS2 | GRUB version < 2.06 or Argon2id unsupported | Use LUKS1 for /boot, or upgrade GRUB to 2.12+ |
cryptsetup: command not found | Package not installed | Install cryptsetup package for your distribution |