Google Coral USB TPU with Proxmox
Table of Contents:
- Intro
- The setup
- Prepare Proxmox LXC container
- Start Frigate
- Adapt Proxmox LXC config
- Restart Frigate
Intro
I recently bought some RTSP-capable cameras (Reolink, to be specific) for home security and to play around with the detection capabilities of Frigate and others (like double-take). After using the CPU as my main horse power, the Google Coral TPUs popped up, in specific the small USB accelerator. Ok, bought. But how to use it with Proxmox?
The setup
I wanted to use my existing Proxmox hypervisors for running Frigate in a LXC container. To do so, we need the following:
- The Coral TPU plugged into one USB port of your hypervisor
- An LXC container (Debian perferred, but that’s up to you) with Docker installed
- Some tweaks to get the Coral TPU passed through to the Frigate container inside the LXC container
Prepare Proxmox LXC container
First of all, get the USB device information. To do so, login to Proxmox via SSH and execute lsusb
. You should see something similar like this:
$ lsusb
Bus 004 Device 004: ID 1a6e:089a Global Unichip Corp.
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 8087:0026 Intel Corp. AX201 Bluetooth
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
In my case, the TPU is listed as Global Unichip Corp.
device on USB bus 4. We need to note that. Some may asking: But I thought this is a Google device?
. Yes, be aware that the USB device ID and manufactor name is changing after first use of the TPU.
Next, some best practice according to other folks out there: create a udev rule to configure the USB device permissions, to allow non-root users to access the device without additional permissions. Make sure that you’re using the correct vendor and product ID.
$ echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="1a6e", ATTRS{idProduct}=="089a", MODE="0664", TAG+="uaccess"' | tee -a /etc/udev/rules.d/71-edgetpu.rules > /dev/null
$ udevadm control --reload-rules && udevadm trigger
Now create a new LXC container, which is privileged and has nesting enabled. Don’t start it yet. After creation, navigate to the container conf file (to be found in /etc/pve/lxc/<id>.conf
) and add the following:
unprivileged: 0
lxc.cgroup2.devices.allow: c 226:0 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.cgroup2.devices.allow: c 29:0 rwm
lxc.cgroup2.devices.allow: c 189:* rwm
lxc.apparmor.profile: unconfined
lxc.cgroup2.devices.allow: a
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file 0, 0
lxc.mount.entry: /dev/bus/usb/004 dev/bus/usb/004 none bind,optional,create=dir 0, 0
lxc.cap.drop:
lxc.mount.auto: cgroup:rw
Again, make sure that you use the correct USB bus mount entry (in my case 004
).
After that, start the container, install Docker (e.g. using the convenience script: curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh
) as well as the usbutils
package to be able to execute lsusb
.
Execute lsusb
to list all connected USB devices. You should see the Global Unichip Corp.
device as well.
Start Frigate
Now we can start Frigate to use
the TPU. An example docker-compose file is the following - adapt this to your needs:
version: "3.9"
services:
frigate:
container_name: frigate
privileged: true
restart: unless-stopped
image: ghcr.io/blakeblackshear/frigate:0.13.0-beta6
shm_size: "126.99mb"
devices:
- /dev/bus/usb:/dev/bus/usb # passes the USB Coral, needs to be modified for other versions
volumes:
- /etc/localtime:/etc/localtime:ro
- <your-path>/config:/config # config path
- <your-path>:/media/frigate # recordings path
- type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear
target: /tmp/cache
tmpfs:
size: 1000000000
ports:
- "5000:5000"
- "8554:8554" # RTSP feeds
- "8555:8555/tcp" # WebRTC over tcp
- "8555:8555/udp" # WebRTC over udp
environment:
FRIGATE_RTSP_PASSWORD: "asuperlongandsecurepassword"
In the config.yaml
inside the config directory, set the Coral TPU detector:
...
detectors:
coral:
type: edgetpu
device: usb
...
Please see the Frigate config documentation for all possible config options.
Start the container: docker compose up -d
After a short time, you should see the container crashing because it’s not detecting any TPU. This is expected since the TPU changed its ID and name after the first use. More information about that here.
We now need to adapt our LXC config.
Adapt Proxmox LXC config
Again, on the Proxmox host, execute lsusb
:
$ lsusb
Bus 004 Device 005: ID 18d1:9302 Google Inc.
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 8087:0026 Intel Corp. AX201 Bluetooth
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
You see, we’re now dealing with a Google device. Again, execute the following to extend the udev rules:
$ echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="9302", MODE="0664", TAG+="uaccess"' | tee -a /etc/udev/rules.d/71-edgetpu.rules > /dev/null
$ udevadm control --reload-rules && udevadm trigger
Restart Frigate
Now we can restart the Frigate container: docker compose restart
When looking at the logs (docker compose logs -f
), you should now see the following:
...
frigate | frigate.detectors.plugins.edgetpu_tfl INFO : Attempting to load TPU as usb
frigate | frigate.detectors.plugins.edgetpu_tfl INFO : TPU found
...
That’s it! You’re ready to use the TPU.
If you like posts like that and want to support me, some sats (see my about page) are highly appreciated 🧡