Вопрос или проблема
У меня есть 2 экземпляра AWS EC2, один из которых находится в публичной подсети и настроен как NAT экземпляр, и выполняет Nginx. Другой экземпляр находится в частной подсети, но может взаимодействовать с публичным. Соответствующие IP-адреса экземпляров, например:
- 172.25.48.14 – экземпляр Nginx в публичной подсети (172.25.48.0/28), имеет присвоенный Elastic IP
- 172.25.48.140 – экземпляр, выполняющий php-fpm в частной подсети (172.25.48.128/28)
Дело в том, что я хочу, чтобы этот веб-сайт был доступен по определенному URL – я предполагал, что Nginx будет действовать как обратный прокси-сервер, который сопоставляет запросы к определенным поддоменам или URL соответствующим ресурсам. И вот моя конфигурация Nginx:
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
server_names_hash_bucket_size 128;
include /etc/nginx/mime.types;
default_type text/html;
proxy_headers_hash_bucket_size;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 80;
location ~ ^/site1(.*)$ {
# Эти строки закомментированы, поскольку вне зависимости от того, указаны они или нет, результат остается тем же
# index index.php;
# try_files $uri $uri/ /site1/index.php?$request_uri;
location ~ \.php$ {
include fastcgi.conf;
try $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 172.25.48.140:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
}
А вот, соответственно, конфигурация пула php-fpm для сайта в частном экземпляре:
[site1]
user = www-data
group = www-data
listen = 172.25.48.140:9000
listen.allowed_clients = 172.25.48.14, 172.25.48.140, 127.0.0.1
php_admin_value[disable_functions] = exec, passthru, shell_exec, system
php_admin_flag[allow_url_fopen] = off
pm = dynamic
pm.max_children = 10
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 8
pm.process_idle_timeout = 30s
pm.status_path = /php_status
ping.path = /ping
ping.response = wrrrrrrrrryyyyyyyyyyy
access.log = /var/log/php/8.3/$pool.access.log
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{milli}d %{kilo}M %C%%"
Для простоты, давайте предположим, что у меня есть всего один index.php
файл, который также расположен в частном экземпляре по адресу /apps/site1/
, который имеет символическую ссылку на /var/www/html/site1
.
Проблема в том, что, что бы я ни пробовал, я получаю 404, и судя по логам на стороне частного экземпляра, запрос даже не доходит туда – хотя я знаю, что группы безопасности экземпляра настроены правильно и на нужных портах, потому что в противном случае я могу подключаться от частного экземпляра к публичному и наоборот без каких-либо проблем. Единственный случай, когда я смог передать запрос на php-fpm (хотя тоже 404), был, когда я переместил углубленный “location” (тот, который соответствует .php скриптам) на верхний уровень сервера – так что, по сути, запрос пошел прямо на 172.25.48.14
, а не на 172.25.48.14/site1
, как я предполагал.
Я что-то упускаю? Может быть, проблема в том, что исходные файлы находятся на том же экземпляре, что и php-fpm, а не на стороне Nginx? Я неправильно понимаю, как это работает? Пожалуйста, если у вас есть какие-либо идеи по этому поводу, я буду крайне благодарен за вашу помощь. Спасибо заранее!
-
Ваша конфигурация, проверяемая с помощью команды
nginx -t
, должна выдавать сообщение об ошибке, такое какnginx: [emerg] unknown directive "try" in ...
из-за строки
try $uri =404;
Если это должно быть
try_files $uri =404;
то это также не сработает. Это заставляет nginx проверять ваш URI запроса как физический файл относительно корня вашего веб-сервера (который вообще не определен), очевидно, что это не сработает (так как ваш PHP файл находится на другом хосте). Эта строка должна быть удалена из вашего вложенного местоположения.
-
Поскольку вы не явно определили корень вашего веб-сайта, по умолчанию он равен
{prefix}/html
, где{prefix}
является некоторым предварительно скомпилированным значением (можно посмотреть с помощью командыnginx -V
). Так что все, что вы передаете на ваш частный экземпляр черезfastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
скорее всего, неверно. Вам следует использовать либо
root /apps/site1;
либо
root /var/www/html/site1;
внутри вашего вложенного местоположения (хотя я не знаю, как PHP-FPM будет обрабатывать пути с включенными символическими ссылками).
-
Как уже говорилось на StackOverflow:
У вас есть вложенное местоположение, которое обрабатывает запросы
.php
, но похоже, что вы не запрашиваете фактический PHP файл в вашем тестовом URL. Типичный шаблон будет иметь директивуtry_files
, которая пытается загрузить запрашиваемый файл / каталог на диске или вернуться к маршрутизации запроса через файлindex.php
как фронтальный контроллер. Похоже, у вас этого нет.Добавьте либо
try_files $uri /site1/index.php$is_args$args;
либо
error_page 404 = /site1/index.php$is_args$args;
в ваше родительское местоположение.
-
Вам не нужно использовать обе
include fastcgi.conf;
и
include fastcgi_params;
в вашем вложенном местоположении. Они почти одинаковы, единственное отличие заключается в том, что файл
fastcgi.conf
включает строкуfastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
в то время как
fastcgi_params
не включает ее (если вы используете файлfastcgi_params
вместоfastcgi.conf
, вы должны включить эту строку сами). -
Любые вещи, связанные с
PATH_INFO
, такие какfastcgi_split_path_info ^(.+\.php)(/.+)$;
не имеют смысла в
location ~ \.php$ { ... }
местах (в отличие отlocation ~ \.php(?:/|$) { ... }
). -
Почему бы не использовать простое префиксное местоположение, такое как
location /site1/ { ... }
или
location ^~ /site1/ { ... }
? Особенно если вы все равно не используете группу захвата регулярного выражения.
Ответ или решение
Настройка обратного прокси Nginx для удаленного сервера PHP-FPM с FastCGI в AWS
В этой инструкции рассмотрим, как правильно настроить обратный прокси Nginx на экземпляре AWS EC2, который будет направлять запросы на удаленный сервер PHP-FPM, расположенный в частной подсети. У вас уже настроены два экземпляра EC2: один работает в публичной подсети и содержит Nginx, а другой выполняет PHP-FPM в частной подсети.
Шаг 1: Правильная конфигурация Nginx
Ваш исходный конфигурационный файл Nginx, судя по всему, нуждается в доработке. Следует обратить внимание на несколько деталей:
-
Корневая директория (root)
Укажите корневую директорию для вашего приложения. В вашем случае приложение находится в
/apps/site1
, поэтому в конфигурации Nginx необходимо добавить:location /site1/ { root /apps/site1; # Другие параметры... }
-
Настройка обработки PHP файлов
Вы правильно предполагаете использовать FastCGI для обработки PHP. Однако у вас есть ошибка в конфигурации. Замените:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
на
fastcgi_param SCRIPT_FILENAME $document_root/site1$fastcgi_script_name;
Это гарантирует, что Nginx правильно найдет ваш файл
index.php
. -
Использование
try_files
Добавьте директиву
try_files
, которая будет проверять существование запрашиваемого файла или перенаправлять наindex.php
:location /site1/ { try_files $uri /site1/index.php$is_args$args; # Настройки для обработки PHP... }
Шаг 2: Конфигурация PHP-FPM
Ваша конфигурация пула PHP-FPM также требует внимания. Убедитесь, что он слушает только на интерфейсе, который доступен для Nginx (в вашем случае 172.25.48.140:9000
):
[site1]
listen = 172.25.48.140:9000
listen.allowed_clients = 172.25.48.14, 127.0.0.1
Шаг 3: Устранение ошибок и отладка
-
Логи Nginx
Убедитесь, что используете логи доступа и ошибки Nginx, чтобы видеть, какие запросы обрабатываются и какие ошибки возникают. Они находятся по указанному вами пути:
access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log;
-
Логи PHP-FPM
Также проверьте логи PHP-FPM, чтобы убедиться, что запросы фактически доходят до сервера PHP-FPM. Лог может находиться по пути:
/var/log/php/8.3/site1.access.log
Шаг 4: Проверка и тестирование
После внесения всех изменений перезапустите Nginx и PHP-FPM:
sudo systemctl restart nginx
sudo systemctl restart php-fpm
Затем проверьте:
- Доступность
http://<your-elastic-ip>/site1/index.php
. - Правильность работы и отсутствие ошибок 404.
Заключение
Обработка запросов через Nginx в качестве обратного прокси на сервер PHP-FPM может быть тонким процессом, требующим внимания к деталям конфигурации. Проверьте правильность указанных путей, необходимых параметров и логов для диагностики. Удачи в настройке!