Reverse proxy
When you self-host Restura, put it behind your reverse proxy of choice for TLS termination, auth (via Cloudflare Access, OIDC, etc.), and rate limiting.
The container needs the proxy to:
- Forward
/api/wsas a WebSocket upgrade (don’t terminate the upgrade). - Pass through the
X-Worker-Tokenheader or theCf-Access-Authenticated-User-Emailheader from your IdP. - Not strip the
Content-Encodingheader — streaming responses (SSE, chunked) depend on it.
Example configs
Section titled “Example configs”server { listen 443 ssl http2; server_name restura.example.com;
ssl_certificate /etc/ssl/restura.crt; ssl_certificate_key /etc/ssl/restura.key;
location / { proxy_pass http://restura:3000; proxy_http_version 1.1; 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;
# WebSocket upgrade proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection;
# Streaming endpoints proxy_buffering off; proxy_read_timeout 1h; }}restura.example.com { reverse_proxy restura:3000 { transport http { versions h1 h2c keepalive 30s } header_up Host {host} header_up X-Real-IP {remote_host} }}Caddy handles WebSocket upgrades and SSE buffering correctly out of the box.
services: restura: image: ghcr.io/dipjyotimetia/restura:latest labels: - traefik.enable=true - traefik.http.routers.restura.rule=Host(`restura.example.com`) - traefik.http.routers.restura.entrypoints=websecure - traefik.http.routers.restura.tls=true - traefik.http.services.restura.loadbalancer.server.port=3000 environment: WORKER_PROXY_TOKEN: ${WORKER_PROXY_TOKEN:?required}With Cloudflare Access (or any header-injecting IdP)
Section titled “With Cloudflare Access (or any header-injecting IdP)”- Put Cloudflare Access in front of
restura.example.comand configure your identity provider. - In the Restura container, set
REQUIRE_CF_ACCESS=true. - The server reads the user identity from the
Cf-Access-Authenticated-User-Emailheader (or your IdP’s equivalent) and skips the shared-token check.
Make sure the header your IdP injects matches what the server reads — see Self-hosting / Docker for the env var names.
Multi-replica notes
Section titled “Multi-replica notes”WebSocket tickets are per-replica in-memory (v1 constraint). Either use sticky routing on /api/ws-ticket and /api/ws paths, or stick to a single replica.
Per-replica in-memory rate limiting means high-traffic deployments should put a rate limiter in the reverse proxy too.
Related
Section titled “Related”- Docker — env vars and the single-image setup.
- Security model.