Proxmox + Frigate: Adding a Google Coral (Worksheet)

THE TUTORIAL IS MEANT TO BE USED WITH THIS VIDEO!

Thank you to Tony, a viewer, for sending the Coral that made this video possible.

If you want to keep the Coral instead of rolling back, do Steps 1 to 4 and skip Step 7. The Maintenance section at the end covers living with it.

Before You Start

  1. Parts 1, 2, and 3 finished and working: VM 101 running Frigate on the 3060 with a YOLOv9 model, your cameras added, recordings landing on the separate recordings disk.

  2. A Google Coral USB Accelerator and a decent USB-C to USB-A cable. The one in the box works for most people; if the Coral misbehaves later, the cable is the first suspect.

  3. A free USB 3 port on the back of the Proxmox box, straight on the motherboard. Not a front-panel port, not an unpowered hub. The Coral can draw up to 900 mA, and it needs USB 3 to run at full speed.

  4. Room for the backup on the Proxmox host. The backup is VM 101's system disk only (the recordings disk is left out on purpose, see Step 2), compressed. Plan for roughly the used space on that disk, typically 15 to 40 GB with the tensorrt image, the models, and Ollama.

  5. Two short camera outages: a few minutes while the backup starts (Step 2) and 10 to 20 minutes for the restore (Step 7).

  6. This worksheet does not change your Frigate image or version. The tensorrt image already includes the Coral runtime, and the USB Coral needs no driver on the host or in the VM.

Commands run in one of two places: the Proxmox shell (web UI, click the node, then Shell) or an SSH session to VM 101 (ssh netserv@YOUR-FRIGATE-VM-IP, from Part 1). Each step says which. Paste multi-line blocks in one go.

My Proxmox IP: ______________________________

My Frigate VM IP: ______________________________

Recordings disk line from Step 2.1 (looks like scsi1: recordings:vm-101-disk-0,backup=0,size=500G): ______________________________

Backup file name from Step 2.5: ______________________________

Coral USB port from Step 3.4 (looks like 2-3): ______________________________

The numbers (Frigate, System metrics):

3060, YOLOv9-s-320, inference speed: ______ ms Detector CPU: ______ %

Coral, default model, inference speed: ______ ms Detector CPU: ______ %

Coral, YOLOv9 (optional, Step 5), inference speed: ______ ms Detector CPU: ______ %

CPU detector (Part 1, or optional Step 6), inference speed: ______ ms Detector CPU: ______ %

Step 1 - Record the Baseline

Frigate web UI.

1.1 - Open https://YOUR-FRIGATE-VM-IP:8971, then System metrics. Let it sit for a couple of minutes with the cameras running normally.

1.2 - Write down the 3060 line in The Numbers above: inference speed and detector CPU usage. Also glance at the Cameras tab and note that skipped fps is 0 on every camera. That is what "keeping up" looks like.

1.3 - (Optional) From an SSH session to VM 101, note the card's power draw and memory with Frigate detecting:

nvidia-smi --query-gpu=power.draw,memory.used,utilization.gpu --format=csv

Step 2 - Back Up VM 101

Proxmox shell, then the Proxmox web UI. Nothing in this step changes VM 101.

2.1 - Find the recordings disk. List VM 101's disks:

qm config 101 | grep -E '^(scsi|sata|virtio|ide|unused)[0-9]'

You will see the system disk (usually scsi0, around 32 to 64 GB) and the recordings disk (usually scsi1, the big one). Write the whole recordings disk line in the box at the top. You need it in Step 7.

2.2 - Make sure the recordings disk is excluded from backups. Its line should contain backup=0. Part 1's Maintenance section had you set this. If it is missing: VM 101 > Hardware > double-click the recordings disk > uncheck Backup (tick Advanced at the bottom of the dialog if you do not see it) > OK. Re-run the command from 2.1 and confirm backup=0 is there now.

Why: a backup that includes a 500 GB video disk takes hours and needs 500 GB of space to hold footage you do not need to roll back. It also matters on the way back. When Proxmox restores a VM, it replaces the disks that are in the backup and leaves the others alone. Excluding the recordings disk means the restore cannot touch your footage. See 7.5 for the one thing to check afterward.

