Nginx & Traefik¶
A reverse proxy in front of FasterAPI handles TLS termination, load balancing, rate limiting, and static file serving — letting uvicorn focus on Python.
Nginx¶
Basic configuration¶
# /etc/nginx/conf.d/fasterapi.conf
upstream fasterapi {
server 127.0.0.1:8000;
server 127.0.0.1:8001; # optional second worker
keepalive 16;
}
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
location / {
proxy_pass http://fasterapi;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
# SSE — disable buffering
location /events {
proxy_pass http://fasterapi;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
}
# WebSocket
location /ws {
proxy_pass http://fasterapi;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
TLS with Certbot (Let's Encrypt)¶
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d api.example.com
# Auto-renewal
sudo systemctl enable certbot.timer
Rate limiting¶
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location / {
limit_req zone=api burst=20 nodelay;
proxy_pass http://fasterapi;
}
}
}
Gzip (if not using FasterAPI's GZipMiddleware)¶
Traefik¶
Traefik is a cloud-native reverse proxy that auto-discovers services via Docker labels or Kubernetes annotations.
docker-compose with Traefik¶
# docker-compose.yml
version: "3.9"
services:
traefik:
image: traefik:v3
command:
- "--api.insecure=false"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.httpchallenge=true"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.le.acme.email=admin@example.com"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
api:
image: my-fasterapi-app
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=le"
- "traefik.http.services.api.loadbalancer.server.port=8000"
# Redirect HTTP → HTTPS
- "traefik.http.routers.api-http.rule=Host(`api.example.com`)"
- "traefik.http.routers.api-http.entrypoints=web"
- "traefik.http.routers.api-http.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
Rate limiting with Traefik middleware¶
labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50"
- "traefik.http.routers.api.middlewares=ratelimit"
Static Traefik config (traefik.yml)¶
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
certificatesResolvers:
le:
acme:
email: admin@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
providers:
docker:
exposedByDefault: false
FasterAPI root path¶
Tell FasterAPI the URL prefix used by the proxy (affects Swagger UI server URL):
Or via middleware — see Behind a Proxy.
Next steps¶
- Kubernetes — scale beyond single-host deployments.
- Cloud Services — managed proxies on AWS / GCP / Azure.