Nginx as a Reverse Proxy
Configure Nginx as a reverse proxy — upstream servers, load balancing, SSL termination, WebSocket support, and caching.
What you'll learn
- ✓How a reverse proxy works and why you need one
- ✓Configuring Nginx to proxy to backend services
- ✓Load balancing across multiple servers
- ✓SSL termination and WebSocket proxying
Prerequisites
- •Basic Linux command line skills
- •A running backend service to proxy to
A reverse proxy sits between clients and your backend servers. Nginx is the most popular choice — it handles SSL, load balancing, caching, and static files so your application does not have to.
Basic reverse proxy
server {
listen 80;
server_name myapp.com;
location / {
proxy_pass http://localhost:3000;
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_pass forwards requests to your backend. The proxy_set_header directives pass the original client information through.
Multiple backends with upstream
upstream api_servers {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
server {
listen 80;
server_name api.myapp.com;
location / {
proxy_pass http://api_servers;
}
}
Load balancing methods
# Round robin (default)
upstream backend {
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
# Least connections
upstream backend {
least_conn;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
# IP hash (sticky sessions)
upstream backend {
ip_hash;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
# Weighted
upstream backend {
server 10.0.0.1:8080 weight=3;
server 10.0.0.2:8080 weight=1;
}
SSL termination
Handle HTTPS at Nginx so backends receive plain HTTP.
server {
listen 443 ssl http2;
server_name myapp.com;
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name myapp.com;
return 301 https://$host$request_uri;
}
WebSocket support
location /ws {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
Caching
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;
server {
location /api {
proxy_pass http://api_servers;
proxy_cache my_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
}
}
Rate limiting
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://api_servers;
}
}
Serving static files
Let Nginx serve static assets directly — far more efficient than proxying them.
server {
location /static/ {
alias /var/www/myapp/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://localhost:3000;
}
}
Health checks
upstream backend {
server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.3:8080 backup;
}
If a server fails 3 times in 30 seconds, Nginx marks it as down. The backup server activates only when all primary servers are down.
Testing and reloading
nginx -t # Test configuration
sudo nginx -s reload # Reload without downtime
Summary
Nginx as a reverse proxy handles the concerns your application should not — SSL, load balancing, caching, rate limiting, and static file serving. Start with a basic proxy_pass, add SSL with Let’s Encrypt, and layer on caching and load balancing as your traffic grows.
Related articles
- DevOps NGINX as a Reverse Proxy: Configuration That Works
Set up NGINX as a reverse proxy for Node, Python, or container backends with the right headers, timeouts, and TLS configuration for production.
- DevOps Ansible vs Terraform: Configuration vs Infrastructure
Compare Ansible and Terraform for DevOps automation. Learn when to use each tool, how they differ in approach, and how to combine them effectively.
- DevOps Chaos Engineering: Test Your System's Resilience
Learn chaos engineering principles and tools. Run controlled experiments with Chaos Monkey, Litmus, and Gremlin to find weaknesses before they cause real outages.
- DevOps Configuration Management: Ansible, Chef, and Puppet
Compare Ansible, Chef, and Puppet for configuration management. Learn how each tool works with practical examples for server provisioning and application deployment.