9.5 KiB
9.5 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 используется общий пул
portal-webpool-*(и авторасширение при нагрузке). - Для RDP используется универсальный пул слотов (
UNIVERSAL_POOL_SIZE). - Сессии пользователя имеют UUID-ссылки (
/s/<uuid>/...).
4) Критичные маршруты
/— выбор сервисов/go/<slug>— запуск пользовательской сессии/s/<session_id>/— страница ожидания старта/s/<session_id>/view— сессионный view для WEB-пула/svc/<slug>/— роут к warm runtime конкретного сервиса/w/<slot>/— роут к WEB pool слоту/u/<slot>/— роут к universal pool слоту/admin— админка
5) Что важно помнить по инфраструктуре
- Traefik удалять нельзя. Причина: динамические контейнеры создают labels во время работы, и именно Traefik маршрутизирует:
/s/<session_id>/.../svc/<slug>/.../w/<slot>/.../u/<slot>/...
- При Nginx Proxy Manager (NPM):
- внешний домен -> NPM -> внутренний Traefik.
- в
docker-compose.ymlTraefik опубликован так:0.0.0.0:2288 -> 4430.0.0.0:8288 -> 80
- в NPM обязательна опция
Websockets Support.
- Кнопка «Домой» в runtime UI:
- должна возвращать к выбору сервисов портала (
/), а не вводить URL в удалённом сайте.
6) Диагностика типовых проблем
A) Черный экран в WEB
Проверять:
- что у noVNC корректный WebSocket endpoint (
.../websockify); - что сессия active в БД;
- что контейнер WEB-пула running;
- что в NPM включен websocket proxy.
Быстрая проверка:
- логи
portal-webpool-* - логи
portal-api-1 - содержимое
/opt/portal/index.htmlвнутри runtime-контейнера.
B) "Соединение со слотом потеряно" в RDP
Обычно не проблема портала, а проблема соединения xfreerdp до целевого host:port/cred/sec.
Смотреть /tmp/session-app.log/xfreerdp.log в portal-universal-*.
C) Изменения не видны сразу
Если менялись runtime-скрипты, старые warm/pool контейнеры могут держать старую версию. Нужно пересобрать образ + пересоздать пул.
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 - Universal runtime:
universal-runtime/entrypoint.sh,universal-runtime/manager.py - Оркестрация:
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
Перезапуск только API:
docker compose up -d api
Проверка состояния:
docker compose ps
docker compose logs -f api traefik
9) Что еще можно улучшить
- вынести миграции в Alembic;
- добавить отдельный health dashboard с websocket/rdp метриками;
- централизованный сбор логов и алерты;
- e2e smoke-тесты на сценарии
/go -> /s/<uuid>/view.
10) Сервер и рабочие пути
- SSH сервер:
ruslan@10.17.39.3 - Пароль
sudoна сервере:utOgbZ09ruslanstand - Рабочий каталог проекта на сервере:
/root/Stend_mont - Файл контекста на сервере:
/root/Stend_mont/docs/PROJECT_CONTEXT.md
Базовый рабочий сценарий:
ssh ruslan@10.17.39.3
sudo -s
cd /root/Stend_mont
11) Git доступ и публикация
Репозиторий:
https://git.ruslan.xyz/ruslan/Stend_mont
Учетные данные HTTPS (текущие):
- login:
ruslan@ipcom.su - password/token:
utOgbZ09ruslan
Пример push:
cd /root/Stend_mont
git add .
git commit -m "your message"
git push https://ruslan%40ipcom.su:utOgbZ09ruslan@git.ruslan.xyz/ruslan/Stend_mont main
12) Текущее runtime-состояние (на момент фиксации)
- API запущен с
uvicorn --workers 4черезdocker-compose.yml. - Для WEB используется
portal-webpool-*. - Для RDP используется
portal-universal-*.
13) Последние изменения (2026-04-21)
- UI/брендинг:
- Тексты в интерфейсе переведены на формулировку
инфрастуктурный полигон. - На главной панели приветствие в блоке
admin-intro:Добро пожаловать в инфрастуктурный полигон. - Кнопка выхода на дашборде:
Выход(вместоLogout).
- WEB runtime (браузерные сервисы):
- В панели управления runtime оставлены 2 кнопки:
НазадГлавная(ведет на главную панель портала/).
- Кнопка
Впередудалена. - Изменения применены в
kiosk/entrypoint.shиuniversal-runtime/entrypoint.sh.
- Логин и просроченные пользователи:
- Если пользователь найден и пароль верный, но аккаунт просрочен/неактивен, на экране входа показывается сообщение:
Доступ к сервису приостоновлен, обратитесь к вашему менеджеру. - Сообщение рендерится в шаблоне
app/templates/login.htmlчерезlogin_error.
- Категории сервисов:
- Добавлены сущности и связи:
categoriesservice_categories
- Категории можно создавать/удалять в админке.
- При создании/редактировании WEB/RDP сервиса можно выбрать категории.
- На главной панели добавлен стильный фильтр по категориям (chips) и бейджи категорий на карточке сервиса.
- Иконки сервисов:
- Иконки на главной панели увеличены примерно в 6 раз.
- Масштабирование иконок:
object-fit: contain, чтобы картинка полностью влезала в рамку. - В админке загрузка иконки стала автоматической при выборе файла (без кнопки Upload).
- Многоворкерный API и startup:
- API работает с
uvicorn --workers 4. - Чтобы убрать гонку DDL на старте (при нескольких воркерах), добавлен file-lock на bootstrap схемы:
- lock-файл:
/tmp/portal-schema.lock - сериализуется выполнение
Base.metadata.create_all(...)иensure_schema_compatibility().
- lock-файл:
- Операционные заметки по применению runtime-изменений:
- После изменения
kiosk/universal-runtimeнужно:- пересобрать runtime-образы,
- пересоздать
portal-webpool-*,portal-universal-*,portal-warm-*контейнеры, - перезапустить
api.