Behind a Reverse Proxy

When running behind Nginx or a load balancer, tell Express to trust the proxy.

Syntaxapp.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

Example · javascript
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.

Example · bash
# /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.

Example · js
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.

Example · bash
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

  • Be the first to comment on this lesson.