proxy_pass — это директива Nginx, при помощи которой можно передавать входящие HTTP-запросы другому сервису. Nginx в принимает запрос от клиента, отправляет его на указанный адрес и возвращает ответ обратно.
Один из самых распространенных примеров применения — сервис, запущенный на сервере и доступный только локально по адресу вида localhost:порт. Технически можно открыть этот порт наружу и обращаться к сервису напрямую, но такой подход может быть неудобным и небезопасным. Обращаться к сервису по домену проще, а сам сервис при этом может не поддерживать SSL, авторизацию или ограничение доступа по IP. В такой схеме Nginx принимает запросы по домену и проксирует их на локальный порт сервиса.
Другой сценарий — использование вебхуков. Например, при работе Telegram-бота вебхуки требуют публичный HTTPS-адрес. Сам бот при этом может работать локально или в контейнере и принимать HTTP-запросы. Nginx в этом случае используется для приема HTTPS-запросов, обработки сертификатов и проксирования запросов к сервису бота через proxy_pass.
proxy_pass также часто применяют, когда инфраструктура разнесена на несколько серверов. Например, сайт работает на одном сервере, а форум — на другом. С помощью Nginx можно настроить проксирование так, чтобы при обращении к /forum запросы отправлялись на отдельный сервер с форумом. Для пользователя все выглядит как единый сайт, хотя фактически сервисы физически разделены.
Перечисленные примеры — лишь часть ситуаций, в которых применим proxy_pass.
Предварительная подготовка
Если Nginx еще не установлен — установите его при помощи команд:
sudo apt update && sudo apt install nginx -y
После установки запустите сервис и добавьте его в автозагрузку:
sudo systemctl start nginx && sudo systemctl enable nginx
Проверьте статус сервиса — он должен быть в состоянии active:
sudo systemctl status nginx
Для удобства управления конфигурациями рекомендуется создавать отдельный конфиг для каждого сервиса. В rpm-based дистрибутивах конфигурационные файлы обычно располагаются в каталоге /etc/nginx/conf.d/.
В deb-based дистрибутивах используется другая схема: конфиги размещаются в /etc/nginx/sites-available/, а для их активации создаются симлинки в /etc/nginx/sites-enabled/.
Далее в примерах будет использоваться deb-based дистрибутив.
По умолчанию Nginx создает конфигурацию default. Если обратиться в браузере к адресу http://IP_сервера, вы увидите стандартную заглушку Nginx — за нее как раз отвечает этот конфиг. Его можно удалить:
rm /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
Создайте новый конфигурационный файл для сервиса:
touch /etc/nginx/sites-available/my-service.conf
И сразу создайте симлинк:
sudo ln -s /etc/nginx/sites-available/my-service.conf /etc/nginx/sites-enabled/
Далее, после любого изменения конфигурации проверьте ее корректность:
nginx -t
Если ошибок нет, примените изменения:
systemctl reload nginx
Пример использования
В первом примере представим, что сервис запущен на localhost:6789. Это может быть, например, сайт на Python или Telegram-бот на Node.js, запущенный через gunicorn или pm2. Мы хотим, чтобы сервис был доступен из интернета по домену service.example.com.
Откройте конфигурационный файл для редактирования:
nano /etc/nginx/sites-available/my-service.conf
Минимальная конфигурация будет выглядеть следующим образом:
server { listen 80; server_name _; location / { proxy_pass http://127.0.0.1:6789; } }
При такой конфигурации все обращения к серверу, включая обращения по его IP-адресу, будут проксироваться на внутренний сервис 127.0.0.1:6789. Вместо IP-адреса можно указать домен, URI или путь к UNIX-сокету.
Чтобы сервис был доступен по конкретному домену, укажите его вместо _ в директиве server_name.
В текущей конфигурации внутреннему сервису не передаются заголовки, которые отправляет клиент. Это может привести к проблемам с логированием, редиректами и определением реального IP клиента. Для передачи заголовков используются директивы proxy_set_header. Также имеет смысл отключить буферизацию ответов с помощью proxy_buffering, особенно если сервис отдает данные потоково или используется для вебхуков.
Итоговая конфигурация может выглядеть так:
server { listen 80; server_name service.example.com; location / { proxy_pass http://127.0.0.1:6789; proxy_http_version 1.1; 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; proxy_buffering off; } }
Проверьте конфигурацию:
nginx -t
И перезагрузите Nginx, чтобы применить изменения:
systemctl reload nginx
Проксирование части запроса
Предположим, что у сервиса есть API, который расположен на другом сервере и должен быть доступен по адресу service.example.com/api. В этом случае также можно использовать proxy_pass.
Добавьте новый блок location в конфигурационный файл:
server {
listen 80;
server_name service.example.com;
location / {
proxy_pass http://127.0.0.1:6789;
proxy_http_version 1.1;
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;
proxy_buffering off;
}
location /api/ {
proxy_pass http://ip_стороннего_сервера:8000;
}
}
В этом случае все запросы к /api будут проксироваться на отдельный сервер, а остальные — обрабатываться основным сервисом.
Настройка авторизации
Чтобы ограничить доступ к сервису с помощью базовой HTTP-аутентификации, сначала сгенерируйте хэш пароля. Например, с помощью openssl:
openssl passwd -apr1
Дважды укажите желаемый пароль. В результате команда вернет строку с хэшем, например:
$apr1$9o.mJgYk$43kvlHx0DSqezaAL3yMHe1
Создайте файл для хранения логинов и хэшей паролей. Его можно разместить в любой удобной директории, например в каталоге Nginx:
nano /etc/nginx/.htpasswd
Укажите в файле данные в формате имя_пользователя:хэш_пароля:
admin:$apr1$9o.mJgYk$43kvlHx0DSqezaAL3yMHe1
Сохраните файл и установите для него права доступа:
sudo chmod 640 /etc/nginx/.htpasswd
Задайте владельца и группу:
sudo chown root:www-data /etc/nginx/.htpasswd
В rpm-based дистрибутивах группу www-data нужно заменить на nginx.
После этого добавьте директивы auth_basic в конфигурацию Nginx:
server {
listen 80;
server_name service.example.com;
location / {
proxy_pass http://127.0.0.1:6789;
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_http_version 1.1;
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;
proxy_buffering off;
}
}
Проверьте конфигурацию и примените изменения:
sudo nginx -t
sudo systemctl reload nginx
Ограничение по IP
Чтобы ограничить доступ к сервису по IP-адресам, используйте директивы allow и deny. Пример конфигурации:
server {
listen 80;
server_name service.example.com;
location / {
allow IP1;
allow IP2.0/24;
deny all;
proxy_pass http://127.0.0.1:6789;
proxy_http_version 1.1;
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;
proxy_buffering off;
}
}
В этом случае доступ к сервису будет разрешен только с IP-адреса IP1 и из подсети IP2.0/24.
Настройка SSL
Чтобы настроить SSL-сертификат для уже существующего конфига, можно воспользоваться certbot или установить сертификат вручную.