Hello everyone,
I'm setting up a Node.js application and want to use Nginx as a reverse proxy for it. I've read some documentation, but I'm not entirely sure about the best practices for configuring Nginx to handle SSL, load balancing (if needed later), and health checks.
Specifically, I'm looking for guidance on:
X-Forwarded-For, X-Real-IP, and Host correctly.Here's a snippet of what I have so far:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
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;
}
}
Any help or examples would be greatly appreciated!
This is a common and important setup! Your initial configuration is a good starting point. Here are some refined best practices and a more complete example, including SSL:
First, ensure you have Certbot installed and configured for your domain.
# Redirect HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
# HTTPS Server Block
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# Recommended SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1; # Important for keepalive connections
proxy_set_header Upgrade $http_upgrade; # For WebSocket support
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;
proxy_read_timeout 0; # Prevent timeouts on long polling or WebSocket connections
}
# Optional: serve static files directly from Nginx for better performance
# location /static/ {
# alias /path/to/your/node/app/public/static/;
# expires 30d;
# }
}
server block handles the HTTP to HTTPS redirect.server block listens on 443 ssl, specifies SSL certificate paths, and includes robust SSL settings for security.proxy_http_version 1.1; is crucial for enabling keep-alive connections to your Node.js app, improving performance.proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection 'upgrade'; are essential for WebSocket support.proxy_read_timeout 0; can be useful for applications that use long polling or WebSockets to prevent Nginx from closing the connection prematurely.If you need to scale, you can add an upstream block:
upstream nodejs_app {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
# server backend_ip:port;
}
server {
# ... SSL and other settings ...
location / {
proxy_pass http://nodejs_app; # Use the upstream name here
# ... proxy_set_header directives ...
}
}
Nginx will then distribute requests among the listed servers. You can add health checks for more advanced setups.
client_max_body_size 10M;This setup should provide a solid foundation for your Node.js application behind Nginx.
Thanks for the detailed answer, expert_admin! I was having trouble with WebSockets.
I have a follow-up question: what if my Node.js app is running inside a Docker container on the same host, but on a different IP or port exposed to the host?
For example, the container exposes port 8080, but it's accessible from the host at 172.17.0.2:8080 (Docker's internal network).
How would the proxy_pass directive change?