Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Let's Encrypt: сертификаты и автопродление

TLS-сертификаты Let's Encrypt: выпуск, автопродление и грабли продакшна

Практика HTTPS на своём сервере: как работает ACME, certbot против acme.sh, webroot и DNS-проверки, продление без даунтайма, мониторинг истечения, wildcard — рабочий чек-лист.

Прямой ответ

Let's Encrypt выдаёт бесплатные доверенные сертификаты через протокол ACME: автоматическая проверка владения доменом → выпуск → продление каждые 60–90 дней ботом. Рабочий сетап на сервере: certbot (или acme.sh) с проверкой webroot (бот кладёт файл в /.well-known/acme-challenge/, nginx отдаёт его без перезапусков) или DNS-01 (TXT-запись через API DNS-провайдера — единственный способ для wildcard и серверов без публичного HTTP), системный таймер продления (certbot renew дважды в день, сертификат обновляется за 30 дней до истечения) и reload nginx после обновления. Грабли, на которые наступают все: автопродление настроено, но nginx не перечитал сертификат (деплой-хук обязателен), rate limits Let's Encrypt (лимит дубликатов в неделю — «переиграть выпуск» десять раз не выйдет), и «сертификат истёк ночью в субботу» — потому что продление молча ломалось месяц без алерта. Мониторинг истечения — обязательная часть сетапа, а не опция.

Как работает ACME: три типа проверок

