Веб-сервер для PHP — это программа, которая принимает HTTP-запрос по сети, передает его интерпретатору PHP и отдает браузеру готовый ответ. Сам по себе PHP — это интерпретатор, а не сетевой сервер: чтобы страница открылась по адресу, ему нужен слой, который слушает порт. Ниже разберем два разных сценария: встроенный сервер php -S для локальной разработки и связку Apache с PHP для боевого сайта. Отдельно сравним два способа подключить PHP к Apache — mod_php и PHP-FPM — и покажем установку, настройку DocumentRoot, .htaccess и базовую защиту.
Содержание
- Как PHP исполняется на сервере
- Встроенный сервер php -S: только для разработки
- mod_php и PHP-FPM: два способа подключить PHP к Apache
- Установка и запуск Apache с PHP-FPM
- DocumentRoot и виртуальный хост
- .htaccess: локальные правила каталога
- Обработка запроса: путь от браузера до ответа
- Безопасность: базовый минимум
- Выводы
- Где применяется / связь с практикой
- FAQ
Проверено на сентябрь 2026: актуальная стабильная ветка — PHP 8.5 (последний релиз 8.5.10), ветка 8.4 в активной поддержке до конца 2026 года, обновления безопасности для нее — до конца 2028 года; Apache HTTP Server — 2.4.68.
Как PHP исполняется на сервере
Важно сразу развести три сущности, которые новички путают:
- веб-сервер (Apache, nginx) — слушает порт, принимает HTTP-запрос, отдает ответ;
- интерпретатор PHP — выполняет код
.phpи возвращает готовый HTML или иной текст; - SAPI (Server API) — интерфейс, через который сервер вызывает интерпретатор.
Один и тот же интерпретатор работает через разные SAPI: cli (запуск из терминала), cli-server (встроенный сервер php -S), fpm-fcgi (PHP-FPM), в старых сборках — модуль Apache (apache2handler). От выбора SAPI зависит, как именно запрос дойдет до вашего кода.
Встроенный сервер php -S: только для разработки
Начиная с PHP 5.4 в интерпретатор встроен простой веб-сервер. Он однопоточный: обрабатывает запросы по одному, и если один запрос завис, остальные ждут. Поэтому он удобен для локальной проверки, но не годится для продакшена.
Запуск из каталога с проектом:
cd ~/public_html
php -S localhost:8000
В консоли появится примерно такой вывод:
[Sat Sep 20 12:00:00 2026] PHP 8.5.10 Development Server (http://localhost:8000) started
Теперь http://localhost:8000/ откроется в браузере. Если URL не указывает на конкретный файл, сервер ищет index.php или index.html в каталоге; если файла нет — вернет код 404. Явно задать корень можно флагом -t:
php -S localhost:8000 -t public/
Здесь только ASCII-дефисы: -S и -t — это обычные короткие флаги, при копировании из статьи они должны остаться дефисами, а не превратиться в типографское тире.
Скрипт маршрутизации
Если после адреса и порта указать PHP-файл, он становится роутером: выполняется в начале каждого запроса. Если роутер возвращает false, сервер отдает запрошенный файл как есть (удобно для картинок и CSS), иначе браузеру уходит вывод скрипта.
<?php
// router.php - скрипт маршрутизации встроенного сервера
$uri = $_SERVER["REQUEST_URI"];
if (preg_match('/\.(?:png|jpg|css|js)$/', $uri)) {
return false; // отдать статический файл как есть
}
echo "Добро пожаловать";
Запуск: php -S localhost:8000 router.php. Запрос картинки вернет саму картинку, а запрос HTML-страницы — строку «Добро пожаловать». Режим с несколькими воркерами (переменная PHP_CLI_SERVER_WORKERS) существует с PHP 7.4, но помечен как экспериментальный и не работает в Windows — на него тоже не стоит опираться в бою.
mod_php и PHP-FPM: два способа подключить PHP к Apache
Для боевого сайта нужен полноценный веб-сервер. Классический выбор — Apache. Подключить к нему PHP можно двумя способами, и это ключевая развилка статьи.
- mod_php — PHP встроен в процесс Apache как модуль. Прост в настройке, но требует MPM
preforkи держит интерпретатор внутри каждого процесса сервера. - PHP-FPM (FastCGI Process Manager) — PHP работает отдельным процессом, а Apache общается с ним по FastCGI через модуль
mod_proxy_fcgi. Это рекомендуемый на 2026 год способ.
| Критерий | mod_php | PHP-FPM (через mod_proxy_fcgi) |
|---|---|---|
| Где живет PHP | внутри процесса Apache | отдельный процесс-менеджер |
| MPM Apache | только prefork |
event или worker (меньше памяти) |
| Изоляция | нет, общее адресное пространство | да, свои пулы и свой пользователь |
| Несколько версий PHP | сложно | легко: разные пулы и сокеты |
| Работа с nginx | нет | да, тот же FPM подходит и для nginx |
| Статус на 2026 | считается устаревшим, не по умолчанию | рекомендуемый вариант |
Как выбрать: для нового проекта берите PHP-FPM — он экономит память и позволяет держать несколько версий PHP. mod_php осмысленно оставить только в старом окружении, которое дорого перестраивать.
Установка и запуск Apache с PHP-FPM
Пример для Debian/Ubuntu. Имя пакета содержит версию: возьмем php8.4-fpm (стабильная поддерживаемая ветка); при желании ставится и php8.5-fpm.
sudo apt update
sudo apt install apache2 php8.4-fpm
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.4-fpm
sudo systemctl restart apache2
Команды a2enmod и a2enconf включают модуль проксирования FastCGI и готовый конфиг связки. После рестарта Apache будет отдавать .php через FPM. Проверить версию интерпретатора:
php -v
PHP 8.4.13 (cli) (built: ...)
Если версия ниже ожидаемой — значит, в системе несколько сборок PHP; уточните пакет и путь к сокету FPM (обычно /run/php/php8.4-fpm.sock).
DocumentRoot и виртуальный хост
DocumentRoot — каталог, который Apache считает корнем сайта: путь из URL приклеивается к нему. Хорошая практика — указывать на подкаталог public, чтобы код и конфиги лежали выше корня и не отдавались наружу.
<VirtualHost *:80>
ServerName example.local
DocumentRoot /var/www/example/public
<FilesMatch "\.php$">
SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost"
</FilesMatch>
<Directory /var/www/example/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Блок FilesMatch направляет файлы .php в PHP-FPM по unix-сокету (поддержка сокетов в mod_proxy_fcgi есть с Apache 2.4.9). Require all granted открывает доступ к каталогу; для служебных папок его меняют на запрет.
.htaccess: локальные правила каталога
.htaccess — файл с настройками Apache для конкретного каталога; он работает, только если в <Directory> разрешен AllowOverride. Типовое применение — «единая точка входа»: все несуществующие пути направить на index.php (front controller).
# public/.htaccess - направить все на index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
Условия проверяют, что файла и каталога нет, и только тогда передают управление в index.php. Учтите: .htaccess читается на каждый запрос и немного замедляет сервер, поэтому на нагруженных проектах правила выносят в основной конфиг, а AllowOverride ставят в None.
Обработка запроса: путь от браузера до ответа
Сквозная цепочка на связке Apache + PHP-FPM:
- браузер шлет HTTP-запрос
GET /pageна порт 80/443; - Apache сопоставляет запрос с виртуальным хостом и DocumentRoot;
- статический файл (картинку, CSS) Apache отдает сам;
.phpпо правилуSetHandlerуходит в PHP-FPM по сокету;- FPM запускает интерпретатор, тот выполняет код и возвращает ответ;
- Apache отдает результат браузеру и пишет строку в лог доступа.
Безопасность: базовый минимум
Первое — не показывать версии Apache и PHP: по ним подбирают известные уязвимости.
ServerTokens Prod
ServerSignature Off
В php.ini отключите заголовок с версией PHP:
expose_php = Off
Второе — права доступа. Не давайте рекурсивный chmod -R 777: это открывает запись всем. Разграничьте права направленно — каталогам 750, файлам 640 — и назначьте владельцем пользователя веб-сервера:
sudo find /var/www/example -type d -exec chmod 750 {} +
sudo find /var/www/example -type f -exec chmod 640 {} +
sudo chown -R www-data:www-data /var/www/example
Третье — держите код и загрузки вне DocumentRoot и включайте HTTPS. Встроенный php -S в открытую сеть не выставляйте: он для локальной разработки.
Выводы
- PHP — это интерпретатор, а не сетевой сервер; чтобы страница открывалась по адресу, нужен слой, слушающий порт: встроенный
php -Sили полноценный веб-сервер. - Встроенный сервер
php -Sоднопоточный и предназначен только для разработки, в продакшен его не выносят. - Для боевого сайта PHP подключают к Apache через PHP-FPM (
mod_proxy_fcgi);mod_phpна 2026 год считается устаревшим. - DocumentRoot стоит направлять на подкаталог
public, а разовые правила каталога держать в.htaccessтолько при разрешенномAllowOverride. - Базовая защита: скрыть версии (
ServerTokens Prod,expose_php = Off), задать направленные права (750/640) и не открывать dev-сервер в сеть.
Где применяется / связь с практикой
Связка PHP и Apache — это ежедневная рабочая среда backend-разработчика: на ней крутятся сайты на Laravel и Symfony, WordPress, самописные API. Умение поднять локальный php -S, а затем настроить боевой Apache с PHP-FPM, разобраться в DocumentRoot и .htaccess — базовый навык, который спрашивают на собеседованиях и который нужен с первого рабочего дня.
Освойте тему на практике
Системно освоить язык, окружение и деплой можно на курсе PHP-разработчик в Otus. Если хотите сначала посмотреть формат и уровень занятий, загляните на открытые уроки Otus — там разбирают практические темы вживую и отвечают на вопросы.
FAQ
Можно ли использовать php -S в продакшене, если нагрузка небольшая?
Не стоит: встроенный сервер однопоточный, без изоляции и без штатных инструментов защиты. Даже для маленького сайта берите Apache или nginx с PHP-FPM.
Что выбрать для nginx — тоже PHP-FPM?
Да. У nginx нет аналога mod_php, он всегда работает с PHP через FastCGI и PHP-FPM. Тот же пул FPM можно переиспользовать при миграции с Apache на nginx.
Почему после установки Apache отдает код PHP как текст, а не выполняет его?
Значит, обработчик .php не подключен: не включены proxy_fcgi и конфиг FPM, либо в SetHandler указан неверный путь к сокету. Проверьте a2enmod proxy_fcgi, a2enconf php8.4-fpm и перезапустите Apache.



