Introduction

When PHP-FPM is restarted or reloaded, Apache connections to PHP-FPM via mod_proxy_fcgi can fail with "Connection refused" errors. This happens because the PHP-FPM socket file may be removed and recreated during restart, or TCP connections are dropped before Apache's connection pool notices. The error log shows:

bash
[Tue Apr 09 00:15:00.123456 2026] [proxy:error] [pid 5678] (111)Connection refused: AH00957: FCGI: attempt to connect to Unix domain socket /run/php/php8.2-fpm.sock failed

Symptoms

  • 503 Service Unavailable for all PHP pages immediately after PHP-FPM restart
  • Apache error log shows "Connection refused" to PHP-FPM socket
  • Error lasts from a few seconds to several minutes after PHP-FPM restart
  • Static files serve correctly; only PHP requests fail
  • Socket file exists at the expected path but Apache cannot connect

Common Causes

  • PHP-FPM socket file is removed before the new one is created during restart
  • Apache's connection pool still holds references to the old (deleted) socket
  • PHP-FPM pool starts listening on a different socket path after configuration change
  • TCP backlog queue overflow when many Apache connections attempt to reconnect simultaneously
  • PHP-FPM process takes time to initialize pools before accepting connections

Step-by-Step Fix

  1. 1.Configure PHP-FPM socket with proper permissions. Edit /etc/php/8.2/fpm/pool.d/www.conf:
  2. 2.```ini
  3. 3.listen = /run/php/php8.2-fpm.sock
  4. 4.listen.owner = www-data
  5. 5.listen.group = www-data
  6. 6.listen.mode = 0660
  7. 7.`
  8. 8.Ensure the socket directory exists and is writable:
  9. 9.```bash
  10. 10.sudo mkdir -p /run/php
  11. 11.sudo chown www-data:www-data /run/php
  12. 12.`
  13. 13.Use TCP instead of Unix socket for more resilient connections during restarts:
  14. 14.In PHP-FPM pool config:
  15. 15.```ini
  16. 16.listen = 127.0.0.1:9000
  17. 17.`
  18. 18.In Apache VirtualHost:
  19. 19.```apache
  20. 20.<FilesMatch \.php$>
  21. 21.SetHandler "proxy:fcgi://127.0.0.1:9000"
  22. 22.</FilesMatch>
  23. 23.`
  24. 24.TCP connections handle restart scenarios more gracefully than Unix sockets.
  25. 25.Configure Apache proxy retry behavior:
  26. 26.```apache
  27. 27.<Proxy "fcgi://127.0.0.1:9000">
  28. 28.ProxySet retry=5
  29. 29.</Proxy>
  30. 30.`
  31. 31.Or for Unix socket:
  32. 32.```apache
  33. 33.<FilesMatch \.php$>
  34. 34.SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost/"
  35. 35.</FilesMatch>
  36. 36.`
  37. 37.Implement graceful PHP-FPM reload instead of restart:
  38. 38.```bash
  39. 39.# Use reload instead of restart - this waits for in-flight requests
  40. 40.sudo systemctl reload php8.2-fpm

# Or send USR2 signal for graceful reload sudo kill -USR2 $(cat /run/php/php8.2-fpm.pid) ```

  1. 1.Add a health check wrapper for PHP-FPM restarts:
  2. 2.```bash
  3. 3.#!/bin/bash
  4. 4.sudo systemctl reload php8.2-fpm
  5. 5.for i in {1..10}; do
  6. 6.if curl -sf http://localhost/health.php > /dev/null; then
  7. 7.echo "PHP-FPM is healthy"
  8. 8.exit 0
  9. 9.fi
  10. 10.echo "Waiting for PHP-FPM... attempt $i"
  11. 11.sleep 1
  12. 12.done
  13. 13.echo "PHP-FPM failed to become healthy"
  14. 14.exit 1
  15. 15.`

Prevention

  • Always use systemctl reload instead of systemctl restart for PHP-FPM to avoid dropping the socket
  • Monitor PHP-FPM pool status via the status page: enable pm.status_path = /fpm-status
  • Use TCP connections (127.0.0.1:9000) instead of Unix sockets in high-availability setups
  • Add PHP-FPM health monitoring: systemctl status php8.2-fpm && curl -sf http://localhost/health.php
  • Keep PHP-FPM pm.start_servers high enough to handle connection bursts after restart
  • Deploy PHP-FPM configuration changes during low-traffic windows with proper rollback procedures