Let's Encrypt не продлился: чек-лист починки
Почему Let's Encrypt не продлился: как это устроено
Let's Encrypt выдаёт сертификаты бесплатно, но с коротким сроком действия — 90 дней. Это осознанное решение: чем короче жизнь сертификата, тем меньше окно для злоупотреблений, если ключ скомпрометирован. Плата за короткий срок — необходимость регулярно продлевать сертификат. Большинство администраторов автоматизируют это через certbot и таймер systemd, поэтому в норме продление происходит незаметно за несколько недель до истечения.
Проблема возникает, когда автоматика ломается, а узнаёте вы об этом в самый неподходящий момент: браузер показывает «срок действия сертификата истёк», посетители видят предупреждение, а клиенты пишут, что «сайт лежит». Симптом «Let's Encrypt не продлился» почти всегда означает одно: автоматический запуск certbot renew перестал выполняться или стал падать с ошибкой, и это тихо копилось неделями.
Разберём, как устроено продление, какие причины ломают его чаще всего и как восстановить работоспособность — по шагам, с командами и пояснением вывода.
Как продление работает изнутри
Стандартная схема на сервере с nginx или Apache выглядит так:
- certbot устанавливается вместе с плагином (
python3-certbot-nginxилиpython3-certbot-apache). - При первой выдаче сертификата создаётся конфигурация в
/etc/letsencrypt/renewal/. - Таймер systemd (
certbot.timer) по расписанию вызываетcertbot renew. - certbot проверяет, каким сертификатам до истечения осталось меньше 30 дней, и продлевает их.
- После продления certbot выполняет хуки — перезагрузку веб-сервера, чтобы тот подхватил новые файлы.
Ключевой файл — /etc/letsencrypt/renewal/ваш-домен.conf. В нём записаны параметры продления: как проверять владение доменом, какие хуки запускать после выдачи.
cat /etc/letsencrypt/renewal/example.com.conf
В выводе важны две директивы:
[renewalparams]
authenticator = webroot
webroot_path = /var/www/html,
account = abc123...
authenticator— способ подтверждения владения доменом (webroot,nginx,apache,standalone,dns-*).webroot_path— каталог, куда certbot кладёт проверочный файл для HTTP-01 валидации.
Если здесь указан путь, который больше не существует, или веб-сервер отдаёт не тот каталог, продление падает. Это одна из самых частых причин, почему Let's Encrypt не продлился.
Причины, по которым продление ломается
Причин немного, но каждая встречается регулярно. Удобно держать их в виде таблицы «симптом → причина → решение».
| Симптом | Причина | Решение |
|---|---|---|
certbot renew падает с «no such file or directory» |
Удалён каталог webroot_path или сайт перенесён на другой путь |
Вернуть каталог или обновить webroot_path |
| Ошибка HTTP-01 валидации, «connection refused» | Порт 80 закрыт, сервер не отвечает, сайт за редиректом на HTTPS без обработки ACME | Открыть порт 80, исключить ACME-пути из редиректа |
| Ошибка DNS («NXDOMAIN», «no valid A records») | Домен не резолвится или A/AAAA-запись смотрит на другой сервер | Проверить dig, поправить DNS |
| Таймер не срабатывает | certbot.timer выключен или отсутствует |
Включить и проверить systemctl list-timers |
| Продление проходит, но сайт всё равно с истёкшим сертификатом | Веб-сервер не перезагружен, отдаёт старый сертификат из кеша | Выполнить systemctl reload nginx |
| «too many certificates already issued» | Превышен лимит Let's Encrypt на домен | Дождаться сброса лимита, разобраться с дублями |
| «urn:ietf:params:acme:error:rateLimited» | Слишком много неудачных попыток валидации подряд | Подождать час, устранить корневую причину |
Шаг 1. Проверить, что с сертификатом и таймером
Первое, что стоит сделать, — посмотреть фактическое состояние сертификатов на сервере. certbot умеет показывать это одной командой:
certbot certificates
Вывод для каждого сертификата:
Found the following certs:
Certificate Name: example.com
Serial Number: 4f2a...
Key Type: RSA
Domains: example.com www.example.com
Expiry Date: 2024-05-01 12:00:00+00:00 (INVALID: EXPIRED)
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
Смотрим на строку Expiry Date. Если там EXPIRED — продление действительно не случилось. Если до истечения ещё больше 30 дней, а сайт всё равно ругается, проблема не в certbot, а в том, что веб-сервер отдаёт старый файл.
Второе — проверяем, живой ли таймер автопродления:
systemctl list-timers certbot.timer
systemctl status certbot.timer
Если таймера в списке нет или статус inactive, автоматическое продление не выполняется вообще. Включить его можно так:
systemctl enable --now certbot.timer
После этого certbot renew будет запускаться сам по расписанию (обычно дважды в сутки), а реальное продление сертификатов произойдёт, когда до истечения останется меньше 30 дней.

