# ВЕКТОР МЧС — Гайд по развёртыванию на серверах МЧС **Пошаговое руководство для IT-специалистов МЧС Республики Беларусь по развёртыванию системы определения приоритетных направлений поиска (ВЕКТОР) на серверах организации.** > **Версия документа:** 1.0 от 9 сентября 2026 г. > **Репозиторий:** [`Sadmin/vector`](http://192.168.0.106:3000/Sadmin/vector) --- ## Оглавление 1. [Требования к серверу](#1-требования-к-серверу) 2. [Архитектура развёртывания](#2-архитектура-развёртывания) 3. [Подготовка сервера](#3-подготовка-сервера) 4. [Установка Docker и Docker Compose](#4-установка-docker-и-docker-compose) 5. [Получение кода проекта](#5-получение-кода-проекта) 6. [Конфигурация окружения (.env)](#6-конфигурация-окружения-env) 7. [Запуск сервисов](#7-запуск-сервисов) 8. [Инициализация базы данных (миграции, сиды)](#8-инициализация-базы-данных-миграции-сиды) 9. [Загрузка OSM-геослоя (PostGIS)](#9-загрузка-osm-геослоя-postgis) 10. [Проверка работоспособности](#10-проверка-работоспособности) 11. [Создание пользователей и справочника подразделений](#11-создание-пользователей-и-справочника-подразделений) 12. [Настройка интеграции с КОНТУР](#12-настройка-интеграции-с-контуром) 13. [Обратный прокси и HTTPS](#13-обратный-прокси-и-https) 14. [Обновление проекта](#14-обновление-проекта) 15. [Резервное копирование](#15-резервное-копирование) 16. [Мониторинг и логи](#16-мониторинг-и-логи) 17. [Диагностика проблем](#17-диагностика-проблем) 18. [Чек-лист развёртывания](#18-чек-лист-развёртывания) --- ## 1. Требования к серверу ### Минимальные требования | Параметр | Значение | |----------|----------| | ОС | Debian 12/13, Ubuntu 22.04+ (любая с Docker) | | CPU | 2 vCPU | | RAM | 4 ГБ (2 ГБ свободно для импорта OSM — см. раздел 9) | | Диск | 20 ГБ + 1 ГБ под дамп OSM | | Сеть | Доступ браузеров к серверу по HTTP(S); для первичной загрузки дампа OSM — доступ в интернет (одноразово) | ### Требования безопасности - Сервер в закрытом контуре организации; **данные ПДн не должны покидать контур** — не настраивать проксирование на внешние сервисы - Смена всех паролей по умолчанию (см. раздел 6) - Для полностью offline-сценария без интернета: скачать дамп OSM заранее (раздел 9) и учесть, что фронт тянет OSM-тайлы с CDN — для абсолютного offline нужен локальный tile-сервер (в планах) --- ## 2. Архитектура развёртывания Docker Compose поднимает 4 сервиса: | Контейнер | Образ | Порт | Назначение | |-----------|-------|------|-----------| | `vector-postgres` | postgres:16 (+PostGIS 3.6 в контейнере) | 5432 | БД `vector_mchs`, данные + OSM | | `vector-backend` | сборка backend/Dockerfile | 8000 | FastAPI (uvicorn --reload) | | `vector-frontend` | сборка frontend/Dockerfile | 3000 | React SPA (CRA dev-сервер) | | `vector-adminer` | adminer | 8080 | Веб-администрирование БД | Код backend/services и frontend смонтирован volume'ами — правки подхватываются без пересборки (dev-режим). --- ## 3. Подготовка сервера ```bash # 1. Обновление системы apt update && apt upgrade -y # 2. Базовые утилиты apt install -y curl git ca-certificates gnupg # 3. (опционально) NTP-синхронизация — важна для корректных меток времени аудита apt install -y systemd-timesyncd timedatectl set-ntp true ``` --- ## 4. Установка Docker и Docker Compose ```bash # Официальный скрипт (или репозиторий docker-ce — по политике организации) curl -fsSL https://get.docker.com | sh systemctl enable --now docker docker --version # 24+ docker compose version # v2 ``` --- ## 5. Получение кода проекта ```bash mkdir -p /root/vector && cd /root/vector git clone http://:3000/Sadmin/vector.git . ``` Ключевые ветки: `master` — рабочая. --- ## 6. Конфигурация окружения (.env) ```bash cp .env.example .env ``` Обязательные переменные: ```ini # Подключение к БД (внутри compose — хост postgres) DATABASE_URL=postgresql://postgres:<СМЕНИТЬ_ПАРОЛЬ>@postgres:5432/vector_mchs # Секрет JWT — сгенерировать: openssl rand -hex 32 JWT_SECRET=<СЛУЧАЙНАЯ_СТРОКА> # CORS — адрес(а) фронтенда CORS_ORIGINS=http://<адрес-сервера>:3000 # Интеграция с КОНТУР (раздел 12; можно отложить) CONTOUR_API_URL=http://:8000 CONTOUR_TOKEN=<токен из КОНТУРа> ``` > **НЕ добавлять** никаких ключей внешних ИИ/API — по политике закрытого контура их в проекте нет и быть не должно (тест-страж `TestNoLLM`). Пароль БД должен совпадать с `POSTGRES_PASSWORD` в `docker-compose.yml` (сервис postgres). --- ## 7. Запуск сервисов ```bash cd /root/vector docker compose up -d docker compose ps # все 4 контейнера Up/healthy ``` Первый старт backend создаёт таблицы через `init_db` (create_all). Порядок применения Alembic-миграций — раздел 8. --- ## 8. Инициализация базы данных (миграции, сиды) ### 8.1 Миграции Alembic ```bash docker exec vector-backend sh -c 'cd /app/backend && alembic upgrade head' docker exec vector-backend sh -c 'cd /app/backend && alembic current' # 009_e3_operations ``` Миграции идемпотентны на чистой БД. **Если** БД уже была инициализирована через create_all и `alembic upgrade` падает `DuplicateTable` — применить стемп-скрипт: ```bash docker exec -i vector-postgres psql -U postgres -d vector_mchs < scripts/prod-stamp-backfill.sql ``` ### 8.2 Сид первого администратора ```bash docker exec vector-backend sh -c 'cd /app && python backend/seed_users.py' ``` Создаётся стартовый администратор (логин `admin`, пароль по умолчанию — сменить при первом входе через форму). Скрипт пропускается, если пользователи уже есть. ### 8.3 Сид подразделений (142 юнита) ```bash docker exec vector-backend sh -c 'cd /app && python backend/seed_units.py' ``` Создаёт РЦУ РЧС → 6 ОУМЧС → 135 Г(Р)ОЧС/ПАСО (справочник идемпотентный: существующие названия не дублируются). Без него админка пользователей бесполезна (пустые селекты подразделений). --- ## 9. Загрузка OSM-геослоя (PostGIS) Бэкенд рассчитывает рельеф секторов из локальной OSM. На чистой БД геосервис автоматически fallback'ится на публичный Overpass (медленно, требует интернет) — **для продуктива импортируйте дамп**. ### 9.1 Установка PostGIS в контейнер БД ```bash docker exec -u root vector-postgres apt update docker exec -u root vector-postgres apt install -y postgresql-16-postgis-3 osm2pgsql docker exec vector-postgres psql -U postgres -d vector_mchs -c 'CREATE EXTENSION IF NOT EXISTS postgis;' ``` > Установка пакетом в живой контенер переживает перезапуск контейнера (данные в volume), но слетает при ПЕРЕСОЗДАНИИ контейнера — тогда повторить команды. ### 9.2 Импорт дампа OSM ```bash # Скачивание (одноразово, ~333 МБ; можно перенести на сервер любым носителем) wget https://download.geofabrik.de/europe/belarus-latest.osm.pbf -O /tmp/belarus-latest.osm.pbf # Импорт (~4,5 мин, RAM 2 ГБ, node cache 800) sh scripts/b16-import.sh ``` Скрипт сам: удаляет старые planet_osm_* таблицы, копирует дамп в контейнер, запускает osm2pgsql (--slim, SRID по умолчанию), выводит список таблиц. ### 9.3 Проверка ```bash docker exec vector-postgres psql -U postgres -d vector_mchs -t -c " SELECT 'roads', count(*) FROM planet_osm_roads UNION ALL SELECT 'forests', count(*) FROM planet_osm_polygon WHERE landuse='forest';" ``` Ожидается ~1 млн дорог, ~190 тыс. лесов. --- ## 10. Проверка работоспособности ```bash # 1. Health бэкенда curl -s http://localhost:8000/api/v1/health # 2. Логин (ТОЛЬКО form-urlencoded!) TOKEN=$(curl -s -X POST http://localhost:8000/api/v1/auth/login \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data 'username=admin&password=<пароль>' | python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])') # 3. Профиль (9 прав у admin) curl -s http://localhost:8000/api/v1/auth/me -H "Authorization: Bearer $TOKEN" # 4. Фронт curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/ # 200 # 5. Полный расчёт (e2e-скрипты в scripts/e2e-*.sh — см. примеры вызовов) ``` В браузере: `http://<адрес>:3000` → дашборд «Активные поиски». --- ## 11. Создание пользователей и справочника подразделений Пользователи создаются через UI: **Дашборд → Пользователи → «+ Новый пользователь»** (доступ: роль admin РЦУ РЧС или coordinator ОУМЧС в рамках своего поддерева). - При создании задаётся временный пароль — пользователь обязан сменить его при первом входе - Роли: РЦУ РЧС / ОУМЧС / Г(Р)ОЧС / Наблюдатель (описание прав — README.md, раздел RBAC) - Инлайн-операции в таблице: смена роли/подразделения, отключение/включение, сброс пароля (отзывает все сессии) - Все изменения пишутся в журнал аудита (вкладка «Аудит», ретенция 90 дней) Иерархию подразделений менять: правкой `backend/seed_units.py` (идемпотентно, kind ∈ rcu/oblast/gor_rayon — ограничение БД `ck_mchs_units_kind`). --- ## 12. Настройка интеграции с КОНТУР КОНТУР — система полевой координации (ATAK + Meshtastic) на отдельном сервере. ВЕКТОР отправляет в неё приоритетные зоны. 1. В `.env`: `CONTOUR_API_URL` (адрес API КОНТУРа) и `CONTOUR_TOKEN` (выдаётся на стороне КОНТУРа) 2. `docker compose up -d backend` — **пересоздать** контейнер (restart не перечитывает env!) 3. Проверка: операция → «Отправить зоны в КОНТУР» на странице анализа; при недоступности КОНТУРа бэкенд вернёт понятную ошибку 502 и запишет `contour_send_failed` в аудит Входящие данные (треки групп, проверенные квадраты) — этап B17, в разработке. --- ## 13. Обратный прокси и HTTPS Для доступа пользователей по HTTPS поставьте nginx/traefik перед фронтендом и API: ```nginx server { listen 443 ssl; server_name vector.mchs.example; ssl_certificate /etc/ssl/certs/vector.crt; ssl_certificate_key /etc/ssl/private/vector.key; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; } location /api/ { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; client_max_body_size 10m; } } ``` В `CORS_ORIGINS` укажите итоговый https-адрес. В закрытом контуре допустима работа по HTTP без прокси (порты 3000/8000 напрямую). --- ## 14. Обновление проекта ```bash cd /root/vector git pull origin master # Если менялись миграции: docker exec vector-backend sh -c 'cd /app/backend && alembic upgrade head' # Если менялись env-переменные (.env / compose environment) — ПЕРЕСОЗДАТЬ контейнер: docker compose up -d backend # restart НЕ перечитывает env! # Обычное обновление кода: docker restart vector-backend vector-frontend ``` Схема обновления, применяемая при разработке: правки коммитятся в Gitea → на сервере `git pull` → `docker restart`. После рестарта frontend пользователи перелогиниваются. --- ## 15. Резервное копирование ```bash # Полный дамп БД (данные + OSM-таблицы) docker exec vector-postgres pg_dump -U postgres -d vector_mchs -F c \ -f /tmp/vector_mchs_$(date +%F).dump docker cp vector-postgres:/tmp/vector_mchs_$(date +%F).dump /root/backups/ # Только прикладные данные (без тяжёлых planet_osm_* — их восстанавливают импортом дампа): docker exec vector-postgres pg_dump -U postgres -d vector_mchs \ --exclude-table='planet_osm_*' -F c -f /tmp/vector_app_$(date +%F).dump ``` Рекомендация: ежедневный cron прикладного дампа (он небольшой) + еженедельный полный. Хранить копии вне сервера. --- ## 16. Мониторинг и логи ```bash docker compose logs -f # все сервисы docker compose logs -f backend # API + аудит-сообщения docker compose logs -f frontend # сборка CRA / ошибки компиляции docker stats # потребление контейнеров ``` Ключевые события в логах backend: `admin closed case ... операция(ий) завершены` (синхронизация закрытия), ошибки расчёта (полный traceback uvicorn). --- ## 17. Диагностика проблем | Симптом | Причина | Решение | |---------|---------|---------| | Логин даёт 422 | JSON вместо form-urlencoded | Логин строго `application/x-www-form-urlencoded` | | «Session expired or revoked» сразу после логина | Несовпадение sha256-токена | Убедиться, что БД и backend на одной БД; пересоздать сессии | | Селекты подразделений пусты | Не выполнен сид юнитов | `python backend/seed_units.py` | | `alembic upgrade` → DuplicateTable | create_all создал таблицы раньше миграций | `scripts/prod-stamp-backfill.sql`, затем upgrade | | Зоны «всегда вверх-вправо» | Расчёт по case_id терял tnp_lat/lon | Исправлено; при доработках сверять имена полей карточки с входом движка | | Расчёт падает TypeError float×None | Payload содержит None-поля | SearchInput.to_case_data() выбрасывает None — регресс-тест есть | | Правка .env не применилась | restart не перечитывает env | `docker compose up -d backend` (пересоздание) | | Импорт OSM OOM | Мало RAM | Параметры --cache 800 --number-processes 2 уже в скрипте; закрыть лишние сервисы | | КОНТУР недоступен при отправке зон | Нет связи/токена | curl до CONTOUR_API_URL; проверить CONTOUR_TOKEN; после правки env — up -d | | Тайлы карты не грузятся | Нет интернета у браузера | Для полного offline — локальный tile-сервер (в планах) | --- ## 18. Чек-лист развёртывания - [ ] Docker + Compose установлены - [ ] Код получен (`/root/vector`), `.env` создан из `.env.example` - [ ] `JWT_SECRET` заменён на случайный; пароль БД сменён (compose + DATABASE_URL) - [ ] `docker compose up -d` — 4 контейнера Up - [ ] `alembic current` = `009_e3_operations` - [ ] `seed_users.py` выполнен, пароль админа сменён при первом входе - [ ] `seed_units.py` выполнен (142 подразделения в селектах) - [ ] PostGIS установлен в контейнере БД, extension создан - [ ] Дамп OSM импортирован (`b16-import.sh`), таблицы заполнены - [ ] Логин через UI работает, смена пароля обязательна - [ ] Пробный поиск: карточка → анализ → зоны на карте, радиус соответствует контрольным точкам - [ ] Создан тестовый пользователь ОУМЧС — скоуп видимости проверен - [ ] Завершение поиска: исход внесён, кейс в архиве, «прогноз vs факт» отображается - [ ] (опционально) КОНТУР: env-переменные, пересоздание backend, тестовая отправка зон - [ ] (опционально) HTTPS/обратный прокси настроен, CORS обновлён - [ ] Cron резервного копирования настроен, копия выгружена вне сервера - [ ] Внешние ИИ/API-ключи отсутствуют в `.env` и `docker-compose.yml` (политика закрытого контура) --- *Сопровождение: репозиторий [`Sadmin/vector`](http://192.168.0.106:3000/Sadmin/vector), план работ — `vector_tasks.md`, описание системы — [README.md](README.md).*