Linux Disk Encryption with LUKS: Protecting Data When Your Server Is Lost or Stolen

Security tutorial - IT technology blog
Security tutorial - IT technology blog

When Network Security Isn’t Enough — The Physical Access Problem

I once had my SSH brute-forced and spent half the night scrambling to fix it. After that incident, I set up a firewall, fail2ban, changed the SSH port — the whole works. But there was one scenario I kept overlooking: what happens if someone physically walks off with the server’s hard drive?

For a VPS, this risk might seem far-fetched. But for bare-metal servers at the office, in a colocation facility, or even a home server — it’s a very real threat. No need to crack the root password or bypass the firewall. Just pull the drive, plug it into another machine, mount it, and everything is readable. If you’re not sure whether your server has already been compromised before you set this up, it’s worth reading this practical guide on detecting and responding to a hacked server first.

That’s exactly what LUKS (Linux Unified Key Setup) was designed for. Data on the partition is encrypted with AES-256 at the block device layer — meaning even the OS sees nothing until the volume is unlocked. Without the passphrase or keyfile, the drive is just a blob of random bytes — no matter what machine you plug it into.

Installing cryptsetup

cryptsetup is the package that manages LUKS. Ubuntu typically comes with it pre-installed; for other distros, one command is all you need:

# Ubuntu / Debian
sudo apt update && sudo apt install cryptsetup -y

# CentOS / RHEL / Rocky Linux
sudo dnf install cryptsetup -y

# Check version
cryptsetup --version
# cryptsetup 2.6.1

The dm-crypt kernel module needs to be loaded. Quick check:

lsmod | grep dm_crypt
# If the output is empty, load it manually:
sudo modprobe dm-crypt

Setting Up LUKS Step by Step

Step 1 — Prepare the Partition or Disk

Suppose you have a secondary drive /dev/sdb or partition /dev/sdb1 that needs to be encrypted. Use lsblk to identify the correct device first — cryptsetup luksFormat will wipe all existing data with no undo.

lsblk
# NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
# sda      8:0    0   50G  0 disk
# └─sda1   8:1    0   50G  0 part /
# sdb      8:16   0   20G  0 disk   ← this is the drive to encrypt

Step 2 — Format the Partition with LUKS

sudo cryptsetup luksFormat /dev/sdb

This command asks for confirmation with YES (uppercase) and prompts you to set a passphrase. This passphrase cannot be recovered if forgotten — use a strong one (20+ characters) and store it in a password manager immediately.

If you want to explicitly specify the encryption algorithm:

# AES-256 with XTS mode — the default on cryptsetup >= 2.x
sudo cryptsetup luksFormat --type luks2 \
  --cipher aes-xts-plain64 \
  --key-size 512 \
  --hash sha256 \
  /dev/sdb

Step 3 — Open the Encrypted Volume

Once formatted, the partition is encrypted but not yet usable. You need to “unlock” it first — luksOpen decrypts and maps the partition to a virtual block device at /dev/mapper/<name>:

# "data_encrypted" is a custom name — it will appear at /dev/mapper/data_encrypted
sudo cryptsetup luksOpen /dev/sdb data_encrypted
# Enter passphrase...

# Verify
ls -la /dev/mapper/data_encrypted
# lrwxrwxrwx 1 root root 7 ... /dev/mapper/data_encrypted -> ../dm-0

Step 4 — Format the Filesystem and Mount

From here, /dev/mapper/data_encrypted looks and behaves just like a regular partition — format it, mount it, and use it normally:

# Format as ext4
sudo mkfs.ext4 /dev/mapper/data_encrypted

# Create mount point
sudo mkdir -p /mnt/secure_data

# Mount
sudo mount /dev/mapper/data_encrypted /mnt/secure_data

# Verify
df -h /mnt/secure_data
# /dev/mapper/data_encrypted   20G  45M   19G   1% /mnt/secure_data

Step 5 — Configure Auto-Mount on Boot

This is the step most people skip. To have the LUKS volume auto-mount after a reboot, you need to configure two files: /etc/crypttab and /etc/fstab. If you’re running Ubuntu Server and haven’t already locked down the basics, this checklist of things to do after installing Ubuntu Server 22.04 covers several complementary hardening steps worth doing in the same session.

First, get the UUID of the raw partition (not the device mapper):

sudo blkid /dev/sdb
# /dev/sdb: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="crypto_LUKS"

Add to /etc/crypttab:

