Skip to content

Reverse Proxy

Autentico listens on plain HTTP. Always deploy it behind a TLS-terminating reverse proxy in production.

Caddy handles TLS automatically via Let’s Encrypt:

auth.example.com {
reverse_proxy localhost:9999
}

Or with Docker Compose (Autentico on internal network):

auth.example.com {
reverse_proxy autentico:9999
}

If your relying party SPA needs to call the token endpoint from a browser, configure allowed origins via the Admin UI (CORS page) or the cors_allowed_origins runtime setting:

Terminal window
# Via API
curl -X PUT \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"cors_allowed_origins": "https://app.example.com,https://admin.example.com"}' \
https://auth.example.com/admin/api/settings

Use specific origins in production. Set * to allow all origins (development only). Leave empty to disable CORS and handle it at the reverse proxy level instead.

Autentico ignores forwarding headers by default. For nginx or Caddy on the same host, configure and restart Autentico:

AUTENTICO_TRUSTED_PROXIES=127.0.0.1/32,::1/128

For container proxies, use the proxy’s address or a dedicated proxy network as seen by Autentico, rather than loopback. See Docker Compose.

A trusted proxy must append its actual incoming peer to X-Forwarded-For (as nginx’s $proxy_add_x_forwarded_for does above), or replace the header with the verified client address. Autentico walks from right to left and stops at the first untrusted address. A client-supplied leftmost value cannot override that address. Every proxy hop that should be skipped must be configured; the first untrusted intermediate proxy is treated as the client.

Rate limiting, session IPs and audit logs use this resolved address. Without a trusted-proxy setting, all users behind a proxy share its IP and rate-limit budget. X-Real-IP is not used to establish client identity. Only allow the intended proxy to reach the application’s internal port when you configure proxy trust.