MAATRIX / Блог / Coolify не выдаёт SSL-сертификат: причины и решение

Coolify не выдаёт SSL-сертификат: причины и решение

Coolify не выдаёт SSL-сертификат: причины и решение

MAATRIX

Домен привязан, приложение задеплоено, а браузер показывает NET::ERR_CERT_AUTHORITY_INVALID и сертификат с именем TRAEFIK DEFAULT CERT. Это значит одно из двух: Coolify либо вообще не попросил сертификат у Let's Encrypt, либо попросил и получил отказ. Поломки разные — ниже как за пять минут понять, какая у вас.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Быстрая диагностика: три команды, которые называют причину

Начните с того, что реально отдаёт сервер:

openssl s_client -connect app.example.com:443 -servername app.example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject -dates

Сертификат не выпущен — увидите заглушку issuer=CN = TRAEFIK DEFAULT CERT и такой же subject. Рабочий вариант: issuer=C = US, O = Let's Encrypt, CN = R11 и ровно 90 дней в notAfter.

Дальше журнал прокси — весь ACME-обмен идёт через Traefik, и он пишет причину отказа открытым текстом. И хранилище: Coolify держит его в /data/coolify/proxy/acme.json, резолвер — letsencrypt.

docker logs coolify-proxy --since 30m 2>&1 | grep -iE 'acme|certificate|unable' | tail -20
jq -r '.letsencrypt.Certificates[].domain.main' /data/coolify/proxy/acme.json

Пустой вывод jq — сертификата нет. Сверьтесь с таблицей:

Что видно в логахПричина
Ни строки acme про ваш доменнет TLS-роутера — секция 2
Invalid response ... : 404запрос идёт не на ваш сервер — секция 3
Timeout during connect (likely firewall problem)80-й порт закрыт — секция 4
permissions 644 for /traefik/acme.json are too openправа на хранилище — секция 5
urn:ietf:params:acme:error:rateLimitedлимит Let's Encrypt — секция 6

Причина №1: домен без схемы https:// — Coolify даже не пробовал

Самый частый случай, когда Coolify SSL не работает, вообще не связан с Let's Encrypt. Coolify собирает метки Traefik из поля Domains и решает по схеме URL. Если там app.example.com или http://app.example.com, создаётся только HTTP-роутер: метки tls и certresolver не появляются, запрос в удостоверяющий центр не уходит никогда, а в логах прокси идеальная тишина.

Проверяется одной командой по контейнеру приложения:

docker inspect <имя_контейнера> \
  --format '{{range $k,$v := .Config.Labels}}{{$k}}={{$v}}{{"\n"}}{{end}}' \
  | grep -i traefik | sort

Рабочий набор обязан содержать строки такого вида:

traefik.enable=true
traefik.http.routers.https-0-r8ck0cs.entrypoints=https
traefik.http.routers.https-0-r8ck0cs.rule=Host(`app.example.com`) && PathPrefix(`/`)
traefik.http.routers.https-0-r8ck0cs.tls.certresolver=letsencrypt

Только роутеры http-0- и ни одного https-0- — дело в схеме. Впишите домен как https://app.example.com и сделайте Redeploy, а не Restart: метки вшиваются в контейнер при создании.

То же для домена панели — Settings → Instance Domain тоже начинается с https://. Сохранили туда домен до того, как разошёлся DNS, и потеряли доступ — верните APP_URL=http://<ваш-ip>:8000 в /data/coolify/source/.env и поднимите контейнер заново через docker compose up -d --force-recreate coolify.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Coolify

DNS: AAAA-ловушка, CAA и оранжевое облако Cloudflare

Let's Encrypt проверяет владение доменом по HTTP — домен обязан вести именно на ваш сервер. Смотрим три записи:

dig +short A    app.example.com @1.1.1.1
dig +short AAAA app.example.com @1.1.1.1
dig +short CAA  example.com     @1.1.1.1
curl -s https://api.ipify.org

A-запись должна совпасть с выводом последней команды. Частая история: домен переехал, но у регистратора остались две A-записи. Валидация тогда попадает на старый хост через раз, и в логах мигают 404.

AAAA — главная ловушка. Let's Encrypt предпочитает IPv6, и если AAAA есть, а IPv6 на сервере не работает или Docker не публикует на нём порты, в логе будет:

acme: error: 400 :: urn:ietf:params:acme:error:connection :: Fetching http://app.example.com/
.well-known/acme-challenge/mQ8f...: Timeout during connect (likely firewall problem)

Проще всего удалить AAAA до выпуска сертификата. Нужен IPv6 — включайте честно: "ip6tables": true в /etc/docker/daemon.json и рабочий адрес на интерфейсе.

