Encrypting a disk with LUKS

general / published / guide #72 / ≈ 13 min read

A laptop or external drive that is not encrypted gives up everything the moment it is lost or stolen: the thief does not need your password, they just pull the disk out and read it on another machine. Disk encryption fixes that. While the disk is locked, its contents are indistinguishable from random noise — without the passphrase, there is nothing to read. On GNU/Linux the standard way to do this is LUKS (Linux Unified Key Setup), the on-disk format, driven by a command-line tool called cryptsetup (free software, GPLv2+ — already installed on many systems, and a one-line apt/pacman/dnf away otherwise).

LUKS encrypts a whole disk or partition as a block device, underneath the filesystem — so anything you put on it (ext4, Btrfs, your files, swap) is encrypted automatically, with no per-file fuss. There are two moments you might reach for it. The first is at install time: most distribution installers offer an "encrypt the whole system" checkbox, which sets up LUKS on your root disk for you — if that is what you want, tick the box and you are done. This guide covers the other case: encrypting a data disk or partition now, on a running system — a second internal drive, a USB stick, or an external backup disk — by hand, so you understand exactly what each piece does.

Everything here uses only cryptsetup and tools already on your system. Read the big warning first — it is the one that prevents a disaster.

Warning: this erases the target disk

Setting up LUKS on a device with luksFormat destroys everything already on it. There is no "encrypt in place, keep my files" in the basic flow (an advanced in-place option exists — see the last section — but it is risky and not where a beginner should start). So treat the target as a blank disk.

Warning: luksFormat wipes the device you point it at. Do your first run on a spare USB stick or an empty partition you do not care about — not your only copy of anything. Back up first if there is data on it.

Warning: the single most common way to lose data here is naming the wrong device. Before any command, confirm the device by its size with lsblk, and double-check it is the disk you mean — not your system disk.

List your disks and find the target by its size:

# show every disk and partition with its size and mount point
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS

Throughout this guide, /dev/sdX1 is a stand-in for your partition (or /dev/sdX for a whole disk). Substitute the real name you just confirmed — for example /dev/sdb1 for a partition on the second disk. If the device is currently mounted, unmount it first:

# unmount it if it is mounted (replace with your device)
sudo umount /dev/sdX1

Install cryptsetup

The whole guide needs just one package. Install it for your distribution:

# Debian / Mint / Ubuntu
sudo apt install cryptsetup

# Arch / Manjaro
sudo pacman -S cryptsetup

# Fedora
sudo dnf install cryptsetup

Confirm it is there and see its version:

cryptsetup --version

Create the encrypted container

Now turn the device into a LUKS container with luksFormat. This writes the LUKS header (the small metadata area that holds the encryption settings and your locked keys) at the start of the device and sets your first passphrase. Modern cryptsetup defaults to the newer LUKS2 format; we ask for it explicitly so there is no doubt:

# Pick a STRONG passphrase when prompted — it is the only thing protecting
# the disk, and there is no recovery if you forget it.
sudo cryptsetup luksFormat --type luks2 /dev/sdX1

It will warn you in capital letters that this overwrites data, and make you type YES (in full, uppercase) to continue — a deliberate speed bump. Then it asks for your passphrase twice.

Warning: there is no "forgot password" link for LUKS. If you lose the passphrase (and have no other keyslot — see below), the data is gone for good. Choose a passphrase you can remember or store it in a password manager, and add a backup key once the container exists.

Tip: the defaults (AES-XTS with a 512-bit key, Argon2 for the passphrase hashing) are sensible and you do not need to change them. If you are curious how fast the algorithms run on your hardware, cryptsetup benchmark prints a table — useful on slow or old machines, but purely informational.

Open it, put a filesystem on it, and use it

A freshly formatted LUKS container is locked. To use it you open (unlock) it, which creates a decrypted mapper device — a virtual block device under /dev/mapper/. You read and write that; cryptsetup transparently encrypts on the way down and decrypts on the way up.

# unlock /dev/sdX1 and expose it as /dev/mapper/secretdata
# (you choose the name "secretdata" — it is just a label)
sudo cryptsetup open /dev/sdX1 secretdata

It asks for the passphrase, then the unlocked device appears at /dev/mapper/secretdata. A brand-new container has no filesystem yet, so create one on the mapper device (never on /dev/sdX1 directly — that would write over the encrypted container):

# make an ext4 filesystem inside the encrypted container
sudo mkfs.ext4 /dev/mapper/secretdata

Now mount it like any other disk and use it normally:

