Learning path
Web servers: nginx and HTTPS in production
An app behind nginx, HTTPS that renews itself, and the errors you'll meet on the way.
3 stages · 16 steps
Stage 1
Put an app behind nginx
A working reverse proxy, and what happens when the port is taken.
- 1
- 2
Article
Nginx reverse proxy for Node.js and Express, with HTTPS and WebSockets
Set up Nginx in front of a Node.js or Express app: a complete config with HTTPS and WebSockets, a systemd service, trust proxy for real client IPs, and common errors.
- 3
Article
Nginx reverse proxy with Docker Compose: in a container or on the host
Put Nginx in front of Docker Compose services: on the host or in a container, connect by service name, fix "host not found in upstream", keep ports private, add HTTPS.
- 4
Article
"Address already in use": find who is using port 80 (or any port)
Fix "bind() failed (98: Address already in use)": find the process holding the port with ss or lsof, then stop it, move it, or change your port.
- 5
Lesson
Incident: Nginx won't start
A real incident to solve in your browser: after a config change Nginx won't start. Read the error, find the line with nginx -t, fix it and start the service again.
Stage 2
HTTPS
Get a certificate, keep it renewed, and recognize the errors when it doesn't.
- 6
Article
Certbot "failed to authenticate some domains": read the Type, then fix DNS, port 80 or the path
Fix Certbot "failed to authenticate some domains": read the error type, then fix DNS records, an IPv6 AAAA record, a closed port 80, the webroot, Cloudflare and CAA.
- 7
Article
"Certificate has expired": check the dates, renew it, and find out why it didn't renew
Fix "certificate has expired" and NET::ERR_CERT_DATE_INVALID: check the dates with openssl, renew with Certbot, reload the server, and fix why renewal or clock failed.
- 8
Article
ERR_TOO_MANY_REDIRECTS with Nginx and Cloudflare: find the loop and break it
Fix ERR_TOO_MANY_REDIRECTS: follow the loop with curl, then fix Cloudflare Flexible SSL, HTTPS redirects behind a proxy, X-Forwarded-Proto and www redirects that fight.
- 6
Stage 3
When it breaks
Read the error log, and go from the error code to the cause.
- 9
Guide
Website down? Find the cause, step by step
Start here whenever the site is down: it asks what you see.
- 10
Article
Nginx "502 Bad Gateway": find the cause in the error log
Fix nginx 502 Bad Gateway: read error.log, then fix the backend that is down, the wrong address or socket, the crashing app, or SELinux on RHEL.
- 11
Lesson
Incident: the site gives a 502
A real incident to solve in your browser: the API answers 502 Bad Gateway. Trace it from Nginx's error log to a crashed backend. On RHEL, SELinux adds one more step.
- 12
Article
Nginx "504 Gateway Time-out": find out what's slow before raising the timeout
Fix Nginx "504 Gateway Time-out": read the error log, measure the backend, set proxy_read_timeout or fastcgi_read_timeout, and check Cloudflare and load balancers.
- 13
Article
Nginx "403 Forbidden": read the error log, then fix the index, permissions or SELinux
Fix Nginx "403 Forbidden": the error log says if it's a missing index file, wrong permissions on a parent folder, a deny rule or SELinux. namei checks the whole path.
- 14
Article
Nginx "413 Request Entity Too Large": raise the upload limit in the right place
Fix 413 Request Entity Too Large on uploads: set client_max_body_size in nginx, then the limits of PHP, Node.js, the Kubernetes ingress and any proxy in front.
- 15
Article
Nginx "upstream sent too big header while reading response header": raise the right buffer
Fix Nginx "upstream sent too big header while reading response header from upstream" and its 502: measure the headers, then raise the right buffer.
- 16
Article
"Blocked by CORS policy": what the browser is really refusing, and how to fix it on the server
Fix "has been blocked by CORS policy: No Access-Control-Allow-Origin header": why it happens, the fix on the server or in Nginx, preflight requests, and cookies.
- 9
Your progress is saved in this browser only, never sent anywhere. Clearing the browser data clears it too.