Blog
Frigate NVR: Local Cameras and AI Detection, Without the Cloud Subscription
Cloud cameras are convenient — pretty app, timely push notifications, and when one breaks you just swap it. But the fact that my footage lives on someone else's disk never let me sleep easy. In November I moved my two cameras — front door and yard — over to a local Frigate setup: RTSP into local inference, event-based recordings landing on my own ZFS pool. I'll write this in the order of my shopping diary: money and hardware first, then config, then how the disk math shakes out.
Shopping diary: cameras, host, Coral
Week one was about confirming the cameras could actually output RTSP. That's the baseline. One consumer cam that only worked through its own app went straight back for a refund; another, from a domestic brand, had the /stream0 main and /stream1 sub streams buried in its firmware — the docs were incomplete and I only found them by digging through community forum posts. Create a dedicated read-only user for the credentials; don't put your admin account into the Frigate config.
For the host, I didn't run out and buy a dedicated NVR box. I used an existing small machine with a USB port, running detection on the CPU first with the frame rate dialed down to something tolerable. Ten days in, the CPU was sitting at medium-to-high load pretty much permanently and the fan was loud at night — so a Coral USB got ordered in week two. Once it arrived, map /dev/bus/usb into the container and confirm the apex device shows up; if you go the PCIe route, re-check /dev/apex_0 after driver and kernel updates. The Coral isn't magic — model loading, resolution, and detection zones still need tuning — but it turned person detection from pegging the whole host into background-noise-level usage.
Recordings don't go on the system disk. I carved out an NFS share on the NAS for the Frigate recording directory, and the system disk only holds config and the database. Your shopping list also needs network cable and PoE: two cameras on a PoE switch means two fewer wall warts and much cleaner wiring. Brackets, waterproof boxes, and outdoor-rated cable are what actually blow the budget, far more than "one more Coral" — write that down so you're not only staring at the AI accelerator. Power and cooling belong on the list too: the Coral and the host stuffed into the utility box need airflow. A thermal reboot in a stuffy summer cabinet is more miserable than any false positive.
Config: sub-stream for detection, main stream for recording
A stable stream matters more than maxed-out resolution. The standard pattern: sub-stream feeds detect, main stream feeds record. Detection at 1280×720 is plenty for person detection — no need to push 4K through the inference pipeline. Sample config below; passwords go in environment variables or a tightly permissioned file, never in git:
cameras:
gate:
ffmpeg:
inputs:
- path: rtsp://user:pass@ip:554/stream1
roles: [detect]
- path: rtsp://user:pass@ip:554/stream0
roles: [record]
detect:
width: 1280
height: 720
MQTT hooks into Home Assistant, and notifications only fire on person detection inside a specified zone. Week one, leaves, cats, and the corridor in the building across the street will blow up your phone — tighten the zone boxes, object filters, and minimum object stay time gradually. Don't just disable notifications out of frustration; that's the same as never having installed it. Without a Coral, first lower the detection framerate and resolution, confirm RTSP stays up and the recording directory is writable, then add hardware acceleration. Change ten knobs at once and you won't know whose fault the breakage is.
Once hardware acceleration is in, think of daytime and nighttime thresholds separately: IR footage is noisy, and one shared sensitivity setting will false-positive all over the place. Masking off the balcony across the way and the tree branches is much cleaner than blindly dropping the global confidence threshold. Write the recording codec and snapshot strategy into the config comments — six months from now you'll want to know why you set things the way you did.
Disk math: daily growth, retention days, and what happens when it fills up
Estimate daily growth from the camera bitrate. A main stream around 4 Mbps running continuously comes to a few GB to a dozen-plus GB per day (it varies with motion in the scene); event-based recording is much smaller and depends on trigger frequency. Two cameras with 14 days of events vs. 24/7 continuous recording plus 30 days of retention are completely different orders of magnitude. I think of event clips and continuous recording separately: the front door leans event-driven plus a short continuous buffer so I can review who passed by; the garage can be shorter.
A full disk means broken recordings, database errors, and all-night debugging. Watch the free space on the NFS share and Frigate's own disk alerts; prefer shorter retention over a full disk. When upgrading Immich or some other service, don't accidentally mount it to the same pool that just filled up. Privacy and the law go in the ledger too: only frame your own property within reason, and mind compliance if the view catches a public sidewalk. Put auth on the dashboard and streaming endpoints — the NVR web UI never runs naked on the public internet.
The maintenance cost of a local NVR is real: firmware, password rotation, Coral drivers, disk lifecycle. Back up the database and config directory separately — don't trust that "the video files are still there." One botched cleanup deleted the event index; the clip files remained but were nearly impossible to search. Since then, config and DB go into restic, and the recordings themselves ride on retention policy plus disk space monitoring.
Once the nighttime false positives were down, notifications became useful again. The last line in my shopping diary is accepting the ops time itself — buying the hardware is only the first half. Calibrating zones, doing the disk math, and being clear about the privacy boundary is what makes an NVR you can keep running for years. The peace of mind of "footage in my own pool" is something a monthly subscription can't sell you — but that peace of mind only holds if you're willing to keep paying the maintenance cost.