Если вы администрируете сайт на VDS, рано или поздно встречаете спор: оставить старый добрый prefork с mod_php или перевести Apache на mpm_event и php-fpm. Вопрос не академический: от выбора MPM зависит расход памяти, поведение keep-alive соединений, удобство изоляции сайтов и то, насколько спокойно вы сможете обновлять PHP.
В этой статье я, Вася из Fastfox, разложу схему по полочкам: чем отличаются режимы Apache, почему mod_php исторически привязан к prefork, как включить mpm_event и подключить PHP через FastCGI, что проверить на Debian/Ubuntu и AlmaLinux/Rocky Linux, а также какие настройки безопасно трогать на небольшом и среднем сервере.
Короткий вывод: для новых PHP-проектов на VDS почти всегда стоит выбирать Apache с
mpm_eventиphp-fpm. Связкуpreforkиmod_phpимеет смысл оставлять только ради совместимости со старой конфигурацией и после осознанной оценки ресурсов.
Что такое MPM в Apache и почему это важно
MPM, или Multi-Processing Module, определяет, как Apache принимает соединения и обслуживает запросы. Это не модуль уровня rewrite или сжатия, а базовая модель работы веб-сервера: процессы или потоки, сколько клиентов держать одновременно, что делать с долгими keep-alive соединениями и где выполняется обработчик запроса.
На Linux чаще всего встречаются три варианта: prefork, worker и event. На практике современный выбор обычно сводится к двум схемам: prefork для старого mod_php и event для связки с внешним обработчиком, например php-fpm. worker тоже работает с PHP-FPM, но хуже обращается с keep-alive, поэтому для новых серверов редко нужен.
prefork создаёт отдельные процессы Apache. Каждый процесс обслуживает один запрос в единицу времени, потоков внутри процесса нет. Модель простая и исторически безопасная для старых не thread-safe библиотек, но тяжёлая по памяти: каждый процесс несёт набор модулей, а при mod_php ещё и PHP-интерпретатор.
mpm_event использует процессы и потоки, а отдельный механизм событий помогает не тратить рабочий поток на idle keep-alive соединение. Это особенно заметно на сайтах с HTTP/2, большим количеством коротких запросов, медленными клиентами и обычной современной браузерной нагрузкой.
Почему mod_php почти всегда означает prefork
mod_php — это встроенный PHP-интерпретатор внутри процесса Apache. Запрос пришёл в Apache, Apache сам выполнил PHP-код и отдал результат. Для администратора это удобно: поставил пакет, включил модуль, файлы .php начали работать. Поэтому старые инструкции по LAMP часто выглядят очень коротко.
Цена простоты — тесная связка Apache и PHP. Если PHP загружен как модуль веб-сервера, он живёт в каждом процессе Apache. При prefork это означает много отдельных процессов с заметным расходом RAM. На VDS с 1–2 ГБ памяти такая модель быстро упирается в swap или OOM, особенно если рядом работают MySQL или MariaDB, Redis, почта, панель управления и фоновые задачи CMS.
Есть ещё один важный момент: mod_php плохо сочетается с потоковыми MPM. В дистрибутивах это обычно решено жёстко: пакет PHP module для Apache требует mpm_prefork или конфликтует с mpm_event. Поэтому сценарий «включить mpm_event и оставить mod_php» в нормальной эксплуатации не рассматриваем. Для mpm_event PHP выносится наружу — в php-fpm.
Как работает PHP-FPM рядом с Apache
php-fpm — отдельный менеджер PHP-процессов. Apache принимает HTTP-запрос, определяет, что файл нужно обработать как PHP, и передаёт его в FPM через Unix-сокет или TCP. PHP-FPM выполняет код и возвращает результат обратно Apache. Для Apache это внешний FastCGI backend.
Такое разделение даёт несколько практичных плюсов. Apache может обслуживать статику, TLS, HTTP/2, редиректы и access control без загрузки PHP в каждый рабочий процесс. Настройки PHP-процессов вынесены в отдельные пулы: можно задать pm.max_children, пользователя, лимиты, slowlog и разные версии PHP для разных сайтов. Перезапуск PHP-FPM не равен полному перезапуску Apache.
Для хостинга нескольких сайтов это особенно удобно. Один проект может работать на PHP 8.3, второй — на PHP 8.2, третий — в отдельном пуле с более строгим open_basedir и своим пользователем. При mod_php такая изоляция либо сложнее, либо невозможна без дополнительных прослоек.

