Snapshot of the Pi 'wan' Claude memory: wayback van-router build notes, ZT DNS, HA VM, LAN port, and the Pi port memory updated for the 2026-07-06 USB hub move (AP live on the Pi) and the cockpit-bridge fd-limit fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
12 KiB
name, description, metadata
| name | description | metadata | ||||||
|---|---|---|---|---|---|---|---|---|
| wayback-campervan-ap | wayback campervan router/AP — hand-rolled hostapd (RTL8852BU, 80MHz/HE) + dnsmasq + nftables; NM owns WAN; eventual Starlink+4G multi-WAN |
|
Goal: turn wayback (Asus UX391U laptop, Ubuntu 24.04) into a campervan hub/router/AP. Eventual WAN = Starlink (ethernet) + 4G/5G modem with failover; LAN = wifi AP for clients. See wayback-fan-max-ec-latch.
SOURCE OF TRUTH: ~/vanlink/ on wayback (2026-06-28). Consolidated working dir, Claude Code now installed ON wayback so future van-router dev happens there. Contains README.md (full architecture + gotchas + ops), deploy.sh (copies files→system locations, idempotent), and copies of every config/script grouped: ap/ failover/ dns/ cockpit/vanrouter/. Edit there, sudo ./deploy.sh. This memory is the why/history; the README is the operational reference.
Architecture (2026-06-28): hand-rolled hostapd + dnsmasq + nftables, NM owns WAN. Decided against NM-hotspot (capped at HT20/20MHz) and against RaspAP (RPi-OS/dhcpcd tool; bare-metal installer would enable dhcpcd → fight NM, and disable systemd-resolved → unsafe on this x86/Ubuntu/NM box).
Radios:
- phy1 = Realtek RTL8852BU (
0bda:b832, driverrtw89_8852bu, ifacewlxc83a35a4ee55) = AP radio. Confirmed empirically: AP mode + VHT80 + HE (WiFi-6) at 80MHz works. - phy0 = Intel 8265 (
wlp1s0) = mgmt/uplink, assoc home SSIDWapana(192.168.10.27). - 2.4GHz AP added 2026-07-06 (commit
e652b0f): Linksys WUSB6300v2 (13b1:0045, RTL8822BU, driverrtw88_8822bu, ifacewlxd8ec5e2faa8c). Same SSID/PSK, ch6 HT20, bridged into br0. Own hostapd instance (hostapd-2g.service+van-ap-watchdog-2g) so one radio's USB wedge can't kill the other;van-ap-watchdognow takes conf+unit args./etc/modprobe.d/rtw88.conf:disable_lps_deep=Y(PS gotcha analog) +switch_usb_mode=N(blocks driver's USB2→3 self-upgrade only — the dongle sits in a USB3 port and still enumerates SuperSpeed; move to a USB2 port if 2.4GHz range/interference disappoints). Shares Bus 002 with an RTL8153 — watch for the hub-contention signature. Cockpit vanrouter plugin shows both bands with per-band Restart (const APSlist in vanrouter.js, commitdb16964).
Management/recovery paths (3): ethernet enx00e04c3600ab 192.168.10.235 (USB RTL8152; now PRIMARY default route metric100 — previews Starlink-on-eth), wifi wlp1s0 .27 (metric600), ZeroTier ztuga7c2kh 192.168.196.22.
Deployed config (all enabled at boot):
- hostapd
/etc/hostapd/hostapd.conf: SSIDVanLink, ch149 VHT80/HE, WPA2-PSK (user changed it 2026-06-28; valid = 8-63 chars),country_code=CA./etc/default/hostapdDAEMON_CONF set. (was masked during testing — now unmasked/enabled.) - rtw89 power-save MUST be disabled for AP stability:
/etc/modprobe.d/rtw89.conf=options rtw89_core disable_ps_mode=Y. ROOT CAUSE of "SSID disappears after a few min": when the last client idles out (hostapd 5-min inactivity timer), rtw89 low-power mode sleeps the radio and STOPS beaconing until restart. To apply live you must unload the WHOLE stack so rtw89_core reloads (modprobe -r rtw89_8852bu rtw89_usb rtw89_8852b rtw89_8852b_common rtw89_corethenmodprobe rtw89_8852bu; -r of just the leaf does NOT cascade to core). Verifycat /sys/module/rtw89_core/parameters/disable_ps_mode= Y. - GOTCHA: Ubuntu's hostapd does NOT support
noscan(rejects "unknown configuration item 'noscan'" → service fails). Don't add it. Restarts occasionally log stuck at HT_SCAN but still beacon — trustiw dev <ap> info(ssid+channel+width present = beaconing), not the journal ENABLED line. - AP iface unmanaged by NM via
/etc/NetworkManager/conf.d/van-ap-unmanaged.conf; static IP 10.42.0.1/24 via systemd-networkd/etc/systemd/network/10-van-ap.network(ConfigureWithoutCarrier=yes). - dnsmasq dedicated instance (binary from dnsmasq-base, NOT the distro service): config
/etc/van-ap/dnsmasq.conf(interface=AP, bind-dynamic → no clash with systemd-resolved on 127.0.0.53), unitvan-ap-dnsmasq.service. DHCP 10.42.0.10-254/12h, gw+dns 10.42.0.1. - nftables
/etc/nftables.conf: own tablevan_router_nat(create+delete idiom, no global flush) masquerading10.42.0.0/24 oifname != AP→ covers any WAN.ip_forward=1persisted in/etc/sysctl.d/99-van-router.conf. - regdomain.service (oneshot
iw reg set CA, Before=NetworkManager) — needed: country 00 only allows 5GHz ch36/48; CA unlocks ch149-161 @30dBm no-DFS. - Cockpit on :9090 still installed (system/WAN monitoring; canNOT edit wifi — cockpit-networkmanager has no wifi UI).
To change AP: edit /etc/hostapd/hostapd.conf + systemctl restart hostapd. DHCP: /etc/van-ap/dnsmasq.conf + restart van-ap-dnsmasq.
Reboot-persistence VERIFIED (2026-06-28): after systemctl reboot all 4 services auto-started, regdomain CA applied, disable_ps_mode=Y from boot, VanLink beaconing 80MHz, ethernet .235 recovery path back. (Lesson: avoid hot-reloading rtw89_8852bu; reboot to apply module options.)
RESOLVED — load-hang was USB hub contention. Symptom: Android Speedtest (good numbers, then dropped), SSID invisible while hostapd still "active". Fatal dmesg signature = c2h reg timeout + Polling beacon packet empty fail (chip↔host USB comms hang → beacon TX stops); recovers via systemctl restart hostapd. Root cause: the dongle was on a shared USB-2 hub (1-1.4) with the r8152 ethernet + a camera; under load the shared bus starved chip comms. FIX (2026-06-28): moved Realtek to its own root USB-C port (1-3). After move: 3 Speedtests completed, ZERO c2h/beacon-fail errors, 2 clients at 80MHz HE (WiFi-6) >1Gbit/s PHY, tx-failed ~0. The lone post-move timed out to flush queues is BENIGN (doesn't drop AP); the c2h+beacon-fail combo is the fatal one.
Caveats: (1) the 8852BU is USB-2.0-native — enumerates 480M even on a USB-C/USB-3 port (USB3 can't speed a USB2 device); ~280Mbps real USB ceiling = fine for Starlink/4G van WAN but that's the aggregate cap. (2) In the van build keep the AP dongle and the WAN ethernet on separate USB controllers — don't re-share a hub or the c2h hang returns. (3) Interface name is MAC-based (wlxc83a35a4ee55), survives port moves; all configs reference the name. Unused fallback if it ever regresses: pivot AP to Intel 8265 (PCIe, WiFi5/ac 80MHz).
Note: iw sometimes reports control channel as 153 (not the configured 149) within the same 149-161/80MHz block — cosmetic, clients connect fine.
Pending / next steps:
- Idle-survival still being confirmed: original symptom was beacon dropping ~5min after last client idled out (hostapd 5-min inactivity deauth). Watching across an idle cycle post-fix. Strongest real test = connect a device, use it, let it idle past 5 min, confirm SSID stays visible.
- Verify: client association → DHCP + internet (basic assoc seen; full internet path not yet end-to-end tested).
- Multi-WAN failover BUILT + TESTED (2026-06-28). Daemon
/usr/local/sbin/van-failover(Python), config/etc/van-failover/config.json, unitvan-failover.service(Restart=always, enabled). 3 WANs, priority = WiFi(wlp1s0)=100 → Starlink/eth(enxd8ec5eeb3512)=200 → 4G(Koodo gsm)=300 (user chose WiFi-first to save Starlink; 4G auto last-resort). How it works: probes each WAN's real internet every 4s via HTTP-204 check (catches "link up no internet" + captive portals), demotes a failed WAN by raising its NM route-metric (+10000) so kernel routes via next-best healthy WAN; auto fail-back with hysteresis (3 fail→down, 2 ok→up). Writes/run/van-failover/state.json(0644) → Cockpit "WAN Failover" card reads it. NAT (nftables oifname != AP) follows automatically; nothing else needed. Tested with an nft block on wlp1s0:80 → failed over to Starlink in ~30s, failed back in ~20s.- GOTCHA: per-WAN probing needs
curl --interface if!<dev>(explicit SO_BINDTODEVICE) — plain--interface <name>binds source IP but still routes via the default WAN, so all probes test the same path. rp_filter is already 2 (loose) which is required. Probe all (WAN×url) pairs CONCURRENTLY else a dead WAN takes N×timeout serially (was why first failover test looked broken).ping -Ito test eth is unreliable here (ICMP lossy on the gateway) — use the curl-204 check. - Absent WANs (modem unplugged → Koodo has no device): daemon skips probing, just sets the profile's base metric so it lands right when it connects. ModemManager active +
Koodogsm profile autoconnect=yes already present; lights up when USB modem arrives. - CRITICAL fix (r8152 USB-ethernet flapping): the daemon must change route-metrics via
ip route(del/add default at new metric), NOTnmcli device reapply— reapply RESETS the r8152 carrier (verified: reapply=2 carrier events, ip-route=0), causing ~10s ping drops + a feedback loop (transient probe fail → reapply → carrier reset → more fails). Daemon keeps the NM profile metric in sync (nmcli con mod, no reapply) so NM re-assertions don't drift. Also: disable EEE on the eth adapter or its idle (backup, no-traffic) link parks and probes fail — done via NM dispatcher/etc/NetworkManager/dispatcher.d/50-disable-eee(runsethtool --set-eee <if> eee offon up; ethtool setting doesn't persist otherwise). Also: arp_ignore=1 / arp_announce=2 (/etc/sysctl.d/99-van-arp.conf) to stop ARP flux when two WANs share a subnet (a home-LAN test artifact; in the van Starlink+wifi are on different subnets). After all three: eth stable, failover/failback clean, 0 carrier resets even when eth becomes active. - To tune: edit config.json (probe_interval/timeout, thresholds, probe_urls, wans list) +
systemctl restart van-failover. WAN list keys eth/wifi bydevice, cellular byconnectionname.
- GOTCHA: per-WAN probing needs
- Cockpit plugin BUILT (basic v1, 2026-06-28):
/usr/share/cockpit/vanrouter/(manifest.json menu "Van Router" + index.html + vanrouter.css + vanrouter.js). Pure static + cockpit.js: read-only status viacockpit.spawnas logged-in user (iw info/station dump, nmcli device status,ip -j route/addr, systemctl is-active); mutating actions use{superuser:"require"}(polkit). Features: AP panel (hostapd state, SSID/ch/width, client list) + Restart AP; WAN panel (per NM ethernet/wifi device: state/IP/route-metric, ★=active default) with Up/Down (nmcli device connect/disconnect) and Prefer (sets chosen route-metric=50, others=200,nmcli device reapply). AP iface name hardcoded as const AP. Confirmed discovered viacockpit-bridge --packages. To see it: reload Cockpit browser / re-login; enable Administrative access for the buttons. Now also has a "WAN Failover" card reading/run/van-failover/state.json(active egress + per-WAN priority/device/up-down/metric). Source only on host + session scratchpad (not in a repo). - Evaluated & REJECTED
apsetup-cockpit(github cyberorg/apsetup-cockpit, 2026-06-28): NM-hotspot-based AP tool (uses an NM dispatcher90apnmdispatcher+ its own dnsmasq + NAT; needsDNSStubListener=no). Doesn't fit: (1) NM-created AP on rtw89 = HT20/20MHz, throws away our 80MHz/HE; (2) it owns the AP (own NM conn/dnsmasq/NAT) → collides with our hand-rolled hostapd+van-ap-dnsmasq+nftables + AP-iface-unmanaged; (3) disables resolved stub host-wide (we kept resolved via bind-dynamic). If a web AP-config form is wanted, ADD an SSID/channel/PSK card to our own vanrouter plugin editing /etc/hostapd/hostapd.conf + restart hostapd — keeps 80MHz, no conflict. - Mgmt ethernet changed (2026-06-28): now
enxd8ec5eeb3512@ 192.168.10.251 (metric100, active default); oldenx00e04c3600ab@ .235 nowunavailable(swapped/unplugged during USB reorg). Cockpit now at https://192.168.10.251:9090. AP NAT (oifname != AP) follows it automatically. Stale NM profile for the .235 adapter still present (shows "unavailable" in plugin).