6.9 KiB
Architecture · Overview
This is the high-level technical view. For specific subsystems see the sibling files in this folder.
The four tiers
┌──────────────────────────────────────┐
│ Hub (EU sovereign bare-metal) │
│ - multi-site control plane │
│ - cross-site forensic search │
│ - operator auth (Keycloak) │
│ - long-term embeddings index │
└────────────────┬─────────────────────┘
│ MQTT bridge over TLS
│ + HTTPS for blob storage
│
╔══════════════╪══════════════╗
║ │ ║ per-site
║ ┌─────────▼─────────┐ ║ boundary
║ │ Router (OpenWrt) │ ║
║ │ - mosquitto │ ║
║ │ - tailscale │ ║
║ │ - GitOps recon. │ ║
║ │ - SPA host │ ║
║ │ - reverse proxy │ ║
║ └────┬─────────┬────┘ ║
║ │ │ ║
║ VLAN-10 VLAN-20 ║
║ cameras compute ║
║ ┌──┐ ┌──┐ ┌────────┐ ║
║ │c1│ │c2│ │ Cell │ ║
║ └──┘ └──┘ │RK3588 │ ║
║ ... │ │ ║
║ │frigate │ ║
║ │enricher│ ║
║ │re-id │ ║
║ │healthd │ ║
║ └────────┘ ║
║ ▲ ║
║ │ ║
║ ▼ ║
║ (optional Core) ║
║ ┌─────────────┐ ║
║ │ Jetson Orin │ ║
║ │ federates │ ║
║ │ N Cells │ ║
║ └─────────────┘ ║
╚══════════════════════════════╝
Data flow
Capture: cameras (RTSP) and microphones publish to the Cell.
Inference: Frigate runs detection on streams, generates events. Enricher consumes events and produces embeddings, hashes, re-ID vectors.
Bus: everything flows over MQTT topics on the local broker. The contract is documented in mqtt-contract.md.
Storage:
- Raw video clips → Cell's encrypted disk (NVMe hot + HDD cold). Never bridged.
- Embeddings + metadata → Cell's local index, optionally bridged to hub.
- Snapshots → local only.
- Aggregated health/state → bridged to hub.
Console: SPA hosted by the router. Talks to the router via /api/router/* (ubus) and to the Cell via /api/cell/* (reverse-proxied by the router).
Configuration: GitOps repos cloned by the router. Reconciled every 5 minutes. See ADR-0004.
Egress sovereignty: only what the bridge policy explicitly allows leaves the site. See data-sovereignty.md.
Key technologies
| Layer | Choice |
|---|---|
| Router OS | OpenWrt 23.05+ |
| Router hardware | GL.iNet GL-MT6000 (default), Banana Pi BPi-R4 (alternative) |
| Cell OS | Balena OS on RK3588 |
| Cell hardware | Banana Pi BPI-W3, Radxa Rock 5B+ |
| Edge AI engine | Frigate v0.14+ with RKNN |
| Models | YOLOv8n (detection), CLIP (embeddings), reid models, Whisper-v3 (audio) |
| Broker | Mosquitto with bridge |
| Time sync | chrony with NTS |
| VPN | Tailscale |
| GitOps | Git + cron-driven reconcile (custom ucode script) |
| Hub OS | Debian on Hetzner bare-metal |
| Hub services | Mosquitto, MinIO, Qdrant, TimescaleDB, Keycloak, Caddy |
Provisioning lifecycle
- Image build: OpenWrt Image Builder produces a router firmware with
luci-app-blocao-consoleand dependencies. - First boot: router shows the wizard at
http://blocao-router.local/. Installer goes through 6 steps. - Cell enrollment: Cell devices on the local network are auto-discovered (mDNS + MQTT announce). Balena handles their provisioning over the air.
- GitOps repos: created by the wizard at hub side. Site repo is initialized with applied UCI config.
- Hub registration: router exchanges enrollment token for mTLS cert. Bridge starts. Sites Overview at hub now shows the new site.
- Camera onboarding: scan VLAN-10, identify, authenticate, test, configure. GitOps commit + Frigate reload.
- Operator login: console at the router via Tailscale or local network.
Failure modes considered
| Failure | Mitigation |
|---|---|
| WAN down | Site continues operating; events queue locally; bridge resumes when WAN returns |
| Hub down | Router operates standalone; queue grows; reconnects automatically |
| Cell crash | Frigate auto-restarts via Balena; events buffered; selftest alerts in <30s |
| Camera offline | Detected by selftest; alert in SYNOPSIS and CAMS; doesn't block other cameras |
| Bridge cert expires | Selftest warns 90 days before; auto-renewal planned (currently manual) |
| GitOps push conflict | Reconcile fails, alerts via _bridge/status, last-known-good remains applied |
| Cell disk full | Retention rotates oldest first; soft alert at 75%, hard at 85%, evidence locker has separate quota |
| Operator forgets password | Router has local recovery via console port; hub has Keycloak admin recovery |
Out of scope (for design phase)
- Mobile operator app — explicitly post-MVP.
- Real-time video streaming to operator over WAN — bandwidth-prohibitive, only on-demand clips.
- Automated camera positioning / PTZ control — vendor-specific, deferred.
- Cross-site real-time correlation (e.g., follow a vehicle across sites in real time) — analytics-grade feature, post-MVP.
See also
tiers.md— detailed roles per tier.mqtt-contract.md— MQTT topic schema.data-sovereignty.md— what stays local, what leaves.storage-retention.md— capacity planning.network-topology.md— VLANs, firewall, segmentation.