Sign inSign up

ricariel/tang

By ricariel

•Updated about 9 hours ago

A multiarch tang Docker image, based on Alpine Linux.

Image
0

50K+

ricariel/tang repository overview

⁠docker_tang

A Tang⁠ server in a container, based on Debian 12. Tang provides the network half of NBDE⁠ (Network Bound Disk Encryption): a client bound with Clevis can unlock its LUKS volume automatically as long as it can reach the Tang server, and only then.

Tang itself holds no secrets belonging to the client — it never sees the passphrase or the key. It only participates in a key exchange that succeeds when the client is on the expected network.

⁠Features

  • Dual-stack: listens on IPv4 and IPv6 simultaneously; either can be disabled.
  • Healthcheck built in: the container reports unhealthy if the advertisement endpoint stops answering on an enabled protocol.
  • Persistent key material: signing and exchange keys live in the /db volume.

⁠Quickstart

docker run -d --name tang \
  -p 8080:8080 \
  -v tang-db:/db \
  docker_tang

On the first start Tang generates a fresh key pair in /db. Verify the server answers:

curl http://localhost:8080/adv

Bind a client to it with Clevis, using the address the client will actually reach:

clevis luks bind -d /dev/sda2 tang '{"url":"http://tang.example.com:8080"}'

Clevis shows the key thumbprint and asks for confirmation. Compare it against the server before accepting — that check is what stops an attacker from substituting their own Tang server.

⁠Configuration

VariableDefaultPurpose
ENABLE_IPv41Listen on IPv4. Set to any other value to disable.
ENABLE_IPv61Listen on IPv6. Set to any other value to disable.

IPv6-only operation:

docker run -d -e ENABLE_IPv4=0 -p 8080:8080 -v tang-db:/db docker_tang

Disabling both protocols leaves the container running with no listener; the healthcheck then trivially passes because it checks nothing.

⁠Volume
PathContents
/dbTang signing and key-exchange keys (.jwk files)

A host directory works just as well as a named volume:

docker run -d --name tang -p 8080:8080 -v /path/to/tang/db:/db docker_tang

The files are written as root, since this image does not drop privileges.

Back this volume up. Losing /db means every client bound to this server can no longer unlock automatically and has to be rebound with its recovery passphrase.

⁠Port

Tang is served on port 8080 inside the container over plain HTTP.

⁠How It Works

There is no long-running Tang daemon. start-servers runs socat listeners that fork a tangd process per connection:

  • socat TCP4-LISTEN:8080,reuseaddr,fork for IPv4
  • socat TCP6-LISTEN:8080,ipv6only=1,reuseaddr,fork for IPv6

socat passes the client address into the REMOTE_ADDR environment variable so tangd can log it. The healthcheck (check-servers, every 5 s) requests /adv over each enabled protocol via loopback.

⁠Key Rotation

Rotate by renaming the current keys in /db so their filename starts with a dot, then generating new ones:

docker exec tang sh -c 'cd /db && for k in *.jwk; do mv "$k" ".$k"; done'
docker exec tang /usr/libexec/tangd-keygen /db

Hidden keys are no longer advertised to new clients but still accept existing bindings, which gives already-bound clients time to be rebound. Delete the hidden files only once every client has been rebound.

⁠Security Notes

  • Tang speaks plain HTTP and is designed to. The protocol does not need confidentiality; the client verifies the server through the thumbprint recorded at bind time.
  • The security model is network reachability. Expose the port only on the network whose reachability should be the unlock condition — never on the public internet.
  • The container runs as root. The scripts under /etc/docker-entrypoint.d/99-extra-scripts are a leftover from padhi-homelab/docker_tang⁠, the Alpine-based image this one was forked from. Its base image ran an entrypoint runner and dropped privileges through DOCKER_UID (background⁠); the Debian base image here has neither, so those scripts never run.

⁠Origin

Forked from padhi-homelab/docker_tang⁠ and rebased on Debian. Upstream also ships a compose setup under padhi-homelab/services⁠.

⁠Building

docker build -t docker_tang .

⁠Contributing

This project uses pre-commit for style and quality checks, Conventional Commits for the history, and Renovate for dependency updates.

⁠License

MIT — see LICENSE⁠.

Tag summary

Content type

Image

Digest

sha256:bd5a10a8f…

Size

57.8 MB

Last updated

about 9 hours ago

docker pull ricariel/tang