TL;DR#
1
2
3
4
5
| mkdir -p /opt/frigate/config /opt/frigate/media
cd /opt/frigate
# write docker-compose.yml and config/config.yml (below)
docker compose up -d
docker compose logs -f frigate
|
Authenticated UI at https://<host>:8971. On first run it prints the generated admin password in the log.
Frigate is an NVR with real-time object detection (person, car, animal…) for IP cameras. It runs happily in a container: give it a docker-compose.yml, a config.yml and your cameras’ RTSP URLs. The rest is tuning shared memory and hardware acceleration.
docker-compose.yml#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| services:
frigate:
container_name: frigate
image: ghcr.io/blakeblackshear/frigate:stable
restart: unless-stopped
stop_grace_period: 30s
shm_size: "256mb" # raise it per camera count and resolution
devices:
- /dev/dri/renderD128 # iGPU (VAAPI) for decoding; optional
# - /dev/bus/usb:/dev/bus/usb # Coral USB
# - /dev/apex_0:/dev/apex_0 # Coral PCIe
volumes:
- /etc/localtime:/etc/localtime:ro
- ./config:/config
- ./media:/media/frigate
- type: tmpfs
target: /tmp/cache
tmpfs:
size: 1000000000
ports:
- "8971:8971" # authenticated UI (use this one)
- "8554:8554" # RTSP restream (go2rtc)
- "8555:8555/tcp" # WebRTC
- "8555:8555/udp"
environment:
FRIGATE_RTSP_USER: "${FRIGATE_RTSP_USER}"
FRIGATE_RTSP_PASSWORD: "${FRIGATE_RTSP_PASSWORD}"
|
Camera credentials live in a .env next to the compose file (never in git):
1
2
3
| # /opt/frigate/.env
FRIGATE_RTSP_USER=viewer
FRIGATE_RTSP_PASSWORD=change-me
|
config/config.yml#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| mqtt:
enabled: false # or point it at a mosquitto broker for Home Assistant
detectors:
cpu1:
type: cpu # switch to edgetpu (Coral) or tensorrt (NVIDIA)
ffmpeg:
hwaccel_args: preset-vaapi # Intel/AMD iGPU; NVIDIA: preset-nvidia
go2rtc:
streams:
door1:
- "rtsp://{FRIGATE_RTSP_USER}:{FRIGATE_RTSP_PASSWORD}@camera-ip:554/stream1"
cameras:
door1:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/door1 # single connection via go2rtc
roles: [detect, record]
detect:
width: 1280
height: 720
fps: 5
objects:
track: [person, car, dog]
record:
enabled: true
retain:
days: 7
snapshots:
enabled: true
|
Add more cameras by repeating the go2rtc.streams + cameras blocks. Reload with docker compose restart frigate.
What each piece does#
| Piece | Purpose |
|---|
shm_size | Frame buffers in /dev/shm. Too small = cameras crash. |
go2rtc | Repackages the camera RTSP and serves it on :8554. Frigate reads from there to detect and record over a single connection to the camera. |
hwaccel_args | Offloads video decode to the GPU/iGPU. Without it the CPU melts. |
detectors | Where inference runs: cpu (slow), edgetpu (Coral) or tensorrt (NVIDIA). |
Port 8971 | UI with login. This is the one you expose. |
record / snapshots | Write to ./media. Retention decides how much disk you burn. |
Traps#
- Small
shm_size → cameras that restart themselves. Rough per-camera rule: (width*height*1.5*9 + 270480) / 1048576 MB; sum all cameras and leave a base. A few 1080p cameras will blow past 64–128 MB. - Do not expose port 5000. It’s the unauthenticated internal API. The public UI is
8971 (with login). Keep 5000 on loopback / an internal network only. - Use the go2rtc restream. Putting the camera RTSP straight into both
detect and record opens two connections to the sensor; many cheap cameras can’t take it. Detect and record from rtsp://127.0.0.1:8554/<cam>. - Detect at low resolution.
detect at 1280×720 and 5 fps is plenty; record the high stream separately if your camera has two. - Hardware acceleration or 100% CPU.
preset-vaapi (Intel/AMD) or preset-nvidia; the /dev/dri device (or the NVIDIA runtime) must be mapped in. - A detector isn’t really optional. The
cpu detector is fine to smoke-test, but past one or two cameras you want Coral or TensorRT.
See also#