README: назначение/контекст, политика закрытого контура, архитектура, стек, структура репо, БД (21 таблица), матмодель (контрольные точки), OSM-геослой, API (12 роутеров), фронт, RBAC (142 юнита, 4 роли/9 прав), мультипоиск, интеграция КОНТУР, аудит, планы. SETUP_GUIDE: 18 разделов — требования, Docker, .env (смена секретов), миграции/сиды, импорт OSM в PostGIS, проверки, пользователи, КОНТУР, прокси/HTTPS, обновление (up -d для env!), бэкапы, диагностика (11 типовых проблем), чек-лист развёртывания.
20 KiB
ВЕКТОР МЧС — Гайд по развёртыванию на серверах МЧС
Пошаговое руководство для IT-специалистов МЧС Республики Беларусь по развёртыванию системы определения приоритетных направлений поиска (ВЕКТОР) на серверах организации.
Версия документа: 1.0 от 9 сентября 2026 г. Репозиторий:
Sadmin/vector
Оглавление
- Требования к серверу
- Архитектура развёртывания
- Подготовка сервера
- Установка Docker и Docker Compose
- Получение кода проекта
- Конфигурация окружения (.env)
- Запуск сервисов
- Инициализация базы данных (миграции, сиды)
- Загрузка OSM-геослоя (PostGIS)
- Проверка работоспособности
- Создание пользователей и справочника подразделений
- Настройка интеграции с КОНТУР
- Обратный прокси и HTTPS
- Обновление проекта
- Резервное копирование
- Мониторинг и логи
- Диагностика проблем
- Чек-лист развёртывания
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. Подготовка сервера
# 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
# Официальный скрипт (или репозиторий docker-ce — по политике организации)
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker --version # 24+
docker compose version # v2
5. Получение кода проекта
mkdir -p /root/vector && cd /root/vector
git clone http://<gitea-host>:3000/Sadmin/vector.git .
Ключевые ветки: master — рабочая.
6. Конфигурация окружения (.env)
cp .env.example .env
Обязательные переменные:
# Подключение к БД (внутри 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://<kontur-host>:8000
CONTOUR_TOKEN=<токен из КОНТУРа>
НЕ добавлять никаких ключей внешних ИИ/API — по политике закрытого контура их в проекте нет и быть не должно (тест-страж
TestNoLLM).
Пароль БД должен совпадать с POSTGRES_PASSWORD в docker-compose.yml (сервис postgres).
7. Запуск сервисов
cd /root/vector
docker compose up -d
docker compose ps # все 4 контейнера Up/healthy
Первый старт backend создаёт таблицы через init_db (create_all). Порядок применения Alembic-миграций — раздел 8.
8. Инициализация базы данных (миграции, сиды)
8.1 Миграции Alembic
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 — применить стемп-скрипт:
docker exec -i vector-postgres psql -U postgres -d vector_mchs < scripts/prod-stamp-backfill.sql
8.2 Сид первого администратора
docker exec vector-backend sh -c 'cd /app && python backend/seed_users.py'
Создаётся стартовый администратор (логин admin, пароль по умолчанию — сменить при первом входе через форму). Скрипт пропускается, если пользователи уже есть.
8.3 Сид подразделений (142 юнита)
docker exec vector-backend sh -c 'cd /app && python backend/seed_units.py'
Создаёт РЦУ РЧС → 6 ОУМЧС → 135 Г(Р)ОЧС/ПАСО (справочник идемпотентный: существующие названия не дублируются). Без него админка пользователей бесполезна (пустые селекты подразделений).
9. Загрузка OSM-геослоя (PostGIS)
Бэкенд рассчитывает рельеф секторов из локальной OSM. На чистой БД геосервис автоматически fallback'ится на публичный Overpass (медленно, требует интернет) — для продуктива импортируйте дамп.
9.1 Установка PostGIS в контейнер БД
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
# Скачивание (одноразово, ~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 Проверка
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. Проверка работоспособности
# 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) на отдельном сервере. ВЕКТОР отправляет в неё приоритетные зоны.
- В
.env:CONTOUR_API_URL(адрес API КОНТУРа) иCONTOUR_TOKEN(выдаётся на стороне КОНТУРа) docker compose up -d backend— пересоздать контейнер (restart не перечитывает env!)- Проверка: операция → «Отправить зоны в КОНТУР» на странице анализа; при недоступности КОНТУРа бэкенд вернёт понятную ошибку 502 и запишет
contour_send_failedв аудит
Входящие данные (треки групп, проверенные квадраты) — этап B17, в разработке.
13. Обратный прокси и HTTPS
Для доступа пользователей по HTTPS поставьте nginx/traefik перед фронтендом и API:
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. Обновление проекта
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. Резервное копирование
# Полный дамп БД (данные + 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. Мониторинг и логи
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 контейнера Upalembic current=009_e3_operationsseed_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, план работ — vector_tasks.md, описание системы — README.md.