Nginx: не применяет SSL — причины и решение
Выпустили сертификат, прописали его в конфиг, а Nginx не применяет SSL: сайт по-прежнему открывается по HTTP, отдаёт старый сертификат или браузер ругается на несоответствие. Это частая ситуация, и причина почти всегда в одной из нескольких типовых ошибок конфигурации или в том, что новый конфиг не перечитан. Разберём по порядку, как заставить HTTPS заработать.
Содержание
- Первое действие: проверьте конфиг и перезагрузите Nginx
- Причина 1: нет блока listen 443 ssl
- Причина 2: порт 443 закрыт файрволом
- Причина 3: нет редиректа с HTTP на HTTPS
- Причина 4: браузер показывает старый или несовпадающий сертификат
- Как проверить, что HTTPS действительно работает
- Профилактика: чтобы SSL всегда применялся
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Первое действие: проверьте конфиг и перезагрузите Nginx
Самая частая причина — правки внесены, но Nginx работает на старом конфиге, потому что его не перезагрузили. Сначала убедитесь, что конфиг валиден, затем перечитайте его:
nginx -t && systemctl reload nginx
Если nginx -t показывает ошибку в SSL-директивах — например, не находит файл сертификата, — сайт останется без HTTPS, пока вы её не исправите. Если тест успешен, а изменения всё равно не видны, дело почти наверняка было в отсутствии перезагрузки: reload применяет новую конфигурацию. После этого проверьте сайт в браузере в режиме инкогнито, чтобы исключить кэш. Эти два шага — валидация и перезагрузка — решают заметную долю случаев «SSL не применяется» ещё до глубокого разбора.
Причина 1: нет блока listen 443 ssl
Чтобы Nginx обслуживал HTTPS, у сайта должен быть серверный блок, слушающий порт 443 с включённым SSL. Если такого блока нет, сайт физически не отвечает по HTTPS, сколько сертификатов ни прописывай. Минимально нужно:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
Убедитесь, что этот блок есть и server_name в нём точно совпадает с вашим доменом. Частая ошибка — сертификат прописан в блоке для 80-го порта или server_name не тот, и Nginx отдаёт дефолтный сайт вместо нужного. Директивы ssl_certificate (полная цепочка fullchain.pem) и ssl_certificate_key (приватный ключ) обязательны и должны указывать на реально существующие файлы. После правки — снова nginx -t и перезагрузка.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под сайтыПричина 2: порт 443 закрыт файрволом
Даже с идеальным конфигом HTTPS не заработает, если 443-й порт закрыт файрволом или не проброшен. Браузер просто не достучится до сервера по защищённому соединению. Проверьте, что порт открыт и Nginx на нём слушает:
ss -tlnp | grep :443
ufw status
Если ss не показывает Nginx на 443 — вернитесь к конфигу (нет рабочего блока listen 443 ssl). Если Nginx слушает, но извне сайт по HTTPS недоступен — откройте порт в файрволе:
ufw allow 443/tcp
Учтите и облачные файрволы: у некоторых провайдеров есть внешний сетевой экран на уровне панели, который надо настроить отдельно от ufw на самом сервере. Пока 443 закрыт хотя бы на одном уровне, SSL работать не будет, даже если локально всё выглядит правильно.
Причина 3: нет редиректа с HTTP на HTTPS
Иногда HTTPS на самом деле работает, но пользователи всё равно попадают на HTTP, потому что нет редиректа. Сайт по адресу https:// открывается корректно, а по http:// — как обычно, без шифрования. Чтобы весь трафик уходил на защищённую версию, в блоке 80-го порта добавьте перенаправление:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Это отправит любого, кто пришёл по HTTP, на HTTPS. Проверьте, что редирект не зациклился (частая ошибка за внешним балансировщиком или CDN, который сам терминирует SSL, — тогда нужна аккуратная настройка заголовков). После добавления редиректа сайт будет последовательно работать только по HTTPS, что и требуется. Не забудьте перечитать конфиг.
Причина 4: браузер показывает старый или несовпадающий сертификат
Если браузер ругается на несоответствие сертификата или показывает старый, причин несколько. Первая — сертификат выпущен на другое имя: например, только на example.com, а вы открываете www.example.com, которого нет в сертификате. Проверьте, что реально отдаёт сервер:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates
Команда покажет, на какое имя выпущен сертификат и его срок. Если имя не совпадает — перевыпустите сертификат со всеми нужными доменами. Если сертификат старый после обновления — Nginx не перезагрузили после продления (вернитесь к первому шагу). Если срок истёк — продлите сертификат. И помните про кэш браузера: после смены сертификата проверяйте в приватном окне, чтобы не смотреть на устаревшую версию.
Как проверить, что HTTPS действительно работает
После всех правок убедитесь, что сайт корректно отвечает по HTTPS с валидной цепочкой. Быстрая проверка заголовков:
curl -Iv https://example.com 2>&1 | grep -Ei "HTTP/|SSL|subject|issuer"
Ответ HTTP/2 200 и валидные данные сертификата без ошибок проверки означают, что SSL применён правильно. Если curl жалуется на самоподписанный или неполный сертификат, скорее всего вы указали в ssl_certificate только сам сертификат без промежуточной цепочки — используйте именно fullchain.pem, а не cert.pem. Это частая причина, когда «в браузере вроде работает, а клиенты и API ругаются»: не все проверяющие достраивают цепочку сами.
Профилактика: чтобы SSL всегда применялся
Чтобы не возвращаться к этой проблеме, придерживайтесь простого набора правил. Всегда используйте fullchain.pem для ssl_certificate, держите один аккуратный блок listen 443 ssl на сайт с точным server_name, настройте редирект с 80 на 443 и держите 443-й порт открытым на всех уровнях файрвола. После любого выпуска или продления сертификата обязательно перезагружайте Nginx — лучше автоматически, хуком в вашем ACME-клиенте.
Отдельно проследите за автопродлением: сертификаты Let's Encrypt живут 90 дней, и если продление молча перестало работать, однажды сайт встретит посетителей ошибкой. Настройте оповещение об истечении срока и периодически проверяйте, что после продления Nginx подхватывает новый сертификат. Тогда HTTPS будет применяться стабильно и без сюрпризов, а посетители всегда попадут на защищённую версию сайта.
Наконец, если сайт стоит за CDN или внешним балансировщиком, помните, что SSL может терминироваться не на вашем Nginx, а раньше — на стороне CDN. Тогда поведение HTTPS определяется настройками там, а не только конфигом сервера, и часть проблем «сертификат не тот» решается в панели CDN, а не на VPS. Чётко понимайте, где именно завершается шифрование в вашей схеме: это избавляет от долгих поисков не в том месте и от зацикленных редиректов между HTTP и HTTPS, которые возникают, когда обе стороны пытаются перенаправлять трафик друг на друга.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под сайтыОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Почему Nginx не применяет SSL после правки конфига?
Чаще всего конфиг не перезагружен: выполните nginx -t && systemctl reload nginx. Также проверьте, что есть блок listen 443 ssl с верным server_name и существующими файлами сертификата.
Сайт открывается по HTTP, а не по HTTPS — что делать?
Настройте редирект с 80-го порта на HTTPS через return 301 https://$host$request_uri; и убедитесь, что рабочий блок для 443 существует, а порт открыт в файрволе.
Браузер показывает старый сертификат после продления. Почему?
Nginx не перезагрузили после обновления, либо вы смотрите из кэша. Перечитайте конфиг и проверьте сайт в приватном окне; убедитесь, что используется fullchain.pem.
Как оплатить сервер под сайты из России?
В MAATRIX — картой российского банка, через СБП, криптовалютой или токеном MAAT. Сам сертификат Let's Encrypt бесплатен.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.