[GH-ISSUE #124] feat(deploy): Proposals and best practices #771

Closed
opened 2026-04-24 17:47:04 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @gustavorps on GitHub (Feb 17, 2026).
Original GitHub issue: https://github.com/reconurge/flowsint/issues/124

Context

When deploying FastAPI behind a reverse proxy (e.g., NGINX, Traefik, Caddy), several issues commonly arise:

  • Incorrect scheme detection (http instead of https)
  • Redirect loops (especially trailing slash redirects)
  • Broken OpenAPI docs URLs
  • Misinterpreted client IP addresses
  • Security header inconsistencies
  • Inconsistent behavior between local and production environments

Reference: Official docs "Behind a Proxy - FastAPI"

Proposals

Disable Automatic Redirect Slashes

Proposal

app = FastAPI(redirect_slashes=False)

Why

FastAPI (via Starlette) automatically redirects:

  • /endpoint/endpoint/
  • or /endpoint//endpoint

Behind a proxy, this can cause:

  • Scheme downgrades (HTTPS → HTTP)
  • Infinite redirect loops
  • Incorrect Location headers

Benefits

  • Avoids proxy-related redirect issues
  • Makes routes explicit and predictable
  • Reduces 307/308 unnecessary redirects
  • Cleaner behavior in containerized/proxy environments

Best Practice

Be explicit in route definitions:

@app.get("/users")

and ensure frontend uses exact paths on the clients SDK.

Proper Proxy Header Handling (CRITICAL)

Disabling redirect slashes alone is not enough.

Ensure proxy headers are trusted:

Run with:

fastapi run app.main:app --proxy-headers

or (if using uvicorn directly):

uvicorn app.main:app --proxy-headers --forwarded-allow-ips="*"

Why

Without this:

  • request.url.scheme may be wrong
  • Generated OpenAPI docs may use http
  • Redirects may downgrade HTTPS

This is mandatory behind TLS termination.

Adopt fastapi run Over uvicorn

Proposal

Standardize on:

fastapi run app.main:app

over:

uvicorn app.main:app

Why

fastapi run:

  • Is the officially recommended entrypoint
  • Provides better defaults
  • Handles reload and production flags more clearly
  • Reduces config drift between environments

Recommendation

  • Use fastapi dev for development
  • Use fastapi run for production
  • Avoid mixing CLI strategies across environments

Set Proper Referrer Policy

Proposal

Add response header:

Referrer-Policy: strict-origin-when-cross-origin

(or if you truly need same-origin only)

Referrer-Policy: same-origin

strict-origin-when-cross-origin

Why

It:

  • Sends full referrer for same-origin
  • Sends only origin for HTTPS cross-origin
  • Sends nothing for HTTP downgrade
  • Is modern browser default
  • Protects sensitive paths

Reverse Proxy Configuration

NGINX Example

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;

Without these:

  • HTTPS detection fails
  • Client IP is lost
  • URL generation breaks

Set root_path If Behind Subpath

If your app is served at: https://example.com/api

Use:

API_ROOT_PATH = os.environ.get("LLM_PROVIDER", "/api")
app = FastAPI(root_path=API_ROOT_PATH)

Or configure via proxy properly.

Otherwise:

  • OpenAPI docs break
  • Swagger UI fails
  • Static URLs mismatch

Recommended Deployment Baseline

FastAPI App

app = FastAPI(
    redirect_slashes=False,
)

Run Command

fastapi run app.main:app --proxy-headers

Proxy Must Set

  • X-Forwarded-Proto
  • X-Forwarded-For
  • Host

Security Headers

  • Referrer-Policy
  • X-Content-Type-Options
  • X-Frame-Options
  • Strict-Transport-Security (if HTTPS)
Originally created by @gustavorps on GitHub (Feb 17, 2026). Original GitHub issue: https://github.com/reconurge/flowsint/issues/124 Context ------- When deploying FastAPI behind a reverse proxy (e.g., NGINX, Traefik, Caddy), several issues commonly arise: - Incorrect scheme detection (`http` instead of `https`) - Redirect loops (especially trailing slash redirects) - Broken OpenAPI docs URLs - Misinterpreted client IP addresses - Security header inconsistencies - Inconsistent behavior between local and production environments Reference: Official docs "[Behind a Proxy - FastAPI](https://fastapi.tiangolo.com/advanced/behind-a-proxy/)" Proposals ========= Disable Automatic Redirect Slashes -------------------------------------- ### Proposal ``` app = FastAPI(redirect_slashes=False) ``` ### Why FastAPI (via Starlette) automatically redirects: - `/endpoint` → `/endpoint/` - or `/endpoint/` → `/endpoint` Behind a proxy, this can cause: - Scheme downgrades (HTTPS → HTTP) - Infinite redirect loops - Incorrect Location headers ### Benefits - Avoids proxy-related redirect issues - Makes routes explicit and predictable - Reduces 307/308 unnecessary redirects - Cleaner behavior in containerized/proxy environments ### Best Practice Be explicit in route definitions: ``` @app.get("/users") ``` and ensure frontend uses exact paths on the clients SDK. Proper Proxy Header Handling (CRITICAL) ------------------------------------------- Disabling redirect slashes alone is not enough. Ensure proxy headers are trusted: ### Run with: ``` fastapi run app.main:app --proxy-headers ``` or (if using uvicorn directly): ``` uvicorn app.main:app --proxy-headers --forwarded-allow-ips="*" ``` ### Why Without this: - `request.url.scheme` may be wrong - Generated OpenAPI docs may use `http` - Redirects may downgrade HTTPS This is **mandatory** behind TLS termination. Adopt `fastapi run` Over `uvicorn` -------------------------------------- ### Proposal Standardize on: ``` fastapi run app.main:app ``` over: ``` uvicorn app.main:app ``` ### Why `fastapi run`: - Is the officially recommended entrypoint - Provides better defaults - Handles reload and production flags more clearly - Reduces config drift between environments ### Recommendation - Use `fastapi dev` for development - Use `fastapi run` for production - Avoid mixing CLI strategies across environments Set Proper Referrer Policy ------------------------------ ### Proposal Add response header: ``` Referrer-Policy: strict-origin-when-cross-origin ``` (or if you truly need same-origin only) ``` Referrer-Policy: same-origin ``` ### Recommended Value `strict-origin-when-cross-origin` ### Why It: - Sends full referrer for same-origin - Sends only origin for HTTPS cross-origin - Sends nothing for HTTP downgrade - Is modern browser default - Protects sensitive paths Reverse Proxy Configuration -------------------------------------- ### NGINX Example ``` proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; ``` Without these: - HTTPS detection fails - Client IP is lost - URL generation breaks Set `root_path` If Behind Subpath ------------------------------------- If your app is served at: `https://example.com/api` Use: ``` API_ROOT_PATH = os.environ.get("LLM_PROVIDER", "/api") app = FastAPI(root_path=API_ROOT_PATH) ``` Or configure via proxy properly. Otherwise: - OpenAPI docs break - Swagger UI fails - Static URLs mismatch Recommended Deployment Baseline =============================== ### FastAPI App ``` app = FastAPI( redirect_slashes=False, ) ``` ### Run Command ``` fastapi run app.main:app --proxy-headers ``` ### Proxy Must Set - `X-Forwarded-Proto` - `X-Forwarded-For` - `Host` ### Security Headers - Referrer-Policy - X-Content-Type-Options - X-Frame-Options - Strict-Transport-Security (if HTTPS)
Author
Owner

@dextmorgn commented on GitHub (Feb 23, 2026):

Hey @gustavorps,

Thanks a lot for your work. I'll spend some time in the next day to review your PR.

I'll let you know :)

<!-- gh-comment-id:3943653169 --> @dextmorgn commented on GitHub (Feb 23, 2026): Hey @gustavorps, Thanks a lot for your work. I'll spend some time in the next day to review your PR. I'll let you know :)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/flowsint#771