MAATRIX / Блог / Бэкап и восстановление Zigbee2MQTT

Бэкап и восстановление Zigbee2MQTT

MAATRIX

Zigbee2MQTT снимает зависимость от фирменных хабов, но платит за это своей точкой отказа: вся сеть — реестр устройств, их привязки друг к другу и ключи шифрования — держится на нескольких файлах на диске сервера. Потеряете их вместе с диском — и придётся не переустанавливать софт, а физически обходить квартиру или дом, заново нажимая кнопку сопряжения на полусотне выключателей, датчиков и реле, часть из которых уже закручена в стены. Ниже — что именно копировать, чем автоматизировать и как восстановить сеть на новом сервере так, чтобы устройства не заметили переезда.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что бэкапить в Zigbee2MQTT: три файла и что будет, если их потерять

Если вы разворачивали мост по инструкции про установку Zigbee2MQTT на VPS (или на локальном сервере с проброшенным USB-координатором), состояние сети целиком лежит в каталоге данных — обычно /opt/zigbee2mqtt/data. В отличие от типового веб-сервиса, где потеря конфига — это часовая работа по восстановлению настроек, здесь потеря части файлов означает физическое пере-сопряжение устройств.

ФайлЧто содержитЧто теряется без бэкапа
configuration.yamlНастройки моста: MQTT-брокер, порт координатора, PAN ID, канал, флагиНастройки восстанавливаются вручную за 10–15 минут — не критично
database.dbРеестр устройств: IEEE-адреса, friendly names, network address, короткие адресаВсе устройства нужно сопрягать заново — физически, руками
coordinator_backup.jsonДамп сети с координатора: PAN ID, extended PAN ID, network key, список привязанных устройствБез него сеть невозможно восстановить на новом координаторе без ресета всех устройств
state.jsonПоследние известные состояния устройств (для восстановления после рестарта)Не критично — обновится само за первый цикл опроса
log/Логи мостаНе нужен для восстановления

Ключевой файл — coordinator_backup.json. Zigbee-сеть привязана не к софту, а к конкретному радиочипу координатора: PAN ID и network key физически прошиты в его памяти и в памяти каждого устройства сети при сопряжении. Если координатор выходит из строя или вы переезжаете на новый сервер с новым USB-стиком, восстановить сеть на новом чипе без re-pairing можно только одним способом — залить туда именно тот coordinator_backup.json, что был снят со старого координатора. Без него новый чип получит новый случайный PAN ID и network key, и все устройства с точки зрения сети окажутся "ничьими".

database.db — это SQLite-подобная newline-delimited JSON база (несмотря на расширение .db, это текстовый файл, который можно открыть и прочитать построчно). В ней Zigbee2MQTT хранит сопоставление IEEE-адресов устройств с friendly names, которые вы задавали руками, и таблицу маршрутизации для router-устройств (умных розеток, работающих ретрансляторами сигнала). Потеряв её при живом координаторе, вы формально не потеряете сеть — устройства продолжат быть привязанными на радиоуровне, — но Zigbee2MQTT перестанет их узнавать: в MQTT полезут топики с сырыми IEEE-адресами вместо понятных имён, а все автоматизации в Home Assistant или Node-RED, завязанные на friendly name, отвалятся.

Простой бэкап: снапшот каталога данных

Для домашней установки без строгих SLA достаточно тарить весь каталог data целиком, исключив только логи:

mkdir -p /mnt/backup/zigbee2mqtt

tar --exclude='data/log' \
    -czf /mnt/backup/zigbee2mqtt/z2m-$(date +%F).tar.gz \
    -C /opt/zigbee2mqtt data

Перед снятием бэкапа стоит убедиться, что сам мост успел записать актуальный coordinator_backup.json на диск — по умолчанию Zigbee2MQTT пересоздаёт этот файл при каждом старте и периодически в рантайме, но если вы только что добавили новое устройство, безопаснее сделать бэкап через встроенную команду, а не полагаться на файл, оставшийся с последнего запуска:

mosquitto_pub -h localhost -t 'zigbee2mqtt/bridge/request/backup' -m ''

Эта команда шлёт в MQTT запрос на принудительный экспорт бэкапа координатора — после неё coordinator_backup.json в каталоге данных гарантированно отражает текущее состояние сети, включая устройства, добавленные секунду назад.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Автоматизация через restic: дедупликация и офсайт

Каталог data небольшой (обычно десятки мегабайт даже для сети из сотни устройств), но регулярный tar всё равно накапливает избыточные копии одного и того же. Restic решает это дедупликацией и заодно шифрует архив — в database.db и MQTT-конфиге внутри configuration.yaml может лежать пароль от брокера. Подробно установка и работа с restic разобраны в статье про бэкап и восстановление restic, здесь — только применение к Zigbee2MQTT.

Инициализация репозитория (один раз):

