Encrypted Filesystems with LUKS (cryptsetup)
- Explain what LUKS/dm-crypt protects (data at rest) and what the LUKS header stores
- Create, open, format, and mount an encrypted block device with cryptsetup
- Read a volume's cipher specification and key slots from cryptsetup luksDump
- Make an encrypted volume open automatically at boot with /etc/crypttab and /etc/fstab
- Back up the LUKS header and explain why losing it destroys the data
What LUKS encrypts, and what it doesn't
Place LUKS in the stack: dm-crypt does the encryption, LUKS manages the keys, and it all protects data AT REST.
LUKS (Linux Unified Key Setup) is the standard way to encrypt a block device on Linux. It sits on two pieces: dm-crypt, the kernel device-mapper target that transparently encrypts and decrypts every block as it's written and read, and the LUKS header, an on-disk metadata area that stores the cipher choice and the key slots. What it protects is data at rest: pull the disk, image it, or steal the laptop, and without the passphrase the bytes are noise. What it does not protect is a running, unlocked system — once the volume is open, the filesystem is plaintext to anyone with access, exactly like any other mount.
The key detail that trips people up: LUKS does not encrypt your data with your passphrase. The disk is encrypted with a random master key, generated once at format time. Your passphrase unlocks a key slot that holds an encrypted copy of that master key. That indirection is why you can have up to eight passphrases for one volume, change a passphrase without re-encrypting a terabyte of data, and why the header is everything — lose it, and the master key is gone with it (more on that at the end).
Create an encrypted volume: cryptsetup luksFormat (run on a real host or VM)
Initialise a block device as LUKS, writing the header and the first key slot.
Before you type anything: the commands in steps 1–5 need a real host or VM with the device-mapper stack, and
cryptsetupis not installed on the lab box — so don't expect them to run in your lab terminal (you'll getcryptsetup: command not found, and it isn't installable there). Read them here and run them on a real machine — step 6 has a loopback recipe that needs no spare disk — then come back to the lab box for the header-reading half. The lab box is for the read-only side of LUKS; the write side is real-hardware work.luksFormatwrites a fresh LUKS header onto the device and sets up key slot 0 from a passphrase you choose. It is destructive — it overwrites whatever was there — so it asks you to confirm by typingYESin capitals. On a modern system you get LUKS2 and a sensible default cipher without specifying one.sudo cryptsetup luksFormat /dev/sdb1WARNING: Device /dev/sdb1 already contains a 'ext4' superblock signature. WARNING! ======== This will overwrite data on /dev/sdb1 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/sdb1: Verify passphrase:
- luksFormat
- Initialise the named device as a LUKS container and write its header.
- -c / --cipher
- Override the cipher spec, e.g. -c aes-xts-plain64. Omit it to take the built-in default.
- -s / --key-size
- Key size in bits, e.g. -s 512 (XTS splits it: 512 = two 256-bit keys).
This creates the container but plants no filesystem yet — a LUKS device is a wrapper you still have to open and format. Typing YESis a deliberate speed bump because there is no undo. The passphrase you set here fills key slot 0; you can add more later withluksAddKey.Open it, format it, mount it
Unlock the container to a /dev/mapper node, put a filesystem on it, and mount it.
An encrypted device is opened to a mapper name under
/dev/mapper/. That mapper node is the plaintext view — you make a filesystem on it and mount it exactly like a normal partition, and dm-crypt encrypts every block on the way down to/dev/sdb1.sudo cryptsetup luksOpen /dev/sdb1 secureEnter passphrase for /dev/sdb1:
- luksOpen (aka open)
- Unlock the container and expose it as /dev/mapper/<name> after a correct passphrase.
After this succeeds, /dev/mapper/secureexists and is the decrypted device.ls -l /dev/mapper/secureandlsblkboth show the mapping (sdb1 → secure (crypt)). Nothing is on it yet.Example — not runnable on your lab box
sudo mkfs.ext4 /dev/mapper/secure && sudo mount /dev/mapper/secure /mnt/securemke2fs 1.46.5 (30-Dec-2021) Creating filesystem with 262144 4k blocks ... done
You format and mount the mapper node, never the raw /dev/sdb1— writing a filesystem straight onto the encrypted device would clobber the LUKS header. Files written under/mnt/secureare ciphertext on the disk and plaintext through the mount.Read the crypto: cryptsetup luksDump
Inspect a volume's header to report its cipher specification and key slots.
luksDumpprints the header without unlocking anything — no passphrase needed, because the header itself is not secret (only the key slots are, and those are encrypted). It is how you answer 'what cipher is this volume using?' on an incident report: the cipher name (e.g.aes), the cipher mode (xts-plain64), and the key size. The full specification a report wants is the joined form,aes-xts-plain64.sudo cryptsetup luksDump /dev/sdb1LUKS header information Version: 2 Epoch: 3 Cipher name: aes Cipher mode: xts-plain64 Key size: 512 [bits] Data segments: 0: crypt cipher: aes-xts-plain64 Keyslots: 0: luks2 Key: 512 bits
- luksDump
- Print the LUKS header: version, cipher, key size, and each occupied key slot.
- --dump-master-key
- (Dangerous) also print the master key — needed for header recovery, never for routine reads.
Read Cipher name+Cipher modetogether for the full spec — hereaes-xts-plain64.Key size: 512 [bits]is XTS splitting into two 256-bit AES keys, so this is AES-256. TheKeyslotssection shows which of the eight slots hold a passphrase; a volume with several slots simply has several people/keys able to open it.Make it open at boot: /etc/crypttab and /etc/fstab
Persist an encrypted mount so it survives a reboot, the way a real system runs it.
By itself an opened volume is gone after a reboot — the mapping lives in kernel memory. Two files make it persistent, and they work as a pair.
/etc/crypttabsays how to unlock the device into a mapper name;/etc/fstabthen mounts that mapper name like any other filesystem.crypttabis read beforefstabat boot precisely so the mapper node exists by the time fstab wants it.echo 'secure UUID=<sdb1-uuid> none luks' | sudo tee -a /etc/crypttabsecure UUID=1b3f... none luks
- field 1 (name)
- The mapper name to create: becomes /dev/mapper/secure.
- field 2 (device)
- The backing block device — prefer UUID= over /dev/sdb1, which can renumber.
- field 3 (key)
- A keyfile path, or none to prompt for the passphrase at boot.
- field 4 (options)
- luks marks it a LUKS device; add options like discard here.
Use the device's UUID ( blkid /dev/sdb1), not the kernel name —/dev/sdband/dev/sdccan swap between boots and you'd unlock the wrong disk.nonein field 3 means 'ask me for the passphrase at boot'; a keyfile path there unlocks it unattended.echo '/dev/mapper/secure /mnt/secure ext4 defaults 0 2' | sudo tee -a /etc/fstab/dev/mapper/secure /mnt/secure ext4 defaults 0 2
fstab mounts the mapper node, never /dev/sdb1. Validate the pair without rebooting:sudo cryptdisks_start secure(orsystemctl start systemd-cryptsetup@secure) thensudo mount -a— if both succeed cleanly, the boot will too.Close it, and guard the header
Tear down a mapping safely, and understand why the header is the whole ballgame.
Sealing a volume back up is the mirror image of opening it, and the order matters: unmount the filesystem first, then close the mapping. Skip the unmount and the close fails because the device is still in use. But the more important idea in this step is why an encrypted volume is so unforgiving of header damage — the same indirection that makes LUKS flexible also makes the header the one thing you cannot lose.
Example — not runnable on your lab box
sudo umount /mnt/secure && sudo cryptsetup luksClose secure- luksClose (aka close)
- Remove the /dev/mapper mapping — the plaintext view disappears; the data is sealed again.
Always umountbeforeluksClose— closing a mapping with a filesystem still mounted on it will fail ('Device secure is still in use'). After close,/dev/mapper/secureis gone and only ciphertext remains on/dev/sdb1.Check yourself
You run luksFormat again on a device that already holds an encrypted filesystem you care about. What happens to the existing data?
On the lab box: read the header, and know what a container can't do
Read a LUKS volume's crypto from a captured header on the lab box, and understand why the create/open lifecycle needs a real machine.
The lab box is a container, and that changes what of this lesson you can run here.
cryptsetupis not installed on the lab image (andapt-get install cryptsetupreports "no installation candidate", so you can't add it),/dev/mapperholds only itscontrolnode, and there is no spare disk to format. That is not a gap in the room — dm-crypt is a kernel device-mapper target, and creating a mapping needs the module, the device-mapper stack, and a real block device. Steps 1–5 are how you do this on a real host or VM; run them there, on a spare disk or a loopback file, where every one of them works.What the lab box is genuinely good for is the half of LUKS that analysis and exam tasks actually ask about: reading a header you were handed. You never need to unlock a volume — or even have
cryptsetup— to answer "what cipher is this?"lsblk -fNAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS nbd0 nbd1 ... vda vdb 64K 0% /.fly-upper-layer vdc
- -f
- Show filesystem info — FSTYPE, LABEL, UUID and mountpoint per device. The FSTYPE column is where crypto_LUKS appears.
This is the real output on a lab box: virtio and network-block devices, and no `crypto_LUKS` row, because nothing here is encrypted. Learn the shape anyway — on a real system a LUKS container shows crypto_LUKSin the FSTYPE column, and that is how you spot an encrypted volume during triage before you ever open it.ls -l /dev/mapper/total 0 crw------- 1 root root 10, 236 Sep 18 11:19 control
- -l
- Long listing — shows each entry's type, so you can tell the
controlcharacter device from the symlinks that opened volumes create.
Only the controlnode — no mappings exist and none can be created here. On a real machine each volume youluksOpenappears in this directory as a named node (/dev/mapper/secure), which is the node you thenmkfsandmount. Seeing justcontrolis how you confirm nothing is currently unlocked.Runnable in the st10 room — that room’s setup plants the files it reads
grep -iE 'cipher|Key:' /root/storage/luksdump.txtcipher: aes-xts-plain64 Key: 512 bits- -i
- Case-insensitive — luksDump output capitalises inconsistently across versions (
cipher:vsCipher name:). - -E
- Extended regex, so
|means alternation — match the cipher line or the key-size line in one pass.
An analysis room hands you a captured luksDumpinstead of a live volume — in Storage Analysis: LUKS Cipher it is at/root/storage/luksdump.txt. This is the whole read: thecipher:line already carries the full spec (aes-xts-plain64= cipher-chainmode-iv), andKey: 512 bitsmeans AES-256 under XTS, because XTS splits the key into two halves. That pair is exactly the report line an encryption-analysis task wants.
- LUKS = dm-crypt (per-block encryption) + a header holding the cipher and the key slots; your passphrase unlocks a slot that decrypts the random master key, it does not encrypt the data directly.
- Lifecycle is one tool: luksFormat (create, destructive) -> luksOpen to /dev/mapper/<name> -> mkfs + mount the MAPPER node -> luksClose. Never format or mount the raw device.
- luksDump reads the header with no passphrase: join Cipher name + Cipher mode for the spec (aes-xts-plain64), and Key size 512 = AES-256 under XTS.
- Persist with /etc/crypttab (unlock -> mapper name, by UUID) read before /etc/fstab (mount the mapper); back up the header, because losing it destroys the volume no matter how many passphrases you know.
