Commit Graph
59 Commits
Author SHA1 Message Date
andreasandClaude Sonnet 5 d46fd5a1e4 deploy: --apply-network changes nothing itself; helper does install/apply, two-stage gate, checked rollback, status file
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:44:59 -04:00
andreasandClaude Sonnet 5 eaec8eb8b9 deploy: --apply-network with detached apply, connectivity gate and automatic rollback
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:35:43 -04:00
andreasandClaude Sonnet 5 7be698a5f1 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
2026-09-23 18:33:38 -04:00
andreasandClaude Sonnet 5 e8fa2e025f deploy: install missing packages, NetworkManager WAN section, --wan-plan
Pure-bash SHA-1 derived CELLULAR_UUID (no uuidgen); skip keyfile if empty.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:30:17 -04:00
andreasandClaude Sonnet 5 65c0356463 Template NM WAN pieces: netplan split, cellular keyfile, new host variables
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:27:19 -04:00
andreasandClaude Sonnet 5 7333c1a1b3 post_check: radio present but not beaconing (no ssid) is a warning, not ok
Adds classify_radio + hidden --classify-radio seam and check 13.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 17:35:33 -04:00
andreasandClaude Sonnet 5 c4d9def8e3 post_check: run-to-completion units that exited 0 are ok, not warnings
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 17:26:33 -04:00
andreasandClaude Sonnet 5 6142935e29 post_check: shared bounded retry for br0/LAN/NAT/DHCP probes, pipefail-safe matching
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 17:23:36 -04:00
andreasandClaude Sonnet 5 5b43add677 deploy.sh: post-deploy check, --post-check, host-aware verify list
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 17:20:48 -04:00
andreasandClaude Sonnet 5 667edc8621 deploy --diff: never diff seeded secret files, redact secret values
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 16:41:31 -04:00
andreasandClaude Sonnet 5 f4bb65de9c deploy --diff: cover plain install files and removals
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 14:48:50 -04:00
andreasandClaude Sonnet 5 ac897799e6 Template hostapd interface/SSIDs/5GHz radio lines; guard against other-host hardcodes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 14:48:22 -04:00
andreasandClaude Sonnet 5 a39fd5a654 Docs: shared checkout model, /etc/vanlink.conf references
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 14:39:22 -04:00
andreasandClaude Sonnet 5 83974f731d deploy: feature flags, --diff, tolerate failed restarts
Li3, NVMe watchdog, Home Assistant/ESPHome, Frigate and Cockpit are
installed, enabled and restarted only when their ENABLE_* flag is 1.
--diff shows what would change in /etc. A unit that fails to restart is
recorded as a warning instead of aborting the deploy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:34:13 -04:00
andreasandClaude Sonnet 5 d704069ffc Template remaining host-specific values (WAN wifi, LAN/eth0, NVMe, nftables)
nftables.conf hardcoded the R5C network, van-br0-setup.service the R5C
interfaces and several configs wlan0/eth0. All now come from the host
config; the onboard LAN port is skipped when ONBOARD_LAN_IFACE is empty.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:32:09 -04:00
andreasandClaude Sonnet 5 164cb30d93 deploy: gate cockpit block on ENABLE_COCKPIT
SKIP_COCKPIT only existed in the deleted deploy.conf; under set -u the
cockpit block would abort with an unbound variable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:30:05 -04:00
andreasandClaude Sonnet 5 0cbbeb7aba deploy: host config from /etc/vanlink.conf (hosts/<hostname>.conf)
deploy.conf is replaced by one versioned file per host plus an example.
deploy.sh validates the config, renders every template with a generic
token loop, refuses to install output with leftover @TOKENs and gains
--check/--templates. LAN_USB_IFACE is renamed LAN_IFACE.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:28:11 -04:00
andreasandClaude Sonnet 5 442010c4b8 deploy: render dnsmasq/br0 configs, install LAN file as 05-van-lan
van-ap-dnsmasq.conf and 21-van-br0.network carry @TOKEN@ placeholders but
were installed unrendered. Armbian's netplan-generated 10-netplan-* file
matched the LAN port before 22-van-lan.network, so it was never bridged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:27:04 -04:00
andreas b4dfc88780 Add podman and homeassistant/esphome container support
Added podman to REQUIRED_PACKAGES for running homeassistant and esphome
containers on R5C.

