Skip to content

Hub on Docker

  • TCP 443 — client TLS
  • TCP 8443 — hub control plane
  • UDP 51820 — iroh QUIC

DNS for the hub hostname must point at the VPS.

Terminal window
docker run -d --name towonel \
-p 443:443 -p 8443:8443 -p 51820:51820/udp \
-v towonel-data:/data \
-e TOWONEL_HUB_PUBLIC_URL=https://hub.example.eu \
-e TOWONEL_EDGE_ADVERTISED_ADDRESSES=hub.example.eu:443 \
-e TOWONEL_HUB_TLS_ACME_EMAIL=ops@example.eu \
codeberg.org/towonel/towonel-node:latest

/data holds node.key, operator.key, invite_hash.key, and ACME certs. Keys are generated on first boot.

TOWONEL_HUB_TLS_ACME_EMAIL enables ACME (TLS-ALPN-01) on the hub API port. Use Let’s Encrypt staging while testing to dodge rate limits, and override the cert cache or ACME directory if needed:

Terminal window
-e TOWONEL_HUB_TLS_ACME_STAGING=true
-e TOWONEL_HUB_TLS_CERT_DIR=/data/acme
# -e TOWONEL_HUB_TLS_ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory

The bundled-Caddy variant below terminates TLS at Caddy instead, so these don’t apply there.

codeberg.org/towonel/towonel-hub-caddy:latest ships Caddy (caddy-l4) in the same image. Caddy binds :80/:443 and L4-forwards to towonel with PROXY v2.

Terminal window
docker run -d --name towonel \
-p 80:80 -p 443:443 -p 8443:8443 -p 51820:51820/udp \
-v towonel-data:/data \
-e TOWONEL_HUB_PUBLIC_URL=https://hub.example.eu \
-e TOWONEL_EDGE_ADVERTISED_ADDRESSES=hub.example.eu:443 \
-e TOWONEL_HUB_TLS_ACME_EMAIL=ops@example.eu \
codeberg.org/towonel/towonel-hub-caddy:latest

Mount a custom Caddyfile at /etc/caddy/Caddyfile to override.

Back up /data. In particular:

  • operator.key — admin auth for the CLI
  • invite_hash.key — losing it invalidates every outstanding invite

For production, set TOWONEL_INVITE_HASH_KEY from a secret manager.

Terminal window
docker exec towonel towonel invite create \
--name alice \
--hostnames 'app.alice.example.eu,*.alice.example.eu'
# tt_inv_2_<token>