Reverse proxy — базовый элемент веб-инфраструктуры: Nginx принимает трафик на порту 80/443 и перенаправляет его на приложение на внутреннем порту. Так получают единый вход, HTTPS и возможность поднимать несколько сервисов. Разберём настройку Nginx как reverse proxy, выпуск сертификатов и их автообновление.
Установка и структура конфигов
В Debian и Ubuntu конфигурация разложена по каталогам: общие настройки в nginx.conf, сайты — в sites-available с ссылками в sites-enabled. Так проще отключать виртуальные хосты без удаления файлов.
sudo apt update && sudo apt install nginx
# структура
ls /etc/nginx/sites-available /etc/nginx/sites-enabled
# статус
systemctl status nginx --no-pager | head
# проверить конфиг перед перезагрузкой
sudo nginx -t
Всегда выполняйте nginx -t перед reload: Nginx откажется перезагружаться при ошибке, и текущая конфигурация останется рабочей.
Базовый reverse proxy
Приложение слушает локальный порт, Nginx проксирует запросы на него. Важно передавать заголовки: без них приложение не узнает исходный IP и протокол.
# /etc/nginx/sites-available/app
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
# включить сайт
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Блок Upgrade/Connection нужен для WebSocket. Если приложение его не использует, строку Connection можно убрать.
Статические файлы и тайм-ауты
Если приложение отдаёт статику, лучше раздать её напрямую Nginx: это снимает нагрузку с процесса и ускоряет ответ. Тайм-ауты увеличивайте только там, где реально долгие операции.
location /static/ {
alias /srv/app/static/;
expires 30d;
access_log off;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 60s;
proxy_connect_timeout 5s;
}
Не ставьте proxy_read_timeout 3600s «на всякий случай»: это скрывает зависшие запросы.
HTTPS через Let’s Encrypt
Certbot получает сертификат и сам добавляет блок ssl в конфигурацию. Для DNS-имени, указывающего на сервер, процесс занимает минуту.
sudo apt install certbot python3-certbot-nginx
# получить сертификат и настроить Nginx автоматически
sudo certbot --nginx -d app.example.com
# проверить
sudo certbot certificates
# тест обновления
sudo certbot renew --dry-run
Флаг --nginx требует, чтобы сервер уже отвечал на домен по HTTP. Если порт 80 закрыт файрволом, откройте его до запуска.
Автообновление сертификатов
Сертификат Let’s Encrypt живёт 90 дней. Обновление выполняет тайм-сервис, но проверяйте его: просроченный сертификат — самая распространённая причина недоступности сайта.
# тайм-сервис и его расписание
systemctl list-timers | grep -i certbot
journalctl -u certbot -n 50 --no-pager
# ручной запуск с проверкой
sudo certbot renew --dry-run 2>&1 | tail -20
Добавьте мониторинг срока действия: openssl s_client покажет, сколько дней осталось.
# дата окончания сертификата
echo | openssl s_client -servername app.example.com -connect app.example.com:443 2>/dev/null | openssl x509 -noout -dates
Перенаправление на HTTPS
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
# после certbot этот блок обычно добавляется автоматически
Логи и диагностика
# доступа и ошибок
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
# коды ответов за час
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# проверить прокси изнутри
curl -I http://127.0.0.1:8080
curl -I https://app.example.com
Коды 502/504 почти всегда означают, что приложение не отвечает или тайм-аут слишком мал. Проверьте внутренний порт до правки Nginx.
Типичные проблемы
- 502 Bad Gateway — приложение не запущено или слушает другой адрес.
- Петля редиректов — дважды включено перенаправление на HTTPS.
- Обрыв WebSocket — не переданы заголовки Upgrade.
- Неверный IP у приложения — не переданы X-Forwarded-* заголовки.
- Слишком большой запрос — не увеличен
client_max_body_size.
# лимит загрузки файлов (по умолчанию 1 МБ)
# client_max_body_size 20m;
sudo nginx -t && sudo systemctl reload nginx
Кэширование ответов
Для статичного и малодинамичного контента кэш в Nginx снимает нагрузку с приложения. Главное — грамотно разделять, что можно кэшировать, а что нет.
# в server-блоке
# proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=appcache:10m max_size=1g inactive=60m;
# location / { proxy_cache appcache; proxy_cache_valid 200 10m; }
sudo mkdir -p /var/cache/nginx && sudo chown www-data /var/cache/nginx
sudo nginx -t && sudo systemctl reload nginx
# убедиться, что кэш задействован
curl -I https://app.example.com/page | grep -iE "x-cache|age"
Не кэшируйте страницы с авторизацией и персональными данными: ключом по умолчанию является URL, и пользователи увидят чужой контент.
Ограничение скорости запросов
Модуль limit_req защищает приложение от перебора паролей и лавинных запросов. Ставьте лимиты на формы входа и тяжёлые эндпоинты.
# limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# location /login { limit_req zone=login burst=3 nodelay; }
sudo nginx -t && sudo systemctl reload nginx
# проверить, как срабатывает
sudo tail -f /var/log/nginx/error.log | grep -i "limiting"
Следите за логом после включения: если легитимные пользователи получают 503, увеличьте burst, а не отключайте ограничение полностью.
Итог
Reverse proxy на Nginx — это proxy_pass с корректными заголовками, раздача статики, HTTPS через certbot и мониторинг автообновления сертификатов. Проверяйте конфигурацию через nginx -t перед каждой перезагрузкой, а ошибки 502/504 диагностируйте изнутри — сначала приложение, потом Nginx.