Процесс: клиент (certbot) генерирует ключевую пару, CA проверяет контроль над доменом (challenge), выпускает сертификат на 90 дней, привязанный к домену (не к серверу). HTTP-01: файл по <token> — самый простой; требует доступности домена по HTTP на 80 порту (отсюда «порт 80 нельзя закрывать совсем» — редирект на HTTPS обязателен, но location challenge'а отдаётся до редиректа). DNS-01: TXT-запись _acme-challenge.домен через API провайдера — работает без публичного веб-сервера (внутренние сервисы за VPN) и единственный вариант для wildcard (*.домен); цена — API-ключ DNS-провайдера (секрет, хранится по правилам). TLS-ALPN-01 — нишевый (порт 443 без HTTP). Практический выбор: обычный сайт — HTTP-01/webroot; wildcard или закрытый сервер — DNS-01. Короткий срок жизни сертификата — не баг, а дизайн: компрометация ключа ограничена 90 днями, а автоматизация делает продление незаметным.

Certbot на сервере: полная настройка с nginx

Установка (пакет дистрибутива — свежее snap/pip-версий в репозиториях достаточно). Выпуск: certbot certonly --webroot -w /var/www/certbot -d example.com -d www.example.com (certonly — только сертификат, nginx-конфиг правим сами; в nginx-конфиге — location /.well-known/acme-challenge/ { root /var/www/certbot; } и общий редирект на HTTPS; полный набор прокси-конфига — в статье про nginx). В server-блок — пути ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem и ключ, ssl_protocols TLSv1.2 TLSv1.3. Продление: systemctl list-timers | grep certbot — таймер из пакета уже стоит; критичное дополнение — deploy-hook: certbot renew --deploy-hook "systemctl reload nginx" (без reload nginx держит в памяти старый сертификат до рестарта — «продлилось, но браузеры видят истёкший» — классика). Проверка всего сценария: certbot renew --dry-run (прогон против staging-CA, не тратит rate limits) — раз в квартал или в CI-проверке конфига.

Альтернативы: acme.sh, Caddy, облачные LB

acme.sh — шелл-клиент без Python-зависимостей, агрессивнее по совместимости (десятки DNS-провайдеров из коробки) — частый выбор для DNS-01 и минималистичных серверов. Caddy — веб-сервер с автоматическим TLS «из коробки» (выпуск и продление встроены, конфиг — три строки; локальная разработка с локальным CA — в статье про Caddy/mkcert) — для небольших сервисов убирает и certbot, и половину nginx-конфига. Облачные балансировщики/CDN (Cloudflare, ALB) — сертификат живёт на границе облака, продление — забота провайдера; на origin трафик идёт по внутреннему сертификату или снова Let's Encrypt. Выбор — по архитектуре: «свой nginx на VPS» — certbot/acme.sh; «всё за облачным LB» — сертификаты облака; «маленький сервис без требований к nginx» — Caddy.

Мониторинг истечения и типовые сбои

Алерт на истечение — обязательный слой: probe (check_ssl_cert/blackbox_exporter) проверяет фактический сертификат на 443 и алертит при < 14 дней (Grafana-алерты); внешний сервис-мониторинг (UptimeRobot и подобные) дублирует из другой сети — «сервер лёг вместе с мониторингом» не должен означать «никто не узнал». Типовые сбои продления и их признаки: webroot-путь перестал отдаваться (конфиг nginx переехал — dry-run ловит), DNS-01 с устаревшим API-ключом (провайдер сменил API), rate limit после экспериментов (лечение — staging-CA для тестов, лимит сбрасывается через неделю), смена IP без обновления DNS (challenge уходит на старую машину). Привычка: после любого изменения веб-конфига — certbot renew --dry-run; пятиминутная проверка, которая предотвращает субботний инцидент.

Практический сценарий: HTTPS для нового сервиса за полчаса

Домен куплен, A-запись указывает на VPS, nginx поднят. Последовательность: (1) в nginx — server-блок на 80 с challenge-location и редиректом всего остального; reload. (2) certbot certonly --webroot ... — сертификат выпущен за двадцать секунд; (3) server-блок 443: fullchain+key, TLSv1.2/1.3, http2, HSTS добавляем после проверки, что HTTPS работает стабильно (max-age наращиваем постепенно: 300 → день → год; HSTS на полчаса неработающего HTTPS запоминается браузерами надолго); (4) deploy-hook reload в конфиг продления + renew --dry-run; (5) внешний SSL-мониторинг с алертом < 14 дней; (6) запись в runbook («истёк сертификат» — команды проверки и ручного продления; runbook-дисциплина). Через 60 дней продление происходит само и незаметно — именно так и должно быть: TLS в 2026 — решённая инфраструктурная задача, требующая настройки один раз и мониторинга навсегда.

FAQ

Wildcard-сертификат: когда нужен и как получить? Для сервисов с произвольными поддоменами (*.dev.example.com — стенды, тенанты). Только через DNS-01 (API DNS-провайдера); покрывает один уровень поддоменов (*.example.com не покрывает a.b.example.com). Для двух-трёх поддоменов проще выпустить отдельные SAN-сертификаты через HTTP-01.

Почему rate limits — реальная проблема? Let's Encrypt ограничивает: ~50 сертификатов на домен в неделю, 5 дубликатов, 5 провалов проверки в час. Скрипт «перевыпустить на каждый деплой» упирается в лимит за день — и настоящий перевыпуск (истёк/компрометация) становится невозможен до сброса. Отсюда: продление по таймеру, тесты — только staging.

Можно ли один сертификат на несколько серверов? Да: сертификат не привязан к машине — копируйте fullchain+key на второй сервер (или терминируйте TLS на одном балансировщике). Ключ при этом становится секретом, который нужно ротировать и защищать на обеих машинах — иногда проще выпустить отдельный сертификат на каждый.

Что делать при компрометации приватного ключа? Немедленный перевыпуск (certbot certonly --force-renewal — вне лимита дубликатов при revocation), развёртывание нового, отзыв старого через ACME (certbot revoke) — браузеры с CRL/OCSP-stapling узнают; и постмортем: как ключ утечёк (бэкап в открытом виде? лог?) — ротация без устранения канала утечки бессмысленна.

Источники: letsencrypt.org (how it works), документация certbot, acme.sh — ссылки в шапке.