Reverse proxy setup
Run rChat behind Caddy, nginx, or HAProxy. The reverse proxy terminates TLS 1.3 and forwards plain WebSocket traffic to rChat on a local port.
Why use a reverse proxy
Section titled “Why use a reverse proxy”- Automatic HTTPS — Caddy and certbot handle certificates for you
- Multiple services — Run rChat alongside a website or other apps on the same host
- Load balancing — Distribute connections across multiple rChat backends
- Security hardening — WAF rules, rate limiting, and access controls at the edge
Server configuration
Section titled “Server configuration”When running behind a reverse proxy, disable TLS in rChat and bind to localhost:
[server]bind_addr = "127.0.0.1:8443"The proxy listens on port 443 and forwards to 127.0.0.1:8443.
Caddy is the easiest option — it handles TLS automatically via Let’s Encrypt.
Install
Section titled “Install”sudo apt install caddyConfiguration
Section titled “Configuration”Create /etc/caddy/Caddyfile:
chat.example.com { tls { protocols tls1.3 }
reverse_proxy 127.0.0.1:8443}The protocols tls1.3 directive ensures only TLS 1.3 is offered to clients.
Reload
Section titled “Reload”sudo systemctl reload caddyInstall
Section titled “Install”sudo apt install nginxConfiguration
Section titled “Configuration”Create /etc/nginx/sites-available/rchat:
upstream rchat_backend { server 127.0.0.1:8443; keepalive 1000;}
map $http_upgrade $connection_upgrade { default upgrade; '' close;}
server { listen 443 ssl http2; 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.3; ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256; ssl_prefer_server_ciphers off;
location / { proxy_pass http://rchat_backend; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400; proxy_send_timeout 86400; }}
# Redirect HTTP to HTTPSserver { listen 80; server_name chat.example.com; return 301 https://$server_name$request_uri;}Enable the site:
sudo ln -s /etc/nginx/sites-available/rchat /etc/nginx/sites-enabled/rchatsudo nginx -tsudo systemctl reload nginxLet’s Encrypt with certbot
Section titled “Let’s Encrypt with certbot”sudo apt install certbot python3-certbot-nginxsudo certbot --nginx -d chat.example.comHAProxy
Section titled “HAProxy”Install
Section titled “Install”sudo apt install haproxyConfiguration
Section titled “Configuration”Edit /etc/haproxy/haproxy.cfg:
global maxconn 100000 ssl-default-bind-options ssl-min-ver TLSv1.3 ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
defaults mode http timeout connect 5s timeout client 300s timeout server 300s option httpchk
frontend rchat_frontend bind *:443 ssl crt /etc/letsencrypt/live/chat.example.com/fullchain.pem alpn h2,http/1.1
# Enforce TLS 1.3 only bind *:443 ssl crt /etc/letsencrypt/live/chat.example.com/fullchain.pem ssl-min-ver TLSv1.3
# WebSocket upgrade acl is_websocket hdr(Upgrade) -i websocket acl is_connection_upgrade hdr_beg(Connection) -i upgrade
use_backend rchat_backend
backend rchat_backend server rchat_local 127.0.0.1:8443 check
# WebSocket support option httpchk GET /
# Redirect HTTP to HTTPSfrontend http_redirect bind *:80 redirect scheme https code 301 if !{ ssl_fc }Reload:
sudo haproxy -c -f /etc/haproxy/haproxy.cfgsudo systemctl reload haproxyWebSocket headers
Section titled “WebSocket headers”All three proxies must pass these headers for WebSocket upgrades to work:
| Header | Value | Purpose |
|---|---|---|
Upgrade | websocket | Initiates WebSocket upgrade |
Connection | upgrade | Maintains upgrade connection |
Host | original host | Required for virtual hosting |
X-Forwarded-For | client IP | Preserves client address |
X-Forwarded-Proto | https | Tells rChat the request was secure |
Health checks
Section titled “Health checks”All proxies can check whether rChat is healthy before sending traffic:
curl -f http://127.0.0.1:8443/healthIf rChat returns HTTP 200, it is ready. If it returns anything else or refuses the connection, the proxy should try another backend or return a 503.