Использование Nginx и Apache совместно с PHP
При настройке веб-сервера для обработки PHP-скриптов администраторы часто выбирают между Nginx и Apache, а также их комбинацией. Каждый подход имеет свои преимущества и ограничения. В этой статье рассмотрены основные схемы, даны примеры конфигураций и раскрыты типичные проблемы.
Основной вариант: Nginx с PHP-FPM
Как настроить Nginx для работы с PHP через FastCGI Process Manager (PHP-FPM)?
Это решение считается наиболее производительным для большинства современных проектов. Nginx обрабатывает статические файлы и передает запросы к PHP-FPM через Unix-сокет или TCP. PHP-FPM управляет пулом процессов PHP, обеспечивая высокую стабильность.
Цель: обеспечить высокую скорость и низкое потребление памяти при пиковых нагрузках. Подходит для сайтов с большим количеством одновременных подключений.
server {
listen 80;
server_name example.com;
root /var/www/example.com/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}Install nginx php (установка nginx и php (англ.))
Пошаговое пояснение:
- Указывается корневая директория сайта.
- Директива
try_filesобеспечивает перенаправление всех запросов на index.php для поддержки ЧПУ. - Блок
location ~ \.php$перехватывает PHP-файлы и передает их в PHP-FPM. - Параметр
fastcgi_passуказывает путь к сокету. Можно использовать TCP: 127.0.0.1:9000. - Обязательно наличие
include fastcgi_paramsдля передачи стандартных переменных.
Распространенная ошибка: файлы PHP скачиваются вместо выполнения.
Причина: отсутствует блок location ~ \.php$ или не установлен PHP-FPM. Проверьте, что сокет существует (ls -la /var/run/php/) и сервис запущен (systemctl status php8.1-fpm).
502 Bad Gateway
Указывает на недоступность PHP-FPM. Перезапустите сервис и проверьте конфигурацию пула (файлы в /etc/php/8.1/fpm/pool.d/). Убедитесь, что listen указан корректно.
Вариант 1: Nginx как прокси перед Apache (mod_php)
Как использовать Nginx в качестве фронтенда, а Apache с mod_php как backend?
Этот подход применяется, когда проект уже работает на Apache и содержит множество правил .htaccess, которые сложно перенести. Nginx отдает статические файлы и проксирует все остальные запросы на Apache, работающий на другом порту (например, 8080).
Случаи использования: миграция с Apache на Nginx без изменения бэкенда; необходимость использования .htaccess; совместимость с legacy-приложениями.
# nginx.conf
server {
listen 80;
server_name example.com;
root /var/www/example.com;
location / {
try_files $uri @apache;
}
location @apache {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ \.php$ {
proxy_pass http://127.0.0.1:8080;
}
}Nginx apache php (nginx и apache с php)
Apache настраивается стандартно: загружается mod_php, корневая папка совпадает с nginx root.
# httpd.conf (Apache)
Listen 8080
DocumentRoot "/var/www/example.com"
AllowOverride All
Require all granted
LoadModule php_module modules/libphp.so
AddHandler php-script .phpNginx html php (обработка html и php в nginx)
Проблема: IP посетителя заменяется адресом 127.0.0.1.
Решение: установить в Apache модуль mod_remoteip и настроить его для получения реального IP из заголовка X-Forwarded-For.
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1Nginx index php (настройка index.php в nginx)
Ошибка: статические файлы не отдаются Nginx, все проксируется на Apache.
Проверьте, что try_files $uri @apache работает корректно, и root одинаков в обоих серверах.
Вариант 2: Apache с PHP-FPM
Как настроить Apache для работы с PHP через PHP-FPM вместо встроенного mod_php?
Современный способ использования Apache с PHP: вместо mod_php подключается PHP-FPM через модуль mod_proxy_fcgi. Это позволяет разделить процессы Apache и PHP, улучшая стабильность и безопасность.
Подходит для проектов, где требуется совместимость с .htaccess, но нужна более высокая производительность, чем mod_php.
# httpd.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
SetHandler "proxy:fcgi://127.0.0.1:9000"
# Или через Unix-сокет:
# SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost"установка nginx php (установка nginx и php)
PHP-FPM настраивается отдельно, слушает на порту 9000 или на сокете. Apache должен быть скомпилирован с поддержкой proxy_fcgi.
Ошибка: 503 Service Unavailable.
Причина: PHP-FPM не запущен или не принимает соединения. Проверьте пул и перезапустите оба сервиса.
Проблема: медленная загрузка страниц.
Может быть связано с неправильной конфигурацией пула PHP-FPM (например, слишком маленькое количество процессов).
Вариант 3: Nginx с PHP-FPM и кешированием FastCGI
Как включить кеширование динамического контента в Nginx для PHP?
Для ускорения работы можно настроить кеширование FastCGI, при котором Nginx сохраняет ответы PHP в памяти или на диске и отдает их без обращения к PHP-FPM для заданного времени.
Используется для сайтов с большим количеством динамических страниц, которые редко меняются (лендинги, порталы).
http {
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:100m max_size=10g inactive=60m;
server {
listen 80;
server_name example.com;
root /var/www/example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_cache CACHE;
fastcgi_cache_valid 200 60m;
fastcgi_cache_use_stale error timeout updating;
fastcgi_cache_methods GET HEAD;
add_header X-Cache $upstream_cache_status;
}
}
}
Проблема: кеширование не работает, заголовок X-Cache всегда MISS.
Проверьте права доступа к директории /var/cache/nginx, убедитесь, что модуль ngx_http_fastcgi_module включен. Может потребоваться очистка кеша: rm -rf /var/cache/nginx/*.
Расширенные примеры конфигураций
Пример 1: Несколько версий PHP через разные пулы PHP-FPM
Для одновременной работы разных версий PHP создаются отдельные пулы, слушающие разные сокеты.
# /etc/php/7.4/fpm/pool.d/www.conf
[www74]
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 10
# /etc/php/8.1/fpm/pool.d/www.conf
[www81]
user = www-data
group = www-data
listen = /run/php/php8.1-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 20
В Nginx для сайта, использующего PHP 7.4, указывается fastcgi_pass unix:/run/php/php7.4-fpm.sock;, для PHP 8.1 - соответственно.
Результат: разные версии PHP работают параллельно без конфликтов.
Пример 2: Балансировка нагрузки между несколькими PHP-FPM через upstream
Позволяет распределять запросы между несколькими экземплярами PHP-FPM.
upstream php_upstream {
server unix:/var/run/php/php8.1-fpm.sock weight=3;
server 192.168.1.10:9000 weight=1 backup;
hash $request_uri consistent;
}
server {
...
location ~ \.php$ {
fastcgi_pass php_upstream;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Директива hash $request_uri consistent обеспечивает привязку запросов к одному серверу (сессионная стабильность).
Результат: увеличивается пропускная способность при высоких нагрузках.
Пример 3: Переменные окружения в PHP-FPM
Через конфигурацию пула можно задавать переменные окружения, доступные в PHP через $_ENV или getenv().
[www]
env[APP_ENV] = production
env[DATABASE_URL] = mysql://user:pass@localhost/db
Результат: внутри PHP к переменным можно обращаться: echo getenv('APP_ENV'); // production
Пример 4: Ограничение доступа к PHP по IP в Nginx
Позволяет разрешить выполнение PHP-скриптов только с определенных IP-адресов.
location ~ \.php$ {
allow 192.168.1.0/24;
deny all;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Результат: при попытке доступа с IP не из сети 192.168.1.0/24 Nginx вернет 403 Forbidden.
Пример 5: Настройка лимитов для загрузки больших файлов
Увеличивается максимальный размер тела запроса и тайм-ауты для больших файлов.
http {
client_max_body_size 50M;
fastcgi_read_timeout 300;
...
server {
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_buffering off;
...
}
}
}
Результат: возможность загружать файлы до 50 МБ без ошибок 413 или 504.
Пример 6: Использование событийного MPM в Apache с PHP-FPM
Для высокой производительности Apache рекомендуется MPM event в сочетании с PHP-FPM.
# httpd.conf
LoadModule mpm_event_module modules/mod_mpm_event.so
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 1000
SetHandler "proxy:fcgi://127.0.0.1:9000"
Результат: Apache обрабатывает больше одновременных запросов при меньшем потреблении памяти.
Пример 7: Настройка chroot для PHP-FPM (ограничение доступа к файловой системе)
Повышает безопасность, изолируя PHP-процессы в отдельной корневой директории.
[www]
chroot = /srv/php-jail
chdir = /
user = www-data
group = www-data
listen = /run/php/php8.1-fpm.sock
security.limit_extensions = .php .php3 .php4 .php5 .phtml
Внутри chroot необходимо скопировать все необходимые библиотеки и исполняемые файлы.
Результат: PHP-скрипты не могут получить доступ к файлам за пределами /srv/php-jail.