Linux Unified Key Setup for full-disk and partition encryption with multiple key slot support and standardized on-disk format.

Table of Contents#

  1. Overview
  2. LUKS1 vs LUKS2
  3. How LUKS Works
  4. Setting Up LUKS Encryption
  5. Key Management
  6. Key Files
  7. Header Backup and Recovery
  8. Automating Decryption
  9. Initramfs Integration
  10. Performance Considerations
  11. Recovery Procedures
  12. Troubleshooting
  13. See Also
  14. 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#

FeatureLUKS1LUKS2
Key slots832
Header formatBinaryJSON metadata + binary keyslots
Header size2 MiB (fixed)4-16 MiB (flexible)
Key derivationPBKDF2Argon2id (memory-hard, GPU-resistant)
Integrity (dm-integrity)NoYes (AEAD or separate integrity)
Token supportNoYes (systemd tokens, FIDO2, TPM2)
Online reencryptionNoYes (via cryptsetup reencrypt)
Metadata redundancyPartialFull (primary + secondary header areas)
Minimum cryptsetup version1.02.0
GRUB supportFullPartial (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 luks2

3. How LUKS Works#

Encryption Architecture#

  1. A master key is randomly generated during luksFormat. This key encrypts all data on the volume.
  2. The master key is encrypted by each key slot using a passphrase-derived key (via PBKDF2 or Argon2id).
  3. When unlocking, the user provides a passphrase. Cryptsetup tries each key slot until one successfully decrypts the master key.
  4. 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#

ParameterLUKS1 DefaultLUKS2 Default
Cipheraes-xts-plain64aes-xts-plain64
Key size256 bits (512 for XTS = 2x256)256 bits (512 for XTS)
HashSHA-256SHA-256
KDFPBKDF2Argon2id

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 cryptsetup

Create 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-keyfile

Add a Key File to a LUKS Volume#

sudo cryptsetup luksAddKey /dev/<device> /root/luks-keyfile

Open with a Key File#

sudo cryptsetup open /dev/<device> <name> --key-file /root/luks-keyfile

Security 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.bin

Store 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.bin

Warning: restoring a header replaces all key slots. If you added new passphrases after the backup, they will be lost.

Header Size#

FormatTypical 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-file

8. 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,noauto

Then 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 2

TPM2 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=auto

TPM2 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 -u

Configure in /etc/crypttab:

root_crypt    UUID=<device-uuid>    none    luks,discard

Arch 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 -P

Kernel 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.cfg

systemd-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 rw

10. Performance Considerations#

Benchmark Cipher Performance#

cryptsetup benchmark

Example 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/s

Performance Impact#

ScenarioTypical Overhead
AES-NI hardware acceleration present1-5% (negligible)
AES-NI absent (software AES)15-30%
SSD with discard enabledSame as above + minor TRIM overhead
HDDOften 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 discard to 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 aesni

11. 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.bin

Damaged 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#

IssueCauseSolution
No key available with this passphraseWrong passphrase or corrupted key slotTry other passphrases; restore from header backup
Device already existsMapper name conflictChoose a different name or cryptsetup close the existing one
Cannot use device, permission deniedNot running as root, or device in useUse sudo; check lsof /dev/<device>
Boot hangs at passphrase promptMissing encrypt hook in initramfsRebuild initramfs with the correct hooks
LUKS header not detectedWrong device, or header was overwrittenCheck device path; try header backup
Poor performanceAES-NI not enabled or wrong cipherRun cryptsetup benchmark; check /proc/cpuinfo for AES flag
SSD not trimming through LUKSMissing discard optionAdd discard to crypttab options
GRUB cannot unlock LUKS2GRUB version < 2.06 or Argon2id unsupportedUse LUKS1 for /boot, or upgrade GRUB to 2.12+
cryptsetup: command not foundPackage not installedInstall cryptsetup package for your distribution

See Also#

Sources#