LUKS Disk Encryption
Quick Reference
# Create encrypted volume
cryptsetup luksFormat /dev/sdb
# Open encrypted volume
cryptsetup open /dev/sdb crypt_data
# Close encrypted volume
cryptsetup close crypt_data
# Check status
cryptsetup status crypt_data
# Dump header info
cryptsetup luksDump /dev/sdb
# Add backup key
cryptsetup luksAddKey /dev/sdb
# Backup header
cryptsetup luksHeaderBackup /dev/sdb --header-backup-file header.img
Understanding LUKS
What is LUKS?
LUKS (Linux Unified Key Setup) provides:
-
Standardized encryption - Consistent on-disk format
-
Multiple key slots - Up to 8 different passphrases/keys
-
Header metadata - Cipher info stored on disk
-
Key derivation - PBKDF2/Argon2 protection against brute force
-
Plausible deniability - Detached headers option
LUKS Versions
| Version | Features | Use Case |
|---|---|---|
LUKS1 |
8 key slots, PBKDF2, wide compatibility |
Legacy systems, compatibility needs |
LUKS2 (default) |
32 key slots, Argon2id, integrity, tokens |
Modern systems, recommended |
Encryption Stack
┌─────────────────────────────────────────┐
│ Filesystem (ext4/xfs) │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Device Mapper (dm-crypt) │
│ /dev/mapper/crypt_data │
└─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ LUKS Container (encrypted) │
│ /dev/sdb │
│ ┌───────────────────────────────────┐ │
│ │ LUKS Header (metadata, key slots) │ │
│ ├───────────────────────────────────┤ │
│ │ Encrypted Data Area │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
Creating Encrypted Volumes
Basic Creation
# Format with LUKS2 (default)
cryptsetup luksFormat /dev/sdb
# You'll be prompted for:
# - Confirmation (YES in uppercase)
# - Passphrase (entered twice)
# Open the encrypted volume
cryptsetup open /dev/sdb crypt_data
# The decrypted device is now at /dev/mapper/crypt_data
# Create filesystem
mkfs.ext4 /dev/mapper/crypt_data
# Mount
mount /dev/mapper/crypt_data /mnt/secure
Advanced Creation Options
# LUKS2 with specific cipher and key size
cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--iter-time 5000 \
/dev/sdb
# LUKS1 (for compatibility)
cryptsetup luksFormat --type luks1 /dev/sdb
# With Argon2id (LUKS2 default, recommended)
cryptsetup luksFormat --type luks2 \
--pbkdf argon2id \
--pbkdf-memory 1048576 \
--pbkdf-parallel 4 \
--pbkdf-force-iterations 4 \
/dev/sdb
# With integrity (authenticated encryption)
cryptsetup luksFormat --type luks2 \
--integrity hmac-sha256 \
/dev/sdb
# Non-interactive (key from file)
echo -n "mypassphrase" | cryptsetup luksFormat /dev/sdb -
# Using key file
cryptsetup luksFormat /dev/sdb --key-file /root/keyfile
Opening and Closing Volumes
Open (Unlock)
# Basic open
cryptsetup open /dev/sdb crypt_data
# Same as (legacy syntax)
cryptsetup luksOpen /dev/sdb crypt_data
# Open with key file
cryptsetup open /dev/sdb crypt_data --key-file /root/keyfile
# Open read-only
cryptsetup open --readonly /dev/sdb crypt_data
# Open with specific key slot
cryptsetup open --key-slot 1 /dev/sdb crypt_data
# Allow discards (for SSD TRIM - security tradeoff)
cryptsetup open --allow-discards /dev/sdb crypt_data
# Open with detached header
cryptsetup open --header /path/to/header.img /dev/sdb crypt_data
Close (Lock)
# Unmount first
umount /mnt/secure
# Close the encrypted volume
cryptsetup close crypt_data
# Same as (legacy syntax)
cryptsetup luksClose crypt_data
# Deferred close (waits for users to finish)
cryptsetup close --deferred crypt_data
Check Status
# Check if device is LUKS
cryptsetup isLuks /dev/sdb && echo "Is LUKS"
# Detailed status
cryptsetup status crypt_data
# Output:
# /dev/mapper/crypt_data is active.
# type: LUKS2
# cipher: aes-xts-plain64
# keysize: 512 bits
# key location: keyring
# device: /dev/sdb
# sector size: 512
# offset: 32768 sectors
# size: 1953493296 sectors
# mode: read/write
# Dump LUKS header
cryptsetup luksDump /dev/sdb
Key Management
Key Slots
LUKS supports multiple key slots (8 for LUKS1, 32 for LUKS2), allowing: - Multiple passphrases for same volume - Recovery keys - Key rotation without re-encryption
Add Key
# Add new passphrase (prompted for existing + new)
cryptsetup luksAddKey /dev/sdb
# Add to specific slot
cryptsetup luksAddKey --key-slot 2 /dev/sdb
# Add key file as new key
cryptsetup luksAddKey /dev/sdb /root/newkeyfile
# Add passphrase using existing key file
cryptsetup luksAddKey --key-file /root/oldkey /dev/sdb
# Non-interactive (pipe both keys)
echo -n "existingpass" | cryptsetup luksAddKey /dev/sdb /root/newkeyfile
Remove Key
# Remove by passphrase (prompted)
cryptsetup luksRemoveKey /dev/sdb
# Remove specific slot
cryptsetup luksKillSlot /dev/sdb 2
# Remove key file
cryptsetup luksRemoveKey /dev/sdb /root/oldkeyfile
Change Key
# Change passphrase
cryptsetup luksChangeKey /dev/sdb
# Change specific slot
cryptsetup luksChangeKey --key-slot 0 /dev/sdb
View Key Slots
# Dump header (shows slot status)
cryptsetup luksDump /dev/sdb
# Output includes:
# Keyslots:
# 0: luks2
# Key: 512 bits
# Priority: normal
# Cipher: aes-xts-plain64
# 1: luks2
# ...
# 2-7: (unused)
Key Files
# Create random key file
dd if=/dev/urandom of=/root/keyfile bs=4096 count=1
# Secure permissions
chmod 400 /root/keyfile
# Use key file
cryptsetup open --key-file /root/keyfile /dev/sdb crypt_data
# Multiple key files (use specific one)
cryptsetup open --key-file /root/keyfile1 /dev/sdb crypt_data
Header Management
Header Backup (Critical!)
| Always backup LUKS headers. Header loss = data loss. |
# Backup header
cryptsetup luksHeaderBackup /dev/sdb \
--header-backup-file /root/luks-header-sdb.img
# Store backup securely:
# - Encrypted USB drive
# - Password manager
# - Secure cloud storage (encrypted)
# - Safety deposit box
# Verify backup
cryptsetup luksDump /root/luks-header-sdb.img
Header Restore
# Restore header (DESTRUCTIVE - overwrites current header)
cryptsetup luksHeaderRestore /dev/sdb \
--header-backup-file /root/luks-header-sdb.img
# Test with --header (doesn't modify disk)
cryptsetup open --header /root/luks-header-sdb.img /dev/sdb crypt_test
Detached Headers
For enhanced security, store header separately from data:
# Create with detached header
cryptsetup luksFormat --header /root/header.img /dev/sdb
# Open with detached header
cryptsetup open --header /root/header.img /dev/sdb crypt_data
# Without the header file, the disk looks like random data
Header Information
# View header info
cryptsetup luksDump /dev/sdb
# LUKS2 shows:
# - Version
# - UUID
# - Label (if set)
# - Cipher/hash/iterations
# - Key slot info
# - Segments
# - Digests
# Set label
cryptsetup config --label "MyEncryptedDisk" /dev/sdb
# View label
cryptsetup luksDump /dev/sdb | grep Label
Auto-Mount with crypttab
Basic crypttab Entry
# <target name> <source device> <key file> <options>
crypt_data /dev/sdb none luks
crypt_home UUID=12345678-1234-1234-1234-123456789abc none luks
With Key File
# Auto-unlock with key file (no password prompt)
crypt_data /dev/sdb /root/keyfile luks
crypttab Options
| Option | Description |
|---|---|
|
LUKS mode (default, auto-detected) |
|
Plain dm-crypt mode |
|
Allow TRIM/discard (SSD, security tradeoff) |
|
Don’t open at boot |
|
Don’t fail boot if device missing |
|
Open read-only |
|
Number of password attempts |
|
Seconds to wait for password |
|
Use detached header |
|
Read N bytes from key file |
|
Skip N bytes in key file |
|
Use specific key slot |
Example Configurations
# Interactive password at boot
crypt_root UUID=abc123 none luks,timeout=30
# Key file (automated)
crypt_data /dev/sdb /root/keyfile luks
# SSD with TRIM (security vs performance)
crypt_ssd /dev/nvme0n1p2 none luks,discard
# Optional device (won't block boot)
crypt_usb /dev/sdc none luks,noauto,nofail
# Detached header
crypt_secure /dev/sdd /root/keyfile luks,header=/boot/header.img
Full Disk Encryption
System Installation FDE
Most Linux installers support FDE:
-
Choose "Encrypt disk" or "LVM on LUKS"
-
Set encryption passphrase
-
Installer handles the rest
Manual FDE Setup (Arch Linux Style)
# 1. Partition disk
# /dev/sda1 - EFI (512M, unencrypted)
# /dev/sda2 - LUKS container (rest)
# 2. Create LUKS container
cryptsetup luksFormat /dev/sda2
# 3. Open LUKS
cryptsetup open /dev/sda2 cryptroot
# 4. Create LVM inside LUKS (optional)
pvcreate /dev/mapper/cryptroot
vgcreate vg /dev/mapper/cryptroot
lvcreate -L 50G -n root vg
lvcreate -L 8G -n swap vg
lvcreate -l 100%FREE -n home vg
# 5. Format
mkfs.ext4 /dev/vg/root
mkfs.ext4 /dev/vg/home
mkswap /dev/vg/swap
# 6. Mount and install system
mount /dev/vg/root /mnt
mkdir /mnt/home /mnt/boot
mount /dev/vg/home /mnt/home
mount /dev/sda1 /mnt/boot
# 7. Configure crypttab/mkinitcpio/grub for encrypted root
Encrypting Existing Data
| Always backup data before encryption operations. |
In-Place Encryption (cryptsetup-reencrypt)
# 1. Backup data
rsync -av /dev/sdb /backup/sdb.img
# 2. Unmount
umount /dev/sdb
# 3. Encrypt in place
cryptsetup reencrypt --encrypt --reduce-device-size 16M /dev/sdb
# The --reduce-device-size makes room for LUKS header
# 4. Open and mount
cryptsetup open /dev/sdb crypt_data
mount /dev/mapper/crypt_data /mnt
Safer Method: Copy to New Encrypted Volume
# 1. Create new encrypted volume
cryptsetup luksFormat /dev/sdc
cryptsetup open /dev/sdc crypt_new
mkfs.ext4 /dev/mapper/crypt_new
mount /dev/mapper/crypt_new /mnt/new
# 2. Copy data
rsync -av /mnt/old/ /mnt/new/
# 3. Verify
diff -r /mnt/old /mnt/new
# 4. Swap drives
LVM and LUKS Combinations
LVM on LUKS (Recommended)
Single password unlocks all LVs:
# 1. Create LUKS container
cryptsetup luksFormat /dev/sdb
cryptsetup open /dev/sdb crypt_data
# 2. Create LVM on decrypted device
pvcreate /dev/mapper/crypt_data
vgcreate vg_encrypted /dev/mapper/crypt_data
lvcreate -L 100G -n lv_data vg_encrypted
lvcreate -l 100%FREE -n lv_backup vg_encrypted
# 3. Format LVs
mkfs.ext4 /dev/vg_encrypted/lv_data
mkfs.ext4 /dev/vg_encrypted/lv_backup
LUKS on LVM
Separate password per LV:
# 1. Create LVM first
pvcreate /dev/sdb
vgcreate vg_plain /dev/sdb
lvcreate -L 100G -n lv_secure vg_plain
# 2. Encrypt individual LVs
cryptsetup luksFormat /dev/vg_plain/lv_secure
cryptsetup open /dev/vg_plain/lv_secure crypt_secure
# 3. Format
mkfs.ext4 /dev/mapper/crypt_secure
Performance Tuning
Check Crypto Performance
# Benchmark crypto algorithms
cryptsetup benchmark
# Output:
# PBKDF2-sha1 1234567 iterations per second
# PBKDF2-sha256 876543 iterations per second
# PBKDF2-sha512 654321 iterations per second
# aes-cbc 1234.5 MiB/s 1234.5 MiB/s
# aes-xts 2345.6 MiB/s 2345.6 MiB/s
Troubleshooting
Can’t Open Volume
# Verify LUKS device
cryptsetup isLuks /dev/sdb
# Check header
cryptsetup luksDump /dev/sdb
# Try with verbose
cryptsetup -v open /dev/sdb crypt_data
# Try specific key slot
cryptsetup open --key-slot 0 /dev/sdb crypt_data
# If header corrupted, restore from backup
cryptsetup luksHeaderRestore /dev/sdb \
--header-backup-file /backup/header.img
Forgot Passphrase
If you have: - Another working key slot: Use it to add new passphrase - Key file: Use it to add new passphrase - Header backup + passphrase: Restore header - None of the above: Data is lost (by design)
# Add new passphrase using key file
cryptsetup luksAddKey --key-file /root/backup-key /dev/sdb
Corrupted Header
# Restore from backup
cryptsetup luksHeaderRestore /dev/sdb \
--header-backup-file /backup/header.img
# If no backup, try repair (LUKS2 only)
cryptsetup repair /dev/sdb
Boot Issues with Encrypted Root
# Boot from live USB
# Open encrypted root
cryptsetup open /dev/sda2 cryptroot
# Mount
mount /dev/mapper/cryptroot /mnt
# Or if LVM: mount /dev/vg/root /mnt
# Chroot
arch-chroot /mnt # or mount --bind /dev /mnt/dev etc.
# Verify crypttab
cat /etc/crypttab
# Regenerate initramfs
mkinitcpio -P # Arch
update-initramfs -u # Debian
# Verify GRUB
cat /etc/default/grub
grub-mkconfig -o /boot/grub/grub.cfg
Security Considerations
Best Practices
-
Use LUKS2 with Argon2id (default)
-
Strong passphrases - 20+ characters recommended
-
Backup headers - Encrypted, stored separately
-
Key files - Random, on encrypted media
-
Secure deletion -
shredkey files when done -
Memory protection - Consider encrypted swap
Secure Key File Management
# Create secure key file
dd if=/dev/urandom of=/root/keyfile bs=4096 count=1
chmod 400 /root/keyfile
chattr +i /root/keyfile # Immutable
# When done with key file
shred -vfz -n 5 /root/keyfile
rm /root/keyfile
Quick Command Reference
# Creation
cryptsetup luksFormat /dev/sdb # Create LUKS container
cryptsetup open /dev/sdb crypt_name # Open/unlock
cryptsetup close crypt_name # Close/lock
# Information
cryptsetup isLuks /dev/sdb # Check if LUKS
cryptsetup luksDump /dev/sdb # Show header info
cryptsetup status crypt_name # Show open device info
cryptsetup benchmark # Crypto benchmarks
# Key management
cryptsetup luksAddKey /dev/sdb # Add passphrase
cryptsetup luksRemoveKey /dev/sdb # Remove passphrase
cryptsetup luksChangeKey /dev/sdb # Change passphrase
cryptsetup luksKillSlot /dev/sdb N # Remove slot N
# Header management
cryptsetup luksHeaderBackup /dev/sdb --header-backup-file backup.img
cryptsetup luksHeaderRestore /dev/sdb --header-backup-file backup.img
# Advanced
cryptsetup reencrypt --encrypt /dev/sdb # Encrypt in place
cryptsetup repair /dev/sdb # Repair LUKS2 header