Difficulty: Intermediate (comfortable with CLI and flashing firmware)
Cost: ~$5–$10
Time: ~2–3 hours
What This Guide Covers
This guide walks through building a standalone WiFi-based Thread border router using an ESP32-C6 development board. The board runs entirely on its own — no USB connection to HA required — and advertises itself via mDNS so Home Assistant discovers it automatically.
This is not the ESPHome OpenThread component approach, which makes the C6 a Thread end device. This builds a proper border router using the ot_br example from ESP-IDF, equivalent to what a commercial border router does.
Why This Approach?
Most DIY guides cover using an ESP32-C6 or ESP32-H2 as an RCP (Radio Co-Processor) plugged directly into your HA server via USB. That works, but it ties your border router to your server and means a USB cable running to wherever you need coverage.
This guide builds a standalone border router — plug it into any USB charger anywhere in your home, and it connects over WiFi and joins your Thread network automatically.
Hardware Required
- ESP32-C6 development board with 8MB flash (N8 variant)
- The Seeed Studio XIAO ESP32-C6 is a popular choice for its small size
- Any standard ESP32-C6 devkit works
- Avoid 4MB flash variants — partition space is very tight
- A Mac or Linux machine for building (this guide uses Mac/Linux)
- A USB cable for flashing
Note: The ESP32-C6 shares one RF path between WiFi and Thread. This is a minor performance tradeoff vs a dedicated two-chip setup, but works well as a home border router.
Important: What This Firmware Cannot Do
Before starting, understand one key limitation: the ot_br example has no REST API. This means you cannot push Thread credentials to it remotely. The only reliable way to join it to an existing HA Thread network is to flash it with no stored dataset and let HA provision it automatically on first boot. This guide covers exactly how to do that.
If you already have a Thread border router connected to HA, you must temporarily disconnect it before provisioning the ESP32-C6. With an existing border router present, HA considers the Thread network already active and will not provision a new device — the ESP32-C6 will boot with no dataset and form its own separate Thread network instead of joining yours.
The process is: disconnect your existing border router first → power up the ESP32-C6 → wait for HA to discover and provision it → then reconnect your existing border router. Once provisioned, both border routers will be on the same network and can run simultaneously.
Part 1: Set Up the Build Environment
Install Dependencies (Mac)
brew install cmake ninja dfu-util python3 git
Clone ESP-IDF
mkdir -p ~/esp && cd ~/esp
git clone -b v5.4.2 --recursive https://github.com/espressif/esp-idf.git
Run the Installer
cd ~/esp/esp-idf
./install.sh esp32c6
Activate the Environment
Run this at the start of every new terminal session before building:
. ~/esp/esp-idf/export.sh
Part 2: Configure the Firmware
Navigate to the example:
cd ~/esp/esp-idf/examples/openthread/ot_br
Open the configuration menu:
idf.py menuconfig
Work through each section below. These settings are not optional — skipping any of them will cause the build to fail or the device to misbehave.
Flash Size
Serial flasher config → Flash size → 8MB
Must match your board’s actual flash size.
Radio Mode ← CRITICAL
Component config → OpenThread → Thread 15.4 Radio Link
Select: Native 15.4 radio
This is the most important setting. Without it, the firmware tries to talk to an external radio chip that doesn’t exist, and nothing will work.
Console Type
Component config → OpenThread → Thread Console
Select: USB Serial/JTAG
This prevents a watchdog crash caused by a conflict between the UART console task and the USB serial connection used for flashing and monitoring.
Disable OpenThread CLI
Component config → OpenThread → Thread Extended Features
Disable: Enable OpenThread CLI
Not needed for a standalone border router and causes issues when enabled alongside the USB Serial/JTAG console.
WiFi Credentials
Example Connection Configuration
- WiFi SSID: your network name
- WiFi Password: your password
- Auth mode:
WPA2 PSK
The default auth mode is Open — you must change this or the device will fail to connect to any secured network.
Auto-Start
Example Configuration
Enable: Enable the automatic start mode in Thread Border Router
Without this, the device boots but does not start the border router automatically.
Thread Dataset (Optional)
Component config → OpenThread → Thread Core Features → Thread Operational Dataset
You can optionally pre-configure your Thread network credentials here. However, it is recommended to leave these blank and let HA provision the device on first boot instead. See Part 4 for why.
Save and exit menuconfig.
Part 3: Build and Flash
Find your device port:
ls /dev/cu.* # Mac
ls /dev/ttyUSB* # Linux
Build and flash:
idf.py build && idf.py -p /dev/cu.usbmodem101 flash monitor
Replace /dev/cu.usbmodem101 with your actual port.
Successful Boot — What to Look For
OpenThread attached to netif
Got IPv4 event: address: 192.168.x.x
mDNS task will be created from internal RAM
Exit the monitor with Ctrl+].
Verify mDNS Discovery
From your Mac or Linux machine:
dns-sd -B _meshcop._udp local # Mac
avahi-browse _meshcop._udp # Linux
You should see esp-ot-br listed. This confirms Home Assistant will be able to discover the device.
Part 4: Join Your Existing HA Thread Network
When the device first boots with no stored dataset, HA will automatically provision it with your preferred Thread network credentials. This is the cleanest way to ensure it joins the right network.
If the device previously had a dataset stored (from a prior flash or from pre-configuring credentials in menuconfig), it will form its own separate Thread network instead of joining yours. To fix this:
- Erase the flash to clear the stored dataset:
idf.py -p /dev/cu.usbmodem101 erase-flash
- Reflash:
idf.py -p /dev/cu.usbmodem101 flash
- On boot, the device will have no dataset. HA discovers it via mDNS and provisions it with your preferred network credentials automatically.
After provisioning, check Settings → Devices & Services → Thread in HA. Your esp-ot-br border router should appear under your preferred network.
Part 5: Deploy
Once confirmed working:
- Note the IP address from the boot log or your router’s DHCP table
- Assign a static DHCP reservation so the IP doesn’t change between reboots
- Unplug from your Mac and plug into any USB charger — the device is now standalone
Monitoring
Since there is no REST API and no web UI in this firmware, your options for checking the device is alive are:
- Uptime Kuma — add a ping monitor for the device’s reserved IP
- Home Assistant Thread page — if
esp-ot-brdisappears from the border router list, it’s offline - mDNS query —
dns-sd -B _meshcop._udp localfrom any Mac on the network
Re-flashing Reference
If you need to rebuild in a future session:
. ~/esp/esp-idf/export.sh
cd ~/esp/esp-idf/examples/openthread/ot_br
# sdkconfig stores your settings — only re-run menuconfig if starting fresh
idf.py build && idf.py -p /dev/cu.usbmodem101 flash monitor
Gotchas Summary
| Gotcha | Fix |
|---|---|
CONFIG_OPENTHREAD_RADIO_NATIVE not set by default |
Set manually in menuconfig → Thread 15.4 Radio Link |
| Watchdog crash on boot | Switch console to USB Serial/JTAG in menuconfig |
| Default WiFi auth is Open | Change to WPA2 PSK in menuconfig |
| Auto-start not enabled by default | Enable in Example Configuration |
| Device forms its own Thread network | Erase flash, reflash, let HA provision |
| esp-thread-br SDK won’t work for single-chip builds | Use ot_br from esp-idf instead — esp-thread-br is two-chip only |
Software Versions Used
- ESP-IDF: v5.4.2
- HA OpenThread Border Router add-on: v2.15.3
- Home Assistant OS: tested on current stable
Notes
- The
esp-thread-brSDK does not support single-chip native radio mode. It requires a two-chip setup (e.g., ESP32-S3 host + ESP32-H2 radio). Use theot_brexample fromesp-idffor single-chip C6 builds. - If you want a border router with a web UI and REST API (for easier credential management), look at the Espressif ESP Thread Border Router board (S3 + H2 two-chip design) or a commercial option like the GL-S20.
- Multiple border routers on the same Thread network are fully supported by HA and improve mesh reliability and coverage.
This took a fair amount of trial and error to get working and the documentation for the single-chip native radio path is sparse.