Конфигурация Apache 2.4 и PHP: практическое руководство
Настройка Apache 2.4 для работы с PHP
Основное решение: модуль mod_php (исполнение PHP внутри Apache)
Этот способ подходит, если используется MPM prefork и требуется максимальная производительность для статических PHP-скриптов. PHP-интерпретатор встраивается непосредственно в процесс Apache, что даёт наименьшую задержку.
Пошаговая установка (на примере PHP 8.2, Debian/Ubuntu)
sudo apt update
sudo apt install apache2 php8.2 libapache2-mod-php8.2
sudo a2enmod php8.2
sudo systemctl restart apache2
После установки модуль mod_php автоматически подключает обработчик для файлов .php. Убедиться в этом можно командой:
sudo apache2ctl -M | grep php
Вывод должен содержать строку php8_module (или php7_module).
Типичные ошибки и их решение
Проблема: Файлы PHP не обрабатываются, браузер выводит исходный код.
Причина: Отсутствует директива AddType application/x-httpd-php .php или модуль не включён.
Решение: Проверьте конфигурацию в файле /etc/apache2/mods-enabled/php8.2.conf. Если его нет – выполните sudo a2enmod php8.2. Вручную можно добавить в virtual host:
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Проблема: Конфликт с PHP-FPM, когда одновременно активированы mod_php и mod_proxy_fcgi.
Решение: Отключите mod_php, если используете FPM: sudo a2dismod php8.2.
Вариант: PHP-FPM через mod_proxy_fcgi (для event/worker MPM)
Как настроить Apache для работы с PHP-FPM?
Этот вариант позволяет отделить процесс PHP от Apache, используя быстрый CGI-прокси. Рекомендуется для сайтов с высокой нагрузкой и при использовании MPM event или worker.
Установка и настройка
sudo apt install php8.2-fpm
sudo a2enmod proxy_fcgi setenvif
sudo systemctl restart apache2
Далее нужно указать Apache обрабатывать PHP через сокет PHP-FPM. Внутри virtual host добавить:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Проверить синтаксис конфигурации: sudo apache2ctl configtest.
Проблема: Ошибка 502 Bad Gateway.
Причина: PHP-FPM не запущен, или не совпадает путь к сокету.
Решение: Проверьте статус sudo systemctl status php8.2-fpm. Убедитесь, что сокет существует (ls -la /run/php/). Если используется TCP-порт (например, 127.0.0.1:9000), замените unix-сокет на fcgi://127.0.0.1:9000.
Проблема: PHP-скрипты выполняются, но медленно.
Решение: Увеличьте количество процессов PHP-FPM в его конфигурации (/etc/php/8.2/fpm/pool.d/www.conf): pm.max_children = 50. Или используйте директиву ProxySet для настройки таймаутов в Apache.
Вариант: CGI (mod_cgi) – устаревший, но совместимый
Когда имеет смысл использовать CGI для PHP?
Этот способ применяется очень редко, в основном для изоляции PHP-скриптов в средах с повышенными требованиями безопасности, либо для совместимости с очень старыми версиями PHP. Каждый запрос запускает отдельный процесс интерпретатора.
Настройка
sudo a2enmod cgi
sudo systemctl restart apache2
# В virtual host:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI
AddHandler cgi-script .php
Require all granted
</Directory>
Скрипты помещаются в каталог /usr/lib/cgi-bin/ и должны иметь права на выполнение.
Проблема: Ошибка 403 Forbidden при попытке доступа к cgi-скрипту.
Причина: Неправильные права или отсутствие директивы Options +ExecCGI.
Решение: Установите права 755 на скрипт и проверьте, что Apache может читать каталог. Добавьте Require all granted.
Проблема: Высокая нагрузка на сервер при большом количестве запросов.
Причина: CGI запускает новый процесс на каждый запрос.
Решение: Используйте PHP-FPM или mod_php вместо CGI.
Расширенные примеры конфигурации и отладки
1. Полный Virtual Host с поддержкой PHP (mod_php и PHP-FPM в одном домене)
<VirtualHost *:8080>
ServerName app.local
DocumentRoot /var/www/app
# Для статики используем кеширование
<LocationMatch "\.(jpg|png|css|js)$">
Header set Cache-Control "max-age=86400, public"
</LocationMatch>
# PHP через mod_php (если нужен быстрый путь)
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
# Альтернативный путь через PHP-FPM для отдельных скриптов
<Location /admin/>
SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost"
</Location>
ErrorLog ${APACHE_LOG_DIR}/app-error.log
CustomLog ${APACHE_LOG_DIR}/app-access.log combined
</VirtualHost>
# Результат: запросы к /index.php обрабатываются mod_php, к /admin/script.php – PHP-FPM. # Лог показывает два разных обработчика.
2. Проверка конфигурации с помощью phpinfo()
# Создайте файл info.php в корне DocumentRoot:
<?php phpinfo(); ?>
# Затем откройте в браузере http://example.com/info.php
# Вы увидите секцию 'Server API' – она показывает, какой обработчик используется (Apache 2.0 Handler – для mod_php, FPM/FastCGI – для PHP-FPM).
3. Отладка проблем с PHP-FPM через переменные окружения
# Включите логирование ошибок PHP-FPM:
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
# Раскомментируйте или добавьте:
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php-fpm-error.log
# Используйте SetEnvIf в Apache для проброса переменных:
SetEnvIf Request_URI ^/api no-gzip
<LocationMatch "/api/.*\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000"
Header set X-Debug-Proxy "PHP-FPM"
</LocationMatch>
# Результат: в заголовках ответа появляется X-Debug-Proxy: PHP-FPM. # Лог PHP-FPM содержит детальные сообщения об ошибках конкретного скрипта.
4. Настройка таймаутов и лимитов через ProxySet
<VirtualHost *:80>
ServerName slow.example.com
DocumentRoot /var/www/slow
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
<Proxy fcgi://localhost enablereuse=On max=10 timeout=300>
# Увеличенный таймаут для долгих скриптов
ProxySet timeout=600
</Proxy>
TimeOut 600
</VirtualHost>
# Результат: Apache ждёт ответа от PHP-FPM до 10 минут, прежде чем вернуть ошибку 504 Gateway Timeout. # Значение enablereuse=On позволяет переиспользовать соединения.
5. Использование .htaccess для переключения обработчика PHP
# В каталоге /var/www/example/subdir/ создаём .htaccess:
RewriteEngine On
RewriteRule ^test\.php$ - [E=HANDLER:proxy:fcgi://127.0.0.1:9000]
# Или задаём обработчик через SetHandlerIf:
<If "%{REQUEST_URI} =~ /legacy/">
SetHandler cgi-script
</If>
# Результат: для всех файлов в подкаталоге test.php обрабатывается через PHP-FPM, остальные – через mod_php. # Удобно при поэтапном переходе с mod_php на FPM.