Docs: README --force semantics; spec amendments for the pending conf, preflight and byte-identical netplan

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
This commit is contained in:
2026-09-23 20:01:45 -04:00
co-authored by Claude Sonnet 5
parent 722cad1ac3
commit 1ce4a30336
2 changed files with 8 additions and 2 deletions
+5 -2
View File
@@ -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 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 (`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 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 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 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` `/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`, 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 `present` (device and connection both resolved), `up`, `healthy`, `active` (holds the best default
@@ -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 <ts> …`). 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. - **§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 <ts> …`). 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. - **§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`. - 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:<STARLINK_IFACE>`, 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.