DevOps
Nginx Production Setup Guide
Configure Nginx for production with SSL/TLS, load balancing, reverse proxy, aggressive caching, rate limiting, and security headers.
What you'll learn
- Install and configure Nginx on Ubuntu 24.04
- Configure SSL/TLS with modern cipher suites
- Set up reverse proxy for Node.js, Python, or PHP applications
- Implement upstream load balancing
- Configure gzip and brotli compression
- Add rate limiting and connection throttling
- Implement security headers and WAF rules
Installation
Bash
1sudo apt update && sudo apt install -y nginx
2sudo systemctl enable --now nginx
3sudo ufw allow 'Nginx Full'
4
5# Verify
6curl -I http://localhost # HTTP 200
7nginx -v # nginx versionSSL/TLS Configuration
NGINX
1# /etc/nginx/conf.d/ssl-params.conf — shared SSL settings
2ssl_protocols TLSv1.3;
3ssl_prefer_server_ciphers off;
4ssl_session_cache shared:SSL:10m;
5ssl_session_timeout 1d;
6ssl_session_tickets off;
7ssl_stapling on;
8ssl_stapling_verify on;
9resolver 8.8.8.8 8.8.4.4 valid=300s;
10resolver_timeout 5s;
11
12# Diffie-Hellman group
13openssl dhparam -out /etc/nginx/dhparam.pem 2048
14ssl_dhparam /etc/nginx/dhparam.pem;Reverse Proxy
NGINX
1# /etc/nginx/sites-available/myapp
2server {
3 listen 80;
4 server_name myapp.example.com;
5 return 301 https://$host$request_uri;
6}
7
8server {
9 listen 443 ssl;
10 http2 on;
11 server_name myapp.example.com;
12
13 ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
14 ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
15 include /etc/nginx/conf.d/ssl-params.conf;
16
17 location / {
18 proxy_pass http://127.0.0.1:3000;
19 proxy_http_version 1.1;
20 proxy_set_header Upgrade $http_upgrade;
21 proxy_set_header Connection 'upgrade';
22 proxy_set_header Host $host;
23 proxy_set_header X-Real-IP $remote_addr;
24 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
25 proxy_set_header X-Forwarded-Proto $scheme;
26 proxy_cache_bypass $http_upgrade;
27 proxy_read_timeout 60s;
28 }
29}Load Balancing
NGINX
1# /etc/nginx/conf.d/upstream.conf
2upstream app_servers {
3 least_conn; # route to least-busy server
4 server 10.0.0.1:3000 weight=3; # primary — 3x traffic
5 server 10.0.0.2:3000 weight=1;
6 server 10.0.0.3:3000 backup; # only used if primaries fail
7 keepalive 32; # persistent connections
8}
9
10server {
11 location / {
12 proxy_pass http://app_servers;
13 }
14}Caching & Compression
NGINX
1# nginx.conf http block
2gzip on;
3gzip_comp_level 6;
4gzip_min_length 1000;
5gzip_types text/plain text/css application/json application/javascript
6 text/xml application/xml application/rss+xml image/svg+xml;
7
8# Proxy cache
9proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m
10 max_size=1g inactive=60m use_temp_path=off;
11
12# Server block
13location /api/ {
14 proxy_pass http://app_servers;
15 proxy_cache app_cache;
16 proxy_cache_key "$scheme$request_method$host$request_uri";
17 proxy_cache_valid 200 5m;
18 proxy_cache_valid 404 1m;
19 add_header X-Cache-Status $upstream_cache_status;
20}
21
22# Static assets with long cache
23location /assets/ {
24 root /var/www/myapp;
25 expires 1y;
26 add_header Cache-Control "public, immutable";
27}Security & Rate Limiting
NGINX
1# Rate limiting zones (http block)
2limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
3limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
4limit_conn_zone $binary_remote_addr zone=addr:10m;
5
6# Apply in location blocks
7location /api/ {
8 limit_req zone=api burst=40 nodelay;
9 limit_conn addr 20;
10 proxy_pass http://app_servers;
11}
12
13location /api/auth/login {
14 limit_req zone=login burst=5;
15 proxy_pass http://app_servers;
16}
17
18# Security headers (server block)
19add_header X-Frame-Options "DENY" always;
20add_header X-Content-Type-Options "nosniff" always;
21add_header Referrer-Policy "strict-origin-when-cross-origin" always;
22add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
23add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
24
25# Test config before reload
26sudo nginx -t && sudo systemctl reload nginx