Шаг 2. Прогнать сухую проверку certbot renew --dry-run
Прежде чем трогать что-то по-настоящему, безопасно прогнать весь цикл продления в тестовом режиме. Для этого есть флаг --dry-run:
certbot renew --dry-run
Команда проходит все те же этапы, что и реальное продление — обращается к серверу Let's Encrypt (в тестовую среду staging), выполняет валидацию домена, перевыпускает сертификат, — но полученный сертификат не сохраняется как рабочий, а используется только для проверки. Успешный вывод:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating renewal of an existing certificate for example.com and www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
Ключевая строка — Congratulations, all simulated renewals succeeded. Если она появилась, конфигурация валидна и проблема была либо в отключённом таймере, либо в том, что реальное продление не запускалось.
Если же проверка падает, читаем конкретную ошибку. Типичные случаи:
Failed authorization procedure. example.com (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://example.com/.well-known/acme-challenge/xxx: Connection refused
Здесь сервер Let's Encrypt не смог подключиться к сайту по порту 80. Причина — порт закрыт фаерволом, сайт переехал, или nginx слушает только 443. Проверить доступность порта можно снаружи и изнутри:
curl -I http://example.com/.well-known/acme-challenge/test
Если запрос не доходит, надо открыть порт 80 и убедиться, что веб-сервер на него отвечает. Важный нюанс: редирект с HTTP на HTTPS не должен перехватывать ACME-пути, иначе certbot при authenticator = webroot не сможет добраться до проверочного файла.
Шаг 3. Исправить причину и запустить реальное продление
Когда --dry-run прошёл успешно, можно запускать настоящее продление:
certbot renew
Успешный вывод сообщит, какие сертификаты обновлены, а какие ещё не требуют этого:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal; no action taken.
Или, если сертификат действительно подошёл к концу:
Renewing an existing certificate for example.com and www.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)
После успешного продления новые файлы лежат в /etc/letsencrypt/live/example.com/, но nginx или Apache всё ещё могут держать в памяти старый сертификат. Чтобы сервер подхватил обновлённые файлы, его нужно перезагрузить:
systemctl reload nginx
Для Apache команда аналогична:
systemctl reload apache2
reload мягче, чем restart: сервер перечитывает конфигурацию и файлы сертификатов, не обрывая текущие соединения. Именно поэтому в хуках certbot почти всегда используется reload, а не полный перезапуск.
Шаг 4. Настроить автопродление так, чтобы оно не ломалось
После разовой починки стоит устранить корень проблемы, чтобы через 90 дней история не повторилась. Практические меры:
-
Прописать reload-хук. В
/etc/letsencrypt/renewal/example.com.confдобавить директиву, чтобы после каждого продления веб-сервер перезагружался сам:renew_hook = systemctl reload nginxТогда не будет ситуации «сертификат обновился, а сайт отдаёт старый».
-
Убедиться, что порт 80 открыт и отдаёт ACME-пути. Даже если весь сайт редиректит на HTTPS, для webroot-валидации нужен HTTP.
-
Проверить корректность DNS. Если домен смотрит на другой сервер или записи A/AAAA отсутствуют, валидация провалится. Проверить резолвинг можно так:
dig example.com A +shortВывод — список IP-адресов, на которые указывает домен. Если он пуст или указывает на другой хост, проблему надо искать в DNS, а не в certbot.
-
Следить за сроком заранее. Не дожидаться, пока браузеры начнут показывать ошибку. Регулярная проверка срока действия сертификата — это то, что умеет делать инструмент проверки срока SSL-сертификата у UptimeChecker: он показывает, сколько дней осталось до истечения, и позволяет настроить напоминание до того, как сертификат протухнет.
Частные случаи: webroot, standalone и смена плагина
Отдельный класс проблем возникает, когда способ валидации в конфигурации больше не соответствует реальности. Классический сценарий: сайт изначально выдавался с authenticator = nginx, затем администратор вручную перенёс сертификат на другой сервер или пересобрал конфигурацию nginx, и теперь плагин не может выполнить валидацию привычным способом.
Если сайт переехал и проверочный каталог изменился, обновить путь можно вручную в /etc/letsencrypt/renewal/example.com.conf (директива webroot_path) или перевыпустить сертификат с новым способом:
certbot certonly --webroot -w /новый/путь -d example.com -d www.example.com
Флаг --webroot явно указывает плагину класть проверочные файлы в заданный каталог, а -w задаёт сам путь. После перевыпуска с новым путём автопродление будет использовать уже корректные параметры.
Ещё один нюанс — лимиты Let's Encrypt. Если в конфигурации накопилось много дублей (несколько записей на один домен с разными путями), можно упереться в лимит на число сертификатов и получить too many certificates already issued. В таком случае стоит навести порядок: удалить неиспользуемые записи из /etc/letsencrypt/renewal/, оставив одну актуальную на домен, и дождаться сброса лимита.
Связка с мониторингом: как не пропустить момент
Отдельная ручная проверка раз в 90 дней не спасёт — человеческий фактор почти гарантированно приведёт к пропуску. Рабочий подход — автоматическая проверка, которая оповестит заранее, а не постфактум.
Схема простая:
- Внешний мониторинг регулярно проверяет срок действия сертификата сайта.
- Если до истечения осталось меньше порога (например, 14 или 7 дней), приходит уведомление.
- Администратор успевает продлить сертификат, пока посетители ничего не заметили.
Для самопроверки прямо сейчас удобно использовать проверку SSL-сертификата: она покажет, действителен ли сертификат, до какой даты и корректно ли собрана цепочка. А если вы уже столкнулись с истёкшим сертификатом на проде, начните со статьи про истёкший SSL-сертификат — там разобраны первые действия в аварийной ситуации.
Чек-лист починки: короткая версия
Соберём всё в один список, по которому удобно идти при инциденте «Let's Encrypt не продлился»:
- Посмотреть состояние:
certbot certificates— истёк ли сертификат на самом деле. - Проверить таймер:
systemctl list-timers certbot.timer— включено ли автопродление. - Прогнать тест:
certbot renew --dry-run— валидна ли конфигурация, какая именно ошибка. - Устранить причину: порт 80, DNS, webroot-путь, лимиты Let's Encrypt.
- Запустить реальное продление:
certbot renew. - Перезагрузить веб-сервер:
systemctl reload nginx. - Проверить результат снаружи:
curl -Iv https://example.comи срок действия через сервис проверки SSL. - Закрепить: reload-хук, открытый порт 80, автоматический мониторинг срока.


Если продление настроено правильно и сервер перезагружается после каждой выдачи, проблема «Let's Encrypt не продлился» перестанет быть регулярной. Останется только одна зона риска — сам факт истечения сертификата, и её надёжно закрывает внешняя проверка срока действия. Проверьте свой сайт в инструменте срока SSL-сертификата, чтобы убедиться, что до ближайшего истечения у вас есть запас времени.