Skip to content

feat(deploy): Proposals and best practices #124

@gustavorps

Description

@gustavorps

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

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions