Error 502 Bad Gateway usually means that the reverse proxy received an invalid response from the upstream service or could not reach it. On a VPS, this proxy is most often Nginx, while the upstream may be PHP-FPM, a Node.js application, a Docker container, Apache, a backend on another port, or a service behind a CDN.
The first thing to determine: who exactly is returning 502. The error may be shown by Nginx on the server, a CDN in front of the server, Apache acting as a proxy, or another load balancer. Until the source is identified, it is easy to fix the wrong layer.
A basic troubleshooting flow looks like this:
| Step | What to check | Why |
| 1 | Which component returns the 502 | To understand where to start troubleshooting: the CDN, Nginx, Apache, or the backend |
| 2 | Service status | To see whether Nginx, PHP-FPM, Node.js, Docker, and the required containers are running |
| 3 | Error logs | To find the actual cause: connection refused, timeout, permission denied, no such file |
| 4 | Socket, port, or upstream | To check where Nginx is trying to forward the request |
| 5 | Memory and limits | To rule out OOM, too few PHP-FPM processes, or a Node.js process or container crash |
For Nginx, troubleshooting usually starts with the logs: sudo tail -n 100 /var/log/nginx/error.log
If the site runs on PHP, check PHP-FPM: systemctl status php8.2-fpm
The version may be different: php8.1-fpm, php8.3-fpm, or another one, depending on the server.
If the backend is written in Node.js, check whether the process is running and whether the application is listening on the required port: ss -tulpn | grep 3000
If the application runs in Docker, check the container status and its logs:
docker ps
docker logs container_name –tail=100
It is important not to confuse 502 with 504. With a 502, the proxy often receives an invalid response or cannot connect to the upstream. With a 504, the upstream usually does not respond in time, and the problem is more often related to a timeout, a long-running request, a stuck backend, or overload.
Clearing the cache rarely fixes a 502. It can help if a CDN or proxy is temporarily showing an old error page, but it will not fix a PHP-FPM crash, an incorrect proxy_pass, a closed Node.js port, an incorrect socket, or a crashed Docker container.
The most common mistake is restarting the server immediately without reading the logs. A restart may temporarily bring the site back online, but the root cause will remain: insufficient memory, an incorrect upstream port, a process crashing after deployment, a socket permissions issue, a broken container, or an incorrect healthcheck.
The correct approach is to first identify the source of the 502, then open error.log, check service status, the upstream socket or port, server resources, and application logs, and only then restart the specific service. After a temporary fix, you need to record the cause; otherwise, the error will return.
How 502 Bad Gateway Works

