Level 2

Encrypted filesystems with LUKS and dm-crypt

Maximilian B. 11 min read 12 views

Encrypting Linux filesystems with LUKS and dm-crypt protects data at rest when disks are stolen, decommissioned, or accessed by unauthorized parties. On Linux, the standard encryption stack is dm-crypt (the kernel-level block encryption layer) combined with LUKS (Linux Unified Key Setup -- the on-disk format that manages encryption metadata and key slots). LUKS2 is the current default format on all major distributions in 2026. This article covers the full lifecycle of encrypted filesystems: creating LUKS volumes, managing key slots, integrating encryption with LVM, backing up LUKS headers, and understanding the performance implications of disk encryption on Linux.

Commands below apply to Debian 13.3, Ubuntu 24.04.3 LTS / 25.10, Fedora 43, and RHEL 10.1 (with RHEL 9.7 notes). The cryptsetup package provides all LUKS tooling on every major distribution.

Understanding dm-crypt and the Linux Device Mapper

Encrypted filesystems with LUKS and dm-crypt visual summary diagram
Visual summary of the key concepts in this guide.

dm-crypt is a kernel subsystem that provides transparent block-level encryption. It operates through the device mapper framework, the same infrastructure used by LVM and multipath. When you open a LUKS volume, dm-crypt creates a virtual block device (e.g., /dev/mapper/mydata) that decrypts reads and encrypts writes on the fly. The underlying physical device stores only ciphertext.

Layered architecture diagram of the dm-crypt and LUKS encryption stack showing the path from application filesystem layer through device mapper virtual device, dm-crypt kernel subsystem, LUKS2 header with key slots, down to the physical block device storing ciphertext; with a LUKS2 key slot management panel and a LUKS1 vs LUKS2 comparison table

The device mapper stacking model means you can layer encryption under or over LVM logical volumes. The two common patterns are:

  • LUKS on partition, then LVM on top: encrypt the entire PV, then create VGs and LVs inside. This is the standard full-disk-encryption layout used by Fedora 43 and Ubuntu installers.
  • LVM first, then LUKS on each LV: gives flexibility to encrypt only certain volumes, but adds per-volume key management overhead.

For most production use, encrypt the whole physical volume first. It is simpler to manage and avoids accidentally leaving unencrypted LVs. Understanding how LVM and encryption interact is essential -- see our advanced LVM guide on thin provisioning and migration for more on layered storage architectures.

LUKS1 vs LUKS2: Key Differences in Linux Disk Encryption

LUKS2 replaced LUKS1 as the default format in cryptsetup 2.1 (released 2019). All current distributions (Debian 13.3, Ubuntu 24.04.3, Fedora 43, RHEL 10.1) create LUKS2 volumes by default. The key differences between LUKS1 and LUKS2:

Feature LUKS1 LUKS2
Header format Binary, fixed layout JSON metadata, extensible
Key slots 8 (fixed) 32 (extensible)
Default KDF PBKDF2 Argon2id (memory-hard)
Integrity support No Yes (dm-integrity)
Token plugins No Yes (systemd-cryptenroll, FIDO2, TPM2)
Redundant headers No Yes (built-in redundancy)
Online re-encryption No Yes

LUKS2's use of Argon2id is significant. Argon2id is a memory-hard KDF, meaning brute-force attacks require large amounts of RAM per guess, not just CPU time. This makes offline passphrase attacks substantially more expensive compared to LUKS1's PBKDF2. For any new encrypted volume in 2026, LUKS2 with Argon2id is the standard.

Creating, Opening, and Closing LUKS Encrypted Volumes

The basic LUKS encryption workflow: format the partition with LUKS, open it to create the mapper device, create a filesystem inside, mount it.

Five-step LUKS volume lifecycle flowchart covering pre-check, luksFormat, cryptsetup open, mkfs inside the mapper device, mount, and close operations; with panels showing persistent crypttab boot configuration and the critical importance of LUKS header backups

cryptsetup luksFormat destroys all data on the target device. Triple-check the device name with lsblk before proceeding.

# Step 1: Format partition with LUKS2 (default)
sudo cryptsetup luksFormat /dev/sdb1

# You'll be asked to type YES (uppercase) and enter a passphrase
# Default cipher: aes-xts-plain64, 512-bit key, Argon2id KDF

# Step 2: Open the LUKS volume (creates /dev/mapper/mydata)
sudo cryptsetup open /dev/sdb1 mydata

# Step 3: Create a filesystem on the decrypted device
sudo mkfs.ext4 -L encrypted_data /dev/mapper/mydata

# Step 4: Mount it
sudo mkdir -p /mnt/secure
sudo mount /dev/mapper/mydata /mnt/secure

# When done: unmount and close
sudo umount /mnt/secure
sudo cryptsetup close mydata

The filesystem you create inside the LUKS container can be any supported Linux filesystem. For guidance on choosing between ext4, XFS, or Btrfs for the inner filesystem, see our Linux filesystem internals comparison.

Checking LUKS Volume Status and Header Details

# View LUKS header information
sudo cryptsetup luksDump /dev/sdb1

