Sovereign Cloud Stack

Sovereign Cloud Stack (SCS) ist eine offene, föderierbare und modulare Cloud- und Containerplattform auf Basis von Open-Source-Software.

SCS Infrastructure KeylessGo

Mathias Fechner 17. August 2022

NBDE – Network Bound Disk Encryption

As an Operator i want to be sure that storage’s is encrypted, as a DevOps i think it is hard to integrated with Automation.

This was the sparking intention to integrate NBDE in OSISM.

Network Bound Disk Encryption is a method to automatically handle LUKS for bare metal system in location such as data centers. Its purpose is to protect against unauthorized access to data on storage devices in case of loss or vendor lifecycle management.

The involved components Luks, Clevis and Tang in one figure:


is the Javascript Object Signing and Encryption Framework. In context of NBDE it uses an RSA based encryption preconfigure part to solve the hen and egg problem.


is a JOSE based pluggable framework which automatically handles LUKS encryption locally inside the boot procedure and is able to handle network base encryption or combine it with other methods.


itself is a small webserver with the JOSE library. The tang protocol relies on the JSON Object Signing and Encryption (JOSE) standards. In tang protocol is every message a valid JOSE object.

Build a encrypted base image

As a first step, we build an image with a preconfigured LUKS encryption and password. Inside the images is a dropbear-ssh server preconfigured with a corresponding authorized_key file.

Prebooting step

In the second step within the boot phase we now access the preconfigured ssh server with the particular ssh key. This part will be later removed from installation, because an co-existing installation is not possible.

Listening on LPF/ens3/fa:16:3e:12:77:28
Sending on   LPF/ens3/fa:16:3e:12:77:28
Sending on   Socket/fallback
DHCPDISCOVER on ens3 to port 67 interval 3 (xid=0xea981b1a)
DHCPREQUEST for on ens3 to port 67 (xid=0x1a1b98ea)
DHCPACK of from (xid=0xea981b1a)
bound to -- renewal in 16380 seconds.

cryptsetup: luksroot: set up successfully

Init clevis and tang

The second step is to install the Clevis Tang “PIN”

That means Clevis requests a private key from Tang and signs it with a local blended key, which is new encryption key. This is used as new Luks meta information to create a keyslot in Luks table.

$ osism apply clevis

PLAY [test] **********************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
ok: []

TASK [clevis : Gather variables for each operating system] ***********************************************************************************************************
ok: []

TASK [clevis : Include distribution specific package tasks] **********************************************************************************************************
included: /ansible-collection-commons/roles/clevis/tasks/install-Debian.yml for

TASK [clevis : Wait for apt lock] ************************************************************************************************************************************
ok: [] => (item=lock)
ok: [] => (item=lock-frontend)

TASK [clevis : Install clevis packages] ******************************************************************************************************************************
changed: []

TASK [clevis : Install tang encryption] ******************************************************************************************************************************
included: /ansible-collection-commons/roles/clevis/tasks/create-tangcrypt.yml for

TASK [clevis : Remove dropbear ssh initramfs packages] ***************************************************************************************************************
changed: []

TASK [clevis : Remove dropbear artefacts] ****************************************************************************************************************************
ok: []

TASK [clevis : Check if disk /dev/sda6 already bind to tang] *********************************************************************************************************
fatal: []: FAILED! => {"changed": false, "cmd": ["clevis", "luks", "list", "-d", "/dev/sda6", "-s", "2"], "delta": "0:00:00.137538", "end": "2022-08-16 15:02:16.298475", "msg": "non-zero return code", "rc": 1, "start": "2022-08-16 15:02:16.160937", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}

TASK [clevis : Prepare clevis environment] ***************************************************************************************************************************
changed: []

TASK [clevis : Get adv handshake from tang server] *******************************************************************************************************************
changed: []

TASK [clevis : Insert the keyfile for luks unlock] *******************************************************************************************************************
changed: []

RUNNING HANDLER [clevis : Update initramfs] **************************************************************************************************************************
ok: []

RUNNING HANDLER [clevis : Enable clevis-luks-askpass.path service] ***************************************************************************************************
ok: []

RUNNING HANDLER [clevis : Chain tang pin] ****************************************************************************************************************************
changed: []

RUNNING HANDLER [clevis : Enable tang boot environment] **************************************************************************************************************

What is happening within the Tang service …

Jul 20 11:53:10 tang-server tangd[54307]: GET /adv => 200 (src/tangd.c:82)
Jul 20 11:53:10 tang-server systemd[1]: tangd@3- Succeeded.

and get the advertisement, the reply message contains a JWS-signed JWKSet

and on the bare metal server ?

$ cryptsetup luksDump /dev/sda1

2: tang '{"url":""}'

        0: clevis
        Keyslot:  2

The tang protocol implements the McCallum-Relyea exchange. This process is very familiar with ssh authentication. Now the “PIN” is bound to the Tang service. After reboot the server will request with the clevis-initramfs embbed client the network Tang service. If the Clevis Tang advertised signing JWK, short “PIN” is valid, the reboot will continue.

The server is now booting with NBDE, see the successful Tang server logs *

Aug 16 13:08:11 tang-server tangd[157304]: POST /rec/ebTVn9gtMeD-RV6Ux4DeCiSpff0 => 200 (src/tangd.c:165)
Aug 16 13:08:11 tang-server systemd[1]: tangd@6- Succeeded.

In SCS stacks it is now able to activate NBDE for bare metal nodes like control, compute, network and storage nodes!