Wildcard SSL давно стал стандартным инструментом для мультисайтов и SaaS, где у каждого арендатора свой поддомен. Правильная организация выпуска через DNS‑01 в связке с ACME‑клиентами (certbot, lego) и DNS API снимает рутину, а ошибки в автоматизации приводят к ночным пейджингам, простоям и утечкам токенов. Разбираем архитектуру, практику и «минные поля» в одном месте.
Когда и зачем нужен wildcard SSL
Wildcard сертификат закрывает домены вида *.example.com
, что идеально для мультисайтов и SaaS с арендаторскими поддоменами: client1.example.com
, client2.example.com
и так далее. Это уменьшает количество сертификатов, упрощает конфигурации и снижает риск упереться в лимиты ACME (Let’s Encrypt). Но у wildcard есть ограничения:
- Он не покрывает корневой домен
example.com
— apex нужно добавлять отдельным SAN (совместно с wildcard) в один сертификат. - Он не покрывает второй уровень поддоменов (
*.a.example.com
— это уже другой wildcard). - Он не поможет, если у клиентов кастомные домены (разные зоны). Для таких случаев нужен выпуск отдельного сертификата на домен клиента или режим DNS‑alias.
Если политика безопасности требует коммерческий wildcard (OV/EV) или нестандартную CA, оформите его через SSL-сертификаты.
Почему в SaaS важен именно DNS‑01
ACME поддерживает несколько способов проверки: HTTP‑01
, DNS‑01
и TLS‑ALPN‑01
. В мультисайтах и SaaS чаще выбирают DNS‑01
по таким причинам:
- Только DNS‑01 позволяет выпускать wildcard (
*.example.com
). - Нет зависимости от веб‑стека (Nginx/Apache/бэкэнд), проверки идут через DNS‑провайдера.
- Для кастомных доменов клиентов можно использовать CNAME‑алиас на
_acme-challenge
, не требуя у клиента ни API‑ключей, ни HTTP‑доступа.
Если у вас SaaS и доля доменов с apex (без www) высокая, закладывайте поддержку DNS‑01 с первого дня. HTTP‑01 не решит apex и wildcard одновременно.
Архитектурные паттерны для мультисайтов и SaaS
1) Один домен и поддомены арендаторов
Классика: tenant.example.com
. Идеальный кандидат для одного серта с SAN: example.com
+ *.example.com
. Выпуск по DNS‑01 через API DNS‑провайдера. Ротация раз в ~60 дней, чтобы не упираться в край срока.
2) Кастомные домены клиентов
HTTP‑01 требует публикации файла у клиента — сложно и уязвимо. Предпочтительно использовать DNS‑alias: клиент добавляет CNAME
запись _acme-challenge.client-domain.tld
указывающую на _acme-challenge.client-domain.tld.your-saas.example
. ACME‑сервер следует CNAME и читает TXT там, где вы автоматизируете. Дальше ваш конвейер меняет TXT на своей зоне без доступа к DNS клиента. Это масштабируется и снижает поддержку.
3) On‑demand TLS
Для динамической выдачи сертификатов «по запросу» (когда клиент впервые заходит на домен) используют библиотеки/прокси с ACME (например, интеграции с certbot/lego). Здесь важно кэширование сертификатов, дисциплина по rate‑limit и отказоустойчивость: если ACME или DNS API временно недоступны, трафик не должен падать.
Предварительный чек‑лист
- Определите зону ответственности: какие домены/поддомены, нужно ли apex, как обрабатываются кастомные домены клиентов.
- Выберите ACME‑клиент: certbot, lego, acme.sh — ориентируйтесь на поддержку вашего DNS‑провайдера и нужные фичи.
- Приготовьте DNS API токены с минимальными правами (только на нужную зону и только DNS‑записи).
- Решите, где и как хранить секреты: права на файлы 600, отдельный vault/секрет‑хранилище, контроль доступа.
- Запланируйте ротацию и перезапуск/перезагрузку веб‑сервера без даунтайма.
Если вы только выбираете доменное имя для платформы, заранее проверьте доступность и оформите его через регистрацию доменов.

