Short answer: Zigbee doesn’t speak MQTT. You need a translator, and that’s Zigbee2MQTT. It reads what your Zigbee devices transmit through a USB stick (the coordinator) and publishes it as MQTT messages to a broker — usually Mosquitto. The other way round, any MQTT message to the right topic sends a command back to the device.
So you need three things:
- A Zigbee coordinator — a USB stick such as the SONOFF ZBDongle-E or the Home Assistant Connect ZBT-1.
- An MQTT broker — Mosquitto, as a Home Assistant add-on or in Docker.
- Zigbee2MQTT — the bridge between the two.
Below are both ways to set it up, and how to see that it works.
What MQTT actually does
MQTT is a messaging system. A broker receives messages on topics and passes them on to everyone subscribed to that topic. Zigbee2MQTT publishes, for example:
zigbee2mqtt/Living room sensor {"temperature":21.4,"humidity":48,"battery":92}
And listens on zigbee2mqtt/<device>/set for commands:
zigbee2mqtt/Kitchen light/set {"state":"ON","brightness":180}
The nice thing: anything that speaks MQTT can read and control your Zigbee devices — Home Assistant, Node-RED, your own script, a dashboard. You’re not tied to one platform or brand.
Route 1: with Home Assistant (the easiest)
On Home Assistant OS, it’s two add-ons.
- Install Mosquitto. Settings → Add-ons → Add-on store → Mosquitto broker → install and start, with Start on boot on. Home Assistant then finds the broker itself under Devices & services; confirm the MQTT integration.
- A user for Zigbee2MQTT. Settings → People → Users → new user, say
zigbee, with its own password. Mosquitto accepts Home Assistant users as MQTT logins. - Install Zigbee2MQTT. Add the repository
https://github.com/zigbee2mqtt/hassio-zigbee2mqttin the Add-on store and install Zigbee2MQTT. - Point it at the stick. In the add-on’s configuration, set the serial path to your stick. Use the path starting with
/dev/serial/by-id/— not/dev/ttyUSB0, which can change number after a reboot. - Start it. The log shows the coordinator being recognised and the MQTT connection up. Devices appear in Home Assistant by themselves as you pair them.
Our full walkthrough, including choosing the stick and building out the network, is in the Zigbee2MQTT guide.
Route 2: without Home Assistant, with Docker
To use MQTT without Home Assistant — for Node-RED, your own dashboard or another platform — run the broker and Zigbee2MQTT yourself, for example on a Raspberry Pi.
docker-compose.yml:
services:
mosquitto:
image: eclipse-mosquitto:2
restart: unless-stopped
ports:
- "1883:1883"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
zigbee2mqtt:
image: ghcr.io/koenkk/zigbee2mqtt
restart: unless-stopped
depends_on:
- mosquitto
ports:
- "8080:8080"
environment:
- TZ=Europe/Amsterdam
volumes:
- ./zigbee2mqtt/data:/app/data
- /run/udev:/run/udev:ro
devices:
- /dev/serial/by-id/usb-YOUR-STICK-if00:/dev/ttyACM0
mosquitto/config/mosquitto.conf — without this file Mosquitto 2 only accepts connections from its own machine, and a container doesn’t count as its own machine:
listener 1883
allow_anonymous false
password_file /mosquitto/config/passwd
persistence true
persistence_location /mosquitto/data/
Create a user with docker compose run --rm mosquitto mosquitto_passwd -c /mosquitto/config/passwd zigbee.
zigbee2mqtt/data/configuration.yaml:
mqtt:
base_topic: zigbee2mqtt
server: mqtt://mosquitto:1883
user: zigbee
password: your-password
serial:
port: /dev/ttyACM0
adapter: ember # SONOFF ZBDongle-E and ZBT-1; 'zstack' for the ZBDongle-P
frontend:
enabled: true
port: 8080
advanced:
channel: 20
Start everything with docker compose up -d. Zigbee2MQTT’s web interface is then on port 8080.
Checking it works
Subscribe to everything under zigbee2mqtt/ with the MQTT client that ships with Mosquitto:
mosquitto_sub -h localhost -u zigbee -P your-password -t 'zigbee2mqtt/#' -v
The first thing you should see is:
zigbee2mqtt/bridge/state {"state":"online"}
Turn on Permit join in the web interface (with a time limit), put a device in pairing mode, and within a minute its messages appear. Then try a command:
mosquitto_pub -h localhost -u zigbee -P your-password -t 'zigbee2mqtt/Kitchen light/set' -m '{"state":"TOGGLE"}'
If the light turns on, your Zigbee is connected to MQTT.
If it doesn’t work
- “Connection refused” to the broker. With Docker: is the
listener 1883line missing frommosquitto.conf? Are you usingmqtt://mosquitto:1883(the service name) in Zigbee2MQTT, notlocalhost? - “Not authorized”. Wrong user or password, or the
passwdfile was never created. - The stick isn’t found. Wrong serial path, or the wrong
adapter. A ZBDongle-E isember, a ZBDongle-P iszstack— instructions online are often for the other one. - Devices keep dropping off. Almost never MQTT, almost always the radio: the stick is right next to a USB 3.0 port or the router, or your Zigbee channel sits under your Wi-Fi. Put the stick on a USB 2.0 extension cable and pick a channel with our Zigbee channel planner — it also tells you which Wi-Fi channel to move your router to if your Zigbee is already running and you don’t want to re-pair everything.
Does it have to go through MQTT?
No. Home Assistant also has ZHA, a built-in Zigbee integration without a broker. It’s quicker to set up. Zigbee2MQTT supports more devices, gives more settings per device, and makes your Zigbee network usable by anything that speaks MQTT — not only Home Assistant. If you might later connect Node-RED, your own dashboard or a second system, go with MQTT.
Rather have it set up right in one go, with a network that covers the whole house? That’s our smart home installation.