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) задайте:
MiVOLO (age/gender) теперь учитывает local_files_only, поэтому при этих переменных он берёт веса только из
локального кэша.
Дополнительно убедитесь, что включён:
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, чтобы бэкапы не уходили за пределы периметра:
Так весь цикл резервного копирования остаётся внутри 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 эксплуатируется полностью автономно.