Files
esh-pfi-infrastructure/docs/pfi/ipv6-naming-scheme.md
T
vh 4e83395ddf docs(ipv6): all three esh-server hosts now carry the segment name
esh-pve-nas and esh-vm-db join esh-docker-vm on 4411:b105, at
:50:55 and :50:60 respectively, each applied by the same prefix-deriving
if-up.d hook so the last two groups read straight off the IPv4 address.

Two obstacles are recorded because both will recur. The Proxmox node had
link-local only despite every relevant sysctl appearing correct, because
its bridge carries per-interface forwarding and the kernel ignores router
advertisements on a forwarding interface unless accept_ra is explicitly
two rather than one. The fix takes the advertised prefix while declining
the default route, so the hypervisor gains an address without any change
to how it routes; this was verified after applying, with the v6 default
route count still at zero.

The database VM refuses key authentication for the privileged accounts
and its unprivileged login cannot escalate without a password, so the
hook went in through the QEMU guest agent from the hypervisor, which
executes as root inside the guest. The document notes the base64
indirection needed to get a multi-line script through intact.
2026-08-23 22:39:39 -07:00

7.3 KiB
Raw Blame History

ESH IPv6 naming scheme

Every ESH LAN carries an eight-hex-digit phrase as the first half of the interface identifier. Picked 2026-08-18/19. This file is the canonical record.

Why this file exists. The scheme originally lived as a single line in persistent-memory.md and was silently deleted by a memory: snapshot commit (837fa36). Recovering it took a hunt through session transcripts to find the commit that had held it. A naming convention is not temporal state — it belongs in a document, so it now is one.

The names

network hex reads as
Default 4BA5:3417 A BASE FOR IT
esh-mgmt 15DA:B055 IS DA BOSS
esh-server 4411:B105 FOR ALL BIOS
esh-userland CAFE:4411 CAFE FOR ALL
esh-iot 4DBA:D107 FOR DA BAD IOT
esh-cameras 1533:FACE5 I SEE FACES
(reserved) DMZ 4411:DBAD FOR ALL DA BAD

The DMZ name is claimed against a network that does not exist yet — there is no DMZ on the ESH UDM. Do not reuse it.

Substitutions are the standard hexspeak set: 0→O, 1→I/L, 5→S, plus letters that are already native hex (AF). Anything outside 0-9a-f is not expressible — b0ss and c00l do not work, which is why the set above uses B055 and avoids c00l entirely.

House style, arrived at rather than designed: eight digits, and a complete phrase rather than a single word. Words are allowed to straddle the group boundary (4DBA:D107 is 4·D·BAD·107); the phrase reads through the colon.

Address structure

2607:73c0:402:1d02 : 4411:b105 : 50 : 45
└──── ISP /64 ────┘ └ segment ─┘ └ 10.0.50.45 ┘
  • Prefix — Cityside's, not ours to name. ESH holds a /56 (2607:73c0:402:1d00::/56, 256 × /64); the subnet id is assigned by UniFi's ipv6_pd_prefixid. esh-cameras is 1d00, esh-server is 1d02.
  • Segment word pair — 32 bits, from the table above.
  • Host — the last two IPv4 octets, written as literal digits so they read straight off the address. 10.0.50.45:50:45.

The scheme lives entirely in the interface identifier, so it is delegation-size independent. It works identically on a /56, a /48, or NH3's single /64. It never competes with the subnet id, which is far too small to hold a word (8 bits at ESH — two hex digits).

Note: 4411:b105:50:45 fills all four host groups, so there is no :: in these addresses. Writing ...::4411:b105:50:45 is malformed and will be rejected.

What can and cannot carry a name

slot nameable?
/64 subnet id (ipv6_pd_prefixid) No — 8 bits at ESH, two hex digits, no room for a word
the gateway's own address No — fixed at ::1 by UniFi, no field for it
a UniFi client reservation No — UniFi has no IPv6 equivalent of use_fixedip
a host taking its own address Yes — this is the one that works

The original note concluded these names could never appear in a dig or ip -6 output. That is wrong. The first three rows are correct, but they only establish that UniFi cannot assign the address. A Linux host can simply take one within its own advertised prefix, and the router gets no vote. Appliances with no shell — cameras, most IoT — genuinely cannot, so 1533:FACE5 and 4DBA:D107 are likely to stay documentation-only.