Практика: выпуск wildcard через certbot + DNS‑плагин
Certbot удобен, если у вас дистрибутив с готовыми пакетами плагинов DNS и простой интеграцией с cron/systemd. Пример для DNS‑провайдера с поддержкой плагина (покажем общий подход):
Установка
apt update && apt install -y certbot python3-certbot-dns-cloudflare
Замените плагин на свой: python3-certbot-dns-route53
, python3-certbot-dns-digitalocean
и т.д., если используете другой провайдер.
Токен и права
Создайте API токен только с правом редактирования DNS в нужной зоне. Сохраните его в файл, доступный только root:
cat > /etc/letsencrypt/cloudflare.ini << 'EOF'
dns_cloudflare_api_token = <ваш_токен>
EOF
chmod 600 /etc/letsencrypt/cloudflare.ini
Первичный выпуск wildcard + apex
certbot certonly \
--agree-tos \
--non-interactive \
--email admin@example.com \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d example.com \
-d *.example.com
Если провайдер медленно распространяет TXT, увеличьте ожидание плагина (например, --dns-cloudflare-propagation-seconds 120
— конкретная опция зависит от плагина). Повторный выпуск и продление будут использовать сохранённый профиль автоматически.
Раскатка и автоматическое продление
Добавьте деплой‑хук для перезагрузки Nginx без простоя:
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'EOF'
#!/bin/sh
systemctl reload nginx || nginx -s reload || true
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Проверьте продление:
certbot renew --dry-run
Практика: lego + DNS API (пример с Route53 и Cloudflare)
Lego — статичный бинарник на Go с широкой поддержкой DNS API и простым CLI. Примеры:
Route53
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_REGION="eu-central-1"
lego --email "admin@example.com" \
--dns route53 \
--domains "example.com" \
--domains "*.example.com" run
Продление за 30 дней до истечения:
lego --dns route53 \
--domains "example.com" \
--domains "*.example.com" renew --days 30
Cloudflare c токеном
export CF_DNS_API_TOKEN="..."
lego --email "admin@example.com" \
--dns cloudflare \
--domains "example.com" \
--domains "*.example.com" run
У lego есть полезная опция --dns.resolvers
для указания публичных резолверов и --dns.disable-cp
для отключения проверки наличия TXT через кэш резолверов (если понимаете, что делаете).
systemd‑юнит для регулярного продления
# /etc/systemd/system/lego-renew.service
[Unit]
Description=Renew ACME certificates via lego
[Service]
Type=oneshot
Environment=CF_DNS_API_TOKEN=...
ExecStart=/usr/local/bin/lego --dns cloudflare \
--domains "example.com" \
--domains "*.example.com" renew --days 30
ExecStartPost=/bin/systemctl reload nginx
# /etc/systemd/system/lego-renew.timer
[Unit]
Description=Daily ACME renew via lego
[Timer]
OnCalendar=daily
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target
Активируйте таймер: systemctl enable --now lego-renew.timer
.
Как подключить wildcard в Nginx
Сертификат, выпущенный как SAN на example.com
и *.example.com
, подключается как обычно:
server {
listen 443 ssl http2;
server_name .example.com example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Рекомендуемые флаги
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
# Приложение
location / { proxy_pass http://app; }
}
Для лучшей производительности рассмотрите выпуск ECDSA ключей: в certbot --key-type ecdsa
, в lego --key-type ec256
. Если требуется совместимость со старыми клиентами, держите параллельно RSA и ECDSA (dual‑cert через повтор ssl_certificate
директорий). Про базовую обвязку HTTPS и HSTS я писал в материале о настройке HTTPS, Certbot и HSTS.
DNS alias mode для кастомных доменов клиентов
Чтобы не просить у клиента DNS API ключ, используйте CNAME для валидации. Клиент создаёт:
_acme-challenge.client-domain.tld. CNAME _acme-challenge.client-domain.tld.your-saas.example.
ACME‑сервер при проверке TXT по _acme-challenge.client-domain.tld
следует CNAME и считывает TXT из вашей зоны. Дальше ваш автомат выставляет/убирает TXT только у себя. Этот подход поддерживается современными CA (Let’s Encrypt) и большинством ACME‑клиентов. Для lego есть параметр --dns.challenge-alias
, для других клиентов — свои флаги или «ручные» хуки.

Подводные камни и как их обойти
Лимиты ACME (Let’s Encrypt)
- До 50 сертификатов в неделю на зарегистрированный домен. Wildcard сильно экономит лимит: один сертификат покрывает весь зоопарк поддоменов.
- Дубликаты: не более 5 идентичных сертификатов в неделю. Изменяйте SAN только при необходимости, используйте продление.
- Стадия тестов: применяйте staging‑окружение для прогонов CI/CD и массовых проверок, чтобы не выжечь прод лимиты.
Пропагация TXT и split‑horizon DNS
- Плагины часто ждут распространения записей фиксированное время. Настройте таймауты под вашего провайдера и не экономьте на ожидании.
- Проверяйте TXT снаружи авторитетной зоны:
dig TXT _acme-challenge.example.com @8.8.8.8 +short
. Если у вас split‑horizon, убедитесь, что публичная зона содержит корректные записи.
Конкурентные запросы и гонки
- Ограничивайте параллелизм при массовом выпуске: lock‑файлы, очереди, бэк‑оффы. Два клиента, меняющих одну и ту же TXT, легко сломают проверку.
- Не смешивайте ручные TXT и автоматические. Держите директорию для ACME отдельно от «ручных» правок.
CAA записи
- Если в зоне настроен CAA, добавьте разрешение для CA, например
issue "letsencrypt.org"
, и при необходимостиiodef
для уведомлений. - Не забывайте зеркалить CAA при делегировании/миграции зон, иначе выпуск внезапно перестанет работать. Про переносы зон и SSL см. заметки о миграции домена, 301 и HSTS.
Безопасность токенов DNS API
- Минимальные права: только DNS‑редактирование в нужной зоне.
- Хранение секретов: права 600 на файлы, отдельный пользователь/группа, ограничение доступа к бэкапам и логам.
- Ротация токенов и контроль утечек: проверяйте какие узлы действительно используют токен, исключайте «мёртвые» копии.
Миграция между DNS‑провайдерами
- Заранее подготовьте плагин/интеграцию под нового провайдера.
- На время миграции увеличьте длительность сертов и при необходимости вручную продлите заранее, чтобы пережить возможные сбои API.
Тестирование и мониторинг
- Проверка цепочки и SNI:
openssl s_client -connect tenant.example.com:443 -servername tenant.example.com -showcerts
. - Зонд, считающий дни до истечения: экспортируйте срок в мониторинг и ставьте алерты за 21/14/7 дней.
- Логи прозрачности (CT): проверяйте, что выпускаются только ожидаемые сертификаты на ваши домены.
Рекомендации по производству
- Отдавайте предпочтение ECDSA, если нет строгой обратной совместимости — меньше CPU на рукопожатие.
- Делайте rollout сертов «вширь», а не «вглубь»: сначала выпустите, затем перезагрузите балансировщики по батчам.
- Для SaaS с on‑demand следите за кэшом ключей/сертов на диск и в память, чтобы рестарты процессов не провоцировали лавину выпусков.
- Используйте staging для регрессионных тестов конвейера certbot/lego после обновлений.
Краткая памятка
- Нужен wildcard? Значит DNS‑01.
- Apex + wildcard — один сертификат с двумя SAN.
- Кастомные домены клиентов — внедряйте DNS alias mode.
- Минимальные права токенам DNS API и строгий контроль доступа.
- Следите за лимитами Let’s Encrypt и используйте staging в тестах.
Итог: связка wildcard SSL + DNS‑01 + автоматизация через certbot или lego по DNS API надёжно масштабируется под мультисайты и SaaS. Ключ к успеху — аккуратная работа с секретами, продуманный пайплайн выдачи и мониторинг экспирации сертов. Тогда вопросы шифрования перестают быть проектом и превращаются в предсказуемую рутину.