PHP-FPM (FastCGI Process Manager) ist der Standard für PHP-Ausführung auf Webservern. Die richtige Konfiguration ist entscheidend für Performance und Stabilität.
PHP-FPM Architektur
Prozessmodell
Master-Prozess
│
├── Worker-Prozess 1
├── Worker-Prozess 2
├── Worker-Prozess 3
└── Worker-Prozess NPool-Konzept
PHP-FPM Master
│
├── Pool: www (default)
│ └── Worker für allgemeine Websites
│
├── Pool: wordpress
│ └── Worker speziell für WordPress
│
└── Pool: api
└── Worker für API-AnwendungenInstallation
Debian/Ubuntu
apt install php8.2-fpm
systemctl enable php8.2-fpm
systemctl start php8.2-fpmStatus prüfen
systemctl status php8.2-fpm
php-fpm8.2 -t # Konfiguration testenPool-Konfiguration
Haupt-Pool
; /etc/php/8.2/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; Process Manager
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
; Status
pm.status_path = /status
ping.path = /ping
ping.response = pong
; Logging
access.log = /var/log/php8.2-fpm/access.log
slowlog = /var/log/php8.2-fpm/slow.log
request_slowlog_timeout = 5s
; PHP-Einstellungen
php_admin_value[error_log] = /var/log/php8.2-fpm/error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_admin_value[upload_max_filesize] = 50M
php_admin_value[post_max_size] = 50M
php_admin_value[max_execution_time] = 60Process Manager Modi
Dynamic (Empfohlen)
pm = dynamic
pm.max_children = 50 ; Maximale Worker
pm.start_servers = 5 ; Beim Start
pm.min_spare_servers = 5 ; Minimum Idle
pm.max_spare_servers = 35 ; Maximum IdleStatic (Hochlast)
pm = static
pm.max_children = 50 ; Feste Anzahl WorkerOndemand (Wenig Traffic)
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s ; Worker beenden nach IdleVergleich
| Modus | Vorteile | Nachteile | |-------|----------|-----------| | dynamic | Flexibel, ressourcenschonend | Spawn-Overhead | | static | Keine Spawn-Verzögerung | Mehr RAM | | ondemand | Minimaler RAM-Verbrauch | Spawn bei jedem Request |
Worker-Berechnung
Formel
max_children = (Verfügbarer RAM - Anderer RAM-Bedarf) / Durchschnittlicher PHP-Prozess-RAM
Beispiel:
- Server: 4 GB RAM
- OS + Dienste: 1 GB
- Verfügbar für PHP: 3 GB
- PHP-Prozess: ~50 MB
max_children = 3000 / 50 = 60RAM pro Prozess ermitteln
# Durchschnittlichen RAM pro Worker
ps aux | grep php-fpm | awk '{sum += $6} END {print sum/NR/1024 " MB"}'
# Detailliert
ps -eo pid,rss,cmd | grep php-fpm | sort -k2 -nSeparate Pools
WordPress-Pool
; /etc/php/8.2/fpm/pool.d/wordpress.conf
[wordpress]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm-wordpress.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 30
pm.start_servers = 3
pm.min_spare_servers = 3
pm.max_spare_servers = 20
pm.max_requests = 500
php_admin_value[memory_limit] = 512M
php_admin_value[upload_max_filesize] = 100M
php_admin_value[post_max_size] = 100M
php_admin_value[max_execution_time] = 300
; OPcache-Einstellungen
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.max_accelerated_files] = 20000API-Pool
; /etc/php/8.2/fpm/pool.d/api.conf
[api]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm-api.sock
pm = static
pm.max_children = 20
pm.max_requests = 1000
php_admin_value[memory_limit] = 128M
php_admin_value[max_execution_time] = 30Nginx-Konfiguration
# WordPress
server {
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm-wordpress.sock;
include fastcgi_params;
}
}
# API
server {
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm-api.sock;
include fastcgi_params;
}
}OPcache-Optimierung
Konfiguration
; /etc/php/8.2/fpm/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; In Production
opcache.save_comments=1
opcache.enable_file_override=1
opcache.jit_buffer_size=100M
opcache.jit=1255 ; PHP 8+OPcache-Status
<?php
// opcache-status.php
print_r(opcache_get_status());
?>Status-Seite
Aktivieren
; In Pool-Config
pm.status_path = /fpm-status
ping.path = /fpm-pingNginx
location = /fpm-status {
allow 127.0.0.1;
deny all;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location = /fpm-ping {
allow 127.0.0.1;
deny all;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}Abrufen
curl http://localhost/fpm-status
curl http://localhost/fpm-status?full
curl http://localhost/fpm-status?jsonStatus-Ausgabe
pool: www
process manager: dynamic
start time: 26/Jan/2026:10:00:00
start since: 3600
accepted conn: 12543
listen queue: 0
max listen queue: 12
listen queue len: 128
idle processes: 5
active processes: 3
total processes: 8
max active processes: 15
max children reached: 0Slow-Log
Aktivieren
slowlog = /var/log/php8.2-fpm/slow.log
request_slowlog_timeout = 5s
request_slowlog_trace_depth = 20Auswerten
tail -f /var/log/php8.2-fpm/slow.log
# Häufigste langsame Funktionen
grep -A5 "script_filename" /var/log/php8.2-fpm/slow.log | \
sort | uniq -c | sort -rnMemory-Leak-Schutz
; Worker nach X Requests recyclen
pm.max_requests = 500
; Emergency Restart bei zu viel Speicherverbrauch
emergency_restart_threshold = 10
emergency_restart_interval = 1m
; Prozess-Kontrolle
process_control_timeout = 10sSicherheit
Einschränkungen
; Gefährliche Funktionen deaktivieren
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen
; Open Basedir
php_admin_value[open_basedir] = /var/www/html:/tmp:/var/lib/php/sessions
; Session-Sicherheit
php_admin_value[session.cookie_secure] = 1
php_admin_value[session.cookie_httponly] = 1Berechtigungen
# Socket-Berechtigungen
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
# Log-Verzeichnis
mkdir -p /var/log/php8.2-fpm
chown www-data:www-data /var/log/php8.2-fpmMonitoring
Prometheus-Metriken
# php-fpm_exporter
docker run -d -p 9253:9253 \
-e PHP_FPM_SCRAPE_URI="unix:///run/php/php-fpm.sock;/fpm-status" \
hipages/php-fpm_exporterNagios/Icinga
#!/bin/bash
# check_php-fpm.sh
ACTIVE=$(curl -s http://localhost/fpm-status | grep "active processes" | awk '{print $3}')
MAX=$(curl -s http://localhost/fpm-status | grep "max active" | awk '{print $4}')
PERCENT=$((ACTIVE * 100 / MAX))
if [ $PERCENT -gt 90 ]; then
echo "CRITICAL: PHP-FPM $PERCENT% active ($ACTIVE/$MAX)"
exit 2
elif [ $PERCENT -gt 70 ]; then
echo "WARNING: PHP-FPM $PERCENT% active ($ACTIVE/$MAX)"
exit 1
else
echo "OK: PHP-FPM $PERCENT% active ($ACTIVE/$MAX)"
exit 0
fiZusammenfassung
| Parameter | Empfehlung | |-----------|------------| | pm | dynamic (Standard) | | pm.max_children | RAM / 50MB | | pm.start_servers | max_children / 10 | | pm.max_requests | 500-1000 | | memory_limit | 256M (Apps abhängig) |
| Datei | Funktion | |-------|----------| | /etc/php/8.2/fpm/php-fpm.conf | Globale Config | | /etc/php/8.2/fpm/pool.d/*.conf | Pool-Configs | | /run/php/php8.2-fpm.sock | Socket |
| Befehl | Funktion | |--------|----------| | php-fpm8.2 -t | Config testen | | systemctl reload php8.2-fpm | Reload | | curl /fpm-status | Status abfragen |
Fazit
Die richtige PHP-FPM-Konfiguration ist entscheidend für Webserver-Performance. Die Worker-Anzahl sollte an den verfügbaren RAM angepasst werden. Separate Pools für verschiedene Anwendungen ermöglichen granulare Kontrolle. OPcache beschleunigt PHP erheblich. Die Status-Seite und Slow-Logs helfen bei der Fehlersuche. Regelmäßiges Monitoring verhindert Ressourcenengpässe.