LUKS2 Encryption on Shani OS — Setup, Management, and Recovery

Full-disk encryption on Shani OS is a single checkbox in the installer. If you skipped it, the correct path is to reinstall — not to attempt to encrypt an existing installation in place.

This guide covers why that is the right call, how to reinstall cleanly, and then — for users who already have an encrypted system — a complete reference for everything you can do with LUKS2: managing keyslots and passphrases, adding keyfiles, backing up the LUKS header, enrolling TPM2 auto-unlock, and recovering from worst-case scenarios.

Full reference: docs.shani.dev — LUKS.

---

If You Missed Encryption at Install: Reinstall

Encrypting an existing unencrypted Shani OS installation requires wiping the root partition entirely. There is no in-place conversion. Attempting it by hand means: backing up all data, booting from USB, repartitioning, creating a LUKS container, recreating the Btrfs subvolume layout, restoring data, regenerating UKIs, and re-enrolling TPM2. Each step is an opportunity for data loss. The Shani OS installer does all of this correctly in a few clicks.

The right approach:

  1. Back up your home directory and any data you want to keep:
   # restic is pre-installed
   restic -r /media/external/backup init
   restic -r /media/external/backup backup ~/
   restic -r /media/external/backup backup /data/
   restic -r /media/external/backup check
   
  1. Download the latest Shani OS ISO from shani.dev and write it to a USB drive
  2. Boot from the USB and run the installer
  3. On the disk setup screen, enable full-disk encryption — it is a single toggle
  4. Complete installation, reboot, and restore your home directory from the backup

The installer creates the LUKS2 container with argon2id KDF, creates all Btrfs subvolumes, configures /etc/crypttab, and generates the UKIs with the correct LUKS UUID embedded. Everything is wired up correctly from the start.

After reinstalling, enroll TPM2 for passwordless unlock:

sudo gen-efi enroll-tpm2

That's it. The rest of this guide is for users who already have an encrypted system and want to manage it.

---

Why LUKS2 with argon2id

Shani OS uses LUKS2 with the argon2id key derivation function:

  • argon2id is memory-hard — it requires a large amount of RAM to compute, making GPU and ASIC brute-force attacks orders of magnitude more expensive than with older PBKDF2-based setups
  • LUKS2 supports multiple keyslots, allowing you to have a passphrase, a keyfile, and a TPM2-sealed key all active simultaneously
  • The passphrase you choose still matters — argon2id slows attackers down but a weak passphrase is still a weak passphrase

Default encryption parameters used by the Shani OS installer:

Cipher:      aes-xts-plain64
Key size:    512 bits
PBKDF:       argon2id
Memory cost: 1048576 KB (1 GB)
Time cost:   4 iterations
Parallelism: 4 threads

---

Checking Encryption Status

# Is the root partition encrypted?
lsblk -f | grep -E "crypt|luks"
# Should show crypto_LUKS under your root partition (e.g. nvme0n1p2)

# View the full LUKS header — version, cipher, KDF, all keyslots
sudo cryptsetup luksDump /dev/nvme0n1p2

# Confirm the active mapper device
cat /proc/mounts | grep mapper

Look for Version: 2, cipher: aes-xts-plain64, and PBKDF: argon2id. If you see pbkdf2 instead of argon2id, your KDF is significantly weaker — you can convert it:

sudo cryptsetup luksConvertKey --pbkdf argon2id /dev/nvme0n1p2

---

Managing Keyslots

LUKS2 supports up to 32 keyslots. Each keyslot holds an independent key that can decrypt the volume. You can have a primary passphrase, a backup passphrase, a keyfile, and a TPM2-sealed key all active at once.

Adding a Second Passphrase (Recovery Key)

Adding a second passphrase gives you a backup if you forget the first, or a separate passphrase for a trusted person:

sudo cryptsetup luksAddKey /dev/nvme0n1p2
# Enter any existing passphrase when prompted, then set the new one

Changing Your Passphrase

LUKS does not have a "change passphrase" operation — you add a new keyslot then remove the old one:

# Step 1: Add the new passphrase (creates a new keyslot)
sudo cryptsetup luksAddKey /dev/nvme0n1p2

# Step 2: Find the keyslot number of the old passphrase
sudo cryptsetup luksDump /dev/nvme0n1p2 | grep -A2 "Keyslot"

# Step 3: Remove the old keyslot
sudo cryptsetup luksKillSlot /dev/nvme0n1p2 <keyslot-number>
# You will be prompted to authenticate with any remaining valid key

Adding a Keyfile

Keyfiles are useful for automated unlock scenarios or as a recovery key stored securely off-device:

# Generate a strong random keyfile
sudo dd if=/dev/urandom of=/root/luks-keyfile bs=512 count=8
sudo chmod 400 /root/luks-keyfile

# Add the keyfile as an additional LUKS keyslot
sudo cryptsetup luksAddKey /dev/nvme0n1p2 /root/luks-keyfile

