Полное руководство по SSL/TLS и HTTPS в Nginx: от сертификатов до HSTS и reverse proxy | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Полное руководство по SSL/TLS и HTTPS в Nginx: от сертификатов до HSTS и reverse proxy

05 апреля 2026 10 мин. чтения

Настройка безопасного HTTPS в Nginx — обязательный шаг для любого публичного сервиса. Это руководство предоставляет готовые, проверенные на практике конфигурации для всех ключевых сценариев: от быстрого получения SSL-сертификатов (самоподписанных и бесплатных от Let's Encrypt) до автоматизации их обновления, настройки современных параметров безопасности (TLS 1.3, HSTS) и корректной работы в архитектуре с reverse proxy и Docker. Вы получите конкретные команды и блоки конфигурации для немедленного применения, которые закрывают основные риски и вопросы системных администраторов и DevOps инженеров.

Инструкция построена пошагово и ориентирована на решение конкретных задач: как быстро запустить HTTPS для тестов, как обеспечить бесплатный и доверенный SSL для production-сайтов, как настроить автоматическое обновление сертификатов, чтобы избежать сбоев, и как правильно проксировать защищённый трафик на внутренние приложения, включая контейнеры Docker. Каждый шаг сопровождается пояснениями и предупреждениями о возможных проблемах.

Базовые сценарии: от самоподписанных сертификатов до Let's Encrypt

Первым шагом для включения HTTPS является получение и установка SSL/TLS сертификата. Выбор метода зависит от среды: самоподписанные сертификаты подходят для локального тестирования или внутренних сервисов, а для публичных сайтов стандартом является бесплатный и доверенный сертификат от Let's Encrypt, выдаваемый через Certbot.

Самоподписанный сертификат: для тестов и внутренних сетей

Самоподписанный сертификат позволяет быстро запустить HTTPS без взаимодействия с внешними сервисами. Он идеально подходит для разработки, тестирования конфигураций или защиты внутренних сервисов в частной сети, где доверие браузера не требуется. Для его генерации используется стандартная утилита openssl.

Генерация ключа и сертификата:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/selfsigned.key \
    -out /etc/nginx/ssl/selfsigned.crt

Эта команда создаёт ключ (selfsigned.key) и сертификат (selfsigned.crt) сроком действия 365 дней. После генерации необходимо настроить блок server в Nginx:

server {
    listen 443 ssl;
    server_name your_domain_or_local_ip;

    ssl_certificate /etc/nginx/ssl/selfsigned.crt;
    ssl_certificate_key /etc/nginx/ssl/selfsigned.key;

    # ... остальная конфигурация (root, index, location)
}

Важно: браузеры и клиенты будут показывать предупреждение о недоверенном сертификате при подключении. Этот метод непригоден для публичных production-сайтов, так как нарушает доверие пользователей и может блокировать интеграции с некоторыми API.

Let's Encrypt и Certbot: бесплатный SSL для production

Для любого публичного сайта рекомендуется использовать доверенные сертификаты. Let's Encrypt предоставляет их бесплатно, а инструмент Certbot автоматизирует получение и установку. Это стандарт де-факто для современного веба.

Пошаговый процесс для системы на базе Ubuntu/Debian:

  1. Установка Certbot (рекомендуется через snap для получения самых актуальных версий):
    sudo snap install --classic certbot
  2. Выполнение команды для получения сертификата и автоматической интеграции с Nginx:
    sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
  3. Certbot проведёт проверку владения доменом (HTTP-01 challenge), получит сертификат и автоматически обновит конфигурацию Nginx, добавив блок для порта 443 с правильными директивными ssl_certificate и ssl_certificate_key.

После успешного выполнения команды Certbot создаст конфигурацию, аналогичную этой:

server {
    listen 443 ssl;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # Директивы, добавленные Certbot для безопасности
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    # ... остальная конфигурация сервера
}

Этот метод является основным для production-сред. Сертификаты Let's Encrypt доверяются всеми основными браузерами и клиентами.

Автоматическое обновление SSL-сертификатов Let's Encrypt

Сертификаты Let's Encrypt имеют срок действия 90 дней. Их ручное обновление создаёт риск сбоя сайта. Автоматизация этого процесса критически важна для стабильной работы.

Самый простой и надежный способ — использование cron. Certbot включает команду renew, которая проверяет срок действия всех установленных сертификатов и обновляет только те, которым осталось менее 30 дней.

Пример записи в crontab для ежедневного проверки и обновления с автоматической перезагрузкой Nginx:

0 12 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

Эта команда запускается ежедневно в 12:00. Опция --quiet подавляет вывод, если обновление не требуется. --post-hook гарантирует, что Nginx перезагрузит конфигурацию только после успешного обновления сертификатов, что безопаснее, чем постоянная перезагрузка.

Для Docker-среды, где Nginx работает в контейнере, стратегия зависит от архитектуры:

  • Монтирование volumes: Путь /etc/letsencrypt на хосте монтируется как volume в контейнер Nginx. Certbot запускается на хосте и обновляет сертификаты в этом volume. После обновления требуется перезагрузка контейнера Nginx через docker compose restart nginx или аналогичную команду, которую можно добавить в post-hook.
  • Контейнер с Certbot: Можно запустить отдельный контейнер с Certbot, который будет обновлять сертификаты и сигнализировать основному контейнеру Nginx через shared volume.

Для диагностики можно использовать скрипт проверки срока действия:

openssl x509 -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem -noout -dates

Частые проблемы при автоматическом обновлении: недоступность домена для проверки (HTTP-01 challenge требует, чтобы домен был доступен по HTTP на порту 80), недостаточные права на файлы в /etc/letsencrypt, или конфликты с другими процессами, использующими порт 80. Решение — обеспечить временную доступность порта 80 во время выполнения cron-задачи или использовать альтернативные методы проверки (DNS-01), если порт 80 занят.

Безопасная конфигурация TLS, шифров и заголовка HSTS

После получения сертификата необходимо настроить параметры безопасности TLS, чтобы защитить соединение от известных атак и обеспечить соответствие современным стандартам. Это включает выбор версий протокола, алгоритмов шифрования и настройку заголовка HSTS.

Настройка HSTS: защита от downgrade-атак

HTTP Strict Transport Security (HSTS) — это механизм, который принудительно указывает браузерам использовать только HTTPS для соединения с вашим сайтом, предотвращая атаки типа SSL stripping, где злоумышленник пытается перевести соединение на незащищённый HTTP.

Для включения HSTS в Nginx используется директива add_header в блоке server для порта 443:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Параметр max-age=31536000 указывает браузерам хранить эту политику в течение одного года (в секундах). includeSubDomains распространяет политику на все поддомены сайта. Использование always гарантирует, что заголовок будет отправлен даже для ответов с ошибками.

Важное предупреждение: Включение includeSubDomains требует, что все поддомены также поддерживают HTTPS. Если какой-то поддомен не готов, это приведёт к невозможности подключения к ним. Параметр preload используется для включения сайта в предварительно загружаемый список HSTS браузеров (например, Chrome). Его добавление требует отдельной регистрации на сайте hstspreload.org и является окончательным действием — удалить сайт из списка позже будет очень сложно.

Выбор алгоритмов шифрования и версий TLS

Настройка протоколов и шифров должна балансировать безопасность и совместимость с клиентами. Рекомендуется полностью отключить устаревшие и небезопасные протоколы.

Базовые безопасные настройки для Nginx:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

TLS 1.3 обеспечивает значительные улучшения в безопасности и скорости по сравнению с TLS 1.2 благодаря сокращённому «рукопожатию». Если все клиенты поддерживают TLS 1.3, можно ограничиться только им (ssl_protocols TLSv1.3). Однако для обеспечения совместимости с более старыми системами часто включают и TLS 1.2.

Также важно отключить сжатие TLS для защиты от атак типа CRIME:

ssl_compression off;

Для проверки корректности цепочки сертификатов (что предотвращает ошибку «NET::ERR_CERT_AUTHORITY_INVALID») убедитесь, что в конфигурации используется файл fullchain.pem от Let's Encrypt, который включает как ваш сертификат, так и промежуточные сертификаты (chain). Директива ssl_trusted_certificate обычно не требуется для базовой настройки.

Тестирование конфигурации можно провести с помощью онлайн-сервисов, таких как SSL Labs Server Test, или локальной утилиты testssl.sh.

Настройка Nginx как reverse proxy с SSL-терминацией

В типичной production-архитектуре Nginx выступает как reverse proxy, принимая HTTPS-трафик от клиентов, терминализируя SSL/TLS и проксируя незашифрованные HTTP-запросы на внутренние сервисы (бэкенд-приложения, контейнеры Docker). Это централизует управление сертификатами и повышает безопасность.

Конфигурация для Docker-контейнеров и Docker Compose

Для среды Docker, где приложение работает в контейнере, Nginx также может быть запущен в контейнере. Ключевой момент — обеспечить связь между контейнерами через Docker network и правильно указать адрес бэкенда в директиве proxy_pass.

Пример docker-compose.yml для простого стека:

version: '3.8'
services:
  nginx:
    image: nginx:alpine
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
      - ./html:/usr/share/nginx/html:ro
    networks:
      - app-network

  app:
    image: your-backend-image:latest
    container_name: backend-app
    expose:
      - "3000"
    networks:
      - app-network

networks:
  app-network:

Конфигурация Nginx (nginx.conf) для проксирования на приложение:

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # ... безопасные настройки TLS и HSTS из предыдущих разделов

    location / {
        proxy_pass http://app: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;
    }
}

