HTTP 500 in Apache after PHP-FPM RESTart is a typical operational case: a planned RESTart, a security patch or an automated deployment — and suddenly PHP endpoints return generic HTTP 500. In most cases the cause lies at the integration edge between Apache (web server) and PHP-FPM (FastCGI Process Manager). FastCGI is the protocol for handing HTTP requests to PHP processes; socket here refers to either a Unix domain socket file or a TCP port. Pools are FPM process groups with their own settings.
HTTP 500 in Apache after PHP-FPM RESTart: Causes & Procedure
HTTP 500 is a catch-all response from the web server and means: the backend call failed or aborted. In a PHP-FPM setup typical causes are: socket/port unreachable, incorrect owner/permissions, Mandatory-Access-Control (SELinux/AppArmor), cold-start timeouts, or inappropriate pool sizing. This article shows a prioritized verification sequence, concrete commands and sustainable measures — with a focus on operations, monitoring and rollback.
Quick check: Do timing and cause match?
First verify whether the 500 actually coincides with the PHP-FPM RESTart. Otherwise you may spend time on the wrong component (e.g. database, network or storage).
Typical indicators of FPM/FastCGI problems
- Apache error log: messages containing „proxy_fcgi“, „AH01079“, „AH02454“, „Connection refused“ or „Primary script unknown“.
- FPM logs/journal: missing „ready to handle connections“ or bind/listen errors.
- Static content is served, dynamic PHP endpoints are not.
Pragmatic check sequence (Runbook)
Work sequentially: services/logs → socket/port → Apache config → permissions/policies → resources/timeouts → pool parameters. Document every finding for the incident ticket.
1) Check services and logs in parallel
journald provides quick hints, complemented by the Apache error log and FPM log files.
systemctl status apache2 --no-pager || systemctl status httpd --no-pager
systemctl status php-fpm --no-pager || systemctl status php8.2-fpm --no-pager
journalctl -u php-fpm -n 200 --no-pager
journalctl -u apache2 -n 200 --no-pager || journalctl -u httpd -n 200 --no-pagerWhy: This shows start errors, bind problems or permission denials immediately. Copy precise log lines into the ticket.
2) Check socket/port
Check whether FPM is listening on the expected endpoint: Unix socket or TCP port (e.g. 127.0.0.1:9000).
ss -ltnp | grep -E 'php-fpm|:9000' || true
ss -lxnp | grep -E 'php-fpm|fpm' || true
ls -lah /run/php || true
find /run -maxdepth 3 -type s -name '*fpm*.sock' -ls 2>/dev/null | headWhy: Paths can change after updates; Apache might point to an old socket. If the socket exists, the next step is permissions and policy inspection.
3) Inspect Apache configuration
Determine how Apache forwards PHP requests: mod_proxy_fcgi (recommended) or mod_fcgid. Do the target paths match FPM’s listen configuration?
apache2ctl -M 2>/dev/null | grep -E 'proxy|fcgi' || httpd -M 2>/dev/null | grep -E 'proxy|fcgi'
apache2ctl -S 2>/dev/null || httpd -S 2>/dev/null
grep -R --line-number -E 'proxy_fcgi|SetHandler|FilesMatch|.sock|:9000' /etc/apache2 /etc/httpd 2>/dev/null | head -n 80Why: Often a vHost still points to an old socket. Centrally configured include files reduce sources of error.
4) Permissions: socket ownership, modes and directories
A Unix socket is a file with owner/group/mode. Apache runs, for example, as www-data (Debian) or apache (RHEL). If the traversal bit is missing on parent directories, Apache cannot reach the socket even if the socket itself appears open.
# Beispiel: Socket prüfen
SOCK="/run/php/php-fpm.sock" # anpassen
ls -lah "${SOCK}" 2>/dev/null || true
namei -l "${SOCK}" 2>/dev/null || true
# Apache-User ermitteln
ps -eo user,comm | awk '$2 ~ /apache2|httpd/ {print $1}' | sort -uWhy: /run is tmpfs; after a RESTart runtime directories are recreated and require explicit ownership/mode settings, otherwise the connection will fail.
Concrete root causes and how to remediate them permanently
Socket path changes (multiple PHP versions)
With multiple PHP versions on one host the socket name can easily change. Stabilize paths by using explicit listen directives or assign the desired PHP version per vHost.
; Beispiel pool-Konfiguration
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660Tip: Avoid having multiple pools use the same socket — they need separate endpoints or TCP ports.
Incorrect socket permissions after RESTart
Set listen.owner/listen.group/listen.mode in the pool file; verify that the Apache user is a member of the group or adjust the group accordingly.
# Apache in Gruppe aufnehmen (sorgfältig verwenden)
usermod -aG www-data apache 2>/dev/null || usermod -aG www-data www-data 2>/dev/null
systemctl reload apache2 || systemctl reload httpdWhy: A temporary mode of 0666 resolves access issues in the short term but increases the attack surface. Explicit ownership and group membership are preferable.
SELinux/AppArmor blocks connections
Mandatory Access Control (MAC) such as SELinux or AppArmor can prevent socket access even when Unix permissions are correct. Check AVC or AppArmor DENIED entries.
# SELinux prüfen
getenforce 2>/dev/null || true
ausearch -m avc -ts recent | tail -n 40 || true
# Falls SELinux aktiv ist: Socket-Context setzen
semanage fcontext -a -t httpd_var_run_t '/run/php(/.*)?' || true
RESTorecon -Rv /run/php || true
# AppArmor prüfen
aa-status 2>/dev/null || true
journalctl -k | grep -i apparmor | tail -n 40 || trueWhy: MAC policies are effective but can cause connection failures for runtime paths without appropriate labels. Policy changes must go through change management; disabling is only acceptable as a short-term measure.
Stale socket/port or orphaned PID
Sometimes a socket file remains or another process occupies the port. Check with ss/lsof and clean up, but only remove sockets if no process is using them.
ss -ltnp | grep ':9000' || true
lsof /run/php/php-fpm.sock 2>/dev/null || true
# Wenn sicher: rm /run/php/php-fpm.sock && systemctl RESTart php-fpmWhy: Thoughtless deletion can terminate active connections. Inspect PID information beforehand.
Timeouts, OpCache cold start and load balancers
After a RESTart caches are empty; initial requests take longer. If Apache or a load balancer has too short timeouts, requests are aborted and clients see 500/502/504.
# Beispiel: Apache-Timeouts prüfen
apache2ctl -t -D DUMP_RUN_CFG 2>/dev/null | head -n 40 || true
# FPM: slowlog/request_terminate_timeout in Pool-Dateien prüfen
grep -R --line-number -E 'request_terminate_timeout|slowlog' /etc/php* 2>/dev/null | head -n 40Mitigations: increase timeouts moderately, perform OpCache warmup during deploys and use a staged RESTart procedure: bring pools up and warm them before allowing traffic.
pm.max_children and process management
If too few workers are available the queue backs up. After a RESTart bottlenecks occur immediately because workers reinitialize. Size pm.max_children based on measured memory and CPU metrics.
pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 16
pm.max_requests = 500Why: a value set too low causes immediate rejections; too high burdens the server. Measure consumption per worker and test under load.
Primary script unknown: path/chroot/open_basedir issues
If FPM cannot open the target script, FPM reports „Primary script unknown“ and Apache returns 500. Check DocumentRoot, proxy path, chroot settings or open_basedir RESTrictions.
Practical: troubleshooting scripts and runbook snippets
Systemd integration: RuntimeDirectory and tmpfiles.d
Systemd can ensure that /run/php exists with correct permissions before start. Use RuntimeDirectory in the unit file or a tmpfiles.d configuration.
# Beispiel systemd-Override (speichern unter /etc/systemd/system/php-fpm.service.d/10-run.conf)
[Service]
RuntimeDirectory=php
RuntimeDirectoryMode=0755
RuntimeDirectoryPreserve=yes
# tmpfiles.d Alternative (z. B. /etc/tmpfiles.d/php-fpm.conf)
# d /run/php 0755 www-data www-data -
Why: this ensures the directory is always created with the correct owner/mode before service start — avoids race conditions during boot/RESTart.
Fallback to TCP: configuration & considerations
As a short-term diagnostic bypass, switching from a Unix socket to TCP (127.0.0.1:9000) can help, since many permission and MAC issues are avoided. However, permanently using TCP introduces latency, less fine-grained access control and potential port collisions.
; php-fpm pool.conf
; unix socket
;listen = /run/php/php-fpm.sock
; TCP alternative
listen = 127.0.0.1:9000# Apache ProxyPassMatch Beispiel TCP
# In vHost
SetHandler "proxy:fcgi://127.0.0.1:9000"
When this fails: if infrastructure firewalls enforce local TCP policies or if multiple processes are listening on the port.
OpCache warmup script (simple example)
A scripted warmup can populate the OpCache entries during deploy or RESTart and thus reduce cold-start latencies.
#!/bin/bash
# opcache-warmup.sh - ruft eine Liste relevanter URLs sequentiell ab
URLS=( "/" "/login" "/app/home" )
HOST="https://localhost"
for u in "${URLS[@]}"; do
curl -ksS --fail "${HOST}${u}" >/dev/null || echo "Warmup failed for ${u}"
sleep 0.5
done
Why: reduces load spikes and timeouts for the first user requests after a RESTart. Test this in staging.
Quick rollback script: switching Socket ↔ TCP
#!/bin/bash
# rollback-to-tcp.sh - schaltet Pool auf TCP um und reloadet Dienste
POOL_CONF="/etc/php/8.2/fpm/pool.d/www.conf"
cp ${POOL_CONF} ${POOL_CONF}.bak.$(date +%s)
sed -i 's|listen = /run/php/php-fpm.sock|listen = 127.0.0.1:9000|' ${POOL_CONF}
systemctl RESTart php-fpm && systemctl reload apache2 || systemctl RESTart httpd
Why: A controlled rollback minimizes downtime. Test this script in a safe environment before deploying it to Prod.
Monitoring, alerts and prevention
Supplement generic 5xx monitoring with specific indicators: Apache error-log patterns (proxy_fcgi), FPM pool stats (active processes, listen queue), pm.max_children alerts and system metrics (RAM/IO). This lets you distinguish cold-start effects from structural bottlenecks.
Recommendations for alerts
- Alert on repeated AH01079/AH02454 lines in the Apache error log within a short time.
- FPM: alert if the listen queue > 0 persistently or „reached pm.max_children“ appears in logs.
- System: high swap/I/O utilization or OOM-killer entries immediately before 500-class incidents.
Post-incident: root-cause analysis and preventive measures
After a short-term remediation, always perform a structured RCA: Which change triggered the error? Was it an update, a configuration change or a race condition at startup? Adjust configuration management (Git), change templates for pools and systemd overrides and document the lessons learned in the runbook.
Checklist for an incident ticket (compact)
- Timestamp of the RESTart and duration of the incident
- Exact Apache error log lines
- FPM journal excerpt around the RESTart
- ss/ls/find output for socket/port
- namei -l output of the socket path
- SELinux/AppArmor status and relevant AVC/deny lines
- Short memory/IO/CPU metrics
- Whether switching to TCP helped (yes/no)
Practical best practices and operational knowledge
- Version pool and Apache includes in Git; deploy only via CI with tests.
- Use systemd RuntimeDirectory or tmpfiles.d so /run/php is prepared correctly.
- Consider labels for SELinux early in the change process, not ad hoc.
- Implement health checks and warmup scripts for RESTarts.
- Test rollback scripts before documenting them as an emergency tool.
Conclusion
A 500 after a PHP-FPM RESTart is in most cases an integration issue at the Apache ↔ PHP-FPM interface: socket/port, ownership/mode, MAC policies, timeouts and pool sizing are the typical causes. The sustainable solution combines immediate, log-driven error analysis with permanent measures: stable socket paths, explicit ownership in pool files, systemd integration for runtime directories, appropriate SELinux/AppArmor labels, warmup procedures and targeted monitoring. Additionally, tested rollback mechanisms and documented runbooks reduce the risk of follow-up incidents.
Use the checklist above as an incident template and perform an RCA and policy adjustment after every outage. That way the next PHP-FPM RESTart becomes a routine operation.
Operational aspects: orchestration, health checks and containers
Automated RESTarts by systemd, configuration management, or orchestrators can create race conditions if load‑balancers or frontends are not drained. Plan staggered RESTarts with drain phases and health checks (readiness/liveness) so that sessions and incoming connections are torn down in a controlled manner.
systemd socket activation can be a stable building block here: the socket unit holds the endpoint across RESTart cycles and reduces „Connection refused“ cases. However, pay attention to runtime directories and tmpfs persistence.
In container setups, Unix sockets on OverlayFS or in mounted volumes are more prone to permission and inode issues; therefore check TCP bindings or dedicated shared volumes with clear ownership rules.
Improve observability: correlate Apache and FPM logs via request‑IDs and export pool metrics (listen‑queue, active) for early alerting.
For this topic, Apache Http 500 and Php-Fpm Socket are also important. The article places these aspects into context and shows what matters in day-to-day operations.