# 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`.