export RESTIC_REPOSITORY=/mnt/backup-disk/zigbee2mqtt-restic
export RESTIC_PASSWORD_FILE=/root/.restic-z2m-pass
restic init

Сам бэкап с предварительным принудительным экспортом координатора:

mosquitto_pub -h localhost -t 'zigbee2mqtt/bridge/request/backup' -m ''
sleep 3

restic backup /opt/zigbee2mqtt/data \
  --tag zigbee2mqtt \
  --exclude='/opt/zigbee2mqtt/data/log'

Пауза в три секунды после запроса на бэкап нужна, чтобы мост успел записать файл на диск до того, как restic начнёт его читать — сама операция асинхронная, подтверждения о завершении записи в ответ не приходит.

Для офсайта — копии не на том же диске, что и сам сервер с координатором, — направьте RESTIC_REPOSITORY на отдельный сервер по SFTP. Требования к такому серверу под архив разобраны в статье про VPS для бэкапов и архива. Для Zigbee2MQTT объём хранения минимален — даже недорогой тариф с запасом покроет годы ежедневных снапшотов сети из сотен устройств.

Автоматизация: скрипт и systemd timer

#!/usr/bin/env bash
# /usr/local/bin/zigbee2mqtt-backup.sh
set -euo pipefail

DATA_DIR=/opt/zigbee2mqtt/data

mosquitto_pub -h localhost -t 'zigbee2mqtt/bridge/request/backup' -m ''
sleep 3

export RESTIC_REPOSITORY=/mnt/backup-disk/zigbee2mqtt-restic
export RESTIC_PASSWORD_FILE=/root/.restic-z2m-pass

restic backup "$DATA_DIR" \
  --tag zigbee2mqtt \
  --exclude="$DATA_DIR/log"

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
chmod +x /usr/local/bin/zigbee2mqtt-backup.sh

Unit и таймер:

# /etc/systemd/system/zigbee2mqtt-backup.service
[Unit]
Description=Zigbee2MQTT data backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/zigbee2mqtt-backup.sh
# /etc/systemd/system/zigbee2mqtt-backup.timer
[Unit]
Description=Daily Zigbee2MQTT backup

