Fehlercode 500 in Apache nach PHP-FPM-Restart ist ein typischer Betriebsfall: Ein geplanter Restart, ein Security-Patch oder ein automatisches Deployment — und danach liefern PHP-Endpunkte plötzlich generische HTTP 500. In den meisten Fällen liegt die Ursache an der Integrationskante zwischen Apache (Webserver) und PHP-FPM (FastCGI Process Manager). FastCGI ist das Protokoll zur Übergabe von HTTP-Requests an PHP-Prozesse; Socket bezeichnet hier entweder eine Unix-Domain-Socket-Datei oder einen TCP-Port. Pools sind FPM-Prozessgruppen mit eigenen Einstellungen.
Fehlercode 500 in Apache nach PHP-FPM-Restart: Ursachen & Vorgehen
HTTP 500 ist eine Sammelantwort des Webservers und bedeutet: Der Backend-Aufruf ist fehlgeschlagen oder abgebrochen. Beim PHP-FPM-Setup sind typische Ursachen: Socket/Port nicht erreichbar, falsche Besitz-/Rechte, Mandatory-Access-Control (SELinux/AppArmor), Timeouts bei Kaltstart, oder eine unpassende Pool-Dimensionierung. Dieser Beitrag zeigt eine priorisierte Prüfreihenfolge, konkrete Commands und nachhaltige Maßnahmen — mit Fokus auf Betrieb, Monitoring und Rollback.
Kurzcheck: Stimmen Zeitpunkt und Ursache?
Verifizieren Sie zuerst, ob der 500er wirklich mit dem PHP-FPM-Restart zusammenfällt. Sonst investieren Sie Zeit an der falschen Komponente (z. B. Datenbank, Netzwerk oder Storage).
Typische Indikatoren für FPM-/FastCGI-Probleme
- Apache-Error-Log: Meldungen mit „proxy_fcgi“, „AH01079“, „AH02454“, „Connection refused“ oder „Primary script unknown“.
- FPM-Logs/journal: fehlende „ready to handle connections“ oder Bind-/Listen-Fehler.
- Statische Inhalte werden ausgeliefert, dynamische PHP-Endpunkte nicht.
Pragmatische Prüfreihenfolge (Runbook)
Arbeiten Sie sequentiell: Dienste/Logs → Socket/Port → Apache-Config → Rechte/Policies → Ressourcen/Timeouts → Pool-Parameter. Dokumentieren Sie jede Erkenntnis für das Incident-Ticket.
1) Dienste und Logs parallel prüfen
journald liefert schnelle Hinweise, ergänzt durch Apache-Error-Log und FPM-Logdateien.
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-pagerWarum: So sehen Sie Startfehler, Bind-Probleme oder Permission-Denieds unmittelbar. Kopieren Sie präzise Log-Zeilen in das Ticket.
2) Socket/Port prüfen
Prüfen Sie, ob FPM auf dem erwarteten Endpoint horcht: Unix-Socket oder TCP-Port (z. B. 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 | headWarum: Nach Updates ändern sich Pfade; Apache könnte auf einen alten Socket zeigen. Existiert der Socket, ist der nächste Schritt Rechte- und Policy-Prüfung.
3) Apache-Konfiguration anschauen
Ermitteln Sie, wie Apache PHP-Aufrufe weiterleitet: mod_proxy_fcgi (empfohlen) oder mod_fcgid. Stimmen die Zielpfade mit FPM-listen überein?
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 80Warum: Häufig zeigt ein vHost noch auf einen alten Socket. Zentral konfigurierte Include-Dateien reduzieren Fehlerquellen.
4) Rechte: Socket-Besitz, Modi und Verzeichnisse
Ein Unix-Socket ist eine Datei mit Owner/Group/Mode. Apache läuft z. B. als www-data (Debian) oder apache (RHEL). Fehlt das Traversal-Bit auf Elternverzeichnissen, kann Apache den Socket nicht erreichen, auch wenn der Socket selbst offen aussieht.
# 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 -uWarum: /run ist tmpfs; nach Restart entstehen Runtime-Verzeichnisse neu und benötigen explizite Besitz-/Modus-Einstellungen, sonst stimmt die Verbindung nicht.
Konkrete Root Causes und wie man sie nachhaltig behebt
Socket-Pfadwechsel (Mehrere PHP-Versionen)
Bei mehreren PHP-Versionen auf einem Host ändert sich leicht der Socket-Name. Stabilisieren Sie Pfade durch eindeutige Listen oder ordnen Sie pro vHost die gewünschte PHP-Version zu.
; Beispiel pool-Konfiguration
listen = /run/php/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660Tipp: Vermeiden Sie, dass mehrere Pools denselben Socket verwenden — sie brauchen eigene Endpoints oder TCP-Ports.
Falsche Socket-Rechte nach Restart
Setzen Sie listen.owner/listen.group/listen.mode in der Pool-Datei; prüfen Sie, dass der Apache-User Mitglied in der Gruppe ist oder passen Sie die Group an.
# 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 httpdWarum: Ein temporärer Modus 0666 löst kurzfristig Zugriffsprobleme, erhöht aber Angriffsfläche. Besser ist eine explizite Ownership und Gruppenmitgliedschaft.
SELinux/AppArmor blockiert Verbindungen
Mandatory Access Control (MAC) wie SELinux oder AppArmor kann Socket-Zugriff verhindern, auch wenn Unix-Rechte korrekt sind. Prüfen Sie AVC- oder AppArmor-DENIED-Einträge.
# 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 || trueWarum: MAC-Policies sind sehr effektiv, können aber bei Laufzeitpfaden ohne passende Labels Verbindungsabbrüche verursachen. Policy-Änderungen müssen über Change-Management erfolgen; Deaktivieren ist nur kurzfristig erlaubt.
Stale Socket/Port oder verwaiste PID
Manchmal bleibt eine Socket-Datei bestehen oder ein anderweitiger Prozess belegt den Port. Prüfen mit ss/lsof und bereinigen, aber löschen Sie Sockets nur, wenn kein Prozess sie verwendet.
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-fpmWarum: Unbedachtes Löschen kann aktive Verbindungen abbrechen. Prüfen Sie PID-Informationen vorher.
Timeouts, OpCache-Kaltstart und Load-Balancer
Nach einem Restart sind Caches leer; erste Requests dauern länger. Wenn Apache oder ein Load-Balancer Timeouts zu kurz sind, werden Requests abgebrochen und Clients sehen 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 40Gegenmaßnahmen: Timeouts moderat erhöhen, OpCache-Warmup bei Deploys und ein gestaffeltes Restart-Verfahren: Pools zuerst warmlaufen lassen, dann Traffic zulassen.
pm.max_children und Prozessmanagement
Wenn zu wenige Worker verfügbar sind, staut sich die Queue. Nach Restart treten Engpässe sofort auf, weil Worker neu initialisieren. Dimensionieren Sie pm.max_children anhand gemessener Memory- und CPU-Kennzahlen.
pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 16
pm.max_requests = 500Warum: Ein zu niedrig gewählter Wert führt zu sofortigen Ablehnungen; zu hoch belastet den Server. Messen Sie Konsum pro Worker und testen unter Last.
Primary script unknown: Pfad-/chroot-/open_basedir-Probleme
Wenn FPM das Zielskript nicht öffnen kann, meldet FPM „Primary script unknown“ und Apache liefert 500. Prüfen Sie DocumentRoot, Proxy-Pfad, chroot-Einstellungen oder open_basedir-Beschränkungen.
Praxis: Troubleshooting-Skripte und Runbook-Snippets
Systemd-Integration: RuntimeDirectory und tmpfiles.d
Systemd kann sicherstellen, dass /run/php mit korrekten Rechten vor dem Start existiert. Nutzen Sie RuntimeDirectory im Unit-File oder eine tmpfiles.d-Konfiguration.
# 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 -
Warum: So entsteht das Verzeichnis immer mit korrektem Owner/Mode vor dem Dienststart — vermeidet Race-Conditions beim Boot/Restart.
Fallback auf TCP: Konfiguration & Hinweise
Als kurzfristigen Diagnose-Bypass kann das Umschalten von Unix-Socket auf TCP (127.0.0.1:9000) helfen, da viele Rechte- und MAC-Probleme umgangen werden. Dauerhaft bringt TCP aber Latenz, weniger feingranulare Zugriffskontrolle und mögliche Port-Kollisionen.
; 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"
Wann scheitert das: Wenn Infrastruktur-Firewalls lokale TCP-Policies haben oder wenn mehrere Prozesse auf dem Port laufen.
OpCache-Warmup-Skript (einfaches Beispiel)
Ein scripted Warmin kann beim Deploy oder Restart die OpCache-Einträge füllen und so Kaltstart-Latenzen reduzieren.
#!/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
Warum: Reduziert die Lastspitzen und Timeouts bei den ersten Benutzeranfragen nach Restart. Testen Sie das im Staging.
Schnelles Rollback-Skript: Socket ↔ TCP Umschalten
#!/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
Warum: Ein kontrollierter Rollback minimiert Downtime. Testen Sie das Skript in einer sicheren Umgebung bevor Sie es in Prod einsetzen.
Monitoring, Alarme und Prävention
Ergänzen Sie generisches 5xx-Monitoring durch spezifische Indikatoren: Apache-Error-Log-Muster (proxy_fcgi), FPM-Pool-Stats (active processes, listen queue), pm.max_children-Alarme sowie Systemmetrik (RAM/IO). So unterscheiden Sie Kaltstart-Effekte von strukturellen Engpässen.
Empfehlungen für Alerts
- Alarm bei wiederholten AH01079/AH02454-Zeilen in Apache-Error-Log innerhalb kurzer Zeit.
- FPM: Alert wenn listen queue > 0 dauerhaft oder „reached pm.max_children“ in Logs.
- System: hoher Swap-/I/O-Util oder OOM-Killer-Einträge unmittelbar vor 500er-Fällen.
Post-Incident: Root-Cause-Analyse und präventive Maßnahmen
Nach einer kurzfristigen Behebung führen Sie immer eine strukturierte RCA durch: Welche Änderung hat den Fehler ausgelöst? War es ein Update, eine Konfig-Änderung oder ein Race-Condition beim Start? Passen Sie Konfigurationsmanagement (Git), Change-Templates für Pools und systemd-Overrides an und dokumentieren Sie die Lessons Learned im Runbook.
Checkliste für ein Incident-Ticket (kompakt)
- Zeitpunkt des Restarts und Dauer des Vorfalls
- Genaue Apache-Error-Log-Zeilen
- FPM-Journal-Auszug rund um Restart
- ss/ls/find-Ausgabe für Socket/Port
- namei -l Output des Socket-Pfads
- SELinux/AppArmor-Status und relevante AVC/deny-Zeilen
- Memory/IO/CPU-Kurz-Metriken
- Ob Umschalten auf TCP geholfen hat (ja/nein)
Praktische Best Practices und Betriebswissen
- Versionieren Sie Pool- und Apache-Includes in Git; Deploys nur über CI mit Tests.
- Nutzen Sie systemd RuntimeDirectory oder tmpfiles.d, damit /run/php korrekt vorbereitet wird.
- Labels für SELinux früh im Change-Prozess berücksichtigen, nicht ad-hoc.
- Implementieren Sie Healthchecks und Warmup-Skripte für Neustarts.
- Testen Sie Rollback-Skripte, bevor Sie sie als Notfall-Tool dokumentieren.
Fazit
Ein 500er nach PHP-FPM-Restart ist in den meisten Fällen ein Integrationsproblem an der Schnittstelle Apache ↔ PHP-FPM: Socket/Port, Ownership/Mode, MAC-Policies, Timeouts und Pool-Dimensionierung sind die typischen Ursachen. Die nachhaltige Lösung kombiniert sofortige, loggetriebene Fehleranalyse mit dauerhaften Maßnahmen: stabile Socket-Pfade, explizite Ownership in Pool-Dateien, systemd-Integration für Runtime-Verzeichnisse, passende SELinux/AppArmor-Labels, Warmup-Verfahren und gezieltes Monitoring. Zusätzlich reduzieren getestete Rollback-Mechanismen und dokumentierte Runbooks das Risiko von Folgevorfällen.
Nutzen Sie die obenstehenden Prüfschritte als Incident-Template und fertigen Sie nach jeder Störung eine RCA und Policy-Anpassung an. So wird der nächste PHP-FPM-Restart wieder zur Routineoperation.
Betriebsaspekte: Orchestrierung, Healthchecks und Container
Automatisierte Restarts durch systemd, Configuration-Management oder Orchestratoren können Race-Conditions erzeugen, wenn Load‑Balancer oder Frontends nicht drained werden. Planen Sie gestaffelte Neustarts mit Drain‑Phasen und Healthchecks (readiness/liveness), damit Sessions und eingehende Verbindungen kontrolliert abgebaut werden.
Systemd-Socket-Activation kann hier ein stabiler Baustein sein: Die Socket-Unit hält den Endpunkt über Restartzyklen hinweg und reduziert „Connection refused“-Fälle. Achten Sie aber auf Runtime‑Verzeichnisse und tmpfs-Persistenz.
In Container-Setups sind Unix-Sockets auf OverlayFS oder in gemounteten Volumes anfälliger für Berechtigungs- und Inode-Probleme; prüfen Sie deshalb TCP-Bindings oder dedizierte Shared-Volumes mit klaren Ownership-Rules.
Verbessern Sie Observability: korrelieren Sie Apache- und FPM-Logs via Request‑IDs und exportieren Sie Pool‑Metriken (listen‑queue, active) zur frühzeitigen Alarmierung.
Für dieses Thema sind auch Apache Http 500 und Php-Fpm Socket wichtig. Der Beitrag ordnet diese Aspekte verständlich ein und zeigt, worauf es im Alltag ankommt.