В директиве proxy_pass используется имя сервиса app и его внутренний порт 3000, указанный в expose. Docker автоматически разрешает это имя внутри общей сети app-network. Сертификаты монтируются из хоста в контейнер Nginx через volume ./ssl.

Передача правильных заголовков и решение проблем WebSocket

При проксировании важно передавать бэкенду правильные заголовки, чтобы приложение могло идентифицировать клиента и понимать исходный протокол. Стандартный набор заголовков включает:

  • Host: оригинальное имя хоста из запроса клиента.
  • X-Rеal-IP: реальный IP-адрес клиента (вместо IP-адреса Nginx).
  • X-Forwarded-For: список всех прокси, через которые прошёл запрос.
  • X-Forwarded-Proto: оригинальный протокол (в данном случае «https»).

Для поддержки WebSocket-соединений (например, для live-updates, чатов) требуется специальная конфигурация, поскольку WebSocket использует upgrade механизм HTTP:

location /ws/ {
    proxy_pass http://app:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

Директивы proxy_http_version 1.1, Upgrade и Connection "upgrade" необходимы для корректного установления WebSocket соединения. Проблемы с WebSocket часто проявляются как ошибки «400 Bad Request» или невозможность установить соединение. Диагностику следует проводить через проверку логов Nginx (error.log) и логов бэкенд-приложения.

Для комплексного развертывания на VDS с Ubuntu можно объединить все шаги: установка Docker и Docker Compose, создание сети, подготовка конфигурации Nginx с SSL и проксированием, и запуск стека. Это соответствует финальному деплою, упомянутому в контексте курсов.

Миграция с HTTP на HTTPS и устранение ошибок

Перевод существующего работающего сайта с HTTP на HTTPS требует планомерного подхода, чтобы избежать простоев и проблем с SEO. Пошаговый план миграции:

  1. Получение и локальное тестирование SSL-сертификата: Получите сертификат через Certbot и создайте тестовый блок server для порта 443 в отдельном файле или временной конфигурации. Проверьте доступность сайта по HTTPS, используя curl -I https://yourdomain.com или браузер.
  2. Настройка 301 редиректа с HTTP на HTTPS: Добавьте или измените блок server для порта 80, чтобы он перенаправлял все запросы на HTTPS.
    server {
        listen 80;
        server_name yourdomain.com www.yourdomain.com;
        return 301 https://$server_name$request_uri;
    }
  3. Проверка и исправление смешанного контента (Mixed Content): После перехода убедитесь, что все ресурсы (CSS, JS, изображения) также загружаются по HTTPS. Проблема смешанного контента возникает, когда страница, загруженная по HTTPS, включает ресурсы, запрашиваемые по HTTP. Это блокируется браузерами и приводит к ошибкам. Используйте инструменты разработчика браузера (Console) для поиска таких ошибок и исправьте внутренние ссылки в коде.
  4. Обновление sitemap.xml и robots.txt: Измените URL в файле sitemap.xml на HTTPS-версии. В robots.txt можно указать новый адрес главного зеркала сайта.
  5. Настройка в Search Console: Добавьте новую HTTPS-версию сайта в Google Search Console (или аналогичный инструмент) и используйте функцию «Изменение адреса» для корректной обработки миграции поисковыми системами.

Распространенные ошибки SSL/TLS и их решения:

Ошибка Причина Решение
NET::ERR_CERT_AUTHORITY_INVALID Неполная цепочка сертификатов (отсутствует промежуточный CA). Убедитесь, что в ssl_certificate указан файл fullchain.pem от Let's Encrypt, а не cert.pem.
SSL_ERROR_RX_RECORD_TOO_LONG Клиент пытается установить TLS соединение на порту, который слушает HTTP (например, порт 80). Проверьте, что блок server для порта 443 включает директиву ssl (listen 443 ssl;).
ERR_SSL_VERSION_OR_CIPHER_MISMATCH Клиент и сервер не могут согласовать версию TLS или алгоритмы шифрования. Убедитесь, что ssl_protocols включает TLSv1.2 или TLSv1.3, и проверьте список ssl_ciphers. Используйте более широкий список шифров для совместимости.
Сайт недоступен после перезагрузки Nginx Конфигурация содержит синтаксические ошибки или неправильные пути к файлам сертификатов. Проверьте конфигурацию командой nginx -t. Проверьте права на файлы сертификатов и их наличие.

Для глубокой диагностики используйте команду openssl s_client -connect yourdomain.com:443 для проверки установления TLS соединения и просмотра деталей сертификата.

Эта инструкция охватывает полный цикл настройки безопасного HTTPS в Nginx, от базовых шагов до продвинутых настроек для production-сред. Для дальнейшего углубления в тему управления контейнеризованными приложениями и их безопасностью рекомендуем ознакомиться с руководствами по продвинутому Docker и Docker в production. Для оптимизации производительности веб-приложений, которые теперь работают за защищённым Nginx, полезным будет гайд по диагностике и оптимизации производительности.

Поделиться:
Сохранить гайд? В закладки браузера