Reverse Proxy (Nginx, Caddy, Traefik)
An intermediary server architectural layer that accepts external internet traffic (ports 80/443), performs SSL/TLS termination, compression (Brotli/Gzip), static caching, and securely routes requests to internal applications.
1. Concept Overview & Systemic Problem
Beginner developers often attempt to expose their server directly to the internet by running npm start or uvicorn main:app on port 80. Such a configuration is a gross violation of production architectural standards:
- Security: Listening on ports 80 and 443 requires the process to run with superuser privileges (
root). Any vulnerability in an npm dependency gives an attacker full control over the operating system. - Slowloris Attacks: A client with a poor connection that sends one byte every 10 seconds can block the Node.js or Python event loop, paralyzing service for other users.
- Inefficient Static Serving: Serving images, fonts, and JS files through application worker threads consumes resources that should be allocated to business logic.
- Fragility of SSL: The need to configure encryption within the application code necessitates service restarts with every certificate update.
Reverse Proxy serves as the secure gateway to your infrastructure. It accepts external internet traffic, decrypts HTTPS connections, compresses data, caches static files, and transparently forwards clean internal traffic to the local ports of your isolated applications (127.0.0.1:3000).
2. Architectural Taxonomy & Mental Model
The architectural landscape of reverse proxies is classified by configuration paradigms:
┌─────────────────────────────────────────────────────────────┐
│ REVERSE PROXY COMPARISON MATRIX │
├─────────────────────────────────────────────────────────────┤
│ 1. Nginx: Event-driven C architecture (epoll / kqueue) │
│ • Maximum raw performance, minimal memory usage │
│ • Requires external Certbot for Let's Encrypt │
├─────────────────────────────────────────────────────────────┤
│ 2. Caddy: Memory-safe Go Server with Auto-HTTPS (ACME) │
│ • Native automatic acquisition and rotation of SSL │
│ • Modern concise syntax (Caddyfile) │
│ • Native support for HTTP/3 (QUIC) out of the box │
├─────────────────────────────────────────────────────────────┤
│ 3. Traefik: Cloud-Native Container Router │
│ • Dynamic service discovery via Docker Labels │
│ • Ideal for PaaS automation (Coolify, Kubernetes) │
└─────────────────────────────────────────────────────────────┘
- TLS/SSL Termination:
- The proxy handles resource-intensive cryptographic operations (TLS Handshake), relieving the backend from load.
- Virtual Hosting & Routing:
- Allows hosting multiple projects on a single server with one IP address:
gotburnout.com➔ local container on port 3000 (Next.js).api.gotburnout.com➔ local container on port 8000 (FastAPI).n8n.gotburnout.com➔ internal port 5678 (n8n).
- Allows hosting multiple projects on a single server with one IP address:
- WebSockets & SSE Proxying:
- Special handling of
Upgradeheaders and disabling buffering to support full-duplex connections and token streaming from LLMs.
- Special handling of
- On-the-fly Compression (Gzip & Brotli):
- Compresses text resources, reducing the volume of traffic sent to the client by 60–80%.
3. Technical Pipeline & Internal Mechanics
The lifecycle of a client request passing through a reverse proxy:
- Establishing a Secure Connection (TLS Handshake):
The client initiates a connection on port
443. Caddy or Nginx negotiates TLS 1.3, sends a valid domain certificate, and encrypts the channel. - Header and SNI Analysis (Server Name Indication):
The proxy reads the
Host: gotburnout.comheader and the URL path/api/v1/chat. - Proxy Header Normalization:
The proxy adds service headers so the internal application knows the real client IP address:
X-Real-IP: 203.0.113.195 X-Forwarded-For: 203.0.113.195, 10.0.0.1 X-Forwarded-Proto: https - Upstream Dispatch:
The request is redirected to the local socket
http://127.0.0.1:3000through a pre-opened connection pool. - Receiving and Forwarding the Response to the Client:
- If a static file is returned — the proxy caches it.
- If it is token streaming (SSE) — the proxy immediately streams each chunk to the client without buffering.
4. Production Engineering Scenarios
01. Configuring Caddy for Next.js and AI Streaming in 10 Lines
A Caddyfile for production with automatic HTTPS and streaming support:
gotburnout.com {
encode zstd gzip
# Proxying the application
reverse_proxy 127.0.0.1:3000 {
# Disabling buffering for instant LLM token streaming
flush_interval -1
}
# Caching Next.js static files for 1 year
@static path /_next/static/*
header @static Cache-Control "public, max-age=31536000, immutable"
}
02. Nginx Configuration for Server-Sent Events (SSE)
Preventing streaming hangs in Nginx:
location /api/generate {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Connection '';
# Critical directives for AI streaming:
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
proxy_read_timeout 600s;
}
03. Routing a Multi-Service Platform on a Single Server
Organizing access to internal tools:
- Caddy distributes traffic: requests to
ai.company.internalare routed to the Ollama container, whilemetrics.company.internalgoes to the Grafana dashboard, securing access with basic authorization (basic_auth).
5. Pitfalls, Common Mistakes & Security
- Streaming hangs due to buffering: The most common mistake in Nginx is having
proxy_bufferingenabled by default. Users see a blank screen for 30 seconds, after which the entire generated article appears at once. - IP Spoofing through unreliable headers: If your backend naively reads
req.headers['x-forwarded-for']without verifying that the request came from your local proxy, an attacker can spoof any IP address to bypass rate limits. - Host Header Injection: If the Nginx configuration has a default block (
default_server) that forwards traffic without checking the host name, an attacker can manipulate password reset links through a forgedHostheader. - Forgotten timeouts for long AI requests: The standard timeout for waiting for a response from the backend is 60 seconds (
proxy_read_timeout 60s). If a complex reasoning model takes 90 seconds, the proxy will return a504 Gateway Timeoutto the client. Increase the timeout for AI routes.
FAQ: Reverse Proxy (Nginx, Caddy, Traefik)
Related terms
Coolify (Self-Hosted PaaS)
An open-source infrastructure management platform (Self-Hosted PaaS, an alternative to Vercel, Heroku, and Render) that automates application deployment from Git, SSL certificate generation, database management, and backups on your own VPS.
Zero-Downtime Deployment
A methodology and engineering mechanisms for updating production services without interrupting user service, breaking existing TCP connections, or generating HTTP errors 502/503.
Rate Limiting (Request Frequency Limitation and API Protection)
A systemic mechanism for controlling the intensity of incoming and outgoing traffic (Token Bucket, Sliding Window) to protect the backend from resource exhaustion, brute force attacks, Layer 7 DDoS, and financial overdraft on AI endpoints.
VPS Hosting
A model for providing isolated computing resources via a hardware hypervisor (KVM), offering full root access to a Linux operating system for deploying autonomous systems.