# Isolér PHP-FPM-pools pr. website

> Isolér PHP-FPM-pools pr. website: kontrollér eksisterende pools, beskyt sockets, begræns endelser, skjul statussider og sæt grænser for hver pool.

Kilde: https://phpsos.de/da/blog/php-fpm-pools-isolieren/  
Status: 25.10.2026  
Udbyder: PHP SOS, PHP-nødhjælp og serversikkerhed. Akut hjælp på WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20har%20brug%20for%20hj%C3%A6lp%20med%20vores%20PHP-server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort sagt:** Hvert website på en server bør have sin egen PHP-FPM-pool med egen systembruger og egen socket. Adskillelsen bliver dog først virksom med detaljerne: socket-rettigheder kun for webserveren, `security.limit_extensions` på `.php`, ingen offentligt tilgængelige statussider, egne grænser for processer og køretid samt adskilte logs. Mod PHP2Shell selv beskytter kun opdateringen; pools begrænser, hvor langt et angreb rækker.

## En server, mange websites, en fælles risiko

På mange servere er der over årene vokset noget frem, som ingen har planlagt sådan. Firmawebsitet, shoppen, en kampagneside fra 2019 og et testsystem kører side om side, ofte under den samme bruger og i den samme pool. Kompromitteres den glemte kampagneside, ligger shoppens kundedata også åbne.

PHP-FPM, PHP's FastCGI-procesmanager, løser det med pools: grupper af worker-processer med egne indstillinger. Hvordan grundprincippet fungerer, forklarer [PHP-FPM forklaret: Procesmanager, pools og workers](https://phpsos.de/da/php/php-fpm-erklaert/). Opbygningen af adskilte pools med egen bruger, egen temp-mappe og `open_basedir` beskriver vejledningen [open_basedir og isolation pr. website](https://phpsos.de/da/ratgeber/open-basedir/). Dette indlæg går et skridt videre: Hvordan kontrollerer I eksisterende pools, og hvilke indstillinger gør adskillelsen holdbar?

Vigtigt for indordningen: Ved PHP2Shell ligger sårbarhederne CVE-2026-109618 og CVE-2026-109619 i PHP-fortolkeren, som alle pools i en PHP-version deler. En egen pool forhindrer ikke en udnyttelse. Men den afgør, om en angriber bagefter når ét website eller alle.

## PHP-FPM-pools med egen bruger: Kontrollér beholdningen

Før I ændrer noget, skaffer I jer overblik. De følgende kommandoer læser kun. Stier og versionsnumre afviger fra distribution til distribution:

```bash
# Alle pools med bruger og socket
grep -HE '^\s*(\[|user|group|listen)\s*' /etc/php/*/fpm/pool.d/*.conf

# Kørende pools og deres brugere
ps -eo user,pid,cmd | grep '[p]hp-fpm: pool'

# Sockets og deres rettigheder
ls -l /run/php/

# Kontrollér konfigurationen for fejl (ændrer intet)
sudo php-fpm8.3 -t
```

Vær opmærksom på tre mønstre: flere websites i den samme pool, pools, der kører som `www-data` eller endda som `root`, og sockets, der kan skrives af alle brugere. Hvert af dem underminerer adskillelsen.

