Sitemap
Lumenyx

Lumenyx

Stop Driving Home to Unlock Your Server: Automatic Disk Decryption with Tang and Clevis

5 min readJul 31, 2026

--

Have you ever set up disk encryption on your Linux server and had to unlock it by putting in the passphrase?

Have you ever had the server reboot for some reason when you’re incredibly far away?

Then you have to drive all the way back home or get someone to type in your passphrase just to get your server working again?

This exact scenario happened to me after I rebooted my server after critical updates.

Thankfully we can use Clevis and Tang to decrypt the drive automatically.

WHAT IS CLEVIS AND TANG?

What is Clevis?

It’s a framework for automated decryption. It lets you add additional ways to unlock a LUKS volume besides typing a passphrase.

What is Tang?

Tang is a server that Clevis (client) talks to at boot, as long as it’s reachable over the network.

This means that your machine can be decrypted automatically as long as it’s on the correct network.

HOW DOES IT DECRYPT THE DRIVE?

Tang and Clevis use asymmetrical encryption referred to as the McCallum-Relyea key exchange protocol.

1. Tang (server) publishes its public key.

2. Clevis (Client) generates a random disk unlock secret.

3. Clevis uses Tang’s public key to encrypt the secret and stores the encrypted data in LUKS.

4. At boot, Clevis sends Tang the stored key-exchange data that was created when the disk was enrolled.

5. Tang uses its private key to perform a mathematical operation that only Tang can perform and returns the result to Clevis.

6. Clevis combines that result with its locally stored data to reconstruct the unlock secret and unlock the disk.

INSTALL TANG

On a separate machine we will install Tang:

sudo apt install tang -y

Start and enable the tang socket:

sudo systemctl enable --now tangd.socket

The difference between a service and a socket is that a service is a background program that performs task, whereas a socket is a communication endpoint used by programs to send and receive data.

If you get an error about a port conflict, then add in this override to change the port. In the below example we set it to 7500:

sudo mkdir -p /etc/systemd/system/tangd.socket.d
sudo tee /etc/systemd/system/tangd.socket.d/override.conf <<'EOF'
[Socket]
ListenStream=
ListenStream=7500
EOF
  • The first ListenStream= clears the default port
  • The second ListenStream=7500 sets the port to be 7500

Restart the socket:

sudo systemctl restart tangd.socket

Verify that it’s listening:

sudo systemctl status tangd.socket && sudo ss -tlnp | grep 7500
Press enter or click to view image in full size

OPTIONAL — Restrict firewall access (below example uses firewalld):

sudo firewall-cmd --permanent --zone=FedoraServer --add-rich-rule='rule family="ipv4" source address="<encrypted-host-IP>" port port="7500" protocol="tcp" accept'
sudo firewall-cmd --reload

That is all the configuration that’s needed for the Tang server.

FIND THE DRIVE THAT NEEDS TO BE DECRYPTED

Now we should switch over the the client, the device that needs to be unlocked every time it turns back on.

We have to find what is called ‘The LUKS partition’.

Get Lumenyx’s stories in your inbox

Join Medium for free to get updates from this writer.

This is what requires the decryption key upon boot.

A LUKS partition is a section of a storage drive encrypted using Linux Unified Key Setup to protect your files, system data, and personal information from unauthorized access.

We can find out which drive is our LUKS partition by utilising these commands:

lsblk -f
sudo blkid
Press enter or click to view image in full size

For me, it’s /dev/sda3.

BIND THE LUKS VOLUME TO TANG

First we have to install Clevis.

sudo dnf install clevis clevis-luks clevis-dracut -y

What is ‘binding’?

‘Binding’ is the act of registering one of the automated unlock methods (like Tang) with your LUKS volume.

LUKS lets a disk have several valid unlock codes at once (referred to as keyslots), and binding adds an extra keyslot whose key can only be reconstructed by talking to Tang.

Bind the volume to your Tang server:

sudo clevis luks bind -d /dev/[VOLUME] tang '{"url":"http://<TANG-IPADDRESS>:[PORT]"}'

Example:

sudo clevis luks bind -d /dev/sda3 tang '{"url":"http://192.168.0.14:7500"}'

If the binding was successful, you should see see something like:

1: tang '{"url":"http://<pi-IP>:7500"}'

If it was unsuccessful you would receive an error like this:

You’ll be prompted for your existing LUKS passphrase to authorize the new binding, and asked to confirm trust of the Tang server’s advertisement.

REBUILD INITRAMFS

The initramfs is a temporary filesystem image used to help the Linux Kernel mount the root filesystem and run the main Init system.

- https://wiki.debian.org/initramfs

Rebuild initramfs so that it includes Clevis, Tang, and networking support:

sudo dracut -f --regenerate-all

Dracut is a tool that’s used to build an initramfs image by reading your system configuration and copying only the necessary kernel modules/scripts/binaries into the emergency boot environment.

Since we installed clevis-dracut earlier, it dropped the necessary files into /usr/lib/dracut/modules.d/.

When dracut rebuilds the image, it also scans your system’s LUKS environment (via /etc/crypttab and the LUKS headers) and notices that we already have a Tang/Clevis binding, therefore it will automatically add the Clevis module, as well as networking support since that is what Clevis depends on.

Now we have to verify that the rebuild actually pulled the correct components:

sudo lsinitrd /boot/initramfs-$(uname -r).img | grep -iE 'clevis|tang|NetworkManager'

lsinitrd is a tool that’s used to show the contents of an initramfs image.

You should see clevis-decrypt-tang, clevis-luks-askpass, and NetworkManager binaries listed:

Press enter or click to view image in full size

Add the required boot parameters:

sudo grubby --update-kernel=ALL --args="rd.neednet=1 rd.net.timeout.dhcp=30"

This tells the boot sequence that we need networking as early as the boot-up process.

grubby is a command line tool for configuring grub and zipl.

Rebuild initramfs again:

sudo dracut -f --regenerate-all

Confirm that the bootloader changes are present:

sudo bash -c "grep -o 'rd.neednet=1' /boot/loader/entries/*.conf"
sudo bash -c "grep -o 'rd.net.timeout.dhcp=[0–9]*' /boot/loader/entries/*.conf"
Press enter or click to view image in full size

TESTING

Reboot the client and confirm if it unlocks automatically:

sudo reboot

On the server you can check the logs to see if Tang was contacted for the decryption (look for a POST /rec/... request, not just GET /adv):

sudo journalctl -u tangd.socket -u 'tangd@*' -f

If it unlocks with no prompt and you see that POST /rec/... line in the Pi's journal, then you have succeeded in having it unlock automatically.

Press enter or click to view image in full size

--

--