Debugging '502 Bad Gateway' Caused by Unix Domain Socket (UDS) Permissions in Nginx/PHP-FPM

A deep-dive technical guide into resolving Nginx 502 Bad Gateway errors caused by Unix Domain Socket (UDS) file permission mismatches with PHP-FPM.

Debugging '502 Bad Gateway' Caused by Unix Domain Socket (UDS) Permissions in Nginx/PHP-FPM

If you manage a high-performance web stack involving Nginx and PHP-FPM, encountering a 502 Bad Gateway error is an occupational hazard. While a 502 error simply means Nginx received an invalid response from the upstream server (PHP-FPM in this case), the root cause is often deeply embedded in system-level configurations.

One of the most insidious and commonly misunderstood triggers for this error is a Unix Domain Socket (UDS) file permission mismatch. This issue frequently arises during server migrations, custom PHP-FPM pool creations, or aggressive security hardening.

In this deep-dive diagnostic guide, we will dissect the error logs, understand how UDS permissions work between Nginx and PHP-FPM, and implement a robust fix.

The Symptom: 502 Bad Gateway and Nginx Error Logs

When a visitor attempts to load a PHP page (like a WordPress site), their browser displays a plain 502 Bad Gateway screen.

To diagnose this, your first stop should always be the Nginx error log, typically located at /var/log/nginx/error.log or a site-specific log file.

tail -n 20 /var/log/nginx/error.log

You are looking for an error string that resembles this:

2026/09/20 14:32:11 [crit] 1845#1845: *1345 connect() to unix:/var/run/php/php8.2-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.1.105, server: example.com, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.2-fpm.sock:", host: "example.com"

The critical piece of telemetry here is (13: Permission denied). This explicitly tells us that the Nginx worker process does not have the necessary filesystem permissions to read/write to the PHP-FPM socket file.

Understanding the Architecture: TCP vs. UDS

Nginx and PHP-FPM can communicate over two mediums:

  1. TCP Sockets: e.g., 127.0.0.1:9000. This network-based approach is necessary if Nginx and PHP-FPM are on different physical servers or containers.
  2. Unix Domain Sockets (UDS): e.g., /var/run/php/php8.2-fpm.sock. This is a file-based communication protocol. It avoids the TCP/IP network stack entirely, resulting in lower latency and higher throughput.

Because a UDS is fundamentally a file on the Linux filesystem, it is governed by standard POSIX file permissions (chmod and chown).

Inspecting Socket Permissions

Let’s inspect the permissions of the socket file mentioned in our error log:

ls -la /var/run/php/php8.2-fpm.sock

Output:

srw-rw---- 1 root root 0 Sep 20 14:30 /var/run/php/php8.2-fpm.sock

Here is the crux of the problem:

  • The socket file is owned by user root and group root.
  • The permissions srw-rw---- (0660) mean that only the user root and members of the group root can read and write to this socket.

Now, let’s check which user Nginx is running as:

ps aux | grep nginx

Output:

root      1234  0.0  0.1  54321  1234 ?        Ss   14:28   0:00 nginx: master process /usr/sbin/nginx -g daemon off;
www-data  1235  0.0  0.2  54890  2345 ?        S    14:28   0:00 nginx: worker process

Nginx worker processes are running as the www-data user. Since www-data is neither root nor in the root group, the kernel rightfully blocks its attempt to connect to the socket, returning the 13: Permission denied error.

The Solution: Aligning PHP-FPM Pool Configuration

To fix this, we need to instruct PHP-FPM to create the socket file with ownership and permissions that allow the Nginx worker process to access it.

Open the PHP-FPM pool configuration file. For PHP 8.2 on a Debian/Ubuntu system, this is typically located at:

nano /etc/php/8.2/fpm/pool.d/www.conf

Locate the listen.owner and listen.group directives. By default, or in a misconfigured custom pool, they might be commented out or set to root.

Update them to match the user Nginx is running as (usually www-data on Debian/Ubuntu, or nginx on RHEL/AlmaLinux/CentOS):

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server.
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Explanation of Settings:

  • listen.owner & listen.group: Determines who owns the socket file. Setting this to www-data guarantees Nginx can interact with it.
  • listen.mode: 0660 provides read and write access to the owner and group, which is strictly necessary for bi-directional FastCGI communication.

Note: For heightened security in multi-tenant environments, you might run separate PHP-FPM pools for different users (e.g., user bob). In that case, listen.owner = bob, but you must ensure the Nginx user (www-data) is part of bob’s group, or use listen.mode = 0666 (less secure), or better yet, utilize ACLs.

Scaling Up: When Configuration Isn’t Enough

Sometimes, 502 errors aren’t just permission issues. If you are seeing Resource temporarily unavailable or EAGAIN alongside connection issues on a massive enterprise WordPress or Magento site, your traffic may be saturating the backlog queues of your UDS or maxing out CPU capabilities.

When software optimization hits a physical wall, you need bare-metal performance. Migrating high-throughput platforms to our high-performance Dedicated Servers provides the unshared CPU cores and vast I/O capacity required for intensive object caching and PHP processing. For regional latency optimization in South Asia, deploying on Dedicated Servers in Pakistan ensures sub-millisecond local network execution and eliminates upstream timeouts caused by physical distance.

Applying the Fix

After correcting the PHP-FPM pool configuration, restart both PHP-FPM and Nginx to flush the old socket file and spawn a new one with the correct permissions.

# Restart PHP-FPM first so the new socket is created
systemctl restart php8.2-fpm

# Verify the socket was created with new permissions
ls -la /var/run/php/php8.2-fpm.sock
# Expected output: srw-rw---- 1 www-data www-data 0 Sep 20 14:45 /var/run/php/php8.2-fpm.sock

# Restart Nginx
systemctl restart nginx

Reloading your web page should now execute the PHP script perfectly, and the 502 Bad Gateway error will be resolved.

By understanding the mechanics of Unix Domain Sockets and their interaction with the Linux permission model, you can quickly diagnose and resolve these connection blockades without resorting to guesswork.