Disk Encryption (LVM-on-LUKS)
Overview
This guide covers LVM-on-LUKS encryption for data drives on Linux workstations. This is the recommended approach for enterprise deployments requiring encryption at rest.
|
LVM-on-LUKS vs LUKS-on-LVM
LVM-on-LUKS is simpler: one passphrase/key unlocks the container, then LVM manages the space inside. |
Architecture
Physical Disk: /dev/sda (raw disk)
↓
LUKS Container: /dev/mapper/secure_vol (cryptsetup)
↓
LVM Physical Vol: /dev/mapper/secure_vol (pvcreate)
↓
LVM Volume Group: dataVG (vgcreate)
↓
LVM Logical Vol: /dev/mapper/dataVG-dataLV1 (lvcreate)
↓
Filesystem: ext4 (mkfs.ext4)
↓
Mount Point: /data/LV1
Boot Sequence
Understanding the boot sequence is critical for troubleshooting:
| Step | System Action | Config File |
|---|---|---|
1 |
systemd reads crypttab |
|
2 |
Unlock LUKS container → |
Passphrase or keyfile |
3 |
Activate LVM volume groups |
Automatic (lvm2 service) |
4 |
Mount filesystems from fstab |
|
|
crypttab unlocks LUKS BEFORE LVM exists. The crypttab entry points to the raw encrypted device, NOT the LVM device inside. |
Prerequisites
-
Empty disk or partition for encryption (e.g.,
/dev/sda) -
Root access
-
cryptsetuppackage installed
Step 1: Identify Target Disk
# List all block devices
lsblk -f
# Identify the disk to encrypt (e.g., /dev/sda)
# ENSURE it's the correct disk - this process destroys all data!
|
Double-check the device! The following commands will DESTROY all data on the target disk. |
Step 2: Create LUKS Container
# Create LUKS2 container on raw disk
sudo cryptsetup luksFormat --type luks2 /dev/sda
# You'll be prompted:
# - Type uppercase YES to confirm
# - Enter passphrase (this is the master passphrase - store securely!)
|
Passphrase escrow: Store the master passphrase in a secure location (password manager, encrypted vault). If this passphrase is lost and no keyfile exists, the data is unrecoverable. |
Step 3: Open the LUKS Container
# Open (unlock) the LUKS container
sudo cryptsetup open /dev/sda secure_vol
# Enter the passphrase when prompted
# Verify it's open
ls -la /dev/mapper/secure_vol
The unlocked container is now available at /dev/mapper/secure_vol.
Step 4: Create LVM Structure
# Create Physical Volume on the unlocked LUKS container
sudo pvcreate /dev/mapper/secure_vol
# Create Volume Group
sudo vgcreate dataVG /dev/mapper/secure_vol
# Create Logical Volume (use all available space)
sudo lvcreate -l 100%FREE -n dataLV1 dataVG
# Verify LVM structure
sudo lvs
sudo vgs
sudo pvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
dataLV1 dataVG -wi-a----- <10.91t
VG #PV #LV #SN Attr VSize VFree
dataVG 1 1 0 wz--n- <10.91t 0
PV VG Fmt Attr PSize PFree
/dev/mapper/secure_vol dataVG lvm2 a-- <10.91t 0
Step 5: Format and Mount
# Format with ext4
sudo mkfs.ext4 -L "Research Data" /dev/mapper/dataVG-dataLV1
# Create mount point
sudo mkdir -p /data/LV1
# Mount
sudo mount /dev/mapper/dataVG-dataLV1 /data/LV1
# Verify
df -h /data/LV1
Step 6: Configure crypttab
The /etc/crypttab file tells systemd how to unlock LUKS at boot.
|
crypttab format:
|
6.1 Get LUKS UUID
# Get the UUID of the LUKS container
sudo cryptsetup luksUUID /dev/sda
# Example output: a786315e-2a33-401c-bdfa-e8abd4524488
6.2 Edit crypttab
sudo vim /etc/crypttab
secure_vol UUID=a786315e-2a33-401c-bdfa-e8abd4524488 none luks
|
Common mistake: Using the LVM device in crypttab
Field-tested at CHLA (2026-02-06): This error caused boot failures until corrected. |
Step 7: Configure fstab
The /etc/fstab file mounts the filesystem AFTER LUKS is unlocked and LVM is activated.
sudo vim /etc/fstab
/dev/mapper/dataVG-dataLV1 /data/LV1 ext4 defaults 0 2
| Field | Value |
|---|---|
Device |
|
Mount point |
|
Filesystem |
|
Options |
|
Dump |
|
Pass |
|
|
Common mistake: Wrong filesystem type
Field-tested at CHLA (2026-02-06): This error caused mount failures. |
Keyfile Auto-Unlock (Unattended Boot)
For servers that must boot unattended, use a keyfile instead of passphrase prompt.
|
Security tradeoff: Keyfile on disk means anyone with physical access to the drive can decrypt. Only use this for:
|
8.1 Create Keyfile
# Generate random keyfile
sudo dd if=/dev/urandom of=/root/.crypt_pw_file bs=512 count=1
# Secure permissions (root-only)
sudo chmod 400 /root/.crypt_pw_file
sudo chown root:root /root/.crypt_pw_file
8.2 Add Keyfile to LUKS
# Add keyfile as additional unlock method
sudo cryptsetup luksAddKey /dev/sda /root/.crypt_pw_file
# Enter the existing passphrase when prompted
|
LUKS supports multiple key slots. The keyfile is slot 1, passphrase remains in slot 0. Both can unlock. |
8.3 Update crypttab
sudo vim /etc/crypttab
none to keyfile path:secure_vol UUID=a786315e-2a33-401c-bdfa-e8abd4524488 /root/.crypt_pw_file luks
Verification Commands
# LUKS status
sudo cryptsetup status secure_vol
# LUKS header info
sudo cryptsetup luksDump /dev/sda
# LVM structure
sudo pvs
sudo vgs
sudo lvs
# Mount status
mount | grep dataLV1
# Disk usage
df -h /data/LV1
/dev/mapper/secure_vol is active.
type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/sda
sector size: 512
offset: 32768 sectors
size: 23433854951 sectors
mode: read/write
Troubleshooting
Boot Fails at crypttab
Symptom: System hangs at boot, waiting for LUKS passphrase or showing errors about missing device.
Cause: crypttab references wrong device or wrong format.
Fix:
# Boot from live USB
# Open the LUKS container manually
sudo cryptsetup open /dev/sda secure_vol
# Mount root filesystem
sudo mount /dev/mapper/root /mnt # adjust for your root device
# Edit crypttab
sudo vim /mnt/etc/crypttab
# Verify UUID matches
sudo cryptsetup luksUUID /dev/sda
fstab Mount Fails
Symptom: System boots but mount fails with "wrong fs type" or "special device does not exist."
Causes:
1. Wrong filesystem type in fstab (luks instead of ext4)
2. LVM not activated before mount
Fix:
# Check what filesystem is actually on the LV
sudo blkid /dev/mapper/dataVG-dataLV1
# Fix fstab
sudo vim /etc/fstab
# Change luks to ext4
# If LVM not active, activate it
sudo vgchange -ay dataVG
# Then mount
sudo mount -a
"No key available with this passphrase"
Symptom: When using keyfile, LUKS reports no key available.
Cause: Keyfile not added to LUKS key slots.
Fix:
# Add the keyfile (requires existing passphrase)
sudo cryptsetup luksAddKey /dev/sda /root/.crypt_pw_file
Recovering After Wrong crypttab Entry
Symptom: Boot loops or fails to find LUKS device.
Fix (from live USB):
# Mount root
sudo mount /dev/sdX1 /mnt # your root partition
# Fix crypttab
sudo vim /mnt/etc/crypttab
# Regenerate initramfs (if using dracut/mkinitcpio)
sudo arch-chroot /mnt
mkinitcpio -P
exit
sudo reboot
Security Best Practices
-
Use LUKS2: Modern encryption, better header protection
-
Strong passphrase: At least 20 characters, random if possible
-
Escrow passphrase: Store securely (password manager, physical safe)
-
Keyfile permissions: 400 or 600, root:root only
-
Secure boot: Consider TPM-based unlock for additional protection
-
Backup LUKS header:
cryptsetup luksHeaderBackup /dev/sda --header-backup-file header.img
Quick Reference
# Create LUKS container
sudo cryptsetup luksFormat --type luks2 /dev/sda
# Open container
sudo cryptsetup open /dev/sda secure_vol
# Create LVM
sudo pvcreate /dev/mapper/secure_vol
sudo vgcreate dataVG /dev/mapper/secure_vol
sudo lvcreate -l 100%FREE -n dataLV1 dataVG
# Format and mount
sudo mkfs.ext4 /dev/mapper/dataVG-dataLV1
sudo mount /dev/mapper/dataVG-dataLV1 /data/LV1
# Add keyfile
sudo dd if=/dev/urandom of=/root/.crypt_pw_file bs=512 count=1
sudo chmod 400 /root/.crypt_pw_file
sudo cryptsetup luksAddKey /dev/sda /root/.crypt_pw_file
# Get UUID for crypttab
sudo cryptsetup luksUUID /dev/sda