Every time you deploy something behind Nginx, you end up googling the same config. Here it is, once and for all.
The Config
Save as /etc/nginx/sites-available/myapp:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
# SSL (managed by certbot or your own certs)
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
gzip_min_length 1000;
# Proxy to your app
location / {
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_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_cache_bypass $http_upgrade;
}
# Static files (if served by Nginx)
location /static/ {
alias /var/www/myapp/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Whatβs included
- HTTP β HTTPS redirect β all traffic forced to SSL
- HTTP/2 β faster page loads, multiplexed connections
- Security headers β XSS protection, clickjacking prevention, HSTS
- Gzip compression β smaller responses, faster loads
- WebSocket support β the
UpgradeandConnectionheaders handle WS connections - Proxy headers β your app sees the real client IP, not 127.0.0.1
- Static file caching β 30-day cache with immutable flag
Setup steps
# Enable the site
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
# Test config
sudo nginx -t
# Reload
sudo systemctl reload nginx
# Get SSL cert (if you don't have one)
sudo certbot --nginx -d yourdomain.com
Common tweaks
Rate limiting:
# Add to http block in /etc/nginx/nginx.conf
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# Add to location block
limit_req zone=api burst=20 nodelay;
Increase upload size:
client_max_body_size 50M;
Multiple apps on different paths:
location /api/ {
proxy_pass http://127.0.0.1:4000/;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
Replace yourdomain.com with your domain, 3000 with your appβs port, and youβre live.
Related: Nginx Cheat Sheet Β· AI App Deployment Checklist