Files
CDNManager/docs/deploy-traefik.md
T
DenozordecandCursor f063378e6b
quality / commitlint (push) Skipped
CD / update-wiki (push) Successful in 7s
quality / changes (push) Successful in 5s
quality / web (push) Skipped
quality / api (push) Skipped
quality / docker-check (push) Skipped
CD / quality (push) Successful in 6s
CD / publish (push) Successful in 31s
chore(deploy): добавить общий compose CDN и MikrotikManager с Traefik
Один стек для cdn.shnt.top и mm.shnt.top за общим Traefik.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-04 19:07:49 +07:00

6.4 KiB
Raw Blame History

Развёртывание CDN Manager + Traefik (один Docker Compose)

Один стек: Traefik (HTTPS, Let's Encrypt DNS-01 через Cloudflare) + cdnmanager (API + SPA, SQLite).

Образ git.shx.one/denozord/cdnmanager (алиас cdn-manager)
Runtime node:22-alpine, API + SPA + SQLite
Публичный URL https://cdn.shnt.top
Compose deploy/docker-compose.traefik.yml
Env-шаблон deploy/env.traefik.example
SSO integrate-auth-portal.md
Релизы releasing.md

CDN + MikrotikManager на одном Traefik: deploy/docker-compose.cdn-mm.yml + deploy/env.cdn-mm.examplecdn.shnt.top и mm.shnt.top, каталог /opt/cdn-mm.

Документация Traefik: Expose Docker, ACME DNS challenge.

Internet → :80/:443 (Traefik) → cdnmanager:8080
                ↑
         Cloudflare DNS TXT (ACME)

Предпосылки

  1. Зона домена в Cloudflare (например shnt.top).
  2. Docker Engine + Compose plugin на VPS.
  3. Свободные порты 80 и 443 на хосте (этот стек сам поднимает Traefik).
  4. docker login git.shx.one.
  5. Для SSO — работающий auth-portal с тем же JWT_SECRET / AUTH_ISSUER.

Если на сервере уже крутится другой Traefik на 80/443 — либо остановите его, либо смените TRAEFIK_HTTP_PORT / TRAEFIK_HTTPS_PORT. Два Traefik на одних портах не запустятся.


1. Cloudflare: токены и DNS

Два разных токена

Переменная Куда Назначение
CF_DNS_API_TOKEN контейнер Traefik ACME DNS-01 (TXT _acme-challenge)
CLOUDFLARE_API_TOKEN контейнер app Zone DNS Edit + Zone Read для sync флота

Можно один токен с нужными правами продублировать в обе переменные, либо разделить (рекомендуется least privilege).

API Tokens → Create Token — шаблон Edit zone DNS или Custom:

Permission Access
Zone → DNS Edit
Zone → Zone Read (желательно)

Zone Resources: Include → Specific zone → ваша зона. Не Global API Key, не в Git.

DNS-запись

Type Name Content Proxy
A / AAAA cdn IP VPS DNS only (серое облако)
dig +short cdn.shnt.top A

Traefik для сертификата создаёт TXT _acme-challenge.cdn… через Cloudflare API.


2. Файлы на сервере

mkdir -p /opt/cdnmanager/data
cd /opt/cdnmanager

# из репозитория:
#   cp deploy/docker-compose.traefik.yml docker-compose.yml
#   cp deploy/env.traefik.example .env

curl -fsSL -o docker-compose.yml \
  https://git.shx.one/denozord/CDNManager/raw/branch/main/deploy/docker-compose.traefik.yml
curl -fsSL -o .env \
  https://git.shx.one/denozord/CDNManager/raw/branch/main/deploy/env.traefik.example

nano .env   # заполнить секреты

Обязательные переменные в .env

Переменная Назначение
CF_DNS_API_TOKEN Cloudflare token для ACME DNS-01 (Traefik)
LETSENCRYPT_EMAIL Email для Let's Encrypt
CDN_DOMAIN Хост в Traefik rule, по умолчанию cdn.shnt.top
CLOUDFLARE_API_TOKEN Token приложения для DNS sync
AUTH_JWT_SECRET / JWT_SECRET = JWT_SECRET auth-portal (HS256)
AUTH_ISSUER https://auth.shnt.top
AUTH_PORTAL_URL URL UI портала

Опционально: CDN_IMAGE_TAG, TRAEFIK_IMAGE_TAG, TRAEFIK_HTTP_PORT, TRAEFIK_HTTPS_PORT, AUTH_AUDIT_INGEST_SECRET, AUTH_REQUIRED (default true).

На стороне портала добавьте origin в RETURN_TO_ALLOWLIST (https://cdn.shnt.top) и выдайте app cdn + права cdn:*. App Switcher URL: тот же origin.

Важно: AUTH_JWT_SECRET в CDN Manager должен совпадать с JWT_SECRET auth-portal, AUTH_ISSUERс ISSUER портала. Иначе после SSO UI зацикливается / «Страница не отвечает».


3. Запуск

cd /opt/cdnmanager
docker login git.shx.one
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f --tail=100

Проверка:

curl -fsS https://cdn.shnt.top/health
# {"status":"ok",…}

Откройте https://cdn.shnt.top → редирект на auth-portal → handoff на /auth/callback.


4. Обновление

cd /opt/cdnmanager
docker compose pull
docker compose up -d

Миграции SQLite применяются при старте API. Volume ./data сохраняется.


5. Остановка

docker compose down
# с удалением ACME volume (сертификаты перевыпустятся):
# docker compose down -v

Данные SQLite в ./data на хосте остаются, пока не удалите каталог.


Troubleshooting

Симптом Причина
Порт 80/443 занят другой Traefik/nginx; смените порты или хост
ACME timeout CF_DNS_API_TOKEN без DNS Edit; Cloudflare Proxy на A-записи (нужен DNS only)
SSO loop / 401 разный AUTH_JWT_SECRET / AUTH_ISSUER vs portal
403 «Нет доступа» у пользователя нет app cdn
return_to rejected https://cdn.shnt.top не в RETURN_TO_ALLOWLIST портала
Sync CF падает пустой/CLOUDFLARE_API_TOKEN без Zone DNS Edit

Без Traefik (plain docker run / простой Compose): deploy-docker.md.