Wildcard-сертификат Certbot через DNS-01
Настройте wildcard-сертификат Certbot через DNS-01: создайте TXT-запись для _acme-challenge, установите DNS-плагин и включите автоматическое продление.
Почему для wildcard-сертификата требуется DNS-01
Wildcard-сертификат охватывает все поддомены первого уровня: *.example.com подходит для app.example.com, blog.example.com и любого другого имени с одним уровнем вложенности. Let's Encrypt выпускает wildcard-сертификаты только через проверку DNS-01, поэтому Certbot должен доказать управление DNS домена, опубликовав TXT-запись по адресу _acme-challenge.example.com. Проверка HTTP-01 не подходит, так как размещение токена в файле подтверждает контроль только над одним конкретным именем хоста, с которого сервер проверки запрашивал файл. Wildcard — это заявка на все возможные имена на один уровень ниже домена, и единственная публичная запись, которая подтверждает права на всё пространство имён, — это сам DNS.
Это требование определяет всё остальное на этой странице. Чтобы пройти DNS-01, вы должны иметь возможность создавать TXT-записи в зоне домена или в отдельной зоне проверки, на которую _acme-challenge указывает с помощью CNAME (описано ниже), вручную или через API (интерфейс прикладного программирования) вашего DNS-провайдера. Ручной способ работает один раз, но терпит неудачу при обновлении по конкретной причине, указанной ниже. Способ через API с использованием DNS-плагина Certbot позволяет выполнять обновление автоматически, и именно к такой настройке следует стремиться.
Это глава о wildcard-сертификатах из нашего руководства по Certbot. Обычные сертификаты для одного хоста, настройка веб-сервера и правила для 80 порта описаны в Certbot с nginx в Ubuntu 24.04 и Certbot с Apache в Ubuntu 24.04.
Как работает TXT-запись _acme-challenge
Когда Certbot запрашивает *.example.com, Let's Encrypt отвечает случайным токеном. Certbot объединяет этот токен с ключом учетной записи ACME (среда автоматического управления сертификатами), хеширует результат с помощью SHA-256 и получает короткое текстовое значение. Это значение должно быть указано в TXT-записи по адресу _acme-challenge.example.com. Затем Let's Encrypt запрашивает авторитетные серверы имен вашего домена из своей инфраструктуры. Если прочитанная запись совпадает с ожидаемым значением, вы доказали, что управляете зоной. Управление зоной считается подтверждением управления всеми именами в этой зоне.
Большинство сбоев вызывают два обстоятельства:
- Запрос
example.comи*.example.comв одном сертификате означает две отдельные проверки. Обе TXT-записи размещаются по одному имени:_acme-challenge.example.com. Обе записи должны существовать одновременно. Добавить вторую запись правильно. Замена первой записи второй приводит к сбою первой проверки. - При проверке считываются данные с авторитетных серверов, но панели управления провайдеров могут передавать новую запись на эти серверы в течение минуты или дольше. Перед запуском проверки проверьте запись извне:
dig +short TXT _acme-challenge.example.com @1.1.1.1Если команда выводит значение, которое запросил Certbot, проверка может завершиться успешно. Если команда ничего не выводит, подождите и выполните ее снова.
Однократная проверка работы: ручной режим
В ручном режиме запись DNS изменяется вручную. Это лучший способ понять механизм до его автоматизации:
sudo certbot certonly --manual --preferred-challenges dns -d example.com -d '*.example.com'Кавычки вокруг wildcard не позволяют оболочке воспринимать * как шаблон имени файла. Certbot приостанавливает выполнение и выводит инструкции:
Please deploy a DNS TXT record under the name:
_acme-challenge.example.com.
with the following value:
Jx9mQ2wLr8vTn5cKp0aYdG3hB7fZs4eN1oiRuXqMk6EСоздайте эту TXT-запись в панели управления DNS-провайдера. Проверьте, что она видна с помощью приведённой выше команды dig, и только после этого нажмите Enter. Поскольку этот запуск запрашивает основной домен и wildcard, Certbot выводит запрос дважды. Не удаляйте обе записи до завершения выпуска сертификата. При успешном выполнении в конце отображаются знакомые строки:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pemПочему ручной режим не может продлить сертификат самостоятельно
Каждое продление начинается с новой проверки и новым токеном, поэтому значение TXT меняется каждый раз. Запись, которую вы добавили сегодня, через 60 дней станет непригодной. Таймер продления запускает Certbot без участия пользователя два раза в день. За клавиатурой никого нет, чтобы вставить новое значение. Поэтому сертификат, выпущенный вручную, не продлевается и вы получаете именно эту ошибку:
Failed to renew certificate example.com with error: The manual plugin is not
working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with
--manual-auth-hook when using the manual plugin non-interactively.')Это требование можно выполнить с помощью скриптов --manual-auth-hook, которые вызывают API вашего DNS-провайдера. Но в таком случае вы фактически вручную создаёте DNS-плагин. Используйте ручной режим, чтобы изучить процесс, или для действительно разовой операции с доменом, DNS которого пока нельзя автоматизировать. Установите напоминание задолго до 90-го дня, поскольку Let's Encrypt больше не отправляет уведомления об окончании срока действия. Во всех остальных случаях используйте плагин.
Вариант с плагином: certbot-dns-cloudflare в Ubuntu 24.04
Плагин DNS хранит учетные данные API вашего провайдера DNS и самостоятельно выполняет всю последовательность операций с TXT-записью при выпуске сертификата и каждом его продлении. В качестве примера используется Cloudflare, поскольку это самый востребованный плагин провайдера и он входит в состав Ubuntu.
В руководствах по Certbot мы рекомендуем пакеты apt в Ubuntu 24.04. Для Cloudflare действует та же рекомендация:
sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflareСледует учитывать версии. В архиве 24.04 этот плагин имеет версию 2.0.0 и устанавливается вместе с Certbot 2.9.0; apt policy python3-certbot-dns-cloudflare показывает установленную у вас версию. Несовпадение версий не мешает работе. Ограниченные токены API поддерживаются, поскольку базовая библиотека python3-cloudflare в 24.04 имеет версию 2.11.1. Это выше версии 2.3.1, необходимой плагину для поддержки токенов. В старых выпусках Ubuntu эта библиотека была слишком старой для работы с токенами. Поэтому в найденных в интернете предупреждениях говорится, что плагин apt требует Global API Key. Для 24.04 эти предупреждения больше не актуальны.
В панели Cloudflare создайте ограниченный токен API, а не Global API Key: откройте My Profile, затем API Tokens и Create Token. Укажите единственное разрешение Zone / DNS / Edit и ограничьте токен одной зоной, для которой выпускается сертификат. Запишите его в файл, доступный для чтения только root:
sudo mkdir -p /root/.secrets
sudo tee /root/.secrets/cloudflare.ini > /dev/null <<'EOF'
dns_cloudflare_api_token = paste_your_scoped_token_here
EOF
sudo chmod 600 /root/.secrets/cloudflare.iniCertbot проверяет режим доступа к файлу и предупреждает о Unsafe permissions on credentials configuration file, если файл доступен для чтения другим пользователям. Теперь выпустите сертификат:
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com'Плагин создает TXT-записи через API, ожидает небольшое время распространения изменений, запускает проверку и затем удаляет записи. Если серверы имен вашей зоны медленно применяют изменения, увеличьте время ожидания с помощью --dns-cloudflare-propagation-seconds 60. Сертификат будет сохранен в /etc/letsencrypt/live/example.com/. Настройте nginx или Apache на использование fullchain.pem и privkey.pem точно так, как показано в основных руководствах, включая deploy hook.
Если плагин вашего провайдера отсутствует в apt
В репозиториях 24.04 упакованы плагины только для небольшого числа провайдеров, включая Cloudflare, Route 53, DigitalOcean и стандартный интерфейс RFC 2136. Запустите apt search certbot-dns, чтобы увидеть список. Если вашего провайдера нет в списке, это единственный случай, когда мы отступаем от рекомендации использовать apt: установите Certbot и плагин через snap, предварительно удалив версию Certbot из apt, чтобы два таймера обновления не конфликтовали из-за /etc/letsencrypt:
sudo apt remove certbot python3-certbot-dns-cloudflare
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-yourproviderSnap-плагин подключается только к snap-версии Certbot; он не может расширить функционал версии из apt, поэтому эти два способа установки не должны сосуществовать. Если ваш DNS-хостинг вообще не предоставляет API, у вас есть три реальных варианта. Вы можете перенести DNS домена к провайдеру, у которого есть API. Вы можете запустить собственный сервер имён и настроить плагин rfc2136 на работу с ним. Либо вы можете оставить текущий DNS-хостинг и добавить однократную CNAME-запись из _acme-challenge.example.com в зону проверки, где есть API, например, в сервис acme-dns или на собственный сервер acme-dns. Let's Encrypt следует за этой CNAME-записью во время проверки, поэтому TXT-записи будут находиться в делегированной зоне, а ваша основная зона больше не будет меняться.
Продление: выполните проверку сейчас, а не через 60 дней
Certbot записывает сведения о способе выпуска каждого сертификата в /etc/letsencrypt/renewal/example.com.conf, включая authenticator = dns-cloudflare и путь к файлу учетных данных. Поэтому стандартный таймер, запускаемый дважды в день, продлевает сертификат без вашего участия. Проверьте весь процесс в тестовой среде:
sudo certbot renew --dry-runУспешное выполнение означает, что учетные данные работают, а проверка проходит от начала до конца. Реальное продление через 60 дней будет выполняться тем же способом. Сегодня стоит выполнить еще две задачи. Во-первых, обновленный сертификат на диске не используется автоматически, пока веб-сервер не перезагрузит его. Поэтому настройте deploy hook, описанный в руководствах по nginx и Apache. Во-вторых, защищайте файл учетных данных: любой пользователь, который может его прочитать, может изменить вашу DNS-зону. Этого достаточно, чтобы перенаправить вашу почту или самостоятельно пройти проверки DNS-01. Установите для файла режим 600, храните его в /root, ограничьте токен одной зоной и замените токен, если подозреваете утечку.
Когда вам не нужен wildcard
Wildcard — правильный инструмент для множества субдоменов или для субдоменов, которые нельзя заранее определить. Для всех остальных случаев это не лучший вариант по умолчанию.
- Один субдомен или несколько известных субдоменов: обычный сертификат SAN (subject alternative name) проще.
certbot --nginx -d example.com -d www.example.com -d app.example.comпокрывает до 100 имен через обычную проверку HTTP-01, а учетные данные для DNS API никогда не хранятся на сервере. - Wildcard соответствует ровно одному уровню.
*.example.comне покрывает основной доменexample.com, поэтому приведенные выше команды запрашивают оба имени. Он также не покрываетa.b.example.com: для этого потребуется*.b.example.com. - За всеми субдоменами стоит один закрытый ключ. Если машина, на которой он хранится, будет скомпрометирована, это сразу затронет все имена, покрываемые wildcard.
- Если Traefik завершает TLS (transport layer security) для ваших контейнеров, Certbot вообще не нужен: Traefik самостоятельно запрашивает wildcard-сертификаты через DNS-01, используя токен провайдера того же типа.
Wildcard действительно полезен для субдоменов отдельных клиентов или приложений, которые создаются быстрее, чем вы успеваете перевыпускать сертификаты, а также для внутренних узлов без общедоступного порта 80, например сервисов, доступных только через VPN WireGuard. DNS-01 не подключается к хосту, для которого выпускается сертификат, поэтому даже полностью закрытая машина может использовать сертификат, которому доверяют общедоступные центры сертификации.
FAQ
Может ли Certbot выпустить wildcard-сертификат с помощью HTTP-01?
Нет. HTTP-01 подтверждает контроль над одним именем хоста, так как сервер проверки запрашивает файл токена именно с этого имени. Wildcard охватывает все имена первого уровня под доменом, поэтому Let's Encrypt требует для него проверку DNS-01, а аутентификаторы --nginx, --apache, --webroot и --standalone работают на основе HTTP. Единственный путь — это TXT-запись по адресу _acme-challenge.example.com (или в зоне, куда она делегирована через CNAME), размещенная вручную или DNS-плагином.
Покрывает ли wildcard-сертификат корневой домен?
Нет. Wildcard соответствует ровно одной метке, поэтому *.example.com покрывает www.example.com, но не сам домен example.com и не a.b.example.com. Запросите оба имени в одном сертификате с помощью -d example.com -d '*.example.com'. Это создаст две проверки, и обе TXT-записи будут находиться по одному адресу _acme-challenge.example.com, поэтому добавьте вторую запись, не удаляя первую.
Почему мой wildcard-сертификат не обновляется автоматически?
Потому что он был выпущен с использованием --manual. Каждое обновление требует нового значения TXT, и автоматический таймер не может его вставить, поэтому обновление останавливается с ошибкой An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively. Перевыпустите сертификат с помощью DNS-плагина, такого как certbot-dns-cloudflare, или предоставьте скрипты --manual-auth-hook и --manual-cleanup-hook, которые редактируют запись через API вашего провайдера.
Как долго появляется TXT-запись _acme-challenge?
Это зависит от вашего DNS-провайдера: от нескольких секунд до нескольких минут. Проверка считывает данные с авторитетных серверов вашей зоны, поэтому проверяйте с помощью dig +short TXT _acme-challenge.example.com @1.1.1.1 и дождитесь появления ожидаемого значения, прежде чем продолжать ручной запуск. При использовании плагина увеличьте встроенное время ожидания через опцию распространения (propagation), например --dns-cloudflare-propagation-seconds 60, если проверка сообщает, что запись не найдена.
Менее безопасен ли wildcard-сертификат, чем обычный?
Криптография идентична. Различия заключаются в эксплуатации: один закрытый ключ охватывает все поддомены, поэтому компрометация затрагивает больше ресурсов, а учетные данные DNS API, необходимые для автоматизации, сами по себе являются секретными данными, хранящимися на сервере. Если вы используете лишь несколько известных поддоменов, SAN-сертификат позволяет избежать обеих проблем — именно в таких случаях данное руководство рекомендует отказаться от использования wildcard.