# Reverse Proxy

In production, Sentinel typically runs behind a reverse proxy, CDN, API gateway, or load balancer — nginx and Cloudflare are common choices. Getting client IP and header forwarding right matters here, since Sentinel's detection features depend on them.

## Public vs. internal endpoints

Sentinel serves the web dashboard, the full management API, and the widget-facing endpoints from the same origin — but only two need to be reachable from the public internet, since they're called directly by the browser:

- **`/v1/challenge`** (including `/v1/challenge/audio/{token}`) — issues challenges to the `<altcha-widget>`.
- **`/v1/verify`** — verifies the solved challenge the widget submits.

Everything else should be reachable only from your internal network or VPN — the dashboard, `/v1/docs`, and the management API (`/v1/accounts`, `/v1/users`, `/v1/admin/*`, `/v1/security-groups`, and so on). Restrict it at the reverse proxy rather than relying on authentication alone; it keeps credential-stuffing and scanning traffic off the admin surface entirely.

**`/v1/verify/signature`** depends on who calls it: it verifies the server signature from a `POST /v1/verify` payload, and that call is always server-to-server, never from the browser. Keep it internal-only if the services doing that verification all live on your internal network. Expose it publicly only if an external service — a form handler or backend outside your network — needs to call it directly to verify a signature.

## Forwarding the client IP

Sentinel reads the client IP from the standard `X-Forwarded-For` header. Set `X_FORWARDED_FOR_TRUSTED` to your proxy's IP addresses so Sentinel only trusts `X-Forwarded-For` values coming from a proxy you actually control — values from any other source are rejected, preventing a client from simply spoofing the header itself.

```
X_FORWARDED_FOR_TRUSTED=10.0.0.1,10.0.0.2
```

See [ENV Variables](/docs/sentinel/operations/env-variables/#security--access) and [IP Resolvers](/docs/sentinel/integrations/ip-resolvers/).

## Forwarding headers

Forward all client request headers where feasible. At minimum, these feed Sentinel's browser/platform/device detection and shouldn't be stripped by your proxy:

- `Accept`
- `Accept-Language`
- `Sec-CH-UA`
- `Sec-CH-UA-Mobile`
- `Sec-CH-UA-Platform`
- `User-Agent`

Dropping these reduces the accuracy of [Detection Signals](/docs/sentinel/features/detection-signals/) like header entropy and language detection.

## Preserving the response

`/v1/challenge` and `/v1/verify` both return `application/json` — the `<altcha-widget>` parses that response directly, so the proxy must leave it alone on the way back:

- **Forward the `Content-Type` response header as-is, or set it to `application/json` yourself** if your proxy or gateway strips/rewrites it (some do, especially API gateways with a default content-type policy). A missing or wrong `Content-Type` can make the widget — or an intermediate cache/WAF — treat the body as something other than JSON.
- **Return the JSON body byte-for-byte, without modification.** No reformatting, minifying, key reordering, compression that isn't transparently reversed, or WAF/gateway "response sanitization" — any of that can invalidate the signed challenge/verification payload or simply fail to parse. Treat these two endpoints as pass-through, not something to be transformed in flight.
- **Forward Sentinel's own cache-control headers (`Cache-Control`) unmodified** rather than letting the proxy or CDN apply its own caching policy. Every `/v1/challenge` response is single-use and every `/v1/verify` response is specific to one solve — a proxy or edge cache serving either from cache hands out a stale or already-consumed challenge/result, breaking verification for whoever gets the cached copy.

## Related

- **[ENV Variables](/docs/sentinel/operations/env-variables/)** — `X_FORWARDED_FOR_TRUSTED` and other networking variables.
- **[IP Resolvers](/docs/sentinel/integrations/ip-resolvers/)** — configuring how Sentinel resolves the real client IP.
- **[Install with Docker Compose](/docs/sentinel/install/docker-compose/#step-4--set-up-a-reverse-proxy)** — HTTPS termination options for a VPS deployment.
