Почему wildcard-сертификат не выпускался в mailcow 2026-03 и что именно исправили в 2026-03a
Если сразу после перехода на mailcow 2026-03 wildcard-сертификат по DNS-01 не выпускается, а в логе acme-mailcow ошибка «is redundant with a wildcard domain in the same request» — дело не в DNS-записях. Это баг первой версии DNS-01 в mailcow: MAILCOW_HOSTNAME попадал в запрос вместе с покрывающим его wildcard. Исправлен в 2026-03a через три дня. Разбираю ошибку, патч и чистую настройку.
Кейс: «Цветной оттиск» переходит на встроенный DNS-01 — и получает отказ
Типография «Цветной оттиск» — 41 рабочее место, у них mailcow работает третий год: заказы на печать приходят по почте, часть — с приложенными макетами по 40–60 МБ, и любой сбой почты сразу бьёт по производству, потому что менеджер не увидит новый заказ в очереди на печать вовремя. Мы ведём для них корпоративную почту на собственном сервере. Wildcard на домен у них был и раньше, но выпускался он в обход mailcow: на хосте жил certbot с DNS-плагином и самописным хуком, который копировал сертификат в data/assets/ssl и перезапускал контейнеры.
До релиза 2026-03 другого пути и не было: встроенный acme-mailcow умел только HTTP-01, а wildcard без DNS-01 не выпустить. В 2026-03 (10 марта 2026) разработчики добавили DNS-01 прямо в acme-mailcow (PR #6912 «acme: add DNS challenges»), и я решил убрать самописную связку — чем меньше внешних скриптов вокруг почтового сервера, тем меньше сюрпризов. 11 марта обновили mailcow, включили DNS-01, перечислили wildcard в ADDITIONAL_SAN — и acme-mailcow вместо сертификата выдал ошибку. Старый сертификат от certbot действовал ещё около трёх недель, так что паники не было, но и откладывать не хотелось.
Первое подозрение у коллеги, который делал переключение, было «мы что-то не так настроили в DNS или в токене API». На деле токен работал: TXT-записи в зоне создавались. Отказывал сам Let's Encrypt — на этапе, когда заказ сертификата ещё только формируется. Это важная подсказка: если ошибка приходит до проверки DNS, копать надо в список имён, а не в DNS-зону.
Почему wildcard сам по себе не покрывает всё — apex-домен и ADDITIONAL_SAN
Прежде чем разбирать баг, важно закрыть базовую вещь, которую путают чаще всего: сертификат на *.example.com не покрывает сам example.com — это прямо написано в документации mailcow про первые шаги с SSL и DNS. Домен без поддомена (апекс, он же корневой домен) — это отдельное имя с точки зрения TLS, и wildcard его не защищает, сколько бы поддоменов ни было закрыто.
Поэтому если вам нужен сертификат и на mail.tsvetnoy-ottisk.example, и на голый tsvetnoy-ottisk.example (например, для веб-морды на корневом домене), документация требует явно перечислить оба имени в переменной ADDITIONAL_SAN в mailcow.conf:
# mailcow.conf
ADDITIONAL_SAN=*.tsvetnoy-ottisk.example,tsvetnoy-ottisk.exampleДля DNS-01 в mailcow отвечает набор переменных в mailcow.conf: ACME_DNS_CHALLENGE=y включает проверку через DNS вместо HTTP, ACME_DNS_PROVIDER указывает плагин провайдера (в документации пример — dns_servercow, для DNS-хостинга Servercow; в шаблоне конфига стоит заглушка dns_xxx), ACME_ACCOUNT_EMAIL — адрес ACME-аккаунта. Учётные данные API провайдера кладутся отдельно в data/conf/acme/dns-01.conf. Именно в этой новой связке и сидел баг, который поймала типография.
Баг 2026-03: когда MAILCOW_HOSTNAME конфликтует с wildcard в одном запросе
В issue #7112 трекера mailcow-dockerized, открытом 10 марта 2026 года — в день выхода 2026-03, — описан ровно этот сценарий: MAILCOW_HOSTNAME=mail.example.com, а ADDITIONAL_SAN=*.example.com,example.com,*.example.email,example.email. Имя хоста — поддомен, покрытый wildcard из того же списка, и запрос сертификата у Let's Encrypt отваливается с ошибкой.
Ошибка, которую видит администратор в логе acme-mailcow, дословно звучит так: «Domain name "mail.example.com" is redundant with a wildcard domain in the same request. Remove one or the other from the certificate request.» — то есть сам сервер Let's Encrypt отказывается принимать запрос, где одновременно перечислены и конкретный поддомен, и wildcard, который его уже покрывает, потому что с точки зрения ACME это избыточность в одном запросе.
Логически это правильное поведение центра сертификации — Let's Encrypt не принимает в одном заказе и mail.example.com, и *.example.com, раз второе покрывает первое. Проблема была в том, что в первой версии DNS-01 генератор списка имён в acme-mailcow всегда добавлял MAILCOW_HOSTNAME в запрос, не проверяя, покрыт ли он wildcard из ADDITIONAL_SAN. Убрать hostname из запроса через настройки было нельзя — он обязателен, это основное имя сервера.
Мы посмотрели логи «Цветного оттиска» — картина совпала один в один с описанием issue #7112, вплоть до формулировки ошибки. Это сняло вопрос «может, я что-то сломал в DNS» и превратило задачу из отладки в ожидание патча или временный обход.
Что именно исправили в релизе 2026-03a
Патч вышел быстро — через три дня после открытия issue: релиз 2026-03a (Revision A) датирован 13 марта 2026 года и, по описанию, чинит проблемы с LDAP/Keycloak-входом и с новой функцией DNS-01. В список изменений вошли два ACME-исправления. Первое — PR #7124 «[ACME] Fix wildcard certificate conflict with MAILCOW_HOSTNAME» — прямое исправление конфликта между именем хоста и wildcard в одном запросе.
Второе — PR #7134 «[ACME] Skip autodiscover/mta-sts subdomains covered by wildcard certificates» — соседняя проблема из той же серии: mailcow по умолчанию добавляет в сертификат autodiscover. и autoconfig. для каждого домена (переменная AUTODISCOVER_SAN), а при включённом MTA-STS — и mta-sts.. При wildcard на тот же домен эти имена стали бы такой же избыточностью, и Let's Encrypt отверг бы заказ по той же причине. После патча покрытые wildcard имена из запроса пропускаются.
Для «Цветного оттиска» обновление до 2026-03a стало единственным нормальным решением — оно устранило причину, а не симптом. После ./update.sh и перезапуска сертификат выпустился с первой попытки, без ручной правки ADDITIONAL_SAN. Самописный certbot-хук мы удалили только после того, как убедились, что новый сертификат реально отдаётся на всех портах.
Обходной путь без обновления существовал — временно убрать из ADDITIONAL_SAN wildcard на домен хоста и перечислить нужные имена явно, а после обновления вернуть. Но у нас был запас по старому сертификату, а патч вышел всего через три дня после репорта — возиться с временными полумерами на продакшен-почте типографии в сезон заказов было рискованнее, чем подождать и обновиться один раз.
Как настроить DNS-01 и wildcard с нуля, чтобы не повторить чужие грабли
Если вы включаете DNS-01 впервые, порядок такой: сначала решаете, какие имена реально нужны в сертификате — MAILCOW_HOSTNAME (например mail.example.com), wildcard *.example.com для прочих имён домена и сам апекс, если он нужен. Версия mailcow — не ниже 2026-03a: в 2026-03 с hostname под wildcard вы гарантированно получите ошибку из issue #7112.
Дальше включаете саму DNS-проверку и провайдера в mailcow.conf:
# mailcow.conf
ACME_DNS_CHALLENGE=y
ACME_DNS_PROVIDER=dns_servercow
ACME_ACCOUNT_EMAIL=admin@tsvetnoy-ottisk.example
ADDITIONAL_SAN=*.tsvetnoy-ottisk.example,tsvetnoy-ottisk.exampleУчётные данные API провайдера прописываются не в mailcow.conf, а в /opt/mailcow-dockerized/data/conf/acme/dns-01.conf — для Servercow это SERVERCOW_API_Username и SERVERCOW_API_Password, для других провайдеров имена переменных берутся из документации соответствующего DNS-плагина. После правки конфигурации применяете изменения через docker compose up -d в каталоге /opt/mailcow-dockerized — пересоздастся контейнер acme-mailcow.
Правило, которое стоит держать в голове: не дублируйте в ADDITIONAL_SAN конкретные поддомены, если они уже покрыты вашим же wildcard. В 2026-03a mailcow сам убирает из запроса hostname и служебные autodiscover/autoconfig/mta-sts имена, но за собственные записи вроде *.example.com,imap.example.com отвечаете вы — Let's Encrypt отклонит такой заказ по той же причине избыточности.
Если вы разворачиваете mailcow с нуля, а не чините существующую установку, всю последовательность действий — от выбора хостинга до первого письма, которое не улетело в спам — я подробно расписывал в пошаговом регламенте развёртывания mailcow; там же DNS-01 и wildcard настраиваются в правильном порядке относительно остальных шагов, а не отдельно от них задним числом.
- MAILCOW_HOSTNAME — основное имя сервера; с 2026-03a, если его покрывает wildcard, mailcow не добавляет его в запрос отдельно
- ADDITIONAL_SAN — wildcard и апекс через запятую, без поддоменов, которые wildcard уже покрывает
- ACME_DNS_CHALLENGE=y — включает проверку через DNS вместо HTTP-01 на порту 80
- ACME_DNS_PROVIDER и ACME_ACCOUNT_EMAIL — плагин DNS-провайдера и адрес ACME-аккаунта
- data/conf/acme/dns-01.conf — учётные данные API провайдера
Как убедиться, что сертификат реально обновился, а не просто «нет ошибки»
Отсутствие свежей ошибки в логе — не то же самое, что выпущенный сертификат: следующая попытка может просто ещё не наступить. Поэтому я смотрю логи контейнера в реальном времени во время попытки выпуска:
docker compose logs -f acme-mailcowВ логе должно быть явное подтверждение получения сертификата, а не просто отсутствие новых строк. Дальше я проверяю, что реально отдаёт сервер — это надёжнее, чем верить логам на слово: echo | openssl s_client -connect mail.example.com:443 -servername mail.example.com 2>/dev/null | openssl x509 -noout -dates -ext subjectAltName покажет срок действия и список имён (ключ -ext есть в OpenSSL 1.1.1 и новее). Ту же проверку повторяю на 993 и 465 — IMAP и SMTP берут сертификат из того же каталога, но убедиться стоит.
Для «Цветного оттиска» после обновления мы дождались полного цикла выпуска (несколько минут на проверку TXT-записи центром сертификации) и закрыли задачу только тогда, когда openssl показал в SAN *.tsvetnoy-ottisk.example и tsvetnoy-ottisk.example, а срок действия — свежие 90 дней.
Частые ошибки при диагностике: не путайте баг 2026-03 с обычными проблемами DNS-01
Первая ошибка — сразу переписывать DNS-записи или менять DNS-провайдера, когда сертификат перестал выпускаться. Если ошибка в логе именно про «redundant with a wildcard domain», проблема не в DNS-записях и не в правах API-токена, а в списке SAN, который формирует сам mailcow — здесь версия сервера важнее, чем настройки DNS-зоны.
Вторая ошибка — путать этот баг с закрытым портом 80 при выборе HTTP-01 вместо DNS-01: это разные механизмы проверки, у них разные типовые ошибки, и симптом «сертификат не выпускается» у обеих настолько общий, что администраторы иногда начинают чинить не тот способ верификации. Если у вас порт 80 вообще закрыт на периметре и вы сознательно выбрали DNS-01 именно из-за этого, стоит отдельно свериться с тем, как выпустить сертификат при закрытом порте 80 — там другой набор типичных ошибок, не связанный с багом 2026-03.
Похожая путаница возникает и у администраторов, которые привыкли выпускать сертификаты для веба через certbot или встроенные механизмы Nginx и IIS — там логика продления Let's Encrypt устроена немного иначе, чем встроенный acme-mailcow, и переносить оттуда привычки диагностики один в один не всегда правильно: mailcow сам управляет своим ACME-клиентом внутри контейнера, а не полагается на системный certbot.
Третья ошибка — обновляться на 2026-03a вслепую, не читая release notes, если вы намеренно держите mailcow на старой ветке. Revision A точечная, но 2026-03 в целом — крупный релиз (в заголовке — принудительная 2FA, DNS-01, обновления SOGo и Rspamd), и перед ним я делаю бэкап через helper-scripts/backup_and_restore.sh и выбираю тихий день, а не пиковый день сдачи тиража.
Четвёртая — не проверять реальный результат выпуска, а полагаться на то, что «раз ошибок в логе больше нет, значит всё в порядке». Как я писал выше, отсутствие свежей ошибки не гарантирует новый сертификат, поэтому финальный критерий — вывод openssl s_client с нужными именами и датами, а не молчание лога.
Частые вопросы
Wildcard-сертификат покрывает корневой домен example.com?
Нет. *.example.com не покрывает сам example.com — документация mailcow прямо указывает на это. Если нужен и апекс-домен, его нужно явно добавить в ADDITIONAL_SAN вторым значением через запятую.
Почему wildcard-сертификат не выпускался в mailcow 2026-03?
Это баг первой версии встроенного DNS-01, появившегося в 2026-03: если MAILCOW_HOSTNAME — поддомен, покрытый wildcard из ADDITIONAL_SAN, mailcow включал в заказ оба имени, и Let's Encrypt отклонял его как избыточный. Описано в issue #7112 от 10 марта 2026 года.
Как исправить эту ошибку прямо сейчас?
Обновиться до 2026-03a от 13 марта 2026 года: там конфликт исправлен (PR #7124), а PR #7134 убирает из запроса autodiscover/mta-sts-имена, покрытые wildcard. Ручная правка ADDITIONAL_SAN нужна, только если вы сами перечислили поддомены под wildcard.
В чём разница между DNS-01 и HTTP-01 верификацией в mailcow?
DNS-01 подтверждает владение доменом через TXT-запись в DNS и включается переменной ACME_DNS_CHALLENGE=y с указанием провайдера в ACME_DNS_PROVIDER; HTTP-01 требует открытого порта 80. Ошибки редундантности SAN из бага 2026-03 относятся именно к DNS-01 и wildcard-доменам, а не к порту 80.
Как проверить, что сертификат реально обновился, а не просто исчезла ошибка из лога?
Смотреть docker compose logs -f acme-mailcow во время выпуска и затем проверить, что отдаёт сервер: openssl s_client -connect mail.example.com:443 с выводом через openssl x509 -noout -dates -ext subjectAltName. Отсутствие новых ошибок само по себе ничего не гарантирует.
Можно ли было выпустить wildcard в mailcow до 2026-03?
Встроенным acme-mailcow — нет: DNS-01 добавили только в релизе 2026-03 (PR #6912), а без DNS-01 Let's Encrypt wildcard не выдаёт. Раньше wildcard получали внешним клиентом и подкладывали как собственный сертификат.
Источники
- mailcow docs: SSL — DNS Challenge and Wildcard Certificates — Переменные ACME_DNS_CHALLENGE, ACME_DNS_PROVIDER (пример dns_servercow), ACME_ACCOUNT_EMAIL, файл data/conf/acme/dns-01.conf, пример ADDITIONAL_SAN=*.example.com,example.com, wildcard не покрывает апекс, docker compose logs -f acme-mailcow. https://docs.mailcow.email/post_installation/firststeps-ssl-dns/
- GitHub mailcow-dockerized issue #7112 — ACME: DNS-01 Challenge and Wildcard Domains — Открыт 10 марта 2026 года; дословная ошибка Let's Encrypt о редундантности домена с wildcard в одном запросе при MAILCOW_HOSTNAME, покрытом ADDITIONAL_SAN. https://github.com/mailcow/mailcow-dockerized/issues/7112
- GitHub mailcow-dockerized — релиз 2026-03a — Revision A от 13.03.2026: PR #7124 «[ACME] Fix wildcard certificate conflict with MAILCOW_HOSTNAME», PR #7134 «[ACME] Skip autodiscover/mta-sts subdomains covered by wildcard certificates». https://github.com/mailcow/mailcow-dockerized/releases/tag/2026-03a
- GitHub mailcow-dockerized — релиз 2026-03 — Релиз от 10.03.2026, в котором DNS-01 впервые добавлен в acme-mailcow: «acme: add DNS challenges», PR #6912. https://github.com/mailcow/mailcow-dockerized/releases/tag/2026-03
- mailcow: шаблон mailcow.conf (generate_config.sh) — ACME_DNS_CHALLENGE=n, ACME_DNS_PROVIDER=dns_xxx, ACME_ACCOUNT_EMAIL по умолчанию; комментарии к ADDITIONAL_SAN. https://github.com/mailcow/mailcow-dockerized/blob/master/generate_config.sh



