Wildcard-сертификат Let's Encrypt через проверку в DNS
Wildcard-сертификат нельзя подтвердить через веб-сервер, нужна TXT-запись в DNS. Инструкция показывает ручной и автоматический способ на Debian 13, Debian 12, Ubuntu 24.04 и 22.04, а также ошибки, на которых дело действительно срывается.
Wildcard-сертификат покрывает все имена одного уровня: shop.MeineDomain.de, mail.MeineDomain.de, kunde-4711.MeineDomain.de, в том числе те, которых сегодня ещё не существует. Именно поэтому привычный путь через веб-сервер здесь больше не работает. В этой инструкции разобраны оба рабочих способа, ручной и автоматический, и особое внимание уделено местам, на которых дело чаще всего срывается на практике.
Всё описанное проверено на Debian 13, Debian 12, Ubuntu 24.04 LTS и Ubuntu 22.04 LTS. По части Certbot эти четыре системы различаются заметно сильнее, чем признаёт большинство инструкций, поэтому ниже приведена отдельная таблица.
Почему wildcard-сертификат выдаётся только через DNS
У Let's Encrypt есть три способа проверки. Два из них для wildcard не подходят:
- HTTP-01 кладёт файл по адресу
http://name/.well-known/acme-challenge/token. Но для*.MeineDomain.deнет ни одного конкретного имени, под которым этот файл мог бы лежать. Удостоверяющему центру пришлось бы опросить бесконечное количество хостов. - TLS-ALPN-01 страдает тем же самым: он тоже проверяет конкретный хост на порту 443.
- DNS-01 проверяет TXT-запись по имени
_acme-challenge.MeineDomain.de. Тот, кто может создать эту запись, управляет зоной, а значит и любым именем внутри неё. Это единственное доказательство, которое подходит к звёздочке.
На практике это означает: --apache, --nginx, --webroot и --standalone для wildcard непригодны. Тот, кто всё же попробует, получит такое сообщение:
Client with the currently selected authenticator does not support any
combination of challenges that will satisfy the CA. You may need to use an
authenticator plugin that can do challenges over DNS.
Это не ошибка в вашей конфигурации, а корректный ответ на невыполнимый запрос. Для обычного случая с несколькими фиксированными именами путь через веб-сервер по-прежнему верен, он описан в статье про бесплатный SSL-сертификат с Certbot.
Второй момент, о котором почти все инструкции умалчивают: wildcard-сертификат покрывает только имена на один уровень ниже. *.MeineDomain.de действует для shop.MeineDomain.de, но ни для самого MeineDomain.de, ни для a.b.MeineDomain.de. Голый домен нужно запрашивать дополнительно, и это имеет последствия для TXT-записи, о чём ниже.
Требования и наличие пакетов в разных дистрибутивах
Понадобятся root-доступ по SSH, домен, зоной которого вы управляете, и Certbot. Запущенный веб-сервер для выпуска не нужен, порт 80 открывать не требуется. Это приятный побочный эффект: сертификат можно выпустить и для службы, которая вообще не смотрит в интернет.
Установите Certbot и инструменты для работы с DNS:
apt update
apt install -y certbot bind9-dnsutils
Пакет bind9-dnsutils приносит dig. Старое имя dnsutils на всех четырёх системах осталось лишь заглушкой, которая указывает на bind9-dnsutils. Проверьте, какая версия Certbot вам досталась:
certbot --version
Различия существенные, и именно они определяют, какой путь вам вообще доступен:
| Система | Certbot | Плагины из репозиториев дистрибутива |
| Debian 13 | 4.0.0 | cloudflare, desec, google, infomaniak, rfc2136, route53 |
| Debian 12 | 2.1.0 | cloudflare, digitalocean, dnsimple, gandi, gehirn, google, linode, ovh, rfc2136, route53, sakuracloud |
| Ubuntu 24.04 | 2.9.0 | cloudflare, digitalocean, dnsimple, gandi, gehirn, google, infomaniak, linode, ovh, rfc2136, route53, sakuracloud |
| Ubuntu 22.04 | 1.21.0 | cloudflare, digitalocean, dnsimple, gandi, gehirn, google, linode, ovh, rfc2136, route53, sakuracloud |
Вот что удивляет: Debian 13 выбросил из архива большинство DNS-плагинов. Тот, кто на Debian 12 работал с python3-certbot-dns-ovh или python3-certbot-dns-linode и обновился до Debian 13, просто не найдёт там этих пакетов. Команда apt upgrade через границу выпусков удаляет их, и продление обрывается, причём никто на это не смотрит. Проверьте это до смены версии дистрибутива.
Какие плагины на вашей системе действительно подхватываются, показывает команда:
certbot plugins
Ручной способ с TXT-записью
Ручной способ не требует доступа к API и работает у любого DNS-провайдера. Он годится, чтобы попробовать, и для зон, к которым вы и так редко прикасаетесь. У него есть один серьёзный недостаток, о нём сразу дальше.
Заранее выставьте будущей TXT-записи низкий TTL в вашей зоне, от 60 до 300 секунд. Это ничего не стоит и сэкономит вам время ожидания. Затем:
certbot certonly --manual --preferred-challenges dns \
--cert-name meinedomain.de \
-d "*.MeineDomain.de" -d MeineDomain.de
Кавычки вокруг "*.MeineDomain.de" обязательны. Без них оболочка подставит вместо звёздочки имена файлов из текущего каталога, и Certbot запросит сертификаты на ваши файлы. Параметр --cert-name тоже настоятельно рекомендуется: иначе Certbot образует имя каталога с сертификатом из первого имени, а каталог со звёздочкой в названии искать никому не захочется.
Certbot останавливается и показывает примерно такое:
Please deploy a DNS TXT record under the name:
_acme-challenge.MeineDomain.de.
with the following value:
gfj9Xq...Rg85nM
Вот здесь и проваливается большинство попыток. Вы запросили два имени, звёздочку и голый домен. Это две отдельные проверки, и обе приходят на одно и то же имя записи _acme-challenge.MeineDomain.de, но с разными значениями. Certbot об этом и предупреждает:
This must be set up in addition to the previous challenges; do not remove, replace, or undo the previous challenge tasks yet. Note that you might be asked to create multiple distinct TXT records with the same name. This is permitted by DNS standards.
Многие панели управления DNS предлагают для одного имени лишь одно поле ввода и заменяют первое значение вторым. В итоге в зоне остаётся только одно значение, одна из двух проверок не проходит, а в сообщении об ошибке всё равно названо только одно имя. Если ваша панель не допускает двух TXT-записей с одинаковым именем, ручной способ вам не подходит. Тогда используйте делегирование через CNAME, о нём ниже.
Сначала проверить, потом нажимать Enter
Certbot ждёт вашего подтверждения. Не нажимайте Enter сразу. Откройте вторую SSH-сессию и проверьте запись сначала на авторитативном сервере имён, а не на локальном резолвере:
dig +short NS MeineDomain.de
dig +short TXT _acme-challenge.MeineDomain.de @ns1.anbieter.example
dig +short TXT _acme-challenge.MeineDomain.de @1.1.1.1
dig +short TXT _acme-challenge.MeineDomain.de @8.8.8.8
Только когда оба значения появятся в одном ответе, причём на нескольких независимых друг от друга резолверах, нажимайте Enter. Пустой вывод означает, что записи ещё нет. Вот как это выглядит для домена без записи, вывод остаётся пустым:
dig +short TXT _acme-challenge.example.com @1.1.1.1
Зачем этот обход через авторитативный сервер? Если вы запросите _acme-challenge до того, как создали запись, ваш резолвер запомнит её отсутствие на время отрицательного TTL из SOA-записи, нередко на целый час. Вы ещё долго ничего не увидите, хотя запись давно на месте, и будете искать ошибку не там. У авторитативного сервера такого кэша нет.
Подвох ручного способа
Сертификат, выпущенный с --manual и без скрипта, никогда не продлевается сам. При следующем автоматическом запуске в журнале появится:
An authentication script must be provided with --manual-auth-hook when using
the manual plugin non-interactively.
Certbot пропускает такой сертификат и переходит к остальным, а код возврата при этом часто выглядит безобидно. Вы заметите это, когда начнёт ругаться браузер. Так что твёрдо рассчитывайте повторять ту же процедуру вручную каждые 60-90 дней либо переходите на один из автоматических способов.
Автоматический способ через плагин провайдера
Если у вашего DNS-провайдера есть API и для него существует плагин Certbot, то Certbot сам создаёт TXT-запись, ждёт, даёт провести проверку и потом убирает её обратно. Это тот путь, который нужен для рабочих систем. На примере Cloudflare:
apt install -y python3-certbot-dns-cloudflare
Положите учётные данные вне веб-каталога и сразу же закройте к ним доступ:
mkdir -p /root/.secrets/certbot
chmod 700 /root/.secrets/certbot
В файле /root/.secrets/certbot/cloudflare.ini должна быть ровно одна строка:
dns_cloudflare_api_token = ВашТокенЗдесь
После этого обязательно:
chmod 600 /root/.secrets/certbot/cloudflare.ini
Иначе Certbot при каждом запуске предупреждает о слишком широких правах. Используйте ограниченный токен с правом на запись DNS-записей, а не глобальный ключ учётной записи. Глобальный ключ пока ещё работает, но он может всё в вашей учётной записи, и после этого лежит на сервере открытым текстом. Токен же ограничивается одной-единственной зоной и в случае утечки отзывается отдельно.
Выпуск:
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
--cert-name meinedomain.de \
-d "*.MeineDomain.de" -d MeineDomain.de
Значение --propagation-seconds задаёт паузу между созданием записи и запросом на проверку. По умолчанию это 10 секунд, для многих зон слишком мало. 60 секунд — хорошее стартовое значение, у медлительных провайдеров лучше 120. Одно только это число объясняет большую часть эпизодически падающих продлений, которые потом никто не может воспроизвести.
У других провайдеров пакет называется python3-certbot-dns-<провайдер>, параметры устроены по тому же образцу. Сверьтесь с таблицей выше, есть ли ваш провайдер в вашем дистрибутиве вообще.
Если нужного пакета нет
Первый порыв: pip install certbot-dns-что-нибудь. На Debian 12, Debian 13 и Ubuntu 24.04 это заканчивается так:
error: externally-managed-environment
× This environment is externally managed
Так задумано, это не дефект. На Ubuntu 22.04 та же команда ещё проходит, но подмешивает пакеты pip к системным, и при следующем apt upgrade версии Certbot и плагина перестают соответствовать друг другу. Не продавливайте это через --break-system-packages.
Чистый выход: версия Certbot из snap, которая приносит плагины с собой и сама держит себя в актуальном состоянии. Перед этим удалите пакет дистрибутива, чтобы два Certbot не управляли одним каталогом:
apt remove -y certbot
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
snap set certbot trust-plugin-with-root=ok
snap install certbot-dns-cloudflare
Важно: имеющиеся данные в /etc/letsencrypt/ сохраняются, snap их подхватывает. Но таймер systemd после этого называется snap.certbot.renew.timer, а не certbot.timer. Кто это упустит, получит два таймера или ни одного.
Без плагина провайдера: rfc2136 и делегирование через CNAME
Два способа работают независимо от того, кто у вас DNS-провайдер.
rfc2136 — стандартный путь для динамического обновления DNS с ключом TSIG. Он работает с BIND, Knot и PowerDNS и есть в виде пакета на всех четырёх системах:
apt install -y python3-certbot-dns-rfc2136
Если вы держите DNS сами, это самое надёжное решение, потому что оно не требует ни чужой службы, ни HTTP-интерфейса.
Делегирование через CNAME — более изящный ответ сразу на две проблемы. В основной зоне вы один раз создаёте неизменную запись:
_acme-challenge.MeineDomain.de. CNAME MeineDomain.de.acme.eine-andere-zone.de.
При поиске TXT-записи Let's Encrypt идёт по цепочкам CNAME. Значит, TXT-запись возникает в целевой зоне, и права на запись серверу нужны только там. Это решает сразу несколько вопросов:
- Учётные данные на веб-сервере не могут изменить вашу основную зону. Взломанный веб-сервер не сможет переписать MX-записи.
- Целевая зона вправе держать несколько значений TXT одновременно, даже если панель вашего основного провайдера так не умеет.
- У целевой зоны может быть очень низкий TTL, и основная зона от этого не страдает.
Сам CNAME больше никогда не трогают, у него может быть высокий TTL. Проверить его можно так:
dig +short CNAME _acme-challenge.MeineDomain.de @1.1.1.1
Автоматизация продления
Certbot уже приносит с пакетом таймер, который запускается дважды в сутки. Сертификат при этом продлевается только тогда, когда это нужно:
systemctl list-timers certbot.timer
Если он не работает:
systemctl enable --now certbot.timer
На всех четырёх системах пакет приносит два триггера: /lib/systemd/system/certbot.timer и дополнительно /etc/cron.d/certbot. Файл cron в начале сам проверяет, активен ли таймер, и тогда ничего не делает, так что двойного продления не происходит. Собственное cron-задание на продление вам поэтому не нужно, оно стало бы третьим триггером для одной и той же задачи.
Здесь есть различие между дистрибутивами, о котором стоит знать. Certbot до версии 3 продлевает, когда до конца срока остаётся меньше 30 дней. Certbot 4.0, то есть версия в Debian 13, продлевает вместо этого, когда осталась треть срока. При привычных сегодня 90 днях оба варианта дают один и тот же момент. Как только Let's Encrypt начнёт выпускать сертификаты с более коротким сроком, поведение двух версий разойдётся, и подстроится автоматически только новая.
Проверьте всю процедуру вхолостую. При этом ничего не выпускается и лимит не расходуется:
certbot renew --dry-run
Wildcard-сертификат Certbot в конфигурацию веб-сервера не прописывает, это придётся один раз сделать самостоятельно. Чтобы веб-сервер после каждого продления действительно загружал новый сертификат, создайте deploy-hook. Оформите его файлом, а не параметром:
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
Содержимое файла /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh:
#!/bin/sh
systemctl reload nginx
Затем сделайте его исполняемым:
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh
Скрипты в этом каталоге выполняются для каждого продлённого сертификата. А параметр --deploy-hook, наоборот, записывается только в файл продления тех сертификатов, которые обрабатывались именно в этот момент. У добавленных позже сертификатов его не будет, и выяснится это лишь спустя месяцы.
Предупреждение насчёт учётных данных API: если токен отозван у провайдера или у него истёк срок, продление завершается ошибкой, при этом внешне ничего не сломано. Сертификат ведь ещё действует. Служба встанет только через 30 дней. Поэтому время от времени проверяйте, что сертификаты действительно обновляются, и не полагайтесь на письма с предупреждением об истечении срока.
По каким признакам понять, что всё действительно получилось
То, что команда отработала без ошибок, доказательством не является. Доказательством являются эти три проверки. Первая, общий обзор:
certbot certificates
В строке Domains должны стоять оба имени, *.MeineDomain.de и MeineDomain.de. Если звёздочки нет, вы получили обычный сертификат и просто этого не заметили.
Вторая, взгляд в сам файл:
openssl x509 -noout -text -in /etc/letsencrypt/live/meinedomain.de/fullchain.pem | grep -A1 "Subject Alternative Name"
Там должно появиться DNS:*.MeineDomain.de. Решающим является поле Subject Alternative Name, а не Common Name, который современные браузеры вообще больше не разбирают.
Третья, и это и есть настоящее доказательство: запросите имя, которое вы только что придумали:
echo | openssl s_client -servername test-1234.MeineDomain.de -connect MeineDomain.de:443 2>/dev/null | openssl x509 -noout -subject -dates
Если в ответ приходит действительный сертификат и никакого предупреждения нет, wildcard действительно работает. Только теперь дело сделано.
Частые ошибки дословно
- «DNS problem: NXDOMAIN looking up TXT for _acme-challenge.MeineDomain.de»: записи не существует, она ещё не распространилась либо вы создали её у не того провайдера. Самый частый случай: домен зарегистрирован у провайдера A, но серверы имён указывают на провайдера B, а запись лежит у A. Решающим является исключительно то, что выводит
dig +short NS MeineDomain.de. - «Incorrect TXT record ... found at _acme-challenge.MeineDomain.de»: значение есть, но не то. Типично после прерванной попытки, когда старое значение осталось в зоне, либо когда панель записала второе значение поверх первого. Удалите старые записи
_acme-challengeи начните заново. - «DNS problem: SERVFAIL looking up TXT ... the domain's nameservers may be malfunctioning»: почти всегда сломанная подпись DNSSEC, например после смены провайдера, при которой старая DS-запись осталась у регистратуры. Сначала почините это, иначе любой выпуск будет завершаться ошибкой.
- «CAA record for MeineDomain.de prevents issuance»: часто упускаемый камень преткновения. Для wildcard удостоверяющий центр сначала смотрит на
issuewild. У кого прописаноissue "letsencrypt.org", но рядом стоитissuewild ";", тот получит обычные сертификаты, а wildcard нет. Проверяется командойdig +short CAA MeineDomain.de. - «too many certificates (5) already issued for this exact set of identifiers»: для одной и той же комбинации имён разрешено пять сертификатов за семь дней. Поэтому проверяйте с
--dry-runили на тестовой среде через--test-cert. Блокировка снимается сама по истечении срока, вручную её не убрать. - Панель показывает TXT-запись, а dig нет: некоторые провайдеры требуют, чтобы изменения в зоне были явно опубликованы. Сохранённая запись не становится активной автоматически.
- Имя записи задваивается: некоторые панели дописывают домен автоматически. Вводите там только
_acme-challenge, иначе получится_acme-challenge.MeineDomain.de.MeineDomain.de. Запросdigпо полному имени сразу это вскроет.
На перспективу: DNS-PERSIST-01
Let's Encrypt работает над новым способом проверки под названием DNS-PERSIST-01. Вместо того чтобы при каждом продлении публиковать свежий токен, вы один раз размещаете постоянную запись, которая даёт право на выпуск определённой учётной записи ACME. После этого серверу для продления вообще не нужен доступ на запись в DNS. Для wildcard это стало бы заметным выигрышем в безопасности.
По плану Let's Encrypt тестовая среда была намечена на конец первого квартала 2026 года, продуктивная работа на второй квартал. Поддержит ли Certbot этот способ, пока не объявлено. Так что закладываться на него ещё рано, но держите его в поле зрения, если как раз сейчас строите управление сертификатами заново.
Итог
Wildcard-сертификат выпускается исключительно через проверку в DNS, потому что звёздочку невозможно подтвердить через один-единственный веб-сервер. Ручной путь через TXT-запись работает везде, но никогда не продлевается сам. Путь через плагин провайдера единственный, который можно оставить без присмотра, и на практике он чаще всего спотыкается на слишком коротком времени ожидания или на учётных данных, которые тихо перестали действовать. Если запоминать только одно: проверяйте TXT-запись на авторитативном сервере имён, прежде чем дать Certbot продолжить, и при звёздочке плюс голом домене твёрдо рассчитывайте на две записи под одним и тем же именем.
Частые вопросы
Почему нельзя выпустить wildcard-сертификат через Apache или nginx?
Покрывает ли *.MeineDomain.de сам домен MeineDomain.de?
Зачем нужны две TXT-записи с одним и тем же именем?
Как проверить, распространилась ли уже TXT-запись?
Продлевается ли автоматически wildcard-сертификат, выпущенный вручную?
Какие DNS-плагины Certbot есть в Debian 13?
Что даёт делегирование _acme-challenge через CNAME?
2026 KernelHost GmbH. Все права защищены. Эта инструкция охраняется авторским правом. Публикация на других сайтах, в том числе частично или в изменённом виде, без нашего письменного согласия не разрешается. Цитирование с указанием источника и активной ссылкой мы приветствуем.

