Редирект с HTTP на HTTPS в Nginx: живой пример
Показываем на конфигурации Nginx 1.24+, как перенаправить HTTP на HTTPS без циклов, потери URI и поломки ACME-проверки. Заодно разберём HSTS, прокси и типичные ошибки.

Редирект с HTTP на HTTPS в Nginx занимает несколько строк, но одна неверная директива может вызвать бесконечный цикл, потерять параметры запроса или сломать автоматическое продление сертификата. Ниже — рабочая схема для сайта shop.example.com: HTTP принимает запрос, отвечает кодом 301, а HTTPS сохраняет путь и query-параметры. Примеры рассчитаны на Nginx 1.24 и новее.
Что должно быть готово до настройки
Редирект не заменяет TLS-сертификат. Сначала HTTPS-виртуальный хост должен открываться без предупреждения браузера, и только после этого имеет смысл перенаправлять HTTP-трафик.
- сервер с установленным Nginx 1.24+;
- домен
shop.example.com, направленный DNS-записью на этот сервер; - действующий сертификат и закрытый ключ;
- доступ к конфигурации Nginx и возможность выполнить проверку конфигурации;
- открытые TCP-порты 80 и 443.
В примере сертификат лежит в /etc/letsencrypt/live/shop.example.com/. Если у вас другой путь, замените его на фактический. Закрытый ключ нельзя добавлять в репозиторий, отправлять в чат или показывать в диагностике.
HTTPS-редирект — это не настройка «поставить галочку», а цепочка из DNS, сертификата, двух виртуальных хостов и проверки реального ответа сервера.
Два подхода и цена каждого
Перенаправление можно сделать на уровне Nginx или приложения. Для обычного сайта первый вариант почти всегда проще: запрос уходит в редирект до загрузки PHP, Python или Node.js. Приложение стоит использовать только там, где маршрутизация уже централизована и Nginx не является точкой входа.
| Подход | Что происходит | Цена и риск |
|---|---|---|
| Nginx | HTTP-виртуальный хост сразу отвечает 301 | Минимальная нагрузка, но нужно отдельно настроить сертификат и DNS |
| Приложение | Запрос проходит до веб-фреймворка и только потом получает редирект | Проще менять правила в коде, но растёт задержка и риск цикла за прокси |
| Балансировщик или CDN | Редирект выполняется до вашего сервера | Меньше запросов на origin, но правило зависит от конкретного провайдера |
Дальше рассматриваем именно Nginx. Редирект в приложении и настройка CDN — отдельные задачи: смешивать их в одном правиле не стоит.
Конфигурация Nginx для HTTP и HTTPS
У сайта должны быть два блока server. Первый слушает порт 80 и ничего не проксирует: он только возвращает постоянный редирект. Второй слушает 443, подключает сертификат и обслуживает сайт.
Готовый пример
Фрагмент ниже рассчитан на Nginx 1.24+ и приложение, которое работает на локальном порту 127.0.0.1:3000. Если у вас статический сайт, замените блок location / на root и настройку файлов, а прокси-директивы удалите.
server {
listen 80;
listen [::]:80;
server_name shop.example.com;
# Оставляем путь и query-параметры при перенаправлении
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name shop.example.com;
ssl_certificate /etc/letsencrypt/live/shop.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/shop.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
Директива $request_uri сохраняет исходный путь вместе с параметрами запроса. Например, http://shop.example.com/catalog?page=2 превратится в https://shop.example.com/catalog?page=2. В отличие от $request_uri, переменная $uri не содержит query-параметры.
Как применить изменения без остановки Nginx
Не перезагружайте конфигурацию вслепую. Сначала проверьте синтаксис, затем попросите Nginx перечитать файл.
- Сохраните конфигурацию. Положите блоки в активный файл виртуального хоста или в тот файл, который подключается из основного
nginx.conf. Проверка: вы можете найти в нём оба значенияlisten— 80 и 443. - Проверьте синтаксис. Выполните
sudo nginx -t. Проверка: в выводе должны появиться сообщенияsyntax is okиtest is successful. - Перечитайте конфигурацию. Выполните
sudo systemctl reload nginx. Проверка: команда завершается без ошибки, а процесс Nginx продолжает работать. - Проверьте HTTP. Выполните
curl -I 'http://shop.example.com/catalog?page=2'. Проверка: ответ содержит301 Moved Permanentlyи заголовокLocation: https://shop.example.com/catalog?page=2. - Проверьте HTTPS. Выполните
curl -I 'https://shop.example.com/catalog?page=2'. Проверка: сервер отвечает уже содержимым сайта, а не новым перенаправлением на тот же адрес.
Если приложение само возвращает редирект, проверьте цепочку командой curl -IL 'http://shop.example.com/catalog?page=2'. Ключ -L покажет все переходы, а не только первый ответ.
Что ломается чаще всего
Цикл редиректов за обратным прокси
Схема выглядит так: CDN или балансировщик принимает HTTPS, а до Nginx подключается по HTTP. Приложение видит внутренний HTTP и снова отправляет клиента на HTTPS. В результате браузер сообщает о слишком большом числе перенаправлений.
В конфигурации выше заголовок X-Forwarded-Proto передаётся приложению только как фактическая схема соединения с Nginx. Если TLS завершается на внешнем прокси, нужно сверить документацию этого прокси и настройки доверия к заголовку. Не заставляйте приложение безусловно редиректить любой запрос, если оно не умеет отличать внешний HTTPS от внутреннего HTTP.
В редиректе пропали параметры
Такое происходит, когда вместо $request_uri используют только $uri. Ссылка на страницу останется рабочей, но фильтр, UTM-метки или параметр пагинации исчезнут. Для обычного перенаправления всего домена используйте return 301 https://$host$request_uri;.
Редирект ломает выпуск или продление сертификата
Центр сертификации может проверять специальный путь /.well-known/acme-challenge/. Если запрос уходит в приложение, а приложение отвечает ошибкой, проверка не завершится. Сам по себе HTTP-редирект иногда допустим для ACME-проверки, но это зависит от клиента и способа проверки, поэтому перед продлением смотрите документацию используемого инструмента.
Появился не тот сертификат
Если на одном IP несколько доменов, Nginx выбирает виртуальный хост по имени и параметрам TLS. Проверьте server_name, наличие сертификата для нужного имени и порядок подключённых конфигураций. Команда sudo nginx -T выводит итоговую конфигурацию, которую реально видит Nginx.
Когда добавлять HSTS
HSTS[1] сообщает браузеру, что сайт нужно открывать только по HTTPS. После добавления заголовка браузер может перестать обращаться к HTTP даже тогда, когда вы временно исправляете сервер, поэтому включать его сразу после первого успешного теста рискованно.
Сначала проверьте HTTPS для всех нужных поддоменов, ссылки, изображения, API и административную панель. Затем можно начать с небольшого времени действия заголовка:
add_header Strict-Transport-Security "max-age=300" always;
После проверки увеличивайте срок осознанно. Параметры includeSubDomains и preload добавляйте только если готовы обслуживать по HTTPS каждый соответствующий поддомен. HSTS не исправляет сертификат и не перенаправляет первый запрос пользователя сам по себе — он работает в браузере после получения заголовка.
[1] HSTS — HTTP-заголовок Strict Transport Security, который заставляет браузер обращаться к домену по HTTPS в течение заданного срока.
Что делать дальше
После настройки проверьте не только код ответа, но и содержимое страницы: формы, изображения, шрифты, запросы к API и cookie. В инструментах разработчика браузера откройте вкладку Network и найдите смешанный контент — обращения к HTTP внутри HTTPS-страницы.
В проде полезно наблюдать долю ответов 301, ошибки TLS, коды 495/496, если они используются вашей сборкой Nginx, и дату окончания сертификата. Отдельно поставьте проверку продления: редирект работает только пока сертификат на 443 действителен.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: NGINX: Configuring HTTPS servers, NGINX: Rewrite module documentation
Частые вопросы
Почему нельзя просто оставить HTTP и HTTPS на одном блоке server?
Как сохранить UTM-метки и параметры фильтра при редиректе?
Почему после настройки браузер показывает бесконечный редирект?
Нужно ли ставить 301 или лучше использовать 302?
Сломается ли продление сертификата из-за редиректа с HTTP?
Что делать, если у меня другая версия Nginx?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.