Configure Home Surveillance System
I spent months trying cloud-based security cameras before realizing I was paying recurring fees for a solution that sent my footage to a corporation's servers. Now I run Frigate—an open-source NVR (Network Video Recorder)—on my homelab, and I control everything: the footage stays encrypted at home, I own the storage, and I can set up intelligent detection without subscriptions. In this guide, I'll walk you through building a self-hosted surveillance system that rivals commercial alternatives at a fraction of the cost.
Why Self-Host Surveillance?
When I evaluated my options, the math was clear. Cloud services charge $10–30 per camera monthly. A cheap IP camera costs $30–80 upfront. After a year, you've paid more for the service than the hardware itself. Beyond cost, self-hosting gives you:
- Privacy: Your footage never leaves your network unless you want it to.
- Local processing: AI detection happens on your hardware—no API calls, no latency spikes.
- Retention control: Store as much or as little as your drives allow, not what a plan allows.
- Flexibility: Mix camera brands, add storage on demand, integrate with Home Assistant or Node-RED.
The tradeoff? You manage the system. But if you've built a homelab, you can handle it.
Hardware You'll Need
I recommend this baseline setup:
- NVR Server: A Micro PC (Intel N100-based, ~$200–300) or repurposed laptop. Frigate runs light—aim for 4 CPU cores and 4GB RAM minimum.
- Storage: 2–4TB of internal or NAS storage. Surveillance writes 24/7, so use surveillance-grade drives (WD Purple, Seagate SkyHawk) or NAS drives (WD Red).
- IP Cameras: Reolink PoE cameras ($50–100 each) or Wyze cams ($20–40). I prefer PoE—power and data over one cable means cleaner installs.
- PoE Switch: If using PoE cameras, a managed PoE switch (Netgear GS110MX, ~$100) powers them all.
- Optional—Coral TPU: A USB Coral accelerator ($50–75) speeds up object detection tenfold. Your CPU will thank you.
Total? Under $1,000 for a 4-camera system with local storage. A month of cloud subscriptions often cost more.
Install Frigate with Docker Compose
Frigate is the heart of the system. It pulls RTSP streams from your cameras, runs object detection (people, cars, dogs), and records to disk. I deploy it via Docker Compose because it's reproducible and easy to update.
First, set up Docker and Docker Compose on your NVR server (Ubuntu 22.04 LTS is my go-to). Then create this directory structure:
mkdir -p ~/frigate/{config,storage/clips,storage/snapshots}
cd ~/frigate
Now, create your docker-compose.yml:
version: '3.8'
services:
frigate:
image: ghcr.io/blakeblackshear/frigate:stable
container_name: frigate
privileged: true
restart: unless-stopped
shm_size: '256mb'
environment:
- FRIGATE_UID=1000
- FRIGATE_GID=1000
ports:
- "5000:5000"
- "8554:8554"
- "8555:8555/udp"
volumes:
- ./config:/config
- ./storage:/media/frigate
- /etc/localtime:/etc/localtime:ro
devices:
- /dev/bus/usb:/dev/bus/usb # For Coral TPU
networks:
- frigate
frigate-db:
image: postgres:15-alpine
container_name: frigate-db
environment:
POSTGRES_DB: frigate
POSTGRES_PASSWORD: frigatepw
POSTGRES_USER: frigate
volumes:
- ./db:/var/lib/postgresql/data
restart: unless-stopped
networks:
- frigate
networks:
frigate:
driver: bridge
Next, create the core Frigate configuration at config/config.yml. This is where you define cameras, detection zones, and retention:
# config/config.yml
logger:
default: info
logs:
frigate.event: debug
database:
host: frigate-db
port: 5432
dbname: frigate
user: frigate
password: frigatepw
mqtt:
enabled: false
detectors:
coral:
type: edgetpu
device: usb
objects:
track:
- person
- car
- dog
- cat
cameras:
front_door:
ffmpeg:
inputs:
- path: rtsp://192.168.1.100:554/stream1
roles:
- detect
- record
detect:
width: 1280
height: 720
fps: 5
objects:
filters:
person:
min_area: 1500
max_area: 100000
threshold: 0.7
zones:
driveway:
coordinates: 0,0,400,300,500,720,0,720
record:
enabled: true
retain:
days: 7
mode: motion
snapshots:
enabled: true
retain:
default: 10
objects:
person: 30
backyard:
ffmpeg:
inputs:
- path: rtsp://192.168.1.101:554/stream1
roles:
- detect
- record
detect:
width: 1280
height: 720
fps: 5
record:
enabled: true
retain:
days: 14
mode: all
snapshots:
enabled: true
snapshots:
enabled: true
timestamp: false
bounding_box: true
telemetry:
enabled: true
192.168.1.100 and 192.168.1.101 with your actual camera IPs. Find them by logging into your router or using nmap -p 554 192.168.1.0/24 to scan for RTSP ports.Start the containers:
docker compose up -d
Check logs to confirm Frigate connects to your cameras:
docker compose logs -f frigate
You should see successful RTSP connections. If a camera fails, verify the stream URL by opening it in VLC: File → Open Network Stream → rtsp://192.168.1.100:554/stream1.
Access the Web UI and Configure Zones
Open your browser to http://192.168.1.X:5000 (replace X with your NVR's IP). The Frigate interface loads live feeds, event history, and system stats. You'll see each camera stream immediately.
The real power comes from configurable zones. In the config above, I defined a "driveway" zone for the front door—Frigate only triggers alerts when a person enters that area. This cuts false alerts from passing cars or distant activity. Adjust coordinates by editing the config and restarting:
docker compose restart frigate
Recording and Retention Strategy
I use two retention modes: continuous recording for less critical cameras (backyard gets 14 days), and motion-based for high-traffic areas (front door records only when motion detected, keeps 7 days). This balances storage and coverage.
Calculate storage needs: a 1280×720 H.264 stream uses roughly 500MB–1GB per hour. Four cameras recording continuously = 48GB per day. A 4TB drive holds ~83 days. With motion-only recording, you can stretch that to months.
For larger setups, I recommend a NAS (TrueNAS or Unraid) over your network. Point Frigate to an NFS mount:
mount -t nfs 192.168.1.50:/mnt/surveillance /mnt/surveillance
Then update docker-compose.yml to bind that mount.
Mobile Access and Notifications
For remote access, I use Tailscale VPN. Install Tailscale on your NVR and any phone/laptop, and you're encrypted end-to-end:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Get your Tailscale IP, then access Frigate from anywhere via https://YOUR_TAILSCALE_IP:5000.
For push notifications (person detected, car detected), integrate Frigate with Home Assistant. Home Assistant runs on your homelab, subscribes to Frigate MQTT events, and sends notifications to your phone. Or use Frigate's native webhooks to trigger IFTTT applets.
Performance Tuning with Coral TPU
Without a Coral accelerator, Frigate's CPU detection runs at 2–3 fps per camera on modest hardware. With a Coral TPU USB device, it jumps to 15+ fps while using 10% of the CPU. I consider it essential for systems with 3+ cameras.
To enable it, add the USB device to your compose file (done above) and set the detector model in config:
detectors:
coral:
type: edgetpu
device: usb
num_threads: 3
Frigate automatically downloads the correct model. You can override it for specific cameras or object types if needed.
Backup Strategy
I back up the Frigate config to my Git server weekly and export key events (person/car detections) to a secondary NAS monthly. The database is small (<100MB), so I include it in backups. Raw video stays local—it's massive and re-recordable, so no need to backup.
Use rsync or a cron job:
0 2 * * * rsync -av ~/frigate/config /mnt/backup/frigate-config
Next Steps: Extend Your System
Once Frigate is running smoothly, consider:
- License plates: Add ALPR (Automatic License Plate Recognition) via a separate service like CodeProject.AI.
- 2-way audio: Enable microphones on cameras and stream audio back through the web interface.
- Tiered storage: Archive old footage to cold storage (external drive or cloud), keeping hot storage for recent events.
- Multi-server: Run satellite Frigate instances on edge devices and aggregate to a central dashboard.
Self-hosted surveillance takes work, but the payoff is privacy, control, and a system that gets better as you customize it. Once you've eliminated those monthly cloud subscriptions, you'll wonder why you didn't self-host sooner.