Skip to content

TLS / Caddy integration

The gateway itself does not terminate TLS. In production, Caddy sits in front and:

  • Terminates TLS for hivecast.ai and its subdomains.
  • Manages Let's Encrypt certificates automatically.
  • Proxies HTTP traffic to the gateway on localhost:<gateway-port>.
  • Proxies WebSocket upgrades for /nats-ws directly to NATS WS.

Local dev does not use Caddy. The gateway listens on plain HTTP at 127.0.0.1.

Production Caddyfile

The production deployment's Caddyfile lives at projects/deploy-cloud/Caddyfile.bare:

caddyfile
hivecast.ai {
  handle /nats-ws {
    reverse_proxy localhost:4223
  }
  handle /downloads/* {
    root * /home/ubuntu/hivecast
    file_server
  }
  handle {
    reverse_proxy localhost:3198
  }
}

hivecast-lab.hivecast.ai {
  # ... lab variant with extra rules
}

registry.hivecast.ai {
  reverse_proxy localhost:3000
}

hivecast.ai

Three handlers, in order:

  1. /nats-wslocalhost:4223 (NATS WS, direct to NATS)
  2. /downloads/* → static file server (release tarballs)
  3. everything else → localhost:3198 (the gateway)

Note: /nats-ws goes directly to NATS, bypassing the gateway's own /nats-ws upgrade handler. Both paths work; Caddy's direct proxy is faster (one less hop). The gateway-side handler is the local-mode fallback.

The gateway's HTTP port in production is 3198 (not the default 3100). Operators set this via --http-port at install time.

hivecast-lab.hivecast.ai

A separate Caddy site for the lab/preview environment. It has more granular handlers because the lab serves a static SPA preview directly from disk in addition to forwarding API/auth to the production gateway.

registry.hivecast.ai

The Gitea artifact registry. See docs-registry / Gitea backend.

What Caddy provides

FeatureOwned by Caddy
TLS / Let's Encryptyes
HTTP/2, HTTP/3yes
Host-based routing (hivecast.ai vs registry.hivecast.ai)yes
Path-based handlers within a hostyes
Static file serving (/downloads/*)yes
Health checks of upstreamsyes (configurable)
Compressionyes (configurable)

What Caddy does NOT do

  • Authentication. The gateway and Matrix actors handle that.
  • Matrix-specific routing logic. Caddy doesn't parse /<routeKey>/<appName>/...; it forwards the entire URL to the gateway and the gateway parses it.
  • Asset caching. Caddy can be configured to cache, but it's currently not. The gateway's cache-control: no-cache propagates through.

Local dev: no Caddy

Local install (hivecast install --home /tmp/matrix-home) starts the gateway on plain HTTP. Browser hits http://127.0.0.1:3100/... directly. No TLS, no Caddy. The gateway's own /nats-ws handler upgrades and proxies to the embedded NATS WS port.

This works because localhost-to-localhost traffic doesn't need TLS, and because the NATS protocol allows unauthenticated WebSocket connections in local-mode auth (auth.mode: local-client).

Restart vs. reload

Caddy supports zero-downtime config reload:

bash
# Reload Caddyfile without dropping connections
sudo systemctl reload caddy

# Full restart (drops connections briefly)
sudo systemctl restart caddy

The gateway is a separate service; Caddy reloads do not touch it. To restart the gateway:

bash
hivecast stop && hivecast start
# or
sudo systemctl restart hivecast-host.service

Common issues

SymptomLikely causeFix
502 on /apps/...Gateway is downhivecast status; restart
502 on /nats-wsNATS is downhivecast status; restart
TLS certificate errorsCaddy can't renew (DNS or rate-limit)journalctl -u caddy; check rate-limit / DNS
Wrong host servesCaddyfile site block missing or wrongReload Caddyfile after fix
/api/host/stop callable from internetCaddyfile not gating control endpointsAdd a Caddy handle /api/host/* { ... auth ... } block — or rely on local-mode trust

See also

Source: projects/deploy-cloud/Caddyfile.bare. Local-mode dev does not use Caddy; the gateway listens directly.