Zigbee2MQTT в Docker Compose: готовый файл
Фирменные Zigbee-хабы вроде Aqara Hub или Xiaomi Gateway работают, пока производителю выгодно поддерживать облако — стоит закрыть сервис или заблокировать регион, и коробка с датчиками превращается в кирпич. Zigbee2MQTT решает это радикально: он превращает недорогой USB-координатор в мост между Zigbee-устройствами и обычным MQTT-брокером, без единого запроса к серверам вендора. Ниже — рабочий docker-compose.yml, честный разбор проблемы с USB на облачном сервере и то, как собрать связку так, чтобы она не разваливалась после каждой перезагрузки.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что вообще делает Zigbee2MQTT и зачем ему Docker
Zigbee2MQTT — это программный стек на Node.js, который берёт на себя роль Zigbee-координатора: общается с радиомодулем по USB (или по сети), опрашивает датчики и реле, переводит проприетарные Zigbee-команды в понятные MQTT-топики и публикует их в брокер. Дальше с этими топиками может работать что угодно — Home Assistant, Node-RED, openHAB или ваш собственный скрипт на Python.
Ключевое отличие от фирменных хабов: вы не привязаны к экосистеме одного производителя. Zigbee2MQTT поддерживает несколько тысяч моделей устройств от Aqara, IKEA, Tuya, Sonoff, Philips Hue и десятков других брендов одновременно, в одной Zigbee-сети.
Docker для Zigbee2MQTT даёт то же, что и для любого другого сервиса — предсказуемую версию, изоляцию от остальной системы и возможность откатиться одной командой, если после обновления адаптер перестал видеть устройства (такое с Zigbee-стеком случается чаще, чем хотелось бы).
Важный нюанс: USB-координатор и облачный сервер
Прежде чем копировать compose-файл — честно проговорим ограничение, которое часто узнают только после часа безуспешных попыток. Zigbee2MQTT общается с координатором по последовательному порту, то есть ему нужен физический доступ к USB-устройству. Обычный облачный VPS физического USB-порта не имеет — воткнуть в него дongle Sonoff Zigbee 3.0 или ConBee II просто некуда.
Отсюда два рабочих сценария:
- Zigbee2MQTT крутится локально, на мини-ПК или Raspberry Pi дома, рядом с координатором — это самый простой и надёжный вариант, если вам важна низкая задержка и вы не хотите городить сетевые прослойки;
- Zigbee2MQTT крутится на арендованном сервере, а координатор физически стоит дома и пробрасывается по сети через
ser2netили аналогичный TCP-to-serial мост, поверх WireGuard-туннеля между домашней сетью и сервером.
Второй вариант оправдан, если весь остальной умный дом (Home Assistant, Node-RED, база данных, дашборды) уже живёт на арендованном сервере, и вы не хотите держать локальную машину только ради одного контейнера. Задержка через приличный VPN-канал добавляет единицы-десятки миллисекунд — для Zigbee, где команда "включить свет" и так идёт через радиосеть, это не критично.
Дальше в статье будем считать, что координатор физически доступен на той же машине, где поднимается Docker — то есть либо это локальный сервер/мини-ПК дома, либо связка через ser2net уже настроена и координатор виден по TCP.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверГотовый docker-compose.yml
Минимальная рабочая конфигурация — сам Zigbee2MQTT и Mosquitto как MQTT-брокер рядом:
services:
mosquitto:
container_name: mosquitto
image: eclipse-mosquitto:2.0
restart: unless-stopped
ports:
- "1883:1883"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
zigbee2mqtt:
container_name: zigbee2mqtt
image: koenkk/zigbee2mqtt:latest
restart: unless-stopped
depends_on:
- mosquitto
volumes:
- ./zigbee2mqtt/data:/app/data
- /run/udev:/run/udev:ro
devices:
- /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus-if00-port0:/dev/ttyACM0
ports:
- "8080:8080"
environment:
- TZ=Europe/Moscow
Минимальный конфиг Mosquitto — mosquitto/config/mosquitto.conf:
listener 1883
allow_anonymous false
password_file /mosquitto/config/passwd
Пароль для брокера создаётся отдельной командой перед первым запуском:
mkdir -p ~/z2m/mosquitto/config ~/z2m/mosquitto/data ~/z2m/mosquitto/log ~/z2m/zigbee2mqtt/data
cd ~/z2m
docker run --rm -v $(pwd)/mosquitto/config:/mosquitto/config eclipse-mosquitto:2.0 \
mosquitto_passwd -c -b /mosquitto/config/passwd z2m СЛОЖНЫЙ_ПАРОЛЬ
Что важно в самом compose-файле:
devices:— путь к координатору лучше указывать через/dev/serial/by-id/..., а не/dev/ttyUSB0или/dev/ttyACM0напрямую. Порядковый номер USB-устройства не гарантирован после перезагрузки хоста, а вотby-id-путь, завязанный на серийник устройства, стабилен. Посмотреть точный путь:ls -l /dev/serial/by-id/;/run/udev:/run/udev:ro— нужен, чтобы Zigbee2MQTT корректно определял устройство при старте контейнера;- образ
latestдля первого знакомства нормален, но для боевой эксплуатации лучше зафиксировать конкретный тег (например,koenkk/zigbee2mqtt:2.2.0) — так обновления происходят осознанно, а не при каждом пересоздании контейнера.
Конфигурация Zigbee2MQTT: configuration.yaml
При первом запуске Zigbee2MQTT создаёт в ./zigbee2mqtt/data/ файл configuration.yaml. Базовые настройки, которые стоит проверить сразу:
homeassistant:
enabled: true
mqtt:
base_topic: zigbee2mqtt
server: mqtt://mosquitto:1883
user: z2m
password: СЛОЖНЫЙ_ПАРОЛЬ
serial:
port: /dev/ttyACM0
adapter: ember
frontend:
port: 8080
advanced:
network_key: GENERATE
pan_id: GENERATE
log_level: info
Пара моментов, которые легко упустить:
server: mqtt://mosquitto:1883— работает благодаря тому, что оба контейнера в одной Docker-сети по умолчанию и видят друг друга по имени сервиса, безnetwork_mode: host;adapter: ember— актуально для координаторов на чипе EFR32 (Sonoff Zigbee 3.0 Dongle Plus, SLZB-06); для старых CC2531/CC2652 на базе Z-Stack адаптер обычноzstackили автоопределение можно оставить пустым;network_key: GENERATEиpan_id: GENERATE— Zigbee2MQTT сам сгенерирует значения при первом запуске и подставит их в файл. Дальше их лучше не трогать: смена сетевого ключа означает повторное сопряжение всех устройств заново;homeassistant: enabled: true— включает MQTT Discovery, и Home Assistant подхватывает все устройства из Zigbee2MQTT автоматически, без ручного описания каждой сущности в YAML.
После правки configuration.yaml контейнер нужно пересоздать: docker compose restart zigbee2mqtt.
Сопряжение устройств и веб-интерфейс
Веб-фронтенд Zigbee2MQTT поднимается на порту 8080 (http://IP-сервера:8080) и даёт полный контроль без правки YAML руками: список устройств, карта сети, логи в реальном времени, включение режима сопряжения.
Типичный сценарий добавления нового устройства:
- В веб-интерфейсе нажимаете "Permit join" (или
mosquitto_pub -t zigbee2mqtt/bridge/request/permit_join -m '{"value": true, "time": 120}'из консоли); - Переводите устройство в режим сопряжения по инструкции производителя (обычно — несколько быстрых нажатий на кнопку или зажатие на 5-10 секунд);
- Устройство появляется в списке за несколько секунд — если это простой датчик, обычно сразу с корректным описанием модели.
Проблемные устройства случаются — часть дешёвых Tuya-реле сопрягается не с первой попытки, некоторые датчики требуют держать их в паре сантиметров от координатора при первом подключении. Если устройство не находится за пару минут — проверьте логи в веб-интерфейсе, там обычно видна конкретная причина (interview failed, timeout и подобное).
Сразу после сопряжения стоит зайти в настройки устройства и дать ему человекочитаемое имя (friendly_name) вместо MAC-адреса по умолчанию — это тот топик, который дальше будет использоваться в автоматизациях Home Assistant или Node-RED, и переименовывать его задним числом не всегда удобно.
Зона покрытия сети и роутеры
Zigbee — это mesh-сеть: устройства с постоянным питанием (розетки, реле, некоторые лампы) выступают роутерами и ретранслируют сигнал от батарейных датчиков дальше по сети. Чем больше таких "запитанных" устройств равномерно по квартире или дому — тем стабильнее покрытие и тем меньше шансов, что датчик в дальней комнате будет отваливаться.
Практические наблюдения по покрытию:
- координатор лучше не прятать в металлический системный блок или за роутер с Wi-Fi — металл и другие радиомодули рядом заметно бьют по дальности;
- USB-удлинитель на 1-1.5 метра часто решает проблемы с "невидимыми" устройствами лучше, чем любые настройки софта — координатор уходит подальше от корпуса сервера и источников помех;
- карту сети (Network map) в веб-интерфейсе стоит открыть после добавления первых 10-15 устройств — она наглядно показывает, какие узлы работают роутерами, а какие висят "сиротами" напрямую на координаторе со слабым сигналом.
Точных цифр по дальности сознательно не даём — она слишком сильно зависит от планировки, стен и числа роутеров в конкретной сети.
Связка с Home Assistant
Если Home Assistant стоит рядом, в соседнем контейнере той же Docker-сети, интеграция сводится к добавлению интеграции MQTT в самом Home Assistant (Settings → Devices & services → Add integration → MQTT) с адресом того же брокера mosquitto:1883. При включённом homeassistant: enabled: true в конфиге Zigbee2MQTT все устройства появляются в Home Assistant автоматически, каждое — со своими сущностями (датчик температуры, переключатель, диммер и так далее).
Если Home Assistant и Zigbee2MQTT работают на разных серверах — например, Zigbee2MQTT ближе к устройствам, а Home Assistant централизованно на более мощном сервере — MQTT-брокер должен быть доступен обеим сторонам. Проще всего пробросить порт 1883 только через VPN-туннель, а не открывать его в интернет: MQTT без TLS и с учёткой в открытом виде — не то, что стоит светить наружу. Подробно о готовом compose-файле для самого Home Assistant и вариантах его размещения — в отдельной статье про Home Assistant в Docker Compose.
Как альтернативу или дополнение к Home Assistant для логики автоматизаций многие используют Node-RED — он тоже прекрасно подписывается на топики zigbee2mqtt/# и даёт визуальный конструктор сценариев без единой строчки YAML.
Бэкапы и обновление
Всё состояние Zigbee2MQTT — в каталоге ./zigbee2mqtt/data/. Внутри: configuration.yaml, база устройств database.db, сетевой ключ и PAN ID (их потеря означает повторное сопряжение каждого устройства заново — не самая приятная перспектива, если у вас полсотни датчиков по квартире).
Минимальный скрипт для бэкапа перед любым обновлением:
#!/bin/bash
STAMP=$(date +%Y%m%d-%H%M%S)
docker compose stop zigbee2mqtt
tar -czf ~/backups/z2m-data-$STAMP.tar.gz -C ~/z2m zigbee2mqtt/data
docker compose start zigbee2mqtt
Обновление — смена тега образа и пересоздание контейнера:
docker compose pull zigbee2mqtt
docker compose up -d zigbee2mqtt
Перед мажорным обновлением стоит заглянуть в release notes на GitHub проекта — иногда меняется формат configuration.yaml, и без миграции конфига сервис может не подняться. Прошивку самого координатора Zigbee2MQTT не обновляет — для EFR32-адаптеров это делается отдельной утилитой с хоста, координатор на это время придётся временно вынуть из контейнера.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли просто арендовать VPS и воткнуть в него Zigbee-координатор?
Нет — у виртуального сервера физически нет USB-порта, который можно пробросить в вашу квартиру. Координатор должен стоять либо на локальной машине рядом с устройствами, либо на выделенном сервере с реальным физическим доступом, либо подключаться удалённо через сетевой мост вроде ser2net поверх VPN.
Чем ConBee II лучше дешёвого CC2531?
Более современный чип, стабильнее прошивки, лучше держит большое число устройств одновременно (CC2531 ограничен по памяти где-то в районе 20 устройств без роутеров). Для сети из 5-10 устройств разница некритична, для полусотни — CC2531 начнёт сбоить раньше.
Что будет с устройствами, если контейнер Zigbee2MQTT упадёт?
Сама Zigbee-сеть продолжит работать — устройства-роутеры маршрутизируют сигнал независимо от координатора. Но команды и обновления состояния перестанут доходить до MQTT, пока контейнер не поднимется снова — переключить свет через Home Assistant не получится, а прямое физическое управление кнопкой обычно продолжает работать.
Нужен ли отдельный сервер только под Zigbee2MQTT?
Нет, он легковесный и уживается в Docker Compose рядом с Home Assistant, Node-RED или другими сервисами на том же сервере — единственное жёсткое требование — физический доступ к USB-координатору на этой машине.
Стоит ли открывать порт 8080 в интернет?
Не стоит без защиты — доступа к сопряжению устройств и сетевому ключу лучше не давать никому, кроме себя. Тот же принцип, что и с Home Assistant: WireGuard до сервера или reverse-proxy с Basic Auth, но не голый порт наружу.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →