Перейти к содержанию

OFFLINE_RUNBOOK — эксплуатация Iris VMS в полностью автономном (air-gapped) режиме

Этот документ описывает работу Iris VMS без доступа к публичному интернету. Iris спроектирован так, что весь основной функционал выполняется локально (на хосте и в пределах LAN). Документ охватывает: что работает без интернета, что отключается, какие переменные окружения требуются, как развернуть LAN-сайдкары, как заранее загрузить модели, как перенаправить резервные копии на локальный MinIO и как проверить нулевой исходящий трафик.


1. Что работает при нулевом доступе в интернет (всё в пределах LAN)

Runtime Iris уже способен работать в air-gap: модели кэшируются локально, SPA самодостаточен (включая встроенный hls.js), телеметрии и «звонков домой» нет. На локальном GPU (класс T4/L4, 16 ГБ) и в пределах LAN полностью функционируют:

  • Приём камер — RTSP/ONVIF ingest.
  • Запись событий — ffmpeg -c copy (около 0% CPU).
  • Детекция — YOLO.
  • Распознавание лиц — face recognition.
  • Сквозные идентичности — cross-camera re-ID.
  • Аналитика.
  • Аудит безопасности камер — RTSP/ONVIF/Dahua/Hikvision/XM.
  • Управление PTZ/ONVIF.
  • STT / перевод / дубляж / субтитры — через LAN-сайдкары (см. раздел 4). Сайдкары fail-open: если они недоступны, основной конвейер продолжает работать, отключается лишь соответствующая речевая функция.

Архитектура остаётся прежней: два Docker-контейнера — vms (FastAPI API + воркеры по одной подпроцесс-камере) и vms-scanner (crash-isolated discovery/audit). SQLite (WAL) — единственный источник истины. SPA — vanilla-JS без сборки.


2. Что отключается в offline-режиме

Единственные функции, требующие публичного интернета, отключаются настройкой offline_mode:

  • Shodan camera search — поиск камер через Shodan.
  • yt-dlp web-link ingest — приём по веб-ссылке.

При включённом offline_mode обе функции выключены. Весь остальной функционал из раздела 1 не затрагивается.


3. Обязательные переменные окружения

Для гарантированно локальной загрузки моделей (без обращений к Hugging Face Hub) задайте:

HF_HUB_OFFLINE=1
TRANSFORMERS_OFFLINE=1

MiVOLO (age/gender) теперь учитывает local_files_only, поэтому при этих переменных он берёт веса только из локального кэша.

Дополнительно убедитесь, что включён:

offline_mode = true

4. Самостоятельный хостинг LAN-сайдкаров

Опциональные AI-сайдкары размещаются в LAN и работают по принципу fail-open (их недоступность не роняет основной конвейер). Стандартные адреса:

  • whisper-xtts (STT):8000.
  • ollama + EuroLLM (перевод):11434.
  • xtts dub — дубляж.
  • mediamtx — для browser-cam (ingest с браузерной камеры).

Разверните эти сервисы на хостах внутри LAN, заранее загрузив их модели в их локальные кэши (на машинах без интернета — перенесите кэши вручную). Iris обращается к ним по LAN-адресам; при отсутствии ответа соответствующая речевая функция просто отключается.


5. Предварительная загрузка models/

Каталог models/ должен быть заполнен заранее (на машине с интернетом или переносом носителя), чтобы runtime ничего не скачивал. Туда входят модели детекции, лиц и re-ID, используемые Iris. При выставленных HF_HUB_OFFLINE=1 и TRANSFORMERS_OFFLINE=1 все компоненты, поддерживающие local_files_only, читают веса исключительно из локального кэша/каталога models/.

Замечание о лицензиях моделей (release-gate, отложено): YOLOv8 — AGPL; InsightFace buffalo_l — non-commercial; OSNet/MSMT17 — research-only. Для поставляемого on-prem-продукта это худший случай. Путь ремедиации описан в docs/LICENSING.md (переход на RTMDet/RT-DETR + DINOv2; лицензировать-или-отложить лицо). На данном этапе риск принят и устранение отложено.


6. Перенаправление резервных копий на on-prem MinIO

Скрипты резервного копирования (scripts/backup_*.sh через rclone) перенаправляются на локальный MinIO через переменную S3_ENDPOINT. Укажите её на адрес внутреннего MinIO, чтобы бэкапы не уходили за пределы периметра:

S3_ENDPOINT=http://<minio-host-в-LAN>:9000

Так весь цикл резервного копирования остаётся внутри LAN.


7. Безопасность в автономном развёртывании

Уже применено в runtime:

  • Контейнер запускается non-root (uid 1000), с cap_drop: ALL и no-new-privileges.
  • Исходный код смонтирован read-only.
  • Привязка только к loopback 127.0.0.1:8120 за nginx.

Шифрование секретов at-rest: app/crypto.py шифрует секретные поля (например, cameras.onvif_password) — stdlib HMAC-CTR, схема encrypt-then-MAC; ключ берётся из IRIS_SECRET_KEY или из data/secret.key (права 0600) и никогда не хранится в БД. Полнодисковое шифрование LUKS — основной механизм защиты at-rest.

Аутентификация сегодня доверяет SSO-заголовку X-Email (встроенного логина/ролей пока нет — запланированный пункт WS2).


8. Процедура проверки нулевого исходящего трафика (VERIFY-ZERO-EGRESS)

Цель — убедиться, что в боевом режиме Iris не инициирует ни одного соединения в публичный интернет.

Шаг 1. Deny-all исходящий firewall. Закройте весь исходящий трафик за пределы LAN на хосте. Разрешите только нужные внутренние направления (камеры, LAN-сайдкары :8000 / :11434 / mediamtx, MinIO S3_ENDPOINT). Всё остальное (особенно 0.0.0.0/0 наружу) — запретить.

Шаг 2. Функциональный тест. При активном deny-all прогоните основные сценарии из раздела 1 и убедитесь, что они работают полностью:

  • приём RTSP/ONVIF-камер и запись событий;
  • детекция, распознавание лиц, сквозные идентичности (re-ID);
  • аналитика и аудит безопасности камер;
  • управление PTZ;
  • STT/перевод/дубляж/субтитры через LAN-сайдкары (а при их отключении — корректный fail-open без падения конвейера).

Убедитесь также, что offline_mode включён и интернет-функции (Shodan, yt-dlp web-link) недоступны, как и ожидается.

Шаг 3. Подтверждение отсутствия интернет-соединений. Во время и после функционального теста проверьте, что у процессов Iris нет установленных соединений к публичным адресам (только LAN-узлы: камеры, сайдкары, MinIO). Firewall с deny-all не должен зафиксировать ни одной разрешённой исходящей сессии в интернет, а все сценарии при этом обязаны успешно отрабатывать. Это и подтверждает, что Iris эксплуатируется полностью автономно.