# PHP-FPM erklärt: Prozessmanager, Pools und Worker

> PHP-FPM erklärt: wie Master, Pools und Worker arbeiten, was pm static, dynamic und ondemand bedeuten und welche Pool-Einstellungen Sicherheit bringen.

Quelle: https://phpsos.de/php/php-fpm-erklaert/  
Stand: 25.10.2026  
Anbieter: PHP SOS, PHP-Notfallhilfe und Server-Sicherheit. Soforthilfe per WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wir%20brauchen%20Hilfe%20mit%20unserem%20PHP-Server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kurz gesagt:** PHP-FPM (FastCGI Process Manager) betreibt PHP als eigenen Dienst neben dem Webserver. Ein Master-Prozess verwaltet Pools, und jeder Pool startet Worker, die Anfragen über FastCGI bearbeiten. Pools lassen sich je Website mit eigenem Benutzer, eigenen Grenzen und gesperrten PHP-Einstellungen betreiben. Weil Worker viele Anfragen nacheinander bearbeiten, müssen sie nach einem PHP-Update alle neu gestartet werden.

## Was ist PHP-FPM?

Das PHP-Handbuch beschreibt FPM als primäre FastCGI-Implementierung von PHP mit Funktionen, die vor allem für stark belastete Websites nützlich sind. Aufgenommen wurde FPM mit PHP 5.3.3 als eigene SAPI, also als eigene Betriebsart. Ihr SAPI-Name lautet `fpm-fcgi`.