Сравнение prefork/mod_php и mpm_event/PHP-FPM
Чтобы выбрать осознанно, полезно смотреть не только на скорость одного запроса, а на поведение системы под реальной нагрузкой. Веб-сервер редко падает из-за одного тяжёлого запроса. Чаще проблема начинается, когда одновременно приходят живые пользователи, поисковые боты, фоновые AJAX-запросы, медленные мобильные клиенты и пара тяжёлых административных действий в CMS.
prefork+mod_php: проще, привычнее, совместимо со старыми инструкциями, но потребляет больше памяти и хуже масштабируется на keep-alive нагрузке.mpm_event+php-fpm: современнее, экономнее по RAM, удобнее для нескольких сайтов и версий PHP, но требует правильной настройки FastCGI и FPM-пулов.worker+php-fpm: рабочий вариант, но обычно уступаетeventдля keep-alive сценариев, поэтому редко нужен на новых серверах.
По производительности PHP-кода разница между mod_php и php-fpm часто меньше, чем ожидают. Основной выигрыш появляется не потому, что PHP-FPM магически ускоряет каждую функцию, а потому что сервер лучше распределяет память и соединения. Если параллельно выбираете архитектуру веб-слоя, пригодится отдельное сравнение Nginx и Apache для современных проектов.
Когда можно оставить prefork и mod_php
Я не люблю советы в стиле «всё срочно переписать». Иногда prefork и mod_php действительно можно оставить: один небольшой внутренний сайт, низкая посещаемость, нет проблем с памятью, всё закрыто мониторингом, а миграция сейчас рискованнее потенциальной выгоды. В такой ситуации достаточно понимать ограничения и не завышать MaxRequestWorkers.
Ещё один сценарий — старый проект с нестандартными зависимостями, где перенос на FPM требует тестирования. Здесь лучше сделать staging-копию, прогнать авторизацию, загрузки файлов, cron-задачи, отправку почты, работу админки и только потом переключать production. Сам факт старости проекта не запрещает PHP-FPM, но повышает важность проверки.
Если вы разворачиваете новый сайт, переносите проект на свежий VDS или обслуживаете несколько виртуальных хостов, выбирайте mpm_event и php-fpm. Это нормальная базовая архитектура для Apache в 2026 году.
Проверяем текущий режим Apache
Начните с диагностики. Нужно понять, какой MPM включён, загружен ли PHP как модуль Apache и есть ли запущенный PHP-FPM. Команды ниже безопасны: они ничего не меняют.
Debian и Ubuntu
apache2ctl -V | grep -i mpm
apache2ctl -M | grep -E 'mpm|php|proxy_fcgi'
systemctl status apache2
systemctl list-units 'php*-fpm.service'Если версия PHP известна, можно проверить конкретную службу:
systemctl status php8.3-fpmAlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux
httpd -V | grep -i mpm
httpd -M | grep -E 'mpm|php|proxy_fcgi'
systemctl status httpd
systemctl status php-fpmНа RHEL-based системах выбор MPM обычно задаётся в файле /etc/httpd/conf.modules.d/00-mpm.conf. Активным должен быть только один MPM-модуль.
Переход на mpm_event и PHP-FPM на Debian/Ubuntu
Перед изменениями сделайте резервную копию конфигурации и убедитесь, что есть доступ к консоли VDS, а не только SSH. Ошибка в конфиге веб-сервера обычно чинится быстро, но спокойнее иметь запасной канал.
sudo cp -a /etc/apache2 /root/apache2-backup-$(date +%F)
sudo apt update
sudo apt install apache2 php-fpmБазовая современная связка использует модули proxy, proxy_fcgi и конфигурацию FPM, которую добавляет пакет PHP. Дальше отключаем mod_php и mpm_prefork, включаем mpm_event и FastCGI-прокси. Название PHP-модуля зависит от версии, поэтому сначала посмотрите список включённых модулей.
apache2ctl -M | grep php
sudo a2dismod php8.3
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo a2enconf php8.3-fpm
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo systemctl restart php8.3-fpmЕсли у вас PHP 8.2, используйте php8.2 и php8.2-fpm. Если команда a2dismod php8.3 сообщает, что модуля нет, это нормально: возможно, mod_php уже не был установлен.
Переход на mpm_event и PHP-FPM на AlmaLinux/Rocky Linux
В RHEL-based дистрибутивах чаще используется единая служба php-fpm, а версия PHP зависит от модульного потока или выбранного репозитория. В рамках этой статьи важно не то, откуда установлен PHP, а чтобы Apache не грузил PHP как встроенный модуль и передавал запросы в FPM.
sudo cp -a /etc/httpd /root/httpd-backup-$(date +%F)
sudo dnf install httpd php-fpm
sudo systemctl enable --now php-fpm
sudo systemctl enable --now httpd
httpd -M | grep -E 'mpm|php|proxy_fcgi'Проверьте файл /etc/httpd/conf.modules.d/00-mpm.conf. В нём должна быть активна строка с mpm_event_module, а строки с mpm_prefork_module и mpm_worker_module должны быть закомментированы. После изменения обязательно выполните проверку:
sudo httpd -t
sudo systemctl reload httpd
sudo systemctl restart php-fpmЕсли включён SELinux в режиме enforcing, Apache должен иметь право обращаться к FPM-сокету и файлам сайта. Типовая установка из пакетов обычно уже содержит нужные политики. При нестандартных путях проверьте контекст файлов и журналы AVC, а не отключайте SELinux вслепую.
getenforce
sudo ausearch -m avc -ts recent
sudo restorecon -Rv /var/wwwПример виртуального хоста Apache для PHP-FPM
На Debian/Ubuntu пакет php-fpm часто добавляет общий обработчик PHP через a2enconf php8.3-fpm. Но для понимания полезно видеть, как это выглядит на уровне виртуального хоста. Ниже пример через Unix-сокет.
<VirtualHost *:80>
ServerName example.test
DocumentRoot /var/www/site/public
<Directory /var/www/site/public>
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/site-error.log
CustomLog ${APACHE_LOG_DIR}/site-access.log combined
</VirtualHost>Для AlmaLinux и Rocky Linux путь к сокету обычно другой, например /run/php-fpm/www.sock. Переменная APACHE_LOG_DIR характерна для Debian-семейства; на RHEL-based системах чаще указывают явные пути в /var/log/httpd/.
<VirtualHost *:80>
ServerName example.test
DocumentRoot /var/www/site/public
<Directory /var/www/site/public>
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost/"
</FilesMatch>
ErrorLog /var/log/httpd/site-error.log
CustomLog /var/log/httpd/site-access.log combined
</VirtualHost>Unix-сокет обычно быстрее и безопаснее для локальной связки на одном сервере. TCP на 127.0.0.1:9000 удобен, когда нужно явно разделить сетевые пространства, контейнеры или нестандартные окружения. Для обычного VDS с Apache и PHP-FPM на одной системе я бы начинал с Unix-сокета.
Базовая настройка mpm_event
Главная ошибка при тюнинге Apache — копировать большие значения из чужих конфигов. На VDS лимиты должны вытекать из памяти, числа CPU и характера сайта. Для mpm_event важны параметры StartServers, ServerLimit, ThreadsPerChild, MaxRequestWorkers и MaxConnectionsPerChild.
MaxRequestWorkers — верхняя граница одновременных рабочих потоков. Если поставить слишком мало, пользователи увидят очередь и задержки. Если слишком много, сервер может упереться в память, файловые дескрипторы или backend. Для небольшого VDS с 2 ГБ RAM часто начинают с умеренных значений, а затем смотрят метрики.
<IfModule mpm_event_module>
StartServers 2
ServerLimit 4
ThreadsPerChild 25
MaxRequestWorkers 100
MinSpareThreads 25
MaxSpareThreads 75
MaxConnectionsPerChild 10000
</IfModule>Для prefork смысл другой: один процесс — один запрос, и каждый процесс тяжелее. Поэтому MaxRequestWorkers при prefork часто приходится держать заметно ниже. Если один процесс Apache с mod_php занимает 80–150 МБ RSS, то 50 процессов уже могут съесть память небольшого VDS.
<IfModule mpm_prefork_module>
StartServers 3
MinSpareServers 3
MaxSpareServers 8
MaxRequestWorkers 30
MaxConnectionsPerChild 3000
</IfModule>
Настройка PHP-FPM: не забываем про второй лимит
При переходе на PHP-FPM появляется отдельная очередь и отдельный потолок. Apache может принять 200 соединений, но если в пуле FPM разрешено только 10 PHP-процессов, одиннадцатый PHP-запрос будет ждать. Это нормально, если ожидание короткое, но плохо, если очередь растёт постоянно.
В пуле FPM чаще всего настраивают pm, pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers, pm.max_requests, request_slowlog_timeout и slowlog. Для обычных сайтов удобен режим dynamic. Для очень маленьких VDS иногда используют ondemand, чтобы экономить RAM в простое, но первый запрос после простоя может быть чуть медленнее.
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pm.max_requests = 500
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.logНа AlmaLinux и Rocky Linux пользователь обычно apache, а путь к пулу — /etc/php-fpm.d/www.conf. На Debian/Ubuntu пул лежит в /etc/php/8.3/fpm/pool.d/www.conf. После правок проверяйте конфигурацию и перезагружайте FPM.
sudo php-fpm -t
sudo systemctl reload php-fpmНа Debian/Ubuntu бинарник проверки может называться с версией:
sudo php-fpm8.3 -t
sudo systemctl reload php8.3-fpmКак примерно посчитать pm.max_children
Практичный расчёт начинается с наблюдения. Откройте сайт под типичной нагрузкой и посмотрите средний размер PHP-FPM процесса. Для грубой оценки можно использовать ps. RSS не идеальная метрика из-за разделяемой памяти, но для первичного лимита её достаточно.
ps -ylC php-fpm8.3 --sort:rss
ps -o pid,rss,cmd -C php-fpm8.3Если один PHP-процесс потребляет примерно 80 МБ, а вы готовы выделить PHP около 1200 МБ, то pm.max_children около 15 выглядит разумным стартом. Не отдавайте всю память PHP: Apache, база данных, page cache, systemd, SSH, cron и backup-задачи тоже хотят жить.
При большом числе медленных запросов увеличение pm.max_children не всегда лечит проблему. Оно может просто позволить большему количеству тяжёлых PHP-скриптов одновременно давить на базу. Если растёт очередь FPM, смотрите slowlog, SQL-запросы, внешние API, блокировки сессий и кеширование.
KeepAlive, HTTP/2 и почему event выигрывает
Современный браузер редко делает один запрос. Страница тянет HTML, CSS, JS, шрифты, картинки, API-вызовы. Keep-alive помогает не открывать TCP/TLS соединение заново для каждого ресурса. Но в prefork idle keep-alive может занимать целый процесс. При наплыве клиентов процессы заняты не работой, а ожиданием.
mpm_event проектировался как ответ на эту проблему. Он отделяет обработку активных запросов от ожидания keep-alive, поэтому рабочие потоки используются эффективнее. Это не отменяет лимитов, но делает поведение Apache на VDS более предсказуемым.
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2Слишком большой KeepAliveTimeout на небольшом сервере вреден: соединения живут дольше, чем нужно. Слишком маленький может ухудшить повторное использование соединений. Обычно 1–3 секунды достаточно для динамических PHP-сайтов, но лучше смотреть по access-логам и метрикам.
Типовые ошибки после перехода
Первая ошибка — забыли отключить mod_php. В итоге Apache остаётся на prefork, а администратор думает, что уже работает через FPM. Всегда проверяйте apache2ctl -M или httpd -M.
Вторая ошибка — неверные права на сокет. Apache должен иметь право писать в сокет PHP-FPM. На Debian/Ubuntu это обычно достигается через listen.owner и listen.group со значением www-data. На AlmaLinux/Rocky Linux часто используется пользователь apache.
Третья ошибка — разные пользователи файлов и процессов. Если PHP-FPM работает от одного пользователя, а файлы принадлежат другому, появляются 403, ошибки записи кеша, невозможность загрузки файлов и странные проблемы с обновлениями CMS. Лучше заранее определить модель владения файлами и не чинить всё через права 777.
Четвёртая ошибка — завышенные лимиты Apache и FPM. Когда MaxRequestWorkers и pm.max_children одновременно слишком велики, сервер не становится быстрее. Он просто получает возможность одновременно запустить больше тяжёлой работы и быстрее упасть в нехватку памяти.
План миграции без лишнего риска
- Снимите резервную копию конфигурации Apache, PHP-FPM и виртуальных хостов.
- Проверьте текущий MPM и наличие
mod_php. - Установите PHP-FPM и убедитесь, что служба стартует.
- Подготовьте виртуальный хост или общую конфигурацию
proxy_fcgi. - Отключите
mod_phpиmpm_prefork, включитеmpm_event. - Выполните
configtestдля Apache и проверку конфигурации FPM. - Перезагрузите службы через reload, проверьте сайт, логи и статус процессов.
- Через несколько часов нагрузки пересмотрите лимиты по фактическому потреблению памяти.
Если сайт критичный, сначала повторите процедуру на staging-копии. Даже если конфигурация синтаксически правильная, приложение может зависеть от старых значений php.ini, переменных окружения, путей временных каталогов или прав на файлы.
После миграции не забудьте про базовую безопасность HTTP-ответов: HSTS, CSP, X-Content-Type-Options и другие заголовки лучше проверять отдельно. У нас есть практичная инструкция по security headers для Nginx и Apache.
Что мониторить после переключения
После миграции минимум смотрите четыре слоя: Apache, PHP-FPM, систему и приложение. В Apache важны 5xx-ответы, рост времени ответа, занятые workers и сообщения о достижении MaxRequestWorkers. В PHP-FPM — очередь, slowlog, количество активных процессов и ошибки вида server reached pm.max_children.
Debian и Ubuntu
journalctl -u apache2 -n 100
journalctl -u php8.3-fpm -n 100
tail -n 100 /var/log/apache2/error.logAlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux
journalctl -u httpd -n 100
journalctl -u php-fpm -n 100
tail -n 100 /var/log/httpd/error_logНа системном уровне следите за RAM, swap, CPU steal, iowait и количеством открытых файлов. Если после перехода память освободилась, не спешите сразу увеличивать все лимиты. Лучше оставить запас для пиков, обновлений, backup-операций и базы данных.
Итог: какую схему выбрать на VDS
Для нового или обновляемого Apache-сервера на VDS оптимальный выбор — mpm_event плюс php-fpm. Эта связка лучше использует память, устойчивее переносит keep-alive соединения, позволяет тонко управлять PHP-пулами и проще масштабируется на несколько сайтов. Она чуть сложнее на старте, зато понятнее в эксплуатации, когда появляются реальные нагрузки и разные проекты.
prefork и mod_php остаются рабочей, но наследуемой схемой. Её можно поддерживать, если проект небольшой, стабилен и не создаёт проблем. Но если вы уже упёрлись в RAM, видите очередь запросов, хотите несколько версий PHP или планируете нормальную изоляцию сайтов, переход на PHP-FPM почти наверняка окупит время настройки.
Главное — не воспринимать миграцию как один переключатель. Проверьте текущую схему, сделайте backup, включите нужные модули, аккуратно настройте виртуальные хосты, задайте разумные лимиты и посмотрите на метрики после запуска. Тогда Apache будет не источником загадочных 503 и OOM, а предсказуемой частью вашей VDS-инфраструктуры.


