zigbee2mqtt usually just works fine. However, in its latest version 2.x, the way external converters get loaded has changed fundamentally.
To begin with, external converters can now be loaded by sending their code via MQTT, which to me looks like adding some remote eval
capability just for the fun of it.
In order to accomplish this, zigbee2mqtt creates a new file with the converter code inside the external_converters
subdirectory of its own code directory. We therefore get self-modifying code in an application usually entrusted with complete physical control over all smart home devices, something that wouldn’t let me sleep tight at night.
External converters placed manually into the ZIGBEE2MQTT_DATA/external_converters
directory are picked up automatically, and also copied to the code subdirectory.
On Arch Linux, zigbee2mqtt is typically launched as a systemd service via the zigbee2mqtt.service
file. This Arch-specific service definition leverages many of the newer systemd directives which permit strapping down the service process as much as possible. Filesystem r/w access is limited to just two directories:
ReadWritePaths=/var/lib/zigbee2mqtt /etc/zigbee2mqtt
Consequently, when trying to write to its own code directory, the operation fails, the external converter gets marked as invalid, and is never loaded. This is good for security, however it’ll prevent any external converter from being loaded.
In order to work around this – against which I strongly recommend, except for development and debugging purposes – the systemd service definition needs to be amended to allow for zigbee2mqtt to self-modify:
# /etc/systemd/system/zigbee2mqtt.service.d/external-converters.conf
ReadWritePaths=/usr/share/webapps/zigbee2mqtt/dist/external_converters
Also, the external_converters
directory needs to be created:
mkdir /usr/share/webapps/zigbee2mqtt/dist/external_converters
chown zigbee2mqtt: /usr/share/webapps/zigbee2mqtt/dist/external_converters
systemd needs to be reloaded to pick up the changed service configuration:
# systemctl daemon-reload
Finally, make sure to revert all changes before using zigbee2mqtt in production.