- README: project overview, pricing, deployment model - ARCHITECTURE: system design, data flow, components, security - DECISIONS: Pi Zero 2W, Tailscale, reolink-aio, Wasabi S3 choices - ROADMAP: 3-phase plan (MVP, monetization, expansion) - CHANGELOG: concept (Aug 1) and full documentation (Aug 5) - Customer onboarding information request sheet
6.3 KiB
6.3 KiB
NVR Shield — Architecture
System Overview
┌─────────────────────────────────────────────────────────┐
│ CUSTOMER SITE │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ NVR #1 │ │ NVR #2 │ │ NVR #3 │ (Reolink) │
│ │ 192.168.x│ │ 192.168.x│ │ 192.168.x│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ HTTP API (port 80/443) │
│ ┌───────┴────────┐ │
│ │ Pi Zero 2W │ │
│ │ NVR Shield │ │
│ │ Agent │ │
│ └───────┬────────┘ │
│ │ Tailscale (WireGuard) │
└──────────────────────┼───────────────────────────────────┘
│
INTERNET │
│
┌──────────────────────┼───────────────────────────────────┐
│ ITPP CORE (netcup) │
│ │ │
│ ┌───────┴────────┐ │
│ │ NVR Shield │ │
│ │ Dashboard │ │
│ │ API (:8090) │ │
│ └───────┬────────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ ┌───┴──────┐ │
│ │ Wasabi │ │ Alerting │ │ Monthly │ │
│ │ S3 │ │ (Email/ │ │ Reports │ │
│ │ Backups │ │ SMS) │ │ Generator│ │
│ └─────────┘ └─────────┘ └──────────┘ │
└───────────────────────────────────────────────────────────┘
Components
1. Pi Zero 2W Agent (agent.py)
Runs on Raspberry Pi Zero 2W at customer site. Python 3.
Responsibilities:
- Poll each configured NVR every 60s via Reolink HTTP API (
reolink-aio) - Collect: camera online status, HDD health, storage %, firmware version, uptime
- Push metrics to Core heartbeat endpoint
- Dump full NVR config to Wasabi S3 nightly
- Capture motion/AI-triggered clips and upload to S3 (Pro/Enterprise tiers)
- Accept remote config and update commands from Core
- Run custom AI filtering rules (Enterprise tier)
Config schema (config.yaml):
site_id: "cust-shortname"
heartbeat_url: "https://core.itpropartner.com/nvr-shield/heartbeat"
s3_bucket: "nvr-shield-customer-backups"
s3_prefix: "cust-shortname/"
poll_interval: 60 # seconds
config_backup_time: "03:00" # daily
nvrs:
- name: "Warehouse"
ip: "192.168.1.10"
port: 443
user: "admin"
password: "${NVR_PASSWORD_WAREHOUSE}"
- name: "Front Office"
ip: "192.168.1.11"
port: 443
user: "admin"
password: "${NVR_PASSWORD_FRONTOFFICE}"
2. Core Dashboard / API
FastAPI backend on Core (:8090 path /nvr-shield/).
Endpoints:
| Method | Path | Purpose |
|---|---|---|
| POST | /nvr-shield/heartbeat |
Agent pushes metrics (site_id, nvrs[], metrics) |
| GET | /nvr-shield/dashboard |
Admin dashboard — all sites, health, alerts |
| GET | /nvr-shield/site/{id} |
Per-site detail (cameras, history, clips) |
| GET | /nvr-shield/report/{id}/{month} |
Monthly report PDF/HTML |
| POST | /nvr-shield/agent/{id}/config |
Push updated config to agent |
3. Wasabi S3 Storage
Bucket: nvr-shield-customer-backups
Structure:
s3://nvr-shield-customer-backups/
{site_id}/
configs/
2026-08-01-config.json
2026-08-02-config.json
clips/
2026-08-01/
14-32-15-NVR-Warehouse-Cam3-motion.mp4
reports/
2026-07-monthly-report.pdf
4. Tailscale Network
All Pi Zero 2W devices connect via Tailscale to ITPP's tailnet. Each device tagged tag:nvr-shield. Core communicates with agents over Tailscale IPs, not public internet.
Data Flow
- Health polling (every 60s): Agent → NVR HTTP API → metrics JSON → Core heartbeat endpoint
- Nightly config backup: Agent → NVR HTTP API → config JSON → Wasabi S3
- Incident clips (Pro/Enterprise): NVR motion/AI event → agent detects → clip upload to S3 → notification to Core
- Monthly report: Core cron (1st of month) → aggregates metrics from DB + S3 → generates PDF → emails customer
- Alerts: Core evaluates heartbeat gaps (>2 min = alert), disk thresholds (>90% = alert), camera offline
Security
- Pi filesystem is read-only (overlayfs) to prevent SD card corruption
- SSH key-only, no password auth
- NVR passwords stored in env vars, never in git
- Tailscale WireGuard for all agent-Core communication
- S3 credentials scoped to per-customer prefix only