# mount the unlocked device somewhere
sudo mkdir -p /mnt/secret
sudo mount /dev/mapper/secretdata /mnt/secret
# ... copy files in and out of /mnt/secret as usual ...

When you are finished, reverse the steps: unmount, then close the container to lock it again. Once closed, /dev/sdX1 is just encrypted noise to anyone without the passphrase.

# unmount, then lock the container back up
sudo umount /mnt/secret
sudo cryptsetup close secretdata

Warning: always umount before cryptsetup close. Closing a container that is still mounted (or still has files open) can corrupt the filesystem. If close complains the device is busy, something is still using it — unmount everything and try again.

Unlock it automatically at boot

Opening and mounting by hand is fine for a USB stick you plug in occasionally. For a permanent internal data disk you usually want it to come up automatically. Two system files work together: /etc/crypttab says which encrypted device maps to which name, and /etc/fstab says where to mount the resulting mapper device — exactly the crypttab-then-fstab handoff the installer sets up for an encrypted system.

First get the encrypted partition's UUID. Referring to a disk by UUID instead of /dev/sdX1 is important: device names like sdb can change between boots if you add or remove disks, but the UUID is stable. Read it from the underlying encrypted partition (not the mapper device):

# find the UUID of the LUKS partition (look for TYPE="crypto_LUKS")
sudo blkid /dev/sdX1

Add a line to /etc/crypttab mapping that UUID to your chosen name. The fields are: mapper name, the source device, the key (none means "prompt me for a passphrase"), and options (luks is enough):

# /etc/crypttab
# <name>        <source device>                              <key>  <options>
secretdata     UUID=11111111-2222-3333-4444-555555555555    none   luks

Then add the mapper device to /etc/fstab so it gets mounted — note this points at /dev/mapper/secretdata, the unlocked name, not the raw partition:

# /etc/fstab
# <device>                    <mount point>  <type>  <options>        <dump> <pass>
/dev/mapper/secretdata        /mnt/secret    ext4    defaults,nofail  0      2

Tip: the nofail option above is worth keeping — it lets the system finish booting even if the disk is missing (handy for a removable drive). Without it, a disconnected disk can drop you into an emergency shell.

With none as the key, the machine pauses during boot and asks for the passphrase. Test the wiring without a reboot like this:

# apply the new crypttab entry now (opens it, prompting for the passphrase)
sudo systemctl daemon-reload
sudo cryptdisks_start secretdata 2>/dev/null || sudo systemctl start systemd-cryptsetup@secretdata
# then mount everything from fstab
sudo mount -a

Unattended unlock with a keyfile

Typing a passphrase at boot is the safe default, but for a secondary data disk on a machine that already unlocked its root some other way, you may want it to unlock with no prompt. The way to do that is a keyfile: a small file of random bytes that acts as a second key. Create one, lock it down so only root can read it, and register it as an extra key on the container (the next section explains luksAddKey):

# make a 4 KiB random keyfile and restrict it to root only
sudo dd if=/dev/urandom of=/etc/secretdata.key bs=4096 count=1
sudo chmod 600 /etc/secretdata.key
sudo chown root:root /etc/secretdata.key

# register the keyfile as an additional way to unlock the container
sudo cryptsetup luksAddKey /dev/sdX1 /etc/secretdata.key

Then point /etc/crypttab at the keyfile instead of none, and the disk unlocks silently at boot:

# /etc/crypttab — unlock with a keyfile instead of a prompt
secretdata     UUID=11111111-2222-3333-4444-555555555555    /etc/secretdata.key   luks

Warning: a keyfile is as good as a password — anyone who can read it can open the disk. Only use one on the same disk you are protecting from theft when the keyfile lives on a different, already-encrypted disk (e.g. an encrypted root). A keyfile stored in the clear next to the data it unlocks gives you no protection against a stolen drive.

Keyslots: more than one way to unlock

One of LUKS's best features is that a container can hold up to 8 keys (keyslots), any one of which unlocks it. That means you can have a memorised passphrase and a printed backup passphrase and a keyfile, all valid at once — and you can add or revoke them without re-encrypting the disk, because the keys only protect a single master key in the header, not the data directly.

Add another passphrase (it prompts for an existing one to authorise, then the new one):

# add a second passphrase as a backup
sudo cryptsetup luksAddKey /dev/sdX1

Remove a passphrase you no longer want (you supply the passphrase to revoke):

# remove a passphrase from the container
sudo cryptsetup luksRemoveKey /dev/sdX1

To change an existing passphrase in place, the command is cryptsetup luksChangeKey /dev/sdX1 — that and the surrounding good practice are covered in detail in the companion guide, Changing the LUKS passphrase; this guide is about the initial setup, so head there once the disk is up and running.