sudo nano /etc/crypttab
# <mapper_name>     <device>                                    <keyfile>  <options>
data_encrypted   UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890   none       luks

With none in the keyfile column, the system will prompt for the passphrase at boot (via the console). If you prefer a keyfile for unattended unlocking:

# Generate a random 4096-byte keyfile
sudo dd if=/dev/urandom of=/root/luks_keyfile bs=4096 count=1
sudo chmod 400 /root/luks_keyfile

# Add the keyfile to LUKS (the original passphrase remains as a backup)
sudo cryptsetup luksAddKey /dev/sdb /root/luks_keyfile

# Update crypttab
# data_encrypted   UUID=...   /root/luks_keyfile   luks

Then add to /etc/fstab:

sudo nano /etc/fstab
/dev/mapper/data_encrypted   /mnt/secure_data   ext4   defaults   0   2

Checking and Monitoring

Viewing LUKS Status

# Detailed information about the volume
sudo cryptsetup luksDump /dev/sdb
# LUKS header information
# Version:        2
# Epoch:          3
# Metadata area:  16384 [bytes]
# Keyslots area:  16744448 [bytes]
# UUID:           a1b2c3d4-...
# Label:          (no label)
# Subsystem:      (no subsystem)
# Flags:          (no flags)
# ...
# Keyslots:
#  0: luks2   ← passphrase
#  1: luks2   ← keyfile (if added)

# Device mapper status
sudo cryptsetup status data_encrypted
# /dev/mapper/data_encrypted is active.
#   type:    LUKS2
#   cipher:  aes-xts-plain64
#   keysize: 512 bits
#   key location: keyring
#   device:  /dev/sdb
#   ...

Backing Up the LUKS Header — A Required Step

The LUKS header sits at the beginning of the partition — it stores the encryption metadata, key slots, and salt. A bad sector in that region, or an accidental dd to the wrong device, and it’s gone. Your data is permanently lost even if the passphrase is correct. Back it up immediately after setup, don’t put it off:

sudo cryptsetup luksHeaderBackup /dev/sdb \
  --header-backup-file /root/luks_header_backup_sdb.img

# Store this file off the server (USB, S3, encrypted cloud storage...)
# Verify the backup is valid
sudo cryptsetup luksDump /root/luks_header_backup_sdb.img

Closing the Volume When Not in Use

# Unmount first
sudo umount /mnt/secure_data

# Close LUKS
sudo cryptsetup luksClose data_encrypted

# At this point /dev/mapper/data_encrypted disappears
# The drive returns to its fully encrypted state

Managing Passphrases — Add, Remove, Change

LUKS supports up to 8 key slots — meaning you can have multiple passphrases or keyfiles active at the same time:

# Add a new passphrase (e.g., a recovery passphrase for the team)
sudo cryptsetup luksAddKey /dev/sdb

# Remove an old passphrase
sudo cryptsetup luksRemoveKey /dev/sdb

# Check which key slots are in use
sudo cryptsetup luksDump /dev/sdb | grep -E "Keyslots|[0-9]+:"

Practical Points to Keep in Mind

  • Performance overhead: AES-NI (hardware acceleration) is available on most CPUs from 2010 onward. Check with grep aes /proc/cpuinfo. If present, the encryption overhead is nearly negligible — real-world benchmarks typically show less than 3% throughput loss compared to unencrypted.
  • LUKS1 vs LUKS2: Use LUKS2 (the default since cryptsetup 2.x) — it supports Argon2 key derivation, which is significantly more resistant to brute-force attacks than LUKS1.
  • Swap partition: RAM contents paged to swap are stored in plaintext. A real-world example: an SSH private key in active use gets swapped out to /dev/sda3 — anyone with the drive can read it. Use zram or encrypt swap separately to avoid this scenario.
  • Full disk encryption vs partition encryption: This guide covers encrypting a data partition. Encrypting the entire disk (including /) is more involved and is typically done during a fresh OS install. If you’re spinning up a new Linux environment for testing LUKS configurations before applying them to production, using Vagrant for a consistent dev environment can save you from accidentally destroying a real disk.

Ever since that night scrambling to patch SSH, I stopped treating security as something to deal with later. LUKS is now one of the first things I set up whenever I deploy a server that handles important data — alongside setting up a VPN with OpenVPN to ensure data in transit is equally protected. Fifteen minutes of setup in exchange for complete peace of mind whenever I think about the scenario where the drive ends up in the wrong hands.

Share: