Использование Nginx и Apache совместно с PHP

Раздел: Администрирование веб-серверов -> Настройка веб-сервера Nginx и 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 (англ.))

Пошаговое пояснение:

  1. Указывается корневая директория сайта.
  2. Директива try_files обеспечивает перенаправление всех запросов на index.php для поддержки ЧПУ.
  3. Блок location ~ \.php$ перехватывает PHP-файлы и передает их в PHP-FPM.
  4. Параметр fastcgi_pass указывает путь к сокету. Можно использовать TCP: 127.0.0.1:9000.
  5. Обязательно наличие 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 .php

Nginx 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.1

Nginx 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.

Nginx и Apache с PHP - comments

En
Nginx apache php (php)