A 502 error does not appear simply because a “site is down.” It usually means that one server tried to get a response from another server or application, but received an invalid response or could not establish a proper connection.
On a VPS, this setup often looks like this: browser → Nginx → PHP-FPM / Node.js / Docker / Apache / another upstream
The browser sends a request to the site, Nginx accepts the request and forwards it. If the backend does not respond as expected, Nginx may return 502 Bad Gateway to the user.
Who is returning the 502?
The first step in troubleshooting is to determine exactly which component is showing the error. It may not be the service that has actually failed.
A 502 can be returned by:
- Nginx on the VPS;
- Apache, if it is acting as a reverse proxy;
- a CDN in front of the server;
- an external load balancer;
- a control panel;
- a gateway inside the Docker infrastructure;
- another proxy in front of the application.
For example, a user may see a page with a 502 error, but it may be returned by the CDN because the CDN could not connect to the origin server. In another case, the 502 is returned by Nginx on the VPS itself because PHP-FPM is not running or the Node.js application is not listening on the required port.
For this reason, you should not immediately restart the entire server. First, determine where the error came from: the CDN, Nginx, Apache, or the application.
In practice, you can identify this from the error page, HTTP headers, CDN logs, and web server logs. If fresh errors for this domain appear in /var/log/nginx/error.log at the same time, start troubleshooting with the VPS and the upstream.
Once the source of the error has been identified, the next important point is not to confuse a 502 with the similar 504 error.
502 vs 504
502 and 504 are similar in that both errors are often related to a proxy and an upstream service. However, they mean different things.
502 Bad Gateway usually means that the proxy received an invalid response from the upstream or could not establish a normal connection to it.
Typical causes of 502:
- PHP-FPM is not running;
- the Node.js application has crashed;
- the Docker container has stopped;
- Nginx is configured to use the wrong port;
- the PHP-FPM socket does not exist;
- there are insufficient permissions on the socket;
- the backend returned an invalid response;
- the upstream service closed the connection.
504 Gateway Timeout means that the proxy waited too long for a response and did not receive it within the allotted time.
Typical causes of 504:
- the backend is hung on a long-running request;
- a PHP script is taking too long to execute;
- Node.js cannot respond in time;
- the database is overloaded;
- an external API is slow;
- the Nginx timeout is too short for the specific operation;
- the server does not have enough resources.
In other words, with a 502, you usually check upstream availability: whether the service is running, whether the port is open, whether the socket exists, and whether the configuration is correct. With a 504, you usually look at execution time, hung requests, load, slow SQL queries, and timeout settings.
Confusing 502 and 504 leads to the wrong fix. For example, you might increase the timeout even though the Node.js application is not running at all. Or you might restart PHP-FPM even though the problem is a long-running database query.
This makes the core logic of 502 clearer: the problem is usually not in the browser or the cache, but between the proxy and the service that is supposed to handle the request.
Why the problem is almost always in the proxy → upstream chain
On a VPS, Nginx often acts as the entry point. It receives HTTP/HTTPS requests, handles SSL, static files, and redirects, and then forwards dynamic requests further upstream.
For a PHP site, the upstream is usually PHP-FPM: Nginx → PHP-FPM socket or TCP port
For a Node.js application: Nginx → localhost:3000
For Docker: Nginx → container port / published port / Docker network
If this chain breaks, you get a 502. Nginx is running, the domain loads, and SSL may be fine, but the backend either does not accept the request or responds incorrectly.
Examples:
- proxy_pass points to port 3000, but the application is listening on 3001;
- PHP-FPM was restarted with a different socket, while Nginx is still using the old path;
- The Docker container is running inside the network, but the port is not published externally;
- Node.js crashed after a deployment;
- The PHP-FPM pool has exhausted its process limit;
- Nginx does not have permission to access the PHP-FPM socket;
- the backend closes the connection because it is out of memory.
That is why, when troubleshooting a 502, it is better to think in terms of the request path rather than the page in the browser. You need to trace the chain: which component received the request, where it forwarded it next, whether that upstream exists, whether it is listening on the required socket or port, and what the logs say.
Clearing the cache, switching browsers, or fully rebooting the server may accidentally hide the symptom, but they will not explain the cause. To fix the issue properly, you need to analyze the proxy → upstream chain itself: Nginx, PHP-FPM, Node.js, Docker, the port, the socket, permissions, timeouts, memory, and logs.
Step-by-Step Diagnostics

