Connect ZBT-2 Thread to Home Assistant Container

@jkkataja I added your comment to my original message in this thread. Thanks!

1 Like

He Gents,

I have read the whole topic, and im having some issues while following your guides. I tried to solve some steps with CHATGTP as well, but no luck so far. I really hope you guys can help me.

I have a mini PC with docker running. i use the docker-compose through portainer.

First of all, I have installed the RCP via Home Assistant Connect ZBT-2 – Device Toolbox on my ZBT-2.
Secondly i run the script “Allow IPv6 forwarding” without errors (where i changed to my primary network enp1s0).

Then i configured the OTBR in HA. After that I did matter with de default socket. Followed by threat integration and confirmed my OTBR was preferred Border router.

Once done with the integrations and all, i wanted to pair a device and received a message “couldnt connect to this accessory”.

Next step i did, was checking the logs. Im a little clueless what to do. Can somebody guide me a bit here? Cause in the matter logs i do see an error which i cannot resolve.

Also added this in my /etc/sysctl.conf:

net.ipv4.conf.all.forwarding = 1

net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra_rt_info_max_plen = 64
net.ipv6.conf.all.accept_ra = 2

net.ipv6.conf.eth0.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.accept_ra_rt_info_max_plen = 64

logs from OTBR:

s6-rc: info: service legacy-services: stopping
s6-rc: info: service legacy-services successfully stopped
s6-rc: info: service otbr-agent: stopping
00:46:08.240 [D] P-Daemon------: Removing daemon socket: /run/openthread-wpan0.sock
00:46:08.240 [I] BorderRouting-: Disabling
00:46:08.240 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:15, cmd:PROP_VALUE_SET, key:PHY_ENABLED, enabled:0
00:46:08.240 [D] P-RadioSpinel-: Wait response: tid=15 key=32
00:46:08.241 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:15, cmd:PROP_VALUE_IS, key:PHY_ENABLED, enabled:0
00:46:08.241 [I] TrelInterface-: Disabled interface
00:46:08.259 [D] P-Trel--------: platformTrelDeinit()
otbr-agent exited with code 0 (by signal 0).
Chain OT_FORWARD_INGRESS (0 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere             PKTTYPE = unicast
DROP       all  --  anywhere             anywhere             match-set otbr-ingress-deny-src src
ACCEPT     all  --  anywhere             anywhere             match-set otbr-ingress-allow-dst dst
DROP       all  --  anywhere             anywhere             PKTTYPE = unicast
ACCEPT     all  --  anywhere             anywhere            
otbr-ingress-deny-src
otbr-ingress-deny-src-swap
otbr-ingress-allow-dst
otbr-ingress-allow-dst-swap
OpenThread firewall rules removed.
s6-rc: info: service otbr-agent successfully stopped
s6-rc: info: service legacy-cont-init: stopping
s6-rc: info: service legacy-cont-init successfully stopped
s6-rc: info: service fix-attrs: stopping
s6-rc: info: service fix-attrs successfully stopped
s6-rc: info: service s6rc-oneshot-runner: stopping
s6-rc: info: service s6rc-oneshot-runner successfully stopped
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service otbr-agent: starting
Configuring OpenThread firewall...
Configuring OpenThread NAT64...
Starting otbr-agent...
[NOTE]-AGENT---: Running 0.3.0-fa0009a
[NOTE]-AGENT---: Thread version: 1.4.0
[NOTE]-AGENT---: Thread interface: wpan0
[NOTE]-AGENT---: Radio URL: spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800
[NOTE]-AGENT---: Radio URL: trel://enp1s0
[NOTE]-ILS-----: Infra link selected: enp1s0
[INFO]-RCP_HOS-: OpenThread log level changed to 5
49d.19:52:11.304 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:0, cmd:RESET
49d.19:52:11.304 [D] P-SpinelDrive-: Waiting response: key=0
49d.19:52:11.305 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:0, cmd:PROP_VALUE_IS, key:LAST_STATUS, status:RESET_POWER_ON
49d.19:52:11.305 [I] P-SpinelDrive-: co-processor reset: RESET_POWER_ON
49d.19:52:11.306 [C] P-SpinelDrive-: Software reset co-processor successfully
49d.19:52:11.306 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_GET, key:PROTOCOL_VERSION
49d.19:52:11.306 [D] P-SpinelDrive-: Waiting response: key=1
49d.19:52:11.307 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_IS, key:PROTOCOL_VERSION, major:4, minor:3
49d.19:52:11.307 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_GET, key:NCP_VERSION
49d.19:52:11.307 [D] P-SpinelDrive-: Waiting response: key=2
49d.19:52:11.310 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_IS, key:NCP_VERSION, version:SL-OPENTHREAD/2.4.4.0_GitHub-7074a43e4; EFR32; Oct 29 2025 17:44:03
49d.19:52:11.310 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_GET, key:CAPS
49d.19:52:11.310 [D] P-SpinelDrive-: Waiting response: key=5
49d.19:52:11.312 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_IS, key:CAPS, caps:COUNTERS UNSOL_UPDATE_FILTER 802_15_4_2450MHZ_OQPSK CONFIG_RADIO MAC_RAW RCP_API_VERSION RCP_MIN_HOST_API_VERSION RCP_RESET_TO_BOOTLOADER OPENTHREAD_LOG_METADATA 
49d.19:52:11.313 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_GET, key:HWADDR
49d.19:52:11.313 [D] P-RadioSpinel-: Wait response: tid=1 key=8
49d.19:52:11.315 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:1, cmd:PROP_VALUE_IS, key:HWADDR, eui64:e456acfffe67ac33
49d.19:52:11.315 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:2, cmd:PROP_VALUE_GET, key:RCP_API_VERSION
49d.19:52:11.315 [D] P-RadioSpinel-: Wait response: tid=2 key=176
49d.19:52:11.316 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:2, cmd:PROP_VALUE_IS, key:RCP_API_VERSION, version:9
49d.19:52:11.316 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:3, cmd:PROP_VALUE_GET, key:RCP_MIN_HOST_API_VERSION
49d.19:52:11.316 [D] P-RadioSpinel-: Wait response: tid=3 key=177
49d.19:52:11.317 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:3, cmd:PROP_VALUE_IS, key:RCP_MIN_HOST_API_VERSION, min-host-version:4
49d.19:52:11.317 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:4, cmd:PROP_VALUE_GET, key:RADIO_CAPS
49d.19:52:11.317 [D] P-RadioSpinel-: Wait response: tid=4 key=4619
49d.19:52:11.319 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:4, cmd:PROP_VALUE_IS, key:RADIO_CAPS, caps:255
49d.19:52:11.319 [D] P-Trel--------: platformTrelInit(aTrelUrl:"trel://enp1s0")
49d.19:52:11.319 [D] P-Trel--------: otSysTrelInit(aInterfaceName:"enp1s0")
49d.19:52:11.319 [I] P-Netif-------: Sent request#1 to set addr_gen_mode to 1
49d.19:52:11.320 [I] P-Resolver----: Got nameserver #0: 8.8.8.8
49d.19:52:11.320 [I] P-Resolver----: Got nameserver #1: 8.8.4.4
00:00:00.000 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:5, cmd:PROP_VALUE_GET, key:PHY_CHAN_SUPPORTED
00:00:00.000 [D] P-RadioSpinel-: Wait response: tid=5 key=34
00:00:00.002 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:5, cmd:PROP_VALUE_IS, key:PHY_CHAN_SUPPORTED, channelMask:0x07fff800
00:00:00.002 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:6, cmd:PROP_VALUE_SET, key:PHY_ENABLED, enabled:1
00:00:00.002 [D] P-RadioSpinel-: Wait response: tid=6 key=32
00:00:00.003 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:6, cmd:PROP_VALUE_IS, key:PHY_ENABLED, enabled:1
00:00:00.003 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:7, cmd:PROP_VALUE_SET, key:MAC_15_4_PANID, panid:0xffff
00:00:00.003 [D] P-RadioSpinel-: Wait response: tid=7 key=54
00:00:00.004 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:7, cmd:PROP_VALUE_IS, key:MAC_15_4_PANID, panid:0xffff
00:00:00.004 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:8, cmd:PROP_VALUE_SET, key:MAC_15_4_SADDR, saddr:0x0000
00:00:00.004 [D] P-RadioSpinel-: Wait response: tid=8 key=53
00:00:00.005 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:8, cmd:PROP_VALUE_IS, key:MAC_15_4_SADDR, saddr:0x0000
00:00:00.005 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:9, cmd:PROP_VALUE_GET, key:PHY_RX_SENSITIVITY
00:00:00.005 [D] P-RadioSpinel-: Wait response: tid=9 key=39
00:00:00.006 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:9, cmd:PROP_VALUE_IS, key:PHY_RX_SENSITIVITY, sensitivity:-100
00:00:00.006 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:10, cmd:PROP_VALUE_SET, key:RCP_MAC_KEY, keyIdMode:8, keyId:1, prevKey:***, currKey:***, nextKey:***
00:00:00.006 [D] P-RadioSpinel-: Wait response: tid=10 key=2048
00:00:00.009 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:10, cmd:PROP_VALUE_IS, key:LAST_STATUS, status:OK
00:00:00.009 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:11, cmd:PROP_VALUE_SET, key:MAC_15_4_LADDR, laddr:ca72ef55bdef0e79
00:00:00.009 [D] P-RadioSpinel-: Wait response: tid=11 key=52
00:00:00.011 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:11, cmd:PROP_VALUE_IS, key:MAC_15_4_LADDR, laddr:ca72ef55bdef0e79
00:00:00.011 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:12, cmd:PROP_VALUE_SET, key:MAC_15_4_SADDR, saddr:0xfffe
00:00:00.011 [D] P-RadioSpinel-: Wait response: tid=12 key=53
00:00:00.012 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:12, cmd:PROP_VALUE_IS, key:MAC_15_4_SADDR, saddr:0xfffe
00:00:00.012 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:13, cmd:PROP_VALUE_SET, key:MAC_SRC_MATCH_SHORT_ADDRESSES, saddr:none
00:00:00.012 [D] P-RadioSpinel-: Wait response: tid=13 key=4868
00:00:00.013 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:13, cmd:PROP_VALUE_IS, key:LAST_STATUS, status:OK
00:00:00.013 [D] P-SpinelDrive-: Sent spinel frame, flg:0x2, iid:0, tid:14, cmd:PROP_VALUE_SET, key:MAC_SRC_MATCH_EXTENDED_ADDRESSES, extaddr:none
00:00:00.013 [D] P-RadioSpinel-: Wait response: tid=14 key=4869
00:00:00.014 [D] P-SpinelDrive-: Received spinel frame, flg:0x2, iid:0, tid:14, cmd:PROP_VALUE_IS, key:LAST_STATUS, status:OK
00:00:00.014 [I] CslTxScheduler: Set frame request ahead: 7605 usec
00:00:00.015 [I] ChildSupervsn-: Timeout: 0 -> 190
00:00:00.015 [D] P-Trel--------: PrepareSocket()
00:00:00.015 [I] TrelInterface-: Enabled interface, local port:58572
00:00:00.016 [I] InfraIf-------: Init infra netif 2
00:00:00.016 [I] Settings------: Read BrUlaPrefix fd7e:5a2e:fa59::/48
00:00:00.016 [N] BorderRouting-: BR ULA prefix: fd7e:5a2e:fa59::/48 (loaded)
00:00:00.016 [I] BorderRouting-: Generated local OMR prefix: fd7e:5a2e:fa59:1::/64
00:00:00.016 [I] BorderRouting-: Generated local NAT64 prefix: fd7e:5a2e:fa59:2:0:0::/96
00:00:00.016 [N] BorderRouting-: Local on-link prefix: fdde:ad00:beef:cafe::/64
00:00:00.016 [I] InfraIf-------: State changed: NOT RUNNING -> RUNNING
00:00:00.016 [I] P-MdnsSocket--: Successfully opened IPv4 socket
00:00:00.016 [I] P-MdnsSocket--: Successfully opened IPv6 socket
00:00:00.017 [I] P-MdnsSocket--: Enabled
00:00:00.017 [I] MulticastDns--: Auto-enabling on infra-if-index 2
00:00:00.017 [I] Settings------: Read BorderAgentId {id:eba4365812ff0243246f7330958c0ac0}
00:00:00.017 [I] BorderRouting-: Enabling
00:00:00.017 [I] Nat64---------: IPv4 CIDR for NAT64: 192.168.255.0/24 (254 addresses)
[INFO]-HELPER--: Set state callback: OK
00:00:00.018 [I] Nat64---------: State: Disabled -> NotRunning
00:00:00.018 [I] BbrLocal------: Add Domain Prefix: ::/0, NotFound
00:00:00.018 [I] BbrLocal------: Add BBR Service: seqno (100), delay (5s), timeout (3600s), InvalidState
[WARN]-UTILS---: /usr/src/ot-br-posix/src/rest/network_diag_handler.cpp:1300 lacking some attributes for deviceId ca72ef55bdef0e79
[WARN]-UTILS---: /usr/src/ot-br-posix/src/rest/network_diag_handler.cpp:1244 cannot get LeaderData while detached
[WARN]-UTILS---: /usr/src/ot-br-posix/src/rest/rest_devices_coll.cpp:232 - AddItem - ca72ef55bdef0e79
[INFO]-APP-----: Radio Co-processor version: SL-OPENTHREAD/2.4.4.0_GitHub-7074a43e4; EFR32; Oct 29 2025 17:44:03
[INFO]-REST----: RestWebServer listening on 127.0.0.1:8981
00:00:00.018 [I] Notifier------: StateChanged (0x42038210) [MLAddr NetData PanId NetName ExtPanId BbrState Nat64]
00:00:00.018 [I] BbrLeader-----: PBBR state: None
00:00:00.018 [I] Bbr-----------: Start listening on port 61631
00:00:00.018 [I] Bbr-----------: Backbone TMF subscribes ff32:40:fdde:ad00:beef:0:0:3: OK
00:00:00.018 [I] BbrManager----: Start Backbone TMF agent: OK
00:00:00.022 [I] Platform------: Execute command `ipset flush otbr-ingress-allow-dst-swap` = 0
00:00:00.025 [I] Platform------: Execute command `ipset flush otbr-ingress-deny-src-swap` = 0
00:00:00.027 [I] Platform------: Execute command `ipset add otbr-ingress-deny-src-swap fdde:ad00:beef:0::/64 -exist` = 0
00:00:00.029 [I] Platform------: Execute command `ipset swap otbr-ingress-deny-src-swap otbr-ingress-deny-src` = 0
00:00:00.030 [I] Platform------: Execute command `ipset swap otbr-ingress-allow-dst-swap otbr-ingress-allow-dst` = 0
00:00:00.031 [I] P-Netif-------: NAT64 CIDR updated to 192.168.255.0/24.
00:00:00.031 [I] P-Netif-------: Sent request#2 to delete route 192.168.255.0/24
00:00:00.031 [I] P-Netif-------: Deleting route for NAT64
00:00:00.031 [I] P-McastRtMgr--: Disable: OK
[DEBG]-BBA-----: BackboneAgent: HandleBackboneRouterState: state=1, mBackboneRouterState=0
00:00:00.031 [I] RouterTable---: Route table
00:00:00.031 [I] TrelDiscoverer: Registering service otTRELca72ef55bdef0e79._trel._udp
00:00:00.031 [I] TrelDiscoverer:     port:58572, ext-addr:ca72ef55bdef0e79, ext-panid:dead00beef00cafe
00:00:00.031 [I] MulticastDns--: Adding host address 192.168.178.18
00:00:00.031 [I] MulticastDns--: Adding host address fe80:0:0:0:7e83:34ff:feb9:edd1
00:00:00.031 [I] P-Netif-------: Host netif is down
00:00:00.033 [I] P-Netif-------: Succeeded to process request#1
00:00:00.033 [W] P-Netif-------: Failed to process request#2: No such process
s6-rc: info: service otbr-agent successfully started
s6-rc: info: service legacy-services: starting
s6-rc: info: service legacy-services successfully started
00:00:00.870 [I] TrelDiscoverer: DNS-SD service registered successfully
00:00:00.871 [I] TrelPeerTable-: Added peer otTRELca72ef55bdef0e79, dnssd-state:resolving
00:00:00.871 [I] TrelDiscoverer: Peer otTRELca72ef55bdef0e79 is this device itself
00:00:00.871 [I] TrelPeerTable-: Deleted peer otTRELca72ef55bdef0e79, dnssd-state:resolving

Logs from Matter-server:

2026-01-11 11:31:55.326 (MainThread) INFO [matter_server.server.stack] Initializing CHIP/Matter Logging...
2026-01-11 11:31:55.326 (MainThread) INFO [matter_server.server.stack] Initializing CHIP/Matter Controller Stack...
[1768131115.344761][1:1] CHIP:CTL: Setting attestation nonce to random value
[1768131115.344950][1:1] CHIP:CTL: Setting CSR nonce to random value
[1768131115.345542][1:1] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /tmp/chip_kvs
[1768131115.349810][1:1] CHIP:DL: Wrote settings to /tmp/chip_kvs
[1768131115.349990][1:1] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /data/chip_factory.ini
[1768131115.350080][1:1] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /data/chip_config.ini
[1768131115.350111][1:1] CHIP:DL: ChipLinuxStorage::Init: Using KVS config file: /data/chip_counters.ini
[1768131115.351368][1:1] CHIP:DL: Wrote settings to /data/chip_counters.ini
[1768131115.351375][1:1] CHIP:DL: NVS set: chip-counters/reboot-count = 16 (0x10)
[1768131115.351788][1:1] CHIP:DL: Got Ethernet interface: enp1s0
[1768131115.352056][1:1] CHIP:DL: Found the primary Ethernet interface:enp1s0
[1768131115.352535][1:1] CHIP:DL: Failed to get WiFi interface
[1768131115.352539][1:1] CHIP:DL: Failed to reset WiFi statistic counts
[1768131115.352542][1:1] CHIP:PAF: WiFiPAF: WiFiPAFLayer::Init()
2026-01-11 11:31:55.352 (MainThread) INFO [chip.storage] Initializing persistent storage from file: /data/chip.json
2026-01-11 11:31:55.352 (MainThread) INFO [chip.storage] Loading configuration from /data/chip.json...
2026-01-11 11:31:55.437 (MainThread) INFO [chip.CertificateAuthority] Loading certificate authorities from storage...
2026-01-11 11:31:55.437 (MainThread) INFO [chip.CertificateAuthority] New CertificateAuthority at index 1
2026-01-11 11:31:55.437 (MainThread) INFO [chip.CertificateAuthority] Loading fabric admins from storage...
2026-01-11 11:31:55.437 (MainThread) INFO [chip.FabricAdmin] New FabricAdmin: FabricId: 0x0000000000000001, VendorId = 0xFFF1
2026-01-11 11:31:55.438 (MainThread) INFO [matter_server.server.stack] CHIP Controller Stack initialized.
2026-01-11 11:31:55.438 (MainThread) INFO [matter_server.server.server] Matter Server initialized
2026-01-11 11:31:55.438 (MainThread) INFO [matter_server.server.server] Using 'None' as primary interface (for link-local addresses)
2026-01-11 11:31:55.438 (MainThread) INFO [matter_server.server.server] Starting the Matter Server...
2026-01-11 11:31:55.441 (MainThread) INFO [matter_server.server.helpers.paa_certificates] Skip fetching certificates (already fetched within the last 24h).
2026-01-11 11:31:55.441 (MainThread) INFO [chip.FabricAdmin] Allocating new controller with CaIndex: 1, FabricId: 0x0000000000000001, NodeId: 0x000000000001B669, CatTags: []
2026-01-11 11:31:55.477 (Dummy-2) CHIP_ERROR [chip.native.DIS] Failed to advertise records: src/inet/UDPEndPointImplSockets.cpp:417: OS Error 0x02000065: Network is unreachable
2026-01-11 11:31:55.478 (Dummy-2) CHIP_ERROR [chip.native.DIS] Failed to advertise records: src/inet/UDPEndPointImplSockets.cpp:417: OS Error 0x02000063: Cannot assign requested address
2026-01-11 11:31:55.487 (MainThread) INFO [matter_server.server.vendor_info] Loading vendor info from storage.
2026-01-11 11:31:55.490 (MainThread) INFO [matter_server.server.vendor_info] Loaded 386 vendors from storage.
2026-01-11 11:31:55.491 (MainThread) INFO [matter_server.server.vendor_info] Fetching the latest vendor info from DCL.
2026-01-11 11:31:55.739 (MainThread) INFO [matter_server.server.vendor_info] Fetched 385 vendors from DCL.
2026-01-11 11:31:55.739 (MainThread) INFO [matter_server.server.vendor_info] Saving vendor info to storage.
2026-01-11 11:31:55.743 (MainThread) INFO [matter_server.server.device_controller] Loaded 0 nodes from stored configuration
2026-01-11 11:31:55.748 (MainThread) INFO [matter_server.server.server] Matter Server successfully initialized.

Docker-compose i used:

   matter-server:
    image: ghcr.io/matter-js/python-matter-server:stable
    container_name: matter-server
    depends_on:
      - otbr
    network_mode: host
    security_opt:
      - apparmor:unconfined
    volumes:
      - './matter-server/data:/data'
    restart: unless-stopped
    environment:
      - MATTER_PRIMARY_INTERFACE=trel://enp1s0
      - MATTER_ENABLE_WIFI=0     # dwing Wi-Fi uit
      - MATTER_ENABLE_THREAD=1   # Thread inschakelen
    cap_add:
      - NET_ADMIN             # nodig voor sommige netwerkoperaties
  otbr:
    container_name: otbr
    image: openthread/border-router:latest
    devices:
      - /dev/serial/by-id/usb-Nabu_Casa_ZBT-2_DCB4D90E3EC8-if00:/dev/ttyACM5
      - /dev/net/tun:/dev/net/tun
    environment:
      OT_RCP_DEVICE: spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800
      OT_INFRA_IF: enp1s0
      OT_THREAD_IF: wpan0
      OT_REST_PORT: 8981
      OT_REST_LISTEN_PORT: 8981
    network_mode: host
    privileged: true
    restart: unless-stopped
    cap_add:
      - NET_ADMIN

Looking at your docker-compose.yaml in the devices section you reference /dev/ttyACM4 but in your environment section you reference /dev/ttyACM0

1 Like

Thanks for your reply. I have updated this, but it did not changed anything, except for the below line in the log:

[NOTE]-AGENT---: Radio URL: spinel+hdlc+uart:///dev/ttyACM5?uart-baudrate=460800

Any other suggestions?

i just compared your docker-compose yaml to mine.

matter-server

  • you have a few options that might not needed, depends_on, environment, cap_add
  • try to remove those and down/up the container again and see how that go. also, i noticed that every down/up or restart, otbr will need at least like 30 sec for it to be fully functional.

otbr

  • make sure if you map your device to /dev/ttyACM5, then your environment also has to be /dev/ttyACM5.
  • you can remove privileged if you have /dev/net/tun mapped.
  • you probably want to save the otbr data
    volumes:
      - './otbr/data:/data'

hope this help.

1 Like

reporting back …

things to consider

  1. my Tread integration showing a lot of OpenThread networks. obviously only ONE is active/real. but i cant seem to permanently remove them… i can delete but they come back when i restart h-a/otbr/matter-server
  2. IF i have to join a diff network/reset, i cant seem to get any of the paired matter accessories to work anymore. i have to repair everyone. that doesnt seem like a good solution if you have 10+ devices.
  3. speaking of pairing. they dont pair new accessories anymore. maybe because i have messed with the openthread network or something else. the previously paired accessories are fine but just cant pair any new items. BUT if you recreate the network. you will loose every accessories (item 2 above)…

so now i am stuck on having redo EVERYTHING… not ideal at all. i dont know what the correct path. everything is still wizardry at this point to me.

Hi! Apart from what was already said in the replies above, I noticed in your /etc/sysctl.conf output you don’t have net.ipv4.ip_forward=1. Maybe it’s set and just not in the output, but if it isn’t, it’s very likely you need to add it too (and then reload the sysctl settings, of course.)

Also, please note it’s not the same as net.ipv4.conf.all.forwarding = 1.

1 Like

I get the same error as you in the matter-server docker:

Everything else seems to work. I just can’t add matter devices and get the error “Can’t reach device”.

Matter has been nothing but pain, I don’t see it ever replacing Zigbee.

thanks for your reply. I have added this. Unfortunately this did not fix it.

I just got mine fixed.

My issue was an IPV6 issue i guess.

On top of everything mentioned in my first post, i changed to the “ownbee” otbr image and installing radvd, i was able to setup another IPV6 then the default starting with “fe” (config file is below).

For matter, its a bit weird,

  1. i have added (not replaced the default) in the CMD “–primary-interface enp1s0”
  2. the logs showing that it uses now enp1s0 instead of “none”
  3. however, same error still shows (even though it works)

Additionally, i have enabled IPV6 on my router, but my feeling is that this did not solve anything.

I have removed all integrations I had in Home assistant (matter, thread, otbr).
At the end, i have rebooted the mini pc i have.

As said, I do still receive the same error in matter. In OTBR, i do get some other errors, related to other IPV6 addresses. But both can be ignored in my case.

After reboot, Matter and Thread was discovered automatically. Manually i have added the OTBR.

Added the discovered Matter (and thread automatically came with OTBR). Then i have used my iphone to share creds with phone.

After that I could add my device accordingly in pair mode and with my phone i added matter device, scanned the QR-code and worked nicely.

Below my docker-compose.yaml (the CMD command i have added through portainer so its not in my compose below).

  matter-server:
    image: ghcr.io/matter-js/python-matter-server:stable
    container_name: matter-server
    #depends_on:
    #  - otbr
    network_mode: host
    privileged: true
    security_opt:
      - apparmor:unconfined
    volumes:
      - './matter-server/data:/data'
    restart: unless-stopped
    environment:
      PRIMARY_IF: enp1s0
    #  - MATTER_PRIMARY_INTERFACE=enp1s0
    #  - MATTER_ENABLE_WIFI=0     # dwing Wi-Fi uit
    #  - MATTER_ENABLE_THREAD=1   # Thread inschakelen
    #cap_add:
    #  - NET_ADMIN             # nodig voor sommige netwerkoperaties

  otbr:
    container_name: otbr
    image: ghcr.io/ownbee/hass-otbr-docker:latest
    restart: unless-stopped
    privileged: true # don't change this !
    network_mode: host # don't change this !
    cap_add:
      - SYS_ADMIN
      - NET_ADMIN
    environment:
      DEVICE: "/dev/ttyACM5"
      BACKBONE_IF: enp1s0
      FLOW_CONTROL: 1
      FIREWALL: 1
      NAT64: 1
      BAUDRATE: 460800
      OTBR_REST_PORT: 8081
      OTBR_WEB_PORT: 8980
      AUTOFLASH_FIRMWARE: 0
    devices:
      - /dev/serial/by-id/usb-Nabu_Casa_ZBT-2_DCB4D90E3EC8-if00:/dev/ttyACM5
      - /dev/net/tun:/dev/net/tun
    volumes:
      - ./otbr_data:/var/lib/thread

For radvd i have created the file /etc/radvd.conf :

interface enp1s0
{
  AdvSendAdvert on;
  prefix fd42:1337:beef::/64
  {
    AdvOnLink on;
    AdvAutonomous on;
  };
};
2 Likes

@wpbezemer What is your base linux system? Mine is Ubuntu 22.04, maybe that creates a difference in setup as well.

Sietse

I managed to get it to work aswel. Been running perfectly overnight and through a restart so all seems good. I added 2 matter devices without issues.

So I already ran the IPv6 script mentioned here. Just to be sure, I also added the following to the /etc/sysctl.conf. I replaced the “eth0” with my proper interface which is for me “eno2”.

net.ipv4.conf.all.forwarding = 1

net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra_rt_info_max_plen = 64
net.ipv6.conf.all.accept_ra = 2

net.ipv6.conf.eth0.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.accept_ra_rt_info_max_plen = 64

To apply changes:

sysctl -p

And to make changes to the firewall:

modprobe ip6table_filter

Next I also switched to the “ownbee” image and followed your configuration. I did remove the “volume” part in the otbr docker as I got the error I didn’t have permission to access the /var/lib/tread folder. I don’t know how this will affect me. My configuration already survived an otbr container restart and home assistant restart so it seems fine.

I also went with another matter-server image as that one seems to download real slow for me.

So my working configuration:

 otbr:
   container_name: otbr
   image: ghcr.io/ownbee/hass-otbr-docker:latest
   restart: unless-stopped
   privileged: true
   devices:
     - /dev/serial/by-id/usb-Nabu_Casa_ZBT-2_XXXXXXXXXXX-if00:/dev/ttyACM1
     - /dev/net/tun:/dev/net/tun
   environment:
     DEVICE: "/dev/ttyACM1"
     FLOW_CONTROL: 1
     FIREWALL: 1
     NAT64: 1
     BAUDRATE: 460800
     OTBR_WEB_PORT: 8982
     OTBR_REST_PORT: 8981
     AUTOFLASH_FIRMWARE: 0
     BACKBONE_IF: "eno2"    #Change this to your network interface
   network_mode: host

 matter-server:
   container_name: matter-server
   image: ghcr.io/home-assistant-libs/python-matter-server:stable
   restart: unless-stopped
   volumes:
     - ./matter-server/data:/data
   security_opt:
     - apparmor:unconfined
   network_mode: host

Biggest change I noticed during configuration is that during the Open Thread Border Router configuration in Home Assistant I used my local network address 192.x.x.x:[my port number] with the “OTBR_REST_PORT” port instead of the 127.0.0.1:[my port number]. Which makes a lot of sense actually…so home assistant can properly communicate with my network.

Happy it finally works but still no Matter fan… Zigbee is still king for me.

If anything breaks or goes wrong, I’ll report back.

2 Likes

Hi Sietse,

I get this in my linux “Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-164-generic x86_64)”. Based on below it seems the same. But maybe I have messed up the configs in the past (i guess not as i do have a dev mini pc to experiment).

