After a USB re-enumeration the rtw89 radio can come back as a fresh DOWN
netdev, dropped from br0, while the still-running hostapd never notices and
never exits — so Restart=always never fires. hostapd_cli keeps answering
state=ENABLED off stale in-memory state, so the watchdog considered the AP
healthy and left it dark (observed 2026-07-05: AP down ~16:41 until manual
hostapd restart).
Add link_healthy(): require the netdev to be operstate=up and still a port of
its bridge, alongside the existing state=ENABLED check. That catches the wedged
case the control socket can't see.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Starlink's USB ethernet shares a hub with the rtw89 Wi-Fi adapter; when Starlink
flaps, the hub re-enumerates and tears the radio down, so hostapd loses its
interface and exits. Two stock defaults left the AP dark: Restart=on-failure
misses clean exits, and the 5-in-10s start limit makes systemd give up during a
re-enumeration storm.
- hostapd-restart.conf drop-in: Restart=always, RestartSec=5, StartLimitIntervalSec=0
so hostapd retries forever until the interface returns (verified: SIGKILL -> back
to state=ENABLED in ~7s).
- van-ap-watchdog daemon: backstop for the case systemd can't see (hostapd running
but radio wedged). Polls hostapd_cli status; restarts hostapd if the iface is
present but not ENABLED, waits it out if the iface is mid-re-enumeration.
- hostapd.conf: add ctrl_interface so the watchdog can read the real AP state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>