Created docker/start-containers.sh script to start both containers with
persistent /srv volumes for configuration.

Ready for migration of homeassistant + esphome from 10.42.0 to 10.42.1.
Configs can be copied from old vanrouter at /srv/homeassistant and
/srv/esphome, then containers started on R5C.

Ports:
- Home Assistant: 8123 (accessed via --network=host)
- ESPHome: 6052
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 12:42:55 -04:00
andreasandClaude Haiku 4.5 4a4d80db4b Disable systemd-resolved DNS to allow dnsmasq DHCP
systemd-resolved listening on port 53 (even localhost-only) blocks
dnsmasq from binding to port 53 globally, causing DHCP to fail on reboot.

Created drop-in systemd-resolved-disable.conf to prevent the service from
listening on DNS. dnsmasq becomes the sole DNS+DHCP server on bridge br0.

Critical fix: without this, clients don't receive DHCP after reboot.

Verified: 5+ active DHCP leases, clients receiving 10.42.1.x addresses.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 11:57:42 -04:00
andreas 62eac3c389 Make all packages required (no optional packages)
Moved all packages from OPTIONAL_PACKAGES to REQUIRED_PACKAGES:
- rsync, mosquitto, python3-paho-mqtt
- mobile-broadband-provider-info, zerotier-one
- gpsd, gpsd-clients

Deploy will now fail if any package is missing, ensuring all
van-* services have their dependencies available.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 11:25:46 -04:00
andreas f5b29630ae Add usb-modeswitch config for RTL8188GU CDROM mode bypass
RTL8188GU WiFi adapter (0bda:1a2b) ships in CDROM mode on initial connection.
Install usb-modeswitch package and config to automatically switch to network
mode on boot.

Required for 2.4GHz AP to function when using D-Link DWA-171 or similar
RTL8188GU-based adapters.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 10:06:16 -04:00
andreas f564886a4a Make GPS, Bluetooth, and modem packages required
Move python3-gps, python3-bleak to REQUIRED_PACKAGES (needed for van-li3-battery,
van-gps-owntracks). Add modemmanager to REQUIRED_PACKAGES (provides mmcli for
van-sms-* services).

Deploy will now fail if these packages are missing, preventing silent failures
when GPS or SMS services are needed.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 10:01:59 -04:00
andreas 3593655fff Add van-br0-setup.service to fix bridge member persistence on boot
systemd-networkd Bridge= directive wasn't reliably adding interfaces to br0
on Armbian. Created persistent systemd service to ensure enP2p33s0 and wlp1s0
are added to the bridge after boot, maintaining 10.42.1.0/24 network.

This ensures the gateway bridge stays configured even after R5C reboots.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 08:07:47 -04:00
andreasandClaude Haiku 4.5 1002f86172 Fix regulatory domain persistence for 5GHz AP on boot
Problem: wlan1 regulatory domain not set on boot, defaults to 2.4GHz-only mode,
preventing channel 149 (5GHz) from being available. hostapd fails on startup.

Solution:
1. Modified regdomain.service to:
   - Run BEFORE hostapd/hostapd-2g services (Before= directive)
   - Run earlier in boot (After= sysinit.target)
   - RemainAfterExit=yes to persist setting

2. Added 80-regdomain.rules udev rule:
   - Triggers on regulatory device changes
   - Executes 'iw reg set CA' automatically

3. Added hostapd drop-in config:
   - Explicitly requires regdomain.service
   - Adds Wants= to ensure it starts

This ensures the regulatory domain is set BEFORE hostapd attempts to use
channel 149, fixing the boot-time AP failure loop.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 18:45:59 -04:00
andreasandClaude Haiku 4.5 565e8f31ab Fix watchdog timeout and MQTT connectivity issues
Problem: R5C spontaneously rebooted due to hardware watchdog timeout
Cause 1: van-gps-owntracks in infinite restart loop (MQTT connect failed)
Cause 2: mosquitto only listening on localhost, so clients couldn't connect
Solution:
- Add restart limits to van-gps-owntracks and van-li3-battery services
  (max 3 restarts per 5 minutes prevents infinite restart loops)