PRETTY_NAME=“Ubuntu 22.04.5 LTS”
NAME=“Ubuntu”
VERSION_ID=“22.04”
VERSION=“22.04.5 LTS (Jammy Jellyfish)”
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian

Regards,
Wytse

Hi JeL0,

Great to see yours working as well.
I personally did nothing with the firewall, but it seems you know more about linux and networking then I do.

About the volume, I just copied over from other examples I saw. Guess without it automatically create the volume to a default path, instead of the one I mentioned.

Somehow I do agree that local ip makes sense. However I did it with 127.0.0.1:[port] As i saw this in all other examples I could find on the internet.

Also I do agree about zigbee. Still running this in parallel. However, bought yesterday some extra matter devices from Ikea beside the Lafaer presence sensor I already had. But in general there are lesser devices found for matter over thread unfortunately (I did expected now even more in Ali).

For now only thing i noticed is that one device a bit far from the ZBT-2, became unavailable twice in 2 days. Other devices did not show any issues so far.

In case of any other issues / observations I’ll report back too!

ok. so ever since i got it working when i first set it up and tried to recreate the process. it has not worked ever since. )=

i have tried @wpbezemer and @JeL0 's example but the accessories just failed to pair at this point.

i’ve even flashed the HA pi image and run it as standalone. that WORKED, but if i unplug the ZBT-2 and plug it back in. all the matter devices are just unavailable. that kind of defeats the purpose of the border-router. which at that point even a reboot of the pi still shows unavailable…

