Связка Nginx и PHP: эффективные методы настройки
Основные принципы настройки Nginx для работы с PHP
Как настроить стандартную связку Nginx и PHP-FPM через Unix-сокет?
Наиболее эффективное и распространённое решение - использование FastCGI-прокси с передачей запросов на PHP-FPM через Unix-сокет. Это обеспечивает низкую задержку и минимум накладных расходов.
server {
listen 80;
server_name example.com;
root /var/www/example.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Пояснение шагов:
- Директива
listenуказывает порт для входящих соединений. rootзадаёт корневую директорию сайта.try_filesпозволяет обрабатывать запросы без явного указания PHP-скрипта (через фронт-контроллер).- Блок
location ~ \.php$перехватывает все PHP-запросы. fastcgi_passуказывает путь к Unix-сокету PHP-FPM.fastcgi_param SCRIPT_FILENAMEпередаёт полный путь к скрипту.
Типичные ошибки и их устранение:
- Ошибка 502 Bad Gateway - PHP-FPM не запущен или сокет недоступен. Проверка:
systemctl status php8.2-fpm. - Ошибка 404 при обращении к PHP-файлу - неверный путь в
SCRIPT_FILENAME. Убедитесь, что$document_rootсовпадает сroot. - Ошибка доступа к сокету - пользователь nginx не имеет прав на чтение/запись сокета. Решение: настроить юзера в пуле PHP-FPM или изменить права сокета.
Цель использования: универсальная базовая настройка для большинства проектов на PHP (WordPress, Laravel, Symfony).
Как организовать связку Nginx с PHP-FPM через TCP-сокет?
Если PHP-FPM работает на другом сервере или требуется отдельная сетевая изоляция, используется TCP-соединение на порт 9000 (по умолчанию).
fastcgi_pass 127.0.0.1:9000;
# или внешний IP:
# fastcgi_pass 192.168.1.100:9000;
В конфигурации пула (например, /etc/php/8.2/fpm/pool.d/www.conf) необходимо указать listen = 127.0.0.1:9000.
Проблемы: повышенное сетевое потребление, порт может быть занят другими службами. Убедитесь, что брандмауэр разрешает соединение. Для внешнего подключения используйте только доверенные сети.
Когда применяется: распределённые системы, контейнеризация (Docker), облачные архитектуры.
Как изолировать несколько веб-сайтов с помощью отдельных пулов PHP-FPM?
Для разграничения ресурсов между проектами создают разные пулы PHP-FPM с различными сокетами или портами.
# /etc/php/8.2/fpm/pool.d/site1.conf
[site1]
user = site1
listen = /var/run/php/site1.sock
listen.owner = www-data
listen.mode = 0660
# /etc/php/8.2/fpm/pool.d/site2.conf
[site2]
user = site2
listen = /var/run/php/site2.sock
В конфигурации Nginx для каждого сайта указывается свой сокет:
fastcgi_pass unix:/var/run/php/site1.sock;
Возможные сложности: нужно корректно настроить права доступа к сокетам и следить за нагрузкой на каждый пул. Ошибка в имени пула приведёт к неработоспособности сайта.
Цель: повышение безопасности и стабильности на shared-хостинге или при размещении нескольких приложений.
Как использовать Nginx в качестве reverse proxy для Apache с PHP?
Если уже используется Apache как обработчик PHP (например, mod_php), можно поставить Nginx перед ним для проксирования статики.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ~ \.(jpg|png|css|js)$ {
root /var/www/example.com;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Apache слушает на порту 8080, Nginx отдаёт статические файлы напрямую, а PHP-запросы передаёт в Apache.
Проблемы: Apache может потреблять больше памяти; необходимо синхронизировать конфигурации. Убедитесь, что proxy_pass не создаёт циклов.
Случаи применения: миграция с Apache на Nginx, использование модулей Apache (.htaccess, mod_rewrite).
Как ускорить PHP-сайты с помощью FastCGI Cache?
Кэширование ответов PHP снижает нагрузку на сервер и ускоряет отдачу страниц.
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=phpcache:10m inactive=60m;
server {
...
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_cache phpcache;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 302 60m;
fastcgi_cache_valid 404 1m;
add_header X-FastCGI-Cache $upstream_cache_status;
}
}
Добавлен заголовок X-FastCGI-Cache для отладки (HIT/MISS).
Типичные ошибки: избыточное кэширование динамического контента (формы, корзина). Используйте fastcgi_cache_bypass и fastcgi_no_cache для исключения критичных страниц.
Когда полезен: новостные сайты, блоги, корпоративные порталы с большим количеством одинаковых запросов.
Как оптимизировать отдачу статических файлов через Nginx?
PHP не должен обрабатывать css, js, изображения. Nginx отдаёт их напрямую, минуя FastCGI.
location ~* \.(ico|jpg|jpeg|png|gif|svg|css|js|woff2?)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
log_not_found off;
try_files $uri =404;
}
Этот блок следует разместить до обработки PHP-запросов.
Проблемы при неправильном порядке: статика может уйти в PHP, вызывая лишнюю нагрузку. Убедитесь, что блок статики расположен выше location ~ \.php$.
Цель: снижение нагрузки на PHP-FPM, ускорение загрузки страниц.
Расширенные примеры настройки Nginx и PHP
1. Балансировка нагрузки между несколькими PHP-FPM серверами
Используется upstream для распределения запросов между несколькими бэкендами.
upstream php_backend {
least_conn;
server unix:/var/run/php/php8.2-fpm.sock weight=3;
server 192.168.1.101:9000 weight=1;
server 192.168.1.102:9000 backup;
}
server {
...
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass php_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Результат: запросы равномерно распределяются (метод least_conn - на сервер с наименьшим числом активных подключений).
2. Кэширование с учётом сессий (исключение страниц входа)
Чтобы не кэшировать страницы для авторизованных пользователей, используют куки.
location ~ \.php$ {
set $no_cache 0;
if ($cookie_session) {
set $no_cache 1;
}
fastcgi_no_cache $no_cache;
fastcgi_cache_bypass $no_cache;
...
}
Результат: при наличии куки session кэш не используется, динамический контент обрабатывается PHP.
3. Использование переменных в fastcgi_pass для выбора пула
Позволяет динамически направлять запросы к разным пулам в зависимости от имени сервера.
map $http_host $fpm_socket {
default unix:/var/run/php/default.sock;
site2.com unix:/var/run/php/site2.sock;
admin.example.com unix:/var/run/php/admin.sock;
}
server {
...
location ~ \.php$ {
fastcgi_pass $fpm_socket;
...
}
}
Результат: для admin.example.com используется отдельный сокет, остальные идут в default.
4. Ограничение количества одновременных PHP-запросов
Защита от перегрузки через лимиты nginx.
limit_req_zone $binary_remote_addr zone=phplimit:10m rate=30r/s;
server {
...
location ~ \.php$ {
limit_req zone=phplimit burst=10 nodelay;
...
}
}
Результат: максимум 30 запросов в секунду с одного IP, при превышении - задержка или ошибка 503.
5. Детальное логирование PHP-запросов
Включение дополнительных параметров в лог для отладки.
log_format php_debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream=$upstream_addr cache=$upstream_cache_status request_time=$request_time';
server {
access_log /var/log/nginx/example.com_php.log php_debug;
...
}
Результат: в логе появится адрес upstream, статус кэша и время обработки.