MAATRIX / Блог / Let's Encrypt: сертификат не обновляется автоматически — причины и решение

Let's Encrypt: сертификат не обновляется автоматически — причины и решение

Let's Encrypt: сертификат не обновляется автоматически — причины и решение

MAATRIX

Сайт вдруг встречает посетителей предупреждением о просроченном сертификате — хотя вы «всё настроили один раз и забыли». Когда Let's Encrypt сертификат не обновляется автоматически, дело почти никогда не в самом Let's Encrypt: ломается механизм автопродления на вашей стороне. Таймер не запущен, hook не перезагрузил веб-сервер, порт 80 закрылся. Разберём, где рвётся цепочка, и починим её так, чтобы забыть о сертификате по-настоящему.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Как устроено автопродление

Сертификаты Let's Encrypt живут 90 дней, и продлевать их положено заранее — обычно за 30 дней до конца. Автоматику обеспечивает не магия, а конкретный планировщик: либо systemd-таймер certbot.timer, либо cron-задание. Он периодически запускает certbot renew, а тот сам проверяет, каким сертификатам пора продлеваться, и продлевает только их.

Отсюда ясно, что «не обновляется» распадается на несколько независимых вопросов: запускается ли планировщик вообще; доходит ли дело до certbot renew; успешно ли проходит валидация при продлении; и подхватывает ли веб-сервер новый сертификат после выпуска. Сбой на любом из этих этапов даёт один и тот же симптом — просроченный сертификат. Поэтому чинить надо по порядку, проверяя каждое звено.

Важно понять и то, почему проблема всплывает так внезапно. Автопродление — тихий фоновый процесс: пока сертификат действует, никто не замечает, что механизм давно сломан. Поломка происходит в момент выпуска или сразу после первичной настройки, а последствия проявляются через два-три месяца, когда старый сертификат истекает. Из-за этой отсрочки причину легко искать не там: вы вспоминаете вчерашние правки, хотя реальный сбой заложен ещё при установке. Поэтому не доверяйте ощущению «оно же работало» — проверяйте цепочку целиком, звено за звеном.

Проверяем, работает ли планировщик

Первым делом убедитесь, что механизм запуска вообще жив. На современных системах это systemd-таймер.

systemctl list-timers | grep certbot
systemctl status certbot.timer

Если таймер inactive или его нет — автопродление просто некому запускать. Включите его:

systemctl enable --now certbot.timer

На системах с cron проверьте задание вместо таймера:

cat /etc/cron.d/certbot
ls -l /etc/cron.d/ | grep certbot

Частая причина, почему таймера нет: certbot ставили не из пакета, а через pip или snap, и юнит не создался. Или систему переустанавливали/мигрировали, а таймер забыли включить. Убедитесь, что планировщик активен — без него всё остальное не имеет значения, продление никогда не запустится само.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS с чистым IP

Тестируем продление вручную

Даже при живом таймере само продление может падать. Проверьте это безопасно, не тратя лимиты, в режиме симуляции:

certbot renew --dry-run

Эта команда проделывает весь путь продления, но не выпускает реальный сертификат. Если --dry-run проходит — механизм валидации в порядке, и проблема в планировщике или в hook перезагрузки. Если падает — читайте, на чём именно. Чаще всего всплывают те же причины, что и при первом выпуске: закрылся порт 80, изменился конфиг nginx, слетел webroot.

tail -40 /var/log/letsencrypt/letsencrypt.log

Особенно коварна ситуация, когда за 90 дней вы поменяли что-то в инфраструктуре — перенесли webroot, добавили редирект на HTTPS, поставили Cloudflare-прокси. При первом выпуске всё работало, а тихое автопродление спустя месяцы упёрлось в изменившееся окружение. --dry-run ловит это заранее, поэтому запускайте его после любых правок веб-сервера.

Порт 80 закрылся со временем

Очень распространённый сценарий: изначально сайт был на HTTP, порт 80 был открыт, сертификат выпустился. Потом вы перевели всё на HTTPS и закрыли или перестали слушать 80-й как «ненужный». А продление по HTTP-01 требует именно 80-й. В итоге спустя два месяца certbot renew не может пройти валидацию.