but back to ha/otbr/matter-server as docker containers since this is what i am aiming for.

these are the 3 services in my docker-compose.yml… FYI. they dont seem to work so dont copy them. :stuck_out_tongue:
br0 is actually my network (i bridge it to eth0 and wlan1) while my wlan0 is actually talking to the outside world.

my firewall status -

net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra_rt_info_max_plen = 64
net.ipv6.conf.all.accept_ra = 2
net.ipv6.conf.br0.forwarding = 1
net.ipv6.conf.br0.accept_ra = 2
net.ipv6.conf.br0.accept_ra_rt_info_max_plen = 64

docker-compose.yml -
i am sure we all have many other services running. so i dont know if that might be causing some issue…

  home-assistant:
    container_name: home-assistant
    image: ghcr.io/home-assistant/home-assistant:stable
    network_mode: host
    privileged: true
    restart: unless-stopped
    volumes:
      - './home-assistant/config:/config'

  matter-server:
    container_name: matter-server
    image: ghcr.io/matter-js/python-matter-server:stable
    command: >
      --primary-interface br0
    network_mode: host
    privileged: true
    restart: unless-stopped
    security_opt:
      - apparmor:unconfined
    volumes:
      - './matter-server/data:/data'

  otbr:
    container_name: otbr
    image: ghcr.io/ownbee/hass-otbr-docker:latest
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN
    devices:
      - /dev/serial/by-id/usb-Nabu_Casa_ZBT-2_9C139EAC8D34-if00:/dev/ttyACM0
      - /dev/net/tun:/dev/net/tun
    environment:
      DEVICE: '/dev/ttyACM0'
      BACKBONE_IF: br0
      FLOW_CONTROL: 1
      FIREWALL: 1
      NAT64: 1
      BAUDRATE: 460800
      OTBR_REST_PORT: 8081
      OTBR_WEB_PORT: 8080
      AUTOFLASH_FIRMWARE: 0
    network_mode: host
    privileged: true
    restart: unless-stopped
    volumes:
      - './otbr/var-lib-thread:/var/lib/thread'

