Skip to content

Iris — Deployment configuration reference

One page, one source of truth for every knob you set when deploying Iris. Русская версия: DEPLOYMENT_CONFIG.ru.md.

All tunables live in app/config.py (Settings) and are read via get_settings(); set them in .env (device) or the license-server env (cloud). Nothing here ships enabled by default — a plain docker compose up runs a permissive dev box. You turn the commercial/appliance behaviour on explicitly, per the edition you are shipping.


1. Editions at a glance

Edition model_license_clean biometrics_enabled license_enforce Ships
Dev / eval (default) false true false Runs unchanged, unlicensed, all features — for development only
Detection-only, license-clean ⭐ sellable today true false true RT-DETR (Apache), no AGPL/non-commercial/research models, no biometrics
Commercial full (customer-licensed face) true true true + face-anchored identity under the customer's own face-model licence

model_license_clean=true forces the Apache RT-DETR detector + DINOv2 appearance backend (no AGPL YOLOv8 / research OSNet). biometrics_enabled=false is the legally-clean default for a paid box without a commercial face-model licence + biometric legal basis. See LICENSING.md and COMPLIANCE.md.


2. Master switches (device .env)

Setting Default What it does
model_license_clean false License-clean edition: force Apache RT-DETR + DINOv2, no copyleft/research models
biometrics_enabled true Master gate: false = detection-only (face/reid/age-gender off)
detector_backend yolo yolo | rtdetr (Apache) | deepstream | cpu. Forced to rtdetr by the clean edition
reid_appearance_backend osnet osnet (research) | dinov2 (Apache). Forced to dinov2 by the clean edition
faces_enabled / reid_enabled true Per-feature toggles (also gated by biometrics_enabled)
auth_required true Fail-closed: reject requests with no SSO header / API key
local_auth_enabled false Appliance login + RBAC (signed session cookie). Off → SSO-header path
offline_mode false Air-gap: no outbound calls; pair with HF_HUB_OFFLINE=1

3. Licensing & trial

Device (.env)

Setting Default What it does
license_enforce false Ships inert. true = enforce camera cap + module entitlements from the signed licence. Fail-open on error
license_path data/license.json Signed, hardware-bound licence file
trial_auto_enabled false On first boot with no licence, auto-request a trial
trial_server_url "" HTTPS licence server for the auto-trial

License server (cloud env — our infra, not shipped; see cloud/README.md)

Env Default What it does
IRIS_LS_ADMIN_TOKEN Admin secret for /admin/* (token mint, revoke)
IRIS_LS_KEY Vendor private signing key (gen_vendor_key.py; HSM in prod)
IRIS_TRIAL_DAYS 7 Free-trial term = 7 days. Matches EULA §1a; do not raise without editing the EULA (a test locks the default)
IRIS_TRIAL_MODULES "" (all) Trial entitlements; empty = full-feature trial
IRIS_TRIAL_CAMERAS unset (∞) Trial camera cap
IRIS_HEARTBEAT_URL Heartbeat endpoint baked into issued licences
IRIS_STRIPE_WEBHOOK_SECRET / IRIS_YOOKASSA_SECRET Billing webhooks (world / RU)

Trial vs paid, at a glance:

Trial Paid
Features Full (all modules) Per purchased tier
Term 7 days Purchased subscription
Offline Nonegrace_days=0, heartbeat required (won't run offline; needs a live check-in) grace_days 30–90 (runs offline within grace)
Per machine One (keyed on the immutable GPU UUID) Bound to deployment hardware
Acceptance EULA §1a, accepted at install Order form + EULA

The device's public verify key is baked in as IRIS_LICENSE_PUBKEY_N / IRIS_LICENSE_PUBKEY_E (printed by scripts/gen_vendor_key.py). Verify the whole lifecycle without a real deployment: scripts/demo_license_e2e.py (paid) and scripts/demo_trial_e2e.py (trial).


4. .env templates

Detection-only, license-clean appliance (sellable today):

AUTH_REQUIRED=true
MODEL_LICENSE_CLEAN=true          # → RT-DETR (Apache) + DINOv2; no copyleft/research models
BIOMETRICS_ENABLED=false          # detection-only; no face/reid/age-gender
LICENSE_ENFORCE=true              # enforce the signed licence
LICENSE_PATH=data/license.json
LOCAL_AUTH_ENABLED=true           # appliance login + RBAC
OFFLINE_MODE=true                 # air-gap (pair with HF_HUB_OFFLINE=1)

Commercial full (customer holds a face-model licence + legal basis):

MODEL_LICENSE_CLEAN=true
BIOMETRICS_ENABLED=true           # face-anchored identity ON (customer responsibility, EULA §4)
LICENSE_ENFORCE=true
TRIAL_AUTO_ENABLED=true           # optional: 7-day auto-trial on first boot
TRIAL_SERVER_URL=https://lic.example.com

Provision an appliance with the commercial defaults in one shot: EDITION=commercial scripts/provision_appliance.sh (biometrics off, RT-DETR, integrity on, derived key, local auth + offline + licence enforce; prints the hardware fingerprint to licence).


5. Security posture (defaults are already fail-closed)

  • auth_required=true; the SSO identity header overrides any client value (anti-spoof); api_key compared with hmac.compare_digest.
  • The runtime container runs non-root, cap_drop:[ALL], no-new-privileges, source mounted read-only; all writes go to data/. Binds only 127.0.0.1:8120 (nginx terminates TLS + SSO).
  • RTSP credentials masked in every API response; ffmpeg gets -protocol_whitelist (anti-SSRF); uploads have a decompression-bomb guard; file paths are traversal-contained.
  • Licence/integrity signatures are stdlib RSA-PKCS1v15-SHA256; vectors use numpy.frombuffer (never pickle). See SECURITY.md, CODE_PROTECTION.md.

DEPLOYMENT.md · APPLIANCE_DEPLOYMENT.md · APPLIANCE_HARDENING.md · OFFLINE_RUNBOOK.md · RELEASE_RUNBOOK.md · LICENSE_SERVER_SPEC.md · LICENSING.md · legal/EULA.md