A Zigbee2MQTT setup lets you use Zigbee sensors, bulbs and switches from many brands without their hubs or clouds, and exposes every device as simple MQTT topics. In this guide you will choose a coordinator, run Zigbee2MQTT in Docker, connect it to a broker, pair and rename devices, control them from the command line and watch their states on a dashboard. Everything is tested first against the free public test broker with a unique base topic.
How Zigbee2MQTT Fits Together
Zigbee2MQTT is a bridge. On one side it drives a Zigbee coordinator (a USB stick or network adapter) that forms your Zigbee mesh. On the other side it is an MQTT client that publishes each device's state as JSON and listens for commands. Anything that speaks MQTT, such as Home Assistant, Node-RED, a Python script or a phone app, can then use those devices.
[Zigbee devices] ~~radio~~ [Coordinator] --USB/TCP-- [Zigbee2MQTT] --MQTT-- [Broker] -- [Dashboards, automations]
The broker sits in the middle and is the only thing every consumer connects to. If you want a refresher on what an MQTT broker does, it is worth a quick read before you start.
Choosing a Coordinator
The coordinator determines which adapter setting you use. Popular, well-supported choices:
| Coordinator | Chip | adapter value |
Notes |
|---|---|---|---|
| Sonoff Zigbee 3.0 USB Dongle Plus (ZBDongle-P) | TI CC2652P | zstack |
Very widely used, flash recent Z-Stack firmware |
| Sonoff ZBDongle-E | Silicon Labs EFR32MG21 | ember |
Use current EmberZNet firmware |
| SMLIGHT SLZB-06 family | CC2652P or EFR32 | zstack or ember |
Ethernet/PoE, connect via tcp://IP:6638 |
| ConBee II / III | Dresden Elektronik | deconz |
Works, but TI and Silicon Labs adapters are more common |
Two practical tips make a big difference. Use a USB extension cable of about half a metre to move the stick away from USB 3 ports and SSDs, whose interference can severely degrade Zigbee range. And add a few mains-powered routers (smart plugs or bulbs) early, because battery devices do not route and a mesh with only end devices is fragile.
Installing Zigbee2MQTT with Docker
Find the stable path of your adapter, which does not change between reboots:
ls -l /dev/serial/by-id/
Create a folder with a docker-compose.yml:
services:
zigbee2mqtt:
container_name: zigbee2mqtt
image: ghcr.io/koenkk/zigbee2mqtt:latest
restart: unless-stopped
volumes:
- ./data:/app/data
- /run/udev:/run/udev:ro
ports:
- "8080:8080"
environment:
- TZ=Europe/Berlin
devices:
- /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_XXXX-if00-port0:/dev/ttyACM0
Replace the device path with the one from your system and set your time zone. For a long-running installation, pin the image to a specific release tag instead of latest, so updates happen when you choose.
The Zigbee2MQTT Setup Configuration
Create data/configuration.yaml before the first start. Choose a random segment for the base topic, because the public test broker is shared and readable by everyone:
homeassistant:
enabled: false
frontend:
enabled: true
port: 8080
mqtt:
base_topic: connectmq/demo/z7q4/z2m
server: mqtt://broker.connectmq.com:1883
client_id: z2m-z7q4-bridge
serial:
port: /dev/ttyACM0
adapter: zstack
availability:
enabled: true
advanced:
log_level: info
channel: 25
network_key: GENERATE
pan_id: GENERATE
ext_pan_id: GENERATE
Key points:
base_topicis the prefix for everything Zigbee2MQTT publishes. Here it has four levels, leaving room within the public broker's limit of 8 topic levels.client_idmust be unique and non-empty on the broker.channelcannot be changed later without re-pairing every device. Channels 15, 20 and 25 avoid the most common Wi-Fi overlap; check which Wi-Fi channels are busy near you.GENERATEmakes Zigbee2MQTT create a random network key and IDs on first start and write them back into the file. Back upconfiguration.yamlandcoordinator_backup.jsonfrom the data folder afterwards.availabilitypublishes{"state":"online"}orofflineper device, which is very useful on dashboards.
Start it and follow the log:
docker compose up -d
docker compose logs -f zigbee2mqtt
You should see the coordinator firmware version, then a line confirming the connection to the MQTT broker. If you start without a configuration file, recent versions open an onboarding page on port 8080 where you can enter the same values in a form.
Pairing and Naming Devices
Open the frontend at http://<host>:8080 and click Permit join (All), or enable joining over MQTT for up to 254 seconds:
mosquitto_pub -h broker.connectmq.com -p 1883 -i z2m-cli-z7q4 \
-t "connectmq/demo/z7q4/z2m/bridge/request/permit_join" -m '{"time": 254}'
Put the device into pairing mode (usually a long press on its button or a power cycle sequence for bulbs). It appears with an IEEE address like 0x00158d0001abcd12. Rename it to something meaningful right away, because the name becomes its topic:
mosquitto_pub -h broker.connectmq.com -p 1883 -i z2m-cli-z7q4 \
-t "connectmq/demo/z7q4/z2m/bridge/request/device/rename" \
-m '{"from": "0x00158d0001abcd12", "to": "living_room_lamp"}'
Stop joining with {"time": 0} when you are done. Leaving the network open invites neighbours' devices to join by accident.
Use underscores rather than slashes in friendly names while testing on the public broker. A name like living_room/lamp is allowed and creates nicer hierarchies, but each slash adds a topic level, and bridge/request/device/rename already uses all 8 levels with this base topic.
Reading and Controlling Devices over MQTT
Subscribe to everything under the base topic:
mosquitto_sub -h broker.connectmq.com -p 1883 -i z2m-watch-z7q4 -t "connectmq/demo/z7q4/z2m/#" -v
A temperature sensor publishes on connectmq/demo/z7q4/z2m/hallway_sensor:
{"battery": 97, "humidity": 48.2, "linkquality": 116, "temperature": 21.4, "voltage": 2995}
Control a bulb by publishing to its set topic:
mosquitto_pub -h broker.connectmq.com -p 1883 -i z2m-cli-z7q4 \
-t "connectmq/demo/z7q4/z2m/living_room_lamp/set" \
-m '{"state": "ON", "brightness": 180, "color_temp": 370, "transition": 2}'
To ask a device for its current state, publish {"state": ""} to its get topic. Device topics carry the full state, so a dashboard needs only one subscription per device.
From MQTT to a Dashboard
Because Zigbee2MQTT speaks plain MQTT, you have several dashboard options:
- The Zigbee2MQTT frontend for management: device list, network map, OTA updates and logs.
- Home Assistant via its MQTT integration. Set
homeassistant.enabled: trueand Zigbee2MQTT publishes discovery messages so entities appear automatically; the Home Assistant MQTT guide covers that side. - Node-RED Dashboard, subscribing to device topics with an
mqtt innode and a JSON node. - A browser dashboard using MQTT over WebSocket, connecting to
wss://broker.connectmq.com:8084/mqtt.
For quick checks without building anything, the ConnectMQ portal's live topic explorer shows every Zigbee2MQTT topic as it updates, which is handy while pairing and renaming.
Zigbee2MQTT Setup Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| "Failed to connect to the adapter" | Wrong adapter or device path |
Match the table above; use /dev/serial/by-id path |
| Devices drop off or pair poorly | USB 3 interference, no routers | Extension cable, add mains-powered routers |
| Connects to broker, then disconnects | Duplicate client ID | Unique client_id per bridge |
| Bridge messages rejected on the public broker | Large bridge/devices or bridge/definitions payloads on bigger networks |
Test with few devices, use a private broker for full networks |
| Rename has no effect | Topic depth over the public broker's 8 levels | Shorten base_topic or names |
The public test broker also limits each client to 10 messages per second, which a small test network stays well within but a large network at startup can exceed. That is one more reason the public area is for trials only; the free public MQTT broker article lists all its limits.
Moving to a Private Broker
Zigbee2MQTT controls locks, lights and alarms, so production needs credentials and TLS. With a managed MQTT broker such as ConnectMQ, you create a broker in the portal, copy the generated username, password and client ID, and change only the mqtt block:
mqtt:
base_topic: zigbee2mqtt
server: mqtts://broker.connectmq.com:8883
user: YOUR_USERNAME
password: YOUR_PASSWORD
client_id: YOUR_CLIENT_ID
version: 5
The Let's Encrypt certificate validates against the system CA bundle in the container, so no extra certificate files are needed. The free Serverless plan allows messages up to 256 KB, comfortable for typical bridge payloads, and paid plans raise that to 1 MB. The Zigbee2MQTT with a cloud broker guide goes deeper into remote access and multi-site setups, and the IoT automation guide shows where Zigbee fits in a larger home or building system.
Run Zigbee2MQTT on ConnectMQ
ConnectMQ gives your Zigbee2MQTT bridge a private MQTT broker with TLS, Secure WebSocket for browser dashboards and a portal to watch every device topic live. Create a free Serverless broker at app.connectmq.com, no credit card required, and point your mqtt.server at it.
Frequently Asked Questions
Which coordinator is best for a new Zigbee2MQTT setup?
A Texas Instruments CC2652P-based stick with the zstack adapter or a Silicon Labs EFR32MG21 stick with the ember adapter are the most common, well-supported choices. Network-attached adapters are useful when the server is far from the devices.
Can I change the Zigbee channel later?
Technically yes, but most devices must then be re-paired. Choose the channel carefully before pairing anything.
Does Zigbee2MQTT need Home Assistant?
No. Zigbee2MQTT only needs an MQTT broker. Home Assistant is one optional consumer among many, alongside Node-RED, scripts and dashboards.
Is it safe to run Zigbee2MQTT on a public broker?
Only for testing. Anyone can read and publish to public topics, including your set topics, so use a private broker with credentials and TLS for real devices.