Thanks @vogon1 for this post, it really saved me a lot of time!

My setup is a bit different than yours so had some issues with some smaller things that I wanted to share with anyone who might have the same issues.

Main issues:

  1. HA would not connect to the OTBR rest endpoint.
  2. OTBR web UI would not start.

The setup I have is that I run HA on a separate VM than the matter and thread stack. I run everything on the same physical computer in a proxmox environment, but on separate VM’s. Because of this I had some issues connecting HA to the OTBR. And the reason for this was that by default the ORBR rest server only listens to 127.0.0.1 and not the other network addresses. To solve this I had to set the correct environment variable, somthing that was not documented anywhere. But here it is:

OT_REST_LISTEN_ADDR: "0.0.0.0"

Then I got HA connected to the OTBR rest endpoint.

Second issue I had was the web UI did not start, took me a bit to find out why but the default port is uses was used by something else, so had to change that port as well:

OT_WEB_LISTEN_PORT: "8085"

Here is a complete working compose file I use:

services:

  matter-server:
    image: ghcr.io/matter-js/python-matter-server:stable
    container_name: matter-server
    depends_on:
      - otbr
    network_mode: host
    security_opt:
      - apparmor:unconfined
    volumes:
      - ~/services/matter-server/data:/data
    restart: unless-stopped

  otbr:
    container_name: otbr
    image: openthread/border-router:latest
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/serial/by-id/usb-Nabu_Casa_ZBT-2_DCB4D90F8DA8-if00:/dev/ttyACM0
      - /dev/net/tun:/dev/net/tun
    environment:
      OT_RCP_DEVICE: spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800
      OT_INFRA_IF: ens18
      OT_THREAD_IF: wpan0
      OT_LOG_LEVEL: 7
      OT_REST_LISTEN_ADDR: "0.0.0.0"
      OT_REST_LISTEN_PORT: "8081"
      OT_WEB_LISTEN_ADDR: "0.0.0.0"
      OT_WEB_LISTEN_PORT: "8085"
    network_mode: host
    restart: unless-stopped
    volumes:
      - ~/services/otbr/data:/data

