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

Развёртывание устройства Iris (Appliance Deployment)

Документ описывает развёртывание запечатанного устройства Iris VMS на площадке клиента. Iris поставляется как аппаратно-программный комплекс (мы отгружаем железо вместе с ПО): сервер с одним GPU класса NVIDIA T4/L4 и предустановленным образом Iris. Сценарий рассчитан на изолированную (air-gap) сеть — runtime не требует доступа в интернет.

Связанные документы: DEPLOYMENT.md (общее развёртывание), SECURITY.md (модель безопасности), LICENSING.md (лицензирование и риск моделей), ARCHITECTURE.md.


1. Аппаратные и системные требования

Компонент Требование
GPU Один NVIDIA класса T4/L4, 16 ГБ
Драйвер хоста Поддержка CUDA 12.4
Container runtime Docker + NVIDIA Container Toolkit
Хранилище Диск под data/ (записи, сегменты, эскизы, образцы лиц); рекомендуется LUKS full-disk
ОС Linux-хост с поддержкой Docker Compose

GPU обязателен для AI-конвейера (детекция YOLO, распознавание лиц, re-ID). Драйвер хоста должен быть совместим с CUDA 12.4, а NVIDIA Container Toolkit — пробрасывать GPU в контейнер.

Проверка доступности GPU на хосте перед установкой:

nvidia-smi

Резервный режим без GPU (GPU-eviction fallback)

Если GPU недоступен (вытеснен, отказ драйвера, диагностика), runtime можно перевести на CPU, установив:

DETECTOR_DEVICE=cpu

Это деградированный режим для поддержания доступности; производительность AI-конвейера будет существенно ниже.


2. Состав поставки и запечатанный образ

Устройство поставляется с запечатанным Docker-образом, выгруженным через docker save в tar-архив и подписанным поставщиком. На площадке образ проверяется по подписи и загружается локально — без обращения к внешним реестрам.

# Проверка подписи поставки (по приложенной подписи и публичному ключу поставщика)
# затем загрузка образа в локальный Docker
docker load -i iris-appliance-<version>.tar

docker image ls | grep iris

В состав поставки входят:

  • запечатанный образ контейнеров vms и vms-scanner;
  • каталог models/ с локально закэшированными моделями (детекция, лица, re-ID, аудио);
  • образы LAN-сайдкаров AI (опционально, см. §4);
  • per-unit заготовка data/ и файлы конфигурации (.env).

3. Засев моделей и per-unit данных

models/

AI-модели кэшируются локально и не скачиваются в рантайме. Каталог models/ входит в поставку и монтируется в контейнер vms. Для гарантии офлайн-работы выставьте флаги офлайн-режима Hugging Face:

HF_HUB_OFFLINE=1
TRANSFORMERS_OFFLINE=1

Возрастно-гендерная модель MiVOLO теперь учитывает local_files_only, поэтому при выставленных флагах ни одна часть конвейера не пытается обращаться в сеть.

Дополнительно включите офлайн-режим приложения, который отключает единственные две интернет-зависимые функции — поиск камер через Shodan и приём веб-ссылок через yt-dlp:

offline_mode = true

data/ (per-unit)

data/ — это per-unit состояние конкретного устройства: SQLite-БД (единственный источник истины, режим WAL), записи, сегменты, эскизы, образцы лиц. Каталог создаётся при первом запуске и должен лежать на зашифрованном (LUKS) разделе. .env, data/ и models/ не входят в систему контроля версий и содержат конфиденциальные артефакты — обращайтесь с ними соответственно.


4. Контейнеры и LAN-сайдкары AI

Два основных контейнера

  • vms — FastAPI API + менеджеры фоновых задач + по одному worker-подпроцессу на камеру.
  • vms-scanner — изолированный от сбоев контейнер обнаружения/аудита (он не открывает живые камеры, что защищает основной сервис).

Запуск стека:

docker compose up -d
docker compose ps

Опциональные AI-сайдкары (LAN, fail-open)

Расширенный AI-функционал обеспечивают сайдкары, развёрнутые в локальной сети и работающие по принципу fail-open (их отсутствие не ломает основной сервис):

Сайдкар Назначение Порт (LAN)
whisper-xtts STT (распознавание речи) :8000
ollama + EuroLLM перевод :11434
xtts дубляж
mediamtx браузерная камера (browser-cam)

Все сайдкары хостятся в LAN и не требуют выхода в интернет.

Резервные копии