Applying it to a host

Do not use an iface … inet6 static stanza: on Debian that sets accept_ra=0, killing SLAAC and the IPv6 default route — a good way to strand a headless box. Use an if-up.d hook that derives the live prefix instead.

Live example, /etc/network/if-up.d/ipv6-scheme-addr on esh-docker-vm:

#!/bin/sh
[ "$IFACE" = ens18 ] || exit 0
(
  i=0
  while [ $i -lt 30 ]; do
    PFX=$(ip -6 -o addr show dev "$IFACE" scope global 2>/dev/null \
          | awk '{print $4}' | cut -d/ -f1 | head -1 | cut -d: -f1-4)
    if [ -n "$PFX" ]; then
      ip -6 addr replace "${PFX}:4411:b105:50:45/64" dev "$IFACE" && exit 0
    fi
    sleep 2
    i=$((i + 1))
  done
) >/dev/null 2>&1 &
exit 0

Three deliberate properties:

  • The prefix is derived, never hardcoded — self-heals if Cityside re-delegates.
  • Backgrounded with a retry — SLAAC may not have landed when if-up.d runs, and a hook that blocks or fails would stall interface bring-up.
  • Additive/etc/network/interfaces already sources interfaces.d/; nothing existing is edited, and removal is one rm.

Remaining gap: a mid-life prefix change is only picked up at the next interface-up. A timer would close it; not worth building until the prefix is observed to actually move.

Deployed

All three Linux hosts on esh-server now carry the segment name, with the last two groups reading straight off their IPv4 address:

host address v4 applied via
esh-docker-vm (AdGuard) 2607:73c0:402:1d02:4411:b105:50:45 10.0.50.45 if-up.d on ens18
esh-pve-nas 2607:73c0:402:1d02:4411:b105:50:55 10.0.50.55 if-up.d on vmbr0
esh-vm-db 2607:73c0:402:1d02:4411:b105:50:60 10.0.50.60 if-up.d on ens18

esh-docker-vm's is load-bearing, not decorative: the ESH UDM advertises an IPv6 resolver to clients via RDNSS, macOS prefers it over the DHCPv4-supplied one, so whatever sits there is what resolves *.internal for every Mac on the network. It previously pointed at AdGuard's MAC-derived SLAAC address, which would have broken if that VM's NIC ever changed. Both esh-userland and esh-server now advertise the scheme address instead (dhcpdv6_dns_auto=false + dhcpdv6_dns_1=<address>), verified on the wire by soliciting an RA and parsing option type 25.

⚠ Proxmox bridges need accept_ra=2 or SLAAC never runs

esh-pve-nas had link-local only despite accept_ra=1, autoconf=1 and IPv6 enabled — every sysctl looked correct. The cause: vmbr0.forwarding = 1 (Proxmox sets per-interface forwarding on bridges), and the kernel ignores RAs on a forwarding interface unless accept_ra is explicitly 2. accept_ra=1 means "accept only if not forwarding", so it silently did nothing.

Fixed in /etc/sysctl.d/60-ipv6-accept-ra.conf on that host:

net.ipv6.conf.vmbr0.accept_ra = 2
net.ipv6.conf.vmbr0.accept_ra_defrtr = 0

accept_ra_defrtr=0 is deliberate — it takes the advertised prefix (so SLAAC configures an address) while declining the default route, so a hypervisor gains an IPv6 identity with no change to its routing behaviour. Verified after: SLAAC address present, v6 default routes still 0, v4 intact.

Expect the same on any other Proxmox node when its LAN gets IPv6.

Getting into a host with no direct root

esh-vm-db refuses key auth for root and infra-ops, and lkraven's sudo wants a password. It is VMID 101 on esh-pve, and the QEMU guest agent runs as uid 0 inside it, so the hook was installed with:

qm guest exec 101 -- /bin/sh -c 'echo <base64> | base64 -d > /etc/network/if-up.d/... '

base64 because quoting a multi-line script through two SSH layers mangles it. Worth remembering as the general path for guests whose credentials are not vaulted.

Natural next candidates, both on esh-server and both real Linux hosts: esh-pve-nas…:4411:b105:50:55, esh-vm-db…:4411:b105:50:60.