# Verify all keyslots
sudo cryptsetup luksDump /dev/nvme0n1p2 | grep -E "Keyslot|Token"

Store the keyfile off-device. Losing it does not lock you out as long as you still have your passphrase.

Removing a Keyslot

# Remove a specific keyslot by number
sudo cryptsetup luksKillSlot /dev/nvme0n1p2 <keyslot-number>

# Or remove by key (prompts for the key to remove)
sudo cryptsetup luksRemoveKey /dev/nvme0n1p2

Never remove all keyslots — leave at least your passphrase slot intact.

---

Backing Up the LUKS Header

The LUKS header stores all keyslots. If it gets corrupted — by a disk failure, accidental overwrite, or filesystem error — the encrypted data is permanently and completely unrecoverable. Back up the header:

sudo cryptsetup luksHeaderBackup /dev/nvme0n1p2 \
  --header-backup-file ~/luks-header-backup-$(date +%Y%m%d).img

# Store this file off-device — external drive, encrypted cloud storage
# Verify it is readable
file ~/luks-header-backup-*.img

Restoring from a header backup:

# This restores the keyslots as they were at backup time
sudo cryptsetup luksHeaderRestore /dev/nvme0n1p2 \
  --header-backup-file luks-header-backup-20260401.img

Back up the header again any time you add or remove a keyslot.

---

TPM2 Auto-Unlock

TPM2 auto-unlock seals your LUKS key into the TPM2 chip so the disk unlocks silently on boot — no passphrase prompt — as long as the boot chain is unmodified. Your passphrase always remains valid as a fallback.

Enrolling

# gen-efi handles PCR policy selection and KDF validation automatically
sudo gen-efi enroll-tpm2

You will be prompted for your LUKS passphrase. The PCR policy is chosen based on your Secure Boot state:

  • Secure Boot enabled: PCR 0 + PCR 7 — firmware measurements and Secure Boot certificate state
  • Secure Boot disabled: PCR 0 only — firmware measurements only (weaker)

After enrolling, reboot and confirm the disk unlocks silently.

After Firmware Updates

If fwupdmgr update updated your BIOS, PCR 0 changes. The TPM will not release the key, so you will be prompted for your passphrase on the next boot. This is expected behaviour.

# After booting with passphrase, clean up the stale slot and re-enroll
sudo gen-efi cleanup-tpm2
sudo gen-efi enroll-tpm2

After Secure Boot Changes

When you enable, disable, or change enrolled Secure Boot keys, PCR 7 changes. Re-enroll:

sudo gen-efi cleanup-tpm2
sudo gen-efi enroll-tpm2

Adding a TPM2 PIN (Second Factor)

For stronger protection, require a short PIN in addition to TPM2 binding. gen-efi enroll-tpm2 prompts you to opt in during enrollment. Plymouth will ask for the PIN at boot — the disk only unlocks if both the TPM measurement matches and the PIN is correct.

Verifying TPM2 State

# Confirm TPM2 enrollment is present
sudo cryptsetup luksDump /dev/nvme0n1p2 | grep systemd-tpm2

# List all keyslots and tokens
sudo cryptsetup luksDump /dev/nvme0n1p2 | grep -A5 "Token"

# List available TPM2 devices
sudo systemd-cryptenroll --tpm2-device=list

Full TPM2 reference: docs.shani.dev — TPM2 Enrollment.

---

Verifying Encryption is Working

# Confirm the partition type
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT
# nvme0n1p2 should show crypto_LUKS

# Check the mapper device is active
ls -la /dev/mapper/shani_root

# Full header dump
sudo cryptsetup luksDump /dev/nvme0n1p2

---

Emergency Recovery

Forgotten Passphrase, No Backup Key

If you have no backup passphrase, no keyfile, and no TPM2 enrollment — the data is unrecoverable. This is the intended security guarantee of LUKS2.

Boot from the Shani OS USB, reinstall, and restore from your data backups.

Have a Backup Keyfile

# Boot from Shani OS USB
# Open the encrypted partition using the keyfile
sudo cryptsetup open /dev/nvme0n1p2 shani_root \
  --key-file /path/to/luks-keyfile

# Mount and access your data
sudo mount -o subvol=@home /dev/mapper/shani_root /mnt/home
sudo mount -o subvol=@data /dev/mapper/shani_root /mnt/data

Have a Header Backup (Corrupted Header)

# Boot from Shani OS USB
# Restore the header backup first
sudo cryptsetup luksHeaderRestore /dev/nvme0n1p2 \
  --header-backup-file luks-header-backup.img

# Then open with your passphrase as normal
sudo cryptsetup open /dev/nvme0n1p2 shani_root

TPM2 Won't Unlock (Firmware Changed)

# Boot and enter your passphrase when prompted
# Then re-enroll TPM2 with current PCR values
sudo gen-efi cleanup-tpm2
sudo gen-efi enroll-tpm2

---

Resources

---

Built in India 🇮🇳 · Immutable · Atomic · Zero Telemetry