Скрипты резервного копирования (scripts/backup_*.sh через rclone) перенаправляются на локальный (on-prem) MinIO через переменную S3_ENDPOINT — данные не покидают площадку.


5. Сетевая схема

API контейнера vms биндится только на loopback 127.0.0.1:8120. Внешний доступ обеспечивает встроенный обратный прокси (nginx), который терминирует TLS и выполняет SSO-проверку, прокидывая доверенный заголовок идентичности.

[ Клиент ] --HTTPS--> [ nginx (TLS + SSO) ] --HTTP--> [ 127.0.0.1:8120  vms API ]
                                                              |
                                              [ data/ (SQLite WAL, медиа) ]
                                                              |
        LAN AI-сайдкары: whisper-xtts:8000, ollama:11434, mediamtx, xtts

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

Безопасность устройства

Уже реализовано:

  • контейнер выполняется non-root (uid 1000), cap_drop: ALL, no-new-privileges;
  • исходники смонтированы read-only; все записи идут в data/;
  • API доступен только через loopback за nginx;
  • шифрование секретов at-rest (app/crypto.py): чувствительные поля (например, cameras.onvif_password) шифруются по схеме stdlib HMAC-CTR + encrypt-then-MAC; ключ берётся из IRIS_SECRET_KEY либо из data/secret.key (права 0600) и никогда не хранится в БД;
  • LUKS full-disk — основной механизм защиты данных at-rest.

6. Первичная настройка (first-boot)

После загрузки образа и запуска стека:

  1. Сеть. Настройте сетевые параметры хоста и доступ к LAN, где находятся камеры и AI-сайдкары.
  2. TLS / прокси. Установите сертификат в встроенный обратный прокси; проверьте, что внешний доступ идёт только по HTTPS.
  3. Администратор / идентичность. Настройте источник SSO-заголовка X-Email для административного доступа (встроенных логина/ролей пока нет — WS2).
  4. Ключ секретов. Убедитесь, что задан IRIS_SECRET_KEY или сгенерирован data/secret.key (0600) — без него поля секретов at-rest не защищены.
  5. Офлайн-флаги. Выставьте HF_HUB_OFFLINE=1, TRANSFORMERS_OFFLINE=1, offline_mode = true.
  6. Камеры. Добавьте камеры через ingest RTSP/ONVIF; при необходимости используйте обнаружение (vms-scanner). Учётные данные ONVIF шифруются at-rest.
  7. Лицензия (опционально). При включённом enforcement установите подписанную лицензию (см. §8).

7. Проверка работоспособности (smoke-check)

Базовая проверка живости — неаутентифицированный эндпоинт /health:

curl -fsS http://127.0.0.1:8120/health

Дополнительно проверьте:

# контейнеры подняты
docker compose ps

# GPU виден внутри контейнера vms (если не используется DETECTOR_DEVICE=cpu)
nvidia-smi

После этого убедитесь, что внешний HTTPS-доступ через прокси работает, а добавленные камеры дают живой поток и события записываются (ffmpeg -c copy, ~0% CPU).


8. Лицензирование (опционально, по умолчанию выключено)

Подсистема лицензирования (app/licensing/) поставляется инертной; принудительное применение включается настройкой license_enforce. Лицензия — подписанный JSON:

{
  "payload": {
    "license_id": "...",
    "customer": "...",
    "issued": "...",
    "expires": "...",
    "max_cameras": 0,
    "modules": ["faces", "reid", "audit", "audio", "subtitles", "ptz", "analytics"],
    "hardware": "...",
    "hardware_fields": ["gpu", "machine-id", "product_uuid"],
    "heartbeat": { "required": false, "grace_days": 0, "url": "..." }
  },
  "sig": "base64..."
}
  • Подпись: RSA-PKCS1v15-SHA256, проверяется средствами stdlib (app/licensing/rsa_verify.py) с публичным ключом поставщика из IRIS_LICENSE_PUBKEY_N / IRIS_LICENSE_PUBKEY_E.
  • Отпечаток оборудования (app/licensing/fingerprint.py): SHA-256 по выбранным полям; по умолчанию GPU (UUID из nvidia-smi) + machine-id + DMI product_uuid.
  • Гейт функций (app/licensing/gate.py): пустой modules = все модули; иначе только перечисленные; max_cameras ограничивает число камер.
  • Модель — offline-first: подписанная лицензия валидна локально; heartbeat опционален и работает с grace-периодом.

9. Замечание о лицензиях моделей (release-gate, отложено)

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