Lastly I wanted to ask if someone has tried out the new matter.js based container? The container for matter used in this thread has moved to maintenance mode when reading here:

Package python-matter-server ¡ GitHub

I know HA is working on, and have now also relesed a beta, to move over to the matter.js library. So wanted to go for that right away using this image, which seems to be what HA is going to use going forward:

GitHub - matter-js/matterjs-server: Matter server based on Matter.js

Any experiences or thoughts?

Ah, the web UI has been added in this image. When I started on this project, the web UI was not included. I will adjust the start of this thread with this information.

I would love to try it - however looking at the issues on the github page makes me reluctant to start using it right now. I will wait until it is a bit more stable.

Sietse

hey all. here is my check-in. i finally got it working again after weeks of battling.

my docker compose setup -

  • the network_mode and privileged for each containers seems important
  • i went back to openthread/border-router:latest because it worked for me when i first got the ZBT-2.
  • obtr, set it to listen on 0.0.0.0 OT_REST_LISTEN_ADDR: 0.0.0.0 and default port 8081 (feel free to change)

on the host, you need avahi-daemon AND radvd. it wouldnt pair (failed to pair) if radvd is not installed/stopped. afterward. i suggest a reboot of the machine. it MIGHT update some iptables rules. not 100% sure since the following were updated after a reboot even though i dont save my firewall rules -