CAA задаёт, каким центрам разрешено выпускать сертификаты для домена. Вернулось 0 issue "digicert.com" — Let's Encrypt откажет с urn:ietf:params:acme:error:caa. Добавьте 0 issue "letsencrypt.org" либо уберите CAA целиком.

Cloudflare с оранжевым облаком даёт самую запутанную картину: браузер видит валидный сертификат Cloudflare, но на origin сертификата нет, и в режиме Full (strict) сайт отдаёт 526 Invalid SSL certificate. Быстрый путь: переключите запись в DNS only, дождитесь появления домена в acme.json, потом верните проксирование.

Примета 2026 года: с 2025-го Let's Encrypt проверяет домен из нескольких географических точек сразу. Есть в ошибке During secondary validation: — сервер доступен не отовсюду, типичная картина для IP из фильтруемых диапазонов. Лечится не настройками, а адресом.

Порт 80 занят или закрыт снаружи

Coolify использует HTTP-01: Let's Encrypt стучится на http://ваш-домен/.well-known/acme-challenge/<токен> по 80-му порту. Без него сертификата не будет, даже если сайт работает по 443-му. Здоровый вывод — оба порта за docker-proxy:

ss -tlnp | grep -E ':(80|443) '
LISTEN 0 4096 0.0.0.0:80  0.0.0.0:* users:(("docker-proxy",pid=1442,fd=7))
LISTEN 0 4096 0.0.0.0:443 0.0.0.0:* users:(("docker-proxy",pid=1461,fd=7))

Видите там nginx или apache2 — прокси Coolify не поднялся, и в docker logs coolify-proxy будет Bind for 0.0.0.0:80 failed: port is already allocated. Освободите порт (systemctl disable --now nginx) и нажмите Servers → сервер → Proxy → Restart.

Проверьте доступность снаружи, с телефона по мобильному интернету:

curl -sS -m 10 -o /dev/null -w '%{http_code} %{remote_ip}\n' \
  http://app.example.com/.well-known/acme-challenge/probe

Ожидаемый ответ — 404 203.0.113.10. Именно 404: его отдаёт Traefik, то есть запрос дошёл. Пустой вывод или таймаут — трафик режется по дороге.

Честная оговорка: Docker публикует порты своими цепочками iptables и обходит ufw, так что ufw allow 80/tcp тут ничего не решает — снаружи режет фаервол провайдера или security group.

Ошибки внутри Traefik: acme.json, права и staging

Даже при исправных DNS и портах Traefik может молча отказаться от хранилища:

level=error msg="The ACME resolver \"letsencrypt\" is skipped from the resolvers list because:
unable to get ACME account: permissions 644 for /traefik/acme.json are too open, please use 600"

Права слетают после rsync без -p, после scp или распаковки архива без --same-permissions. Чинится строкой chmod 600 /data/coolify/proxy/acme.json && docker restart coolify-proxy.

Второй вариант — файл побился: Unable to read ACME storage: unexpected end of JSON input. Третий — застрявшая запись: сертификат есть, но битый или достался от прошлого сервера. Вырежьте один домен вместо сброса всего файла, чтобы не потратить недельный лимит на остальные:

docker stop coolify-proxy
cp /data/coolify/proxy/acme.json /root/acme.json.bak
jq '.letsencrypt.Certificates |= map(select(.domain.main != "app.example.com"))' \
  /root/acme.json.bak > /data/coolify/proxy/acme.json
chmod 600 /data/coolify/proxy/acme.json && docker start coolify-proxy

Файл нечитаем целиком — echo '{}' > /data/coolify/proxy/acme.json и те же права, но все сертификаты пойдут на перевыпуск.

Четвёртый вариант — остался тестовый удостоверяющий центр. Признак: ошибка доверия, а эмитент выглядит как CN = (STAGING) Pretend Pear X1. Уберите строку caserver из /data/coolify/proxy/docker-compose.yml, сделайте docker compose up -d --force-recreate и очистите хранилище: staging-аккаунт лежит в том же acme.json.

И проверьте свои файлы в /data/coolify/proxy/dynamic/: одна ошибка отступа — и Traefik игнорирует всю динамическую конфигурацию с yaml: line 7: mapping values are not allowed in this context.

Лимиты Let's Encrypt, wildcard и свой сертификат

Если вы полдня передеплоиваете приложение, вы почти наверняка упёрлись в лимиты: 50 новых сертификатов на зарегистрированный домен в неделю, 5 повторных выпусков на один и тот же набор имён за 168 часов, 5 неудачных валидаций на связку аккаунт+домен в час. Текст отказа однозначный:

urn:ietf:params:acme:error:rateLimited :: too many certificates (5) already issued for this
exact set of identifiers in the last 168h0m0s

