— 1 min read
Nginx and SSL
Put Nginx in front of a Node.js app as a reverse proxy and terminate SSL with a free Let's Encrypt certificate.
- Nginx
- Node.js
- DevOps
A Node app can serve HTTPS directly, but in practice it's almost always better to let Nginx sit in front of it: terminate SSL, handle gzip and static files, and reverse-proxy everything else to your app process.
1. Install Nginx and Certbot
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx2. Reverse-proxy config
Create /etc/nginx/sites-available/app.conf:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
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_cache_bypass $http_upgrade;
}
}The Upgrade/Connection headers matter if your app uses WebSockets —
without them, Nginx won't proxy the upgrade handshake correctly.
Enable the site and reload:
sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx3. Get a certificate
sudo certbot --nginx -d example.com -d www.example.comCertbot edits the same config file to add the listen 443 ssl block, the
certificate paths, and an HTTP → HTTPS redirect — no manual cert wiring
needed. It also sets up a renewal timer, so certificates (valid 90 days)
renew themselves; you can confirm with:
sudo certbot renew --dry-runNotes
- Keep your Node app bound to
127.0.0.1, not0.0.0.0— it should only be reachable through Nginx, not directly on its port. - If you're running multiple apps on one box, give each its own
server {}block keyed byserver_name, and a distinct upstream port. - Add
client_max_body_sizein the server block if your app accepts file uploads larger than Nginx's 1MB default.