net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra_rt_info_max_plen = 64
net.ipv6.conf.all.accept_ra = 2
net.ipv6.conf.br0.forwarding = 1
net.ipv6.conf.br0.accept_ra = 2
net.ipv6.conf.br0.accept_ra_rt_info_max_plen = 64

when you pair your accessories. run this on the host. this will do a browse/scan. it also shows the list of matter devices.

──── avahi-browse -rt _matter._tcp; avahi-browse -rt _meshcop._udp; avahi-browse -a -t

avahi config -

──── cat /etc/avahi/avahi-daemon.conf
# MANAGED BY ANSIBLE
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
#
[server]
use-ipv4=yes
use-ipv6=yes
allow-interfaces=br0
deny-interfaces=docker0,veth*,br-*
ratelimit-interval-usec=1000000
ratelimit-burst=1000

[wide-area]
enable-wide-area=yes

[publish]
publish-addresses=yes
publish-hinfo=no
publish-workstation=no
publish-domain=yes

[reflector]

[rlimits]

radvd.conf (chatgpt gave me this. i dont know what the ipv6 mean) -

──── cat /etc/radvd.conf
# MANAGED BY ANSIBLE
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
#
interface br0
{
    AdvSendAdvert on;
    MinRtrAdvInterval 3;
    MaxRtrAdvInterval 10;

