Nginx Common Configuration Mistakes and How to Fix Them
Learn the most common Nginx configuration mistakes when deploying Node.js applications and how to fix them from missing headers to wrong proxy settings.
Nginx Common Configuration Mistakes
This guide covers the most frequent Nginx configuration mistakes and their fixes when deploying Node.js applications.
1. Missing WebSocket Headers
Wrong:
location / { proxy_pass http://localhost:3000; }
Right:
location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; }
Without these headers, Socket.io and WebSocket connections will fail. The Upgrade and Connection headers are required for the WebSocket protocol upgrade.
2. Not Passing Real Client IP
Wrong:
location / { proxy_pass http://localhost:3000; }
Node.js sees req.ip as 127.0.0.1 (Nginx's IP) instead of the real client IP.
Right:
location / { proxy_pass http://localhost:3000; 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; }
And in Express:
app.set("trust proxy", 1);
3. Not Setting the Host Header
Wrong:
location / { proxy_pass http://localhost:3000; }
Node.js sees req.headers.host as localhost:3000 instead of the real domain.
Right:
location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; }
4. Forgetting try_files for React Router
Wrong:
location / { root /home/ubuntu/frontend/dist; index index.html; }
Direct navigation to /profile returns 404.
Right:
location / { root /home/ubuntu/frontend/dist; try_files $uri $uri/ /index.html; }
The try_files directive falls back to index.html for client-side routing.
5. Not Removing the Default Site
Wrong:
# Default site still enabled ls /etc/nginx/sites-enabled/ # default devtinder
The default site may conflict with your configuration or serve the wrong content.
Right:
sudo rm /etc/nginx/sites-enabled/default
6. Using server_name with underscores
Wrong:
server_name your_domain.com;
Underscores are not valid in domain names.
Right:
server_name your-domain.com;
Use hyphens, not underscores.
7. SSL Configuration Issues
Wrong:
server { listen 443; # Missing 'ssl' parameter ssl_certificate /path/to/cert.pem; }
Right:
server { listen 443 ssl; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; }
Or use listen 443 ssl http2; for HTTP/2 support.
8. Not Reloading After Config Changes
Wrong:
# Changed config but didn't reload sudo nano /etc/nginx/sites-available/devtinder # Changes not applied
Right:
sudo nginx -t && sudo systemctl reload nginx
Always test first (nginx -t), then reload (reload not restart to avoid downtime).
9. Blocking All Traffic with CORS
Wrong:
# Don't handle CORS in Nginx when Node.js already handles it add_header Access-Control-Allow-Origin "https://yourdomain.com" always;
If Node.js also sets CORS headers, you'll get duplicate headers, which can cause errors.
Right:
# Let Node.js handle CORS # Don't add CORS headers in Nginx unless Node.js doesn't handle them
10. Large File Uploads Fail
Wrong:
# Default client_max_body_size is 1M # File uploads > 1MB will fail with 413
Right:
client_max_body_size 20M; # Or whatever your app needs
11. SSL Redirect Loop
Wrong:
server { listen 80; return 301 https://$host$request_uri; } server { listen 443 ssl; # Node.js also redirects to HTTPS proxy_pass http://localhost:3000; }
If Node.js also redirects HTTP to HTTPS, you get an infinite loop.
Right:
// In Express app.set("trust proxy", 1); // Now Express knows the request came via HTTPS (from X-Forwarded-Proto)
12. Permissions Issues
Wrong:
root /home/ubuntu/frontend/dist; # Nginx can't read the files
Right:
# Ensure Nginx can read the directory chmod -R 755 /home/ubuntu/frontend/dist
The Takeaway
Common Nginx mistakes include: missing WebSocket headers (Upgrade, Connection), not passing real client IP (X-Real-IP, X-Forwarded-For), not setting Host header, forgetting try_files for React Router, not removing the default site, SSL configuration issues, not reloading after changes, duplicate CORS headers, small client_max_body_size, SSL redirect loops, and permissions issues. Always test with nginx -t before reloading.
The Upgrade and Connection headers are missing. Add proxy_http_version 1.1, proxy_set_header Upgrade $http_upgrade, and proxy_set_header Connection 'upgrade' to the location block. These are required for the WebSocket protocol upgrade from HTTP.
Nginx is not passing the real client IP. Add proxy_set_header X-Real-IP $remote_addr and proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for. Also set app.set('trust proxy', 1) in Express so it reads the X-Forwarded-For header.
Nginx is not configured with try_files. Add try_files $uri $uri/ /index.html to the location block. This tells Nginx to fall back to index.html for any path that doesn't match a static file, enabling client-side routing.
The default client_max_body_size in Nginx is 1 MB. Add client_max_body_size 20M (or whatever size your app needs) to the server block or http block in nginx.conf.
Both Nginx and Node.js are redirecting HTTP to HTTPS. Fix by setting app.set('trust proxy', 1) in Express so it trusts the X-Forwarded-Proto header from Nginx and knows the request is already HTTPS.
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.

