Behind a Reverse Proxy
When running behind Nginx or a load balancer, tell Express to trust the proxy.
app.set('trust proxy', 1)In production your app usually sits behind a reverse proxy like Nginx, or a cloud load balancer, that handles HTTPS and forwards requests. The proxy adds headers such as X-Forwarded-For and X-Forwarded-Proto.
Enable app.set('trust proxy', 1) so Express reads the real client IP and protocol from those headers, which matters for rate limiting and secure cookies.
Example
const app = express();
// Trust the first proxy in front of the app
app.set('trust proxy', 1);
app.get('/ip', (req, res) => {
// now reflects the real client IP, not the proxy's
res.send('Your IP: ' + req.ip);
});When to use it
- An Nginx reverse proxy terminates HTTPS and forwards requests to Express on port 3000, so Express never handles TLS certificates.
- A developer sets app.set('trust proxy', 1) so Express reads the correct client IP from X-Forwarded-For set by the upstream load balancer.
- A team routes /api to an Express server and / to a static Next.js build using a single Nginx configuration file.
More examples
Nginx config for Express
Forwards all HTTP traffic to Express on port 3000, passing the real client IP and protocol via standard headers.
# /etc/nginx/sites-available/myapp
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Trust proxy in Express
Enables trust proxy so Express reads req.ip from X-Forwarded-For and req.secure from X-Forwarded-Proto.
const app = require('express')();
// Trust the first hop (Nginx on the same host)
app.set('trust proxy', 1);
app.get('/ip', (req, res) => {
// req.ip now returns the real client IP, not 127.0.0.1
res.json({ ip: req.ip, secure: req.secure });
});HTTPS redirect at Nginx level
Redirects all HTTP traffic to HTTPS at the Nginx layer so Express code never needs to handle the redirect.
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
Discussion