NODEDC_PLATFORM/infra/synology
Codex 385e2732e8 feat: sync platform ai workspace services 2026-06-13 11:34:40 +03:00
..
tasker-overlays/logo-link-brand-hotfix OPS - TASKER: capture editable logo link overlay 2026-05-14 16:25:20 +03:00
.env.synology.example feat: sync platform ai workspace services 2026-06-13 11:34:40 +03:00
Caddyfile.http fix(platform): isolate authentik admin styling 2026-05-25 01:08:50 +03:00
README.md feat: sync platform ai workspace services 2026-06-13 11:34:40 +03:00
apply-current-runtime.sh fix: document deployed ai workspace hub contract 2026-06-09 15:48:04 +03:00
backup-current.sh Add platform AI Workspace Hub 2026-05-30 13:28:23 +03:00
clear-authentik-brand-css.sh fix(platform): isolate authentik admin styling 2026-05-25 01:08:50 +03:00
deploy-current.sh feat: add shared ai workspace assistant service 2026-06-09 11:43:58 +03:00
docker-compose.platform-http.yml feat: sync platform ai workspace services 2026-06-13 11:34:40 +03:00
verify-current-runtime.sh fix: document deployed ai workspace hub contract 2026-06-09 15:48:04 +03:00

README.md

NODE.DC Synology deploy

Эта папка фиксирует текущий воспроизводимый NAS-deploy для nodedc-platform на Synology RS1221RP+.

Правила

  • Не выполнять docker stop, docker restart, docker compose down, docker system prune для старых проектов.
  • Новый compose project: nodedc-platform.
  • Новая папка на NAS: /volume1/docker/nodedc-platform.
  • Внутренний HTTP edge использует 18080, AI Workspace Hub — 18081, Tasker upstream — 18090, Ops Agents Gateway upstream — 18190.
  • Старые порты 9000 и 5678 заняты старым nodedc-demo и не используются.

Текущие внешние домены

https://id.nodedc.ru  -> Authentik
https://hub.nodedc.ru -> Launcher / Hub
https://ops.nodedc.ru -> Tasker / Operational Core
https://ops-agents.nodedc.ru -> Ops Agents Gateway / MCP
https://ai-hub.nodedc.ru -> AI Workspace Hub / WebSocket relay