2.3 - Check the space on the backup storage:

pvesm status

The local line is where the backup goes. Its Available column (in kilobytes) should comfortably exceed the used space on VM 101's system disk. If local does not list backup as a content type in Datacenter > Storage, edit it and tick VZDump backup file.

2.4 - Keep a copy of the Frigate config inside the VM too. Belt and suspenders. SSH session to VM 101:

cp ~/frigate/config/config.yml ~/frigate/config/config.yml.gpu
cp ~/frigate/docker-compose.yml ~/frigate/docker-compose.yml.gpu

2.5 - Take the backup. Web UI: VM 101 > Backup > Backup now.

  • Storage: local

  • Mode: Stop

  • Compression: ZSTD

  • Notes: Before Coral

Click Backup. Stop mode shuts VM 101 down cleanly, starts the backup, and boots the VM right back up while the backup finishes in the background, so the camera outage is a couple of minutes, not the whole backup. It is the mode that guarantees Frigate's database is closed and consistent.

Same thing from the Proxmox shell, if you prefer:

vzdump 101 --storage local --mode stop --compress zstd --notes-template "Before Coral"

Watch the task log (bottom of the web UI) until it says TASK OK. The log line that mentions the recordings disk should say it was excluded. Then find the file and write its name at the top:

ls -lh /var/lib/vz/dump/ | grep qemu-101

It looks like vzdump-qemu-101-2026_10_28-10_15_02.vma.zst.

STOP HERE and take a breath. Nothing has changed yet, and you have a way back.

Step 3 - Plug In the Coral and Hand It to VM 101

3.1 - Plug the Coral into a rear USB 3 port on the Proxmox box (usually blue, sometimes teal or red). Straight into the board.

3.2 - Confirm the host sees it. Proxmox shell:

lsusb | grep -i -e 1a6e -e 18d1

You should get one line with 1a6e:089a Global Unichip Corp. That is a Coral that has not been used yet. It changes its name later; that is normal (see the note under 3.4).

3.3 - Find its port and speed:

lsusb -t

Find the Coral by the device number from 3.2 (it shows as Class=Vendor Specific Class). The line should end in 5000M. If it ends in 480M, it is on a USB 2 port; move it and run 3.2 again.

3.4 - Pass the port to VM 101. Web UI: VM 101 > Hardware > Add > USB Device. Choose Use USB Port (not Use USB Vendor/Device ID). Pick the port that lists Global Unichip Corp. Add. Then confirm from the Proxmox shell and write the port at the top:

qm config 101 | grep usb

You should see something like usb0: host=2-3.

Why the port and not the device ID: the Coral changes its USB ID. It shows up as 1a6e:089a (Global Unichip) until something loads its firmware, then it drops off the bus and comes back as 18d1:9302 (Google Inc.). If you pass it through by ID, the VM gets the first identity, the Coral changes into the second one, and the VM loses it. Passing the port hands over whatever is plugged into that socket, so it survives the switch. The usb3 checkbox does not matter on a q35 VM like this one; all its USB devices already sit on a USB 3 controller.

3.5 - Stop and start VM 101. VM 101 > Shutdown, wait for stopped, then Start. (Same rule as Part 2: a reboot from inside the VM does not apply hardware changes.)

3.6 - Confirm the VM sees it. SSH session to VM 101:

sudo apt install -y usbutils
lsusb | grep -i -e 1a6e -e 18d1

1a6e:089a Global Unichip Corp. here too. It stays that way until Frigate uses it in Step 4.

Step 4 - Switch Frigate's Detector to the Coral

SSH session to VM 101.

4.1 - Give the container the USB bus. Open the compose file:

nano ~/frigate/docker-compose.yml

In the frigate service (not ollama or anything else in the file), add these two lines directly under the shm_size line, indented to match it:

    devices:
      - /dev/bus/usb:/dev/bus/usb

Save with Control-X, then Y, then Enter. Check it:

cd ~/frigate && docker compose config --quiet && echo OK

If the frigate service already has a devices: section, add only the second line to it.

4.2 - Change the detector. Open the config:

nano ~/frigate/config/config.yml

