Files
claude-memory/wayback-campervan-ap.md
T
Andreas WredeandClaude Fable 5 a304b6d197 memory: initial import (transferred from wayback) + hub-move and cockpit-EMFILE updates
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>
2026-07-06 18:36:43 -04:00

52 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: wayback-campervan-ap
description: "wayback campervan router/AP — hand-rolled hostapd (RTL8852BU, 80MHz/HE) + dnsmasq + nftables; NM owns WAN; eventual Starlink+4G multi-WAN"
metadata:
node_type: memory
type: project
originSessionId: 0f399db0-9a91-4f55-b102-70875f05be7a
---
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`, driver `rtw89_8852bu`, iface `wlxc83a35a4ee55`) = AP radio. Confirmed empirically: AP mode + **VHT80 + HE (WiFi-6)** at 80MHz works.
- **phy0 = Intel 8265** (`wlp1s0`) = mgmt/uplink, assoc home SSID `Wapana` (192.168.10.27).
- **2.4GHz AP added 2026-07-06 (commit `e652b0f`): Linksys WUSB6300v2** (`13b1:0045`, RTL8822BU, driver `rtw88_8822bu`, iface `wlxd8ec5e2faa8c`). 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-watchdog` now 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 APS` list in vanrouter.js, commit `db16964`).
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`: SSID `VanLink`, ch149 VHT80/HE, WPA2-PSK (user changed it 2026-06-28; valid = 8-63 chars), `country_code=CA`. `/etc/default/hostapd` DAEMON_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_core` then `modprobe rtw89_8852bu`; -r of just the leaf does NOT cascade to core). Verify `cat /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 — trust `iw 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), unit `van-ap-dnsmasq.service`. DHCP 10.42.0.10-254/12h, gw+dns 10.42.0.1.
- **nftables** `/etc/nftables.conf`: own table `van_router_nat` (create+delete idiom, no global flush) masquerading `10.42.0.0/24 oifname != AP` → covers any WAN. `ip_forward=1` persisted 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`, unit `van-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 -I` to 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 + `Koodo` gsm 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), NOT `nmcli 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` (runs `ethtool --set-eee <if> eee off` on 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 by `device`, cellular by `connection` name.
- **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 via `cockpit.spawn` as 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 via `cockpit-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 dispatcher `90apnmdispatcher` + its own dnsmasq + NAT; needs `DNSStubListener=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); old `enx00e04c3600ab` @ .235 now `unavailable` (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).