Skip to main content

TLS termination

Written by Aron Day

3B expects to be reached over HTTPS, with TLS terminated somewhere in the request path: at 3B’s built-in nginx, or at a load balancer or proxy in front of it. Note that AI providers require requests to arrive over a secure (HTTPS) connection, so configuring them will not work over plain HTTP.

Whichever option you choose, the certificate must cover every configured hostname. Use a single SAN or wildcard certificate that spans the UI, API, public, and Zero sync hosts, plus *.<domain> if you set a public wildcard domain. A certificate that misses a hostname gives clients TLS errors on the uncovered ones.

Option 1: an upstream load balancer or proxy terminates TLS

Choose this when something in front of 3B already handles HTTPS, such as a cloud load balancer, a reverse proxy, or a CDN. 3B serves plain HTTP internally and trusts the X-Forwarded-Proto: https header, so the upstream must forward it. You provide no certificate to 3B.

This is the usual choice on a managed Kubernetes platform, typically an ALB with an ACM certificate on EKS, a Google-managed certificate on GKE, or an OCI load balancer on OKE. Each platform guide covers what to watch for there.

On the single-server install, pick choice 1 at the TLS prompt (or leave NGINX_TLS_CERT_PATH / NGINX_TLS_KEY_PATH unset).

Option 2: 3B’s nginx terminates TLS with your certificate

Choose this when you have a certificate from your CA, and want 3B itself to serve HTTPS.

Single server: pick choice 2 at the TLS prompt and give the installer the path to the full-chain certificate (PEM) and the private key. The installer checks that the certificate covers every configured hostname and warns you if any is missing, then loads them into Kubernetes as the nginx-tls secret. Non-interactively, set NGINX_TLS_CERT_PATH and NGINX_TLS_KEY_PATH in /opt/3b/.env. To rotate the certificate later, update the files and re-run sudo bash /opt/3b/setup.sh.

Kubernetes with Helm: create the TLS secret and enable nginx TLS in your values:

kubectl -n 3b create secret tls nginx-tls --cert=fullchain.pem --key=key.pem
nginx:
  tls:
    enabled: true
    secretName: nginx-tls

HTTPS is then served on port 443 (NodePort 30443 by default; nginx.tls.hostPort binds the node port directly). All external URLs must use https:// and cookies.secure must be true.

Option 3: a self-signed certificate (evaluation only)

On the single-server install, pick choice 3 at the TLS prompt and the installer generates a certificate on the spot covering all your hostnames. Browsers will show a security warning until you trust it manually. We don’t recommend this outside of evaluations.

Changing your choice later

The single-server installer remembers your choice as NGINX_TLS_MODE in /opt/3b/.env. On later runs it only re-asks if the configured certificate is missing or no longer covers your hostnames; otherwise it offers to reconfigure. To switch options, re-run sudo bash /opt/3b/setup.sh and answer the “Reconfigure nginx TLS?” prompt.

Did this answer your question?