Z2M migration: restore via coordinator_backup.json (fix ext_pan_id byte-order trap) #366

Merged
k.renner merged 1 commits from claude-bot/zha-to-zigbee2mqtt into master 2026-07-23 10:33:46 +00:00
Member

Follow-up to #364 (merged). Corrects the cutover mechanism before it is ever run.

Why

#364 hand-set advanced.pan_id/ext_pan_id/network_key in the Z2M config from the live ZHA values. That is the risky path: the extended PAN ID byte order is reversed between ZHA (zigpy) and Z2M (zigbee-herdsman). Loading the ZHA value as-is makes herdsman see a mismatch and form a new network → every device drops → mass re-pair (the explicit non-goal). Mixing a manual ext_pan_id with a backup also conflicts.

What

Restore an Open Coordinator Backup (the shared zigpy↔herdsman interchange format) instead — it pins byte orders in-spec and handles the reversal on import.

  • New zigbee2mqtt-coordinator-backup ExternalSecret (OpenBao) holds the full backup JSON (network key → OpenBao only, never git); replaces zigbee2mqtt-network-externalsecret.yaml.
  • Init container seeds /app/data/coordinator_backup.json on first run only (also guarded on database.db so Z2M state is never overwritten); renders only the MQTT password into secret.yaml.
  • Config drops advanced.pan_id/ext_pan_id/network_key/channel.
  • Runbook: Step 1 now exports the backup from zigbee.db via zigpy (non-disruptive — no second radio session); added an explicit device re-interview step (devices stay joined, but Z2M's DB starts empty).

Verified live (read-only)

Coordinator: pan 0x8b2b, ext_pan_id fc7a735d08c15476, channel 25; zigpy emits a valid open-coordinator-backup with 15 device records embedded. Kustomize builds; --dry-run=server clean.

Sources: ZHA→Z2M no-re-pair discussion · Z2M FAQ (backup/restore)

🤖 Generated with Claude Code

Follow-up to #364 (merged). Corrects the cutover **mechanism** before it is ever run. ## Why #364 hand-set `advanced.pan_id`/`ext_pan_id`/`network_key` in the Z2M config from the live ZHA values. That is the **risky** path: the extended PAN ID byte order is **reversed** between ZHA (zigpy) and Z2M (zigbee-herdsman). Loading the ZHA value as-is makes herdsman see a mismatch and **form a new network → every device drops → mass re-pair** (the explicit non-goal). Mixing a manual `ext_pan_id` with a backup also conflicts. ## What Restore an **Open Coordinator Backup** (the shared zigpy↔herdsman interchange format) instead — it pins byte orders in-spec and handles the reversal on import. - New `zigbee2mqtt-coordinator-backup` ExternalSecret (OpenBao) holds the full backup JSON (network key → OpenBao only, never git); replaces `zigbee2mqtt-network-externalsecret.yaml`. - Init container seeds `/app/data/coordinator_backup.json` on first run only (also guarded on `database.db` so Z2M state is never overwritten); renders only the MQTT password into `secret.yaml`. - Config drops `advanced.pan_id/ext_pan_id/network_key/channel`. - Runbook: Step 1 now exports the backup from `zigbee.db` via zigpy (non-disruptive — no second radio session); added an explicit **device re-interview** step (devices stay joined, but Z2M's DB starts empty). ## Verified live (read-only) Coordinator: pan `0x8b2b`, ext_pan_id `fc7a735d08c15476`, channel `25`; zigpy emits a valid `open-coordinator-backup` with 15 device records embedded. Kustomize builds; `--dry-run=server` clean. **Sources:** [ZHA→Z2M no-re-pair discussion](https://github.com/Koenkk/zigbee2mqtt/discussions/24478) · [Z2M FAQ (backup/restore)](https://www.zigbee2mqtt.io/guide/faq/) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-07-23 10:31:13 +00:00
Correct the cutover mechanism before it ever runs. The prior approach hand-set
advanced.pan_id/ext_pan_id/network_key in the Z2M config from the ZHA values.
That is the risky path: the extended PAN ID byte order is REVERSED between ZHA
(zigpy) and Z2M (zigbee-herdsman), so loading the ZHA value as-is makes herdsman
see a mismatch and FORM A NEW network — dropping every device (the explicit
non-goal). Mixing a manual ext_pan_id with a backup also conflicts (Z2M ignores
the reversed value).

Instead restore an Open Coordinator Backup, the shared zigpy<->herdsman
interchange format, which pins byte orders in-spec and handles the reversal on
import:
  - New zigbee2mqtt-coordinator-backup ExternalSecret (OpenBao) holds the full
    backup JSON (contains the network key -> OpenBao only, never git), replacing
    zigbee2mqtt-network-externalsecret.yaml.
  - Init container seeds /app/data/coordinator_backup.json on first run only
    (guarded on database.db too, so Z2M's own state is never overwritten), and
    now renders only the mqtt password into secret.yaml.
  - Config drops advanced.pan_id/ext_pan_id/network_key/channel entirely; the
    network comes from the restored backup.

Runbook updated: Step 1 exports the Open Coordinator Backup from zigbee.db via
zigpy (non-disruptive — no second radio session); Step 2 stores it in OpenBao;
added an explicit device re-interview step (devices stay joined but Z2M's
database starts empty), and a PVC-clear note in rollback.

Verified live: coordinator has pan 0x8b2b, ext_pan_id fc7a735d08c15476,
channel 25; zigpy emits a valid open-coordinator-backup for it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
k.renner merged commit d72ca03fe8 into master 2026-07-23 10:33:46 +00:00
Sign in to join this conversation.