- Configure mosquitto to listen on all interfaces (0.0.0.0:1883)
- Deploy mosquitto listener config via deploy.sh
- Restart mosquitto during deploy to apply config changes

This prevents the system from hitting the 11-second hardware watchdog timeout
when services crash and systemd auto-restarts them indefinitely.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 18:20:11 -04:00
andreasandClaude Haiku 4.5 bb2e9c4618 Disable system dnsmasq.service to avoid port 53 conflicts
The system dnsmasq.service from the Debian dnsmasq package conflicts with
van-ap-dnsmasq.service on port 53 (DNS/DHCP). Explicitly disable the system
service during deploy so only van-ap-dnsmasq (bound to br0 for AP DHCP) runs.

Fixes DHCP failures where clients connect to the AP but don't get IP addresses
because port 53 is already in use.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 18:00:33 -04:00
andreasandClaude Haiku 4.5 af241339a3 Add package dependency checks to deploy.sh
Check for required packages (hostapd, iw, nftables, dnsmasq, systemd-resolved)
at deploy start and fail if any are missing. Also warn about optional packages
used by specific components (rsync, mosquitto, gpsd, python3-paho-mqtt, etc.).

Missing required packages halt deployment with clear error message. Optional
packages generate warnings that are captured in deploy-warnings.json for the
router-status MQTT dashboard.

This prevents silent failures when the R5C or other hardware doesn't have
expected dependencies installed.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 17:51:22 -04:00
andreasandClaude Haiku 4.5 ad199fb0b0 Make router IP address configurable via deploy.conf
Add GATEWAY_IP, GATEWAY_PREFIX, GATEWAY_NETWORK, DHCP_RANGE_START, and
DHCP_RANGE_END variables to deploy.conf. Update ap/21-van-br0.network,
ap/van-ap-dnsmasq.conf, and ap/nftables.conf to use @TOKEN@ placeholders
for IP configuration instead of hardcoding 10.42.x addresses.

This allows deploying the same configuration to multiple routers on
different networks (e.g., Pi 5 on 10.42.0.x and R5C on 10.42.1.x) by
simply editing deploy.conf before running ./deploy.sh.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 17:31:18 -04:00
Andreas WredeandClaude Sonnet 5 ec5130ea7d router-status: replace Cockpit's Van Router plugin with MQTT -> Home Assistant
Cockpit's login was unreliable (Firefox rejected sometimes, Android failed
outright with a TLS handshake error) and it was a resource hog on this Pi.
van-router-mqtt publishes the same AP/client/WAN/Starlink/modem status and
accepts the same control actions (AP/modem restart, WAN connect/disconnect,
prefer) via MQTT with HA discovery, using the local Mosquitto broker already
running here. It republishes van-failover/van-thermal's own state.json files
verbatim rather than modifying either daemon (van-thermal is deliberately
stdlib-only; van-failover's control loop wasn't worth an added dependency).

Adds a Lovelace dashboard (ha/dashboards/van-router.yaml) consuming those
entities. Cockpit's plugin is left deployed for now, not yet retired.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2tpeaiHUriQbbnQ4SCbkf
2026-09-14 16:28:01 -04:00
Andreas WredeandClaude Sonnet 5 db22cb50d6 modem: add van-sms-send CLI for sending SMS ad hoc
mmcli's inline "number=...,text=..." properties string breaks on plain
spaces/quotes/colons in the text — found while testing van-sms-watch.
Sidesteps that entirely by passing the message via
--messaging-create-sms-with-text=<tempfile> instead. Tested live
(multi-word text, punctuation, multi-line stdin input all delivered).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 15:40:22 -04:00
Andreas WredeandClaude Sonnet 5 d002058701 modem: add van-sms-watch to archive inbound SMS + Pushover alert
Polls ModemManager for SMS on the EC25's own flash storage, appends each
inbound message to /var/log/van-sms.jsonl, pages via Pushover (shared
van-battery creds), then deletes it from modem storage so it doesn't
silently fill up. MMS can't be decoded (WAP-push notification needs the
carrier's separate MMS APN) — detected and paged as notification-only.

