Skip to content

HTTPS and reverse proxies

Use a dedicated hostname with Relay at /. This example runs Nginx and Relay on the same host, with TLS terminated by Nginx. Obtain a certificate for your hostname before enabling the HTTPS server block.

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 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.

Nginx configuration

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

  1. Run nginx -t, then reload Nginx only after it succeeds.
  2. Open https://chat.example.com/ and check the certificate and HTTP-to-HTTPS redirect.
  3. In browser developer tools, check that /ws upgrades with status 101, then sign in and leave the connection idle before sending another message.
  4. Confirm sessions show the expected client address, and that direct access to port 9000 from an untrusted host fails.
  5. If enabled, test a small upload and its returned URL. Set fileUpload.baseUrl only when files deliberately use another public origin.
  6. 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. This example was checked against official Nginx documentation; a real certificate/proxy deployment was not exercised in the local audit.