Self-hosted NVR · Build guide
REC · FRIGATE 0.17A self-hosted, local-first NVR: it records your RTSP cameras, runs real AI object detection on the edge (no cloud), and hands events to Home Assistant. This is the shape of a running install, trimmed to what you need to stand up your own.
What you're building
Hardware
| Part | What / why |
|---|---|
| Host | Any Linux box with an Intel CPU that has an iGPU (QuickSync) for cheap video decode. A small SFF/mini-PC is plenty. |
| Detector | Google Coral Edge TPU (USB or PCIe) — runs detection at ~near-zero CPU. Optional: skip it and detect on CPU or the iGPU via OpenVINO. |
| Cameras | Any RTSP cameras that expose a main + sub stream (most Dahua / Hikvision / Reolink do). |
| Storage | A disk sized for your retention. ~1 camera at 1080p continuous ≈ a few GB/day; tune the retain days below. |
The one pattern that matters
This is the trick that keeps detection cheap and recordings sharp. Point Frigate at both of each camera's streams and give them different jobs:
Per camera
Main stream → record role (full quality, saved to disk).
Sub stream (≈720p) → detect role (small + fast for the TPU).
The main is also restreamed by go2rtc so the live view is crisp without a second camera connection.
Then tell each camera which objects to track — this cuts false alerts hard.
| Camera | Tracks |
|---|---|
| front_door | person, cat |
| front_yard | person, car |
| driveway | person, car, cat · + motion mask on a noisy corner |
| shed | person, car, cat · + motion mask |
Deploy · the simple way
The original build runs Frigate in an LXC via Podman — this Compose file is the friendlier equivalent. Drop it in a folder, put your config.yml in ./config, and docker compose up -d.
services: frigate: container_name: frigate image: ghcr.io/blakeblackshear/frigate:stable restart: unless-stopped shm_size: "256mb" # raise for >2 cameras (see Frigate docs) devices: - /dev/apex_0:/dev/apex_0 # Coral PCIe — omit if no Coral - /dev/dri/renderD128:/dev/dri/renderD128 # Intel iGPU (hwaccel) volumes: - /etc/localtime:/etc/localtime:ro - ./config:/config - ./media:/media # recordings live here - type: tmpfs target: /tmp/cache tmpfs: { size: 1000000000 } ports: - "5000:5000" # web UI - "8554:8554" # go2rtc RTSP - "8555:8555/tcp" - "8555:8555/udp" environment: FRIGATE_RTSP_PASSWORD: "your_camera_password"
Deploy · the brains
The whole system is this one file. Below is the working shape with credentials and IPs replaced by <placeholders> — set your own and add cameras by copying the front_door block.
mqtt: enabled: false # true + host: if you use Home Assistant detectors: coral: type: edgetpu device: pci:0 # USB Coral -> "usb"; no Coral -> use cpu/openvino ffmpeg: hwaccel_args: preset-intel-qsv-h264 # Intel iGPU decode record: enabled: true retain: { days: 2, mode: all } # keep everything 2 days alerts: { retain: { days: 2 } } detections: { retain: { days: 10 } } # keep clips w/ objects 10 days go2rtc: # hi-res restream for the live view streams: front_door: - rtsp://admin:<PASSWORD>@<CAM_IP>:554/cam/realmonitor?channel=1&subtype=0 cameras: front_door: ffmpeg: inputs: - path: rtsp://admin:<PASSWORD>@<CAM_IP>:554/cam/realmonitor?channel=1&subtype=0 roles: [record] # main stream = recording - path: rtsp://admin:<PASSWORD>@<CAM_IP>:554/cam/realmonitor?channel=1&subtype=02 roles: [detect] # sub stream = detection detect: { width: 1280, height: 720 } objects: track: [person, cat] # per-camera object list
Those RTSP paths are Dahua's subtype=0 (main) / subtype=02 (sub). Other brands differ — check your camera or the Frigate docs for the sub-stream URL.
Bring it up
docker compose up -d, then open http://host-ip:5000.Worth knowing