Argus is a FastAPI backend, a React SPA, and three external binaries (go2rtc, FFmpeg, and optionally rclone) wired together into a single Windows installer or Linux tarball. The design choice that shapes most of its security properties is where those binaries sit relative to the network.
Stream topology
Every camera connection is RTSP, terminated once by go2rtc, which fans the stream out internally to two independent consumers: the FFmpeg recorder and the motion detector. Neither consumer re-requests the stream from the camera, so adding recording or detection doesnât multiply the load on camera hardware.
go2rtcâs own ports (1984 for its API, 8554 for RTSP, 8555 for WebRTC/RTP) bind to 127.0.0.1 only. FastAPI reverse-proxies go2rtcâs HTTP and WebSocket traffic through port 8080, the same port serving the REST API and the built React frontend. This means the browserâs WebRTC negotiation (trickle ICE over WebSocket) also goes through 8080; the only exception is the UDP media itself, which needs 8555 opened separately for LAN or remote clients. The Windows installerâs service-install.ps1 opens these firewall rules automatically; on Linux itâs manual.
Recording vs. detection
Recording and detection are deliberately decoupled processes reading the same go2rtc feed:
- Recorder: FFmpeg in stream-copy mode, no transcoding, writing fragmented MP4 in
SEGMENT_SECONDS-length chunks (default 120s). Fragmentation means a crash or power loss loses at most the current segment, not the whole recording session. Record mode is configurable per camera:continuous,motion-only, ormotion-events. - Detector: frame-diff plus a scipy blob filter, sampled at
DETECT_FPS(default 2). Privacy masks (normalized{x,y,w,h}rectangles, JSON-configured per camera) are applied before detection runs, not after, so masked regions never reach the motion or face pipeline. Arm schedules (JSON{days,start,end}blocks) gate when the detector runs at all. Hikvision cameras can bypass frame-diff and subscribe to the cameraâs own ISAPI VMD alert stream instead, which is lower-latency than software motion detection.
Face recognition sits downstream of the detector, using InsightFaceâs buffalo_sc model (512-d embeddings, ONNX runtime, CPU-only â no GPU or external inference dependency). Embeddings are persisted as raw float32 byte arrays, not pickled Python objects, which rules out pickle deserialization as an attack vector if the embedding store is ever reachable by an attacker.
Identity and secrets
ARGUS_SECRET_KEY does double duty: it signs JWTs and serves as the Fernet key encrypting camera RTSP credentials at rest. RBAC has three tiers (admin/operator/viewer), enforced at the route level; user management, audit log access, and recording purges require admin. Every authentication event and mutating action (user create/update/delete, password reset, camera change) is written to an audit log with actor, IP, and timestamp, with a paginated viewer and purge capability gated to admin.
First login after install uses a fixed default password (Screenshot123!); the frontend blocks all navigation until itâs changed, and any admin-created user is flagged must_change_password=1 on creation, forcing the same flow.
Outbound notifications (Telegram, ntfy, SMTP, webhook, FCM, Web Push) are configured via the Settings page and stored in the database, not .env â so credentials for those channels arenât sitting in a plaintext config file on disk. Webhook payloads are signed with HMAC-SHA256 in an X-Argus-Signature header for receiver-side verification. The settings API itself whitelists recognized keys, which blocks arbitrary key injection through that endpoint.