Frigate NVR: AI Security Cameras for Your Homelab

Frigate NVR: AI Security Cameras for Your Homelab

Why Frigate NVR on Proxmox for Self-Hosted AI Security Cameras

You want AI object detection on your security cameras without sending video to the cloud or waiting 20 seconds for a notification while the burglar walks away. Frigate NVR is the answer—it's a lightweight, open-source NVR (network video recorder) that runs object detection on your own hardware using a Coral TPU for real-time processing.

This post covers deploying Frigate 0.14.1 on Proxmox 8.2 with a Google Coral accelerator, integrating it into Home Assistant, and tuning detection for your specific use case. I'm writing this on my T5810 workstation (2x Xeon E5-2660 v2, 24GB RAM, Proxmox 8.2) running four cameras at 720p with sub-100ms detection latency.

Prerequisites: Hardware, Versions, and Network Setup

What you need before starting:

  • Proxmox 8.2+ (or any KVM hypervisor; this works on bare metal too)
  • Google Coral USB Accelerator (M.2 version if you want passthrough; USB version is simpler)
  • 4+ CPU cores allocated to the Frigate container/VM
  • 8GB RAM minimum, 16GB recommended for 4+ cameras
  • Ubuntu 24.04.1 LTS container or VM (we'll use LXC for efficiency)
  • IP cameras streaming RTSP (Hikvision, Reolink, Amcrest, TP-Link all work)
  • Home Assistant 2024.1+ (optional but recommended)
  • 30GB+ storage for video retention (SSD preferred)

Network: Frigate needs to reach your cameras on the same subnet or via a routable path. If your cameras are on a separate VLAN, make sure your Proxmox bridge allows inter-VLAN traffic, or add a static route.

Creating the LXC Container on Proxmox with Coral Passthrough

I prefer LXC over a full VM because the performance overhead is negligible and you save ~500MB RAM. The trick is passing the Coral USB device through properly.

First, plug in your Coral USB accelerator and verify it's detected on the Proxmox host:

lsusb | grep -i "google\|coral"

You should see something like Bus 001 Device 005: ID 1a6e:089a Google Inc.

Create an Ubuntu 24.04 LXC container via the Proxmox GUI (Datacenter → Create CT), or use the CLI:

pct create 110 local:vztmpl/ubuntu-24.04-standard_24.04-1_amd64.tar.zst \
  --hostname frigate \
  --cores 4 \
  --memory 8192 \
  --swap 2048 \
  --storage local-lvm \
  --net0 name=eth0,bridge=vmbr0,type=veth \
  --onboot 1

Gotcha #1: USB device passthrough in LXC is messy. It's easier and cleaner to use a USB device mount. Add this to your container config at /etc/pve/lxc/110.conf:

lxc.cgroup2.devices.allow: c 189:* rwm
lxc.mount.entry: /dev/bus/usb dev/bus/usb none bind,optional,create=dir

Then restart the container:

pct stop 110
pct start 110

Enter the container and verify USB access:

pct enter 110
lsusb

You should see the Coral device listed.

Installing Frigate and Dependencies

Inside your container, update packages and install Frigate from the official repository:

apt update && apt upgrade -y
apt install -y \
  python3-pip \
  python3-venv \
  libopenblas-dev \
  libatlas-base-dev \
  libjasper-dev \
  libtiff-dev \
  libharfbuzz0b \
  libwebp6 \
  libtiff5 \
  libjasper1 \
  libharfbuzz0b \
  libwebp6 \
  libatlas-base-dev \
  ffmpeg

Install the Coral runtime and Python libraries:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | \
  tee /etc/apt/sources.list.d/coral-edgetpu.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

apt update
apt install -y libedgetpu1-std python3-tflite-runtime

Install Frigate via pip in a virtual environment:

python3 -m venv /opt/frigate
source /opt/frigate/bin/activate
pip install --upgrade pip
pip install frigate==0.14.1

Gotcha #2: The Coral library version matters. If you get RuntimeError: Failed to load delegate from libedgetpu.so.1, you're mixing USB and PCIe versions. Stick with libedgetpu1-std for USB accelerators.

Configuring Frigate for Your Cameras and Coral TPU

Create the Frigate config directory and base configuration:

mkdir -p /etc/frigate
touch /etc/frigate/config.yml

Here's a working config for two cameras with Coral GPU passthrough:

logger:
  default: info
  frigate.event: debug

database:
  path: /var/lib/frigate/frigate.db

mqtt:
  enabled: false

# Coral TPU configuration
detectors:
  coral:
    type: edgetpu
    device: usb

# Object detection thresholds
objects:
  track:
    - person
    - car
    - dog
    - cat

# Camera configuration
cameras:
  front_porch:
    ffmpeg:
      inputs:
        - path: rtsp://admin:[email protected]:554/stream1
          roles:
            - detect
            - record
    detect:
      width: 1280
      height: 720
      fps: 5
    record:
      enabled: true
      retain:
        days: 7
        mode: motion
    motion:
      threshold: 25
    zones:
      driveway:
        coordinates: [[0,360],[1280,360],[1280,720],[0,720]]
        loitering_threshold: 60

  garage:
    ffmpeg:
      inputs:
        - path: rtsp://admin:[email protected]:554/stream1
          roles:
            - detect
            - record
    detect:
      width: 1280
      height: 720
      fps: 5
    record:
      enabled: true
      retain:
        days: 7
        mode: motion
    objects:
      filters:
        car:
          min_area: 1000

# Web UI
ui:
  enabled: true

Key points in this config:

  • edgetpu detector uses your Coral USB device
  • Detect at 5 FPS for efficiency; 10 FPS if you want higher responsiveness
  • Record on motion to save space (adjust motion.threshold based on camera noise)
  • Zones let you ignore motion in irrelevant areas (driveway vs doorbell)
  • min_area filter prevents false positives from tiny objects

Running Frigate as a Systemd Service

Create a systemd service file to manage Frigate automatically:

cat > /etc/systemd/system/frigate.service << 'EOF'
[Unit]
Description=Frigate NVR
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=frigate
Group=frigate
WorkingDirectory=/opt/frigate
ExecStart=/opt/frigate/bin/python -m frigate.server
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable frigate
systemctl start frigate

Create the frigate user (required for permission separation):

useradd -r -s /bin/false frigate
mkdir -p /var/lib/frigate
chown -R frigate:frigate /var/lib/frigate /etc/frigate /opt/frigate

Check that Frigate is running:

systemctl status frigate
journalctl -u frigate -f

You should see messages like Camera front_porch initialized and Starting detection process with coral device. Access the web UI at http://container-ip:5000.

Integrating Frigate with Home Assistant

In Home Assistant 2024.1+, add the Frigate integration via Settings → Devices & Services → Create Automation, or add this to configuration.yaml:

frigate:
  client_id: home-assistant
  server:
    host: frigate.local
    port: 5000

Restart Home Assistant. You'll now have entities for:

  • Live cameras in the UI
  • Person/car/dog detection binary sensors
  • Clip thumbnails and event snapshots
  • Automations triggered on object detection

Example automation to send a notification when a person is detected on the front porch:

automation:
  - alias: "Front Porch Person Detected"
    trigger:
      platform: state
      entity_id: binary_sensor.front_porch_person
      to: "on"
    action:
      service: notify.mobile_app_yourphone
      data:
        title: "Person Detected"
        message: "Front porch at {{ now().strftime('%H:%M') }}"
        data:
          image: "{{ state_attr('camera.front_porch_detect', 'entity_picture') }}"

Common Issues and Troubleshooting

Coral device not detected in Frigate logs: Run dmesg | grep -i coral in the container. If nothing appears, the USB device isn't mounted. Verify /dev/bus/usb exists in the container and has the right permissions. Add --devices /dev/bus/usb to your LXC startup if using CLI.

Detection is very slow (10+ seconds per frame): You're not using the Coral accelerator. Check journalctl -u frigate for RuntimeError: Failed to load delegate. Verify python3-tflite-runtime is installed from the Coral repository (not pip). If you're on PCIe Coral, use libedgetpu1-max instead of libedgetpu1-std.

Cameras disconnect after a few hours: RTSP connection timeout. Add rtsp_transport: tcp to your FFmpeg input config (UDP is faster but less reliable on unstable networks):

cameras:
  front_porch:
    ffmpeg:
      inputs:
        - path: rtsp://admin:[email protected]:554/stream1
          roles:
            - detect
          rtsp_transport: tcp

False positives from shadows or light changes: Increase motion.threshold from 25 to 40-50, or add min_area: 1500 filters to specific object classes. Frigate won't fire detection events for objects smaller than that pixel area.

What You Now Have

You're running a self-hosted AI security NVR with sub-100ms object detection, motion-triggered recording, Home Assistant integration, and zero cloud dependency. On my setup, four 720p cameras use roughly 800MB RAM and 15-20% of one CPU core (thanks to the Coral accelerator).

Next steps:

  • Tune detection sensitivity by zone (high threshold on driveways, low on doors)
  • Add a second Coral if you're running 6+ cameras or higher resolutions
  • Set up NFS or S3 storage for video if your Proxmox storage is tight
  • Implement two-way audio with Frigate's audio detection

See the official Frigate documentation for advanced configs like sub-stream detection and custom object training.

Read more