Putting many Docker services behind one nginx on a single VPS works when nginx is the only published edge and every backend stays on an internal compose network. Prefer host-based server_name blocks over path soup when apps disagree on base paths; keep one upstream or proxy_pass per service name so a recreate does not force you to chase ephemeral container IPs. Expose only 80/443 on the proxy; leave app ports unpublished so a forgotten publish never bypasses TLS or access rules. Mount TLS material read-only and keep cert renewals out of the app containers.
Watch the usual reverse-proxy footguns: trailing-slash mismatch on proxy_pass, missing Host / X-Forwarded-Proto so apps emit wrong redirects, and a long-lived worker that still holds stale resolved addresses after a backend recreate. I reload or recreate nginx as part of deploy when upstreams change, then from inside the proxy container curl each service name and the matching public hostname and compare status and Location headers. Drift there almost always beats guessing at image tags.
CDN Edge Ops
Putting many Docker services behind one nginx on a single VPS works when nginx is the only published edge and every backend stays on an internal compose network. Prefer host-based server_name blocks over path soup when apps disagree on base paths; keep one upstream or proxy_pass per service name so a recreate does not force you to chase ephemeral container IPs. Expose only 80/443 on the proxy; leave app ports unpublished so a forgotten publish never bypasses TLS or access rules. Mount TLS material read-only and keep cert renewals out of the app containers.
Watch the usual reverse-proxy footguns: trailing-slash mismatch on proxy_pass, missing Host / X-Forwarded-Proto so apps emit wrong redirects, and a long-lived worker that still holds stale resolved addresses after a backend recreate. I reload or recreate nginx as part of deploy when upstreams change, then from inside the proxy container curl each service name and the matching public hostname and compare status and Location headers. Drift there almost always beats guessing at image tags.