Deploy Home Surveillance System
When I ditched cloud-based camera subscriptions, I realized how much I was overpaying for basic motion detection and video storage. A self-hosted surveillance system running on a modest homelab setup costs pennies compared to recurring SaaS fees—and you own everything. I'll walk you through setting up Frigate with IP cameras, local storage, and a dashboard you actually control.
Why Self-Hosted Surveillance Makes Sense
Cloud surveillance ecosystems lock you into monthly subscriptions: $10 per camera, $50 for NVR features, $20 for AI detection. After a year with 4 cameras, you've spent $600. Self-hosting costs you the hardware once, then nothing. I prefer Frigate because it's open-source, uses real object detection (YOLO), and runs on commodity hardware—even a Raspberry Pi 4 with an SSD handles 4–6 cameras smoothly.
The real advantages are ownership, privacy, and flexibility. Your footage never touches the internet unless you choose. You can replay events at 3 AM without paying extra. You integrate with Home Assistant, trigger automations, and tinker endlessly.
Hardware and Network Planning
You'll need three layers: cameras, a local NVR/compute box, and storage. I run this stack on a small tower with a Ryzen 5 and 8GB RAM, but I've also tested it on a Beelink SER5 mini PC ($200). For cameras, I use a mix of budget PoE (Power over Ethernet) turrets from Dahua and Hikvision clones—around $40–80 per unit from AliExpress.
Essential hardware:
- NVR box: Intel i5/Ryzen 5, 8GB+ RAM, SSD for OS, HDD for footage
- PoE switch: 8–16 ports, ~$60–150 (powers cameras via network cable)
- Storage: 2–4TB HDD for 30 days of motion-only recordings (adjust for continuous recording)
- Cameras: PoE IP cameras, 2MP–4MP, ~$50–150 each
Before I deployed this, I tested camera compatibility in my network lab. Not every cheap IP camera firmware cooperates with RTSP streams. I recommend buying one camera first, confirm it works with Frigate in your environment, then scale.
Setting Up Frigate with Docker Compose
Frigate is the brain of this system. It ingests RTSP streams from cameras, runs object detection, records events, and serves a web UI. I deploy it via Docker Compose because it isolates dependencies and makes updates trivial.
First, ensure your NVR box runs Ubuntu 22.04 LTS and has Docker + Docker Compose installed. Then create this configuration:
version: "3.8"
services:
frigate:
image: ghcr.io/blakeblackshear/frigate:stable
container_name: frigate
hostname: frigate
restart: unless-stopped
privileged: true
shm_size: "256mb"
devices:
- /dev/dri/renderD128
ports:
- "5000:5000"
environment:
FRIGATE_RTSP_PASSWORD: changeme123
PLUS_API_KEY: ""
volumes:
- ./config:/config
- ./storage:/media/frigate
- /etc/localtime:/etc/localtime:ro
- /tmp/cache:/tmp/cache
networks:
- surveillance
# Optional: Nginx reverse proxy for HTTPS
nginx:
image: nginx:latest
container_name: frigate-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- frigate
networks:
- surveillance
networks:
surveillance:
driver: bridge
Create the directory structure and config file:
mkdir -p frigate/{config,storage,certs}
cd frigate
# Create a minimal config.yml
cat > config/config.yml << 'EOF'
logger:
default: info
mqtt:
enabled: false
database:
path: /config/frigate.db
detectors:
cpu:
type: cpu
objects:
track:
- person
- car
- dog
- cat
cameras:
front_door:
ffmpeg:
inputs:
- path: rtsp://username:[email protected]:554/stream1
roles:
- detect
- record
detect:
width: 1280
height: 720
record:
retain:
days: 7
mode: motion
snapshots:
retain:
default: 10
objects: 30
garage:
ffmpeg:
inputs:
- path: rtsp://username:[email protected]:554/stream1
roles:
- detect
- record
detect:
width: 1280
height: 720
record:
retain:
days: 7
mode: motion
snapshots:
retain:
default: 10
objects: 30
# Coral EdgeTPU GPU acceleration (optional)
# detectors:
# coral:
# type: edgetpu
# device: usb
EOF
docker compose up -d
After 30 seconds, Frigate will start. Visit http://192.168.x.x:5000 from your network, and you'll see the dashboard with live feeds and event history. The first time is magical—you realize your cameras are actually working.
Fine-Tuning Detection and Storage
Out of the box, Frigate's CPU detector is accurate but slow—it processes every frame at reduced resolution. For 4 cameras at 1280×720, CPU detection introduces lag. I upgraded to a Coral USB EdgeTPU accelerator ($50), which runs YOLO inference at 100 FPS. Detection latency dropped from 800ms to 50ms.
Storage is your next bottleneck. Motion-only recording (my config default) saves 80% disk space compared to continuous recording. A 4TB HDD with motion-only retention retains 30+ days of activity. Adjust the retain.days and retain.mode values in config.yml based on your paranoia level.
I also recommend setting up a separate mount point for Frigate storage on a dedicated drive. This prevents your OS disk from filling up:
sudo fdisk -l
# Identify your storage device (e.g., /dev/sdb)
sudo mkfs.ext4 /dev/sdb1
sudo mkdir -p /mnt/frigate-storage
sudo mount /dev/sdb1 /mnt/frigate-storage
sudo chown $USER:$USER /mnt/frigate-storage
# Add to /etc/fstab for persistence
echo '/dev/sdb1 /mnt/frigate-storage ext4 defaults 0 2' | sudo tee -a /etc/fstab
Then update your Docker volumes to ./storage:/mnt/frigate-storage.
Securing and Exposing Frigate Remotely
If you want to check cameras from your phone while away, you need secure remote access. I use Caddy as a reverse proxy with Authelia for authentication. Both run in Docker on the same NVR box.
Create a Caddy config:
frigate.example.com {
reverse_proxy localhost:5000
reverse_proxy /api/* localhost:7814 # Authelia
# Simple basic auth (replace with Authelia for OAuth2)
basicauth /* {
admin $2a$14$...hash...
}
}
Or use Authelia for passwordless OIDC login. Either way, never expose Frigate raw. Bots probe open ports constantly, and default credentials are worthless on the public internet.
For remote access without exposing your home IP, use Tailscale. I run Tailscale on the NVR box, generate an auth token, and access Frigate via the private Tailscale IP from anywhere. This is my preferred method—zero port forwarding, encryption by default, and no DynDNS headaches.
Integrations with Home Assistant
If you run Home Assistant (and honestly, why wouldn't you?), Frigate integrates natively. Add this to your configuration.yaml:
frigate:
client_id: frigate
server_url: http://192.168.1.50:5000 # Your NVR box IP
Restart Home Assistant, and Frigate camera feeds, events, and clips appear in your automations. I trigger notifications when Frigate detects a person at the front door, turn on porch lights, and save a snapshot. This turns surveillance from passive recording into active security automation.
Budget Reality Check
A functional 4-camera self-hosted surveillance system costs roughly:
- NVR box (used i5 tower): $200–400
- 4× IP cameras: $200–400
- PoE switch: $80–150
- Storage (4TB HDD): $70–100
- Total: ~$550–1,050 one-time
Versus cloud subscriptions at $40–50/month per camera ($1,920–2,400/year), you break even in 6–12 months and own the hardware indefinitely. If you're open to used or refurbished gear—which I recommend for homelabs—costs drop further. I found my NVR box on eBay for $180.
For reliable VPS backup storage (archive 30 days of footage to the cloud as an off-site redundancy), consider RackNerd VPS, which offers affordable storage starting at ~$15/month. A small KVM VPS with attached storage handles archival backups without breaking the bank.
Maintenance and Next Steps
Frigate requires minimal ongoing maintenance. Update the Docker image monthly, monitor disk usage, and occasionally review detection thresholds if you're getting false positives (raccoons triggering person alerts). I run a cron job that deletes footage older than 30 days automatically.
From here, you can add features: MQTT integration for smarter automations, license plate recognition (ALPR) via CodeProject.AI, or deep learning models that distinguish between actual threats and shadows. The open ecosystem encourages experimentation.
The biggest win? You've eliminated recurring fees and reclaimed privacy. Your footage stays home, your automations run locally, and your homelab just became genuinely useful.
Discussion