Skip to content

Reverse Proxy Setup

Put Arcane behind Nginx, Apache, or Traefik with WebSockets and the real client IP.

To run Arcane behind Nginx, Apache, Traefik, or another reverse proxy, the proxy must forward WebSockets (used for live updates) and the real client IP (for per-client login rate limits). Set ARCANE_TRUSTED_PROXIES so Arcane believes that IP, and keep the proxy’s header-size limit big enough for session cookies. Set ARCANE_APP_URL to the public URL users open, such as https://arcane.example.com, without the internal :3552 port.

This example enables WebSockets. Replace the domain name and certificate paths with your own:

server {
listen 80;
server_name arcane.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/arcane.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/arcane.yourdomain.com/privkey.pem;
server_name arcane.yourdomain.com;
location / {
add_header X-Robots-Tag "noindex, nofollow";
proxy_pass http://127.0.0.1:3552;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache_bypass $http_upgrade;
}
access_log /var/log/nginx/arcane-access.log;
error_log /var/log/nginx/arcane-error.log debug;
}

The proxy_http_version 1.1;, Upgrade, Connection "upgrade", and proxy_cache_bypass lines enable WebSockets. The client IP goes in X-Forwarded-For and X-Real-IP; set ARCANE_TRUSTED_PROXIES so Arcane trusts it.

Trust the proxy with ARCANE_TRUSTED_PROXIES

Section titled “Trust the proxy with ARCANE_TRUSTED_PROXIES”

Set ARCANE_TRUSTED_PROXIES on the Arcane container to your proxy’s address (ARCANE_TRUSTED_PROXIES=10.0.0.5/32) or a wider CIDR range, such as the shared Docker network (ARCANE_TRUSTED_PROXIES=172.18.0.0/16). Arcane then reads the real client IP from X-Forwarded-For for requests from those addresses. Without it, auth endpoints (login, token refresh, OIDC callback) rate-limit by the proxy’s IP, weakening brute-force protection and locking out users who share the proxy.

Docker’s default pools use 172.17.0.0–172.31.0.0, then 192.168.0.0/16, and your daemon may differ, so look up the actual subnet:

Terminal window
docker network inspect <network> --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'

ARCANE_TRUSTED_PROXIES accepts a comma-separated list of CIDR ranges. Write a single address as /32 for IPv4 or /128 for IPv6; Arcane logs a warning and ignores entries without a prefix length. Forwarded headers are trusted only when the direct peer is listed, so untrusted clients can’t spoof X-Forwarded-For. Loopback and private addresses aren’t trusted unless listed. See Environment Variables for all options.

If sign-in fails with oversized-header errors, raise your proxy’s request header limit, such as large_client_header_buffers in Nginx. Current sessions fit in one cookie, but sessions from older releases carry larger ML-DSA-87 (post-quantum) tokens split across up to four cookies until they refresh.

websocket.org has WebSocket guides for other proxies and load balancers: Nginx, Amazon ALB, Cloudflare, and Kubernetes.