Der Unterschied zu mod_php: PHP läuft nicht im Webserver, sondern als eigener Dienst. Nginx, Apache oder ein anderer Webserver reicht PHP-Anfragen über das FastCGI-Protokoll weiter und erhält die fertige Antwort zurück. Webserver und PHP lassen sich dadurch unabhängig voneinander neu starten, konfigurieren und absichern. Wie FastCGI grundsätzlich funktioniert, steht unter [CGI und FastCGI](https://phpsos.de/php/cgi-und-fastcgi/).

## Master, Pools und Worker: das Prozessmodell

PHP-FPM besteht aus drei Ebenen:

1. **Master-Prozess:** liest die Konfiguration, öffnet die Sockets und startet oder beendet Worker. Er führt selbst keinen Anwendungscode aus.
2. **Pools:** Jeder Pool hat einen Namen, einen eigenen Socket oder Port, einen eigenen Unix-Benutzer und eigene PHP-Einstellungen. Das Handbuch nennt ausdrücklich unterschiedliche uid, gid, chroot, Umgebung und php.ini je Pool.
3. **Worker:** Prozesse eines Pools, die Anfragen annehmen und ausführen. Ein Worker bearbeitet nacheinander viele Anfragen, bevor er ersetzt wird.

Wie viele Worker laufen, bestimmt der Prozessmanager mit der Direktive `pm`:

| Modus | Verhalten | Wichtige Direktiven |
|---|---|---|
| `static` | feste Anzahl Worker | `pm.max_children` |
| `dynamic` | Worker zwischen Unter- und Obergrenze | `pm.start_servers`, `pm.min_spare_servers`, `pm.max_spare_servers` |
| `ondemand` | Worker erst bei Bedarf, Abbau nach Leerlauf | `pm.process_idle_timeout` (Standard 10s) |

`pm.max_children` begrenzt in allen Modi die Zahl gleichzeitiger Anfragen. `pm.max_requests` ersetzt einen Worker nach einer festen Zahl von Anfragen; der Standard 0 bedeutet unbegrenzt.

Welcher Modus passt, hängt von der Last ab. `static` hält immer gleich viele Worker bereit und eignet sich für gleichmäßig stark genutzte Anwendungen mit genug Arbeitsspeicher. `dynamic` ist ein Kompromiss für die meisten Websites. `ondemand` spart Speicher auf Servern mit vielen kleinen Websites, weil Pools ohne Besucher keine Worker belegen; dafür dauert die erste Anfrage nach einer Pause etwas länger. Zu hoch angesetztes `pm.max_children` kann den Server bei Lastspitzen in den Speichermangel treiben, zu niedriges führt zu Wartezeiten und Fehlermeldungen des Webservers.

## Ein Pool mit sicheren Grundeinstellungen

Ein Beispiel für einen eigenen Pool je Website, mit Direktiven aus dem PHP-Handbuch. Pfade und Werte sind Beispiele:

```ini
; /etc/php/8.3/fpm/pool.d/kunde-a.conf
[kunde-a]
user = kunde-a
group = kunde-a

listen = /run/php/kunde-a.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s

request_terminate_timeout = 60s
security.limit_extensions = .php
clear_env = yes

php_admin_value[open_basedir] = /var/www/kunde-a:/tmp
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[error_log] = /var/log/php/kunde-a.error.log
```

Laut Handbuch können Werte über `php_value` und `php_flag` zur Laufzeit per `ini_set()` geändert werden, Werte über `php_admin_value` und `php_admin_flag` dagegen nicht. `security.limit_extensions` steht standardmäßig auf `.php .phar` und legt fest, welche Dateiendungen FPM als Hauptskript ausführt. `clear_env = yes` ist der Standard und leert die Umgebung der Worker.

Für Überwachung gibt es eine Statusseite über `pm.status_path` und eine Ping-Seite über `ping.path`. Beide sollten nur intern erreichbar sein. Langsame Anfragen protokolliert FPM mit Backtrace, wenn `request_slowlog_timeout` und `slowlog` gesetzt sind.

> **Wichtig:**
> Das PHP-Handbuch warnt: Wer eine FastCGI-Verbindung zu PHP-FPM öffnen kann, kontrolliert die Konfiguration der Anfrage und kann damit beliebigen Code ausführen. PHP-FPM darf nie aus einem nicht vertrauenswürdigen Netz erreichbar sein. Nutzen Sie einen Unix-Socket oder `listen.allowed_clients`.

## Welche Rolle spielt PHP-FPM bei PHP2Shell?

PHP-FPM gehört zu den betroffenen Betriebsarten. Besonders deutlich wird das Prozessmodell bei CVE-2026-109619: Zur Anfrage gehörender interner Zustand kann nach dem Freigeben des Speichers bestehen bleiben, und eine spätere Anfrage im selben Worker kann ihn nutzen, bevor er zurückgesetzt wird. Das ist nur möglich, weil Worker viele Anfragen nacheinander bearbeiten.

Daraus folgen drei Pflichten:

1. **Update einspielen:** PHP 8.5.12, 8.4.27, 8.3.36 oder 8.2.35 bzw. ein bestätigter Backport der Distribution.
2. **Alle Worker neu starten:** Neue Dateien auf der Festplatte ändern nichts, solange alte Worker laufen. Das gilt für jede installierte FPM-Version und jeden Pool. Die Befehle stehen unter [PHP-FPM und alle Worker neu starten](https://phpsos.de/php2shell/php-fpm-neustart/).
3. **Übergangswerte gesperrt setzen:** Die Maßnahmen von php.net, etwa `session.upload_progress.enabled=0`, gehören per `php_admin_value` oder `php_admin_flag` in den Pool, nicht in `.user.ini`.

Die Trennung in Pools ersetzt kein Update, begrenzt aber den Schaden: Läuft jede Website unter eigenem Benutzer, erreicht ein Angreifer nach einem Einbruch nicht automatisch die Dateien der anderen. Wie das konkret aussieht, beschreibt [PHP-FPM-Pools pro Website isolieren](https://phpsos.de/blog/php-fpm-pools-isolieren/); die Einbindung in Nginx steht unter [Nginx mit PHP-FPM absichern](https://phpsos.de/server/nginx-php-fpm/).

## Wie hilft PHP SOS konkret?

- **Pools erfassen:** Wir listen alle FPM-Versionen, Pools, Benutzer und Sockets Ihres Servers auf.
- **Patchen und neu starten:** Wir aktualisieren PHP und belegen über Startzeiten, dass kein alter Worker mehr läuft.
- **Pools trennen:** Im Rahmen der [Server-Härtung](https://phpsos.de/leistungen/server-haertung/) richten wir je Website einen Pool mit eigenem Benutzer und gesperrten Einstellungen ein.
- **Erreichbarkeit prüfen:** Wir kontrollieren, dass FastCGI-Sockets und Statusseiten nicht von außen erreichbar sind.


## Häufige Fragen

**Wofür steht FPM?**  
FPM steht für FastCGI Process Manager. Das PHP-Handbuch beschreibt ihn als primäre FastCGI-Implementierung von PHP mit Funktionen, die vor allem für stark belastete Websites nützlich sind. Aufgenommen wurde er mit PHP 5.3.3.

**Was ist der Unterschied zwischen Pool und Worker?**  
Ein Pool ist eine Gruppe von Worker-Prozessen mit gemeinsamer Konfiguration: Benutzer, Socket, Grenzen und PHP-Einstellungen. Ein Worker ist ein einzelner Prozess, der nacheinander Anfragen bearbeitet. Ein Server kann viele Pools haben, etwa einen je Website.

**Sollte PHP-FPM über TCP oder über einen Unix-Socket erreichbar sein?**  
Läuft der Webserver auf demselben Host, empfiehlt das PHP-Handbuch einen Unix-Socket. Bei TCP muss listen.allowed_clients gesetzt werden, weil sonst jede Adresse verbinden darf. Ein offen erreichbarer FastCGI-Port erlaubt laut Handbuch beliebige Codeausführung.

**Schützt pm.max_requests vor Lücken wie PHP2Shell?**  
Nein. pm.max_requests ersetzt einen Worker nach einer festen Zahl von Anfragen und hilft vor allem gegen Speicherlecks in Erweiterungen. Gegen eine Lücke im Interpreter hilft nur das Update mit anschließendem Neustart aller Worker.

## Quellen

- [PHP-Handbuch: FastCGI Process Manager](https://www.php.net/manual/en/install.fpm.php)
- [PHP-Handbuch: FPM-Konfiguration](https://www.php.net/manual/en/install.fpm.configuration.php)
- [php.net: PHP 5.3.3 Release](https://www.php.net/releases/5_3_3.php)
- [php.net: Sicherheitsmeldungen](https://www.php.net/)
