Let's Encrypt: ошибка challenge failed — причины и решение
Certbot доходит до проверки домена и падает: Challenge failed for domain, а рядом — загадочный Detail. Ошибка Let's Encrypt challenge failed означает, что сервер сертификации не смог подтвердить контроль над доменом. Это обобщённый вердикт, а настоящая причина всегда в поле Detail рядом с ним. Научимся читать этот детальный текст — и каждая формулировка приведёт прямо к решению, без гадания.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое challenge и почему он failed
Challenge — это задание, которым Let's Encrypt проверяет, что домен ваш. Для HTTP-01 сервер ACME запрашивает файл по адресу http://домен/.well-known/acme-challenge/ТОКЕН. Для DNS-01 — проверяет TXT-запись _acme-challenge.домен. Если ответ не совпал с ожидаемым или до него не удалось достучаться, проверка помечается как failed.
Ключ к решению — не общая фраза «challenge failed», а сопровождающий её Detail. Именно там ACME пишет, что конкретно пошло не так: соединение отвергнуто, вернулся не тот контент, домен не резолвится, истёк таймаут. Каждая из этих формулировок соответствует своей причине и своему лечению. Поэтому первый шаг всегда один — найти и прочитать Detail, а не перебирать настройки наугад.
Стоит запомнить и то, что проверка идёт снаружи, с серверов Let's Encrypt, а не с вашей машины. Поэтому проверять доступность challenge через localhost бессмысленно: у вас всё откроется, а у проверяющего — нет, если мешает фаервол, NAT или неверная запись DNS. Всегда смотрите на домен глазами внешнего клиента, с другой машины или хотя бы по полному имени домена, а не по петлевому адресу. Этот разрыв между «у меня работает» и «ACME не видит» — источник большинства ложных диагнозов.
Находим настоящую причину в Detail
Запустите certbot подробно и посмотрите точный текст ошибки в выводе и в логе.
certbot certonly --webroot -w /var/www/html -d ваш-домен -v
tail -40 /var/log/letsencrypt/letsencrypt.log
Дальше сопоставьте Detail с таблицей причин. Connection refused — до порта 80 не достучались, закрыт фаерволом или веб-сервер не слушает. Timeout during connect — пакеты не доходят вовсе, чаще NAT или блокировка, иногда неверный A-запись. Invalid response ... 404 — файл-challenge не отдаётся по нужному пути, проблема webroot. Invalid response ... "<html>... — вместо файла отдаётся страница или редирект. DNS problem: NXDOMAIN — домен не резолвится, нет A-записи. Incorrect TXT record — для DNS-01 запись не та или не распространилась. Ниже — разбор самых частых.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS с чистым IPConnection refused и timeout
Если в Detail стоит Connection refused, порт 80 закрыт или на нём никто не слушает. ACME стучится строго на 80-й, изменить это нельзя. Проверьте, что порт открыт и занят веб-сервером.
ss -tlnp | grep ':80'
ufw status | grep 80
systemctl status nginx
Откройте порт и поднимите сервер: ufw allow 80/tcp и systemctl start nginx. Если же в Detail стоит Timeout during connect — пакеты вообще не доходят до сервера. Это уже не «закрытый порт», а более глубокая проблема: сервер за NAT без проброса 80-го, облачный security group блокирует входящий трафик, или A-запись домена ведёт на чужой IP, и ACME стучится не туда.
dig +short A ваш-домен
curl -I http://ваш-домен/ # с внешней машины, не с самого сервера
Сравните IP из dig с реальным адресом сервера. Расхождение — частая причина таймаута: домен указывает на старый хостинг или на Cloudflare-прокси. Разница между refused и timeout важна: первое чинится на сервере, второе — в сети и DNS.
Invalid response: файл отдаётся не так
Порт открыт, соединение проходит, но Detail показывает Invalid response с кодом 404 или куском HTML. Значит, ACME достучался, но получил не тот контент. При 404 — файла нет по ожидаемому пути: webroot в команде certbot не совпадает с корнем, который реально обслуживает nginx для этого домена.
# положите тестовый файл и запросите его снаружи
echo ok > /var/www/html/.well-known/acme-challenge/test
curl http://ваш-домен/.well-known/acme-challenge/test
Если вместо ok пришёл 404 — webroot неверный, поправьте -w так, чтобы он указывал на корень именно этого виртуального хоста. Если пришёл редирект или HTML-страница — весь HTTP редиректится на HTTPS, включая путь ACME. Исключите challenge из редиректа в nginx:
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
default_type text/plain;
try_files $uri =404;
}
Директива ^~ даёт этому location приоритет над общим редиректом, и challenge отдаётся напрямую. Это лечит самый частый Invalid response на сайтах, где всё уходит на HTTPS. Обратите внимание на нюанс с виртуальными хостами: если на сервере несколько сайтов, ACME-запрос по 80-му порту должен попасть именно в тот server-блок, где лежит нужный webroot. Когда домен не совпадает ни с одним server_name, nginx отдаёт его в дефолтный виртуальный хост, и challenge ищется совсем в другом каталоге — отсюда 404 при внешне правильной настройке. Проверьте, что server_name для вашего домена задан явно и запрос не проваливается в чужой блок.
DNS problem: домен не резолвится
Detail с текстом DNS problem: NXDOMAIN looking up A означает, что у домена нет A-записи или она не распространилась. ACME не может даже начать проверку, потому что не знает, к какому IP обращаться. Для DNS-01 аналогично: no TXT record found или Incorrect TXT record — запись _acme-challenge отсутствует, содержит не то значение, или ещё не разошлась по DNS.
dig +short A ваш-домен
dig +short TXT _acme-challenge.ваш-домен
Для NXDOMAIN — создайте A-запись и дождитесь распространения (TTL). Для DNS-01 главная ловушка — спешка: вы создали TXT-запись и сразу продолжили, а она ещё не видна публично. Проверяйте dig до тех пор, пока не увидите ровно то значение, что просит certbot, и только потом жмите Enter. Если у домена несколько NS-серверов, значение должно появиться на всех — рассинхрон между ними тоже даёт Incorrect TXT record.
Отлаживаем на staging, чтобы не ловить лимиты
Пока вы ищете причину challenge failed, каждая неудачная попытка на боевом ACME тратит лимит на неудачные проверки — пять в час. Легко залипнуть: причину ещё не нашли, а уже упёрлись в rate limit и ждёте час. Поэтому всю отладку ведите в тестовом окружении, где лимиты почти безграничны.
certbot certonly --staging --webroot -w /var/www/html -d ваш-домен -v
Гоняйте --staging сколько угодно, пока Detail не перестанет показывать ошибку. Как только staging-выпуск прошёл, повторите то же самое без флага — боевой сертификат выпустится с первого раза. Такой порядок экономит и время, и лимиты: вы не перемешиваете отладку с боевыми попытками. Общий алгоритм борьбы с challenge failed прост: прочитать Detail, определить тип ошибки, починить причину на staging, выпустить на боевом. При такой дисциплине проблема решается за один заход.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS с чистым IPОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
С чего начать, если certbot пишет challenge failed?
С чтения поля Detail рядом с ошибкой в выводе и в /var/log/letsencrypt/letsencrypt.log. Общая фраза бесполезна, а Detail называет точную причину: refused, timeout, 404, DNS problem — и каждая ведёт к своему решению.
В чём разница между Connection refused и Timeout?
Refused — сервер ответил отказом: порт 80 закрыт или веб-сервер не слушает, чинится на самом сервере. Timeout — пакеты не дошли вовсе: NAT, блокировка провайдером или неверная A-запись, чинится в сети и DNS.
Почему Invalid response, хотя сайт открывается?
ACME получил не файл, а редирект на HTTPS или страницу 404. Исключите путь .well-known/acme-challenge/ из общего редиректа nginx через приоритетный location и проверьте, что webroot совпадает с корнем виртуального хоста.
Как отлаживать challenge, не упираясь в лимиты?
Ведите всю отладку с флагом --staging — там лимиты почти не ограничены. Когда тестовый выпуск проходит без ошибок в Detail, повторите без флага, и боевой сертификат выпустится с первой попытки.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.