Find the detectors block from Part 2 (the one with type: onnx) and replace it with:

detectors:
  coral:
    type: edgetpu
    device: usb

Then find the model: block right below it and delete the whole block (model: and every indented line under it). The Coral cannot run the ONNX file, and with no model block, Frigate loads the Coral's built-in default model. Leave the ffmpeg block with hwaccel_args: preset-nvidia exactly as it is, and leave semantic_search, genai, review, and your cameras alone. Save.

What stays on the 3060: video decoding (hwaccel), semantic search, and review summaries. What moves to the Coral: object detection only. Frigate cannot split object detection between two different detector types, so it is one or the other, not both.

4.3 - Recreate the container and watch the log. The compose file changed, so up -d rebuilds the container:

docker compose up -d
docker logs -f frigate 2>&1 | grep -i -e tpu -e detector

You want these two lines, a few seconds apart:

frigate.detectors.plugins.edgetpu_tfl INFO    : Attempting to load TPU as usb
frigate.detectors.plugins.edgetpu_tfl INFO    : TPU found

Control-C. If it says No EdgeTPU was detected instead, do the next paragraph.

The first start can fail with No EdgeTPU was detected and ValueError: Failed to load delegate from libedgetpu.so.1.0, even though lsusb (4.4) shows 18d1:9302. When Frigate loads the firmware, the Coral comes back at a new USB device number, and the container only has the device nodes that existed when it was created. The Coral is already in its Google state now, so recreate the container once more. Recreate, not restart; a restart keeps the old device list:

docker compose up -d --force-recreate frigate
docker logs -f frigate 2>&1 | grep -i -e tpu -e detector

You should now get TPU found.

4.4 - Watch the Coral change its name:

lsusb | grep -i -e 1a6e -e 18d1

Now it says 18d1:9302 Google Inc. Firmware loaded; the Coral is in business. Because you passed the port, the VM kept it through the switch.

4.5 - The number. Frigate > System metrics. Give it a few minutes of normal camera activity, then write down the Coral line in The Numbers. Check the Cameras tab for skipped fps, too.

4.6 - Look at the card:

nvidia-smi

The frigate process is still on the 3060, using less memory than before. That is the decoder and the search model. The detector is gone from the card.

STOP HERE if all you wanted was the Coral running. Steps 5 and 6 are optional comparisons. Step 7 puts everything back.

Step 5 - (Optional) YOLOv9 on the Coral

SSH session to VM 101. Frigate 0.17 can run a YOLOv9 model that was specially rebuilt for the Coral. It is more accurate than the default and a bit slower, and it only knows 17 kinds of object: person, bicycle, car, motorcycle, airplane, bus, train, truck, boat, bird, cat, dog, horse, sheep, cow, elephant, bear.

5.1 - Download the model and its label file into Frigate's config folder (root owns model_cache, hence sudo; the first line installs wget, which a minimal Debian VM does not have):

