Привет, @LotusJeff,
Да, валидация через DNS по-прежнему работает, но, пожалуйста, больше не используйте шаблон из моего первого поста. Он устарел по сравнению с текущей версией discourse_docker:
- Проверка
cert_existsв нём не проходит с текущей цепочкой Let’s Encrypt, поэтому он принудительно запрашивает новые сертификаты при каждом запуске контейнера, что может привести к достижению лимита на дублирование сертификатов. - Шаги
replaceдля nginx нацелены на строки, которые переместились, а шаг сadd_headerтеперь перезаписывает несвязанный заголовокETag.
Теперь вам не нужен пользовательский шаблон. Оставьте стандартный шаблон Let’s Encrypt и переключите его на валидацию через DNS в app.yml:
templates:
# ...
- "templates/web.ssl.template.yml"
- "templates/web.letsencrypt.ssl.template.yml"
env:
# ...
CF_Token: "YOUR_TOKEN" # API-токен Cloudflare с правами Zone > DNS > Edit для этой зоны
CF_Zone_ID: "YOUR_ZONE_ID"
run:
- exec:
cmd:
- mkdir -p /opt/dnsapi
- curl -fsSL https://raw.githubusercontent.com/acmesh-official/acme.sh/3.0.6/dnsapi/dns_cf.sh -o /opt/dnsapi/dns_cf.sh
- replace:
filename: /usr/local/bin/letsencrypt
from: "-w /var/www/discourse/public"
to: "--dns dns_cf"
Что это делает:
- Стандартный шаблон загружает только основной скрипт
acme.shбез плагинов для DNS. Шагexecдобавляет плагин Cloudflare, а стандартный скрипт запуска копирует его в/shared/letsencrypt/dnsapi/. Убедитесь, что версия в URL совпадает с версией acme.sh, указанной вtemplates/web.letsencrypt.ssl.template.yml(на данный момент это 3.0.6). - Секция
run:выполняется после применения шаблонов, поэтомуreplaceпереключает стандартный скрипт запуска с HTTP-валидации на DNS-валидацию. - При валидации acme.sh читает
CF_TokenиCF_Zone_IDиз окружения и сохраняет их вместе с сертификатом. Ежедневная задача cron не видит окружение контейнера, поэтому при обновлении сертификатов используется эта сохраненная копия.
Если вы использовали мой старый шаблон, удалите его строку из секции templates: и переименуйте переменные LETSENCRYPT_CF_TOKEN и LETSENCRYPT_CF_ZONE_ID в CF_Token и CF_Zone_ID.
Если у вас уже есть сертификаты (полученные через HTTP-валидацию или с помощью моего старого шаблона), переместите старую папку acme.sh в сторону перед пересборкой:
cd /var/discourse
mv shared/standalone/letsencrypt shared/standalone/letsencrypt.old
./launcher rebuild app
Без этого acme.sh может пропустить шаг с DNS (он сохраняет старый метод до тех пор, пока не наступит срок обновления, а Let’s Encrypt может повторно использовать недавнюю валидацию). В таком случае токен никогда не сохраняется, и первое обновление по cron завершается ошибкой. При использовании чистой папки acme.sh регистрирует новый аккаунт и выполняет реальную DNS-валидацию, поэтому первый запуск займет примерно на минуту больше.
Не удаляйте папку .old, пока новые сертификаты не заработают корректно. Если шаг с DNS завершится ошибкой, скрипт запуска все равно перезапишет файлы в shared/ssl, и nginx не запустится.
acme.sh сохраняет токен в виде простого текста в папке shared/standalone/letsencrypt/, поэтому выдавайте токену только необходимые разрешения.
Протестировано с discourse_docker и Discourse latest по состоянию на ноябрь 2026 года.