A 502 on Plesk always means the same thing: nginx, which fronts every site, asked an upstream for a response and didn't get a valid one. The upstream is either Apache (ports 7080/7081) or the domain's PHP-FPM socket, depending on the PHP handler. The fix depends entirely on which upstream failed and why, and the domain's proxy error log tells you both in one line.
This guide is a decision tree keyed on that log line. It covers Plesk Obsidian on AlmaLinux, Rocky, Debian, and Ubuntu. If the 502 comes from the Plesk updater rather than a hosted site, see fixing Plesk update failures instead.
Read the proxy error log first
Every domain has its own nginx error log. Reproduce the 502, then read the last few lines:
tail -n 20 /var/www/vhosts/system/example.com/logs/proxy_error_log
Match the error string against the sections below. If the log is empty, the 502 isn't coming from this server's nginx — check Cloudflare or any load balancer in front of it.
| Log contains | Upstream | Jump to |
|---|---|---|
connect() failed (111: Connection refused) while connecting to upstream + :7081 or :7080 | Apache down | Apache is not running |
connect() to unix:...php-fpm.sock failed (2: No such file or directory) | FPM pool missing | PHP-FPM socket missing |
connect() to unix:...php-fpm.sock failed (11: Resource temporarily unavailable) | FPM saturated | PHP-FPM pool is full |
upstream sent too big header while reading response header | Either | Response headers too large |
upstream prematurely closed connection or recv() failed (104: Connection reset by peer) | Either | Upstream dies mid-request |
A 504 Gateway Time-out with upstream timed out is a different problem — slow PHP, not a broken upstream. Fix the slow script before raising timeouts.
Apache is not running
The domain uses nginx as a proxy and Apache isn't listening. Confirm:
ss -ltnp | grep -E ':708[01]'
systemctl status httpd # apache2 on Debian/Ubuntu
If nothing listens on 7080/7081, Apache either crashed or failed to start after a config change. Test the config before restarting:
httpd -t # apache2ctl -t on Debian/Ubuntu
A syntax error almost always points at a file under /var/www/vhosts/system/<domain>/conf/ — usually a customer's Additional Apache directives with a typo, or a stale include left by a removed extension. Fix or clear the directive in the panel, then rebuild the web server configuration:
plesk sbin httpdmng --reconfigure-domain example.com
systemctl start httpd
If Apache starts but dies again within minutes, check /var/log/httpd/error_log for MaxRequestWorkers or segfault lines. Running out of workers produces refused connections under load, not a crash, so raise the limit only after ruling out a single abusive site.
PHP-FPM socket missing
The domain is on an FPM handler, but the pool's socket doesn't exist. This usually follows a PHP version removal, a failed update, or a domain restored from backup with a handler that isn't installed.
ls -l /var/www/vhosts/system/example.com/php-fpm.sock
systemctl status plesk-php83-fpm
If the service is up but the socket is missing, Plesk didn't write the pool. Re-applying the domain's PHP settings regenerates it — open Domains > example.com > PHP Settings and save without changes, or use the repair utility:
plesk repair web example.com -y
If the PHP version itself is gone, switch the domain to an installed version. Don't reinstall an end-of-life PHP just to bring one site back.
PHP-FPM pool is full
Resource temporarily unavailable means the socket's backlog is full: every child is busy and new connections are being dropped. The FPM log confirms it:
grep max_children /var/log/plesk-php83-fpm/error.log | tail -n 5
WARNING: [pool example.com] server reached pm.max_children setting (5), consider raising it
Plesk's default is pm = ondemand with pm.max_children = 5 per domain. That's fine for a brochure site and too low for WooCommerce with a crawler hitting it. Before raising it, find out why the children are busy:
- Slow external calls. Payment gateways, license checks, and remote feeds that hang hold a child for their full timeout.
- Bot traffic on uncached pages. Check the access log for one user-agent or IP range dominating
wp-admin/admin-ajax.phpor search URLs. - A real traffic increase. Then raising the limit is the right fix.
Raise it in PHP Settings > Performance Settings, setting pm.max_children to a value the server's RAM can carry. The sizing math is the same as on cPanel and is covered in PHP-FPM pool tuning. Plesk reloads the pool on save.
Response headers too large
upstream sent too big header means the upstream returned headers bigger than nginx's proxy buffer — usually stacked Set-Cookie headers from a CMS or a security plugin, or a long Link preload header. The default buffer is one memory page (4 KB or 8 KB).
Add to Apache & nginx Settings > Additional nginx directives for the domain. For FPM served by Apache (and any proxied setup):
proxy_buffer_size 16k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
For FPM served by nginx, the response doesn't go through proxy_* at all, so use the FastCGI equivalents:
fastcgi_buffer_size 16k;
fastcgi_buffers 8 16k;
fastcgi_busy_buffers_size 32k;
16 KB covers almost every real application. If a site needs more than 64 KB of headers, the application is broken — find the plugin setting cookies in a loop instead of raising buffers further.
Upstream dies mid-request
upstream prematurely closed connection means the upstream accepted the request and then dropped it. Three causes cover nearly every case.
PHP child crashed
Look for segfaults or terminated children around the timestamp of the 502:
grep -E 'SIGSEGV|SIGKILL|request_terminate_timeout' /var/log/plesk-php83-fpm/error.log | tail
dmesg -T | grep -iE 'oom|segfault' | tail
A SIGKILL alongside an OOM message means the kernel killed the child — the server is out of RAM, not the site. A SIGSEGV is almost always a PHP extension: ionCube, a third-party loader, or an outdated imagick. Disable extensions one at a time on that domain to isolate it.
Request killed by a timeout
If request_terminate_timeout or max_execution_time is lower than the time a long import or report takes, PHP kills the child and nginx logs a 502. Run long jobs from cron or WP-CLI instead of the browser, rather than raising timeouts for every request.
Apache restarted under live traffic
If 502s cluster at the same minute every day, or appear right after you create or edit domains, Apache is restarting. Every config change in Plesk triggers an Apache reload, and a full restart drops in-flight requests. Go to Tools & Settings > Apache Web Server, enable graceful restart, and set an Apache restart interval (for example 60 seconds) so bulk changes are batched into one restart.
Prevent repeat 502s
- Watch
proxy_error_logvolume per domain with the Plesk Monitoring extension and alert on spikes rather than waiting for tickets. - Keep customers off hand-edited Apache directives where possible; one typo stops Apache for every site.
- Put caching in front of PHP. On high-traffic WordPress subscriptions, LiteSpeed on Plesk with LSCache removes most of the PHP load that fills FPM pools.
What causes 502 Bad Gateway in Plesk?+
How do I fix 'upstream sent too big header' in Plesk?+
Why do I get 502 errors when Apache restarts in Plesk?+
Where is the nginx error log for a domain in Plesk?+
Is a 504 Gateway Timeout the same as a 502 in Plesk?+
Next steps
- Plesk repair utility commands — when
plesk repair webfixes broken vhost configs and when it overwrites customer directives. - PHP handlers in Plesk compared — which handler puts Apache in the request path, and which one to standardise on.
- Running Plesk Web Pro or Web Host on a leased license? See Plesk license tiers or order on the Plesk license page.