ss -tlnp | grep ':80'
ufw status | grep 80
curl -I http://ваш-домен/.well-known/acme-challenge/test

Держите 80-й порт открытым и слушающим постоянно, даже на чисто-HTTPS сайте — хотя бы для отдачи ACME-challenge и редиректа. Если закрыть 80 принципиально нужно, переведите продление на DNS-01 через плагин вашего DNS-провайдера, тогда входящий 80-й не потребуется. Но для большинства проще оставить 80-й приоткрытым только под .well-known/acme-challenge/.

Hook не перезагружает веб-сервер

Хитрая поломка: сертификат исправно продлевается, но сайт всё равно отдаёт старый — потому что nginx или apache держит в памяти прежний файл и не знает, что на диске уже новый. Продление без перезагрузки веб-сервера бесполезно для посетителя.

Проверьте, настроен ли deploy-hook:

cat /etc/letsencrypt/renewal/ваш-домен.conf | grep hook

Добавьте перезагрузку после успешного продления — глобально для всех сертификатов:

certbot renew --deploy-hook "systemctl reload nginx"

Или пропишите в файле /etc/letsencrypt/renewal-hooks/deploy/reload.sh скрипт с systemctl reload nginx и правами на исполнение — тогда он выполнится после любого успешного продления. Сравните дату файла сертификата и время последней перезагрузки nginx: если сертификат новее — значит, hook не сработал, и посетители видят старый.

Обратите внимание на разницу между --deploy-hook и устаревшими --renew-hook и --pre-hook. Deploy-hook выполняется только после реального обновления сертификата, а не при каждом холостом запуске certbot renew, — это именно то поведение, которое нужно для перезагрузки веб-сервера. Если вы по старой памяти повесили перезагрузку на pre-hook, nginx будет дёргаться при каждой проверке, даже когда продлевать нечего, а нужный момент — сразу после выпуска — может оказаться не покрыт. Держите один явный deploy-hook и не смешивайте его со старыми вариантами.

openssl x509 -enddate -noout -in /etc/letsencrypt/live/ваш-домен/fullchain.pem

Ставим мониторинг срока

Даже отлаженная автоматика может тихо сломаться, и вы узнаете об этом только от рассерженных пользователей. Правильно — следить за сроком заранее. Простая проверка даты окончания в мониторинге снимает риск.

# сколько дней осталось до истечения
openssl x509 -enddate -noout -in /etc/letsencrypt/live/ваш-домен/fullchain.pem
# проверка удалённо, как видит посетитель
echo | openssl s_client -servername ваш-домен -connect ваш-домен:443 2>/dev/null | openssl x509 -noout -enddate

Заведите алерт, если до истечения осталось меньше 20 дней — это запас, чтобы спокойно разобраться, если автопродление подведёт. Let's Encrypt также присылает письма о скором истечении на указанный при регистрации email, но полагаться только на них не стоит: письмо легко пропустить. Собственный мониторинг надёжнее. На стабильном сервере с постоянно открытым 80-м портом и рабочим deploy-hook сертификат обновляется годами без вашего участия.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS с чистым IP

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Как проверить, что автопродление вообще настроено?

Выполните systemctl list-timers | grep certbot и certbot renew --dry-run. Первый показывает, запускается ли планировщик, второй симулирует продление целиком. Оба должны отрабатывать без ошибок.

Почему сертификат продлился, но браузер видит старый?

Веб-сервер держит прежний файл в памяти и не перечитал новый. Нужен deploy-hook с systemctl reload nginx, который перезагружает сервер после каждого продления. Без него новый сертификат лежит на диске, но не отдаётся.

Может ли автопродление сломаться из-за изменений на сайте?

Да, и это частый случай: перенос webroot, новый редирект на HTTPS, закрытый порт 80 или Cloudflare-прокси ломают валидацию, которая при первом выпуске проходила. Запускайте --dry-run после любых правок веб-сервера.

Нужен ли открытый порт 80, если сайт полностью на HTTPS?

Для HTTP-01 продления — да, 80-й нужен постоянно. Либо держите его приоткрытым под ACME-challenge, либо переведите продление на DNS-01, где входящий 80-й не требуется.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.