    prefix fd15:9ef4:1f7f:9c18::/64
    {
        AdvOnLink on;
        AdvAutonomous on;
        AdvRouterAddr on;
    };

    route fd15:9ef4:1f7f:9c18::/64
    {
    };
};

docker-compose -

  home-assistant:
    container_name: home-assistant
    image: ghcr.io/home-assistant/home-assistant:stable
    environment:
      TZ: America/Los_Angeles
    network_mode: host
    privileged: true
    restart: unless-stopped
    volumes:
      - './home-assistant/config:/config'
      - '/etc/localtime:/etc/localtime:ro'
      - '/run/dbus:/run/dbus:ro'

  matter-server:
    container_name: matter-server
    image: ghcr.io/matter-js/python-matter-server:stable
    network_mode: host
    restart: unless-stopped
    security_opt:
      - apparmor:unconfined
    volumes:
      - './matter-server/data:/data'
      - '/run/dbus:/run/dbus:ro'

  otbr:
    container_name: otbr
    image: openthread/border-router:latest
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/serial/by-id/usb-Nabu_Casa_ZBT-2_9C139EAC8D34-if00:/dev/ttyACM0
      - /dev/net/tun:/dev/net/tun
    environment:
      OT_RCP_DEVICE: spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=460800
      OT_INFRA_IF: br0
      OT_THREAD_IF: wpan0
      OT_LOG_LEVEL: 7
      OT_REST_LISTEN_ADDR: 0.0.0.0
      OT_REST_LISTEN_PORT: 8081
      OT_WEB_LISTEN_ADDR: 0.0.0.0
      OT_WEB_LISTEN_PORT: 8981
    network_mode: host
    privileged: true
    restart: unless-stopped
    volumes:
      - './otbr/data:/data'

this survived host reboot, container restart/stop/start. accessory delete, re-pairing …

@ha-apprentice What hardware / Operating System are you running on?
I will make a link to your post in the top message based on your hw/os.