Resolving Nginx 502 Bad Gateway with PHP-FPM Unix Socket on macOS Localhost
Troubleshoot Nginx 502 Bad Gateway errors on macOS with PHP-FPM Unix sockets. This guide covers common misconfigurations and permissions issues.
Troubleshoot Nginx 502 Bad Gateway errors on macOS with PHP-FPM Unix sockets. This guide covers common misconfigurations and permissions issues.
When developing web applications locally on macOS using Nginx and PHP-FPM, encountering a "502 Bad Gateway" error is a common but frustrating experience. This error typically indicates that Nginx, acting as a reverse proxy, failed to receive a valid response from the upstream server – in this case, PHP-FPM – which is responsible for processing PHP requests. This guide will walk you through the precise steps to diagnose and resolve this issue, focusing on configurations involving Unix sockets.
Symptom & Error Signature
The primary symptom is a generic "502 Bad Gateway" message displayed in your web browser when trying to access a PHP-enabled page. To truly diagnose the problem, you need to consult the Nginx error logs.
Browser Output:
502 Bad Gateway
nginx/1.24.0
Nginx Error Log (typical location on macOS Homebrew: /usr/local/var/log/nginx/error.log):
One of these will typically appear, often providing the most direct clue:
2023/10/26 10:30:05 [crit] 12345#0: *1 connect() to unix:/usr/local/var/run/php-fpm/php-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/usr/local/var/run/php-fpm/php-fpm.sock:", host: "localhost"
Or, a permissions issue:
2023/10/26 10:30:05 [crit] 12345#0: *1 connect() to unix:/usr/local/var/run/php-fpm/php-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/usr/local/var/run/php-fpm/php-fpm.sock:", host: "localhost"
Less commonly, if PHP-FPM starts but crashes or struggles with a request:
2023/10/26 10:30:05 [warn] 12345#0: *1 upstream prematurely closed connection while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/usr/local/var/run/php-fpm/php-fpm.sock:", host: "localhost"
Root Cause Analysis
The 502 Bad Gateway error, when involving a PHP-FPM Unix socket, stems from a communication breakdown between Nginx and PHP-FPM. Here are the most common underlying reasons:
- PHP-FPM Not Running: The most straightforward cause. If the PHP-FPM service isn't active, the Unix socket won't exist, and Nginx will have nothing to connect to.
- Incorrect Unix Socket Path: Nginx is configured to look for the PHP-FPM socket at one path (e.g.,
/usr/local/var/run/php-fpm/php-fpm.sock), but PHP-FPM is configured to create it at a different path (e.g.,/tmp/php-fpm.sock) or simply isn't creating it at all. - Permissions Issues: Even if the socket exists, the Nginx process user (typically
_wwwon macOS Homebrew installations, orwww-dataon Linux) might not have the necessary read/write permissions for the socket file itself or its parent directory. This is particularly prevalent on macOS due to differing user/group contexts. - PHP-FPM Configuration Errors: PHP-FPM might be failing to start or crashing due to syntax errors in its configuration files (
php-fpm.conf,www.conf), or running into resource limits (e.g.,memory_limit,max_children) when processing a request, leading to premature connection closure. - Corrupted or Stale Socket: Occasionally, the socket file might become corrupted or not be properly cleaned up after a previous PHP-FPM shutdown, preventing a new socket from being created correctly.
Step-by-Step Resolution
Follow these steps systematically to pinpoint and resolve the 502 Bad Gateway error.
1. Verify PHP-FPM Status
First, ensure that the PHP-FPM service is actually running. On macOS with Homebrew, this is typically managed as a service.
# List all Homebrew services and their status
brew services list | grep php
You should see an output similar to this:
[email protected] started _www /Users/youruser/Library/LaunchAgents/[email protected]
If the status is stopped or error, restart it:
# Restart the specific PHP version service (adjust for your PHP version)
brew services restart [email protected] # e.g., for PHP 8.8
If you have multiple PHP versions installed via Homebrew, ensure you're starting the one your Nginx configuration expects. Use
php -vto check your command-line PHP version.
2. Cross-Check Unix Socket Path
The most common cause is a mismatch between where Nginx expects the socket and where PHP-FPM creates it.
a. Identify Nginx's fastcgi_pass directive:
Open your Nginx configuration file. On macOS with Homebrew, the main config is usually at /usr/local/etc/nginx/nginx.conf, and site-specific configs are often in servers/ or sites-enabled/ directories included by the main config.
# Open Nginx main configuration (adjust path if different)
sudo nano /usr/local/etc/nginx/nginx.conf
# Or your site-specific config, e.g. /usr/local/etc/nginx/servers/your_site.conf
Look for a location ~ .php$ block and the fastcgi_pass directive. It will specify the Unix socket path:
location ~ .php$ {
fastcgi_pass unix:/usr/local/var/run/php-fpm/php-fpm.sock; # <-- This path
fastcgi_index index.php;
include fastcgi.conf;
}
Make a note of the exact path (e.g., /usr/local/var/run/php-fpm/php-fpm.sock).
b. Identify PHP-FPM's listen directive:
Next, open your PHP-FPM configuration. For Homebrew installations, this is typically located in the php-fpm.d directory within your PHP version's configuration.
# Open PHP-FPM www pool configuration (adjust for your PHP version)
sudo nano /usr/local/etc/php/8.8/php-fpm.d/www.conf
Search for the listen directive:
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - Use IPv4 address and port number.
; '[::1]:port' - Use IPv6 address and port number.
; '/path/to/unix/socket' - Use Unix socket.
; Note: This value is in an environment variable when the FPM is in daemon mode
; and it may override the FPM default configuration.
listen = /usr/local/var/run/php-fpm/php-fpm.sock # <-- This path
Ensure the
fastcgi_passpath in Nginx exactly matches thelistenpath in PHP-FPM. Even a minor typo or different directory will cause a 502 error. If they differ, update one to match the other. Typically, it's easier to adjust the Nginx config to match PHP-FPM's default, which is often/usr/local/var/run/php-fpm/php-fpm.sockfor Homebrew.
After making changes, restart both services:
brew services restart [email protected] # Adjust version
brew services restart nginx
3. Resolve Permissions for Socket Directory and File
A "Permission denied" error (13) in the Nginx logs points directly to this. Nginx's user needs access to the socket.
a. Identify Nginx and PHP-FPM users:
- Nginx User: On macOS Homebrew, Nginx often runs as the
_wwwuser and group. You can verify this by checking theuserdirective innginx.confor by listing running processes:
This indicatesps aux | grep nginx | grep master # Output might show: root 12345 0.0 0.0 4567896 1234 root 0:00.00 nginx: master process /usr/local/opt/nginx/bin/nginx -g daemon off; # And then for workers: _www 12346 0.0 0.0 4568816 2048 _www 0:00.00 nginx: worker process_wwwis the worker user. - PHP-FPM User/Group: In your
www.conf(e.g.,/usr/local/etc/php/8.8/php-fpm.d/www.conf), look foruserandgroupdirectives, as well aslisten.owner,listen.group, andlisten.mode.
Ensure; Unix user/group of processes ; Note: The user/group specified here must also own the socket file, ; so that Nginx can access it. user = _www group = _www ; Set permissions for the socket listen.owner = _www listen.group = _www listen.mode = 0660userandgroup(for PHP-FPM processes) andlisten.owner/listen.group(for the socket file itself) are set to the same user Nginx runs as (e.g.,_www).listen.mode = 0660allows both the owner and group to read/write the socket.
b. Check and Adjust Directory Permissions:
The parent directory of the socket file also needs appropriate permissions. For /usr/local/var/run/php-fpm, the _www user needs to be able to create files.
# Check permissions of the socket's parent directory
ls -ld /usr/local/var/run/php-fpm
It should ideally be owned by _www and have appropriate permissions (e.g., drwxr-xr-x or drwxr-x---). If not, adjust them:
# Change ownership to the Nginx/PHP-FPM user/group
sudo chown -R _www:_www /usr/local/var/run/php-fpm
# Set appropriate directory permissions (read, write, execute for owner; read, execute for group/others)
sudo chmod 755 /usr/local/var/run/php-fpm
Using
-Rwithchownon directories that might contain other important files should be done carefully. For/usr/local/var/run/php-fpm, it's usually safe as it's typically managed by Homebrew/PHP-FPM.
After adjusting permissions and PHP-FPM configurations, restart both services:
brew services restart [email protected] # Adjust version
brew services restart nginx
4. Check PHP-FPM Error Logs
If Nginx logs show upstream prematurely closed connection or PHP-FPM is running but the socket isn't being created, PHP-FPM itself might be encountering issues.
a. Locate PHP-FPM logs:
On Homebrew, the PHP-FPM log file is usually found at /usr/local/var/log/php-fpm.log or a similar path within your PHP version directory.
# Tail the PHP-FPM error log
sudo tail -f /usr/local/var/log/php-fpm.log
Look for any errors, warnings, or fatal messages during startup or when a request is made. Common issues include:
- Syntax errors in
php.iniorwww.conf. - Memory limit exhaustion:
Allowed memory size of X bytes exhausted– adjustmemory_limitinphp.ini. - Max children limit: If
pm.max_childrenis too low inwww.conf, PHP-FPM might become unresponsive. - Missing extensions: PHP-FPM might fail to start if a required extension is missing or misconfigured.
b. Restart PHP-FPM in debug mode (if necessary):
For deeper debugging, you can stop the Homebrew service and try running php-fpm directly from the terminal to see immediate output:
brew services stop [email protected] # Stop the service first
/usr/local/opt/[email protected]/sbin/php-fpm --fpm-config /usr/local/etc/php/8.8/php-fpm.conf -y /usr/local/etc/php/8.8/php-fpm.d/www.conf
This will run PHP-FPM in the foreground and output errors directly to your terminal. Press Ctrl+C to stop it. Remember to restart the Homebrew service afterwards: brew services start [email protected].
5. Nginx Configuration Syntax and Restart
Even if the socket path and permissions are correct, Nginx itself might have a configuration issue preventing it from handling requests properly.
a. Test Nginx configuration syntax:
sudo nginx -t
This command will check the syntax of your Nginx configuration files. If there are any errors, it will report them with file paths and line numbers. Correct any reported issues.
b. Restart Nginx:
Ensure Nginx has picked up any changes to its configuration or PHP-FPM's availability.
brew services restart nginx
6. Clear Stale Socket (If Applicable)
If all else fails and you suspect a corrupted or stale socket file, you can manually remove it.
# Stop PHP-FPM
brew services stop [email protected]
# Remove the socket file (adjust path to match your configuration)
sudo rm /usr/local/var/run/php-fpm/php-fpm.sock
# Start PHP-FPM again (this will recreate the socket)
brew services start [email protected]
# Restart Nginx
brew services restart nginx
This step is usually not necessary but can resolve rare edge cases where the socket file itself becomes problematic.
By following these systematic troubleshooting steps, you should be able to identify and resolve the Nginx 502 Bad Gateway error caused by PHP-FPM Unix socket misconfigurations on your macOS local environment.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.