nginx 502 Bad Gateway
nginx reached the upstream and got nothing usable back. The nginx error log names the reason precisely and is the only place worth starting.
What you see
A 502 page for every request, or intermittently under load. nginx itself is running fine.
What is actually wrong
The application behind it is not running, is listening somewhere else, is refusing the socket's permissions, or is taking longer than the configured timeout.
Codes and articles
Fixes (3)
Confirm the upstream is running and listening where nginx expects
The log says connection refused, or names a socket that does not exist.
Read the actual error. Every 502 has a specific cause written here.
sudo tail -50 /var/log/nginx/error.logCheck the upstream is running.
systemctl status php8.2-fpm --no-pager -lsudo ss -tlnp | grep -E '9000|3000|8080'ls -l /run/php/
The mismatch between what nginx is configured to reach and what the application actually listens on accounts for most of these — commonly a fastcgi_pass pointing at a socket path that changed with a PHP version upgrade.
Compare the two configurations directly.
grep -r 'fastcgi_pass\|proxy_pass' /etc/nginx/sites-enabled/grep -E '^listen' /etc/php/*/fpm/pool.d/www.conf
Correct whichever is wrong and reload rather than restart, so live connections are not dropped.
sudo nginx -t && sudo systemctl reload nginxIf the upstream keeps dying, read its own log rather than nginx's.
sudo journalctl -u php8.2-fpm -n 50 --no-pager
curl -sI http://localhost/ | head -3Fix the socket permissions
The log says permission denied on a socket path.
Look at the socket and who owns it.
ls -l /run/php/php8.2-fpm.sockid www-dataps -o user= -C nginx | sort -u
Set the pool's socket ownership to the user nginx runs as.
sudo sed -i 's/^;*listen.owner.*/listen.owner = www-data/; s/^;*listen.group.*/listen.group = www-data/; s/^;*listen.mode.*/listen.mode = 0660/' /etc/php/8.2/fpm/pool.d/www.confsudo systemctl restart php8.2-fpm
The socket is created by php-fpm with the ownership in its pool configuration. Changing the permissions by hand works until the next restart recreates it, which is why this fault appears to come back on its own.
On a system with SELinux, check for a denial before assuming it is Unix permissions.
sudo ausearch -m avc -ts recent | grep -i nginx | tail -20sudo setsebool -P httpd_can_network_connect 1
Check the directory permissions too — nginx needs execute on every directory in the socket's path.
sudo -u www-data test -w /run/php/php8.2-fpm.sock && echo writableDeal with an upstream that is too slow or crashing
The log says upstream timed out, or prematurely closed the connection.
Find out whether it is slow or dying. A premature close means the worker exited mid-request.
sudo journalctl -u php8.2-fpm --since '1 hour ago' | grep -iE 'exited|signal|oom|segfault'dmesg -T | grep -i 'killed process'
A worker killed by the OOM killer produces exactly the same 502 as a slow query, and raising the timeout for it makes matters worse. One command separates them.
If it is being killed for memory, look at the pool's memory limit and worker count rather than the timeout.
grep -E '^pm|memory_limit' /etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/php.iniIf it is genuinely slow, raise the timeouts on both sides — they must match or the shorter one wins.
grep -rn 'fastcgi_read_timeout\|proxy_read_timeout' /etc/nginx/grep -n 'request_terminate_timeout\|max_execution_time' /etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/php.ini
Set them consistently, and treat a long-running request as something to fix rather than to accommodate.
sudo sed -i 's/^;*request_terminate_timeout.*/request_terminate_timeout = 120/' /etc/php/8.2/fpm/pool.d/www.confsudo systemctl restart php8.2-fpm
Enable the slow log so the actual slow function is recorded.
sudo sed -i 's|^;*slowlog.*|slowlog = /var/log/php-fpm-slow.log|; s/^;*request_slowlog_timeout.*/request_slowlog_timeout = 5s/' /etc/php/8.2/fpm/pool.d/www.confsudo systemctl restart php8.2-fpm
sudo tail -20 /var/log/php-fpm-slow.logRelated faults
Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.