diff --git a/README.md b/README.md index b63eff5..f73483c 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,14 @@ Hosts with `ENABLE_NM_WAN=1` (`hosts/*.conf`) run their uplinks (Starlink, Wi-Fi NetworkManager. `deploy.sh` installs the packages and the cellular NM connection (`CELLULAR_CONN_NAME`/`CELLULAR_APN`), but a routine deploy never touches `/etc/netplan/*` or flaps an uplink; it only warns when the WAN netplan is missing or differs. Apply it with -`sudo ./deploy.sh --apply-network` (add `--force` to override a blocking status): a detached +`sudo ./deploy.sh --apply-network` (`--force` also overrides a blocking status, the preflight — port present, +host file matches the hostname — and the refusal to replace a WAN netplan that differs): a detached helper installs the netplan, gates on uplink health and rolls back automatically on failure. Its log is `/var/log/vanlink-apply-network.log` and its status line is in `/var/lib/vanlink/apply-network.status` (`ok|running|rolled-back|rollback-failed`). `./deploy.sh --wan-plan` -shows, read-only, what the provisioning would do. `--post-check` reports the last apply status. +shows, read-only, what the provisioning would do. `--post-check` reports the last apply status. Until a host's WAN netplan is applied, the routine deploy also keeps +NetworkManager off the uplink with `/etc/NetworkManager/conf.d/zz-van-wan-pending.conf` (only while the netplan is +*missing*; `--wan-plan` shows it) — the apply removes it. Live WAN state: `cat /run/van-failover/state.json` lists each WAN with `device`, `connection`, `present` (device and connection both resolved), `up`, `healthy`, `active` (holds the best default diff --git a/docs/superpowers/specs/2026-09-23-nm-wan-provisioning-design.md b/docs/superpowers/specs/2026-09-23-nm-wan-provisioning-design.md index abb59a3..c2519b6 100644 --- a/docs/superpowers/specs/2026-09-23-nm-wan-provisioning-design.md +++ b/docs/superpowers/specs/2026-09-23-nm-wan-provisioning-design.md @@ -132,3 +132,6 @@ has none). - **§4 `--apply-network`** changes nothing under `/etc/netplan` itself. It validates (NM installed and running, `van-failover` unit present, no apply already running, last status not `running`/`rollback-failed` unless `--force`), no-ops when the netplan already matches and no Armbian file exists (unless `--force`), takes a per-run backup plus a sticky pristine backup `/var/backups/vanlink-netplan-orig`, renders to `/run`, and launches a detached transient unit. The helper installs the file, moves the Armbian file aside, applies, and gates: **stage 1** (≤60 s): apply succeeded, NM device state `100 (connected)` with a `netplan-*` connection, IPv4 address, gateway (`IP4.GATEWAY`, else the DHCP lease's `routers` option, because a never-default profile leaves `IP4.GATEWAY` empty) reachable on-link; **stage 2**: restart `van-failover`, then default route + `ping 1.1.1.1` (≥120 s). Failure → checked rollback (restore, re-apply, connectivity re-check, `ROLLBACK FAILED` if not restored; a last-resort reboot only when the rollback itself failed). Timeouts, a TERM/INT/HUP trap that restores exactly once, budgets derived in one block, log `/var/log/vanlink-apply-network.log`, status file `/var/lib/vanlink/apply-network.status` (`running|ok|rolled-back|rollback-failed …`). Not built: a boot-time recovery unit (power loss mid-apply boots the new config ungated and leaves status `running`), an arping fallback for gateways that do not answer ICMP. - **§6 post-check**: the failover-state rule is refined: `present` in `van-failover`'s state means "has an active NM connection", so an unplugged or out-of-range uplink is normal in a van. Post-check warns only when the WAN's device has link (`carrier` 1) but `present` is false; it also reports the last `--apply-network` status (non-`ok` warns) and checks NM/ModemManager, NM-unmanaged AP/LAN ports, the cellular profile and the netplan state. - Routine deploys also install missing REQUIRED packages via apt (spec §2) and never touch `/etc/netplan`. +- **Uplink stays with networkd until the handover.** While the WAN netplan is *missing*, the routine deploy installs `/etc/NetworkManager/conf.d/zz-van-wan-pending.conf` (`unmanaged-devices+=interface-name:`, from `ap/nm-uplink-pending.conf`) so NM, freshly installed, does not adopt the uplink as "connected (externally)" and van-failover does not start steering it. It is removed when the netplan `matches`, and deliberately left alone when it `differs` or is `unreadable` (a host whose uplink NM already manages, such as the Pi 5 after any template edit, must not lose it). The helper removes it just before `netplan apply` and restores it on rollback. This relies on NM honouring `unmanaged-devices+=` after `nmcli general reload conf` (not live-tested; if ignored the behaviour degrades to "NM adopts the uplink early", not an outage). +- **`--apply-network` preflight** (die unless `--force`): the uplink port exists on this host, and the resolved host file's name matches `hostname -s`; stage 2 additionally requires van-failover's own `proto static` default route on the port. A netplan file the current user cannot read is reported `unreadable` (not `differs`) by the read-only commands. +- **The rendered `ap/50-van-wan.yaml` must stay byte-identical to what live hosts have installed** (measured on the Pi 5): comments in `ap/50-van-wan*.yaml` are part of the rendered bytes, so editing them makes every host read `WAN netplan differs`. Check 14 pins the Pi render against commit 3d117e7.