Ffile2fix
Sign in Get started

Fix Nginx "connect() failed (111: Connection refused)"

[error] 1234#1234: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 203.0.113.5, server: example.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3000/", host: "example.com"

Nginx tried to open a connection to the upstream shown in the log, but nothing was listening on that address and port, so the kernel refused it and the visitor sees 502 Bad Gateway. Start the backend or point proxy_pass/fastcgi_pass at the address it actually listens on.

Also appears as: connect() failed (111: Connection refused) while connecting to upstream, upstream: "fastcgi://127.0.0.1:9000" · connect() failed (111: Unknown error) while connecting to upstream · connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) while connecting to upstream · connect() to 127.0.0.1:8080 failed (13: Permission denied) while connecting to upstream

Common causes

  • The Node, Python, PHP-FPM or other backend process is stopped or crashed on startup
  • The backend listens on a different port, or on a Unix socket while Nginx uses TCP (or the reverse)
  • The app binds to 127.0.0.1 inside a Docker container, so other containers cannot reach it
  • proxy_pass uses localhost inside a Nginx container, which points to the Nginx container itself
  • localhost resolves to IPv6 ::1 but the app only listens on IPv4 127.0.0.1
  • The backend is still starting up or restarting after a deploy

How to fix it

  1. Read the upstream address. The upstream: field in the log shows exactly where Nginx tried to connect, for example http://127.0.0.1:3000 or fastcgi://127.0.0.1:9000.
  2. Check what is listening. Run sudo ss -ltnp | grep -E ':3000|:9000' to see whether any process listens on that port and on which address. No output means the backend is not running there.
  3. Start or fix the backend. Run systemctl status for the service (for example php8.3-fpm or your app's unit) and journalctl -u <service> -n 50 to see why it stopped. Fix the startup error and restart it.
  4. Match the address in Nginx. Make proxy_pass or fastcgi_pass use the same port or socket as the backend, for example the listen value in the PHP-FPM pool file. Use 127.0.0.1 instead of localhost to avoid IPv6 surprises.
  5. Fix Docker networking. Make the app listen on 0.0.0.0 inside its container and use the Compose service name in Nginx, for example proxy_pass http://app:3000;. Both containers must be on the same network.
  6. Reload and test. Run sudo nginx -t && sudo systemctl reload nginx, then curl -I http://127.0.0.1:3000 from the Nginx host or container to confirm the backend answers.

Nginx reverse proxy

upstream app_backend {
    server 127.0.0.1:3000;
}

server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://app_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

How to stop it happening again

  • Run backends under systemd or a process manager with automatic restart
  • Keep backend port and socket settings in one place and reference them from Nginx
  • Add health checks so deploys wait until the backend is listening
  • In Docker, always refer to services by name, never localhost

Frequently asked questions

What is the difference between 111 and 110 errors?

111 Connection refused means nothing is listening, so it fails instantly. 110 Connection timed out means something is there or a firewall drops packets and the backend did not respond in time.

Why does curl to localhost work but Nginx fails?

Often Nginx runs in a different network namespace, such as another container, or resolves localhost to ::1. Test with the exact address from the upstream: field.

What does (13: Permission denied) mean instead?

On SELinux systems Nginx is not allowed to make network connections by default. Run sudo setsebool -P httpd_can_network_connect 1.