Сколько выпущено, видно в логе прозрачности — https://crt.sh/?q=example.com. Обойти лимит нельзя, окно придётся переждать. Отлаживать домен правильнее на тестовом acme-staging-v02.api.letsencrypt.org, где лимиты в разы выше, а потом убрать флаг и очистить acme.json.

Wildcard через HTTP-01 не выпускается в принципе: *.example.com требует DNS-01. Из интерфейса это не настраивается — надо править /data/coolify/proxy/docker-compose.yml: токен провайдера в environment плюс флаг --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare. Минус честно: Coolify считает файл своим и может перезаписать его при перезапуске прокси из UI.

Свой сертификат — купленный или корпоративный — подключается отдельным файлом динамической конфигурации. Каталог /data/coolify/proxy смонтирован в контейнер как /traefik, поэтому файлы кладут в /data/coolify/proxy/certs/:

# /data/coolify/proxy/dynamic/custom-ssl.yaml
tls:
  certificates:
    - certFile: /traefik/certs/example.com.crt
      keyFile: /traefik/certs/example.com.key

Про продление: Traefik обновляет сертификат за 30 дней до конца срока сам, без cron. Но Let's Encrypt с середины 2025 года не рассылает письма об истечении — заведите свою проверку openssl x509 -noout -enddate в cron. Появившиеся тогда же шестидневные сертификаты Coolify по умолчанию не использует, и для боевого сайта это к лучшему: шесть дней не прощают ошибок в автопродлении.

Какой сервер нужен под Coolify, чтобы SSL выдавался сразу

Половина историй «Coolify не выдаёт сертификат» — это не Coolify, а сервер: закрытый 80-й порт, серый IP, забитый диск.

Минимум — 2 vCPU, 4 ГБ RAM, 60 ГБ NVMe. Формально Coolify стартует и на 2 ГБ, но стек самой панели (приложение, PostgreSQL, Redis, сервис реального времени и прокси) в покое занимает около 1 ГБ — на сборках памяти не остаётся. Деплой падает с коротким Killed, а правду видно в журнале ядра:

dmesg -T | grep -i 'out of memory'
[Fri Aug 28 12:41:07 2026] Out of memory: Killed process 2261 (node) total-vm:3184920kB

Упираетесь только на сборках — своп дешевле апгрейда: fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile.

Комфортный вариант — 4 vCPU, 8 ГБ RAM, 160 ГБ NVMe. Панель, десяток приложений, база рядом и параллельные сборки без OOM. Диск связан с темой статьи напрямую: образы и кэш растут быстро, а когда раздел заполняется, Traefik не может записать хранилище — unable to save ACME account: write /traefik/acme.json: no space left on device, и продление тихо перестаёт работать. Следите за docker system df. Расклад по памяти — в материале про требования Coolify к серверу.

Обязательные условия для SSL: белый статический IPv4, открытые входящие 80 и 443, чистая репутация адреса. На этом спотыкаются домашние серверы за NAT и дешёвые VPS с адресами из «грязных» подсетей.

Локация. Для европейской и мировой аудитории берите UK, Лондон: RTT до Франкфурта 10–15 мс, до Амстердама 8–12 мс, IP не попадает в региональные фильтры, плюс GDPR-соседство. Российская аудитория и 152-ФЗ — RU, но заранее проверьте, что входящий 80-й порт не фильтруется. Приложения ходят в OpenAI или Anthropic — US с чистым адресом.

В MAATRIX сервер под Coolify поднимается за несколько минут — белый статический IP, открытые 80/443, локации UK, US, FR и RU, выбрать конфигурацию можно сразу под задачу. Оплата картой российского банка, по СБП, криптой или токеном MAAT: иностранная карта не нужна даже для Лондона. Если Coolify ещё не стоит — начните с установки и настройки, остальные грабли собраны в разборе частых ошибок Coolify.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Coolify

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Сайт открывается по HTTPS, но браузер ругается на сертификат.

Проверьте эмитента через openssl x509 -noout -issuer. TRAEFIK DEFAULT CERT означает, что сертификат так и не выпущен, а (STAGING) Pretend Pear X1 — что в конфиге прокси остался тестовый CA.

Поменял домен, а сертификат не появился.

Метки Traefik пишутся в контейнер при создании, поэтому нужен Redeploy, а не Restart. И домен должен быть указан со схемой https:// — иначе TLS-роутер не создаётся вовсе.

Можно ли обойти лимит, если упёрся в 429?

Нет, окно в 168 часов придётся переждать. Пока ждёте, отлаживайте домен на staging-сервере ACME или подключите свой сертификат через /data/coolify/proxy/dynamic/custom-ssl.yaml.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.