Let's Encrypt: не проходит валидация — причины и решение
Запускаете certbot, а он отваливается: домен не подтверждается, сертификат не выдаётся. Когда Let's Encrypt не проходит валидация, причина всегда в том, что сервер ACME не смог убедиться, что домен действительно ваш. Проверка идёт по строгому протоколу, и любой сбой на пути — закрытый порт, неверный редирект, кривой DNS — рушит весь процесс. Разберём типы проверок и пройдём по причинам от самой частой к редкой.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Как работает валидация домена
Прежде чем выдать сертификат, Let's Encrypt должен доказать, что запрашивающий контролирует домен. Делается это одним из двух способов (challenge). HTTP-01: центр сертификации кладёт вам задание и ждёт, что по адресу http://ваш-домен/.well-known/acme-challenge/ТОКЕН появится нужный файл. DNS-01: вы создаёте TXT-запись _acme-challenge.ваш-домен с определённым значением.
Понимание механизма сразу подсказывает, где искать поломку. Для HTTP-01 сервер ACME обращается к вашему домену снаружи по порту 80 — значит, важны публичный DNS, открытый 80-й порт и корректная отдача файла. Для DNS-01 важно, чтобы TXT-запись реально опубликовалась и разошлась по DNS. Большинство ошибок валидации — это HTTP-01, и почти все они сводятся к тому, что проверяющий просто не достучался до вашего файла.
Ещё одна важная деталь: проверка идёт снаружи, с серверов Let's Encrypt, а не с вашей машины. Поэтому бесполезно проверять доступность challenge локально через localhost — вы обязаны смотреть на домен глазами внешнего клиента. Именно этот разрыв между «у меня всё открывается» и «проверяющий не видит» порождает большинство ложных диагнозов. Всегда тестируйте curl-ом по полному доменному имени, а не по 127.0.0.1.
Домен не указывает на этот сервер
Банальная, но частая причина: A-запись домена ведёт на другой IP (старый хостинг, Cloudflare-прокси, опечатка). Let's Encrypt проверяет тот адрес, что видит в публичном DNS, а не тот, где вы запускаете certbot.
dig +short ваш-домен A
curl -s ifconfig.me # реальный IP сервера
Если эти два адреса не совпадают — валидация обречена. Проверяющий уходит на чужой сервер и не находит там задания. Дождитесь распространения DNS после смены A-записи (TTL может быть до нескольких часов) и повторите. Отдельная ловушка — Cloudflare с оранжевым облаком: трафик идёт через их прокси, и HTTP-01 может не долетать до вашего origin. На время выпуска включите серый режим (DNS only) или используйте DNS-01. Пока A-запись не указывает на ваш сервер, дальнейшая отладка бессмысленна.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS с чистым IPЗакрыт порт 80
HTTP-01 работает только по 80-му порту — это жёсткое требование протокола, его нельзя изменить на 8080 или 443 для проверки. Если 80-й закрыт фаерволом или занят/не слушается, проверяющий получит отказ соединения, и в логе появится Connection refused или Timeout during connect.
ss -tlnp | grep ':80'
ufw status | grep 80
# проверить доступность снаружи (с другой машины)
curl -I http://ваш-домен/
Откройте порт и убедитесь, что на нём слушает веб-сервер:
ufw allow 80/tcp
systemctl status nginx
Частая ошибка — вы открыли только 443 для HTTPS, а про 80 забыли, считая его ненужным. Но именно 80-й нужен для проверки и для последующего редиректа. Даже если сайт полностью на HTTPS, оставьте 80-й открытым хотя бы для ACME. Если certbot работает во standalone-режиме, он сам поднимает временный сервер на 80 — тогда убедитесь, что порт свободен и не занят nginx.
Редиректы и неправильная отдача challenge
Сервер доступен по 80, но валидация всё равно падает — значит, файл-задание не отдаётся как надо. Частая причина: nginx редиректит весь HTTP на HTTPS, включая путь .well-known/acme-challenge/, и проверяющий вместо файла получает редирект на битый или ещё не существующий HTTPS. Или webroot указан неверно, и файла просто нет по нужному пути.
Проверьте руками, положив тестовый файл:
mkdir -p /var/www/html/.well-known/acme-challenge/
echo "test123" > /var/www/html/.well-known/acme-challenge/test
curl http://ваш-домен/.well-known/acme-challenge/test
Если вернулось не test123, а редирект, ошибка 404 или страница — вот и причина. Исключите путь ACME из общего редиректа в конфиге nginx:
location /.well-known/acme-challenge/ {
root /var/www/html;
allow all;
}
location / {
return 301 https://$host$request_uri;
}
Убедитесь, что webroot в команде certbot (-w /var/www/html) совпадает с root в этом location. Несовпадение webroot — причина номер один среди «сервер вроде работает, а валидация нет».
Права доступа и SELinux
Файл создаётся, но веб-сервер не может его прочитать — тогда снаружи прилетает 403 Forbidden. Причина в правах на каталог webroot или в SELinux, который на CentOS/RHEL по умолчанию ограничивает доступ nginx к файлам.
ls -ld /var/www/html/.well-known/acme-challenge/
namei -l /var/www/html/.well-known/acme-challenge/test
getenforce
Каталог и файл должны быть доступны пользователю веб-сервера на чтение и на обход всех родительских директорий. Если getenforce показывает Enforcing, а в логах nginx или audit виден отказ — восстановите контекст SELinux:
chmod -R 755 /var/www/html/.well-known
restorecon -Rv /var/www/html
Не отключайте SELinux целиком ради сертификата — это лечение симптома, а не причины. Правильный контекст решает проблему без снижения безопасности.
DNS-01, когда HTTP-01 невозможен
Если сервер за NAT без публичного 80-го порта, или вы выпускаете wildcard-сертификат (*.домен), HTTP-01 не подходит — нужен DNS-01. Тут валидация идёт через TXT-запись, и типичные ошибки другие: запись не опубликовалась, не успела распространиться, или у домена несколько NS с рассинхроном.
certbot certonly --manual --preferred-challenges dns -d '*.ваш-домен' -d ваш-домен
# после создания записи проверьте, что она видна:
dig +short TXT _acme-challenge.ваш-домен
Главная ловушка DNS-01 — спешка: вы создали TXT-запись и сразу нажали Enter, а запись ещё не разошлась по DNS-серверам. Дайте ей время (проверяйте dig, пока не увидите нужное значение) и только потом продолжайте. Для автоматизации используйте плагин certbot под вашего DNS-провайдера — он создаёт и удаляет записи через API, и человеческий фактор со спешкой исчезает. Wildcard-сертификаты выпускаются только через DNS-01, HTTP-01 их не поддерживает в принципе.
Читаем детальный лог certbot
Когда причина не очевидна, certbot пишет подробности в свой лог. Там видно, что именно ответил сервер ACME и на каком этапе.
certbot certonly --webroot -w /var/www/html -d ваш-домен -v
tail -50 /var/log/letsencrypt/letsencrypt.log
Ищите строки с Detail: — там человеческим языком написано, что пошло не так: Invalid response, Connection refused, DNS problem: NXDOMAIN, Timeout. Каждая формулировка прямо ведёт к разделу выше. Не запускайте выпуск раз за разом наугад — за неудачные попытки Let's Encrypt считает лимиты, и можно упереться в ограничение по количеству ошибок за час. Для отладки используйте тестовое окружение --staging: там лимиты щедрые, а поведение то же самое.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS с чистым IPОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Почему валидация падает, хотя сайт открывается в браузере?
Скорее всего, проверяющий ACME идёт на другой IP (кэш DNS, Cloudflare-прокси) или упирается в редирект/403 на пути .well-known/acme-challenge/. Проверьте dig +short A и отдачу тестового файла curl-ом снаружи.
Обязателен ли открытый порт 80 для Let's Encrypt?
Для HTTP-01 — да, строго 80-й, изменить нельзя. Если открыть его невозможно (NAT, политика), используйте DNS-01 через TXT-запись — этот способ не требует входящего 80-го порта.
Как выпустить wildcard-сертификат?
Только через DNS-01: создаёте TXT-запись _acme-challenge и указываете -d '*.домен'. HTTP-01 wildcard не поддерживает. Удобнее всего с плагином certbot под вашего DNS-провайдера.
Что делать, если упёрся в лимит после неудачных попыток?
Переключитесь на --staging для отладки — там лимиты почти не ограничены. Отладив выпуск на стейджинге, повторите на боевом окружении. Лимиты на ошибки сбрасываются в течение часа.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.