# Запуск CDN Manager на сервере (Docker CLI) Без Traefik (plain `docker run` / простой Compose). **Production HTTPS:** [`deploy-traefik.md`](./deploy-traefik.md). ## Traefik (кратко) ```bash mkdir -p /opt/cdnmanager/data cp deploy/docker-compose.traefik.yml /opt/cdnmanager/docker-compose.yml cp deploy/env.traefik.example /opt/cdnmanager/.env docker login git.shx.one cd /opt/cdnmanager && docker compose pull && docker compose up -d ``` Один alpine-контейнер: API + SPA + SQLite. Образы `cdnmanager` и `cdn-manager` — один манифест (drop-in alias). Registry по умолчанию: `git.shx.one/denozord/…` (подставьте свой owner при необходимости). ## Требования - Docker Engine 24+ (или Docker Desktop) - Cloudflare API token: **Zone DNS Edit** + **Zone Read** - Для SSO: auth-portal с тем же `JWT_SECRET` / `AUTH_ISSUER` и origin CDNManager в `RETURN_TO_ALLOWLIST` ## 1. Pull образа ```bash docker pull git.shx.one/denozord/cdnmanager:latest # эквивалент (тот же образ): docker pull git.shx.one/denozord/cdn-manager:latest ``` Тег релиза: `vX.Y.Z` или `X.Y.Z` (см. Gitea Releases). ## 2. Запуск одной командой (`docker run`) ### Dev / без portal (локальный admin) ```bash docker volume create cdnmanager-data docker run -d \ --name cdnmanager \ --restart unless-stopped \ -p 8080:8080 \ -v cdnmanager-data:/data \ -e DATABASE_URL=sqlite:/data/app.db \ -e STATIC_DIR=/app/static \ -e SERVER_PORT=8080 \ -e AUTH_REQUIRED=false \ -e JWT_SECRET=change-me-in-production \ -e ADMIN_USERNAME=admin \ -e CLOUDFLARE_API_TOKEN=cf_xxxxxxxx \ git.shx.one/denozord/cdnmanager:latest ``` Логин UI: `admin` / `admin` (если `ADMIN_PASSWORD_HASH` пуст — dev default). ### Production + auth-portal SSO ```bash docker volume create cdnmanager-data docker run -d \ --name cdnmanager \ --restart unless-stopped \ -p 8080:8080 \ -v cdnmanager-data:/data \ -e DATABASE_URL=sqlite:/data/app.db \ -e STATIC_DIR=/app/static \ -e SERVER_PORT=8080 \ -e AUTH_REQUIRED=true \ -e JWT_SECRET='<тот же секрет что у auth-portal>' \ -e AUTH_JWT_SECRET='<тот же секрет>' \ -e AUTH_ISSUER=https://auth.shnt.top \ -e AUTH_PORTAL_URL=https://auth.shnt.top \ -e AUTH_AUDIT_INGEST_SECRET='' \ -e CLOUDFLARE_API_TOKEN=cf_xxxxxxxx \ -e LOG_LEVEL=info \ git.shx.one/denozord/cdnmanager:latest ``` Проверка: ```bash curl -sS http://127.0.0.1:8080/health # {"status":"ok",…} ``` Откройте `http://:8080` → редирект на auth-portal → после логина handoff на `/auth/callback`. ## 3. Docker Compose Файлы в репозитории: - корневой [`docker-compose.yml`](../docker-compose.yml) - пример [`deploy/compose/docker-compose.example.yaml`](../deploy/compose/docker-compose.example.yaml) Создайте `.env` рядом с compose: ```env JWT_SECRET=change-me-strong AUTH_REQUIRED=true AUTH_JWT_SECRET=change-me-strong AUTH_ISSUER=https://auth.shnt.top AUTH_PORTAL_URL=https://auth.shnt.top AUTH_AUDIT_INGEST_SECRET=change-me-audit CLOUDFLARE_API_TOKEN=cf_xxxxxxxx ADMIN_USERNAME=admin ``` ```bash # из корня репозитория или каталога с compose docker compose pull docker compose up -d docker compose ps docker compose logs -f --tail=100 ``` Остановка: ```bash docker compose down # данные в volume сохраняются; удалить volume: # docker compose down -v ``` ## 4. За reverse proxy (Traefik / Caddy) Пробросьте HTTPS на контейнер `:8080`. Пример labels Traefik (Host `cdn.shnt.top`): ```yaml labels: - traefik.enable=true - traefik.http.routers.cdnmanager.rule=Host(`cdn.shnt.top`) - traefik.http.routers.cdnmanager.entrypoints=websecure - traefik.http.routers.cdnmanager.tls=true - traefik.http.services.cdnmanager.loadbalancer.server.port=8080 ``` На auth-portal добавьте в `RETURN_TO_ALLOWLIST`: `https://cdn.shnt.top`. В Admin → Apps выставьте URL App Switcher для `cdn` на этот origin. ## 5. Обновление ```bash docker pull git.shx.one/denozord/cdnmanager:latest docker stop cdnmanager && docker rm cdnmanager # затем снова docker run … (тот же volume /data) ``` Или: ```bash docker compose pull docker compose up -d ``` Миграции SQLite применяются при старте API автоматически. ## 6. Сборка своего образа (опционально) См. [`deploy/docker/README.md`](../deploy/docker/README.md) — `docker buildx bake` из `deploy/docker`. ## Переменные окружения | Переменная | Обязательно | Описание | |------------|-------------|----------| | `DATABASE_URL` | да | `sqlite:/data/app.db` | | `STATIC_DIR` | да (prod) | `/app/static` — SPA | | `SERVER_PORT` | нет | default `8080` в образе / `8081` в local `.env` | | `CLOUDFLARE_API_TOKEN` | для sync | Zone DNS Edit + Zone Read | | `AUTH_REQUIRED` | prod SSO | `true` | | `AUTH_JWT_SECRET` / `JWT_SECRET` | при SSO | = portal | | `AUTH_ISSUER` | при SSO | = portal `ISSUER` | | `AUTH_PORTAL_URL` | при SSO | URL UI портала | | `AUTH_AUDIT_INGEST_SECRET` | опц. | dual-write audit | | `ADMIN_*` | только `AUTH_REQUIRED=false` | локальный admin | Подробнее SSO: [`integrate-auth-portal.md`](./integrate-auth-portal.md).