0 Try the Demo

Reverse Proxy Setup

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

To put Arcane behind a reverse proxy such as Nginx, Apache, or Traefik, the proxy has to forward WebSocket connections, which Arcane uses for live updates, and pass the real client IP so Arcane can apply login rate limits per client. You also need to set TRUSTED_PROXIES so Arcane believes the forwarded IP, and make sure the proxy’s header-size limit isn’t too small for Arcane’s session cookies.

Set APP_URL to the public URL users open, such as https://arcane.example.com, without the internal :3552 port.

Configure your proxy

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

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 lines that enable WebSockets are:

  • proxy_http_version 1.1;
  • proxy_set_header Upgrade $http_upgrade;
  • proxy_set_header Connection "upgrade";
  • proxy_cache_bypass $http_upgrade;

This config forwards the client IP in X-Forwarded-For and X-Real-IP. Set TRUSTED_PROXIES so Arcane trusts it, as described below.

Trust the proxy with TRUSTED_PROXIES

Arcane rate-limits authentication endpoints (login, token refresh, OIDC callback) per client IP. Behind a reverse proxy, every request appears to come from the proxy’s IP. That weakens brute-force protection and can lock out legitimate users who share the proxy.

Set TRUSTED_PROXIES on the Arcane container to your proxy’s address, such as TRUSTED_PROXIES=10.0.0.5, or to a CIDR range, such as the Docker network that the proxy and Arcane share (TRUSTED_PROXIES=172.18.0.0/16). Arcane then reads the real client IP from X-Forwarded-For for requests coming from those addresses. Docker’s default address pools hand out subnets from 172.17.0.0–172.31.0.0 and then 192.168.0.0/16, and your daemon may be configured differently, so look up the network’s actual subnet:

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

TRUSTED_PROXIES accepts a comma-separated list of IPs or CIDR ranges. Only requests whose direct peer is in this list have their forwarded headers trusted, so an untrusted client cannot spoof its IP via X-Forwarded-For. See the Environment Variables reference for all configuration options.

Note

If you bind Arcane to a loopback address with LISTEN, such as LISTEN=127.0.0.1 for a proxy on the same host, Arcane trusts loopback proxies (127.0.0.0/8, ::1/128) automatically and you don’t need TRUSTED_PROXIES. This only works with literal loopback IPs, not hostnames such as localhost.

Allow large enough headers

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

Other proxies

websocket.org has WebSocket setup guides for other proxies and load balancers: