Skip to main content
Hyperspeed uses Caddy as its public entrypoint on ports 80 and 443. Caddy handles TLS automatically when you provide a real hostname. No certificate management tooling is needed beyond setting two environment variables.

How it works

The behavior of Caddy depends on the value of CADDY_PUBLIC_HOST: Caddy handles certificate renewal automatically once the initial certificate is issued.

Local development (HTTP only)

With the default settings from .env.example, the stack runs on http://localhost with no TLS:
This is intentional — Let’s Encrypt does not issue certificates for localhost. The app is fully functional over HTTP for development purposes.
CORS_ORIGIN=http://localhost is the correct value when running locally with Docker + Caddy. Do not use https:// for local development unless you configure a self-signed certificate separately.

Production HTTPS

1

Point DNS at your server

Create an A record for your hostname that resolves to your server’s public IP address. Let’s Encrypt uses an HTTP-01 challenge — it makes an HTTP request to your domain on port 80 to verify you control it. DNS must be propagated and port 80 must be reachable before you start the stack.Verify DNS is ready:
2

Set CADDY_PUBLIC_HOST and CADDY_EMAIL

In your .env, set the hostname (no scheme, no trailing slash) and a Let’s Encrypt account email:
Caddy registers a Let’s Encrypt account using CADDY_EMAIL the first time it obtains a certificate. The email receives expiry warnings if automatic renewal ever fails.
3

Set CORS_ORIGIN to the HTTPS origin

Update CORS_ORIGIN to match the HTTPS origin users will open:
Without this, the browser will receive CORS errors on all API calls.
4

Start or restart the stack

Caddy requests the certificate on first start. Watch for errors:
A successful certificate issue looks like:
If port 80 is blocked by a firewall or already in use by another process, the HTTP-01 challenge will fail and Caddy will not be able to obtain a certificate. Ensure ports 80 and 443 are both open and free before starting the stack.

WebSocket and HTTPS

Hyperspeed uses WebSockets for realtime features (collaborative editing, live board updates, terminal). Behind HTTPS, WebSocket connections use wss:// instead of ws://. Caddy handles the WebSocket upgrade automatically — no extra configuration is needed. The Caddyfile routes /api/* to the API container with reverse_proxy, which passes Upgrade and Connection headers through by default.
To verify WebSocket connectivity: open a space with realtime features and check DevTools Network for a 101 Switching Protocols response on the /api/v1/organizations/.../ws connection.

Using Traefik or nginx instead of Caddy

If your infrastructure already uses Traefik or nginx as an edge proxy, you can replace Caddy with your preferred reverse proxy. The routing requirements are:
  • All traffic to /api/* and /health must proxy to the API container on port 8080, with WebSocket upgrade headers forwarded.
  • All other traffic should serve the web container on port 80.
  • The API and web UI must share a single origin in the browser — the SPA calls /api/... relative to the page origin.
  • TLS must terminate at the edge proxy.
An example nginx location block for the API:
When using an alternative proxy, remove or disable the caddy service from docker-compose.yml and configure your proxy to handle TLS for your hostname. Set CADDY_PUBLIC_HOST and CADDY_EMAIL to empty or remove them — they are only read by the Caddy container.

Troubleshooting