A recipe for installing Debian with a LUKS-encrypted root filesystem and configuring it to unlock automatically at boot using Tang and Clevis (Network-Bound Disk Encryption).

Disclaimer: This process will nuke all data on the drives you target. Back up anything you want to keep before you start.

This works on plain ext4 on LUKS (Part 1 below) and on ZFS on LUKS equally – Clevis binds to the LUKS layer regardless of what is on top.


Why Tang + Clevis?

LUKS encryption normally means typing a password at every reboot. On a headless server that’s a problem. Tang provides key-derivation as a service on your LAN. Clevis binds your LUKS volume to Tang so the server can unlock itself at boot as long as the Tang server is reachable.

With two Tang servers and Shamir’s Secret Sharing (SSS), both must be available for the key to reconstruct – you can lose one without losing the ability to boot.


Part 1: Install Debian with encrypted root

This section uses the standard Debian installer with ext4 on LUKS. If you prefer ZFS on the same LUKS layer (snapshots, compression), follow the ZFS on LUKS article instead, then come back to Part 3 for Tang + Clevis.

Step 1.1: Boot and partition

Boot from the Debian 13 netinst ISO and go through the installer normally until you reach the partitioning step.

Choose Manual partitioning and create three partitions:

PartitionSizeUse
1st1024 MiBEFI (FAT32, mounted at /boot/efi)
2nd1024 MiBext4, mounted at /boot
3rdrest of diskPhysical Volume for Encryption

Step 1.2: Configure encryption

  1. Select Configure encrypted volumes from the partitioner menu.
  2. Write changes, then Create encrypted volumes.
  3. Select the 3rd partition and confirm.
  4. Set your LUKS passphrase.

Step 1.3: Use the encrypted volume

  1. Back in the partitioner, navigate into the encrypted volume.
  2. Select the partition inside it and edit it.
  3. Set mount point to / (root).
  4. Finish partitioning and write changes.

When the installer asks about a swap partition, select No if you prefer a swap file (you can add one later).

Step 1.4: Finish the install

Complete the installation normally. Reboot into your new system.

After first boot, check your apt sources:

sudo nano /etc/apt/sources.list

It should look something like this. Adjust as needed:

deb http://deb.debian.org/debian/ trixie main contrib non-free-firmware
deb http://deb.debian.org/debian/ trixie-updates main non-free-firmware
deb http://deb.debian.org/debian/ trixie-backports main non-free-firmware

Part 2: Set up Tang server(s)

Tang is lightweight. It runs as a service on a container or VM on your LAN, or even on a remote VPS.

Step 2.1: Install Tang

On the machine that will host the Tang service:

sudo apt install tang jose

That is it. Tang is a simple HTTP-based service that listens on port 80 by default.

Step 2.2: Verify Tang is working

From another machine on the same network, fetch the advertising key:

curl http://192.168.13.51/adv

You should get a large JSON payload. That means Tang is running.

Step 2.3: Plan your Tang layout

I recommend running at least two Tang servers:

  • One on your LAN (e.g. a container on another encrypted server)
  • One off-site (a friend’s machine, a cheap VPS, or a Raspberry Pi elsewhere)

Both are used together with Shamir’s Secret Sharing, so if either one is down, the other still allows unlocking. Adjust port with e.g. http://203.0.113.42:7500/adv if your remote Tang listens on a non-default port.


Part 3: Configure Clevis on the encrypted server

Step 3.1: Install Clevis

On your encrypted Debian server:

sudo apt install clevis clevis-luks clevis-initramfs

Step 3.2: Bind LUKS to your Tang servers

Find your LUKS partition:

lsblk

Look for the crypt device or the partition under it. On the example setup from Part 1, the raw LUKS partition might be /dev/nvme0n1p3 or /dev/sda3. In this example I use /dev/nvme0n1p3 – change to match your setup.

Bind against two Tang servers with Shamir Secret Sharing (threshold 2):

sudo clevis luks bind -d /dev/nvme0n1p3 sss \
  '{"t":2,"pins":{"tang":[
    {"url":"http://192.168.13.51"},
    {"url":"http://203.0.113.42:7500"}
  ]}}'

Clevis will ask for your LUKS passphrase, verify both Tang servers, and ask you to trust them. After confirming, a new LUKS keyslot is created.

Your existing LUKS passphrase still works. The Tang keyslot is an addition, not a replacement.

Threshold explained: "t":2 with two Tang servers means both must be reachable to unlock. If you want either Tang to suffice, use "t":1 instead. I prefer t:2 for security.


Part 4: Network during boot

For Clevis to unlock at boot, the initramfs needs networking. This is the most fiddly part.

Step 4.1: Configure initramfs networking

Edit the initramfs config:

sudo nano /etc/initramfs-tools/initramfs.conf

At the end of the file, add a line like this (adjust for your network):

IP=192.168.13.15::192.168.13.1:255.255.255.0::enp5s0:off:192.168.13.1

Breaking it down:

PartExampleMeaning
Client IP192.168.13.15Static IP for this server at boot
Server IP(empty)NFS root server (blank for local boot)
Gateway192.168.13.1Default gateway
Netmask255.255.255.0Subnet mask
Hostname(empty)Optional
Interfaceenp5s0Your network interface name
AutoconfoffStatic IP (use dhcp for DHCP)
DNS192.168.13.1Name server (needed if Tang uses hostnames)

The double colons are intentional – server-ip and hostname are left blank in this example.

Find your interface name:

ip a

Step 4.2: CURL hook for remote Tang (optional)

If your Tang server uses a hostname or HTTPS, add a CURL hook so the initramfs can resolve names and fetch over HTTPS.

Create the hook file:

sudo nano /usr/share/initramfs-tools/hooks/curl

Paste this:

#!/bin/sh -e
PREREQS=""
case $1 in
  prereqs) echo "${PREREQS}"; exit 0;;
esac
. /usr/share/initramfs-tools/hook-functions

# Copy curl binary
copy_exec /usr/bin/curl /bin

# Fix DNS lib
cp -a /usr/lib/x86_64-linux-gnu/libnss_dns* $DESTDIR/usr/lib/x86_64-linux-gnu/

# Fix DNS resolver
echo "nameserver 1.1.1.1" > ${DESTDIR}/etc/resolv.conf

# Copy CA certificates for HTTPS
mkdir -p $DESTDIR/usr/share
cp -ar /usr/share/ca-certificates $DESTDIR/usr/share/
cp -ar /etc/ssl $DESTDIR/etc/

Make it executable and update initramfs:

sudo chmod 755 /usr/share/initramfs-tools/hooks/curl
sudo update-initramfs -u -k all

Step 4.3: Reboot

sudo reboot

Watch the boot messages. The initramfs will:

  1. Ask for the LUKS passphrase (fallback if Tang fails).
  2. Bring up networking.
  3. Contact the Tang servers.
  4. Unlock the root partition automatically.

If it works, you have password-less encrypted boot – a server that unlocks itself on your LAN but is useless if stolen.


Notes

  • Your original LUKS passphrase is in a separate keyslot. If the Tang servers are unreachable at boot and the initramfs times out, it will fall back to the passphrase prompt. You are never locked out as long as you remember it.
  • If you need to rebind after changing Tang keys, use clevis luks regen -d /dev/nvme0n1p3 -s 1.
  • Stopping a Tang server prevents any Clevis-bound server from auto-unlocking. Useful as a remote kill switch – if a server is stolen and the Tang server is stopped, the drive stays locked even if booted elsewhere.

Credits and sources