Troubleshooting Nginx 502 Bad Gateway with PHP-FPM Unix Socket on Ubuntu 22.04 LTS
Resolve Nginx 502 Bad Gateway errors when using PHP-FPM via a Unix socket on Ubuntu 22.04 LTS. A definitive guide for common misconfigurations and resource issues.
Resolve Nginx 502 Bad Gateway errors when using PHP-FPM via a Unix socket on Ubuntu 22.04 LTS. A definitive guide for common misconfigurations and resource issues.
A "502 Bad Gateway" error is a common and often frustrating issue encountered when Nginx acts as a reverse proxy for a backend application server like PHP-FPM. Specifically, when Nginx is configured to communicate with PHP-FPM using a Unix socket on Ubuntu 22.04 LTS, this error indicates that Nginx was able to connect to PHP-FPM but received an invalid response, no response at all, or the connection was prematurely closed. This guide provides a highly technical, step-by-step approach to diagnosing and resolving this issue.
Symptom & Error Signature
When a 502 Bad Gateway error occurs, users typically see a generic error page in their web browser, often stating "502 Bad Gateway" or "Nginx 502 Bad Gateway." The more critical indicators, however, are found in your server's log files.
Typical Nginx Error Log Entries (/var/log/nginx/error.log):
2023/10/26 14:35:01 [crit] 12345#12345: *123 connect() to unix:/var/run/php/php8.1-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 192.168.1.10, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.1-fpm.sock:", host: "example.com"
2023/10/26 14:35:02 [crit] 12346#12346: *124 connect() to unix:/var/run/php/php8.1-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.1.10, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.1-fpm.sock:", host: "example.com"
2023/10/26 14:35:03 [error] 12347#12347: *125 upstream prematurely closed connection while reading response header from upstream, client: 192.168.1.10, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.1-fpm.sock:", host: "example.com"
2023/10/26 14:35:04 [error] 12348#12348: *126 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.1.10, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.1-fpm.sock:", host: "example.com"
These specific messages provide crucial clues about the underlying problem.
Root Cause Analysis
The 502 Bad Gateway error, in this context, signifies a communication breakdown between Nginx and PHP-FPM. Nginx, acting as the frontend web server, attempts to pass PHP requests to PHP-FPM, which processes the PHP code and returns the output. When a Unix socket is used, this communication relies on a special file (the socket) residing in the filesystem.
The primary reasons for a 502 error in this setup are:
- PHP-FPM Service Status: PHP-FPM is not running, has crashed, or is unable to start, meaning the Unix socket file doesn't exist or isn't actively listened to.
- Socket Path Mismatch: Nginx is configured to connect to a different Unix socket path than where PHP-FPM is actually listening.
- Permissions Issues: Nginx, running as the
www-datauser, lacks the necessary read/write permissions to access the PHP-FPM Unix socket file or its parent directory. - PHP-FPM Resource Exhaustion or Instability: PHP-FPM processes might be crashing due to script errors, memory limits, execution timeouts, or the process pool has run out of available children to handle requests.
- Nginx Timeouts: Nginx itself might be timing out waiting for a response from PHP-FPM, especially for long-running PHP scripts.
- AppArmor/SELinux Restrictions: While less common on default Ubuntu 22.04 installations, security modules like AppArmor could be preventing Nginx from accessing the socket or PHP-FPM from creating it.
Step-by-Step Resolution
Follow these steps sequentially to diagnose and resolve the Nginx 502 Bad Gateway error.
1. Verify PHP-FPM Service Status
The most common reason for a 502 is PHP-FPM not running.
Check PHP-FPM service status: Ubuntu 22.04 LTS typically uses PHP 8.1. Adjust the version number (
8.1) if you are using a different one.sudo systemctl status php8.1-fpmYou should see output similar to
active (running).If PHP-FPM is not running: Start and enable the service.
sudo systemctl start php8.1-fpm sudo systemctl enable php8.1-fpmExamine PHP-FPM logs for startup errors: If PHP-FPM fails to start or crashes immediately, its logs will contain crucial information.
sudo journalctl -u php8.1-fpm -n 50 --no-pagerLook for
ERROR,WARNING, orCRITICALmessages indicating configuration issues, memory problems, or permission errors.Attempt to restart PHP-FPM (even if running): A simple restart can sometimes resolve transient issues.
sudo systemctl restart php8.1-fpm
2. Confirm PHP-FPM Socket Path and Listening Configuration
A mismatch between where Nginx expects the socket and where PHP-FPM creates it is a frequent cause.
Identify Nginx's configured socket path: Open your Nginx site configuration file (e.g.,
/etc/nginx/sites-available/your_site.conf). Locate thelocation ~ .php$block and thefastcgi_passdirective.sudo nano /etc/nginx/sites-available/your_site.confLook for a line similar to:
location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # <-- This path # ... other fastcgi parameters }Note down the exact path after
unix:.Identify PHP-FPM's listening socket path: Open your PHP-FPM pool configuration file (e.g.,
/etc/php/8.1/fpm/pool.d/www.conf).sudo nano /etc/php/8.1/fpm/pool.d/www.confLook for the
listendirective:listen = /run/php/php8.1-fpm.sock # <-- This pathThe path specified in
fastcgi_passin Nginx MUST exactly match thelistenpath in your PHP-FPM pool configuration. Pay close attention to/var/run/phpvs./run/php– these are often symlinked but can cause issues if not consistent./runis the standard for systemd.Verify the socket file exists: After ensuring both Nginx and PHP-FPM configurations match and PHP-FPM is running, check if the socket file is actually created.
ls -l /run/php/php8.1-fpm.sock # Or your specific path, e.g., ls -l /var/run/php/php8.1-fpm.sockIf the file does not exist, check PHP-FPM logs again (
journalctl -u php8.1-fpm) for errors during socket creation.Reload Nginx and PHP-FPM if paths were changed:
sudo systemctl reload php8.1-fpm sudo systemctl reload nginx
3. Check Socket Permissions
Even if the socket path matches and PHP-FPM is running, Nginx might not have permission to access it.
Inspect socket permissions: Use
ls -lon the socket file.ls -l /run/php/php8.1-fpm.sockA typical healthy output looks like:
srw-rw-rw- 1 www-data www-data 0 Oct 26 14:30 /run/php/php8.1-fpm.sockThis indicates a socket file (
sat the beginning) owned bywww-data:www-datawith read/write permissions for everyone.Verify PHP-FPM pool user/group: In
/etc/php/8.1/fpm/pool.d/www.conf, ensure thelisten.owner,listen.group, andlisten.modedirectives are correctly set.listen.owner = www-data listen.group = www-data listen.mode = 06600660ensures that the owner (www-data) and group (www-data) have read/write access. Nginx typically runs as thewww-datauser, so being in the same group allows access.0666or0777can also work but are less secure.0660is generally preferred.Confirm Nginx user is in the PHP-FPM group: By default, both Nginx and PHP-FPM run under the
www-datauser and group on Ubuntu. Verify this for Nginx:grep "user" /etc/nginx/nginx.confOutput usually shows
user www-data;. Then check thewww-datauser's groups:id www-dataIt should show
uid=33(www-data) gid=33(www-data) groups=33(www-data). If Nginx's user is different or not in the PHP-FPM socket's group, you might have a permission issue.Adjust if necessary: If
listen.owner,listen.group, orlisten.modewere changed inwww.conf, restart PHP-FPM:sudo systemctl restart php8.1-fpm
4. Investigate PHP-FPM Logs for Crashes or Errors
If the connection is made but Nginx receives an invalid response or connection resets, PHP-FPM itself might be encountering fatal errors or running into resource limits.
Monitor PHP-FPM logs in real-time:
sudo journalctl -u php8.1-fpm -fThen try to access your website. Watch for any PHP fatal errors, warnings, or notices related to script execution, memory exhaustion, or child process exits. Look for messages like
child exited with code 70ormemory limit of XXXXX bytes exceeded.Check application-specific PHP error logs: Many PHP applications (e.g., WordPress, Laravel) have their own error logging mechanisms. Consult your application's documentation to find its error log location and review it for specific script failures.
5. Adjust PHP-FPM Process Management Settings & Resource Limits
PHP-FPM might be unable to handle the load or specific requests due to insufficient resources or aggressive timeout settings.
Edit PHP-FPM pool configuration:
sudo nano /etc/php/8.1/fpm/pool.d/www.confReview Process Manager (PM) settings:
pm = dynamic(default, good for varying loads) orpm = ondemand(saves memory for low traffic sites).pm = static(fixed number of children, good for high traffic and stable memory).pm.max_children: The maximum number of child processes that will be created.pm.start_servers: The number of children created on startup.pm.min_spare_servers: The minimum number of idle server processes.pm.max_spare_servers: The maximum number of idle server processes. Ifpm.max_childrenis too low, requests will queue or fail, leading to 502s. Monitor your system's RAM usage to determine appropriate values.
Increasing
pm.max_childrensubstantially without sufficient physical RAM will lead to swapping, severely degrading performance and potentially crashing the server.Adjust
request_terminate_timeout: This setting in PHP-FPM defines how long a single PHP script can run before PHP-FPM kills it. If your scripts are long-running (e.g., processing large files, complex database queries), this can cause 502s if the script times out.request_terminate_timeout = 300s # Example: 5 minutes. Default is often 0 (off) or 30s.Set this to a value higher than your longest expected script execution time.
Increase
php_admin_value[memory_limit]: If PHP scripts are exhausting memory, they will crash.php_admin_value[memory_limit] = 256M # Or 512M, 1G depending on your application needsThis value overrides the
memory_limitset inphp.inifor this specific pool.Restart PHP-FPM after changes:
sudo systemctl restart php8.1-fpm
6. Tune Nginx FastCGI Timeouts
Nginx has its own set of timeouts for FastCGI connections. If PHP-FPM is processing a request but takes too long, Nginx might give up prematurely.
Edit Nginx configuration: You can set these in your
serverblock,locationblock, or globally inhttpblock (e.g.,/etc/nginx/nginx.conf).sudo nano /etc/nginx/sites-available/your_site.confAdjust FastCGI timeout directives:
location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_read_timeout 300s; # How long Nginx waits for a response from PHP-FPM fastcgi_send_timeout 300s; # How long Nginx waits to send data to PHP-FPM fastcgi_connect_timeout 300s; # How long Nginx waits to connect to PHP-FPM # Optional: Buffer settings can sometimes help with large responses fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; }Increase Nginx timeouts after addressing potential PHP script performance issues. Using long timeouts as a primary fix without optimizing your PHP code is often a temporary workaround. Ensure
fastcgi_read_timeoutis at least as long as or longer than PHP-FPM'srequest_terminate_timeout.Test Nginx configuration and reload:
sudo nginx -t sudo systemctl reload nginx
7. AppArmor (Advanced / Rare)
Ubuntu 22.04 uses AppArmor for mandatory access control. In rare cases, a misconfigured or custom AppArmor profile could prevent Nginx from accessing the PHP-FPM socket.
Check AppArmor status:
sudo aa-statusThis will show which profiles are loaded and in what mode (enforce/complain).
Look for AppArmor denials in kernel logs:
sudo dmesg | grep -i apparmor sudo journalctl -k | grep -i apparmorLook for
DENIEDmessages involvingnginxorphp-fpmattempting to access/run/php/php8.1-fpm.sockor its parent directory.Temporary test (if suspected): If you suspect AppArmor is the cause, you can temporarily set the Nginx profile to 'complain' mode to see if the error disappears.
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx sudo systemctl restart nginxIf the 502 error goes away, you've identified an AppArmor issue. You would then need to modify the Nginx AppArmor profile to allow socket access, rather than leaving it in complain mode or disabled. Remember to revert to
aa-enforceonce done testing if this wasn't the issue.sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx sudo systemctl restart nginx
By methodically working through these steps, checking logs, and verifying configurations, you should be able to pinpoint and resolve the Nginx 502 Bad Gateway error stemming from PHP-FPM Unix socket communication issues on your Ubuntu 22.04 LTS server.