Tip: as soon as the container exists, add a second key — a backup passphrase or a keyfile stored safely off the machine. If your everyday passphrase is ever lost or a keyslot is damaged, the spare key is the difference between a shrug and a total loss.

Critical: back up the LUKS header

The LUKS header at the start of the device holds the encryption parameters and all your locked keys. The actual data is decryptable only with information in that header. So if the header is overwritten or corrupted — a stray dd, a bad partition-table edit, a filesystem tool that writes over the start of the disk — every byte on the disk becomes unrecoverable noise, forever, even though you still know the passphrase. No undelete or file-carving tool can bring it back (this is the one case the Recovering deleted files and directories guide cannot help with). A header backup is the cheap insurance against that.

Warning: a destroyed LUKS header means permanent, irreversible data loss — there is no recovery without it. Make a header backup the moment the container is set up, and keep it somewhere other than the disk it protects.

Save a copy of the header to a file:

# write the LUKS header out to a backup file (store it OFF this disk)
sudo cryptsetup luksHeaderBackup /dev/sdX1 --header-backup-file ~/secretdata-luks-header.img

Move that .img file somewhere safe and separate — another encrypted drive, an encrypted backup, a USB stick in a drawer. Then, if the on-disk header is ever damaged, restore it:

# restore the header from your backup (only if the on-disk one is damaged)
sudo cryptsetup luksHeaderRestore /dev/sdX1 --header-backup-file ~/secretdata-luks-header.img

Warning: the header backup file is sensitive. It contains your keyslots, so anyone who has both the header backup and a passphrase (or keyfile) can open the disk. Keep it as protected as the disk itself — ideally on encrypted storage. Also note that if you change a passphrase after taking the backup, an old header backup still unlocks with the old passphrase — re-take the backup after key changes.

Inspect a container

To see what a LUKS device looks like — its version, cipher, and which keyslots are in use — dump its header. This reads only the metadata and is completely safe; it never touches your data or asks for a passphrase:

# show the LUKS version, cipher, and which keyslots are populated
sudo cryptsetup luksDump /dev/sdX1

If a container is currently open, cryptsetup status secretdata shows the live mapping — the cipher in use, the backing device, and the mode.

Encrypting an existing filesystem in place (advanced)

Everything above assumed a blank target. Modern cryptsetup can also encrypt a partition that already holds data, without erasing it, by carefully shrinking the filesystem to make room for the LUKS header and then encrypting the whole device. This is genuinely useful — but it rewrites every block on the disk, so it is slow and a power cut or crash midway can leave the partition in a half-converted state.

Warning: in-place reencryption is the one operation here that can lose data even when you do everything right (e.g. if power is lost mid-conversion). Make a full backup first, run it from a live USB with the partition unmounted, and ideally on a machine on mains power or a UPS. If you are not comfortable with that, copy the data off, do a normal luksFormat on the empty disk, and copy it back — that path is simpler and safer.

# encrypt an existing, UNMOUNTED filesystem in place, shrinking it to fit
# the new LUKS header. Back up first; do not interrupt it.
sudo cryptsetup reencrypt --encrypt --reduce-device-size 32M /dev/sdX1

When it finishes, the partition is a normal LUKS container holding your original (now encrypted) data — open it, then add a /etc/crypttab and /etc/fstab entry exactly as above.

Quick reference

  • lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS — confirm the target device by size first.
  • sudo cryptsetup luksFormat --type luks2 /dev/sdX1 — create the encrypted container (erases the device).
  • sudo cryptsetup open /dev/sdX1 secretdata — unlock to /dev/mapper/secretdata.
  • sudo mkfs.ext4 /dev/mapper/secretdata then sudo mount /dev/mapper/secretdata /mnt/secret — make a filesystem and use it.
  • sudo umount /mnt/secret && sudo cryptsetup close secretdata — unmount, then lock it back up.
  • /etc/crypttab (device by UUID → name) + /etc/fstab (the /dev/mapper device) — unlock and mount at boot; get the UUID with sudo blkid /dev/sdX1.
  • sudo cryptsetup luksAddKey / luksRemoveKey / luksChangeKey — manage keyslots (up to 8); see the Changing the LUKS passphrase guide.
  • sudo cryptsetup luksHeaderBackup /dev/sdX1 --header-backup-file header.imgback up the header and store it off the disk (luksHeaderRestore to recover).
  • sudo cryptsetup luksDump /dev/sdX1 — inspect the header and keyslots.

← back to index