Cannot use secret.yaml for MQTT credentials on add-on 2.13.0-1 — "mqtt must have required property 'server'"
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 15.7k
- Forks
- 2k
- Avg merge
- 18h 55m
- Merged PRs (30d)
- 35
Description
What happened?
Why are you guys not serious about security?
Environment
- Zigbee2MQTT add-on 2.13.0-1 (latest, no update available)
- Zigbee2MQTT core 2.13.0
- Home Assistant Core 2026.8.1 / Home Assistant OS 18.2
data_path: /config/zigbee2mqtt- MQTT: Mosquitto add-on (
mqtt://core-mosquitto:1883) - Adapter is network-attached (TubesZB CC2652 over Ethernet), not USB:
serial:
port: socket://192.168.1.50:6638
adapter: zstack
baudrate: 115200
rtscts: false
Goal
Keep the MQTT password out of configuration.yaml, so the file can be committed to a
private git repo. Followed the documented approach:
https://www.zigbee2mqtt.io/guide/configuration/mqtt.html
Attempt 1 — reference only in configuration.yaml
With the add-on stopped, created /config/zigbee2mqtt/secret.yaml:
password: <64-char password>
and set in configuration.yaml:
mqtt:
base_topic: zigbee2mqtt
server: mqtt://core-mosquitto:1883
user: addons
password: '!secret.yaml password'
Recorded md5sum configuration.yaml while stopped to prove the reference was on disk.
Started the add-on.
Result: Z2M started and connected fine, but configuration.yaml was rewritten — the
md5 changed and password: was back to the 64-char plaintext. secret.yaml was untouched.
This appears to be the add-on writing its own mqtt: options (which were mqtt: {}) into
configuration.yaml on start, per the discussion in Koenkk/zigbee2mqtt#27077.
Attempt 2 — reference in BOTH add-on options and configuration.yaml
Applied the workaround from that thread. Add-on options:
mqtt:
server: "!secret.yaml mqtt_server"
user: "!secret.yaml mqtt_user"
password: "!secret.yaml mqtt_password"
base_topic: zigbee2mqtt
/config/zigbee2mqtt/secret.yaml (mode 600, owned by root):
mqtt_server: mqtt://core-mosquitto:1883
mqtt_user: addons
mqtt_password: <64-char password>
configuration.yaml:
mqtt:
base_topic: zigbee2mqtt
server: '!secret.yaml mqtt_server'
user: '!secret.yaml mqtt_user'
password: '!secret.yaml mqtt_password'
Result: the references now persist in configuration.yaml (so that part of the
workaround does work), but Z2M refuses to start:
[16:44:03] INFO: Preparing to start...
[16:44:03] INFO: Socat not enabled
[16:44:03] INFO: Starting Zigbee2MQTT...
Starting Zigbee2MQTT without watchdog.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
READ THIS CAREFULLY
Refusing to start because configuration is not valid, found the following errors:
- mqtt must have required property 'server'
If you don't know how to solve this, read https://www.zigbee2mqtt.io/guide/configuration
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
So the !secret.yaml references are not being resolved at all — the resulting config has
no mqtt.server.
Reverting both files to plaintext restores normal operation immediately.
Note
configuration.yaml also contains advanced.network_key in plain text, so this affects
more than the MQTT password for anyone version-controlling their config.
What did you expect to happen?
For the pass!secret.yaml <key> references in configuration.yaml should resolve at runtime from
<data_path>/secret.yaml, exactly as documented, so the MQTT password (and ideally
advanced.network_key) never appear as plaintext in configuration.yaml.
Instead, either the plaintext value is written back into the file, or the reference is
not resolved at all and Z2M refuses to start.word security to work
How to reproduce it (minimal and precise)
- Stop the Zigbee2MQTT add-on.
- Create
/config/zigbee2mqtt/secret.yaml:
mqtt_server: mqtt://core-mosquitto:1883
mqtt_user: addons
mqtt_password: <password>
- In the add-on Configuration tab set:
mqtt:
server: "!secret.yaml mqtt_server"
user: "!secret.yaml mqtt_user"
password: "!secret.yaml mqtt_password"
base_topic: zigbee2mqtt
- In
/config/zigbee2mqtt/configuration.yamlset the same three references. - Start the add-on.
Result: refuses to start with mqtt must have required property 'server'.
Variant: with the references ONLY in configuration.yaml and mqtt: {} in the add-on
options, the add-on overwrites configuration.yaml on start and restores the plaintext
password. Verified by taking md5sum configuration.yaml while the add-on was stopped and
again after starting — the file changes.
Zigbee2MQTT version
2.13.0-1
Adapter firmware version
20211210
Adapter
CC2652
Setup
Home Assistant add-on (Supervisor), Home Assistant OS 18.2 running as a VM on Proxmox,
x86-64. Zigbee adapter is network-attached (TubesZB CC2652 over Ethernet, socket://),
not USB.
uname -a:
Linux 6.18.39-haos #1 SMP PREEMPT_DYNAMIC Thu Jul 30 12:31:10 UTC 2026 x86_64 Linux
/etc/issue.net: not applicable on Home Assistant OS (file does not exist)
Device database.db entry
Not attached — the failure occurs during config validation, before Z2M starts logging. The complete validation error is quoted in the body above.
Debug log
Not attached — the failure occurs during config validation, before Z2M starts logging.
The complete validation error is quoted in the body above.
Notes
This affects anyone version-controlling their Home Assistant configuration:
configuration.yaml contains both the MQTT password and advanced.network_key in
plaintext, and there appears to be no working way to externalise them on the add-on.
One untested theory for why the references silently fail to resolve: secret.yaml was
mode 0600 owned by root. If Z2M runs as a non-root user inside the add-on container it
may be unable to read it. configuration.yaml has the same owner and mode and is read
successfully, so this may be a red herring.
Happy to test a patch or provide further detail.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the minimal configuration using configuration.yaml, the add-on options, and secret.yaml, then trace how add-on options are written and how !secret.yaml references reach configuration validation. Done means secret values resolve, mqtt.server passes validation, and starting the add-on no longer rewrites references as plaintext. Retest with the MQTT credentials and advanced.network_key cases described in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100