The limits read the leftmost X-Forwarded-For entry, which the client writes, and the LAN nginx appended to it. The address now comes from uvicorn's proxy-headers middleware (rightmost hop not in FORWARDED_ALLOW_IPS), applied in the app too so tunnel-replayed calls resolve the same way; nginx sets the header to $remote_addr and the compose backend trusts the Docker networks. /users/signup gets a per-address limit of 10 an hour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
36 lines
1.5 KiB
Plaintext
36 lines
1.5 KiB
Plaintext
# Serves the API from the same origin as the SPA, replacing the 404 stub the
|
|
# image ships. Traefik routes on the Host header, which a bare IP never
|
|
# matches, so this is what makes http://<host-ip>:<port> a complete app: the
|
|
# client asks for /api/v1/... on whatever origin served it, and never needs a
|
|
# resolvable api.${DOMAIN} or a CORS allowance.
|
|
|
|
location /api {
|
|
# Docker's embedded DNS, re-resolved: nginx otherwise pins the backend's
|
|
# address at startup and 502s for good once that container is recreated.
|
|
resolver 127.0.0.11 valid=10s ipv6=off;
|
|
set $backend_upstream http://backend:8000;
|
|
proxy_pass $backend_upstream$request_uri;
|
|
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
# Replaced, not appended to: whatever the client sent would otherwise sit
|
|
# in front of the one hop the backend believes, and anything reading the
|
|
# header naively would take it for the caller.
|
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
# The flow websocket (/api/v1/flows/ws) upgrades through here; passing the
|
|
# client's own Connection header covers both it and ordinary requests.
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection $http_connection;
|
|
# A live socket outlives the 60s default by design.
|
|
proxy_read_timeout 1d;
|
|
}
|
|
|
|
# Unchanged from the stub: the API docs stay off the frontend's origin.
|
|
location /docs {
|
|
return 404;
|
|
}
|
|
location /redoc {
|
|
return 404;
|
|
}
|