When dealing with a 502 error, it is important not to start with random actions. A full server reboot, clearing the cache, or randomly restarting all services may temporarily hide the symptom, but they will not reveal the cause.
A better approach is to follow the request path: identify which component returned the error, which services were supposed to process the request, what the logs say, where the proxy is forwarding traffic, and whether the server has enough resources.
Identify the source of the error
First, determine which component is returning the 502 error. It could be Nginx on the VPS, Apache, a CDN, an external reverse proxy, a load balancer, or a gateway within the Docker infrastructure.
If a CDN sits in front of the site, the user may see a 502 error from the CDN even though the problem is on the origin server. The CDN could not connect to the VPS, received an invalid response, or did not receive a valid response from the backend in time.
You can start troubleshooting with a few simple questions:
- Is a CDN or external proxy being used;
- Does the error occur when accessing the server IP directly;
- Are there recent entries in the Nginx or Apache logs;
- Does the time of the error in the browser match the time in the server logs;
- Is the error page being served by Nginx, the CDN, or the application itself.
If the Nginx logs contain recent errors for this domain, continue troubleshooting on the VPS. If there are no entries on the server and the CDN is showing the error, check the availability of the origin, DNS, firewall, and CDN settings separately.
Once the source has been identified, the next step is to make sure the required services are actually running.
Check services
A 502 error often occurs because the upstream service is not running. Nginx is up and accepting requests, but PHP-FPM, Node.js, Apache, or the Docker container that should receive the request is stopped or has crashed.
Start by checking Nginx: systemctl status nginx
If the site runs on PHP, check PHP-FPM. The version may vary: systemctl status php8.2-fpm
For a Node.js application, you need to determine how it is running: via systemd, PM2, Docker, or manually. For example, for PM2: pm2 status
If Docker is used, check the containers: docker ps
Separately, list all containers, including stopped ones: docker ps -a
At this stage, it is important not just to see “active” or “running,” but to understand whether that matches the site’s actual architecture. For example, Nginx may be active, while the Node.js application has crashed. Or a container may be running, but the application inside it may have failed its health check.
If a service is stopped, you can restart it, but it is better to check the logs first. They will show why the process crashed.
Open error.log
Logs are the primary source of information when troubleshooting a 502 error. Without them, it is easy to start fixing the wrong thing: changing timeouts when the port is closed, clearing the cache when PHP-FPM is not running, or restarting Docker when Nginx is pointing to the wrong upstream.
For Nginx, the primary file is error.log: sudo tail -n 100 /var/log/nginx/error.log
If the server hosts multiple sites, it is useful to check the log for the specific virtual host, if it is configured separately: sudo tail -n 100 /var/log/nginx/example.com.error.log
The logs often contain useful clues: connect() failed (111: Connection refused) while connecting to upstream
This means that Nginx tried to connect to the upstream, but the upstream did not accept the connection. The usual cause is an incorrect port, a stopped backend, or a closed socket.
Another example: upstream timed out while reading response header from upstream
Here, the upstream accepted the connection but did not respond in time. This is more likely to indicate a timeout, a long-running request, a hung PHP/Node.js process, or overload.
Another common case: connect() to unix:/run/php/php8.2-fpm.sock failed (13: Permission denied)
This log entry indicates a permissions issue with the PHP-FPM socket.
After checking the logs, it usually becomes clear where to look next: the socket, the port, the upstream configuration, or the server’s resources.
Check the socket, port, and upstream
A 502 error often occurs because the Nginx configuration does not match the actual backend. Nginx forwards the request to one location, while the application is listening somewhere else.
For PHP-FPM, check fastcgi_pass in the Nginx configuration:
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
Then make sure the socket actually exists: ls -la /run/php/
If Nginx points to php8.2-fpm.sock, but the server only has php8.3-fpm.sock, a 502 error will occur. This often happens after a PHP upgrade.
For Node.js, check proxy_pass:
location / {
proxy_pass http://127.0.0.1:3000;
}
Then make sure the application is listening on this port: ss -tulpn | grep 3000
If nothing is listening on the port, the problem is not with Nginx but with the Node.js application, PM2, the systemd service, environment variables, or an error after deployment.
For Docker, check how the ports are published: docker ps
For example, if Nginx on the host connects to 127.0.0.1:3000, the container must publish that port to the host. If Nginx runs on a Docker network, check the service name, the network, and the container’s internal port.
If the socket and port match but the 502 error persists, check the resources. The backend may be running but crash under load or fail to respond in time.
Check memory and limits
A shortage of memory, processes, or file descriptors can also lead to 502 errors. In this case, the service may appear to be running, but it periodically crashes, stops accepting connections, or cannot process requests in time.
Start with the overall load:
free -h
df -h
top
If the server is running out of memory, Linux may terminate the process via the OOM killer. You can check this with: dmesg -T | grep -i “killed process”
Or via the journal: journalctl -k | grep -i oom
For PHP-FPM, check the pool limits. If there are too few processes and too many requests, the site may respond inconsistently:
grep -E “pm.max_children|pm.start_servers|pm.min_spare_servers|pm.max_spare_servers” /etc/php/8.2/fpm/pool.d/www.conf
The PHP version and pool name may differ.
For Node.js, check whether the process is crashing because of an error, insufficient memory, or incorrect environment variables. If PM2 is used: pm2 logs
For Docker, check the container logs and status:
docker logs container_name –tail=100
docker inspect container_name –format='{{.State.Health.Status}}’
If the issue is resource-related, a simple restart will only help temporarily. After some time, the processes will again hit memory constraints, PHP-FPM limits, long-running requests, heavy SQL operations, or application errors.
Therefore, 502 diagnostics should not end with a “restart everything” command, but with a clear conclusion: which upstream failed to respond, why it failed to respond, and what needs to be changed to prevent the error from recurring.
Checks for Nginx, PHP-FPM, Node.js, and Docker

