Skip to main content

Frigate NVR

Frigate is an open-source NVR with real-time AI object detection. On the CM5, Frigate uses the Axelera Metis AX2520 AIPU as its detector backend, offloading inference from the CPU entirely and enabling low-latency detection across multiple camera streams.

Axelera Metis setup

Configure the Metis M.2 AI accelerator before deploying Frigate.

Home Assistant integration

Connect Frigate events to Home Assistant via MQTT.

Prerequisites

The Axelera Metis device node /dev/axelera0 must exist before Frigate starts. Run metis-setup.sh and verify PCIe enumeration before proceeding.
  • /dev/axelera0 present (created by the Axelera udev rule in metis-setup.sh)
  • frigate user added to the axelera group — metis-setup.sh does this automatically
  • /media/frigate/recordings and /media/frigate/snapshots directories created (the image script creates them under the @frigate Btrfs subvolume)
  • Mosquitto MQTT running at 127.0.0.1:1883 (for Home Assistant event integration)

Configuration

Frigate’s configuration lives at /etc/frigate/config.yml. Below is the complete annotated configuration deployed by the image script.
/etc/frigate/config.yml
# Frigate config — CM5 Exaviz / Axelera Metis
# Home Assistant integration via MQTT auto-discovery

mqtt:
  enabled: true
  host: 127.0.0.1        # localhost — pod shares host network
  port: 1883
  # HA Frigate integration picks up events from here automatically
  # Add frigate integration in HA store → configure with this broker

detectors:
  # Axelera Metis AX2520 — swap for cpu: if Metis not yet configured
  axelera:
    type: axelera
    device: /dev/axelera0
  # cpu fallback — comment out once Metis is confirmed working
  # cpu_fallback:
  #   type: cpu
  #   num_threads: 4

database:
  path: /media/frigate/frigate.db

record:
  enabled: true
  retain:
    days: 3
    mode: motion          # only retain segments with motion
  events:
    retain:
      default: 14
      mode: active_objects

snapshots:
  enabled: true
  retain:
    default: 14

objects:
  track:
    - person
    - car
    - dog
    - cat
    - package

# cameras: add your cams here
# cameras:
#   front_door:
#     ffmpeg:
#       inputs:
#         - path: rtsp://user:pass@192.168.1.x/stream
#           roles: [detect, record]
#     detect:
#       width: 1920
#       height: 1080
#       fps: 5            # low fps is fine — Metis is fast enough for burst

Configuration sections explained

Enables the MQTT integration so Frigate publishes detection events to the Mosquitto broker running on 127.0.0.1:1883. Home Assistant’s Frigate integration subscribes to these events for automations and notifications. Because both containers share host network, no port mapping is needed.
Configures the Axelera Metis AX2520 as the inference backend via type: axelera and device: /dev/axelera0. The CPU fallback detector is included but commented out — uncomment it only if Metis is not yet available. Using num_threads: 4 on the CPU fallback limits inference to four cores.
SQLite database path on the @frigate Btrfs subvolume. Storing it on the NVMe/SATA drive alongside recordings avoids hammering eMMC with write-heavy database operations.
Continuous recording is enabled with a 3-day rolling retain window using mode: motion — only segments containing motion are kept, reducing storage usage significantly. Detection events (clips of active objects) are retained for 14 days using mode: active_objects.
JPEG snapshots of detected objects are enabled and retained for 14 days. Snapshots are written to /media/frigate/snapshots, which is also exposed as a read-only Samba share (frigate-snapshots).
Globally tracked object classes: person, car, dog, cat, and package. Per-camera overrides can narrow or extend this list.
Camera definitions are commented out in the default config. Add one block per camera, providing the RTSP stream URL and detect/record roles. The Metis AIPU is fast enough to run detection at low fps (5 fps recommended as a starting point), keeping CPU overhead minimal.

Adding a camera

Edit /etc/frigate/config.yml and add a camera block under cameras::
/etc/frigate/config.yml
cameras:
  front_door:
    ffmpeg:
      inputs:
        - path: rtsp://user:pass@192.168.1.100/stream
          roles: [detect, record]
    detect:
      width: 1920
      height: 1080
      fps: 10
    record:
      enabled: true
      retain:
        days: 7
      events:
        retain:
          default: 14
    snapshots:
      enabled: true
    objects:
      track: [person, car, dog, package]
Restart the Frigate container after changes:
systemctl restart frigate.service

Storage layout

PathContents
/media/frigate/recordingsContinuous recording segments (3-day rolling)
/media/frigate/snapshotsObject detection snapshot JPEGs (14-day retain)
/media/frigate/frigate.dbSQLite event database
Both paths live on the @frigate Btrfs subvolume mounted with nodatacow. Disabling copy-on-write is intentional — Frigate writes large sequential video files that do not benefit from CoW and perform better without it.

Deployment

Frigate is deployed as a Podman quadlet unit. The quadlet file is placed in /etc/containers/systemd/ and picked up automatically by the systemd generator on daemon reload.
/etc/containers/systemd/frigate.container
[Unit]
Description=Frigate NVR
After=network-online.target homeassistant.service
Wants=network-online.target

[Container]
Image=ghcr.io/blakeblackshear/frigate:stable
ContainerName=frigate

# Frigate needs host network for RTSP camera streams
Network=host

# Axelera Metis AIPU
AddDevice=/dev/axelera0

# GPU decode assist (VC4 / V3D on CM5)
AddDevice=/dev/dri/card0
AddDevice=/dev/dri/renderD128

Volume=/etc/frigate/config.yml:/config/config.yml:ro,Z
Volume=/media/frigate:/media/frigate:Z
Volume=/etc/localtime:/etc/localtime:ro

# SHM for frame buffers — scale with camera count
# 64mb per camera is a rough guide
ShmSize=512m

Environment=TZ=UTC

PodmanArgs=--pull=newer

[Service]
Restart=on-failure
RestartSec=15
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target default.target
Alternatively, deploy with Docker Compose for a quick test:
docker-compose.yml
services:
  frigate:
    image: ghcr.io/blakeblackshear/frigate:stable
    container_name: frigate
    restart: unless-stopped
    privileged: true                 # needed for Metis PCIe device access
    shm_size: "256mb"               # increase for more cameras
    devices:
      - /dev/axelera0:/dev/axelera0  # Metis AIPU
      - /dev/dri:/dev/dri            # VC4 GPU for decode assist
    volumes:
      - /etc/frigate:/config
      - /media/frigate:/media/frigate
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "5000:5000"    # Frigate web UI
      - "8554:8554"    # RTSP restream
      - "8555:8555/tcp"
      - "8555:8555/udp"
    environment:
      FRIGATE_RTSP_PASSWORD: "changeme"
Change FRIGATE_RTSP_PASSWORD from changeme before exposing Frigate on any network. The default value is a placeholder only.

Ports

PortProtocolPurpose
5000HTTPFrigate web UI
8554RTSPRestream proxy
8555TCP/UDPWebRTC live view

Accessing the web UI

Open http://<cm5-ip>:5000 in a browser. The dashboard shows live camera feeds, recent detection events, and storage statistics.
If you’re accessing the CM5 headlessly, find its IP address from your router’s DHCP table or by running ip addr over UART or early SSH.

Verifying Metis detection

Check that Frigate loaded the Axelera detector successfully:
journalctl -u frigate.service | grep -i axelera
You should see a line confirming the detector initialized on /dev/axelera0. If the device is missing, Frigate falls back to the CPU detector (if configured) or fails to start.

Build docs developers (and LLMs) love