When I first started using nginx I had no idea what it was actually doing. I just copied config snippets from Stack Overflow and hoped for the best. It worked until it didn't, and when it didn't I had no idea why. This is the explanation I wish I'd had.
What nginx actually is
nginx (pronounced "engine-x") is a web server. But calling it just a web server undersells it — it's also a reverse proxy, a load balancer, and an SSL termination point. Most of the time when I use it, I'm using it as a reverse proxy, which means it sits in front of other services and forwards traffic to them.
The reverse proxy bit explained
Say you have a Node.js app running on port 3000 and you want it accessible at mysite.com on port 443 with HTTPS. You don't point your domain straight at port 3000 — you put nginx in front. nginx listens on 443, handles the SSL certificate, and forwards requests through to your app on 3000. Your app doesn't need to know anything about SSL. nginx handles it.
A basic config
A minimal nginx reverse proxy config looks something like this:
server {
listen 443 ssl;
server_name mysite.com;
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
That's it. nginx listens for HTTPS traffic for mysite.com, uses the Let's Encrypt cert, and forwards everything to your app on port 3000.
SSL with Certbot
Getting the SSL cert in the first place is where a lot of people get stuck. Certbot is the tool that handles this. Once nginx is set up with a basic HTTP config, running certbot --nginx -d mysite.com will get the cert and modify your nginx config automatically. Then it auto-renews. It's actually very smooth once you've done it once.
The stuff that trips people up
The most common issue I've seen — including on my own setups — is forgetting to reload nginx after changing the config. Always run nginx -t first to test the config, then systemctl reload nginx to apply it. The test step has saved me so many times.
tail -f /var/log/nginx/error.log will usually tell you exactly what's wrong.