Nginx Config Best Practices and Summary Complete Configuration Guide
A comprehensive summary of Nginx configuration best practices the complete production config, security, performance, and maintenance checklist.
Nginx Config Best Practices and Summary
This is a complete summary of Nginx configuration best practices for your Node.js application.
The Complete Production Config
# /etc/nginx/nginx.conf user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; worker_connections 2048; worker_rlimit_nofile 65535; http { # Basic settings sendfile on; tcp_nopush on; tcp_nodely on; keepalive_timeout 65; keepalive_requests 100; types_hash_max_size 2048; server_tokens off; client_max_body_size 10M; # Timeouts (prevent slowloris) client_body_timeout 10; client_header_timeout 10; send_timeout 10; # Open file cache open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; # Gzip gzip on; gzip_vary on; gzip_min_length 1000; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml; # Rate limiting limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; include /etc/nginx/mime.types; default_type application/octet-stream; # Logging access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log warn; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
# /etc/nginx/sites-available/devtinder upstream nodejs_backend { server 127.0.0.1:3000; keepalive 32; } # HTTP to HTTPS redirect server { listen 80; server_name yourdomain.com www.yourdomain.com api.yourdomain.com; return 301 https://$host$request_uri; } # API server server { listen 443 ssl http2; server_name api.yourdomain.com; 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_session_cache shared:SSL:10m; # Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; # REST API location /api/ { limit_req zone=api burst=20 nodelay; proxy_pass http://nodejs_backend; 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 Connection ""; } # Socket.io WebSocket location /socket.io/ { proxy_pass http://nodejs_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400s; } # Block hidden files location ~ /\. { deny all; } } # Frontend server server { listen 443 ssl http2; server_name yourdomain.com www.yourdomain.com; ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; root /home/ubuntu/devtinder-frontend/dist; location / { try_files $uri $uri/ /index.html; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; } }
Best Practices Checklist
Configuration
- worker_processes auto, worker_connections 2048
- server_tokens off
- HTTP to HTTPS redirect (301)
- try_files for React Router
- proxy_set_header Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto
- WebSocket headers (Upgrade, Connection) for Socket.io
- Long proxy_read_timeout for WebSocket (86400s)
Security
- Security headers (HSTS, X-Frame-Options, X-Content-Type-Options, CSP)
- Rate limiting (limit_req_zone)
- client_max_body_size set
- Short timeouts (prevent slowloris)
- Block hidden files (location ~ /. { deny all; })
- SSL with TLSv1.2 and TLSv1.3
- OCSP stapling
Performance
- Gzip compression (level 6, text types)
- Static file caching (expires 1y, immutable)
- access_log off for static files
- Proxy buffering on
- Keep-alive (65s, 32 upstream)
- HTTP/2 enabled
- Open file cache
Maintenance
- Test before reload (nginx -t)
- Reload not restart (zero downtime)
- Back up before changes
- Version control config files
- SSL auto-renewal (certbot)
- Monitor access and error logs
- Regular updates (apt upgrade)
The Takeaway
A production Nginx config for Node.js includes: HTTP to HTTPS redirect, SSL with modern protocols, security headers, rate limiting, gzip compression, static file caching, proxy headers for Node.js, WebSocket support for Socket.io, keep-alive connections, HTTP/2, appropriate timeouts, and blocked hidden files. Always test with nginx -t, reload (not restart), back up before changes, and version-control your config. This setup serves both the API and frontend with optimal performance and security.
HTTP to HTTPS redirect, SSL with TLSv1.2/1.3, security headers (HSTS, X-Frame-Options, CSP), rate limiting, gzip compression, static file caching with immutable, proxy headers (Host, X-Real-IP, X-Forwarded-For), WebSocket support (Upgrade, Connection), keep-alive, HTTP/2, appropriate timeouts, blocked hidden files, and worker_processes auto with 2048 connections.
Test before reload (nginx -t), use reload not restart (zero downtime), back up before changes, version-control config files, set server_tokens off, enable gzip and caching, add security headers, set rate limiting, block hidden files, and use HTTP/2 with SSL.
Create separate server blocks: one for api.yourdomain.com (proxy_pass to Node.js on port 3000) and one for yourdomain.com (root pointing to the React build directory with try_files for client-side routing). Add SSL for both and an HTTP to HTTPS redirect.
Add a /socket.io/ location block with proxy_http_version 1.1, proxy_set_header Upgrade $http_upgrade, proxy_set_header Connection 'upgrade', and proxy_read_timeout 86400s. If using load balancing, add ip_hash to the upstream block for sticky sessions.
Gzip compression (level 6), static file caching (expires 1y, immutable), access_log off for static files, proxy_buffering on, keep-alive (65s timeout, 32 upstream connections), HTTP/2, open file cache, worker_processes auto with 2048 connections, and Brotli compression if available.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

