Difficulty: Intermediate
What is Nginx? Explain reverse proxy, load balancing, and how you would configure Nginx for a Node.js application.
Nginx is a high-performance web server that excels as a reverse proxy, load balancer, and static file server. It handles thousands of concurrent connections efficiently using an event-driven, non-blocking architecture.
Reverse proxy: Nginx sits in front of your application servers and forwards client requests to them. Benefits include SSL termination (handling HTTPS at the proxy level), load balancing across multiple app instances, caching static assets, hiding internal server architecture, and providing rate limiting and security headers.
Load balancing distributes traffic across multiple application instances. Strategies include round-robin (default, equal distribution), least connections (sends to the server with fewest active connections), IP hash (same client always goes to same server, useful for sessions), and weighted (more traffic to more powerful servers).
Typical setup: Client -> Nginx (port 80/443) -> Node.js (port 3000). Nginx handles SSL, serves static files directly (much faster than Node.js), and proxies API requests to Node.js. This is the standard production architecture for most web applications.
# /etc/nginx/sites-available/myapp
server {
listen 80;
server_name example.com www.example.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL certificates (Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# Proxy API requests to Node.js
location /api/ {
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_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;
}
# Serve static React build
location / {
root /var/www/myapp/dist;
try_files $uri $uri/ /index.html;
}
}
This config handles SSL, redirects HTTP to HTTPS, proxies /api/ to Node.js, and serves the React build for all other routes. try_files with /index.html enables client-side routing.
# /etc/nginx/nginx.conf
# Define upstream servers
upstream node_app {
# Load balancing strategies:
# Round-robin (default) - equal distribution
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
# Least connections
# least_conn;
# server 127.0.0.1:3001;
# server 127.0.0.1:3002;
# IP hash (sticky sessions)
# ip_hash;
# server 127.0.0.1:3001;
# server 127.0.0.1:3002;
# Weighted (send more traffic to stronger server)
# server 127.0.0.1:3001 weight=3;
# server 127.0.0.1:3002 weight=1;
# Health checks
server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3002 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3003 backup; # only used if others are down
}
server {
listen 80;
location /api/ {
proxy_pass http://node_app;
}
}
Upstream blocks define server groups for load balancing. max_fails and fail_timeout provide automatic health checking. backup servers are standby only.
# Test configuration syntax
sudo nginx -t
# nginx: configuration file /etc/nginx/nginx.conf test is successful
# Reload config without downtime
sudo nginx -s reload
# Start/stop/restart
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl status nginx
# Enable symlink for site
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
# View access and error logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
# Setup SSL with Let's Encrypt (Certbot)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
# Auto-configures Nginx with SSL
# Auto-renewal: certbot handles it via cron/systemd
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://localhost:3000;
}
}
Always run nginx -t before reload to catch syntax errors. Certbot automates SSL certificate management. Rate limiting protects against abuse.
Nginx, Reverse Proxy, Load Balancing, SSL/TLS, Static Files, Caching