sudo apt install -y wget
sudo wget -P ~/frigate/config/model_cache/ https://github.com/dbro/frigate-detector-edgetpu-yolo9/releases/download/v1.0/yolov9-s-relu6-best_320_int8_edgetpu.tflite
sudo wget -P ~/frigate/config/ https://raw.githubusercontent.com/dbro/frigate-detector-edgetpu-yolo9/refs/heads/main/labels-coco17.txt
ls -l ~/frigate/config/model_cache/*.tflite ~/frigate/config/labels-coco17.txt

5.2 - Add a model block to config.yml, at the top level, right under the detectors block from 4.2:

model:
  model_type: yolo-generic
  width: 320
  height: 320
  path: /config/model_cache/yolov9-s-relu6-best_320_int8_edgetpu.tflite
  labelmap_path: /config/labels-coco17.txt

Do not copy input_tensor or input_dtype over from the Part 2 model block; this model uses Frigate's defaults for those.

5.3 - Restart and measure:

docker compose restart frigate
docker logs -f frigate 2>&1 | grep -i -e tpu -e model -e error

Control-C once you see TPU found. Give it a few minutes, then write down the Coral YOLOv9 line in The Numbers. Expect it to be a few milliseconds slower than the default model, and the detector CPU number to be higher: the Coral does the heavy math, and the CPU sorts out the boxes afterward.

Step 6 - (Optional) The CPU, for the Record

SSH session to VM 101. If you still have the CPU number from Part 1, you can skip this. If you want it on camera, this runs Frigate's CPU detector for a few minutes. With several busy cameras it will fall behind; that is the point. Do not leave it like this.

6.1 - In config.yml, replace the detectors block with this, and delete the model block from Step 5 if you added it:

detectors:
  cpu1:
    type: cpu
    num_threads: 3

6.2 - Restart, wait a few minutes, write down the CPU line in The Numbers, and look at skipped fps on the Cameras tab:

docker compose restart frigate

6.3 - Put the Coral back before you move on (or skip straight to Step 7, which puts everything back anyway):

detectors:
  coral:
    type: edgetpu
    device: usb

Step 7 - Roll Back to the 3060

Proxmox web UI and shell. This restores VM 101's system disk and settings from the Step 2 backup. The recordings disk is not in the backup and is left in place.

7.1 - Shut down VM 101. VM 101 > Shutdown. Wait for stopped. A restore will refuse to run over a running VM.

7.2 - Unplug the Coral. The restore removes the USB entry from VM 101's settings anyway (the backup was taken before you added it).

7.3 - Restore. VM 101 > Backup. Select the backup with the note Before Coral > Restore. Leave Start after restore unchecked and Unique unchecked. Confirm the warning that the VM's current data will be replaced. Wait for TASK OK in the task log.

Same thing from the Proxmox shell, using the file name you wrote at the top:

qmrestore /var/lib/vz/dump/YOUR-BACKUP-FILE.vma.zst 101 --force

7.4 - Look at the disks before you start anything:

qm config 101 | grep -E '^(scsi|sata|virtio|ide|unused)[0-9]|hostpci|usb'

You want: the system disk, the recordings disk on the same line you wrote at the top, the hostpci0 line for the 3060, and no usb0 line.

7.5 - If the recordings disk shows up as unused0 instead of scsi1, re-attach it before you boot. Web UI: VM 101 > Hardware > double-click Unused Disk 0 > set Bus/Device to what it was before (SCSI 1 in the example), uncheck Backup, Add. Or from the Proxmox shell, using the volume name from your line at the top (the part between "scsi1: " and the first comma):

qm set 101 --scsi1 recordings:vm-101-disk-0,backup=0

Run 7.4 again and confirm.

Why this matters: Part 1's fstab line mounts the recordings disk with nofail, so the VM boots happily without it, and Frigate then writes recordings to the small system disk until it fills up. Check before you start.

7.6 - Start VM 101 and SSH in:

ssh netserv@YOUR-FRIGATE-VM-IP
df -h /media/frigate
nvidia-smi
docker ps

/media/frigate should be the big disk, nvidia-smi should show the 3060 with the frigate process on it, and the frigate container (and ollama, and anything else you run in this VM) should be Up.

7.7 - Check the number. Frigate > System metrics. Inference speed should be back to your 3060 number from Step 1.

STOP HERE. You are back where you started, with a table of numbers to argue about in the comments.

7.8 - (Optional) Tidy up. Recordings made while the Coral was running are still on the recordings disk, but the restored database has never heard of them. They are harmless. If you want Frigate to find and remove files its database does not know about, add this under the existing record: block in config.yml, restart Frigate once, then take it back out:

  sync_recordings: true

When you are sure you are happy, delete the backup to get the space back: VM 101 > Backup > select it > Remove.

If Your Coral Is M.2 or Mini PCIe

Not shown in the video. The Frigate side is the same idea; the plumbing is different.

  • It needs a kernel driver called gasket (the module that shows up is apex). The USB Coral does not.

  • Google archived the driver in April 2026. Frigate's documentation points to jnicolson/gasket-builder, which builds an installable package with one docker build command. Community forks such as feranick/gasket-driver carry fixes for newer kernels.

  • On Proxmox you have two choices. Pass the card to VM 101 as a PCI device, the same way as the 3060 in Part 2 (vfio on the host, driver in the VM), or install the driver on the host and run Frigate in an LXC. The VM route keeps the driver off the hypervisor.

  • Kernel updates rebuild the driver through DKMS, and that rebuild is what breaks. After any kernel update, confirm ls /dev/apex_0 before assuming Frigate is fine.

  • In the compose file, pass /dev/apex_0:/dev/apex_0 under devices instead of /dev/bus/usb. In config.yml, device: pci instead of usb.

  • The M.2 slot must be A+E or B+M keyed, as the card is; it will not go in an NVMe (M key) slot. The Dual Edge TPU card needs two PCIe lanes on the slot, and most boards wire only one, so only one of its two TPUs shows up. An adapter card fixes that.

If It Doesn't Work

  • 3.2 shows nothing: try another rear port, then another cable. Front-panel ports and unpowered hubs often cannot supply the Coral.

  • 3.3 shows 480M: USB 2 port. It works, but slower. Move it to a USB 3 port.

  • The Frigate log says No EdgeTPU was detected: work outward. Inside the VM, lsusb should show 1a6e:089a or 18d1:9302. If it shows neither, the VM does not have it: check qm config 101 | grep usb on the host, and that you did a Shutdown then Start (3.5). If it shows 18d1:9302 and the log says Failed to load delegate from libedgetpu.so.1.0, the container was created before the Coral changed its USB device number: run docker compose up -d --force-recreate frigate (a restart does not help, it keeps the old device list). If it shows 1a6e:089a, or recreating does not help, check the devices lines from 4.1 are under the frigate service, then run the same recreate command.

  • It worked once, then stopped after the Coral changed to 18d1:9302: you passed it by Vendor/Device ID instead of by port. VM 101 > Hardware > remove the USB device, add it again with Use USB Port (3.4), Shutdown, Start.

  • Frigate log complains about an ONNX file, input shape, or yolov9-s-320.onnx: the Part 2 model block is still in config.yml. Delete it (4.2).

  • Frigate log complains about a label or object that is not in the labelmap, only with the Step 5 model: one of your cameras tracks an object that is not in the 17 labels. Remove it from that camera's objects list for the test, or go back to the default model.

  • Inference speed is much higher than 15 ms with the default model: check 3.3 for USB 2, check that nothing else is plugged into the same USB controller, and give it a few minutes; the first readings after a restart are high.

  • Detection freezes after hours or days and the log shows the detector restarting or stuck: a known USB Coral behavior, and more common in VMs. Unplug and replug the Coral, then docker compose restart frigate. If it keeps happening, try a different cable first; that fixes it more often than anything else.

  • The backup in 2.5 fails with a space error: free space on local, or add a NAS or second disk as a backup storage in Datacenter > Storage and choose it in 2.5.

  • The backup takes hours: the recordings disk was included. Cancel it, redo 2.2, and start again.

  • The restore in 7.3 fails saying the VM is running or locked: wait for stopped. If it says locked, qm unlock 101 in the Proxmox shell, then try again.

  • After the restore, VM 101 will not start and complains about the PCI device: the restore brought back the Part 2 settings, which is correct. Treat it exactly like Part 2's troubleshooting (a cold power cycle of the host is the usual cure for a wedged card).

  • After the restore, df -h /media/frigate shows the small system disk: the recordings disk is not attached. docker compose stop in ~/frigate, shut the VM down, do 7.5, start it again.

Maintenance (if you keep the Coral)

  • Frigate updates: same command as always. The Coral runtime is inside the image; nothing to update on the host or in the VM.

cd ~/frigate && docker compose pull && docker compose up -d
  • Watch skipped fps on the Cameras tab now and then. A single Coral tops out around 1000 divided by its inference speed, in detections per second. If you get near that, tighten motion masks before you buy a second one.

  • The USB Coral gets warm. Give it air, not the inside of a closed cabinet.

  • If you ever move VM 101 to a different USB port or host, redo 3.4.

  • Proxmox backups of VM 101 include the usb0 line. Restoring onto a machine without a Coral in that port just means Frigate's detector fails to start; switch the detectors block back to onnx and restore the model block from config.yml.gpu.

Next
Next

RTSP Monitor v3 (worksheet)