deploy: find cellular profile by id, no-auto-default NM conf, warn on NM enable failure

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 18:33:38 -04:00
co-authored by Claude Sonnet 5
parent e8fa2e025f
commit 7be698a5f1
3 changed files with 48 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
# NetworkManager must never auto-create "Wired connection" DHCP profiles on ports
# that netplan / ./deploy.sh --apply-network has not handed to it yet; otherwise it
# races systemd-networkd's DHCP on the Starlink port.
[main]
no-auto-default=*
+28 -8
View File
@@ -13,9 +13,12 @@
# ./deploy.sh --wan-plan [conf] # what the NetworkManager WAN provisioning would do (read-only, no root)
# ./deploy.sh render <file> # preview a templated file on stdout
# ./deploy.sh --redact # filter stdin, masking secret values (used by --diff; for tests)
# Idempotent. Netplan (wlan0 + Starlink NIC = NM-managed WANs; eth0 is a LAN
# port on br0) is NOT deployed here — reference copy in ap/50-van-wan.yaml,
# applied once manually (apply flaps uplinks). We do check it for drift below.
# VANLINK_NM_DIR=<dir> # test override: where existing NM *.nmconnection files are looked up (default /etc/NetworkManager/system-connections)
# Idempotent. Netplan (the NM-managed WANs; eth0 is a LAN port on br0) is never
# changed by a routine deploy (applying it flaps the uplinks). ENABLE_NM_WAN=0:
# applied manually from the reference copy in ap/50-van-wan.yaml, and checked for
# drift below. ENABLE_NM_WAN=1: a missing/differing WAN netplan is only warned
# about; it is applied by `./deploy.sh --apply-network` alone.
set -euo pipefail
cd "$(dirname "$(readlink -f "$0")")"
@@ -98,6 +101,19 @@ nm_wan_state_netplan() { # missing | differs | matches (the installed WAN netpl
else echo differs; fi
}
cellular_profile_exists() { # true if an NM profile with id=$CELLULAR_CONN_NAME exists (any file name, or known to nmcli)
local d=${VANLINK_NM_DIR:-/etc/NetworkManager/system-connections} f names
for f in "$d"/*.nmconnection; do
[ -f "$f" ] || continue
if grep -Fx "id=${CELLULAR_CONN_NAME}" "$f" >/dev/null 2>&1; then return 0; fi
done
if command -v nmcli >/dev/null 2>&1; then
names=$(nmcli -g NAME connection show 2>/dev/null) || names=
if printf '%s\n' "$names" | grep -Fx "${CELLULAR_CONN_NAME}" >/dev/null 2>&1; then return 0; fi
fi
return 1
}
check_rendered() { # check_rendered <src> <rendered-file> — fail on a leftover @TOKEN@
local left
left=$(grep -oE "$TOKEN_RE" "$2" | sort -u | tr '\n' ' ') || true
@@ -315,7 +331,7 @@ case "${1:-}" in
if [ -f /etc/netplan/10-dhcp-all-interfaces.yaml ]; then echo " armbian: /etc/netplan/10-dhcp-all-interfaces.yaml present -> would move aside"; else echo " armbian: /etc/netplan/10-dhcp-all-interfaces.yaml absent"; fi
if [ -z "${CELLULAR_APN:-}" ]; then
echo " cellular profile: skipped (no CELLULAR_APN)"
elif [ -e "/etc/NetworkManager/system-connections/${CELLULAR_CONN_NAME}.nmconnection" ]; then
elif cellular_profile_exists; then
echo " cellular profile: ${CELLULAR_CONN_NAME} apn=${CELLULAR_APN} exists"
else
echo " cellular profile: ${CELLULAR_CONN_NAME} apn=${CELLULAR_APN} would create"
@@ -643,6 +659,8 @@ install -D -m0644 power/10-vanlink-watchdog.conf /etc/systemd/system.conf.d/10-v
if [ "$ENABLE_NM_WAN" = 1 ]; then
echo "== networkmanager WANs =="
# In place before the package starts NM: no auto-created "Wired connection" profiles.
install -D -m0644 ap/nm-no-auto-default.conf /etc/NetworkManager/conf.d/00-van-no-auto-default.conf
if ! dpkg -s network-manager >/dev/null 2>&1; then
# Installed only now: the package starts NM, which manages Wi-Fi/gsm devices by
# default, so van-ap-unmanaged.conf (AP radios, LAN ports) must already be in place.
@@ -650,7 +668,8 @@ if [ "$ENABLE_NM_WAN" = 1 ]; then
DEBIAN_FRONTEND=noninteractive apt-get install -y network-manager \
|| { echo "deploy: apt-get install network-manager failed" >&2; exit 1; }
fi
systemctl enable --now NetworkManager ModemManager >/dev/null 2>&1 || true
systemctl enable --now NetworkManager ModemManager >/dev/null 2>&1 \
|| warn "failed to enable/start NetworkManager/ModemManager (check: systemctl status NetworkManager ModemManager)"
nmcli general reload conf 2>/dev/null || true
for nm_if in "$WIFI_5G_IFACE" "$WIFI_2G_IFACE" "$LAN_IFACE" ${ONBOARD_LAN_IFACE:-}; do
[ -e "/sys/class/net/$nm_if" ] || continue
@@ -660,7 +679,7 @@ if [ "$ENABLE_NM_WAN" = 1 ]; then
done
if [ -n "${CELLULAR_APN:-}" ]; then
nm_keyfile="/etc/NetworkManager/system-connections/${CELLULAR_CONN_NAME}.nmconnection"
if [ -e "$nm_keyfile" ]; then
if cellular_profile_exists; then
echo " cellular connection ${CELLULAR_CONN_NAME} exists — left unchanged"
elif [ -z "${CELLULAR_UUID:-}" ]; then
warn "CELLULAR_UUID is empty — not creating the cellular keyfile $nm_keyfile"
@@ -670,8 +689,9 @@ if [ "$ENABLE_NM_WAN" = 1 ]; then
echo " created cellular connection ${CELLULAR_CONN_NAME} (apn ${CELLULAR_APN}) — no modem needed"
fi
fi
if [ "$(nm_wan_state_netplan)" != matches ]; then
warn "WAN netplan is not provisioned/up to date: run ./deploy.sh --apply-network (backs up /etc/netplan and rolls back automatically if the uplink does not come back)"
nm_np_state=$(nm_wan_state_netplan)
if [ "$nm_np_state" != matches ]; then
warn "WAN netplan is $nm_np_state (not provisioned/up to date): run ./deploy.sh --apply-network (backs up /etc/netplan and rolls back automatically if the uplink does not come back)"
fi
fi
+15
View File
@@ -242,4 +242,19 @@ u2=$(VANLINK_CONF=hosts/wan.conf ./deploy.sh render ap/cellular.nmconnection | g
[ -n "$u1" ] && [ "$u1" != "uuid=" ] && [ "$u1" = "$u2" ] && ok "cellular uuid non-empty and stable across hosts" || bad "cellular uuid: '$u1' vs '$u2'"
[ "$(grep -v '^[[:space:]]*#' deploy.sh | grep -c uuidgen)" = 0 ] && ok "deploy.sh does not call uuidgen" || bad "deploy.sh calls uuidgen"
# 17b. an existing cellular profile is found by id, whatever its file name
nmd=$(mktemp -d); nme=$(mktemp -d)
printf '[connection]\nid=Koodo\ntype=gsm\n' > "$nmd/weird-file-name.nmconnection"
p=$(VANLINK_NM_DIR=$nmd VANLINK_CONF=hosts/van.conf ./deploy.sh --wan-plan 2>&1)
echo "$p" | grep -q 'cellular profile: Koodo apn=sp.koodo.com exists' && ok "wan-plan: profile found under another file name" || bad "wan-plan: profile under other file name not found"
if command -v nmcli >/dev/null 2>&1 && nmcli -g NAME connection show 2>/dev/null | grep -Fxq Koodo; then
ok "wan-plan would-create assertion skipped (this machine's NM lists Koodo)"
else
p=$(VANLINK_NM_DIR=$nme VANLINK_CONF=hosts/van.conf ./deploy.sh --wan-plan 2>&1)
echo "$p" | grep -q 'cellular profile: Koodo apn=sp.koodo.com would create' && ok "wan-plan: empty NM dir -> would create" || bad "wan-plan: empty NM dir should say would create"
fi
rm -rf "$nmd" "$nme"
# 17c. NM must not auto-create "Wired connection" profiles
[ "$(grep -v '^[[:space:]]*#' ap/nm-no-auto-default.conf 2>/dev/null | grep -v '^[[:space:]]*$')" = "$(printf '[main]\nno-auto-default=*')" ] && ok "nm-no-auto-default.conf is [main] + no-auto-default=*" || bad "ap/nm-no-auto-default.conf missing or wrong"
exit "$fail"