A reverse proxy sits in front of your application servers, handling incoming requests and forwarding them to the appropriate backend. Nginx is the most popular choice for reverse proxying due to its performance, reliability, and flexibility.
Why Use a Reverse Proxy?
- SSL/TLS termination — Handle HTTPS at the proxy, pass HTTP to backends
- Load balancing — Distribute traffic across multiple servers
- Caching — Cache responses to reduce backend load
- Security — Hide backend server details, add headers, rate limit
- WebSocket support — Proxy WebSocket connections
Basic Reverse Proxy Configuration
# /etc/nginx/sites-available/myapp.conf
server {
listen 80;
server_name myapp.example.com;
location / {
proxy_pass http://127.0.0.1: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;
}
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxSSL/TLS Termination
server {
listen 443 ssl http2;
server_name myapp.example.com;
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1: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;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name myapp.example.com;
return 301 https://$server_name$request_uri;
}WebSocket Proxying
location /ws {
proxy_pass http://127.0.0.1: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;
}Load Balancing
upstream backend {
least_conn; # Send to server with fewest connections
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Caching
# Define cache zone
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m max_size=1g inactive=60m;
server {
location / {
proxy_pass http://127.0.0.1:3000;
proxy_cache app_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
}
# Skip cache for dynamic content
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_cache off;
}
}Health Checks and Timeouts
location / {
proxy_pass http://127.0.0.1:3000;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_next_upstream error timeout http_502 http_503;
}