# CDN Manager Self-hosted панель **desired-state DNS** для флота CHR/VPS: канонические ноды (A/AAAA) + сервисные CNAME (failover / geo / ix), синхронизация с Cloudflare DNS-only. ## Vs CFDM | CDNManager | Cloudflare Domain Manager | |------------|---------------------------| | Флот нод + алиасы + drift/orphan | Домены, сервисы, LB, health-checks, сертификаты | | Роутинг-зона (напр. `rtnt.top`) | Мультидоменный ops | | Retarget CNAME как основной UX | Service bindings / HC | App id в auth-portal: **`cdn`**. ## Стек - Monorepo: pnpm + turbo (`apps/*`, `packages/*`) - `apps/web` — Vite + React + TanStack + shadcn **base-nova** + ReUI Frame - `apps/api` — Fastify + Drizzle + SQLite - Packages: `@cdnmanager/ui`, `@cdnmanager/shared`, `@cdnmanager/db` ## Доменная модель - **Location** — справочник кодов (`msk`, `fra`, `ams`, `hel`, `par`) - **Node** — канонический FQDN + A/AAAA (`msk-hub01.rtnt.top`) - **Alias** — CNAME → node (`msk.rtnt.top`, `ix-eu.rtnt.top`) - **Zone** — Cloudflare zone + naming template / TTL - Managed-записи всегда **`proxied: false`** (туннели WG/GRE) Нейминг: шаблон `{loc}-{role}{nn}.{zone}` (см. документ по CHR DNS). ## Команды ```bash pnpm install pnpm --filter @cdnmanager/shared build pnpm --filter @cdnmanager/db build pnpm --filter @cdnmanager/api dev # :8081 pnpm --filter web dev # :5176 pnpm --filter web build ``` Env: `CLOUDFLARE_API_TOKEN` (Zone DNS Edit + Zone Read). Локально `AUTH_REQUIRED=false`, логин `admin` / `admin`. SSO (prod): [`docs/integrate-auth-portal.md`](docs/integrate-auth-portal.md) — `AUTH_REQUIRED=true`, общий `AUTH_JWT_SECRET` с portal, app id `cdn`. Docker CLI на сервере: [`docs/deploy-traefik.md`](docs/deploy-traefik.md) (Traefik + HTTPS) · [`docs/deploy-docker.md`](docs/deploy-docker.md) (plain). ## UI (ReUI PRO + DNA CFDM) Surface: **frame**. Contract: [`docs/ui-design-contract.md`](docs/ui-design-contract.md). | Экран | Kit / pattern | |-------|----------------| | Dashboard | `OpsDashboard` + `KpiStatGrid` + `QuickActionGrid` + charts + `AttentionQueue` (как CFDM) | | Ноды / Алиасы | `ResourcePage` | | Топология | Frame grid + IconTile | | Зоны / Sync | Frame Item rows + sync/apply/BIND export | | Settings | `SettingsShell` (appearance + cloudflare) | Preview: [stats-12](https://reui.io/preview/base/stats-12) · [data-grid-filtering-2](https://reui.io/preview/base/data-grid-filtering-2) · [settings-16](https://reui.io/preview/base/settings-16) · [app-shell-12](https://reui.io/preview/base/app-shell-12). MCP `user-reui` primary + `plugin-shadcn-shadcn` primitives. License: `REUI_LICENSE_KEY` в `apps/web/.env.local`. ## API (кратко) ``` GET/POST /api/v1/zones · POST .../sync · POST .../apply · GET .../export/bind GET/POST /api/v1/nodes · GET/POST /api/v1/aliases · POST .../retarget GET /api/v1/locations · GET /api/v1/dashboard/stats · GET /api/v1/topology GET /api/v1/cloudflare/zones ``` ## CI / Docker Gitea: `.gitea/workflows/{ci,cd,quality}.yaml`. Образы: `deploy/docker` (`cdnmanager` + alias `cdn-manager`). Prod: [`docs/deploy-traefik.md`](docs/deploy-traefik.md) — `deploy/docker-compose.traefik.yml` + `deploy/env.traefik.example`. Без Traefik: [`docs/deploy-docker.md`](docs/deploy-docker.md) · Compose: `docker-compose.yml` / `deploy/compose/docker-compose.example.yaml`. **Коммиты:** только Conventional Commits (`feat`/`fix`/… + русский subject). Иначе CD: `No releasable commits — skipping image publish`. См. [`.cursor/rules/commit-messages-ru.mdc`](.cursor/rules/commit-messages-ru.mdc), [`docs/releasing.md`](docs/releasing.md).