# Check if a device is a LUKS device
sudo cryptsetup isLuks /dev/sdb1 && echo "LUKS" || echo "Not LUKS"

# Show status of an open mapping
sudo cryptsetup status mydata

Persistent LUKS Unlock at Boot with /etc/crypttab

For encrypted volumes that unlock automatically at boot, add an entry to /etc/crypttab. This file tells systemd (via systemd-cryptsetup) which devices to open and how.

# /etc/crypttab format:
# name    device                                  keyfile       options
mydata    UUID=a1b2c3d4-e5f6-7890-abcd-123456789  none          luks,discard

# With a keyfile instead of interactive passphrase:
mydata    UUID=a1b2c3d4-e5f6-7890-abcd-123456789  /root/.keys/mydata.key  luks,discard

# Then add the mount to /etc/fstab:
# /dev/mapper/mydata  /mnt/secure  ext4  defaults,noatime  0  2

The discard option passes TRIM commands through to the underlying SSD. This is important for SSD performance and longevity, but it has a minor security implication: TRIM reveals which blocks are unused, which leaks some information about data density. For most production environments, the SSD performance benefit outweighs this concern.

# Get the UUID of the LUKS partition (not the filesystem inside)
sudo blkid /dev/sdb1

# After editing crypttab and fstab, test without rebooting
sudo systemctl daemon-reload
sudo systemctl start systemd-cryptsetup@mydata.service

LUKS with LVM: Standard Full-Disk Encryption Layout on Linux

Most distribution installers use this pattern for full-disk encryption: one LUKS container on a partition, with LVM inside. All logical volumes (root, home, swap) are encrypted by a single passphrase. This is the layout Fedora 43 and Ubuntu create when you select "Encrypt" during installation.

# Typical layout created by Fedora 43 / Ubuntu installer:
# /dev/sda1  -> /boot/efi  (ESP, unencrypted, FAT32)
# /dev/sda2  -> /boot      (unencrypted, ext4)
# /dev/sda3  -> LUKS container
#   +-- VG: vg0
#       |-- LV: root  -> /
#       |-- LV: home  -> /home
#       +-- LV: swap  -> [swap]

# Manual setup equivalent:
sudo cryptsetup luksFormat /dev/sda3
sudo cryptsetup open /dev/sda3 crypt_pv

sudo pvcreate /dev/mapper/crypt_pv
sudo vgcreate vg0 /dev/mapper/crypt_pv
sudo lvcreate -L 50G -n root vg0
sudo lvcreate -L 100G -n home vg0
sudo lvcreate -L 8G -n swap vg0

sudo mkfs.ext4 /dev/vg0/root
sudo mkfs.ext4 /dev/vg0/home
sudo mkswap /dev/vg0/swap

This layout means you type one passphrase at boot and every LV inside is decrypted. The /boot partition remains unencrypted because GRUB needs to read the kernel and initramfs before LUKS is unlocked. On systems using GRUB with LUKS2 support (Fedora 43, recent Ubuntu), you can encrypt /boot too, but the passphrase must be entered twice: once for GRUB, once for the initramfs.

Managing LUKS Key Slots: Adding, Removing, and Rotating Passphrases

LUKS2 supports up to 32 key slots. Each slot can hold a different passphrase or keyfile, and any one of them can unlock the volume. This is useful for team environments: give each admin their own slot, and revoke access by removing their slot without changing everyone else's passphrase.

# Add a new passphrase in the next available slot
sudo cryptsetup luksAddKey /dev/sdb1

# Add a keyfile
sudo dd if=/dev/urandom of=/root/.keys/mydata.key bs=4096 count=1
sudo chmod 600 /root/.keys/mydata.key
sudo cryptsetup luksAddKey /dev/sdb1 /root/.keys/mydata.key

# Remove a key slot by slot number
sudo cryptsetup luksKillSlot /dev/sdb1 3

# Change the passphrase in a specific slot
sudo cryptsetup luksChangeKey /dev/sdb1 --key-slot 0

Never remove the last key slot. If you do, the volume is permanently inaccessible. Always verify how many active slots exist before removing one: sudo cryptsetup luksDump /dev/sdb1 | grep "Key Slot".

LUKS Header Backup and Disaster Recovery

The LUKS header contains everything needed to unlock the volume: key slot data, salt, cipher parameters. If the header is corrupted (bad sectors, accidental overwrite), the entire volume is lost even if the data is intact. Backing up the LUKS header is non-negotiable for production encrypted volumes.

# Backup the LUKS header
sudo cryptsetup luksHeaderBackup /dev/sdb1 \
  --header-backup-file /root/backups/sdb1-luks-header.bak

# Store this file securely OFF the encrypted volume
# Consider: USB drive in a safe, encrypted cloud storage, or a vault

# Restore a header (e.g., after corruption)
sudo cryptsetup luksHeaderRestore /dev/sdb1 \
  --header-backup-file /root/backups/sdb1-luks-header.bak

