diff --git a/infra/.env.example b/infra/.env.example index 350105a..7f9fd60 100644 --- a/infra/.env.example +++ b/infra/.env.example @@ -4,12 +4,15 @@ AUTH_DOMAIN=auth.local.nodedc AUTH_ADMIN_DOMAIN=auth-admin.local.nodedc LAUNCHER_DOMAIN=launcher.local.nodedc TASK_DOMAIN=task.local.nodedc +BIM_DOMAIN=bim.local.nodedc +NODEDC_BIM_VIEWER_PUBLIC_URL=http://localhost:8080 # proxy PLATFORM_HTTP_PORT=80 PLATFORM_PROXY_IMAGE=nodedc/plane-proxy:ru LOCAL_LAUNCHER_UPSTREAM=host.docker.internal:5173 LOCAL_TASK_MANAGER_UPSTREAM=host.docker.internal:8090 +LOCAL_BIM_VIEWER_UPSTREAM=host.docker.internal:8080 # authentik image AUTHENTIK_IMAGE=ghcr.io/goauthentik/server diff --git a/infra/.env.staging.example b/infra/.env.staging.example index c621c79..e610783 100644 --- a/infra/.env.staging.example +++ b/infra/.env.staging.example @@ -2,6 +2,8 @@ AUTH_DOMAIN=auth.staging.nodedc.example LAUNCHER_DOMAIN=launcher.staging.nodedc.example TASK_DOMAIN=task.staging.nodedc.example +BIM_DOMAIN=bim.staging.nodedc.example +NODEDC_BIM_VIEWER_PUBLIC_URL=https://bim.staging.nodedc.example # edge proxy ACME_EMAIL=admin@nodedc.example @@ -10,6 +12,7 @@ PLATFORM_HTTPS_PORT=443 PLATFORM_PROXY_IMAGE=caddy:2-alpine STAGING_LAUNCHER_UPSTREAM=launcher:5173 STAGING_TASK_MANAGER_UPSTREAM=task-manager-proxy:80 +STAGING_BIM_VIEWER_UPSTREAM=host.docker.internal:18100 # authentik image AUTHENTIK_IMAGE=ghcr.io/goauthentik/server diff --git a/infra/synology/.env.synology.example b/infra/synology/.env.synology.example index 703ed4c..ab1db58 100644 --- a/infra/synology/.env.synology.example +++ b/infra/synology/.env.synology.example @@ -6,9 +6,11 @@ AUTH_ADMIN_DOMAIN=auth-admin.nas.nodedc AUTH_ADMIN_LAN_HOST=172.22.0.222 LAUNCHER_DOMAIN=launcher.nas.nodedc TASK_DOMAIN=task.nas.nodedc +BIM_DOMAIN=bim.nodedc.tech NODEDC_PUBLIC_HTTP_PORT=18080 PLATFORM_HTTP_PORT=18080 SYNOLOGY_TASK_MANAGER_UPSTREAM=host.docker.internal:18090 +SYNOLOGY_BIM_VIEWER_UPSTREAM=host.docker.internal:18100 AUTHENTIK_IMAGE=ghcr.io/goauthentik/server AUTHENTIK_TAG=2026.2.2 @@ -25,6 +27,7 @@ AUTHENTIK_BOOTSTRAP_TOKEN=replace-with-random-synology-secret LAUNCHER_BASE_URL=https://hub.nodedc.ru TASK_BASE_URL=https://ops.nodedc.ru +NODEDC_BIM_VIEWER_PUBLIC_URL=https://bim.nodedc.tech TASK_LOGOUT_URI=https://ops.nodedc.ru/logout TASK_INTERNAL_LOGOUT_URL=https://ops.nodedc.ru/api/internal/nodedc/logout/ NODEDC_ENGINE_DOCKER_NETWORK=nodedc-demo_default diff --git a/infra/synology/Caddyfile.http b/infra/synology/Caddyfile.http index 87160b5..92e1a5a 100644 --- a/infra/synology/Caddyfile.http +++ b/infra/synology/Caddyfile.http @@ -48,12 +48,12 @@ http://{$TASK_DOMAIN} { } } -http://{$BIM_DOMAIN:bim.nodedc.ru} { - reverse_proxy {$SYNOLOGY_BIM_VIEWER_UPSTREAM:ndc-beam-viewer:8080} { +http://{$BIM_DOMAIN:bim.nodedc.tech} { + reverse_proxy {$SYNOLOGY_BIM_VIEWER_UPSTREAM:host.docker.internal:18100} { header_up Host {http.request.host} header_up X-Forwarded-Host {http.request.host} - header_up X-Forwarded-Proto {scheme} - header_up X-Forwarded-Port {$NODEDC_PUBLIC_HTTP_PORT} + header_up X-Forwarded-Proto https + header_up X-Forwarded-Port 443 header_up X-Forwarded-For {remote_host} } } diff --git a/infra/synology/README.md b/infra/synology/README.md index 22aa8fa..e47265a 100644 --- a/infra/synology/README.md +++ b/infra/synology/README.md @@ -7,7 +7,7 @@ - Не выполнять `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`. +- Внутренний HTTP edge использует `18080`, AI Workspace Hub — `18081`, Tasker upstream — `18090`, BIM Viewer upstream — `18100`, Ops Agents Gateway upstream — `18190`. - Старые порты `9000` и `5678` заняты старым `nodedc-demo` и не используются. ## Текущие внешние домены @@ -16,6 +16,7 @@ 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 ``` @@ -26,6 +27,8 @@ https://ai-hub.nodedc.ru -> AI Workspace Hub / WebSocket relay В `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`. @@ -83,8 +86,8 @@ http://task.nas.nodedc:18090 - `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. +- `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 Viewer `server/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`. @@ -137,6 +140,7 @@ exit 1 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 \ @@ -154,6 +158,7 @@ GATEWAY_REPO=/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXA - 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`. @@ -166,6 +171,7 @@ 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` @@ -241,6 +247,45 @@ 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`. + +Первый старт или обновление BIM после `BIM_REPO` sync: + +```bash +cd /volume1/docker/nodedc-platform/bim-viewer/source +sudo cp -n .env.synology.example .env +# Проверить .env: NODEDC_INTERNAL_ACCESS_TOKEN должен совпадать с platform/.env.synology. +sudo /usr/local/bin/docker compose \ + --env-file .env \ + -f docker-compose.beam.yml \ + up -d --build --force-recreate ndc-beam-viewer nodedc-bim-converter +``` + +Минимальная проверка на Synology: + +```bash +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/` должен открываться без авторизации и без 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: + +```bash +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. diff --git a/infra/synology/backup-current.sh b/infra/synology/backup-current.sh index 7bb274e..f7f30aa 100755 --- a/infra/synology/backup-current.sh +++ b/infra/synology/backup-current.sh @@ -16,7 +16,8 @@ mkdir -p "${BACKUP_DIR}/files/platform" \ "${BACKUP_DIR}/files/launcher" \ "${BACKUP_DIR}/files/authentik" \ "${BACKUP_DIR}/files/tasker" \ - "${BACKUP_DIR}/files/ops-agents" + "${BACKUP_DIR}/files/ops-agents" \ + "${BACKUP_DIR}/files/bim-viewer" rsync_dir() { local source="$1" @@ -47,6 +48,7 @@ rsync_dir "${NAS_ROOT}/platform/authentik/" "${BACKUP_DIR}/files/platform/authen rsync_dir "${NAS_ROOT}/platform/notification-core/" "${BACKUP_DIR}/files/platform/notification-core/" rsync_dir "${NAS_ROOT}/platform/ai-workspace-hub/" "${BACKUP_DIR}/files/platform/ai-workspace-hub/" rsync_dir "${NAS_ROOT}/platform/ai-workspace-assistant/" "${BACKUP_DIR}/files/platform/ai-workspace-assistant/" +rsync_dir "${NAS_ROOT}/bim-viewer/source/server/data/" "${BACKUP_DIR}/files/bim-viewer/server-data/" rsync_file "${NAS_ROOT}/platform/.env.synology" "${BACKUP_DIR}/files/platform/" rsync_file "${NAS_ROOT}/platform/.env.synology.example" "${BACKUP_DIR}/files/platform/" @@ -61,6 +63,10 @@ rsync_file "${NAS_ROOT}/ops-agents/.env" "${BACKUP_DIR}/files/ops-agents/" rsync_file "${NAS_ROOT}/ops-agents/.env.synology.example" "${BACKUP_DIR}/files/ops-agents/" rsync_file "${NAS_ROOT}/ops-agents/docker-compose.synology.yml" "${BACKUP_DIR}/files/ops-agents/" +rsync_file "${NAS_ROOT}/bim-viewer/source/.env" "${BACKUP_DIR}/files/bim-viewer/" +rsync_file "${NAS_ROOT}/bim-viewer/source/.env.synology.example" "${BACKUP_DIR}/files/bim-viewer/" +rsync_file "${NAS_ROOT}/bim-viewer/source/docker-compose.beam.yml" "${BACKUP_DIR}/files/bim-viewer/" + cat > "${BACKUP_DIR}/manifest.txt" <&2 + exit 1 + fi + + mkdir -p "${NAS_ROOT}/bim-viewer/source" + rm -rf \ + "${NAS_ROOT}/bim-viewer/source/app" \ + "${NAS_ROOT}/bim-viewer/source/docs" + rsync -av "${RSYNC_METADATA_ARGS[@]}" --delete \ + --exclude='.git/' \ + --exclude='.DS_Store' \ + --exclude='node_modules/' \ + --exclude='dist/' \ + --exclude='app/' \ + --exclude='docs/' \ + --exclude='server/node_modules/' \ + --exclude='frontend/node_modules/' \ + --exclude='server/data/' \ + --include='.env.synology.example' \ + --exclude='.env' \ + --exclude='.env.*' \ + "${BIM_REPO}/" \ + "${NAS_ROOT}/bim-viewer/source/" +else + echo "BIM_REPO is not set; BIM Viewer source was not synced." +fi + if [[ -n "${TASKER_REPO}" ]]; then if [[ ! -d "${TASKER_REPO}/plane-src" || ! -d "${TASKER_REPO}/plane-app" ]]; then echo "TASKER_REPO must point to NODEDC_TASKMANAGER with plane-src and plane-app: ${TASKER_REPO}" >&2 @@ -208,6 +243,18 @@ If runtime was already applied and only verification is needed: cd /volume1/docker/nodedc-platform/platform sudo bash verify-current-runtime.sh +Optional BIM Viewer apply after BIM_REPO sync: + +cd /volume1/docker/nodedc-platform/bim-viewer/source +sudo cp -n .env.synology.example .env +# Edit .env before first production start: NODEDC_INTERNAL_ACCESS_TOKEN must match platform .env.synology. +sudo /usr/local/bin/docker compose \ + --env-file .env \ + -f docker-compose.beam.yml \ + up -d --build --force-recreate ndc-beam-viewer nodedc-bim-converter + +curl -k -fsS http://127.0.0.1:18100/api/auth/session + Manual equivalent: cd /volume1/docker/nodedc-platform/platform diff --git a/infra/synology/verify-current-runtime.sh b/infra/synology/verify-current-runtime.sh index 1052296..39147b6 100755 --- a/infra/synology/verify-current-runtime.sh +++ b/infra/synology/verify-current-runtime.sh @@ -71,6 +71,20 @@ echo "== ai workspace assistant Ops entitlement adapter check ==" "${DOCKER_BIN}" exec nodedc-platform-ai-workspace-assistant-1 sh -lc \ 'test "$AI_WORKSPACE_OPS_ENTITLEMENT_URL" = "http://172.22.0.222:18190/api/internal/v1/ai-workspace/entitlements" && test -n "$AI_WORKSPACE_OPS_ENTITLEMENT_TOKEN" && echo ai-workspace-ops-entitlement-env-ok' +echo "== BIM viewer auth/session check ==" +bim_session="$(fetch_with_retry http://127.0.0.1:18100/api/auth/session)" +printf '%s' "$bim_session" | grep -aE '"authRequired":true|"loginUrl"' + +echo "== BIM viewer public redirect check ==" +bim_public_status="$( + curl -k -sS -o /dev/null -w '%{http_code}' https://bim.nodedc.tech/ +)" +if [[ "$bim_public_status" != "302" ]]; then + echo "public BIM root did not redirect to Launcher auth: status=${bim_public_status}" + exit 1 +fi +echo "bim-public-auth-redirect-ok" + echo "== auth flow check ==" auth_flow="$(fetch_with_retry https://id.nodedc.ru/if/flow/default-authentication-flow/)" printf '%s' "$auth_flow" \