App submission zigbee2mqtt
App Submission
App name
Zigbee2MQTT
256x256 SVG icon
https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/refs/heads/master/images/logo_vector.svg
Gallery images
I have tested my app on:
- [ ] umbrelOS on a Raspberry Pi
- [x] umbrelOS on an Umbrel Home
- [ ] umbrelOS on Linux VM
Actually I'm using a network connected dongle. But I think, you're right, you'll need a device mount to use a local dongle. In that case, I think there may be different ways to use different dongles. Maybe we should react to PRs made by people using local dongles as they may provide the necessary mount points?!
Lets see what @nmfretz and @sharknoon have to say about this topic. I sadly don't have a dongle right now, thinking of getting one.
As far as I used local dongles, it's a mixed bag, because depending on what chipset is used to implement the serial connection, the dongle is mounted as a different device. I solved that by udev rules, but that depended on the serial of the Bridge-Chip. That's one reason I opted in for a network based dongle. We may map some well known devices into the z2m container, but iteration (more than one usb-to-serial device connected) depends on detection while initializing usb-sub-system. So at least a boot or update of the system may mix that up. As mentioned: fixed that by using udev rules. In my opinion that may not be an elegant solution. So we may state we're just supporting network based dongles or used has to take care of udev rules and we map some default device into the container.
Hey @dirstel, discussed with the team. We will probably go ahead with only having the network adapters for now, but still checking some possibilities.
That sounds good to me. Otherwise we can map the default devices (as seen on the onboarding page if z2m) 1:1 into the container. In many cases this should work. Especially when connecting just one or two devices to the machine. In advanced setups this may fail because of the mounting sequence which may change when adding another device or boot. If that is the way, I can make the changes but it will take some time as I am traveling right now.
Maybe a solution can be mapping the path /dev/serial/by-id/ may be a solution? Investigating in the device discovery of z2m https://github.com/Koenkk/zigbee-herdsman/blob/master/src/adapter/adapterDiscovery.ts showed, this is the path scanned for nearly all devices. Anyhow, testing may be an issue, as I do not own a local accessible dongle anymore.
Lets test some stuff out, will get a dongle in the next few days.
@dirstel how did you get this to run on your device? I get the following error when starting the app:
zigbee2mqtt_app_1 | Using '/app/data' as data directory
zigbee2mqtt_app_1 | Starting Zigbee2MQTT without watchdog.
zigbee2mqtt_app_1 | [2025-04-18 09:01:24] info: z2m: Logging to console, file (filename: log.log)
zigbee2mqtt_app_1 | [2025-04-18 09:01:24] info: z2m: Starting Zigbee2MQTT version 2.2.1 (commit #a14feef8c13f5ce49b0ac358d98d3234d21d7ff4
zigbee2mqtt_app_1 | )
zigbee2mqtt_app_1 | [2025-04-18 09:01:24] info: z2m: Starting zigbee-herdsman (3.4.11)
zigbee2mqtt_app_1 | [2025-04-18 09:01:25] error: z2m: Error while starting zigbee-herdsman
zigbee2mqtt_app_1 | [2025-04-18 09:01:25] error: z2m: Failed to start zigbee-herdsman
zigbee2mqtt_app_1 | [2025-04-18 09:01:25] error: z2m: Check https://www.zigbee2mqtt.io/guide/installation/20_zigbee2mqtt-fails-to-start_crashes-runtime.html for possible solutions
zigbee2mqtt_app_1 | [2025-04-18 09:01:25] error: z2m: Exiting...
zigbee2mqtt_app_1 | [2025-04-18 09:01:25] error: z2m: Error: USB adapter discovery error (No valid USB adapter found). Specify valid 'adapter' and 'port' in your configuration.
zigbee2mqtt_app_1 | at discoverAdapter (/app/node_modules/.pnpm/[email protected]/node_modules/zigbee-herdsman/src/adapter/adapterDiscovery.ts:575:15)
zigbee2mqtt_app_1 | at processTicksAndRejections (node:internal/process/task_queues:105:5)
zigbee2mqtt_app_1 | at Function.create (/app/node_modules/.pnpm/[email protected]/node_modules/zigbee-herdsman/src/adapter/adapter.ts:53:33)
zigbee2mqtt_app_1 | at Controller.start (/app/node_modules/.pnpm/[email protected]/node_modules/zigbee-herdsman/src/controller/controller.ts:132:24)
zigbee2mqtt_app_1 | at Zigbee.start (/app/lib/zigbee.ts:69:27)
zigbee2mqtt_app_1 | at Controller.start (/app/lib/controller.ts:104:13)
zigbee2mqtt_app_1 | at start (/app/index.js:149:5)
zigbee2mqtt_app_1 | [2025-04-18 09:01:25] error: z2m: If this happens after updating to Zigbee2MQTT 2.0.0, see https://github.com/Koenkk/zigbee2mqtt/discussions/24364
@al-lac: Sorry for the late reply - wasn't at home some days... What I did:
- clean install (no migration), got the onboarding-page of z2m
Using '/app/data' as data directory
Starting Zigbee2MQTT without watchdog.
Onboarding page is available at http://0.0.0.0:8080/
2a) configured my (network-)adapter and everything is fine:
[2025-04-22 07:47:29] info: z2m: Logging to console, file (filename: log.log)
[2025-04-22 07:47:29] info: z2m: Starting Zigbee2MQTT version 2.2.1 (commit #a14feef8c13f5ce49b0ac358d98d3234d21d7ff4
)
[2025-04-22 07:47:29] info: z2m: Starting zigbee-herdsman (3.4.11)
[2025-04-22 07:47:29] info: zh:ember: Using default stack config.
[2025-04-22 07:47:29] info: zh:ember: ======== Ember Adapter Starting ========
[2025-04-22 07:47:29] info: zh:ember:ezsp: ======== EZSP starting ========
[2025-04-22 07:47:29] info: zh:ember:uart:ash: ======== ASH Adapter reset ========
[2025-04-22 07:47:29] info: zh:ember:uart:ash: Socket ready
[2025-04-22 07:47:29] info: zh:ember:uart:ash: ======== ASH starting ========
[2025-04-22 07:47:31] info: zh:ember:uart:ash: ======== ASH connected ========
[2025-04-22 07:47:31] info: zh:ember:uart:ash: ======== ASH started ========
[2025-04-22 07:47:31] info: zh:ember:ezsp: ======== EZSP started ========
[2025-04-22 07:47:31] info: zh:ember: Adapter EZSP protocol version (13) lower than Host. Switched.
[2025-04-22 07:47:31] info: zh:ember: Adapter version info: {"ezsp":13,"revision":"7.4.1 [GA]","build":0,"major":7,"minor":4,"patc>
[2025-04-22 07:47:32] info: zh:ember: [STACK STATUS] Network up.
[2025-04-22 07:47:32] info: zh:ember: [INIT TC] Adapter network does not match config. Leaving network...
[2025-04-22 07:47:33] info: zh:ember: [STACK STATUS] Network down.
[2025-04-22 07:47:33] info: zh:ember: [INIT TC] No valid backup found.
[2025-04-22 07:47:33] info: zh:ember: [INIT TC] Forming from config.
[2025-04-22 07:47:33] info: zh:ember: [INIT FORM] Forming new network with: {"panId":32529,"extendedPanId":[59,255,6,97,150,29,208>
[2025-04-22 07:47:33] info: zh:ember: [STACK STATUS] Network up.
[2025-04-22 07:47:33] info: zh:ember: [INIT FORM] New network formed!
[2025-04-22 07:47:33] info: zh:ember: [CONCENTRATOR] Started source route discovery. 1246ms until next broadcast.
[2025-04-22 07:47:33] info: zh:controller: Wrote coordinator backup to '/app/data/coordinator_backup.json'
[2025-04-22 07:47:33] info: z2m: zigbee-herdsman started (reset)
[2025-04-22 07:47:33] info: z2m: Coordinator firmware version: '{"meta":{"build":0,"ezsp":13,"major":7,"minor":4,"patch":1,"revisi>
[2025-04-22 07:47:33] info: z2m: Currently 0 devices are joined.
[2025-04-22 07:47:33] info: z2m: Connecting to MQTT server at mqtt://192.168.101.22:1883
[2025-04-22 07:47:33] info: z2m: Connected to MQTT server
[2025-04-22 07:47:33] info: z2m:mqtt: MQTT publish: topic 'zigbee2mqtt/bridge/state', payload '{"state":"online"}'
[2025-04-22 07:47:33] info: z2m: Started frontend on port 8080
[2025-04-22 07:47:33] info: z2m: Zigbee2MQTT started!
2b) Instead of using the onboarding-page, I stopped the containers, pushed my existing conf into the data directory and restarted the containers => all fine including migration from 1.4.2
Hey @dirstel,
thanks for looking at it again!
I figured that it did not work for me because I did not provide a valid config.
From a usability point of view the whole onboarding process is not optimal as it is only shown once. If the users forgets about it and restarts their device in the meantime, they would need to reinstall the app or change the config file directly.
Lets align with @nmfretz on what he thinks would be the right way to tackle this.
I think we would need to adapt the description and maybe the screenshots a bit to inform users better. But maybe that is not really enough.
@al-lac: There has been some discussion about re-enableing the onboarding in the z2m repo: https://github.com/Koenkk/zigbee2mqtt/pull/26608 There are several env-settings allowing to take control of onboarding.
Yeah in the documentation here it also says that the on-boarding page should be shown again on a configuration error, this does not happen for me however.
If Zigbee2MQTT fails to start after submitting the initial configuration (due to something like a wrong adapter path), the onboarding will be executed again on the following start.
And yeah, we could for example set these things as a default:
environment:
ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED: "true"
ZIGBEE2MQTT_CONFIG_FRONTEND_PORT: 8080
Z2M_ONBOARD_NO_REDIRECT: 1
And yeah, we could for example set these things as a default:
environment: ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED: "true" ZIGBEE2MQTT_CONFIG_FRONTEND_PORT: 8080 Z2M_ONBOARD_NO_REDIRECT: 1
@al-lac: Integrated your proposed changes. My setup is still functional, but I can't test with local attached dongle. Please try with local dongle and we should be happy :) (except for the upcoming monthly update of z2m - but that's a different story)
Hey @dirstel,
thanks for integrating the changes.
My main issue with the app currently is that if you do not configure it before a restart, the config is just broken and nothing starts until the user deletes the config from the data directory.
To get around this I added a hook that checks if the config is valid, if not, it backups the bad config and deletes it so that the on-boarding is shown again.
I also managed to get it running with my usb dongle, that of course means running the container with more privileges.
What are you using for the mqtt server? mosquitto? Because from my point of view we could set this as a dependency and already pre-fill the values for it.
My main issue with the app currently is that if you do not configure it before a restart, the config is just broken and nothing starts until the user deletes the config from the data directory. To get around this I added a hook that checks if the config is valid, if not, it backups the bad config and deletes it so that the on-boarding is shown again.
Only drawback from this seems to be the missing user-feedback in case of wrong config - at least better than a hanging app which needs to be reinstalled. Please share your script and I'll integrate it.
I also managed to get it running with my usb dongle, that of course means running the container with more privileges.
Maybe we should map your device (and others to come) into the container?
What are you using for the mqtt server? mosquitto? Because from my point of view we could set this as a dependency and already pre-fill the values for it.
Yes, I'm using Mosquitto. Preconfiguration may be ok, but dependency means, it doesn't work without mosquitto installed - right? That would prevent using different mqtt-brokers (so far only mosquitto is available in umbrel-store) and mqtt-brokers hosted on different hardware/cloud. So I would not recommend this. Maybe some hints in the description will be helpful instead of forcing to use one single mqtt-broker.
Yeah from what I understood it should actually show the on-boarding automatically in case the config is not working, not sure why it does not work here.
This would be the script, if you add it, make sure it is executable and to bump the manifestVersion in the umbrel-app.yml to 1.1
#!/usr/bin/env bash
set -euo pipefail
APP_DATA_DIR="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")"
CONFIG_FILE="${APP_DATA_DIR}/data/configuration.yaml"
echo "Pre-start hook: Checking Zigbee2MQTT configuration..."
# Function to log an error and delete the config file
backup_and_delete() {
local reason="$1"
echo "ERROR: $reason"
echo "Backing up and removing problematic configuration file..."
cp "$CONFIG_FILE" "${CONFIG_FILE}.${reason// /-}.$(date +%s).bak"
rm "$CONFIG_FILE"
echo "Configuration file deleted. Zigbee2MQTT will start in onboarding mode."
}
# Check if configuration file exists
if [[ -f "$CONFIG_FILE" ]]; then
echo "Configuration file found at $CONFIG_FILE"
# Check for completely empty file
if [[ ! -s "$CONFIG_FILE" ]]; then
backup_and_delete "Empty configuration file"
# Check for serial section followed by empty curly braces on same line
elif grep -q "^serial: *{} *$" "$CONFIG_FILE"; then
backup_and_delete "Empty serial section"
# Check if serial section exists
elif ! grep -q "^serial:" "$CONFIG_FILE"; then
backup_and_delete "Missing serial section"
# Check if port is defined anywhere
elif ! grep -q "^ *port:" "$CONFIG_FILE"; then
backup_and_delete "Missing port configuration"
# Everything looks good
else
echo "Configuration contains required elements and appears valid"
fi
else
echo "No configuration file found. Zigbee2MQTT will start in onboarding mode."
fi
echo "Pre-start: Zigbee2MQTT hook completed"
And this would be the docker-compose.yml that also works with USB dongles (and preconfigured mosquitto):
services:
app_proxy:
environment:
APP_HOST: zigbee2mqtt_app_1
APP_PORT: 8080
app:
image: koenkk/zigbee2mqtt:2.2.1@sha256:5c1f0ca9669292b1bdabc7b6d9927642049bc2c1ee53f42b7299181e93dd7d8f
restart: on-failure
volumes:
- ${APP_DATA_DIR}/data:/app/data:rw
- /run/udev:/run/udev:ro
privileged: true
environment:
ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED: "true"
ZIGBEE2MQTT_CONFIG_FRONTEND_PORT: 8080
ZIGBEE2MQTT_CONFIG_MQTT_SERVER: "mqtt://mosquitto_broker_1:1883"
Z2M_ONBOARD_NO_REDIRECT: 1
I have the opposite issue of you though, I have he dongle now, but no devices to connect to.
This is how it shows up during the on-boarding:
Lets see what @nmfretz and @sharknoon have to say about all of this.
Skiping through your script reveals 4 checks implemented there:
- Empty configuration file
- Empty serial section
- Missing serial section
- Missing port configuration
in https://github.com/Nerivec/zigbee2mqtt/blob/a690c6fbdc65828548a145f9268037dbd2a70630/lib/util/onboarding.ts#L559 from line 559 on, a check of the given config is applied and thus should lead to an error raised by z2m.
in https://github.com/Nerivec/zigbee2mqtt/blob/a690c6fbdc65828548a145f9268037dbd2a70630/lib/util/settings.ts#L236 the validation function doesn't seem to check the serial-section though.
This should indeed be checked by z2m itself. Did you consider to open an issue on https://github.com/Koenkk/zigbee2mqtt/issues ? Maybe you should provide a corrupt configuration.yaml generated by onboarding there to to fix that checking part in the project itself.
Yeah not sure how the onboarding would start again after an error is given. I found a similar issue and added a comment here: https://github.com/Koenkk/zigbee2mqtt/issues/27095#issuecomment-2842525927
Replying here directly since the linked issue isn't about the problem here.
I believe this is a side-effect of swapping out the onboarding initial check (if it should run or not), to use just the configuration.yaml. It initially used the database.db too, which is not created until a first successful start (hence, onboarding would re-run until a valid-to-start config was in effect).
https://github.com/Koenkk/zigbee2mqtt/pull/26608#discussion_r1986088216
the validation function doesn't seem to check the serial-section though.
Quick note about this. The validation is handled automatically by AJV (ajvSetting()) from the schema. The rest is just special handling for more complex Z2M-specific scenario.
@Nerivec how would you suggest we solve this then?
Do you think the pre-start check that I commented above would be the way to go here, can we fix this in another way or should we open an issue?
We're already looking into a fix (several ways to accomplish this, trying to find the best solution). I'll update here when it's done.
Perfect, thanks @Nerivec!
A fix was merged. Should be available in June release. Let me know if you can test it with current dev branch and confirm it behaves itself now 😉
@al-lac: should Inedit the docker-compose to use the current dev, so you can try to reproduce the problems you had?
@dirstel already tested it locally, seems to work great now! 🎉
Great job on the fix @Nerivec! 👏
Lets wait until the June release, will discuss with @nmfretz if we should also include support for usb adapters until then.
seems to work great now! 🎉
So I assume, no need for your scripts and hook anymore. I'll leave the PR as is and will insert the June-Version when released.
Thank you both a lot, @al-lac and @Nerivec!
Nice work everyone!
Lets wait until the June release, will discuss with @nmfretz if we should also include support for usb adapters until then.
@al-lac let's go ahead with support for usb adapters as there is already precedent for this in the app store (e.g., Home Assistant binding /run/dbus which is arguably more of a security risk).
Can we bind as readonly? So something like:
/run/udev:/run/udev:ro
Hey @dirstel, after a discussion with @nmfretz we came to the conclusion that it is probably for the best to have mosquitto as a requirement and as a default as that makes getting started really easy for users.
After the setup is done, one can always change their preferred broker in the settings.
Could you please test again with the updates and let us know if everything works?
@al-lac : Sure, I'll test if everythings is still fine. May take some time as I'm busy right now, but better safe than sorry :)
Excellent work @dirstel and @al-lac. Tested and working great, including auto-discovery of my zigbee 3.0 dongle. I'll add the gallery assets to the manifest and then we are good to go 🎉