Накратко: PHP-FPM (FastCGI Process Manager) изпълнява PHP като самостоятелна услуга до уеб сървъра. Главен процес управлява пуловете, а всеки пул стартира работни процеси, които обработват заявките през FastCGI. Пуловете могат да се използват за всеки уебсайт със собствен потребител, собствени ограничения и заключени настройки на PHP. Тъй като работните процеси обработват последователно много заявки, след актуализация на PHP всички те трябва да бъдат рестартирани.
Какво е PHP-FPM?
Ръководството на PHP описва FPM като основната реализация на FastCGI в PHP с функции, полезни най-вече за силно натоварени уебсайтове. FPM е приет с PHP 5.3.3 като самостоятелен SAPI, т.е. като самостоятелен режим на работа. Името му като SAPI е fpm-fcgi.
Разликата спрямо mod_php: PHP не работи в уеб сървъра, а като самостоятелна услуга. Nginx, Apache или друг уеб сървър предава PHP заявките през протокола FastCGI и получава готовия отговор. Така уеб сървърът и PHP могат да се рестартират, конфигурират и защитават независимо един от друг. Как принципно работи FastCGI, е описано в CGI и FastCGI.
Главен процес, пулове и работни процеси: моделът на процесите
PHP-FPM се състои от три нива:
- Главен процес: чете конфигурацията, отваря сокетите и стартира или прекратява работни процеси. Той самият не изпълнява код на приложение.
- Пулове: Всеки пул има име, собствен сокет или порт, собствен Unix потребител и собствени настройки на PHP. Ръководството изрично посочва различни uid, gid, chroot, среда и php.ini за всеки пул.
- Работни процеси: процеси на един пул, които приемат и изпълняват заявки. Един работен процес обработва последователно много заявки, преди да бъде заменен.
Колко работни процеси работят, определя мениджърът на процесите с директивата pm:
| Режим | Поведение | Важни директиви |
|---|---|---|
static |
фиксиран брой работни процеси | pm.max_children |
dynamic |
работни процеси между долна и горна граница | pm.start_servers, pm.min_spare_servers, pm.max_spare_servers |
ondemand |
работни процеси едва при нужда, премахване след бездействие | pm.process_idle_timeout (по подразбиране 10s) |
pm.max_children във всички режими ограничава броя на едновременните заявки. pm.max_requests заменя работен процес след фиксиран брой заявки; стойността по подразбиране 0 означава неограничено.
Кой режим е подходящ, зависи от натоварването. static държи винаги еднакъв брой работни процеси готови и е подходящ за равномерно натоварени приложения с достатъчно оперативна памет. dynamic е компромис за повечето уебсайтове. ondemand спестява памет на сървъри с много малки уебсайтове, защото пулове без посетители не заемат работни процеси; затова първата заявка след пауза отнема малко повече време. Прекалено висок pm.max_children може да докара сървъра до недостиг на памет при върхове в натоварването, прекалено нисък води до чакане и съобщения за грешки от уеб сървъра.
Пул с безопасни основни настройки
Пример за отделен пул за всеки уебсайт с директиви от ръководството на PHP. Пътищата и стойностите са примери:
; /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
Според ръководството стойности чрез php_value и php_flag могат да се променят по време на изпълнение с ini_set(), а стойности чрез php_admin_value и php_admin_flag не могат. security.limit_extensions е по подразбиране .php .phar и определя кои разширения на файлове FPM изпълнява като основен скрипт. clear_env = yes е стойността по подразбиране и изчиства средата на работните процеси.
За наблюдение има страница със състоянието през pm.status_path и ping страница през ping.path. И двете трябва да са достъпни само вътрешно. Бавните заявки FPM записва с backtrace, когато са зададени request_slowlog_timeout и slowlog.
Ръководството на PHP предупреждава: който може да отвори FastCGI връзка към PHP-FPM, контролира конфигурацията на заявката и така може да изпълни произволен код. PHP-FPM никога не бива да е достъпен от недоверена мрежа. Ползвайте Unix сокет или listen.allowed_clients.
Каква роля играе PHP-FPM при PHP2Shell?
PHP-FPM е сред засегнатите режими на работа. Моделът на процесите проличава особено при CVE-2026-109619: вътрешно състояние, принадлежащо към заявката, може да остане след освобождаването на паметта и по-късна заявка в същия работен процес може да го използва, преди то да бъде нулирано. Това е възможно само защото работните процеси обработват много заявки последователно.
От това следват три задължения:
- Внасяне на актуализацията: PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35, респективно потвърден backport на дистрибуцията.
- Рестартиране на всички работни процеси: Новите файлове на диска не променят нищо, докато работят старите работни процеси. Това важи за всяка инсталирана версия на FPM и за всеки пул. Командите са описани в Рестартиране на PHP-FPM и на всички работни процеси.
- Заключване на временните стойности: Мерките от php.net, например
session.upload_progress.enabled=0, се поставят в пула чрезphp_admin_valueилиphp_admin_flag, а не в.user.ini.
Разделянето на пулове не замества актуализацията, но ограничава щетите: ако всеки уебсайт работи под собствен потребител, атакуващият след пробив не достига автоматично файловете на останалите. Как изглежда това конкретно, описва Изолиране на PHP-FPM пулове за всеки уебсайт; включването в Nginx е описано в Защита на Nginx с PHP-FPM.
Как помага PHP SOS конкретно?
- Установяване на пуловете: Изброяваме всички версии на FPM, пулове, потребители и сокети на Вашия сървър.
- Корекция и рестартиране: Актуализираме PHP и доказваме чрез времената на стартиране, че вече не работи стар работен процес.
- Разделяне на пуловете: В рамките на заздравяването на сървъра създаваме за всеки уебсайт пул със собствен потребител и заключени настройки.
- Проверка на достъпността: Контролираме дали FastCGI сокетите и страниците със състоянието не са достъпни отвън.
Често задавани въпроси
Какво означава FPM?
FPM означава FastCGI Process Manager. Ръководството на PHP го описва като основната реализация на FastCGI в PHP с функции, полезни най-вече за силно натоварени уебсайтове. Приет е с PHP 5.3.3.
Каква е разликата между пул и работен процес?
Пулът е група от работни процеси с обща конфигурация: потребител, сокет, ограничения и настройки на PHP. Работният процес е отделен процес, който обработва последователно заявки. Един сървър може да има много пулове, например по един за всеки уебсайт.
Да бъде ли PHP-FPM достъпен през TCP или през Unix сокет?
Когато уеб сървърът работи на същия хост, ръководството на PHP препоръчва Unix сокет. При TCP трябва да се зададе listen.allowed_clients, защото иначе всеки адрес може да се свързва. Свободно достъпен FastCGI порт според ръководството позволява изпълнение на произволен код.
Защитава ли pm.max_requests от уязвимости като PHP2Shell?
Не. pm.max_requests заменя работен процес след фиксиран брой заявки и помага най-вече срещу изтичане на памет в разширения. Срещу уязвимост в интерпретатора помага само актуализацията с последващо рестартиране на всички работни процеси.