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 | None — grace_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_keycompared withhmac.compare_digest.- The runtime container runs non-root,
cap_drop:[ALL],no-new-privileges, source mounted read-only; all writes go todata/. Binds only127.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.
6. Related¶
DEPLOYMENT.md · APPLIANCE_DEPLOYMENT.md · APPLIANCE_HARDENING.md · OFFLINE_RUNBOOK.md · RELEASE_RUNBOOK.md · LICENSE_SERVER_SPEC.md · LICENSING.md · legal/EULA.md