Wired into deploy.sh; installed/verified live on the Pi (backlog SMS
archived + paged successfully) ahead of committing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 15:12:54 -04:00
Andreas Wrede 7a1c47d34c li3: add Lithionics Li3 house battery BMS -> Home Assistant MQTT
Publishes the RV's 12V LiFePO4 house battery to HA via MQTT discovery
(pack voltage, 4 cell voltages, current, SOC, BMS/battery temp, status).
Connects over the battery's BLE HM-10 UART module (service ffe0/char
ffe1, no pairing) using bleak; protocol reverse-engineered from the
com.lithionics.bms Android app's own BLE/parsing code.

Deliberately named li3/ and van-li3-battery, not battery/van-battery —
that name is reserved for the host's own AC/UPS power-supply monitor
(different hardware, unrelated concern).

Self-heals a bluetoothd discovery-state wedge (Discovering stuck "yes",
connects failing with le-connection-abort-by-local) that shows up after
repeated failed connects to this device on the Pi's onboard adapter: the
daemon retries scan/connect internally (MQTT session and HA entities
stay up across retries) and restarts bluetooth.service itself after 3
consecutive scan failures, rate-limited to once per 5 min.
2026-08-17 17:26:14 -04:00
Andreas WredeandClaude Sonnet 5 b7758c9cd5 ha: add Frigate NVR as a Podman Quadlet, wire into deploy.sh
Same sibling-container pattern as HA/ESPHome. The hand-written unit used
Privileged=true, which isn't a real Quadlet key — the generator silently
drops the whole file on an unsupported key, so frigate.service was never
generated (hence `systemctl enable frigate` saying the unit doesn't exist).
Fixed with PodmanArgs=--privileged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 21:12:45 -04:00
Andreas WredeandClaude Sonnet 5 af18dc0755 failover: wire up van-modem-watch in deploy.sh
Completes the van-modem-usb-kick -> van-modem-watch swap from the
previous commit: deploy.sh was still installing/enabling the old unit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 20:28:46 -04:00
Andreas WredeandClaude Sonnet 5 a1bad186b1 failover: add van-modem-usb-kick — recover EC25 modem when it never enumerates at boot
Seen after moving the modem onto the new powered UGreen hub: the port
sometimes never signals a connect during boot (no descriptor-read attempt at
all in dmesg), so the hub never rescans it. Unbind/rebinding the inner hub
chip reproduces the same connect edge a physical unplug/replug does.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 10:17:36 -04:00
Andreas Wrede e7a82126f2 power: add van-nvme-watch — pages on NVMe I/O-timeout/reset recurrence
Tails journalctl -kf for the "nvme nvmeN: I/O tag ... timeout, reset
controller" signature that crashed and corrupted the root fs on 2026-08-02
(and recurred 2026-08-04, that time self-healing). Watches a short grace
window to tell a clean self-heal from an escalation (repeated timeout or a
following ext4 error) before paging via the existing Pushover credentials,
with a live SMART/superblock snapshot in the alert body.
2026-08-04 08:44:53 -04:00
Andreas Wrede 86fa9509df failover: fix Starlink interface + template config.json from deploy.conf
STARLINK_IFACE pointed at the wrong device after the USB hub swap (was
accidentally set to the 5GHz AP dongle's interface). failover/config.json
also hardcoded the old interface name instead of being templated like the
other configs, so deploy.conf changes never reached it — switched it to
@STARLINK_IFACE@ and deploy.sh now renders it.
2026-08-04 08:35:18 -04:00
Andreas WredeandClaude Sonnet 5 8efb8dba5f dns: fixed 1.1.1.1/8.8.8.8 lockdown + scoped mDNS, esphome sibling container
- deploy.conf: DNS_RESOLVERS, always 1.1.1.1/8.8.8.8, never a WAN's own
  DHCP/RA-provided servers (previously whatever Wapana handed out).
- ap/99-van-router-dns.conf: global resolved config (fixed DNS, Domains=~.,
  global MulticastDNS=yes — a prerequisite for any per-link mDNS to work at
  all, not just an on/off toggle).
- failover/60-van-wan-dns: NM dispatcher that strips each WAN's DNS/search-
  domain and disables its mDNS via resolvectl on every connect/lease event
  (NM's own ipv4/ipv6.ignore-auto-dns can't be set as a config-file default —
  confirmed rejected as an unknown key — so this enforces it directly
  instead), retried over ~5s to beat NM's own async DNS commit. Also logs
  what each WAN advertised, never used, to /run/van-wan-dns/.
- ap/21-van-br0.network: MulticastDNS=yes, scoped to the van's own LAN only
  — .local/mDNS now resolves for ESPHome and other LAN devices without
  leaking mDNS onto Wapana/Starlink/cellular.
- dns/: ZeroTier-managed DNS (zt.wrede.pvt) made reproducible — installed
  the official zerotier-systemd-manager package (verified against upstream
  checksums), additive to the above so *.zt.wrede.pvt keeps resolving over
  the overlay independent of WAN.
- ha/esphome.container: ESPHome dashboard as a sibling Podman Quadlet to
  Home Assistant, same host-network/config-volume pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 16:09:01 -04:00
Andreas WredeandClaude Sonnet 5 5d88e1b30c deploy: hardware-instance templating, wlan0 boot watchdog, deploy-time warnings in Cockpit
- deploy.conf templates interface names/USB IDs (@TOKEN@ substitution) across
  ap/* configs so a dongle swap only needs deploy.conf edited, not the repo
  configs themselves; drops ap/rtw88.conf (old 2.4GHz dongle retired for the
  DWA-171, which needs no such power-save override).
- failover/van-wlan-watchdog: recovers wlan0 from NM's post-boot no-secrets
  wedge (a boot-time supplicant race, not a real credential failure).
- deploy.sh: warn() collects dependency/config warnings (missing python3-gps,
  python3-paho-mqtt, mobile-broadband-provider-info, grpcurl, gpsd; netplan
  drift; unedited example configs) into /var/lib/vanlink/deploy-warnings.json,
  rendered as an amber Cockpit card so they're visible without reading deploy
  output.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 11:25:11 -04:00
Andreas WredeandClaude Fable 5 8d5415f326 gps: modem GNSS -> gpsd -> OwnTracks/MQTT publisher
EC25-AF GNSS wiring (udev hotplug into gpsd) plus van-gps-owntracks, a
port of the wayback-era gps_to_owntracks.py: apt-only deps (python3-gps
instead of pip-only gpsdclient, paho 2.x callback API), broker secrets
moved out of the code into /etc/van-gps/config.json (0600, seeded from
a sanitized example), gpsd host now localhost. client_id is vanq-wan —
a legacy client still holds vanq on the broker and shared IDs get
kicked in a connect/disconnect loop. Exit-on-disconnect + systemd
Restart=always is the reconnect logic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 22:03:40 -04:00
Andreas WredeandClaude Sonnet 5 daa545f15c deploy.sh: warn on netplan drift between repo and /etc/netplan
The 07-12 IPv6 fix sat in ap/50-van-wan.yaml for a day without ever being
copied to /etc/netplan/ or applied — deploy.sh deliberately skips netplan
(applying it flaps the uplinks) so nothing caught the gap. Now it diffs
the two and prints the manual deploy commands when they disagree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 11:04:19 -04:00
andreas 4aae62372e deument last change 2026-07-12 12:22:45 -04:00
Andreas WredeandClaude Fable 5 a36b64c7c4 lan: repurpose onboard eth0 as an internal LAN port on br0
With wifi + Starlink + cellular as uplinks, the onboard GbE earns its keep
as a wired LAN port instead of the metric-150 ethernet WAN: eth0 leaves
netplan/NM (added to van-ap-unmanaged.conf) and joins br0 via networkd
(23-van-lan-eth0.network), so wired clients get 10.42.0.x DHCP/DNS and NAT
exactly like Wi-Fi clients. The eth WAN is gone from van-failover's config.

Cutover notes: delete the old netplan-eth0 / stray eth0 NM profiles, then
nmcli general reload + networkctl reload/reconfigure eth0. NEVER cable this
port (or the USB LAN dongle) back into an upstream LAN — dnsmasq on br0
would serve rogue DHCP there; STP stays off, so don't cable both wired LAN
ports to the same switch either.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 07:44:44 -04:00
Andreas WredeandClaude Fable 5 751facd511 starlink: dish route + status card on the Van Router page
The Starlink RTL8153 gets a declarative NM profile in 50-van-wan.yaml
(replaces the auto 'Wired connection 1') with a 192.168.100.1/32 link route,
so the dish's management address stays reachable from the router and — via
the existing !br0 masquerade — from the van LAN, regardless of which WAN
holds the default route.

New Cockpit "Starlink" card queries the dish's gRPC API (:9200, get_status
via grpcurl — not packaged in apt, deploy.sh warns when missing) inside the
existing single batched spawn: online/obstructed/outage pill, alerts,
uptime, sw version, PoP latency, down/up throughput, obstruction %.
Sentinels distinguish adapter-absent / no-grpcurl / dish-unreachable.

Gotcha captured while cutting over: a WAN profile without ipv4.route-metric
makes NM re-assert its DHCP default (metric ~101) against van-failover's
enforce_route pruning every cycle; the profile metric must match (failover's
set_profile_metric does this on health transitions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 07:06:43 -04:00
Andreas WredeandClaude Fable 5 3add42a0cb ha: replace the HAOS VM with a native Podman Quadlet container
The fixed 2 GiB ha_van allocation starved the 4 GB Pi. HA Container now
runs on the host network (http://10.42.0.1:8123): ha/homeassistant.container
installs to /etc/containers/systemd/, config in /srv/homeassistant, host
D-Bus mounted for onboard Bluetooth (needs apparmor=unconfined — Ubuntu's
dbus-daemon mediates per AppArmor label and denies AddMatch to BlueZ —
plus NET_ADMIN/NET_RAW for habluetooth adapter recovery).

Drop the VM-era plumbing: the 10.42.0.50 dhcp-host pin becomes a
host-record for 10.42.0.1, and the legacy-URL DNAT + hairpin masquerade
go away entirely. ha_van.xml retired to git history.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:46:30 -04:00
Andreas WredeandClaude Fable 5 7a92548114 cockpit: fix bridge EMFILE — batch status reads into one spawn, raise fd limit
The Python cockpit-bridge frees spawn-pipe fds only at GC time; the Van
Router page's ~12 cockpit.spawn calls every 5s saw-toothed the bridge to
its 1024-fd soft limit, so the polkit admin-escalation spawn failed with
"Too many files open" whenever it landed near a peak.

Two-sided fix:
- vanrouter.js gathers all read-only status in ONE `sh -c` spawn per
  refresh, sections delimited by @@vr:<name>@@ marker lines (~12x less
  pipe churn). Mutating actions unchanged.
- cockpit-session@.service drop-in raises LimitNOFILE to 65535
  (hard limit is 524288), installed by deploy.sh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 18:32:24 -04:00
Andreas WredeandClaude Fable 5 7066207333 deploy: tolerate absent AP radios (hub not yet plugged in)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 17:06:13 -04:00
Andreas WredeandClaude Fable 5 9bf142074a port to Pi 4 'wan': onboard eth0+wlan0 as NM WANs, AP stack verbatim
The USB hub (5GHz + 2.4GHz AP dongles, Starlink + LAN RTL8153s) moves over
from wayback; MAC-derived wlx*/enx* names travel with it, so hostapd/
networkd/cockpit configs are unchanged. Pi diffs only: failover WAN list
(wlan0 wifi 100, eth0 150, starlink USB 200, Koodo 300), cpu_thermal
sensor, bcm2835 watchdog 10s, no HA DNAT/lease, and deploy.sh drops
battery/lid/heartbeat/ZT-dns. Netplan reference in ap/50-van-wan.yaml.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:59:34 -04:00
Andreas WredeandClaude Fable 5 e652b0f7bd ap: parallel 2.4GHz AP (hostapd-2g) on the Linksys WUSB6300v2 dongle
Second radio (wlxd8ec5e2faa8c, RTL8822BU/rtw88), same VanLink SSID+PSK,
ch6 HT20, bridged into br0 next to the 5GHz AP. Runs as its own hostapd
instance + own watchdog so a USB wedge on one radio never darkens the
other; van-ap-watchdog now takes conf path + unit name as args (defaults
unchanged). rtw88.conf disables deep power-save (rtw89 gotcha analog)
and the driver's USB2->3 self-upgrade (USB3 noise in the 2.4GHz band —
note: dongle currently sits in a USB3 port, so it still enumerates
SuperSpeed; move to a USB2 port if 2.4GHz range disappoints).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 10:03:16 -04:00