binding to loopback versus 0.0.0.0
The choice a service makes about who may open a connection to it, set once in its own configuration: Environment=HOST=127.0.0.1 in the unit, not a firewall rule. Bind to 127.0.0.1 and only processes on this machine can connect — exactly what a reverse proxy needs. 0.0.0.0 gets read as "this machine" and is not: it means every interface, including ones added later, so the public address too. The application is then reachable on port 3000 from the internet, and everything nginx does for it becomes optional — TLS, access logs, rate limiting, security headers, X-Forwarded-Proto. A ufw rule blocking 3000 is a safety net, not the decision: one ufw allow 3000 typed during a debugging session undoes it, and nobody takes it back out. sudo ss -tlnp | grep 3000 must show 127.0.0.1:3000, never 0.0.0.0:3000 or *:3000.
Also written: HOST=127.0.0.1, listen on 0.0.0.0, bind address
