Home Assistant With Zigbee2MQTT and a Coordinator That Works
The dongle, the extension cable and the channel choice that decide everything

Contents
Almost every “my Zigbee network is unreliable” post traces back to one of four things: a bad coordinator, a coordinator plugged directly into the back of a machine, a channel sitting on top of your Wi-Fi, or a router device that lies about being a router. The software is rarely at fault. Zigbee2MQTT is mature, Home Assistant’s MQTT integration is boring in the best sense, and Mosquitto has been solved since about 2014.
I learned all four the slow way. My first Zigbee network had 22 devices and a sensor in the utility room that dropped off every few days, always the same one, always at no useful moment. I rebuilt the network three times before understanding that the problem was a USB 3 enclosure sitting 4cm from the dongle, radiating broadband noise across the entire 2.4GHz band.
This post is the setup I would give myself in 2019: what to buy, how to wire it, and the four failure modes, in the order they will bite you.
Why Zigbee2MQTT rather than ZHA
Home Assistant has a built-in Zigbee integration, ZHA, and it is good. It needs no broker, no second container, and it is configured entirely through the UI. For a small network of mainstream devices it is the right answer and I would not talk anyone out of it.
Zigbee2MQTT earns the extra moving parts on three counts. Its device support is broader and faster — Koenkk’s converter library covers thousands of devices and new ones land within days rather than months, which matters the moment you buy something from a Chinese vendor with a name like a keyboard mash. Its debugging surface is real: the log tells you what the radio did, the frontend draws a live network map with link quality on every edge, and you can subscribe to the raw MQTT and watch the traffic. And it decouples your Zigbee network from Home Assistant entirely — Z2M keeps working while HA restarts, upgrades or dies, and if you ever migrate away from Home Assistant your devices are already publishing to a broker that anything can read.
The cost is a broker and a container. I went through the trade in more detail in Zigbee2MQTT vs ZHA: Home Assistant Zigbee Integrations Compared; the short version is that ZHA is fine until it is not, and the migration is a full re-pair of every device, so the choice is worth making deliberately once.
The coordinator: what to buy
The coordinator is the radio. It is a £20 decision that determines whether the next three years are pleasant, and it is the single most common thing people get wrong.
Texas Instruments CC2652P is the safe answer. The Sonoff ZBDongle-P is the common one; it has an amplifier, it runs Koenkk’s Z-Stack firmware, and Z2M’s zstack driver is the most mature code in the project. If you want to stop reading now, buy this one.
Silicon Labs EFR32MG21 turns up in the Sonoff ZBDongle-E, the Home Assistant ZBT-1, and various others. Its history with Z2M was rough for years. The ember driver, which arrived in Z2M 1.36 in early 2024 and replaced the old ezsp implementation, made it genuinely usable. It works now. It is still the newer, less-travelled path.
SLZB-06 from SMLIGHT is the one I actually run. It is a CC2652P on a small board with Ethernet and PoE, so the radio goes wherever the network goes — in my case, high up and central, well away from anything electrical. The coordinator’s position determines the mesh’s shape, and being able to put it in the right place instead of next to a server is worth more than any firmware.
ConBee II works fine via deCONZ and is fading from relevance.
What to avoid: anything without a documented Z2M driver, and anything advertised as a “Zigbee hub” for a specific vendor’s ecosystem. You want a bare radio.
Wire it correctly, which means a cable
Here is the four-cent fix for the problem that will cost you a month.
USB 3 ports, USB 3 cables, and especially external SSD enclosures emit broadband interference centred right where 2.4GHz lives. Intel published a paper on this in 2012 and everyone has been rediscovering it since. Plug a Zigbee dongle into the USB port next to your NVMe enclosure and you will have a network that works beautifully at first and degrades as you add devices at range.
So:
- Put the dongle on a 1m USB 2.0 extension cable. Not USB 3, and not a hub. This costs almost nothing and fixes more Zigbee problems than any other single action.
- Use a USB 2.0 port on the host if you have one.
- Keep it away from Wi-Fi access points, USB enclosures, unshielded power supplies and large sheets of metal.
If you are going the network-attached route instead — SLZB-06 or an ESP32 running a serial bridge — none of this applies, which is a substantial part of why I moved to it.
Then find the device path, and use the stable one:
| |
Never put /dev/ttyUSB0 in your config. That name is assigned in enumeration order and the day you plug in a second serial device it becomes ttyUSB1, your coordinator vanishes, and the resulting panic is entirely avoidable.
The stack
Mosquitto and Zigbee2MQTT, two containers:
| |
Mosquitto needs a config file, because version 2.0 stopped listening on anything by default and stopped allowing anonymous clients — a change that broke a great many tutorials and improved the world:
| |
| |
Then Z2M’s own configuration. This file is the important one:
| |
Several of those lines are load-bearing.
The channel, and why 11 is a trap
Z2M’s default Zigbee channel is 11. Zigbee channel 11 sits directly under Wi-Fi channel 1, which is one of the three non-overlapping 2.4GHz Wi-Fi channels and therefore one of the busiest slices of spectrum in any building with neighbours.
Zigbee transmits at a few milliwatts. Your access point transmits at a hundred times that. In a straight collision, Zigbee loses, and the symptom is exactly the one everyone reports: it works, mostly, except for the far devices, except sometimes, worse in the evening when the neighbours start streaming.
The channels that fit in the gaps between Wi-Fi 1, 6 and 11 are 15, 20 and 25. Channel 25 sits above Wi-Fi 11 and is usually the quietest of the three, which is why it is in the config above. Check what is actually around you before choosing — a Wi-Fi scan on a phone gives you the local picture in thirty seconds, and if a neighbour is squatting on Wi-Fi 11, use 15 instead.
Do this before you pair anything. Changing the Zigbee channel after the fact requires re-pairing every battery-powered device, one at a time, on a stepladder. Mains-powered routers usually follow the coordinator; sensors mostly do not. Ask me how I know.
The other three values matter for a different reason. pan_id, ext_pan_id and network_key define your network’s identity. Set them explicitly and keep them backed up, and a dead coordinator can be replaced with a new one carrying the same identity — every device rejoins without you touching a single one. Leave them on GENERATE and lose the file, and you re-pair 40 devices by hand. The key is a secret; the !secret.yaml syntax keeps it out of the file you might paste into a forum.
Home Assistant, which is the easy part
homeassistant: true turns on MQTT discovery. Z2M publishes a config topic per device, Home Assistant’s MQTT integration reads it, and entities appear with correct device classes, units and names. There is no per-device configuration in Home Assistant at all.
Add the MQTT integration in HA, point it at the broker with the same credentials, and watch:
| |
That is the entire integration surface, and it is why the decoupling argument holds: those are plain JSON messages on a topic, readable by Node-RED, a shell script, or whatever replaces Home Assistant in 2032.
Rename devices in Z2M’s frontend before they reach HA. The friendly name becomes the entity ID, and fixing 0x00158d0004a1b2c3 into something meaningful after forty automations reference it is a chore.
The mesh: routers, and the ones that lie
Zigbee is a mesh. Mains-powered devices — smart plugs, bulbs, relays — act as routers, forwarding traffic for battery devices, which never route because their radios sleep. A network of nothing but battery sensors is a star, and a star has the range of one radio.
So: coordinator central and high, then enough mains-powered devices spread through the house that no sensor is more than a room or two from one. Three or four cheap plugs in the right places will do more for reliability than any dongle upgrade.
The complication is that some routers are bad at it. This is a genuine, well-documented, decade-old problem. Certain older Xiaomi and Aqara devices interpret the spec creatively and can drop their children. A number of cheap Tuya plugs have small routing tables and silently stop forwarding under load. The symptom is a sensor that works when it joins and disappears a week later, having attached itself to a router that cannot cope.
Read the map. Z2M’s frontend draws it, and the API gives you the same data:
| |
Link quality below about 30 is a link that will fail. Anything consistently under that needs a router nearer to it, or a router that is less of a liar.
Troubleshooting, in the order it happens
Z2M starts and exits with an adapter error. The device path, the permissions, or the driver. Confirm the container can see it:
| |
If it is a permissions problem, the container user needs to be in the host’s dialout group. If the adapter is an EFR32MG21, confirm adapter: ember is set — the wrong driver produces an error that looks like hardware failure.
Devices pair and then never report. Almost always range or a bad router. Re-pair the device physically close to the coordinator, confirm it works, then move it. If it dies on the move, the path home is the problem.
Everything drops at once, periodically. Interference. This is the USB 3 case, or an access point that hops channels, or a microwave. last_seen: ISO_8601 in the config gives you timestamps to correlate against — if the outages line up with someone reheating soup, you have your answer, and the fix is the extension cable.
A device joins but shows as “unsupported”. No converter exists for it yet. Z2M supports external converters, and Koenkk’s project usually absorbs new devices quickly if you open an issue with the fingerprint. This is the tax on buying obscure hardware, and it is much lower than the equivalent tax on ZHA.
Home Assistant shows entities as unavailable while Z2M is happy. The availability feature is doing its job or lying. active.timeout pings mains devices every 10 minutes; a device that is slow to answer gets marked unavailable. Battery devices use the passive timeout and report on their own schedule, which for a door sensor might be hours. Raising passive.timeout fixes a lot of phantom unavailability.
OTA updates brick a device. Z2M can push firmware updates from vendors’ servers. They are usually fine. When they are not, the device is a paperweight. Update one device at a time, never the whole estate, and never a device you cannot physically reach.
Backups
Z2M’s entire state is /srv/appdata/zigbee2mqtt/data: configuration.yaml, database.db (the device list), coordinator_backup.json (the network identity), and the secrets file. It is a few hundred kilobytes and it is the difference between replacing a dead dongle in ten minutes and re-pairing your house.
| |
Ten seconds of downtime, once a night, from cron. Home Assistant’s own backup covers the automations and dashboards, and I have made the case for taking that seriously in Backing Up Home Assistant So a Dead SD Card Isn’t Fatal — the two backups are separate and you need both.
The verdict
Zigbee2MQTT plus Mosquitto is two containers and about 250MB of RAM to run a radio protocol that a £30 vendor hub also runs. The hub is easier. The hub also phones home, stops working when the vendor’s cloud has a bad day, and supports only the devices its manufacturer sells.
Fifty-one devices in, my network has had one unplanned outage in two years, and that was me unplugging the wrong thing. It handles motion sensors that fire in under 200ms, and it does it with no internet connection whatsoever, which is the entire point of choosing Zigbee over Wi-Fi devices in the first place — an argument I set out in Zigbee vs Z-Wave vs Matter: Choosing a Radio You Won’t Regret.
Run this if you have more than about fifteen Zigbee devices, or any device from a vendor Home Assistant has never heard of, or a desire to understand why your mesh behaves the way it does. The network map alone justifies it.
Run ZHA if you have eight bulbs and a motion sensor and no interest in any of the above. It will work, it needs no broker, and there is no prize for complexity.
Either way: buy the extension cable, change the channel to 25 before you pair anything, and back up coordinator_backup.json. Those three things are 90% of the reliability, and none of them are software.