After general diagnostics, you need to move on to the specific stack. A 502 error may look the same in the browser, but the causes will differ for a PHP site, a Node.js application, and a Docker container.
It is easier to work from the entry point toward the backend: first Nginx or an external proxy, then the upstream service that is supposed to process the request.
Nginx
Nginx often returns a 502 when it cannot forward the request to PHP-FPM, Node.js, Apache, a Docker container, or another upstream.
Start by checking the configuration: sudo nginx -t
If the configuration contains a syntax error, Nginx may fail to apply the new settings or continue running with the old configuration.
Next, check the logs: sudo tail -n 100 /var/log/nginx/error.log
If a separate log is configured for the site, check it as well: sudo tail -n 100 /var/log/nginx/example.com.error.log
In Nginx, you usually need to check:
- proxy_pass for Node.js or another backend;
- fastcgi_pass for PHP-FPM;
- the path to the PHP-FPM socket;
- the upstream port;
- socket access permissions;
- timeout settings;
- whether the configuration points to an old PHP version;
- whether the port changed after deployment.
For a PHP site, the error may be in a snippet like this: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
If PHP-FPM uses a different socket after an update, Nginx will keep looking at the old path and return a 502.
For Node.js, check proxy_pass: proxy_pass http://127.0.0.1:3000;
If the application is listening on a different port, Nginx will not be able to connect to the upstream.
Nginx shows where the failure occurs, but it is often not the root cause. After checking its logs, you usually need to move on to PHP-FPM, Node.js, or the container it proxies the request to.
PHP-FPM
PHP-FPM is responsible for executing PHP code. If WordPress, Laravel, or another PHP site is running through Nginx, a PHP-FPM failure can result in users seeing a 502 error.
First, check the service status: systemctl status php8.2-fpm
The version may be different:
systemctl status php8.1-fpm
systemctl status php8.3-fpm
If the service is not running, check its logs:
journalctl -u php8.2-fpm -n 100 –no-pager
Next, check the pool configuration. It is usually located here: /etc/php/8.2/fpm/pool.d/www.conf
Important parameters:
listen = /run/php/php8.2-fpm.sock
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
pm.max_children = 20
The listen parameter must match fastcgi_pass in the Nginx configuration. If PHP-FPM listens on a socket, Nginx must point to that socket. If PHP-FPM listens on a TCP port, Nginx must connect to that port.
You can check the socket as follows: ls -la /run/php/
If the Nginx logs contain Permission denied, check the socket owner and the listen.owner, listen.group, and listen.mode parameters.
PHP-FPM can also cause 502 errors when it runs out of worker processes. If pm.max_children is too low and there are many requests, some requests may hang or be dropped. In this case, check the PHP-FPM logs, load, memory usage, and slow log.
PHP-FPM is typically associated with PHP sites. If the backend is written in Node.js, troubleshooting shifts to the application process and its port.
Node.js
For Node.js, a 502 most often means that Nginx is trying to proxy a request to a port where the application is not responding.
First, determine how the application is running: through PM2, systemd, Docker, screen, supervisor, or manually. If PM2 is used, check the status: pm2 status
And the logs: pm2 logs
If the application is running through systemd:
systemctl status app-name
journalctl -u app-name -n 100 –no-pager
Next, check whether Node.js is listening on the required port: ss -tulpn | grep 3000
If Nginx is configured with: proxy_pass http://127.0.0.1:3000;
then the application must actually be listening on 127.0.0.1:3000 or 0.0.0.0:3000.
Common causes of 502 errors in Node.js:
- The application crashed after deployment;
- Dependencies are not installed;
- An environment variable is not set;
- The required port is already in use;
- The application is listening on a different port;
- PM2 did not save the process after a reboot;
- The backend crashes on the first request;
- Nginx is proxying to the wrong target;
- The request takes too long and hits a timeout.
After fixing the issue, it is important to save the process if PM2 is used: pm2 save
Also check autostart so that the application does not disappear after a reboot.
If Node.js runs inside a container, a standard port check on the host may not be enough. In that case, Docker needs to be checked separately.
Docker
In Docker, a 502 error often occurs because the container is stopped, the application inside the container has crashed, the port is not published externally, or Nginx is connecting to the wrong service name.
First, check the containers: docker ps
And the stopped containers: docker ps -a
If the container keeps restarting, you may see Restarting in its status or frequent changes in its uptime.
Container logs: docker logs container_name –tail=100
If Docker Compose is used:
docker compose ps
docker compose logs app –tail=100
Next, check port publishing. For example, if Nginx on the host connects to 127.0.0.1:3000, the container must publish the port on the host: 0.0.0.0:3000->3000/tcp
If Nginx is also running in Docker, it may need to connect not to 127.0.0.1, but to the service name inside the Docker network: proxy_pass http://app:3000;
In that case, check that both containers are on the same network and that the service is actually named app.
It is also worth checking the healthcheck, if one is configured: docker inspect container_name –format='{{.State.Health.Status}}’
A container may be “running,” while the application inside it is not actually ready to accept requests. A healthcheck helps distinguish a live container from a working application.
Docker adds another layer between the proxy and the backend. However, sometimes the 502 does not come from the VPS at all, but from a CDN or an external proxy in front of the server.
CDN or external proxy
If the site is behind a CDN, an external reverse proxy, or a load balancer, a 502 error may occur before the request even reaches Nginx on the VPS.
In this case, check whether the request reaches the origin server. If the Nginx logs show no recent requests at the time of the error, the issue may be between the CDN and the VPS.
Check the following:
- Whether the CDN points to the correct origin;
- Whether the VPS IP address has changed;
- Whether ports 80 and 443 are open on the server;
- Whether the firewall is blocking the CDN IP addresses;
- Whether the CDN and origin SSL modes match;
- Whether there are any errors in the CDN dashboard;
- Whether the site is accessible directly without the CDN;
- Whether overly strict WAF rules are enabled.
If the CDN returns a 502 error but the site works when accessed directly through the origin, the problem may be in the CDN settings, SSL, firewall, or routing. If the site also returns a 502 error when accessed directly, diagnostics should return to the VPS: Nginx, upstream, PHP-FPM, Node.js, or Docker.
An external proxy is useful for protecting and accelerating a site, but when errors occur, it adds another layer of diagnostics. Therefore, when dealing with a 502 error, it is important not to rely only on the browser: you need to determine where in the request chain the request transmission failed.
Common mistakes

