How to Install Frigate NVR with Coral USB TPU in a Docker VM (Proxmox Guide)
In this guide, I’ll walk you through setting up Frigate NVR using Docker inside a virtual machine,
with hardware acceleration via a passed-through Coral USB TPU. This setup is ideal for homelab
enthusiasts looking to offload object detection tasks and maximize performance on their local
servers.
Prerequisites
- A working VM host (I’m using Proxmox in this example)
- A Google Coral USB TPU for hardware-accelerated object detection
- A virtual machine with Docker and Docker Compose installed
- Storage configured for Frigate recordings (e.g., NFS share, local disk)
- Either Portainer or access to the Docker CLI
Host Configuration (USB Passthrough)
To enable object detection using the Coral TPU, you’ll need to pass the USB device through to your
virtual machine.
For Proxmox users:
- Plug the Coral TPU into your host machine.
- In the Proxmox web interface, go to your VM:
- Hardware > Add > USB Device
- Select the Coral TPU from the list of available USB device

Note: If it says “Unplugged,” don’t worry, it usually means the device is already passed through
and in use by the VM.
Docker Deployment (Frigate with Coral TPU)
Once the Coral USB TPU is passed through, it?s time to deploy Frigate.
Option 1: Using Portainer
- Open Portainer and go to Stacks
- Click Add Stack
- Name your stack (e.g., frigate)
- Paste your docker-compose configuration
Option 2: Using the Docker CLI
- SSH into your Docker VM
- Create a new folder for Frigate, for example:
mkdir -p ~/frigate
cd ~/frigate - Use your preferred text editor to create the compose file:
nano frigate.yml - Paste the Frigate Docker Compose code
version: "3.9"
services:
frigate:
image: ghcr.io/blakeblackshear/frigate:stable
environment:
- FRIGATE_RTSP_PASSWORD=<create secret> <-- change this
container_name: frigate
privileged: true
devices:
- /dev/bus/usb:/dev/bus/usb #TPU
restart: unless-stopped
shm_size: "2048mb"
volumes:
- /etc/localtime:/etc/localtime:ro
- <config source>:/config <-- change this
- <media storage>:/media/frigate <-- change this
- type:
target: /tmp/cache
tmpfs:
size: 2000000000
ports:
- "5000:5000" #Friagte web port
- "1935:1935" # RTMP feeds
- "8554:8554" #Detection restream URL
- "8555:8555/tcp" # WebRTC over tcp
- "8555:8555/udp" # WebRTC over udp
Don’t forget to adjust the configuration to match your environment, such as your volume paths,
network settings, and USB device paths.
Deploying the Stack
- Portainer: Click Deploy the Stack
- CLI: Run the following command in the directory where frigate.yml is located:
- docker compose -f frigate.yml up -d
Frigate Configuration
After the container is running, locate the Frigate configuration file (config.yaml
) within your mapped
volume or project folder.
Edit config.yaml to define:
- Cameras and their input sources
- Detection parameters
- Storage locations
- Object detection zones
- Motion settings
A part of my code:
logger:
logs:
frigate.record.maintainer: debug
##Choose MQTT server##
mqtt:
host:
user:
password:
ffmpeg:
global_args: -hide_banner -loglevel warning -threads 2
#hwaccel_args: preset-vaapi
input_args: preset-rtsp-generic
output_args:
detect: -threads 2 -f rawvideo -pix_fmt yuv420p
record: preset-record-generic-audio-copy
retry_interval: 10
##########################################################################
#########################Go2RTC cams######################################
go2rtc:
streams:
Garden:
- rtsp://<user:pass>@<IP>:554//h265Preview_01_main
Garden-sub:
- rtsp://<user:pass>@<IP>:554//h264Preview_01_sub
Doorbel:
- rtsp://<user:pass>@<IP>:554//h264Preview_01_main#audio=pcm#audio=volume
Doorbel-sub:
- rtsp://<user:pass>@<IP>:554//h264Preview_01_sub#audio=pcm#audio=volume
ffmpeg:
bin: ffmpeg
volume: -af "volume=30dB"
input_args: -avoid_negative_ts make_zero -fflags +genpts+discardcorrupt -flags
low_delay -strict experimental -analyzeduration 1000M -probesize 1000M -timeout
5000000
output_args:
record: -f segment -segment_time 10 -segment_format mp4 -reset_timestamps 1
-strftime 1 -c copy -tag:v hvc1 -c:a aac
##########################################################################
birdseye:
enabled: true
mode: continuous
##########################################################################
######################CONFIG WIDE VARIABLES###############################
##########################################################################
snapshots:
enabled: true
timestamp: false
bounding_box: true
retain:
default: 2
record:
enabled: true
retain:
days: 2
mode: motion
alerts:
retain:
days: 4
mode: motion
pre_capture: 7
detections:
retain:
days: 4
mode: motion
pre_capture: 7
detect:
fps: 5
enabled: true # <---- disable detection until you have a working camera feed
min_initialized: 2
max_disappeared: 25
objects:
track:
- person
##########################################################################
######################SET CORAL TPU DETECTOR##############################
##########################################################################
detectors:
coral:
type: edgetpu
device: usb
cameras:
Garden:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/Garden
roles:
- record
- path: rtsp://127.0.0.1:8554/Garden-sub
roles:
- detect
live:
stream_name: Garden
detect:
width: 640
height: 360
motion:
threshold: 40
contour_area: 30
improve_contrast: true
zones: {}
Doorbel:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/Doorbel
roles:
- record
- path: rtsp://127.0.0.1:8554/Doorbel-sub
roles:
- detect
output_args:
record: preset-record-generic-audio-copy
live:
stream_name: Doorbel
motion:
threshold: 29
contour_area: 12
improve_contrast: true
Refer to the official Frigate documentation for detailed configuration options.
Conclusion
You’ve now installed Frigate NVR with a Coral USB TPU passed through to a Docker VM in your
homelab environment. With this setup, you’ll benefit from efficient, real-time object detection and
centralized camera recording, all while keeping your infrastructure self-hosted and under your
control.