From 6095d538549c2866448d885c22619871f921dd76 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Mon, 13 Apr 2026 20:15:51 +0000 Subject: [PATCH] docs: add persistent project context and NPM deployment notes --- README.md | 32 ++++++++++++ docker-compose.yml | 4 +- docs/PROJECT_CONTEXT.md | 107 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 docs/PROJECT_CONTEXT.md diff --git a/README.md b/README.md index 38f20e2..34d8ca9 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,38 @@ docker compose logs -f api traefik https:///admin ``` +## 5.2 Вариант С Nginx Proxy Manager (NPM) + +Если на сервере уже используется NPM, внешний трафик можно вести через него, а Traefik оставить только внутренним роутером проекта. + +В этом репозитории уже настроены внутренние порты: + +- `127.0.0.1:2288 -> traefik:443` (HTTPS upstream) +- `127.0.0.1:8288 -> traefik:80` (HTTP upstream, технический) + +Важно: Traefik убирать нельзя, он нужен для динамических маршрутов сессий (`/s/*`, `/svc/*`). + +Как настроить NPM: + +1. Создать `Proxy Host` для домена (например `stend.example.com`): +- `Forward Hostname / IP`: `127.0.0.1` +- `Forward Port`: `2288` +- `Scheme`: `https` +- включить `Websockets Support` + +2. На вкладке SSL в NPM выпустить/подключить сертификат для домена. + +3. В `.env` проекта оставить: +- `PUBLIC_HOST=stend.example.com` + +4. Перезапустить проект: + +```bash +docker compose up -d --build +``` + +После этого вход в портал и сессии будут работать через NPM, а Traefik останется внутренним компонентом. + ## 6. Примеры admin API 1) Создать сервис WEB: diff --git a/docker-compose.yml b/docker-compose.yml index 262c31b..12a2f75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,8 +4,8 @@ services: command: - --configFile=/etc/traefik/traefik.yml ports: - - "80:80" - - "443:443" + - "127.0.0.1:8288:80" + - "127.0.0.1:2288:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro diff --git a/docs/PROJECT_CONTEXT.md b/docs/PROJECT_CONTEXT.md new file mode 100644 index 0000000..36a7993 --- /dev/null +++ b/docs/PROJECT_CONTEXT.md @@ -0,0 +1,107 @@ +# Project Context: Portal Stand Access + +Этот файл нужен как быстрый технический контекст для нового разработчика/оператора. + +## 1) Что это за проект + +Веб-портал для выдачи пользователям доступа к стендам/сервисам через браузер. + +Ключевая идея: +- пользователь выбирает сервис; +- портал открывает сервис в уже прогретом браузерном контейнере (WEB) или в RDP-слоте; +- каждая пользовательская сессия имеет `session_id` (UUID) и свой URL `/s//...`. + +## 2) Текущий стек + +- API: FastAPI (`app/main.py`) +- БД: PostgreSQL +- Edge/router: Traefik (обязателен для динамических маршрутов runtime-контейнеров) +- Runtime WEB: `portal-kiosk` (Chromium + x11vnc + websockify/noVNC) +- Runtime RDP: `portal-rdp-proxy` (xfreerdp + x11vnc + websockify/noVNC) + +## 3) Принятые продуктовые решения + +- Режим VNC как отдельный сервис больше не используется (deprecate). +- Основной сценарий для пользователей: WEB и RDP. +- Для WEB используются прогретые per-service пулы (`warm_pool_size` на сервис). +- Для RDP используется универсальный пул слотов (`UNIVERSAL_POOL_SIZE`). +- Сессии пользователя имеют UUID-ссылки (`/s//...`). + +## 4) Критичные маршруты + +- `/` — выбор сервисов +- `/go/` — запуск пользовательской сессии +- `/s//` — страница ожидания старта +- `/s//view` — сессионный view для WEB-пула +- `/svc//` — роут к warm runtime конкретного сервиса +- `/admin` — админка + +## 5) Что важно помнить по инфраструктуре + +1. Traefik удалять нельзя. +Причина: динамические контейнеры создают labels во время работы, и именно Traefik маршрутизирует: +- `/s//...` +- `/svc//...` + +2. При Nginx Proxy Manager (NPM): +- внешний домен -> NPM -> внутренний Traefik. +- в `docker-compose.yml` Traefik опубликован локально: + - `127.0.0.1:2288 -> 443` + - `127.0.0.1:8288 -> 80` +- в NPM обязательна опция `Websockets Support`. + +3. Кнопка «Домой» в runtime UI: +- должна возвращать к выбору сервисов портала (`/`), а не вводить URL в удалённом сайте. + +## 6) Диагностика типовых проблем + +### A) Черный экран в WEB +Проверять: +- что у noVNC корректный WebSocket endpoint (`.../websockify`); +- что сессия active в БД; +- что warm контейнер сервиса running; +- что в NPM включен websocket proxy. + +Быстрая проверка: +- логи `portal-warm--*` +- логи `portal-api-1` +- содержимое `/opt/portal/index.html` внутри warm-контейнера. + +### B) "Соединение со слотом потеряно" в RDP +Обычно не проблема портала, а проблема соединения `xfreerdp` до целевого host:port/cred/sec. +Смотреть `/tmp/session-app.log`/`xfreerdp.log` в `portal-universal-*`. + +### C) Изменения не видны сразу +Если менялись runtime-скрипты, старые warm-контейнеры могут держать старую версию. +Нужно пересобрать образ + пересоздать warm-пул. + +## 7) Где смотреть код + +- Backend и orchestration: `app/main.py` +- Админка/UI: `app/templates/admin.html`, `app/static/style.css` +- Пользовательский дашборд: `app/templates/dashboard.html` +- WEB runtime: `kiosk/entrypoint.sh`, `kiosk/manager.py` +- RDP runtime: `rdp-proxy/entrypoint.sh` +- Оркестрация: `docker-compose.yml`, `traefik/traefik.yml` + +## 8) Операционные команды + +Сборка runtime-образов: +```bash +docker compose --profile build-only build kiosk-image rdp-proxy-image universal-runtime-image +``` + +Поднять всё: +```bash +docker compose up -d --build +``` + +Пересоздать warm-пул (через API startup/ensure) — обычно перезапуск `api` и/или вызов prewarm из админки. + +## 9) Что еще можно улучшить + +- вынести миграции в Alembic; +- добавить отдельный health dashboard с websocket/rdp метриками; +- централизованный сбор логов и алерты; +- e2e smoke-тесты на сценарии `/go -> /s//view`. +