Kører der flere PHP-versioner på serveren, har hver sin egen FPM-tjeneste med egne pool-mapper. Kontrollér dem alle, ikke kun den version, I senest satte op. Netop gamle versioner med glemte pools er en risiko, fordi de ofte hverken vedligeholdes eller genstartes efter opdateringer. Oplysninger herom står under [Flere PHP-versioner på en server](https://phpsos.de/da/blog/mehrere-php-versionen-server/). Notér resultatet i en lille tabel: website, pool, bruger, socket, PHP-version. Det overblik er samtidig grundlaget for enhver senere ændring.

## De vigtigste indstillinger pr. pool

Oversigten nedenfor bygger på FPM-konfigurationen i PHP-manualen. Værdier for processer og tider retter sig efter jeres belastning og applikation:

| Indstilling | Formål | Anbefaling |
|---|---|---|
| `user`, `group` | workernes bruger | egen bruger pr. website, aldrig `root` |
| `listen.owner`, `listen.group`, `listen.mode` | rettigheder på socketten | kun webserverens gruppe, tilstand `0660` |
| `listen.acl_users` | adgang via ACL i stedet for ejer | indtast kun webserverbrugeren |
| `security.limit_extensions` | eksekverbare endelser | begræns til `.php` (standard `.php .phar`) |
| `clear_env` | tøm miljøvariabler | lad stå på standarden `yes` |
| `pm.max_children` | maksimalt antal workers | begræns, så et website ikke belaster serveren fuldt ud |
| `request_terminate_timeout` | afbrydelse af hængende forespørgsler | sæt passende til den længste legitime forespørgsel |
| `pm.status_path`, `ping.path` | status- og ping-side | sæt kun, hvis det er nødvendigt, og afskærm internt |
| `slowlog`, `request_slowlog_timeout` | protokol over langsomme forespørgsler | pr. pool i egen fil |

Et uddrag for en hærdet pool ser således ud:

```ini
; /etc/php/8.3/fpm/pool.d/shop.conf (uddrag)
[shop]
user = shop
group = shop
listen = /run/php/shop.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
request_terminate_timeout = 60s

security.limit_extensions = .php
clear_env = yes

slowlog = /var/log/php/shop.slow.log
request_slowlog_timeout = 10s
php_admin_value[error_log] = /var/log/php/shop.error.log
```

Indstillinger som `memory_limit` eller `session.upload_progress.enabled` sætter I pr. pool med `php_admin_value` og `php_admin_flag`. Ifølge manualen kan disse værdier ikke overskrives med `ini_set()`. Mere herom under [php_admin_value: Lås indstillinger mod overskrivning](https://phpsos.de/da/blog/php-admin-value-sperren/).

## Placér statussider og worker-skift rigtigt

`pm.status_path` og `ping.path` er kun aktive, hvis de er sat. Statussiden viser kørende forespørgsler, processer og belastning. Til overvågning er det nyttigt, men offentligt tilgængeligt er det en unødvendig informationskilde for angribere. Send disse stier videre i webserveren kun for interne adresser. Hvordan Nginx og PHP-FPM arbejder sikkert sammen, beskriver [Afsikr Nginx med PHP-FPM](https://phpsos.de/da/server/nginx-php-fpm/).

`pm.max_requests` fastlægger, efter hvor mange forespørgsler en worker genstarter; standarden er `0`, altså aldrig. En værdi over nul hjælper mod et langsomt voksende hukommelsesforbrug. Som beskyttelse mod PHP2Shell er den ikke tænkt: php.net nævner den ikke blandt overgangsforanstaltningerne og understreger, at kun opdateringen beskytter fuldstændigt. Efter opdateringen gælder desuden: Alle workers i alle pools skal genstartes, fordi gamle processer ellers fortsætter med den sårbare kode.

> **Tip:**
> Vedligehold en skabelon til nye pools, og opret hvert nyt website med den. Så opstår adskillelsen automatisk i stedet for at blive eftermonteret år senere.

## Typiske fejl ved omstillingen

Den hyppigste fejl er en ny pool, der ganske vist kører under egen bruger, men hvis filer fortsat tilhører `www-data`. Så må poolen ikke skrive, hvor den skal, og nogen sætter rettighederne for rundhåndet. Afklar på forhånd, hvilke mapper der skal kunne skrives i. Den anden fejl er planlagte opgaver, der fortsat kører under den gamle bruger og opretter filer med forkert ejer. Den tredje er en fælles session-mappe for alle pools, som ophæver adskillelsen igen.

Test efter hver omstilling websitets login, uploads, caches og planlagte opgaver, og hold poolens fejllog under opsyn.

## Hvordan hjælper PHP SOS konkret?

- Vi registrerer alle pools, brugere, sockets og indstillinger og viser, hvor websites i dag deler processer eller rettigheder.
- Vi opsætter en hærdet pool pr. website, med socket-rettigheder, endelsesgrænse, ressourcegrænser og egne logs.
- Vi afskærmer statussider, genstarter alle workers kontrolleret og tester hvert website.
- Inden for rammerne af [serverhærdningen](https://phpsos.de/da/leistungen/server-haertung/) dokumenterer vi adskillelsen som skabelon til fremtidige projekter.


## Ofte stillede spørgsmål

**Hvorfor skal hvert website have sin egen PHP-FPM-pool?**  
En egen pool med egen systembruger adskiller websites på niveauet af processer og filrettigheder. Kompromitteres et website, kan koden ikke uden videre læse de andres filer. Desuden kan grænser og indstillinger fastlægges særskilt for hvert website.

**Beskytter en egen pool mod PHP2Shell?**  
Nej. Sårbarhederne ligger i selve PHP-fortolkeren, som alle pools deler. Beskyttelse giver kun opdateringen til en rettet version med genstart af alle workers. Adskilte pools begrænser dog, hvor langt et vellykket angreb rækker.

**Hvad gør security.limit_extensions?**  
Ifølge PHP-manualen begrænser indstillingen, hvilke filendelser PHP-FPM udfører som hovedscript. Standarden er .php og .phar. Den, der begrænser til .php, forhindrer, at f.eks. uploadede billedfiler udføres som PHP, hvis webserveren er konfigureret forkert.

**Er PHP-FPM's statusside farlig?**  
Den afslører detaljer om kørende processer og forespørgsler. Er den offentligt tilgængelig uden beskyttelse, letter den angribernes orientering. Ifølge manualen er den kun aktiv, hvis pm.status_path er sat. Så bør webserveren begrænse stien til interne adresser.

## Kilder

- [PHP-manual: FPM-konfiguration](https://www.php.net/manual/en/install.fpm.configuration.php)
- [Nginx-dokumentation](https://nginx.org/en/docs/)
- [BSI IT-Grundschutz (tysk metodik til informationssikkerhed)](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