When a 502 Bad Gateway error occurs, the instinct is to get the site back online as quickly as possible. That is understandable: users can see the error, form submissions are not going through, an online store may be losing orders, and the application appears unavailable.
However, taking quick action without diagnostics often only masks the problem. The site may start working after a restart, but then go down again an hour later for the same reason: the backend cannot handle the load, PHP-FPM is hitting its limits, Node.js crashes after a request, the container fails its health check, or Nginx is pointing to the wrong port.
Restarting without checking the logs
The most common mistake is to immediately restart Nginx, PHP-FPM, Node.js, Docker, or the entire VPS without checking the logs first. Sometimes this does help temporarily: the process starts again, the socket appears, the port starts listening again, and the container comes back up.
The problem is that the root cause remains unknown.
Before restarting, it is worth at least quickly recording the current state:
systemctl status nginx
systemctl status php8.2-fpm
sudo tail -n 100 /var/log/nginx/error.log
For Node.js:
pm2 status
pm2 logs –lines 100
For Docker:
docker ps -a
docker logs container_name –tail=100
If you restart everything immediately, you can lose important context: which service was stopped, what error appeared in the logs, whether there was an OOM event, which container was restarting, and which request caused the application to crash.
A restart is best used as a temporary recovery measure, not as a substitute for investigation. Afterward, you still need to understand why the upstream stopped responding.
The next common mistake is treating a 502 like any other “gateway timeout,” even though it is not always a timeout.
Confusing 502 and 504
502 and 504 look similar, but they indicate different types of problems.
502 Bad Gateway usually means that the proxy received an invalid response from the upstream server or could not connect to it properly. For example, PHP-FPM is not running, Node.js has crashed, a Docker container has stopped, the socket does not exist, or Nginx is proxying to the wrong port.
504 Gateway Timeout means that the proxy waited too long for a response and never received one. The most common causes are long-running requests, a hung backend, an overloaded database, an external API, or timeout settings that are too short.
If you confuse these errors, you can end up troubleshooting in the wrong direction. For example, you might increase the timeout even though the backend is not listening on the port at all, or restart PHP-FPM when the request is actually hanging on a slow SQL query.
For a 502, it is useful to check first:
- Whether the upstream is running;
- Whether the socket exists;
- Whether the required port is listening;
- Whether proxy_pass or fastcgi_pass is configured correctly;
- Whether the logs contain connection refused or permission denied errors.
For a 504, it is more important to look at request duration, the slow log, the database, external APIs, and timeout settings.
Once the error type has been identified, you should not try to fix it by clearing the cache. For a 502, the cache is almost never the layer where the root cause lies.
Clearing the cache instead of diagnosing the issue
Clearing the cache can help if the browser, CDN, or proxy is temporarily showing an old error page. But if Nginx cannot connect to PHP-FPM, Node.js, or a Docker container, the cache will not fix the upstream issue.
A 502 error occurs while a request is being processed between the proxy and the backend. Therefore, the real cause should be investigated in the services and logs, not just in the site cache.
Clearing the cache will not resolve:
- A stopped PHP-FPM service;
- An incorrect socket path;
- A closed Node.js port;
- A crashed container;
- A connection refused error;
- A socket permissions issue;
- Insufficient memory;
- An incorrect proxy_pass directive;
- An application crash after deployment.
For WordPress, clearing the plugin cache is also not a substitute for checking PHP-FPM and Nginx. For a Node.js application, clearing the CDN will not restart a process that crashed because of a code error. For Docker, clearing the cache will not fix a container that keeps restarting.
You can check the cache after basic diagnostics, but you should start with the request path: proxy → upstream. It is especially important to make sure Nginx is connecting to the correct port.
Unchecked upstream port
An incorrect upstream port is one of the simplest and most frustrating causes of a 502 error. The configuration looks almost right, the service appears to be running, but Nginx sends the request to the wrong destination.
Example for Node.js: proxy_pass http://127.0.0.1:3000;
If the application starts listening on 3001 after deployment, Nginx will continue sending requests to 3000 and receive an error.
You can check the port like this: ss -tulpn | grep 3000
Or view all listening ports: ss -tulpn
With PHP-FPM, a similar issue occurs not with a TCP port but with a socket: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
If php8.3-fpm.sock appears after a PHP upgrade while Nginx still points to the old socket, the site may return a 502.
Check: ls -la /run/php/
In Docker, the port may not be published the way Nginx expects. For example, the application inside the container listens on 3000, but a different port is published externally, or no port is published at all.
Therefore, when troubleshooting a 502 error, you should always verify three things: where Nginx is pointing, where the backend is actually listening, and whether there is connectivity between them.
Even if the site starts working after correcting the port or after a restart, the job is not complete. You need to record the cause; otherwise, the same error will return later.
Cause not recorded after a restart
A temporary restart often creates the impression that the problem has been resolved. The site loads, the 502 error is gone, and the task can be closed. But if the cause has not been recorded, this is not a fix; it is only a pause until the next failure.
After recovery, you need to record:
- Which service was not responding;
- What error appeared in the logs;
- Which upstream was used;
- Which port or socket was specified in the configuration;
- Whether there was an OOM event or low memory;
- Which container was failing;
- What exactly was fixed;
- Which commands helped;
- What needs to be changed to prevent the error from recurring.
For example, if PHP-FPM crashed because the pm.max_children value was too low, a simple restart will bring the site back online, but the error will reappear under load. You need to review the limits, server memory, load, and the slow log.
If Node.js crashed after a deployment, a restart does not address the root cause either. You need to check the application error, dependencies, environment variables, and automatic startup.
If a Docker container keeps restarting, it is important not just to run docker restart, but to understand why it is crashing: an error in the entrypoint, environment variables, database, network, or healthcheck.
A good practice is to leave a short note after each incident (postmortem): the symptom, the cause, the fix, and an action plan for preventing similar incidents in the future. This helps resolve recurring errors faster and gradually turns chaotic troubleshooting into normal VPS operations.
What to check after the fix

