Linux Disk Encryption with LUKS: Complete Guide

Tested on: Ubuntu 26.04 LTS · Debian 12 · Fedora 44 · Arch Linux — Last updated: June 2026
LUKS (Linux Unified Key Setup) is the standard disk encryption layer on Linux, built on top of the kernel's dm-crypt subsystem. It encrypts entire block devices — partitions, full disks, loop files — so that without the correct passphrase or key file, the data is cryptographically unreadable. This guide covers everything from encrypting a USB drive in five minutes to automounting encrypted volumes at boot, managing key slots, backing up headers, and understanding the performance characteristics of AES-XTS on modern hardware.
Prerequisites
- Root or sudo access on the target system
cryptsetup2.4+ installed (see below)- For partition encryption: an unmounted block device you can dedicate to LUKS
- Any data on the target device backed up —
luksFormatis destructive and irreversible - Basic familiarity with
lsblk,blkid, and/etc/fstabsyntax
How LUKS Works
LUKS stores its metadata in a header at the very beginning of the encrypted device. That header contains: the encrypted master key (one copy per key slot), the cipher specification, the key derivation function parameters, and a UUID. When you unlock the device, LUKS derives a key-encryption-key from your passphrase using PBKDF2 or Argon2id (LUKS2), uses it to decrypt the master key from your slot, then hands that master key to dm-crypt, which performs the actual block-level AES-XTS encryption and decryption on the fly.
# The stack from physical device to filesystem:
#
# /dev/sdb1 ← raw block device (LUKS container)
# └─ LUKS header ← metadata, key slots, cipher info
# └─ dm-crypt ← kernel-level AES-XTS decryption
# └─ /dev/mapper/secure ← decrypted block device
# └─ ext4 / btrfs / xfs filesystem
# └─ /mnt/data ← your filesThe critical implication: the header is the single point of failure. Destroy or corrupt it, and all data is gone permanently, even if you know the passphrase. Back it up. This is covered in detail below.
Install cryptsetup
# Ubuntu / Debian:
sudo apt install cryptsetup -y
# Fedora / Rocky Linux / AlmaLinux:
sudo dnf install cryptsetup -y
# Arch Linux:
sudo pacman -S cryptsetup
# Verify version (2.4+ required for full LUKS2 support):
cryptsetup --version
# cryptsetup 2.7.3Encrypt a Partition or Drive
Identify your target device carefully. luksFormat on the wrong device means permanent data loss with no undo.
# List all block devices with sizes and mount points:
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE
# NAME SIZE TYPE MOUNTPOINT FSTYPE
# sda 500G disk
# ├─sda1 512M part /boot vfat
# └─sda2 499G part / ext4
# sdb 1T disk
# └─sdb1 1T part ← target: no filesystem, unmounted
# Unmount if currently mounted:
sudo umount /dev/sdb1
# Format with LUKS2 (prompts for passphrase):
sudo cryptsetup luksFormat
--type luks2
--cipher aes-xts-plain64
--key-size 512
--hash sha512
--iter-time 3000
/dev/sdb1
# WARNING!
# ========
# This will overwrite data on /dev/sdb1 irrevocably.
# Are you sure? (Type uppercase yes): YES
# Enter passphrase for /dev/sdb1:
# Verify passphrase:A note on the options: aes-xts-plain64 with --key-size 512 gives you AES-256 in XTS mode (XTS splits the key, so 512 bits → 256-bit effective AES). --iter-time 3000 sets PBKDF calibration to 3 seconds on your hardware, making brute-force attacks more expensive. For LUKS2, Argon2id is used automatically instead of PBKDF2.
# Inspect the new LUKS container:
sudo cryptsetup luksDump /dev/sdb1
# LUKS header information
# Version: 2
# Epoch: 3
# Metadata area: 16384 [bytes]
# Keyslots area: 16744448 [bytes]
# UUID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Label: (no label)
# Subsystem: (no subsystem)
# Flags: (no flags)
#
# Data segments:
# 0: crypt
# offset: 16777216 [bytes]
# length: (whole device)
# cipher: aes-xts-plain64
# sector: 512 [bytes]
#
# Keyslots:
# 0: luks2
# Key: 512 bits
# AF stripes: 4000
# AF hash: sha512
# Area offset:32768 [bytes]
# Area length:258048 [bytes]
# Digest ID: 0Open and Close Encrypted Volumes
# Open the container — creates /dev/mapper/secure:
sudo cryptsetup luksOpen /dev/sdb1 secure
# Enter passphrase for /dev/sdb1:
# 'secure' is the device-mapper name. Choose anything meaningful.
# The decrypted device is now accessible at:
ls -la /dev/mapper/secure
# lrwxrwxrwx 1 root root 7 Jun 14 10:23 /dev/mapper/secure -> ../dm-0
# First time only: create a filesystem on the opened device:
sudo mkfs.ext4 -L encrypted-data /dev/mapper/secure
# For btrfs:
# sudo mkfs.btrfs -L encrypted-data /dev/mapper/secure
# Create mount point and mount:
sudo mkdir -p /mnt/data
sudo mount /dev/mapper/secure /mnt/data
# Verify:
df -h /mnt/data
# Filesystem Size Used Avail Use% Mounted on
# /dev/mapper/secure 1007G 28K 956G 1% /mnt/data
# Check active LUKS mapping status:
sudo cryptsetup status secure
# /dev/mapper/secure is active.
# type: LUKS2
# cipher: aes-xts-plain64
# keysize: 512 bits
# key location: keyring
# device: /dev/sdb1
# sector size: 512
# offset: 32768 sectors
# size: 1953456128 sectors
# mode: read/write
# When done — unmount first, then close:
sudo umount /mnt/data
sudo cryptsetup luksClose secure
# Device is now encrypted and inaccessibleAuto-Mount at Boot with /etc/crypttab and /etc/fstab
Two files control automatic unlocking and mounting: /etc/crypttab handles the LUKS unlock step, and /etc/fstab handles the filesystem mount after unlock.
# Get the UUID of the LUKS device (use the raw device, not /dev/mapper/):
sudo blkid /dev/sdb1
# /dev/sdb1: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="crypto_LUKS"# /etc/crypttab
# Format:
# Prompt for passphrase at boot (interactive):
secure UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 none luks
# Unattended unlock with a key file (for data partitions):
secure UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 /etc/luks-keys/secure.key luks
# Options you may want to add:
# ,timeout=60 — wait 60s for passphrase before failing
# ,discard — enable TRIM for SSDs (trades some security for performance)
# ,noauto — don't unlock at boot, unlock manually # /etc/fstab — add after the crypttab entry
# The mapper name from crypttab becomes the device path here:
/dev/mapper/secure /mnt/data ext4 defaults,noatime 0 2# Rebuild initramfs so the boot system includes LUKS support:
# Ubuntu / Debian:
sudo update-initramfs -u -k all
# Fedora / RHEL:
sudo dracut --force
# Arch (using mkinitcpio):
sudo mkinitcpio -P
# Verify crypttab syntax without rebooting:
sudo systemd-cryptsetup attach secure /dev/sdb1 none luksKey Files for Automated Unlocking
Key files let a data partition unlock at boot without a passphrase prompt. Never use a key file as the only protection on your primary system disk — if the key file is on an unencrypted partition, it undermines the encryption entirely. The correct use case is a secondary data drive that unlocks automatically once the system disk is already decrypted.
# Create a secure key file (512 bytes of urandom):
sudo mkdir -p /etc/luks-keys
sudo dd if=/dev/urandom of=/etc/luks-keys/secure.key bs=512 count=1 status=progress
# Lock it down — root-readable only:
sudo chmod 400 /etc/luks-keys/secure.key
sudo chmod 700 /etc/luks-keys
# Add key file as a new slot (keeps your passphrase in slot 0):
sudo cryptsetup luksAddKey /dev/sdb1 /etc/luks-keys/secure.key
# Enter any existing passphrase: (authenticates the operation)
# Confirm both slots are active:
sudo cryptsetup luksDump /dev/sdb1 | grep -A5 "Keyslots"
# Test key file unlock manually:
sudo cryptsetup luksOpen /dev/sdb1 secure --key-file /etc/luks-keys/secure.key
sudo cryptsetup luksClose secureManaging Key Slots
LUKS1 supports 8 key slots; LUKS2 supports 32. Each slot holds an independent passphrase or key file that can decrypt the same master key. Use this for recovery passphrases, admin access, and automated key files — all simultaneously active.
# Add a recovery passphrase in slot 1:
sudo cryptsetup luksAddKey /dev/sdb1
# Enter any existing passphrase:
# Enter new passphrase for key slot:
# Verify passphrase:
# View all active slots:
sudo cryptsetup luksDump /dev/sdb1 | grep -E "^Keyslots:|[0-9]+: luks"
# Keyslots:
# 0: luks2 ← original passphrase
# 1: luks2 ← recovery passphrase
# 2: luks2 ← key file
# Remove a passphrase (enter the one you want to delete):
sudo cryptsetup luksRemoveKey /dev/sdb1
# Remove a specific slot by number (requires another valid passphrase):
sudo cryptsetup luksKillSlot /dev/sdb1 2
# Enter any remaining passphrase:
# Change an existing passphrase:
sudo cryptsetup luksChangeKey /dev/sdb1
# Enter passphrase to be changed:
# Enter new passphrase:
# This only updates the key slot — the master key is unchanged, no re-encryption neededBackup and Restore the LUKS Header
Header corruption is game over. A power loss during a write near the start of the device, an accidental dd, or a failing drive sector can wipe the LUKS header and make all data permanently unrecoverable. Back it up immediately after creating any LUKS volume.
# Back up the LUKS header to a file:
sudo cryptsetup luksHeaderBackup /dev/sdb1
--header-backup-file /root/luks-header-sdb1-$(date +%Y%m%d).img
# The backup contains everything needed to recover: cipher info,
# key slots, and all passphrases stored in those slots.
# Protect this file — it's as sensitive as the passphrase itself:
sudo chmod 400 /root/luks-header-sdb1-*.img
# Store the backup OFF the encrypted device — use:
# - Another encrypted drive
# - An encrypted offsite backup
# - Physical printed QR code for critical systems
# Do NOT store it unencrypted on a public or shared system.
# Verify backup integrity:
sudo cryptsetup luksDump --header /root/luks-header-sdb1-20260614.img /dev/sdb1
# Restore header in an emergency:
sudo cryptsetup luksHeaderRestore /dev/sdb1
--header-backup-file /root/luks-header-sdb1-20260614.img
# WARNING: This overwrites current header. Only do this if the header is damaged.Performance: AES-NI and Benchmarking
# Check if your CPU has AES hardware acceleration (AES-NI):
grep -m1 -o 'aes' /proc/cpuinfo && echo "AES-NI: YES" || echo "AES-NI: NO"
# Run the cryptsetup benchmark (tests RAM only, no disk IO):
cryptsetup benchmark
# Example output on a modern Intel/AMD CPU with AES-NI:
# Tests are approximate using memory only (no storage IO).
# PBKDF2-sha512 1623348 iterations per second for 256-bit key
# Argon2i 4 iterations, 395903 memory, 4 parallel threads for 256-bit key
# # Algorithm | Key | Encryption | Decryption
# aes-cbc 128b 3412.7 MiB/s 3891.2 MiB/s
# a
Further Reading