Security note: the header backup contains everything needed to decrypt the volume with any of the passphrases that were active when the backup was taken. Store it with the same care as the passphrase itself. If you add new key slots after the backup, take a new backup. Monitor the health of the disk storing your LUKS volumes using SMART monitoring with smartctl to catch hardware degradation before it corrupts the header.

LUKS2 Tokens: TPM2 and FIDO2 Hardware-Based Unlock

LUKS2 introduced a token mechanism that allows automated unlock using hardware security devices. The systemd-cryptenroll tool (available on Fedora 43, RHEL 10.1, and recent Debian/Ubuntu) manages these tokens for TPM2 chips and FIDO2 security keys.

# Enroll a TPM2 chip for automatic unlock at boot
sudo systemd-cryptenroll --tpm2-device=auto /dev/sdb1

# Enroll a FIDO2 security key (e.g., YubiKey)
sudo systemd-cryptenroll --fido2-device=auto /dev/sdb1

# List enrolled tokens
sudo cryptsetup luksDump /dev/sdb1 | grep -A5 "Tokens:"

# Remove a token
sudo systemd-cryptenroll --wipe-slot=tpm2 /dev/sdb1

TPM2 enrollment binds the LUKS key to the machine's TPM chip. The volume unlocks automatically at boot without a passphrase, but only on that specific hardware. If the TPM is cleared or the machine changes, you need the recovery passphrase. This is the standard approach for servers that must boot unattended in locked data centers.

On RHEL 10.1 and Fedora 43, the clevis framework provides an alternative TPM2 and network-based (Tang server) unlock mechanism. Both approaches achieve the same goal; systemd-cryptenroll is the newer, more integrated option.

LUKS Encryption Performance: AES-NI and Throughput Impact

Block-level disk encryption performance depends on the cipher and whether your CPU has hardware acceleration. Understanding the overhead helps you plan capacity for encrypted workloads.

  • AES-NI: All modern x86_64 CPUs (Intel since Westmere, AMD since Bulldozer) have AES-NI instructions. With AES-NI, the performance overhead of AES-XTS encryption is typically 2-5% on sequential I/O. Without AES-NI (some ARM boards, older VMs without passthrough), overhead can reach 20-30%.
  • Check for AES-NI: grep -m1 aes /proc/cpuinfo. If "aes" appears in the flags, hardware acceleration is available.
  • Benchmark: cryptsetup benchmark runs cipher speed tests on your hardware.
# Run cipher benchmark
sudo cryptsetup benchmark

# Sample output on a modern Xeon:
# PBKDF2-sha256     2145023 iterations per second for 256-bit key
#     Algorithm |       Key |      Encryption |      Decryption
#         aes-xts        256b      4716.3 MiB/s      4745.1 MiB/s
#         aes-xts        512b      3894.2 MiB/s      3901.7 MiB/s

# Check which cipher and key size an open volume is using
sudo cryptsetup status mydata

For NVMe SSDs capable of 3+ GB/s, encryption overhead becomes more visible because the CPU must keep up with the SSD's speed. On SATA SSDs (550 MB/s), the CPU is never the bottleneck. If you see encryption-related throughput limits on NVMe, consider enabling the no_read_workqueue and no_write_workqueue flags in crypttab to bypass dm-crypt's internal work queues and improve parallelism.

LUKS and dm-crypt Quick Reference Commands

Task Command
Format with LUKS2 sudo cryptsetup luksFormat /dev/sdX
Open LUKS volume sudo cryptsetup open /dev/sdX name
Close LUKS volume sudo cryptsetup close name
Dump LUKS header info sudo cryptsetup luksDump /dev/sdX
Add passphrase sudo cryptsetup luksAddKey /dev/sdX
Remove key slot sudo cryptsetup luksKillSlot /dev/sdX N
Backup LUKS header sudo cryptsetup luksHeaderBackup /dev/sdX --header-backup-file file.bak
Restore LUKS header sudo cryptsetup luksHeaderRestore /dev/sdX --header-backup-file file.bak
Enroll TPM2 sudo systemd-cryptenroll --tpm2-device=auto /dev/sdX
Enroll FIDO2 key sudo systemd-cryptenroll --fido2-device=auto /dev/sdX
Benchmark ciphers sudo cryptsetup benchmark
Check for AES-NI grep -m1 aes /proc/cpuinfo
Auto-unlock at boot (crypttab) name UUID=... none luks,discard

Summary

LUKS2 with dm-crypt is the standard approach to disk encryption on Linux. The combination of Argon2id key derivation, extensible JSON metadata, and hardware token support makes LUKS2 a significant improvement over LUKS1. For most environments, the recommended layout is a LUKS container on the disk partition with LVM inside, giving you a single passphrase and flexible volume management.

Three operational practices are non-negotiable: back up the LUKS header and store it securely off-device, verify that AES-NI is active to keep performance impact below 5%, and test your unlock procedure (including key slot management) before you need it in a disaster recovery scenario. Use systemd-cryptenroll with TPM2 or FIDO2 for unattended server boot or hardware-bound workstation unlock. And never remove the last key slot.

Share this article
X / Twitter LinkedIn Reddit