# 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 используется общий пул `portal-webpool-*` (и авторасширение при нагрузке). - Для RDP используется универсальный пул слотов (`UNIVERSAL_POOL_SIZE`). - Сессии пользователя имеют UUID-ссылки (`/s//...`). ## 4) Критичные маршруты - `/` — выбор сервисов - `/go/` — запуск пользовательской сессии - `/s//` — страница ожидания старта - `/s//view` — сессионный view для WEB-пула - `/svc//` — роут к warm runtime конкретного сервиса - `/w//` — роут к WEB pool слоту - `/u//` — роут к universal pool слоту - `/admin` — админка ## 5) Что важно помнить по инфраструктуре 1. Traefik удалять нельзя. Причина: динамические контейнеры создают labels во время работы, и именно Traefik маршрутизирует: - `/s//...` - `/svc//...` - `/w//...` - `/u//...` 2. При Nginx Proxy Manager (NPM): - внешний домен -> NPM -> внутренний Traefik. - в `docker-compose.yml` Traefik опубликован так: - `0.0.0.0:2288 -> 443` - `0.0.0.0:8288 -> 80` - в NPM обязательна опция `Websockets Support`. 3. Кнопка «Домой» в 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-образов: ```bash docker compose --profile build-only build kiosk-image rdp-proxy-image universal-runtime-image ``` Поднять всё: ```bash docker compose up -d --build ``` Перезапуск только API: ```bash docker compose up -d api ``` Проверка состояния: ```bash docker compose ps docker compose logs -f api traefik ``` ## 9) Что еще можно улучшить - вынести миграции в Alembic; - добавить отдельный health dashboard с websocket/rdp метриками; - централизованный сбор логов и алерты; - e2e smoke-тесты на сценарии `/go -> /s//view`. ## 10) Сервер и рабочие пути - SSH сервер: `ruslan@10.17.39.3` - Пароль `sudo` на сервере: `utOgbZ09ruslanstand` - Рабочий каталог проекта на сервере: `/root/Stend_mont` - Файл контекста на сервере: `/root/Stend_mont/docs/PROJECT_CONTEXT.md` Базовый рабочий сценарий: ```bash 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: ```bash 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) 1. UI/брендинг: - Тексты в интерфейсе переведены на формулировку `инфрастуктурный полигон`. - На главной панели приветствие в блоке `admin-intro`: `Добро пожаловать в инфрастуктурный полигон`. - Кнопка выхода на дашборде: `Выход` (вместо `Logout`). 2. WEB runtime (браузерные сервисы): - В панели управления runtime оставлены 2 кнопки: - `Назад` - `Главная` (ведет на главную панель портала `/`). - Кнопка `Вперед` удалена. - Изменения применены в `kiosk/entrypoint.sh` и `universal-runtime/entrypoint.sh`. 3. Логин и просроченные пользователи: - Если пользователь найден и пароль верный, но аккаунт просрочен/неактивен, на экране входа показывается сообщение: `Доступ к сервису приостоновлен, обратитесь к вашему менеджеру`. - Сообщение рендерится в шаблоне `app/templates/login.html` через `login_error`. 4. Категории сервисов: - Добавлены сущности и связи: - `categories` - `service_categories` - Категории можно создавать/удалять в админке. - При создании/редактировании WEB/RDP сервиса можно выбрать категории. - На главной панели добавлен стильный фильтр по категориям (chips) и бейджи категорий на карточке сервиса. 5. Иконки сервисов: - Иконки на главной панели увеличены примерно в 6 раз. - Масштабирование иконок: `object-fit: contain`, чтобы картинка полностью влезала в рамку. - В админке загрузка иконки стала автоматической при выборе файла (без кнопки Upload). 6. Многоворкерный API и startup: - API работает с `uvicorn --workers 4`. - Чтобы убрать гонку DDL на старте (при нескольких воркерах), добавлен file-lock на bootstrap схемы: - lock-файл: `/tmp/portal-schema.lock` - сериализуется выполнение `Base.metadata.create_all(...)` и `ensure_schema_compatibility()`. 7. Операционные заметки по применению runtime-изменений: - После изменения `kiosk`/`universal-runtime` нужно: 1. пересобрать runtime-образы, 2. пересоздать `portal-webpool-*`, `portal-universal-*`, `portal-warm-*` контейнеры, 3. перезапустить `api`. ## 14) Обновление контекста (2026-04-21, вечер) 1. Главная страница и 500: - Был зафиксирован Internal Server Error на /. - Причина: синтаксическая ошибка Jinja в app/templates/login.html (поврежденный endif). - Статус: исправлено, API перезапущен, / отвечает 200. 2. Фон и визуальные эффекты: - Были тесты фонов main.jpg, main_general.jpg, 123.jpg и локального файла 71ba42f1d7d61e4313ad8fd086d3ed7f.jpg. - Текущее состояние по запросу: эффекты отключены. - Отключено: parallax, анимации облаков, hover-движения карточек/ссылок, blur карточек. - Главная панель оставлена со статичным светлым фоном без motion-эффектов. 3. Файлы, затронутые в этой волне: - app/templates/dashboard.html: удален parallax/cloud слой из разметки. - app/static/style.css: добавлен override-блок для отключения эффектов. - app/templates/login.html: исправлена ошибка шаблона. 4. Актуальный операционный контур: - Сервер: ruslan@10.17.39.3 - Проект: /root/Stend_mont - Контекст: /root/Stend_mont/docs/PROJECT_CONTEXT.md - Применение UI-правок: 1) ssh ruslan@10.17.39.3 2) sudo -s 3) cd /root/Stend_mont 4) docker compose up -d --build api 5. Git публикация: - origin: https://git.ruslan.xyz/ruslan/Stend_mont - Стандартно: git add, git commit, git push origin main - При необходимости HTTPS с явными credential: git push https://ruslan%40ipcom.su:utOgbZ09ruslan@git.ruslan.xyz/ruslan/Stend_mont main