Hey, thanks for the input. Why do you think this change is needed?
Looks like Espressif changed the structure of esp_openthread_config_t
Yeah, it seems they changed the rcp example, but that is on master. The v6.0-beta1 branch which we use in the guide does not include that change.
My distrobox, running in WSL2 on Windows 10, does not have USB pass-through and I cannot flash from within distrobox. But I have copied the file out to windows and I have connected to my ESP32C6 with ESPConnect. Now I need to flash the bin file, but I am not sure which partition I should flash it to. I think I have to use the factory partition, but does anyone know?
These are the partitions I see:
| Label | Type | Subtype | Offset | Size |
|---|---|---|---|---|
| Bootloader | Reserved | Reserved | 0x0 | 32 KB |
| Partition Table | Reserved | Reserved | 0x8000 | 4 KB |
| nvs | Data (0x01) | NVS (0x02) | 0x9000 | 24 KB |
| phy_init | Data (0x01) | PHY Init Data (0x01) | 0xF000 | 4 KB |
| factory | Application (0x00) | Factory App (0x00) | 0x10000 | 1 MB |
I flashed it to the factory partition, but it seems to disconnect constantly. Maybe the flashing is required to executed from the distrobox…
Try this
esptool.py -p COM10 --baud 921600 write_flash --flash_mode dio --flash_freq 40m --flash_size detect 0x0 bootloader.bin 0x8000 partitions.bin 0x9000 nvs.bin 0xF000 phy_init.bin 0x10000 firmware.bin
Btw can someone please share a pre-compiled bin ?
I’ve flashed an ESP32-H2 with the RCP firmware (configured with USB transport for RCP), but HA isn’t automatically discovering it, even though it’s mapped through to the docker container.
services:
homeassistant:
privileged: true
container_name: home-assistant
image: homeassistant/home-assistant
volumes:
- ./home_assistant/config:/config
- /etc/localtime:/etc/localtime:ro
- ./home_assistant/media:/media
restart: unless-stopped
devices:
- /dev/serial/by-id/usb-Espressif_USB_JTAG_serial_debug_unit_10:51:DB:63:BA:11-if00:/dev/ot-rcp-usb-H2
network_mode: host
depends_on:
- mariadb
- mosquitto
When I try manually install the OTBR add-on it only asks for a URL.
I’m on HA 2026.1.1.
As you are on HA docker 2 more services needed, otbr and matter, both in docker.
See here:
Thanks for the suggestion, but again, I do not have USB access in my distrobox. I use EspConnect homepage.
I updated to guide to provide an option to use a pre-compiled (by myself) binary. Afaict you can use web.esphome.io to flash it too.
Thanks for the guide.
I’m having problems with Package hass-otbr-docker · GitHub starting up the otbr-agent.
2026-02-02T11:47:27.657635573Z [NOTE]-AGENT---: Running 0.3.0-b067e5ac-dirty
2026-02-02T11:47:27.657657106Z [NOTE]-AGENT---: Thread version: 1.3.0
2026-02-02T11:47:27.657663903Z [NOTE]-AGENT---: Thread interface: wpan0
2026-02-02T11:47:27.657670108Z [NOTE]-AGENT---: Radio URL: spinel+hdlc+uart:///dev/ttyRadio?uart-baudrate=460800&uart-init-deassert
2026-02-02T11:47:27.657676804Z [NOTE]-AGENT---: Radio URL: trel://ens18
2026-02-02T11:47:27.657686321Z [NOTE]-ILS-----: Infra link selected: ens18
2026-02-02T11:47:27.657795638Z [INFO]-RCP_HOS-: OpenThread log level changed to 5
2026-02-02T11:47:27.657834741Z 55d.03:49:33.827 [C] Platform------: Init() at hdlc_interface.cpp:153: No such file or directory
2026-02-02T11:47:27.661500082Z **WARNING**: otbr-agent exited with code 5 (by signal 0).
<firewall stuff cut>
2026-02-02T11:47:27.820097997Z s6-svlisten1: **fatal**: /run/s6-rc/servicedirs/otbr-agent failed permanently or its supervisor died
2026-02-02T11:47:27.820448444Z s6-rc: **warning**: unable to start service otbr-agent: command exited 1
2026-02-02T11:47:27.821516796Z s6-rc: info: service legacy-cont-init: stopping
2026-02-02T11:47:27.821723869Z s6-rc: info: service universal-silabs-flasher: stopping
2026-02-02T11:47:27.821912290Z /run/s6/basedir/scripts/rc.init: warning: s6-rc failed to properly bring all the services up! Check your logs (in /run/uncaught-logs/current if you have in-container logging) for more information.
otbr:
container_name: otbr
image: ghcr.io/ownbee/hass-otbr-docker
restart: unless-stopped
privileged: true
network_mode: host
cap_add:
- SYS_ADMIN
- NET_ADMIN
environment:
DEVICE: "/dev/ttyRadio"
FLOW_CONTROL: 1
FIREWALL: 1
NAT64: 1
BAUDRATE: 460800
OTBR_REST_PORT: 8081
OTBR_WEB_PORT: 7586
AUTOFLASH_FIRMWARE: 0
BACKBONE_IF: "ens18" # Replace with your network interface found in Step 3
#PUID: 1000
#PGID: 1000
OTBR_LOG_LEVEL: debug
OTBR_ENABLE: 1
devices:
# - /dev/serial/by-id/usb-Espressif_USB_JTAG_serial_debug_unit_10\:51\:DB\:63\:BA\:11-if00:/dev/ttyRadio
- /dev/net/tun:/dev/net/tun
- /dev/ttyRadio:/dev/ttyRadio
volumes:
- ./otbr_data:/data/thread:rw
Googling isn’t throwing me any bones and I have included a bunch of fixes (such as the PUID/PGID and cap_add) which I found around the net.
Is that agent crash-out indicative of a comms issue with the serial device, can anyone tell me?
Having a quick look here, I can point out an obvious one:
devices:
# - /dev/serial/by-id/usb-Espressif_USB_JTAG_serial_debug_unit_10\:51\:DB\:63\:BA\:11-if00:/dev/ttyRadio
- /dev/net/tun:/dev/net/tun
- /dev/ttyRadio:/dev/ttyRadio
You are supposed to use the /dev/serial/by-id/... device to connect to the ESP32 from the OTBR container. Not /dev/ttyRadio.
Your logs seem to have other issues too (like hdlc_interface.cpp:153: No such file or directory) but maybe try this and report back?
Thanks for looking. /dev/ttyRadio is a udev remapped device, mapped to
dev/serial/by-id/usb-Espressif_USB_JTAG_serial_debug_unit_10:51:DB:63:BA:11-if00 in the underlying host OS. Would that still be a concern?
I’m not sure what to do about the cpp error… I’ll have a further Google.
Remapped device sounds OK to me (but not an expert). Also, I noticed in your yaml:
FLOW_CONTROL: 1
The ESP32-C6 doesn’t support hardware flow control, it should be disabled (0).
ChatGPT/Gemini can be of much more help here than google.
Just some feedback to say that I got it working eventually.
The problem was with my nesting of OTBR within docker which was running on a Ubuntu server VM which is running on Proxmox.
The USB device (ESP32-H2 in my case) isn’t picked-up by OTBR and gives the error “Platform------: Init() at hdlc_interface.cpp:153: No such file or directory”. It’s not a very descriptive error, that’s what threw me - plus the web portal won’t load, so it leaves you in limbo.
I moved over to an LXC and installed docker (Proxmox VE Helper-Scripts) and I udev remapped the raw USB device at the Proxmox host level as follows:
root@proxmox:~# cat /etc/udev/rules.d/99-otbr.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", SYMLINK+="ttyRadio"
Then reload the device rules in Proxmox to create the new /dev/ttyRadio device:
root@proxmox:~# udevadm control --reload-rules
root@proxmox:~# udevadm trigger
My functional docker-compose is as follows:
services:
otbr:
container_name: otbr
image: ghcr.io/ownbee/hass-otbr-docker
restart: unless-stopped
privileged: true
network_mode: host
cap_add:
- SYS_ADMIN
# - NET_ADMIN
environment:
DEVICE: "/dev/ttyRadio"
FLOW_CONTROL: 0
FIREWALL: 0
NAT64: 1
BAUDRATE: 460800
OTBR_REST_PORT: 8081
OTBR_WEB_PORT: 7586
AUTOFLASH_FIRMWARE: 0
BACKBONE_IF: "eth0" # Replace with your network interface found in Step 3
#PUID: 1000
#PGID: 1000
OTBR_LOG_LEVEL: debug
OTBR_ENABLE: 1
devices:
- /dev/net/tun:/dev/net/tun
- /dev/ttyRadio:/dev/ttyRadio
volumes:
- ./otbr_data:/data/thread:rw
Maybe this will help somebody.
Thanks for sharing!
Thank you for posting this! I worked on doing this for hours probably just a few days before you posted it without success. Using this, I now have a border router running on an esp32-h2. Also thanks to alinelena for posting info on setting up OTBR in a container when not running HAOS.
Thanks for the instructions. I have the new border router showing up in the Thread integration, however I can’t set it as my preferred network. I clicked “Send credentials to HA” on my iPhone, but it does not seem to sync them with HA
Solved it… the problem was some old nonexisting Thread network being listed as Preferred in HA. To fix:
- Remove the Thread credentials from the iPhone. This requires a Mac, thankfully I had one lying around.
- Send Credentials to HA from the Companion app
- Restart the HA instance
Now the old network had disappeared, and my OpenThread network was listed as the Preferred network… under the name of that old network? Odd.
- Select “Used for Android/iPhone credentials” on the network.
- On the Companion app, Send Credentials to HA
After that I was able to add a Thread sensor using the app.
Seems the precompiled firmware (C6, internal antenna) contains the freezing bug? Happy that I got border router on C6 to work, now it freezed.
Can someone help with fresh compiled firmware on v6.0 beta 1 or newer?