Kort sagt: PHP-FPM (FastCGI Process Manager) driver PHP som egen tjeneste ved siden af webserveren. En master-proces administrerer pools, og hver pool starter workere, der behandler forespørgsler via FastCGI. Pools kan køres pr. website med egen bruger, egne grænser og låste PHP-indstillinger. Fordi workere behandler mange forespørgsler efter hinanden, skal de alle genstartes efter en PHP-opdatering.
Hvad er PHP-FPM?
PHP-manualen beskriver FPM som PHP's primære FastCGI-implementering med funktioner, der især er nyttige for stærkt belastede websites. FPM blev optaget med PHP 5.3.3 som egen SAPI, altså som egen driftsform. Dens SAPI-navn er fpm-fcgi.
Forskellen til mod_php: PHP kører ikke i webserveren, men som egen tjeneste. Nginx, Apache eller en anden webserver giver PHP-forespørgsler videre via FastCGI-protokollen og får det færdige svar tilbage. Webserver og PHP kan dermed genstartes, konfigureres og sikres uafhængigt af hinanden. Hvordan FastCGI grundlæggende fungerer, står under CGI og FastCGI.
Master, pools og workere: procesmodellen
PHP-FPM består af tre niveauer:
- Master-proces: læser konfigurationen, åbner socketsene og starter eller afslutter workere. Den udfører selv ingen applikationskode.
- Pools: Hver pool har et navn, en egen socket eller port, en egen Unix-bruger og egne PHP-indstillinger. Manualen nævner udtrykkeligt forskellige uid, gid, chroot, miljø og php.ini pr. pool.
- Workere: processer i en pool, som modtager og udfører forespørgsler. En worker behandler mange forespørgsler efter hinanden, før den erstattes.
Hvor mange workere der kører, afgør procesmanageren med direktivet pm:
| Tilstand | Adfærd | Vigtige direktiver |
|---|---|---|
static |
fast antal workere | pm.max_children |
dynamic |
workere mellem nedre og øvre grænse | pm.start_servers, pm.min_spare_servers, pm.max_spare_servers |
ondemand |
workere først ved behov, nedlukning efter tomgang | pm.process_idle_timeout (standard 10s) |
pm.max_children begrænser i alle tilstande antallet af samtidige forespørgsler. pm.max_requests erstatter en worker efter et fast antal forespørgsler; standarden 0 betyder ubegrænset.
Hvilken tilstand der passer, afhænger af belastningen. static holder altid lige mange workere klar og egner sig til jævnt stærkt brugte applikationer med nok arbejdshukommelse. dynamic er et kompromis for de fleste websites. ondemand sparer hukommelse på servere med mange små websites, fordi pools uden besøgende ikke optager workere; til gengæld varer den første forespørgsel efter en pause lidt længere. Et for højt sat pm.max_children kan drive serveren ud i hukommelsesmangel ved belastningsspidser, et for lavt fører til ventetider og fejlmeddelelser fra webserveren.
En pool med sikre grundindstillinger
Et eksempel på en egen pool pr. website, med direktiver fra PHP-manualen. Stier og værdier er eksempler:
; /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
Ifølge manualen kan værdier via php_value og php_flag ændres under kørsel med ini_set(), værdier via php_admin_value og php_admin_flag derimod ikke. security.limit_extensions står som standard på .php .phar og fastlægger, hvilke filendelser FPM udfører som hovedscript. clear_env = yes er standarden og tømmer workernes miljø.
Til overvågning findes en statusside via pm.status_path og en ping-side via ping.path. Begge bør kun kunne nås internt. Langsomme forespørgsler logger FPM med backtrace, hvis request_slowlog_timeout og slowlog er sat.
PHP-manualen advarer: Den, der kan åbne en FastCGI-forbindelse til PHP-FPM, kontrollerer forespørgslens konfiguration og kan dermed udføre vilkårlig kode. PHP-FPM må aldrig kunne nås fra et ikke-betroet netværk. Brug en Unix-socket eller listen.allowed_clients.
Hvilken rolle spiller PHP-FPM ved PHP2Shell?
PHP-FPM hører til de berørte driftsformer. Procesmodellen bliver særligt tydelig ved CVE-2026-109619: Intern tilstand, der hører til forespørgslen, kan blive bestående, efter at hukommelsen er frigivet, og en senere forespørgsel i den samme worker kan udnytte den, før den nulstilles. Det er kun muligt, fordi workere behandler mange forespørgsler efter hinanden.
Heraf følger tre pligter:
- Indspille opdateringen: PHP 8.5.12, 8.4.27, 8.3.36 eller 8.2.35 hhv. en bekræftet backport fra distributionen.
- Genstarte alle workere: Nye filer på disken ændrer intet, så længe gamle workere kører. Det gælder for hver installeret FPM-version og hver pool. Kommandoerne står under Genstart PHP-FPM og alle workere.
- Sætte overgangsværdier låst: Foranstaltningerne fra php.net, f.eks.
session.upload_progress.enabled=0, hører viaphp_admin_valueellerphp_admin_flaghjemme i poolen, ikke i.user.ini.
Adskillelsen i pools erstatter ikke en opdatering, men begrænser skaden: Kører hvert website under egen bruger, når en angriber efter et indbrud ikke automatisk de andres filer. Hvordan det konkret ser ud, beskriver Isolér PHP-FPM-pools pr. website; integrationen i Nginx står under Sikring af Nginx med PHP-FPM.
Hvordan hjælper PHP SOS konkret?
- Kortlægge pools: Vi opstiller alle FPM-versioner, pools, brugere og sockets på jeres server.
- Patche og genstarte: Vi opdaterer PHP og dokumenterer via starttidspunkter, at ingen gammel worker kører mere.
- Adskille pools: Som led i serverhærdningen opretter vi pr. website en pool med egen bruger og låste indstillinger.
- Kontrollere tilgængelighed: Vi kontrollerer, at FastCGI-sockets og statussider ikke kan nås udefra.
Ofte stillede spørgsmål
Hvad står FPM for?
FPM står for FastCGI Process Manager. PHP-manualen beskriver den som PHP's primære FastCGI-implementering med funktioner, der især er nyttige for stærkt belastede websites. Den blev optaget med PHP 5.3.3.
Hvad er forskellen på pool og worker?
En pool er en gruppe worker-processer med fælles konfiguration: bruger, socket, grænser og PHP-indstillinger. En worker er en enkelt proces, der behandler forespørgsler efter hinanden. En server kan have mange pools, f.eks. én pr. website.
Skal PHP-FPM kunne nås via TCP eller via en Unix-socket?
Kører webserveren på den samme host, anbefaler PHP-manualen en Unix-socket. Ved TCP skal listen.allowed_clients sættes, fordi enhver adresse ellers må forbinde. En åbent tilgængelig FastCGI-port tillader ifølge manualen vilkårlig kodeudførelse.
Beskytter pm.max_requests mod sårbarheder som PHP2Shell?
Nej. pm.max_requests erstatter en worker efter et fast antal forespørgsler og hjælper især mod hukommelseslækager i udvidelser. Mod en sårbarhed i fortolkeren hjælper kun opdateringen med efterfølgende genstart af alle workere.