0bbdaf9083
I described ea:f6:0a:ca:f5:b4 as "locally administered, no OUI" and treated it as the class of MAC that may regenerate at boot. ha-dev corrected it and the correction verifies: the device advertises e8:f6:0a:ca:f5:b4 over mDNS, which differs in exactly the locally-administered bit, and E8:F6:0A is registered to Espressif Inc. in the IEEE registry while EA:F6:0A resolves to nothing. That is the standard ESP32 pattern — one factory base MAC in eFuse, sibling interface MACs derived deterministically — so the reservation is keyed correctly and cannot drift on its own. The PoE-cycle test still stands and is now corroborating evidence rather than the only evidence. The residual risk narrows to a firmware change to the derivation scheme. Also from ha-dev: tcp/7638 is open alongside 6638; mDNS crosses the VLAN boundary so HA rediscovers without help; and HA's pending smlight config flow is keyed on the mDNS service name, which did not change, so a stale flow may still hold the dead 10.0.10.58 and should be dismissed rather than confirmed. ha-dev declined the dns: resolver fix on their stack — configuring by IP costs them nothing and the entry would couple HA name resolution to AdGuard uptime for no present benefit.
120 lines
6.2 KiB
Markdown
120 lines
6.2 KiB
Markdown
# SLZB-MR1U Zigbee/Thread coordinator — ESH IoT VLAN
|
||
|
||
Moved onto the IoT VLAN 2026-09-04 and handed to Home Assistant.
|
||
|
||
device SMLIGHT SLZB-MR1U ("SLZB OS", firmware build Jan 27 2026 11:19:04)
|
||
address 10.0.90.10 slzb-mr1u.esh.internal
|
||
network esh-iot, VLAN 90, 10.0.90.0/24
|
||
switch USW Pro XG 10 PoE - ESH-Media (10.0.250.164), port 4, PoE ~1.0-1.5 W
|
||
zigbee tcp/6638 web UI tcp/80 also open: tcp/7638
|
||
consumer Home Assistant container at 10.0.50.46 (esh-docker-vm, macvlan on VLAN 50)
|
||
|
||
## The shape, and why it is this shape
|
||
|
||
**The address lives on the UDM as a DHCP reservation, not on the device.** Same
|
||
ruling as pfi-gx10: a reservation moves with the hardware, a device-side static
|
||
goes stale the moment anything changes. The device stays on DHCP and knows
|
||
nothing about its own address.
|
||
|
||
`10.0.90.10` sits deliberately **below** the esh-iot DHCP pool
|
||
(`10.0.90.40–250`), so the pool can never hand it to something else. Note the
|
||
one pre-existing reservation on this network — the Brother printer at
|
||
`10.0.90.125` — is *inside* the pool; the out-of-pool convention starts here.
|
||
|
||
## The MAC is a derived ESP32 interface address — stable, not fragile
|
||
|
||
ethernet (what DHCP sees) ea:f6:0a:ca:f5:b4 LA bit SET
|
||
base (what mDNS advertises) e8:f6:0a:ca:f5:b4 Espressif Inc. (verified against IEEE)
|
||
|
||
⚠ **An earlier version of this runbook called the MAC "locally administered, no
|
||
OUI" and treated it as the kind that may regenerate at boot. That framing was
|
||
wrong and ha-dev corrected it.** The two addresses differ in exactly one bit —
|
||
the locally-administered bit — which is the standard ESP32 pattern: one factory
|
||
base MAC in eFuse, sibling interface MACs derived from it deterministically. The
|
||
Ethernet interface gets the derived `ea:` variant; mDNS advertises the base
|
||
`e8:`. `E8:F6:0A` resolves to **Espressif Inc.** in the IEEE registry and
|
||
`EA:F6:0A` correctly resolves to nothing, which is what confirms the two are the
|
||
same address wearing different bits rather than two unrelated MACs.
|
||
|
||
So the reservation is keyed on the right address and the derivation cannot drift
|
||
on its own. Independently consistent with the test below.
|
||
|
||
**Tested anyway, and it was free:** the PoE power-cycle needed to make the device
|
||
re-DHCP onto the new VLAN is also a reboot. It came back on **exactly
|
||
10.0.90.10** — which only happens if the reservation matched.
|
||
|
||
The residual risk is real but narrow: only a firmware update that changed the
|
||
derivation scheme would move it. Symptom if that ever happens — the coordinator
|
||
reappears somewhere in `10.0.90.40–250`.
|
||
|
||
## ⚠ port_overrides is a WHOLE-ARRAY PUT
|
||
|
||
ESH-Media carried 8 port overrides. Anything omitted from the PUT is deleted, so
|
||
the array was read, backed up, modified in exactly one field, diffed to prove
|
||
only that field changed, and written back. Read-back confirmed 8 in, 8 out, ports
|
||
2/3/5/6/8/9 still on esh-userland and port 7 still locked down.
|
||
|
||
## ⚠ UniFi's client record lies during the transition — do not read it as breakage
|
||
|
||
While the port was cycling, `stat/sta` reported the client on **the UDM's own
|
||
SFP+ uplink** with its old VLAN-10 address and a frozen uptime, and `port_table`
|
||
showed ESH-Media port 4 down at 0 W. Both were transitional artifacts. The
|
||
authoritative check is the device itself: the page served at the new address was
|
||
**byte-identical** (same 25,413 bytes, same `ETag: "Jan 27 2026 11:19:04"`) to the
|
||
one captured before the move. Fingerprint the endpoint; do not trust the
|
||
controller's cache mid-change.
|
||
|
||
## ⚠ Home Assistant CANNOT resolve `.internal` — give it the IP
|
||
|
||
Verified from inside the container, and it is **pre-existing, not caused by this
|
||
change**:
|
||
|
||
slzb-mr1u.esh.internal FAIL homepage.esh.internal FAIL
|
||
esh-docker-vm.esh.internal FAIL google.com OK
|
||
|
||
The container's resolver is Docker's embedded `127.0.0.11`, whose upstream does
|
||
not include the fleet AdGuard at `10.0.50.45`. Public DNS resolves, so it is
|
||
reaching *an* upstream — just not ours. **Configure HA against `10.0.90.10`.**
|
||
|
||
The fix, if wanted, is a `dns:` entry on the HA service pointing at `10.0.50.45`
|
||
plus a container restart — a change to a live home-automation stack, so it is
|
||
ha-dev's call, not an incidental edit.
|
||
|
||
Separately, note `esh-iot` itself hands out `1.1.1.1` / `8.8.8.8` by DHCP, so
|
||
devices *on* VLAN 90 cannot resolve `.internal` either. Irrelevant here — the
|
||
coordinator never initiates — but relevant to anything on that VLAN that does.
|
||
|
||
## Reachability is already open, and was proven before the move
|
||
|
||
VLAN 50 → VLAN 90 needed no firewall work. Confirmed from the actual consumer —
|
||
`docker exec homeassistant` — against pre-existing IoT devices (the printer and a
|
||
Tasmota plug) *before* touching anything, then against the coordinator after.
|
||
Testing from the Docker **host** would have proven the wrong thing: HA runs on a
|
||
macvlan interface with its own address, not the host's.
|
||
|
||
## Rollback
|
||
|
||
Backups of both mutated objects are transient (session scratch), so the durable
|
||
path is: set ESH-Media port 4's `native_networkconf_id` back to
|
||
`687985eae5d15b673cef1a73` (esh-userland), clear `use_fixedip` on the client, and
|
||
drop the `slzb-mr1u` line from `dns/internal.yaml` + re-run `scripts/dns-sync.py`.
|
||
|
||
## mDNS crosses the VLAN boundary — and that has one sharp edge
|
||
|
||
`esh-iot` has `mdns_enabled: true`, so the coordinator's advert reaches the
|
||
Home Assistant container across VLANs and HA rediscovers it without help.
|
||
|
||
⚠ **HA's pending `smlight` config flow is keyed on the mDNS service name, which
|
||
did NOT change across the move — so the same flow id survived and may still hold
|
||
the dead 10.0.10.58.** Dismiss and re-discover rather than confirming the stale
|
||
flow. This is the kind of thing that makes a device look broken after a clean
|
||
network change. (Reported by ha-dev, 2026-09-04.)
|
||
|
||
## Resolver: ha-dev declined the `dns:` fix, deliberately
|
||
|
||
Offered and turned down: pointing the homeassistant service at `10.0.50.45`
|
||
would couple HA's name resolution to AdGuard's uptime for a benefit they do not
|
||
currently need, since configuring by IP costs them nothing. Recorded on their
|
||
side as a standing foot-gun with the fix written down. Revisit only if something
|
||
inside the container actually needs a name.
|