Skip to content

Runbook – Frigate + Coral USB (Proxmox → VM → Docker)

Cíl

Zajistit bezúdržbový provoz Frigate s Coral USB TPU tak, aby po rebootu / výpadku proudu:

  • Proxmox správně předal USB zařízení do VM,
  • Coral se spolehlivě inicializoval (změna ID z bootloaderu na runtime),
  • Frigate nenabíhala dřív, než je TPU připravené,
  • nebyl nutný žádný ruční zásah.

Architektura (finální stav)

  • Proxmox host: USB passthrough by-path (fyzický port, např. 2-2)
  • VM (docker node):

  • systemd init skript pro inicializaci Coralu

  • standalone Docker (mimo Swarm)
  • Frigate container:

  • restart: unless-stopped

  • healthcheck ověřující dostupnost TPU

Pozadí – proč to není persistentní

  • Coral USB nemá firmware ve flash.
  • Po cold startu se vždy hlásí jako bootloader (1a6e:089a).
  • Teprve otevření EdgeTPU runtime nahraje firmware do RAM a zařízení se re-enumeruje na runtime (18d1:9302).
  • Řešení: passthrough by-path + init skript před Dockerem.

Proxmox – USB passthrough (jednorázové nastavení)

  1. VM → Hardware → Add → USB Device
  2. Zvol Use USB Port
  3. Vyber fyzický port Coralu (např. 2-2)
  4. Ulož a restartuj VM

Pozn.: Nepoužívat Vendor/Device ID (mění se při initu).


VM – inicializace Coralu (systemd)

Skript

/usr/local/bin/init-coral.sh

#!/bin/bash
set -e

# Počkej, až se objeví Coral v bootloader módu
for i in {1..30}; do
  if lsusb | grep -q "1a6e:089a"; then
    break
  fi
  sleep 1
done

# Inicializace EdgeTPU (nahraje firmware → přepne ID)
python3 - << 'EOF'
from tflite_runtime.interpreter import load_delegate
load_delegate("libedgetpu.so.1.0")
print("Coral initialized")
EOF
sudo chmod +x /usr/local/bin/init-coral.sh

systemd unit

/etc/systemd/system/init-coral.service

[Unit]
Description=Initialize Coral USB TPU
After=multi-user.target
Before=docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-coral.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable init-coral.service

Docker – Frigate (standalone)

docker-compose.yml (relevantní části)

services:
  frigate:
    image: ghcr.io/blakeblackshear/frigate:stable
    container_name: frigate
    privileged: true
    restart: unless-stopped
    shm_size: "512mb"

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

    healthcheck:
      test: ["CMD-SHELL", "lsusb | grep -q '18d1:9302'"]
      interval: 20s
      timeout: 5s
      retries: 6
      start_period: 30s

Znovuvytvoření kontejneru (po změnách)

docker compose down
docker compose pull
docker compose up -d

Ověření stavu

VM (po bootu)

lsusb | egrep -i "1a6e:089a|18d1:9302"
  • krátce po bootu: 1a6e:089a
  • po initu: 18d1:9302

Docker

docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' frigate
docker inspect -f '{{.State.Health.Status}}' frigate

Očekávání:

  • restart policy: unless-stopped
  • health: healthy

Frigate log

docker logs -f frigate
  • nesmí se objevovat No EdgeTPU detected

Typické problémy a rychlé řešení

Frigate nenaběhne po rebootu

  • Zkontroluj, že běžel init-coral.service:

bash systemctl status init-coral.service * Ověř lsusb → musí být 18d1:9302. * Vynutit recreate kontejneru (down && up).

Coral zmizel po výpadku proudu

  • Normální stav (reset do bootloaderu).
  • Řeší init-coral.service.

Swarm varianta

  • Nepodporováno pro USB/TPU.
  • Používat standalone Docker.

Doporučení do budoucna

  • Coral USB provozovat za UPS.
  • Ideálně přes napájený USB hub.
  • Pro absolutní stabilitu zvážit Coral M.2 / PCIe.

Shrnutí

  • Passthrough by-path řeší měnící se USB ID.
  • systemd init řeší nepersistentní firmware.
  • Docker restart + healthcheck řeší timing.
  • Výsledek: zapnout a zapomenout.