Связка Nginx и PHP: эффективные методы настройки

Раздел: Администрирование 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, статус кэша и время обработки.

Настройка Nginx для PHP - comments

En
Nginx php (php)