Skip to main content
The web app reads five variables, all at runtime. Nothing about the API address is baked into the image, so the same image can point at a different API by changing an environment variable and restarting.

Variables

Compose sets API_INTERNAL_URL to http://api:4000, which resolves on the Docker network rather than on your machine.

How the proxy works

The browser only ever talks to the web origin. A call to /api/backend/apps is handled by a Next.js route handler, which forwards the request, the session cookie and any bearer header to API_INTERNAL_URL and streams the answer back. Two consequences follow from that, and both are the reason it works this way.
  • The browser never makes a cross origin request, so no CORS headers are involved on this path at all. The API still keeps its own allowlist for callers that do reach it directly. See Hosting.
  • The API never needs to be published. In the Compose stack it stays on a private network and only host port 3001 is exposed to port 3000 in the web container.

What the proxy does with the client address

The proxy never passes a caller supplied X-Forwarded-For or X-Real-IP through to the API, because a caller can write either one and the API keys authentication throttling on what it reads there. Instead it sends exactly one address, the one TRUST_PROXY says it can trust, taken that many entries back from the right of the incoming header. At 0 it sends no address at all, so the API sees the web container as the client and throttles every browser client as one connection. That is blunt but safe, and it is why the documented deployment sets TRUST_PROXY=1 on both apps. See How asobeast works.

What a timeout looks like

When the API does not start answering within API_PROXY_TIMEOUT_MS, the proxy returns a 504 in the standard error envelope rather than leaving the request open. Once the API has started answering, the response streams until it ends, so a long download or an MCP event stream is never cut by this bound. Raise the value if you run a slow upstream, but a proxy timeout usually points at a saturated API rather than at a bound that is too tight.

Configuration reference

Every API variable with its default.

Hosting behind TLS and a reverse proxy

What to set before exposing host port 3001.
Last modified on September 16, 2026