If the 502 error has disappeared and the site is accessible again, you should still not stop the diagnostics immediately. A restart often brings the service back only temporarily without addressing the root cause: insufficient memory, an incorrect upstream, an application crash, an overloaded PHP-FPM pool, or an unstable container.
First, verify that all required services are actually running:
systemctl status nginx
systemctl status php8.2-fpm
For Node.js via PM2:
pm2 status
pm2 logs –lines 50
For Docker:
docker ps
docker logs container_name –tail=50
Next, reopen the Nginx and application logs. Make sure new errors are not still appearing after recovery:
sudo tail -n 100 /var/log/nginx/error.log
If the logs still show connection refused, upstream timed out, permission denied, or application errors, the issue has not been fully resolved.
Next, check the request path itself. Nginx must point to the correct socket, port, or container. If you changed the configuration as part of the fix, be sure to validate the syntax and apply the settings:
sudo nginx -t
sudo systemctl reload nginx
For PHP-FPM, check whether fastcgi_pass matches the actual socket or TCP port. For Node.js, verify that the application is listening on the port specified in proxy_pass. For Docker, make sure the container is running, the port is published, or the service is reachable inside the Docker network.
After that, it is useful to check the server resources:
free -h
df -h
top
If memory is almost exhausted, the disk is full, or the CPU is constantly saturated, the 502 error may return. In that case, you need to identify the cause of the load: heavy requests, a slow database, memory leaks, PHP-FPM limits that are too low, an error in Node.js, or a container that keeps restarting.
After restoring the site, do not check only the home page. Open several internal pages, the admin area, the request form, authentication, the cart, API endpoints, and other dynamic sections. Sometimes the home page opens, while the error remains on resource-intensive routes.
If the issue was related to a deploy, a PHP update, Docker Compose, environment variables, or a port change, record exactly what changed. Otherwise, the error may occur again during the next update.
A minimal incident note may look like this:
| Symptom | Cause | Fix | Action plan |
| 502 on example.com | Nginx was proxying to 127.0.0.1:3000; after the deploy, the application was listening on 3001 | Updated proxy_pass, checked nginx -t, reloaded nginx | Fix the pipeline, add a port check after deploy |
This short postmortem helps avoid fixing the same error again. For a VPS, this is especially useful: most 502 errors recur not by chance, but because the underlying cause was not addressed.
Conclusion

