
NGINX is a high-performance web server and reverse proxy. It uses an event-driven, non-blocking architecture handling 10,000+ concurrent connections with minimal memory. Preferred over Apache for static files and reverse proxying.
| Item | Syntax | Description |
|---|---|---|
| server block | server { listen 80; server_name example.com; } | NGINX virtual host — equivalent to Apache VirtualHost |
| listen | listen 80; / listen 443 ssl; | Port to listen on |
| server_name | server_name www.example.com example.com; | Hostnames for this server block |
| root | root /var/www/html; | Document root directory |
| index | index index.html index.htm; | Default index files |
| location | location / { ... } / location /api/ { ... } | Handle requests matching path |
| location = (exact) | location = /health { return 200 'ok'; } | Exact path match |
| location ~ (regex) | location ~* \.(jpg|png|gif)$ { } | Regex location (case-insensitive with ~*) |
| try_files | try_files $uri $uri/ /index.html; | Try files in order — SPA routing |
| return | return 301 https://$host$request_uri; | Redirect |
| rewrite | rewrite ^/old/(.*)$ /new/$1 permanent; | URL rewrite |
| proxy_pass | proxy_pass http://localhost:3000; | Reverse proxy to backend |
| proxy_set_header | proxy_set_header Host $host; | Forward headers to backend |
| upstream | upstream backend { server app1:8080; server app2:8080; } | Load balancing group |
| ssl_certificate | ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem; | TLS certificate |
| ssl_certificate_key | ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem; | TLS private key |
| ssl_protocols | ssl_protocols TLSv1.2 TLSv1.3; | Allowed TLS versions |
| ssl_ciphers | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:...; | Allowed cipher suites |
| add_header | add_header Strict-Transport-Security 'max-age=63072000'; | Add response header |
| gzip | gzip on; gzip_types text/html text/css application/json; | Enable compression |
| access_log | access_log /var/log/nginx/access.log; | Access log location |
| error_log | error_log /var/log/nginx/error.log warn; | Error log location |
| include | include /etc/nginx/conf.d/*.conf; | Include config files |
| nginx -t | nginx -t | Test configuration syntax |
| nginx -s reload | nginx -s reload | Graceful config reload |
| worker_processes | worker_processes auto; | Number of worker processes |
| keepalive_timeout | keepalive_timeout 65; | Keep-alive connection timeout |
| client_max_body_size | client_max_body_size 10M; | Max upload size |
| rate limiting | limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; | Rate limit zone definition |
| limit_req | limit_req zone=api burst=20 nodelay; | Apply rate limiting |
# /etc/nginx/sites-available/mywebuniversity.conf
# Enable: sudo ln -s /etc/nginx/sites-available/mywebuniversity.conf /etc/nginx/sites-enabled/
# Test: sudo nginx -t
# Reload: sudo systemctl reload nginx
# Rate limiting zone (in http block of nginx.conf)
# limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
# Upstream for load balancing
upstream mywebuniversity_api {
least_conn; # least connections algorithm
server 127.0.0.1:3001 weight=3; # 3x more traffic
server 127.0.0.1:3002 weight=1;
server 127.0.0.1:3003 weight=1;
keepalive 32; # persistent connections to backend
}
# HTTP → HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name www.mywebuniversity.com mywebuniversity.com;
# Let's Encrypt ACME challenge
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.mywebuniversity.com;
root /var/www/React/prod;
index index.html;
# TLS
ssl_certificate /etc/letsencrypt/live/mywebuniversity.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebuniversity.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Logs
access_log /var/log/nginx/mywebuniversity_access.log;
error_log /var/log/nginx/mywebuniversity_error.log warn;
# Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/html text/plain text/css text/javascript
application/javascript application/json application/xml;
# Static files with caching
location ~* \.(ico|jpg|jpeg|png|gif|svg|woff2|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# API — reverse proxy with rate limiting
location /api/ {
limit_req zone=api burst=40 nodelay;
proxy_pass http://mywebuniversity_api/;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
# Health check endpoint
location = /health {
return 200 'healthy\n';
add_header Content-Type text/plain;
access_log off;
}
# SPA routing — fall back to index.html
location / {
try_files $uri $uri/ /index.html;
}
# Error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}
# www redirect
server {
listen 443 ssl http2;
server_name mywebuniversity.com;
ssl_certificate /etc/letsencrypt/live/mywebuniversity.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebuniversity.com/privkey.pem;
return 301 https://www.mywebuniversity.com$request_uri;
}
# Commands:
# sudo nginx -t # test config
# sudo systemctl reload nginx # reload config
# sudo nginx -s reload # alternative reload
# sudo tail -f /var/log/nginx/*.log # monitor logs