5.0 KiB
5.0 KiB
Project Context: Portal Stand Access
Этот файл нужен как быстрый технический контекст для нового разработчика/оператора.
1) Что это за проект
Веб-портал для выдачи пользователям доступа к стендам/сервисам через браузер.
Ключевая идея:
- пользователь выбирает сервис;
- портал открывает сервис в уже прогретом браузерном контейнере (WEB) или в RDP-слоте;
- каждая пользовательская сессия имеет
session_id(UUID) и свой URL/s/<session_id>/....
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/<uuid>/...).
4) Критичные маршруты
/— выбор сервисов/go/<slug>— запуск пользовательской сессии/s/<session_id>/— страница ожидания старта/s/<session_id>/view— сессионный view для WEB-пула/svc/<slug>/— роут к warm runtime конкретного сервиса/admin— админка
5) Что важно помнить по инфраструктуре
- Traefik удалять нельзя. Причина: динамические контейнеры создают labels во время работы, и именно Traefik маршрутизирует:
/s/<session_id>/.../svc/<slug>/...
- При Nginx Proxy Manager (NPM):
- внешний домен -> NPM -> внутренний Traefik.
- в
docker-compose.ymlTraefik опубликован локально:127.0.0.1:2288 -> 443127.0.0.1:8288 -> 80
- в NPM обязательна опция
Websockets Support.
- Кнопка «Домой» в runtime UI:
- должна возвращать к выбору сервисов портала (
/), а не вводить URL в удалённом сайте.
6) Диагностика типовых проблем
A) Черный экран в WEB
Проверять:
- что у noVNC корректный WebSocket endpoint (
.../websockify); - что сессия active в БД;
- что warm контейнер сервиса running;
- что в NPM включен websocket proxy.
Быстрая проверка:
- логи
portal-warm-<slug>-* - логи
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-образов:
docker compose --profile build-only build kiosk-image rdp-proxy-image universal-runtime-image
Поднять всё:
docker compose up -d --build
Пересоздать warm-пул (через API startup/ensure) — обычно перезапуск api и/или вызов prewarm из админки.
9) Что еще можно улучшить
- вынести миграции в Alembic;
- добавить отдельный health dashboard с websocket/rdp метриками;
- централизованный сбор логов и алерты;
- e2e smoke-тесты на сценарии
/go -> /s/<uuid>/view.