What it means
111 is the Linux error ECONNREFUSED: the backend host answered the connection attempt with a reset because no process listens on that port. nginx returns 502 Bad Gateway to the client.
[error] 1234#1234: *12 connect() failed (111: Connection refused) while connecting to upstream, client: 203.0.113.7, server: example.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3000/"With PHP-FPM, the upstream field reads fastcgi://127.0.0.1:9000.
Common causes
1. The app is not running. It crashed, a deploy failed, or it never started after a reboot, sometimes because another process held its port (the same 98: Address already in use that stops nginx from starting). Confirm:
systemctl status myapp
docker ps -a --filter "name=app"2. It listens somewhere else. The app binds 127.0.0.1 while nginx connects to another IP, PHP-FPM listens on a socket while nginx targets port 9000, or localhost inside a container points at nginx itself. Confirm on the backend host:
sudo ss -ltnp | grep -E ":3000|:9000"
grep -R "^listen" /etc/php/*/fpm/pool.d/3. A restart window. Requests arrive while the app restarts. The errors cluster at deploy times and stop on their own.
4. A stale IP in Docker. nginx resolves the hostname in proxy_pass once, at startup. After the app container is recreated with a new IP, nginx keeps connecting to the old one.
How to fix
- Run
ss -ltnpon the backend host to see what actually listens, and on which address. - If nothing does, start the app and read its logs for why it exited.
- Make
proxy_passorfastcgi_passmatch the listen address exactly: same IP or service name, same port, or the same socket path. - For Docker IP changes, reload nginx after recreating containers, or resolve at request time with
resolver 127.0.0.11 valid=10s;and a variable inproxy_pass. - For deploys, run two instances in the upstream block so nginx retries the other one (
proxy_next_upstream error timeoutis the default), and restart them one at a time. - Test and reload:
sudo nginx -t && sudo systemctl reload nginx.
Is it just you?
Confirm the 502 is visible from outside, and from which regions, with Is my site down?.
Get alerted next time
- A TCP port monitor on the app's port, when it is reachable from outside, fails the moment nothing listens there anymore.
- An HTTP monitor on the public URL fails when nginx answers 502 instead of the status code you expect.
- Each failure is rechecked from your other regions before an outage opens, so a two-second restart does not page anyone.
FAQ
Why does proxy_pass http://localhost:3000 fail in Docker? ▼
Inside the nginx container, localhost is the nginx container itself, not the app. Use the app's service name on a shared network, for example proxy_pass http://app:3000, and make sure the app binds 0.0.0.0 rather than 127.0.0.1 inside its own container.
What if the error says (2: No such file or directory) or (13: Permission denied)? ▼
Those are the Unix socket versions. Error 2 means the socket file in fastcgi_pass or proxy_pass does not exist, often a PHP-FPM version mismatch in the path. Error 13 means nginx's user cannot open the socket: check listen.owner, listen.group and listen.mode in the PHP-FPM pool.
Is a 111 error different from a timeout? ▼
Yes. Refused means the host answered right away that the port is closed, so the app is not listening. A timeout (error 110) means nothing answered at all, which usually points at a firewall dropping packets or a host that is down.