MAATRIX / Блог / Let's Encrypt: не проходит валидация — причины и решение

Let's Encrypt: не проходит валидация — причины и решение

Let's Encrypt: не проходит валидация — причины и решение

MAATRIX

Запускаете 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 — десятки моделей в одном окне. Оплата картой РФ и по СБП.