|
|
||
|---|---|---|
| .. | ||
| tasker-overlays/logo-link-brand-hotfix | ||
| .env.synology.example | ||
| Caddyfile.http | ||
| README.md | ||
| apply-ai-hub-relay.sh | ||
| apply-current-runtime.sh | ||
| backup-current.sh | ||
| check-ai-workspace-apply-plan.sh | ||
| clear-authentik-brand-css.sh | ||
| deploy-current.sh | ||
| docker-compose.platform-http.yml | ||
| prepare-ai-workspace-env.sh | ||
| sync-ai-hub-relay.sh | ||
| verify-current-runtime.sh | ||
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, BIM Viewer upstream —18100, Ops Agents Gateway upstream —18190. - Старые порты
9000и5678заняты старымnodedc-demoи не используются.
Deploy runner
nodedc-deploy is managed outside the platform runtime tree. The synced install candidate lives in:
/volume1/docker/nodedc-deploy/runner-install/nodedc-deploy
The live root-owned runner is:
/usr/local/sbin/nodedc-deploy
deploy-current.sh syncs the runner candidate into runner-install. Promoting it to live is explicit:
sudo install -o root -g root -m 0755 \
/volume1/docker/nodedc-deploy/runner-install/nodedc-deploy \
/usr/local/sbin/nodedc-deploy
sudo /usr/local/sbin/nodedc-deploy verify-install
Текущие внешние домены
https://id.nodedc.ru -> Authentik
https://hub.nodedc.ru -> Launcher / Hub
https://ops.nodedc.ru -> Tasker / Operational Core
https://bim.nodedc.tech -> BIM Viewer
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.
bim.nodedc.tech can either be routed by DSM directly to the BIM host port 172.22.0.222:18100, or through the platform HTTP edge 172.22.0.222:18080. When it goes through the platform edge, BIM_DOMAIN=bim.nodedc.tech and SYNOLOGY_BIM_VIEWER_UPSTREAM=host.docker.internal:18100 keep the same target service.
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.
AI Workspace Assistant also calls product entitlement adapters before every Codex run. Ops uses the Agent Gateway internal endpoint; the token must match NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN from the Ops Agent Gateway deployment:
AI_WORKSPACE_OPS_ENTITLEMENT_URL=http://172.22.0.222:18190/api/internal/v1/ai-workspace/entitlements
AI_WORKSPACE_OPS_ENTITLEMENT_TOKEN=<same value as Ops NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN>
AI_WORKSPACE_OPS_ENTITLEMENT_REQUIRED=false
Локальные домены для первичной проверки
На 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 fallback172.22.0.222для Authentik Admin и внешниеid/hub/ops.nodedc.ru.deploy-current.shсинхронизирует compose, Caddyfile, Notification Core source, AI Workspace Hub source и опционально Launcher/BIM source в NAS mount. Authentik templates синхронизируются только при явномSYNC_AUTHENTIK_TEMPLATES=1.backup-current.shделает snapshot Launcher runtime/uploads/Auth templates/config, BIM Viewerserver/dataи готовит команду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 \
BIM_REPO=/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_BIM_VIEWER \
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 интерактивный, поэтому команды применения печатаются в конце.
По умолчанию sync source-копий на SMB/NAS не сохраняет owner/group/perms/times. Для Docker build важен контент, а macOS/Synology metadata может падать на utimensat Operation timed out. Если metadata действительно нужно сохранить для отдельного ручного случая, запускать с RSYNC_PRESERVE_METADATA=1.
Что синхронизируется:
- 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. - BIM Viewer source в
/volume1/docker/nodedc-platform/bim-viewer/source;server/dataне синхронизируется и остаётся live runtime-хранилищем моделей, shares, comments и refs. - 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/bim-viewer/source/.env/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.
AI Hub relay-only deploy
Для локального тестирования с внешней Codex-машиной нельзя деплоить Launcher, Engine, Ops, Authentik или Tasker. Единственная допустимая удалённая точка в этой схеме — ai-workspace-hub, потому что удалённый worker должен иметь публичный WebSocket/HTTP relay.
С Mac, при смонтированном /Volumes/docker, синхронизировать только Hub source, compose и узкий apply-script:
cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
NAS_ROOT=/Volumes/docker/nodedc-platform ./infra/synology/sync-ai-hub-relay.sh
На Synology применить только ai-workspace-hub:
ssh dctouch@100.109.216.21 'cd /volume1/docker/nodedc-platform/platform && sudo bash apply-ai-hub-relay.sh'
Этот путь намеренно делает только:
- build
nodedc/ai-workspace-hub:local; docker compose up -d --no-deps --force-recreate ai-workspace-hub;- container health check;
- проверку
/api/ai-workspace/hub/v1/assistant-relays/<relayId>/poll; - public route check через
https://ai-hub.nodedc.ru.
Он не меняет .env.synology, не синхронизирует Launcher/Tasker/Ops source, не пересоздаёт Authentik, reverse-proxy, базы, storage или product containers.
После успешного relay-only deploy локальная цепочка для теста должна быть такой:
local Launcher/Engine/Ops/Auth/Assistant
-> deployed AI Hub relay: https://ai-hub.nodedc.ru
-> remote Codex worker
-> deployed AI Hub relay
-> local Assistant relay poll
-> local product services
Лёгкое обновление 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'
BIM Viewer deploy
bim.nodedc.tech на Synology можно вести напрямую через DSM Reverse Proxy на 172.22.0.222:18100. В этом режиме Platform Caddy не участвует в публичном BIM-трафике, но Caddyfile.http всё равно содержит BIM route как запасной вариант для маршрута через 172.22.0.222:18080.
Canonical BIM deploy now uses nodedc-deploy with component=bim-viewer; do not deploy BIM by manually running docker compose up from the source directory as the normal path.
Live BIM root:
/volume1/docker/nodedc-platform/bim-viewer/source
Live env stays outside artifacts:
/volume1/docker/nodedc-platform/bim-viewer/source/.env
Before the first canonical apply, prepare .env from .env.synology.example and verify that NODEDC_INTERNAL_ACCESS_TOKEN matches platform/.env.synology. After that, .env must not be included in deploy artifacts.
Canonical deploy commands:
sudo /usr/local/sbin/nodedc-deploy verify-install
sudo /usr/local/sbin/nodedc-deploy plan /volume1/docker/nodedc-deploy/inbox/<bim-artifact>.tgz
sudo /usr/local/sbin/nodedc-deploy apply /volume1/docker/nodedc-deploy/inbox/<bim-artifact>.tgz
The bim-viewer runner component:
- applies payload under
/volume1/docker/nodedc-platform/bim-viewer/source; - rejects
.env,server/data, upload/model/comment/share runtime storage,node_modules,.git, shell hooks and backup files; - prepares required live runtime directories under
server/databefore compose; - builds
nodedc/bim-converter:localfromconverter/Dockerfile; - recreates only
ndc-beam-viewerandnodedc-bim-converter; - healthchecks
http://127.0.0.1:18100/api/auth/session.
Минимальная проверка после apply:
curl -k -fsS http://127.0.0.1:18100/api/auth/session
curl -k -sS -o /dev/null -w '%{http_code}\n' https://bim.nodedc.tech/
Ожидаемо: /api/auth/session возвращает authRequired: true, а прямой public root без BIM-сессии отдаёт 302 в Launcher login/launch. Public share /share/<token> должен открываться без авторизации и без toolbar.
Tasker / OPS BIM iframe rebuild
OPS web bundle получает BIM URL на build-time через VITE_BEAM_VIEWER_BASE_URL и VITE_BEAM_API_BASE_URL. После смены домена пересобрать только web image:
cd /volume1/docker/nodedc-platform/tasker/plane-src
VITE_BEAM_VIEWER_BASE_URL=https://bim.nodedc.tech \
VITE_BEAM_API_BASE_URL=https://bim.nodedc.tech \
BUILD_BACKEND=0 BUILD_WEB=1 BUILD_ADMIN=0 \
sh rebuild-nas-legacy.sh
Это пересоздаёт только web и не трогает PostgreSQL/MinIO volumes.
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/amd64images:nodedc/launcher:localnodedc/notification-core:localnodedc/plane-frontend:runodedc/plane-admin:runodedc/plane-space:runodedc/plane-live:localnodedc/plane-backend:localnodedc/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.