id.nodedc.ru is the user-facing OIDC/login host. Authentik Admin is intentionally not exposed through this public host; /if/admin/* returns 404 there.

ai-hub.nodedc.ru is intentionally routed by Synology DSM Reverse Proxy directly to 172.22.0.222:18081, because this endpoint must carry WebSocket Upgrade traffic for remote Codex agents.

В Caddyfile.http эти домены проксируются через локальный HTTP edge, но upstream получает X-Forwarded-Proto: https и X-Forwarded-Port: 443.

AI Workspace Hub / Assistant contract

ai-workspace-hub remains a thin public WebSocket relay. It is the only AI Workspace service exposed through DSM/Nginx as https://ai-hub.nodedc.ru.

ai-workspace-assistant is an internal platform service for per-user executors, selected device, shared threads and installer generation. It must not be exposed as a public route. Launcher, Engine and Tasker use it through Docker networking:

NODEDC_AI_WORKSPACE_ASSISTANT_URL=http://ai-workspace-assistant:18082
PLANE_NODEDC_AI_WORKSPACE_ASSISTANT_URL=http://ai-workspace-assistant:18082

Installer generation must always point remote Codex workers to the deployed Hub:

AI_WORKSPACE_HUB_PUBLIC_URL=wss://ai-hub.nodedc.ru/api/ai-workspace/hub
AI_WORKSPACE_HUB_INTERNAL_URL=https://ai-hub.nodedc.ru
AI_WORKSPACE_HUB_FALLBACK_URLS=

Server-side Hub API calls, including executor status checks, use AI_WORKSPACE_HUB_INTERNAL_URL and require a token accepted by Hub: AI_WORKSPACE_HUB_TOKEN, NDC_AI_WORKSPACE_HUB_TOKEN, or the shared NODEDC_INTERNAL_ACCESS_TOKEN where that token is intentionally common across platform services.

Локальные домены для первичной проверки

На Mac для первичной проверки добавить в /etc/hosts:

172.22.0.222 auth.nas.nodedc
172.22.0.222 auth-admin.nas.nodedc
172.22.0.222 launcher.nas.nodedc
172.22.0.222 task.nas.nodedc

Первичные URL:

http://auth.nas.nodedc:18080
http://auth-admin.nas.nodedc:18080/if/admin/
http://172.22.0.222:18080/if/admin/
http://launcher.nas.nodedc:18080
http://task.nas.nodedc:18080
http://task.nas.nodedc:18090

auth-admin.nas.nodedc is the technical Authentik Admin entrypoint. 172.22.0.222:18080 is a local IP fallback for workstations without auth-admin.nas.nodedc DNS. Both keep Authentik access separate from the public id.nodedc.ru login entrypoint and do not load NODE.DC auth-flow CSS.

Что входит

  • docker-compose.platform-http.yml поднимает новый Authentik, Launcher, Notification Core, AI Workspace Hub и Caddy edge.
  • Caddyfile.http маршрутизирует локальные auth/auth-admin/launcher/task.nas.nodedc, IP fallback 172.22.0.222 для Authentik Admin и внешние id/hub/ops.nodedc.ru.
  • deploy-current.sh синхронизирует compose, Caddyfile, Notification Core source, AI Workspace Hub source и опционально Launcher source в NAS mount. Authentik templates синхронизируются только при явном SYNC_AUTHENTIK_TEMPLATES=1.
  • backup-current.sh делает snapshot Launcher runtime/uploads/Auth templates/config и готовит команду pg_dump для Authentik Postgres.
  • Tasker поднимается отдельным compose из NODEDC_TASKMANAGER/plane-app/docker-compose.yaml на порту 18090.
  • Ops Agents Gateway поднимается отдельным compose из NODEDC_TASKMANAGER_CODEXAPI/docker-compose.synology.yml на 172.22.0.222:18190; Synology reverse proxy должен вести ops-agents.nodedc.ru на этот порт, а не на 18090.

Внутренний Authentik API для Launcher

Launcher подключен и к platform identity-сети, и к engine-сети. В engine-сети тоже может быть сервис с DNS-именем authentik-server, поэтому это имя нельзя использовать для NODEDC_AUTHENTIK_BASE_URL: Docker DNS может отдать не тот Authentik, и platform API-token будет получать 403 Token invalid/expired.

Для platform Authentik зафиксирован отдельный alias:

http://nodedc-platform-authentik-server:9000

Live /volume1/docker/nodedc-platform/platform/.env.synology должен содержать:

NODEDC_AUTHENTIK_BASE_URL=http://nodedc-platform-authentik-server:9000
AUTHENTIK_BASE_URL=http://nodedc-platform-authentik-server:9000
NODEDC_AUTHENTIK_SERVICE_TOKEN=<server Authentik API token>
AUTHENTIK_SERVICE_TOKEN=<same token>

Быстрая проверка из launcher-контейнера:

sudo /usr/local/bin/docker exec nodedc-platform-launcher-1 sh -lc '
echo "$NODEDC_AUTHENTIK_BASE_URL"
getent hosts nodedc-platform-authentik-server
for attempt in 1 2 3 4 5 6 7 8 9 10; do
  wget -qSO- \
    --header "Authorization: Bearer $NODEDC_AUTHENTIK_SERVICE_TOKEN" \
    "$NODEDC_AUTHENTIK_BASE_URL/api/v3/core/groups/?search=nodedc_admin" \
    2>&1 | head -n 25 && exit 0
  echo "authentik-api-not-ready attempt=$attempt"
  sleep 10
done
exit 1
'

Ожидаемый результат: HTTP/1.1 200 OK.

После изменения platform Authentik alias пересоздавать нужно authentik-server, authentik-worker и launcher. Один authentik-server может временно отдавать 503 Service Unavailable, пока worker и bootstrap не готовы.

Синхронизация текущего состояния

С Mac, при смонтированном /Volumes/docker:

cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
NAS_ROOT=/Volumes/docker/nodedc-platform \
LAUNCHER_REPO=/Users/dcconstructions/Downloads/mnt/data/nodedc_launcher \
TASKER_REPO=/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER \
TASKER_CHANGED_BASE=533f8c6 \
GATEWAY_REPO=/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI \
./infra/synology/deploy-current.sh

Скрипт не запускает Docker сам: на NAS sudo интерактивный, поэтому команды применения печатаются в конце.

Что синхронизируется:

  • Platform compose/Caddy.
  • Notification Core source в /volume1/docker/nodedc-platform/platform/notification-core.
  • AI Workspace Hub source в /volume1/docker/nodedc-platform/platform/ai-workspace-hub.
  • Authentik templates только при SYNC_AUTHENTIK_TEMPLATES=1; по умолчанию они не трогаются, чтобы лёгкий Hub deploy не уносил экспериментальную тему/брендинг в prod.
  • Launcher source в /volume1/docker/nodedc-platform/launcher/source.
  • Tasker plane-app/docker-compose.yaml и, если задан TASKER_CHANGED_BASE, только изменённые source-файлы из диапазона TASKER_CHANGED_BASE..HEAD.
  • Ops Agents Gateway source в /volume1/docker/nodedc-platform/ops-agents.

Полный sync Tasker source по SMB тяжёлый для Plane fork. Использовать его только осознанно:

TASKER_SYNC_SOURCE=1 ./infra/synology/deploy-current.sh

Секретные runtime env-файлы не перетираются:

  • /volume1/docker/nodedc-platform/platform/.env.synology
  • /volume1/docker/nodedc-platform/tasker/plane-app/.env.synology
  • /volume1/docker/nodedc-platform/ops-agents/.env

Если emergency-fix был сделан прямо на Synology в этих env-файлах, перенести sanitized-значение в .env.synology.example/docs, а секрет оставить только в live env.

Лёгкое обновление Hub / Launcher

Для правок только в Launcher/BFF не пересоздавать Authentik, reverse-proxy, Tasker и Ops Agents:

cd /volume1/docker/nodedc-platform/launcher/source
sudo /usr/local/bin/docker build --no-cache -t nodedc/launcher:local .

cd /volume1/docker/nodedc-platform/platform
sudo /usr/local/bin/docker compose \
  --env-file /volume1/docker/nodedc-platform/platform/.env.synology \
  -f /volume1/docker/nodedc-platform/platform/docker-compose.platform-http.yml \
  up -d --force-recreate --no-deps ai-workspace-hub launcher

После такого deploy проверить healthz, запись в launcher storage/uploads и сценарий пользователя без аппрува: сохранение аватара не должно показывать экран Заявка ожидает подтверждения. Дополнительно проверить, что live bundle больше не содержит старый pending gate:

launcher_asset="$(
  curl -k -sS --compressed -H 'Accept: text/html' https://hub.nodedc.ru/ \
    | grep -aoE 'index-[A-Za-z0-9_-]+\.js' \
    | head -n 1
)"
test -n "$launcher_asset"
if curl -k -sS --compressed "https://hub.nodedc.ru/assets/${launcher_asset}" \
  | grep -aq 'Заявка ожидает подтверждения'; then
  echo 'old pending gate still present'
  exit 1
fi
echo 'launcher-pending-gate-ok'

Authentik Admin и Brand CSS

NODE.DC auth-flow CSS must stay template-scoped. Do not store it in Authentik Brand.branding_custom_css: Authentik passes that CSS into Admin/User web component runtime and breaks native controls.

After syncing Authentik templates to NAS, recreate reverse-proxy authentik-server authentik-worker launcher, then clear existing global Brand CSS in the live DB:

cd /volume1/docker/nodedc-platform/platform
sudo bash clear-authentik-brand-css.sh

Verify:

id_admin_status="$(
  curl -k -sS -o /dev/null -w '%{http_code}' https://id.nodedc.ru/if/admin/
)"
if [[ "$id_admin_status" != "404" ]]; then
  echo "public id admin is not closed: status=${id_admin_status}"
  exit 1
fi
echo 'public-id-admin-closed-ok'

auth_admin_page="$(
  curl -k -fsS --compressed http://auth-admin.nas.nodedc:18080/if/admin/
)"
printf '%s' "$auth_admin_page" \
  | grep -aE '<style data-id="brand-css"></style>|authentikBrand.branding_custom_css = ""'

auth_admin_flow="$(
  curl -k -fsS --compressed http://auth-admin.nas.nodedc:18080/if/flow/default-authentication-flow/
)"
if printf '%s' "$auth_admin_flow" | grep -aq '<style data-id="nodedc-auth-login-css">'; then
  echo 'admin host still has NODE.DC auth CSS'
  exit 1
fi
echo 'auth-admin-css-ok'

Backup текущего состояния

С Mac, при смонтированном /Volumes/docker:

cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
NAS_ROOT=/Volumes/docker/nodedc-platform ./infra/synology/backup-current.sh

Файловый backup создаётся в /Volumes/docker/nodedc-platform/backups/platform-current-*.

Для Authentik Postgres dump нужно выполнить напечатанную команду на Synology, потому что Docker доступен через интерактивный sudo:

bash /volume1/docker/nodedc-platform/backups/platform-current-YYYYMMDD-HHMMSS/run-authentik-db-dump-on-synology.sh

Для Notification Core Postgres dump:

bash /volume1/docker/nodedc-platform/backups/platform-current-YYYYMMDD-HHMMSS/run-notification-db-dump-on-synology.sh

Если планируются изменения Tasker backend/schema, дополнительно выполнить:

bash /volume1/docker/nodedc-platform/backups/platform-current-YYYYMMDD-HHMMSS/run-tasker-db-dump-on-synology.sh

Если Ops Agents Gateway уже был запущен и там есть production tokens/grants/audit, дополнительно выполнить:

bash /volume1/docker/nodedc-platform/backups/platform-current-YYYYMMDD-HHMMSS/run-ops-agents-db-dump-on-synology.sh

Что нужно перед запуском

  • Собрать или загрузить linux/amd64 images:
    • nodedc/launcher:local
    • nodedc/notification-core:local
    • nodedc/plane-frontend:ru
    • nodedc/plane-admin:ru
    • nodedc/plane-space:ru
    • nodedc/plane-live:local
    • nodedc/plane-backend:local
    • nodedc/plane-proxy:ru
  • Для Ops Agents Gateway отдельный registry image пока не обязателен: deploy из source repo выполняется через docker compose --env-file .env -f docker-compose.synology.yml up -d --build.
  • Создать .env.synology из .env.synology.example и заменить все replace-with-*.
  • Создать plane.env.synology для Tasker из plane.env.staging.example, но с HTTP URL на *.nas.nodedc:18080 и портами 18090/18490.

Обязательные runtime-права

Launcher пишет runtime snapshot и uploads под пользователем node (uid=1000). После создания NAS-папок:

cd /volume1/docker/nodedc-platform/platform
sudo mkdir -p ../launcher/server-storage ../launcher/uploads
sudo chown -R 1000:1000 ../launcher/server-storage ../launcher/uploads
sudo chmod -R u+rwX,g+rwX ../launcher/server-storage ../launcher/uploads

Проверка внутри контейнера:

sudo /usr/local/bin/docker exec nodedc-platform-launcher-1 sh -lc \
  'touch /app/server/storage/.write-test /app/server/storage/uploads/.write-test && rm /app/server/storage/.write-test /app/server/storage/uploads/.write-test && echo storage-ok'

Проверки после деплоя

curl -k -sS --compressed https://id.nodedc.ru/if/flow/default-authentication-flow/ \
  | grep -aE 'hub.nodedc.ru|launcher.local|getLauncherBaseUrl|Запросить доступ'

В выводе должны быть id.nodedc.ru -> hub.nodedc.ru и не должно быть launcher.local.