LUKS (Linux Unified Key Setup) is the standard format for block device encryption on Linux. Data on a LUKS volume is encrypted with a random master key, and that key is itself protected by one or more passphrases or key files stored in key slots. Without one of them, the disk is unreadable, whether it is a detached volume, a leaked snapshot or a decommissioned drive. In this tutorial you will encrypt a secondary data disk on Ubuntu 24.04 with LUKS2, create a filesystem on it, choose between manual and automatic unlocking at boot, and manage key slots and header backups.
Prerequisites
To follow this tutorial, you need:
- A server running Ubuntu 24.04 LTS, such as a CubePath VPS or a dedicated server.
- A non-root user with
sudoprivileges. - A secondary, empty disk or partition to encrypt. This guide uses
/dev/vdb; yours may be/dev/sdbor/dev/nvme1n1.
WarningFormatting a device with LUKS destroys all data on it. Double-check the device name before every destructive command, and back up anything on it first.
This guide encrypts a data disk on a running system. Encrypting the root filesystem requires choosing encryption in the installer, and a server with an encrypted root needs someone to type the passphrase on the console at every boot, which is rarely practical for a remote server.
Step 1 - Installing cryptsetup and identifying the disk
cryptsetup is the tool that creates and opens LUKS volumes. Install it:
sudo apt update
sudo apt install cryptsetup
Check the version and that the kernel supports the default cipher:
cryptsetup --version
cryptsetup 2.7.0 flags: UDEV BLKID KEYRING KERNEL_CAPI
List the block devices to find the disk to encrypt:
lsblk -l -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
NAME SIZE TYPE FSTYPE MOUNTPOINTS
vda 40G disk
vda1 39G part ext4 /
vda14 4M part
vda15 106M part vfat /boot/efi
vda16 913M part ext4 /boot
vdb 50G disk
Here vdb is the empty 50 GB disk: it has no partitions, no filesystem and no mount point. If the disk shows an old filesystem that you no longer need, clear its signatures so tools do not detect stale data:
sudo wipefs -a /dev/vdb
Step 2 - Creating the LUKS volume
Initialise the disk as a LUKS volume. On Ubuntu 24.04, cryptsetup luksFormat creates LUKS2 with aes-xts-plain64 (AES-256 in XTS mode) and the memory-hard argon2id key derivation function by default, which are good choices:
sudo cryptsetup luksFormat /dev/vdb
WARNING!
========
This will overwrite data on /dev/vdb irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/vdb:
Verify passphrase:
Type YES in capitals and choose a strong passphrase, for example five or six random words. Save it in your password manager: there is no way to recover data if you lose every passphrase and key file.
Confirm that the device is now a LUKS volume:
sudo cryptsetup luksDump /dev/vdb | head -n 12
LUKS header information
Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 3f6c1a7e-2b9d-4c55-9a1e-6d0b7e4f8c21
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)
Data segments:
0: crypt
Further down, the output shows cipher: aes-xts-plain64 and a Keyslots section with slot 0 using argon2id. Note the UUID; you will use it in Step 5.
Step 3 - Opening the volume and creating a filesystem
Opening a LUKS volume asks for the passphrase and creates a decrypted device under /dev/mapper/ with the name you choose. Everything written to that mapped device is encrypted on its way to /dev/vdb:
sudo cryptsetup open /dev/vdb securedata
Check its status:
sudo cryptsetup status securedata
/dev/mapper/securedata is active.
type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/vdb
sector size: 4096
offset: 32768 sectors
size: 104824832 sectors
mode: read/write
A 512-bit key in XTS mode means AES-256. Now create an ext4 filesystem on the mapped device, never on /dev/vdb directly:
sudo mkfs.ext4 -L securedata /dev/mapper/securedata
Create a mount point and mount it:
sudo mkdir -p /mnt/securedata
sudo mount /dev/mapper/securedata /mnt/securedata
df -h /mnt/securedata
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/securedata 49G 24K 47G 1% /mnt/securedata
The usable size is slightly smaller than the disk because of the 16 MB LUKS header and filesystem overhead.
Step 4 - Closing the volume
To lock the data again, unmount the filesystem and close the mapping. After close, the data is unreadable until someone opens it with a valid key:
sudo umount /mnt/securedata
sudo cryptsetup close securedata
lsblk -f /dev/vdb
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
vdb crypto_LUKS 2 3f6c1a7e-2b9d-4c55-9a1e-6d0b7e4f8c21
The disk shows only as crypto_LUKS; the ext4 filesystem inside is invisible until the volume is opened.
Step 5 - Configuring mounting at boot
Decide how the volume should be unlocked when the server starts. There are two sensible options:
| Option | Unlock | Protects against |
|---|---|---|
| A: passphrase, manual | You open it after each boot | Stolen disk, snapshot, server compromised while locked |
| B: key file on the root disk | Automatic at boot | The data disk alone being detached, leaked or discarded |
Option B is convenient, but anyone who can read both the root disk and the data disk can decrypt the data. Choose it when the threat is the data disk leaving your control on its own, not a full server compromise.
In both cases, the volume is described in /etc/crypttab (unlocking) and /etc/fstab (mounting). Use the UUID from Step 2 so that the configuration does not break if device names change. You can print it with sudo cryptsetup luksUUID /dev/vdb.
Option A - Manual unlock with a passphrase
Open /etc/crypttab:
sudo nano /etc/crypttab
Add the volume with the noauto option so boot does not wait for a passphrase that nobody is there to type:
securedata UUID=3f6c1a7e-2b9d-4c55-9a1e-6d0b7e4f8c21 none luks,noauto
Then add the mount to /etc/fstab:
sudo nano /etc/fstab
/dev/mapper/securedata /mnt/securedata ext4 defaults,noauto,nofail 0 2
noauto keeps it from being mounted at boot and nofail ensures a missing volume never blocks startup. Reload systemd so it reads the new entries:
sudo systemctl daemon-reload
After each reboot, unlock and mount the volume with:
sudo cryptsetup open /dev/vdb securedata
sudo mount /mnt/securedata
Option B - Automatic unlock with a key file
Create a random 4 KB key file readable only by root. The umask makes sure it is never created with looser permissions, even briefly:
sudo sh -c 'umask 077; dd if=/dev/urandom of=/root/securedata.key bs=4096 count=1'
sudo ls -l /root/securedata.key
-rw------- 1 root root 4096 Sep 25 11:02 /root/securedata.key
Add the key file to a free key slot of the volume. cryptsetup asks for your existing passphrase to authorise it:
sudo cryptsetup luksAddKey /dev/vdb /root/securedata.key
Enter any existing passphrase:
Add the volume to /etc/crypttab with the key file path in the third field:
sudo nano /etc/crypttab
securedata UUID=3f6c1a7e-2b9d-4c55-9a1e-6d0b7e4f8c21 /root/securedata.key luks
Add the mount to /etc/fstab:
sudo nano /etc/fstab
/dev/mapper/securedata /mnt/securedata ext4 defaults,nofail 0 2
Reload systemd and start the generated unlock unit and the mount to test the configuration without rebooting:
sudo systemctl daemon-reload
sudo systemctl start [email protected]
sudo mount -a
findmnt /mnt/securedata
TARGET SOURCE FSTYPE OPTIONS
/mnt/securedata /dev/mapper/securedata ext4 rw,relatime
Finally, reboot and confirm the volume is mounted automatically with findmnt /mnt/securedata.
Step 6 - Managing key slots
A LUKS2 volume has up to 32 key slots, and any one of them unlocks it. Use this to give each person or system its own key and revoke it independently. List the slots in use:
sudo cryptsetup luksDump /dev/vdb | grep -A1 -E '^\s+[0-9]+: luks2'
0: luks2
Key: 512 bits
1: luks2
Key: 512 bits
Common operations:
- Add a passphrase, for example a recovery passphrase stored offline:
sudo cryptsetup luksAddKey /dev/vdb - Change a passphrase in place:
sudo cryptsetup luksChangeKey /dev/vdb - Remove a passphrase by typing it:
sudo cryptsetup luksRemoveKey /dev/vdb - Remove a slot by number when the passphrase is lost or compromised:
sudo cryptsetup luksKillSlot /dev/vdb 1
Before removing anything, confirm that the key you are keeping works with a dry run that checks it without opening the device:
sudo cryptsetup open --test-passphrase /dev/vdb && echo "passphrase OK"
Enter passphrase for /dev/vdb:
passphrase OK
ImportantNever remove the last working key slot. If every slot is gone, the data is lost permanently.
Step 7 - Backing up the LUKS header
The header at the start of the disk holds the key slots. If it is damaged, for example by an accidental mkfs on /dev/vdb instead of the mapped device, the data cannot be decrypted even with the right passphrase. Back it up:
sudo cryptsetup luksHeaderBackup /dev/vdb --header-backup-file /root/vdb-luks-header.img
sudo ls -lh /root/vdb-luks-header.img
-r-------- 1 root root 16M Sep 25 11:10 /root/vdb-luks-header.img
Copy the file to secure storage off the server, then delete the local copy. Keep in mind that the backup contains the key slots as they are now: anyone with the backup and a passphrase that is valid today can decrypt the disk, even if you later remove that passphrase. Make a new backup after changing keys and destroy the old one.
To restore a damaged header:
sudo cryptsetup luksHeaderRestore /dev/vdb --header-backup-file /root/vdb-luks-header.img
Troubleshooting
No key available with this passphrase. The passphrase is wrong, or you are opening the wrong device. Check the keyboard layout on consoles, and confirm the device with lsblk -f, which should show crypto_LUKS.
Device securedata is still in use when closing. The filesystem is still mounted or a process has files open in it. Check with findmnt /mnt/securedata and sudo lsof +f -- /mnt/securedata, stop the process, unmount, and close again.
Boot drops to emergency mode after editing crypttab or fstab. An entry is wrong and lacks nofail. Use the VNC console in your CubePath panel to log in, fix the file, and run sudo systemctl daemon-reload. Check the unlock unit with sudo journalctl -u [email protected].
Slow disk performance. Run cryptsetup benchmark to see how fast the CPU encrypts. Modern x86 and ARM CPUs have AES instructions and reach several GB/s with aes-xts, so encryption is rarely the bottleneck.
Conclusion
Your data disk is now encrypted with LUKS2 on Ubuntu 24.04, mounted either on demand or automatically with a key file, with a header backup and a plan for adding and revoking keys. As next steps, replace the key file with network-bound unlocking using Clevis and a Tang server if you manage several servers, encrypt your backups before they leave the server, and make sure the passphrase and header backup are stored where your team can reach them in an emergency.
