HTTPS and reverse proxies¶
Use a dedicated hostname with Relay at /. Choose Caddy or Nginx to terminate TLS; the examples below run the proxy and Relay on the same host. Both use the same Relay configuration.
Relay configuration¶
In the active config.yaml:
host: 127.0.0.1
port: 9000
reverseProxy: true
trustedProxies:
- 127.0.0.1/32
https:
enable: false
Restart Relay after changing listener or trust settings. reverseProxy enables forwarded scheme/address handling only for peers matching trustedProxies; entries must be CIDRs, and the list cannot be empty when enabled. Never trust every address merely to make forwarded headers work.
For a container behind host Caddy or Nginx, publish 127.0.0.1:9000:9000, leave Relay listening on the container interface, and trust the actual source address/CIDR of that proxy connection instead of assuming it is loopback. For a separate proxy container, use a private Docker network and restrict direct access to Relay.
Caddy configuration¶
Point your hostname's DNS records at the server and allow inbound TCP ports 80 and 443. In /etc/caddy/Caddyfile, replace chat.example.com with your Relay hostname:
chat.example.com {
reverse_proxy 127.0.0.1:9000
}
Caddy's automatic HTTPS obtains and renews certificates and redirects HTTP to HTTPS. Keep its data directory persistent so certificate state survives restarts.
The reverse proxy handles WebSocket upgrades and forwarded headers automatically; no separate /ws route or manual upgrade headers are needed. This assumes Caddy receives client traffic directly. If a CDN or another proxy sits in front, configure Caddy's trusted proxies for that deployment as well as Relay's; do not trust arbitrary incoming forwarded headers.
Validate before reloading (adjust the configuration path if needed):
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile
Relay still enforces its upload limit. If another proxy imposes a request-body limit, allow multipart overhead above Relay's configured file limit.
Nginx configuration¶
Obtain a certificate for your hostname before enabling this HTTPS server block.
Place the following in a file included inside Nginx's http context (for example /etc/nginx/conf.d/relay.conf). Replace chat.example.com and certificate paths. The 12 MiB request limit allows multipart overhead above Relay's default 10 MiB file limit when uploads are enabled.
map $http_upgrade $relay_connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name chat.example.com;
return 301 https://chat.example.com$request_uri;
}
server {
listen 443 ssl;
server_name chat.example.com;
ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 12m;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $relay_connection_upgrade;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
Nginx requires explicit forwarding of WebSocket upgrade headers. The timeout above extends its idle-read window. See the official Nginx WebSocket proxying guide. This single-proxy example overwrites the client-supplied forwarded address; a multi-proxy deployment needs an explicitly designed trust chain.
Verify the deployment¶
- For Caddy, validate and reload as shown above. For Nginx, run
nginx -t, then reload Nginx only after it succeeds. - Open
https://chat.example.com/and check the certificate and HTTP-to-HTTPS redirect. - In browser developer tools, check that
/wsupgrades with status 101, then sign in and leave the connection idle before sending another message. - Confirm sessions show the expected client address, and that direct access to port 9000 from an untrusted host fails.
- If enabled, test a small upload and its returned URL. Set
fileUpload.baseUrlonly when files deliberately use another public origin. - For OIDC, register
https://chat.example.com/auth/oidc/callback; for security keys, use the intended stable hostname and HTTPS origin.
For failures, see Troubleshooting. These examples were checked against official Caddy and Nginx documentation; a real certificate/proxy deployment was not exercised in the local audit.