A 502 Bad Gateway error on a VPS is almost always caused by a break between the proxy and the upstream. The user sees a single error page, but the request chain may involve Nginx, Apache, PHP-FPM, Node.js, a Docker container, a CDN, an external proxy, or a backend running on a separate port.
Proper diagnostics should not start with a full server reboot, but with the question: which component returned the 502, and where was it trying to forward the request? After that, you need to check service status, review error.log, verify the upstream socket or port, check the application logs, and assess server resources.
For a PHP site, PHP-FPM, the pool configuration, fastcgi_pass, the socket, and access permissions are especially important. For Node.js, check the application process, port, PM2 or systemd, environment variables, and errors after deployment. For Docker, check the container status, port mappings, Docker network, logs, and healthcheck. If there is a CDN in front of the site, you also need to determine separately whether the request reaches the origin server.
A 502 should not be confused with a 504. With a 502, the proxy often cannot connect to the upstream or receives an invalid response. With a 504, the upstream typically takes too long to respond. Because of this difference, the checks also differ: for a 502, the socket, port, process, and connection logs are more important; for a 504, timeouts, long-running requests, the database, and load are more important.
A restart may temporarily bring the site back online, but it is not a fix by itself. If you do not read the logs and identify the cause, the error may return after the next traffic spike, deployment, server restart, or PHP update.
A reliable approach is to follow the request chain, check the specific upstream, fix the root cause, and, after service is restored, verify that errors are no longer appearing. This turns a 502 from a chaotic outage into a clear VPS troubleshooting task.
FAQ
What does the 502 Bad Gateway error mean?
502 Bad Gateway means that a proxy or gateway was unable to get a valid response from an upstream service. On a VPS, this often looks like this: Nginx accepts a request from a user but cannot properly forward it to PHP-FPM, Node.js, a Docker container, Apache, or another backend.
The cause may be a stopped service, an incorrect port, a missing socket, a permissions error, an application crash, an issue inside a container, or an incorrectly configured reverse proxy.
Where to look for the cause of a 502 error on a VPS
The first place to check is the web server error log. For Nginx, this is usually: sudo tail -n 100 /var/log/nginx/error.log
If a separate log is configured for the site, check that log: sudo tail -n 100 /var/log/nginx/example.com.error.log
Next, check the upstream service: PHP-FPM, Node.js, a Docker container, or another backend. For PHP-FPM, check systemctl status and journalctl; for Node.js, check PM2 or systemd logs; for Docker, use docker logs.
Why does a 502 occur after deployment?
After deployment, the components the upstream depends on often change: the application port, environment variables, dependencies, socket path, PHP version, Docker image, or startup command.
For example, Nginx may continue proxying requests to 127.0.0.1:3000, while after deployment the Node.js application is listening on 3001. Or PHP may have been upgraded from 8.2 to 8.3, but fastcgi_pass still points to the old socket.
After deployment, you need to check not only that the application is running, but the entire request path as well: Nginx → port/socket → backend → logs.
What should you do if PHP-FPM causes a 502 error?
First, check the PHP-FPM status: systemctl status php8.2-fpm
The version may differ: php8.1-fpm, php8.3-fpm, or another version.
Then check whether fastcgi_pass in Nginx matches the actual PHP-FPM socket or TCP port. For example: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
Also check the socket: ls -la /run/php/
If the logs contain Permission denied, check the socket ownership and the pool configuration parameters: listen.owner, listen.group, and listen.mode. If PHP-FPM crashes under load, check memory usage, pm.max_children, the slow log, and PHP errors.
What should you do if a 502 error occurs in a Node.js application?
For Node.js, check whether the process is running and listening on the required port.
If PM2 is used:
pm2 status
pm2 logs –lines 100
Port check: ss -tulpn | grep 3000
If Nginx is configured with proxy_pass http://127.0.0.1:3000;, the application must actually be listening on that port. If the process crashes after startup, look for the cause in the logs: a code error, a missing environment variable, missing dependencies, a port already in use, or a database connection issue.
How do you diagnose a 502 error in Docker?
In Docker, first check the container status:
docker ps
docker ps -a
Then check the logs: docker logs container_name –tail=100
If you use Docker Compose:
docker compose ps
docker compose logs app –tail=100
Common causes include the container being stopped, the application inside the container crashing, the port not being published, Nginx connecting to the wrong address, the containers being on different networks, or the health check indicating that the application is not ready to accept requests.
Why doesn’t clearing the cache fix a 502 error?
Clearing the cache can remove an old error page from the browser, CDN, or proxy, but it does not resolve the underlying cause of the 502 error.
If PHP-FPM is not running, Node.js is not listening on the port, a Docker container is crashing, or Nginx is pointing to the wrong upstream, clearing the cache will not help. In these cases, you need to check the logs, service status, socket, port, upstream configuration, and server resources.
When is the CDN responsible for a 502 error?
A CDN can be the source of a 502 error if it cannot connect to the origin server or receives an invalid response from it.
Check the following:
- Whether the CDN points to the correct VPS IP address;
- Whether the origin is directly accessible;
- Whether ports 80 and 443 are open;
- Whether the firewall is blocking the CDN IP addresses;
- Whether the CDN’s SSL mode matches the origin’s;
- Whether requests from the CDN appear in the Nginx logs.
If there are no recent requests in the VPS logs at the time of the error, the issue may be between the CDN and the server. If the requests reach the server and Nginx logs upstream errors, continue troubleshooting on the VPS.
Sources
1. Nginx Documentation — HTTP proxy module
2. Nginx Documentation — FastCGI module