[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now zigbee2mqtt-backup.timer
systemctl list-timers | grep zigbee2mqtt

Ежедневного снапшота для домашней сети более чем достаточно — устройства добавляются нечасто, а coordinator_backup.json не меняется, пока состав сети стабилен. Важнее не частота, а то, чтобы бэкап срабатывал именно после изменений в сети, а не только по расписанию — если вы добавили новое устройство вечером, стоит один раз вручную прогнать скрипт, не дожидаясь ночного таймера.

Восстановление на живом координаторе: та же физическая флешка

Самый простой случай — сервер (диск, ОС) вышел из строя, но USB-координатор физически цел и остаётся тем же чипом. Тогда PAN ID и network key на самом координаторе не меняются, и восстановление сводится к возврату файлов на место:

1. Поднимите базовое окружение тем же способом, что в статье про установку Zigbee2MQTT на VPS, пробросьте тот же USB-координатор в контейнер или к процессу.

2. Восстановите каталог data из restic до первого запуска:

export RESTIC_REPOSITORY=/mnt/backup-disk/zigbee2mqtt-restic
export RESTIC_PASSWORD_FILE=/root/.restic-z2m-pass

mkdir -p /opt/zigbee2mqtt/data
restic restore latest --target /opt/zigbee2mqtt/data --path /opt/zigbee2mqtt/data

3. Проверьте права на файлы — владелец после восстановления может не совпадать с UID, под которым работает контейнер:

chown -R 1000:1000 /opt/zigbee2mqtt/data   # UID контейнера уточните в вашем docker-compose.yml

4. Запустите и проверьте логи:

cd /opt/zigbee2mqtt
docker compose up -d
docker compose logs -f zigbee2mqtt

В логах при штатном запуске должна быть строка о том, что мост запустился с существующим бэкапом координатора без предупреждений о смене network key. Все устройства должны появиться в MQTT под теми же friendly names, что были раньше — physical re-pairing здесь не нужен, потому что физический координатор остался тем же чипом, что и был.

Восстановление на новом координаторе: заливка coordinator_backup.json

Более жёсткий случай — старый USB-координатор физически сгорел или потерян, и вы ставите новый чип (даже той же модели). Здесь одного восстановления файлов из бэкапа недостаточно: новому чипу нужно явно передать сетевые параметры старой сети.

1. Восстановите data тем же способом, что выше.

2. Перед первым запуском с новым координатором большинство адаптеров Zigbee2MQTT (стек zigbee-herdsman, используемый под капотом) при старте с уже существующим в каталоге coordinator_backup.json и *новым*, "пустым" координатором предложат восстановить сеть на нём из этого бэкапа — это штатный сценарий смены железа. Убедитесь, что в configuration.yaml указан правильный serial.port, соответствующий новому устройству (/dev/ttyUSB0, /dev/ttyACM0 или по by-id, что надёжнее — путь /dev/ttyUSB0 может смещаться при переподключении разных USB-устройств):

serial:
  port: /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus...

3. Запустите мост и внимательно проверьте лог первого старта. Если восстановление сети на новом координаторе прошло успешно, устройства начнут появляться в MQTT постепенно — router-устройства (розетки, реле) обычно переподключаются быстрее, battery-устройства (датчики, кнопки) могут молчать до следующего планового пробуждения, это не повод паниковать раньше времени.

4. Если восстановление не сработало (иногда бывает при смене модели чипа на архитектурно другую, например с EZSP-адаптера на Z-Stack) — сеть придётся собирать заново: сброс каждого устройства и повторное сопряжение. Тут бэкап уже не поможет ничем, кроме списка friendly names и типов устройств, которые вы задавали раньше, — держите этот список отдельно (например, экспортом в frontend), чтобы хотя бы не гадать заново, какое устройство как называлось.

Типичные грабли при бэкапе и восстановлении

  • Бэкапили только configuration.yaml, забыли coordinator_backup.json. Настройки моста без проблем восстанавливаются вручную, но без дампа координатора смена железа означает полное пере-сопряжение сети — а это часы физической работы, если устройств много и часть труднодоступна.
  • coordinator_backup.json устарел на момент отказа сервера. Файл обновляется не при каждом изменении сети мгновенно — если вы добавили устройство и сразу отключили сервер, не дождавшись очередного цикла бэкапа, восстановление на новом координаторе пройдёт без этого устройства. Всегда посылайте bridge/request/backup вручную после значимых изменений в сети.
  • Путь к координатору задан как /dev/ttyUSB0 без привязки по by-id. При подключении второго USB-устройства (флешки, другого адаптера) Linux может переназначить номер, и после перезагрузки мост попытается открыть не тот порт. Особенно актуально при переезде на новый сервер с другим набором периферии.
  • Не проверяли, что MQTT-брокер поднялся раньше самого моста. Восстановленный Zigbee2MQTT при старте без доступного брокера падает в цикл переподключения — убедитесь, что порядок запуска контейнеров (depends_on в docker-compose) учитывает эту зависимость.
  • Восстанавливали сеть на новом координаторе поверх уже проинициализированного. Если новый чип успел один раз стартовать без бэкапа и получить собственный случайный PAN ID, последующая попытка залить старый coordinator_backup.json может потребовать явного сброса координатора перед восстановлением — читайте предупреждения в логе первого старта внимательно, там обычно прямо указано, что делать.
  • Ни разу не проверяли восстановление на практике. Работающий бэкап координатора не гарантирует, что восстановление на конкретной модели чипа пройдёт гладко — стоит хотя бы раз протестировать сценарий на запасном USB-адаптере, прежде чем полагаться на него в реальной аварии. Общий подход к таким проверкам разобран в статье про восстановление базы данных из бэкапа на практике.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Нужно ли останавливать Zigbee2MQTT перед бэкапом?

Нет, файловый бэкап через tar или restic безопасен и во время работы моста — файлы не переписываются построчно посреди операции. Единственное, что стоит сделать перед снятием архива, — принудительно запросить свежий coordinator_backup.json через MQTT, если недавно менялся состав устройств.

Можно ли перенести сеть на координатор другой модели или другого чипсета (например, с CC2531 на Sonoff Dongle Plus)?

Иногда да, если оба используют совместимый стек прошивки (Z-Stack к Z-Stack), но это не гарантировано официально и зависит от конкретных версий firmware — прежде чем полагаться на такой перенос в бою, стоит протестировать его на некритичном устройстве.

Что будет с battery-устройствами (датчиками на батарейках) при восстановлении на новом координаторе?

Они не поддерживают постоянное соединение и "узнают" о смене сети только при следующем плановом пробуждении — обычно это часы, иногда сутки в зависимости от интервала отчётов конкретной модели. Не паникуйте, если они не появились в MQTT сразу после restore.

Достаточно ли ежедневного бэкапа или нужен бэкап после каждого изменения?

Ежедневного снапшота хватает для стабильной сети, но после добавления нового устройства или переименования friendly name стоит один раз прогнать скрипт бэкапа вручную, не дожидаясь ночного таймера — иначе при отказе сервера именно в этот день последние изменения потеряются.

Что делать, если database.db повреждена, а координатор жив?

Сеть на радиоуровне не пострадает, но Zigbee2MQTT потеряет сопоставление IEEE-адресов с friendly names. Восстановите database.db из последнего бэкапа — устройства должны переподключиться к прежним именам без пере-сопряжения, поскольку сама сетевая привязка хранится не в этом файле, а на координаторе.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →