Commit Graph
76 Commits
Author SHA1 Message Date
andreasandClaude Sonnet 5.5 11d3fccf75 nftables: don't masquerade traffic leaving via ZeroTier
Hosts on the van LAN were all NATed to the router's ZT address when
reaching ZeroTier peers, hiding real source IPs from logs and
source-based firewall rules. Exclude ztuga7c2kh alongside br0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 09:45:03 -04:00
andreas d896fc908b li3-ha: apply the same status-gate + current-scale fixes to the HA integration
parser.py is a verbatim port of li3/van-li3-battery and still had the old
"000000" string gate and raw int(parts[7]) current. Apply the identical
fixes (72487cf) so the native integration and the MQTT bridge agree:
- status gate and decode_status share one parsed-int helper (0 == OK in any
  representation; unparseable = unreliable)
- main-pack current parsed at its real 0.1 A scale

The 72487c MQTT/systemd/discovery/expire_after hardening intentionally does
not appear here: parser.py is protocol-only, and coordinator.py already uses
bleak_retry_connector + HA bluetooth discovery + native sensor availability
in place of those standalone concerns.
2026-09-27 11:57:06 -04:00
andreas 72487cfdc4 li3: correct status gate and current scaling; harden BLE/MQTT recovery
- status gate and decode_status now both key off one parsed int
  (0 == OK in any repr; unparseable = unreliable), so they can't diverge
  on "0"/"00"/"0000"
- main-pack current parsed at its real 0.1 A scale (was raw)
- run `systemctl restart bluetooth` + settle delay off the event loop
  (asyncio.to_thread, timeout=30; errors logged, not fatal); call site awaits
- bounded MQTT startup: exit (let systemd restart) if broker never connects
  within MQTT_STARTUP_TIMEOUT_S
- re-assert HA discovery on every (re)connect so entities survive a
  mosquitto restart that drops retained config
- expire_after *4 -> *8 so routine scan misses don't flap the battery
  to unavailable
2026-09-27 09:55:18 -04:00
andreasandClaude Sonnet 5 d1354bdd09 hosts/van.conf: disable van-li3-battery (superseded by HA native li3_battery integration)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 11:59:19 -04:00
andreasandClaude Sonnet 5 9dfc28b6f3 Stop tracking a compiled .pyc (already covered by .gitignore)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-25 16:39:40 -04:00
andreasandClaude Sonnet 5 8ea1b5787a hosts/van.conf: record the R5C's current dongles; tests read host values
The R5C's 2.4GHz AP now uses the D-Link dongle wlxf4f26d1760a7 (the same
dongle hosts/wan.conf lists — it moves between hosts) and a Wi-Fi WAN test
dongle wlx200bd04dc756 is configured (not always attached; van-failover
treats an absent device as "not present").

The tests no longer hardcode this host's hardware: assertions read the
expected interface names from the host file (hv helper), and the "no Wi-Fi
WAN" path (no wifis: stanza, `wifi WAN: none`) is covered with a synthetic
copy of van.conf with WIFI_WAN_IFACE emptied.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-25 16:09:04 -04:00
andreasandClaude Sonnet 5 b2526b9d62 deploy: harden mosquitto password_file guards (non-root, runuser errors, symlinks, traversal, all lines)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 22:36:17 -04:00
andreasandClaude Sonnet 5 5ce6996716 deploy: non-fatal service restarts; mosquitto password_file safeguard and post-check probe
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 22:29:51 -04:00
andreasandClaude Sonnet 5 da59562511 van-leds: fix stale-state test carrier
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 22:20:14 -04:00
andreasandClaude Sonnet 5 e2da20a1b9 van-leds fix round 2: state_max_age_s default 180, non-finite/invalid config guards, log-recurrence test
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 22:19:26 -04:00
andreasandClaude Sonnet 5 c7dff14807 van-leds fix round 1: realistic sysfs fake, error paths, stale failover state, log-once, interval and empty-iface guards
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 22:14:15 -04:00
andreasandClaude Sonnet 5 0f643be719 van-leds: drive the R5C power/LAN/WAN/WiFi LEDs (ENABLE_LEDS, LED_* vars, post-check probe)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 22:04:11 -04:00
andreasandClaude Sonnet 5 e2036c295d van-router-mqtt: subscribe and publish discovery in on_connect
Clean sessions lose subscriptions on reconnect and a refused first connect
loses the retained discovery, so both now happen on every successful connect.
Adds reason codes 132-136 and behavioural tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 21:50:14 -04:00
andreasandClaude Sonnet 5 e0792fade2 van-router-mqtt: broker credentials in a separate 0600 file; log refused connects
config.json is re-rendered every deploy, so credentials go in
/etc/van-router-mqtt/credentials.json (seeded empty if absent, never
overwritten). The service logs MQTT connect/refuse/disconnect state changes,
and --post-check warns when the broker refuses the service.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 21:45:16 -04:00
andreasandClaude Sonnet 5 594213138e apply-network fix round 1: reload networkd after the NM reload on rollback; harden post-check tests
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 21:04:33 -04:00
andreasandClaude Sonnet 5 4f62b9f770 apply-network: reload networkd after each netplan apply; post-check flags a networkd/NM double claim
Live R5C run: after the Armbian catch-all .network was removed, networkd kept its
in-memory claim on the uplink port (two addresses, extra proto dhcp default route)
until `networkctl reload`. The helper now reloads networkd after the forward apply
and after the rollback re-apply (not fatal, not gating; logs the port state and a
"networkd still manages" note on the forward path), the AN_* time budget includes
it, and --post-check warns when the netplan matches but networkd still lists the
uplink port configured/configuring.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 20:58:29 -04:00
andreasandClaude Sonnet 5 1ce4a30336 Docs: README --force semantics; spec amendments for the pending conf, preflight and byte-identical netplan
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 20:01:45 -04:00
andreasandClaude Opus 5.5 722cad1ac3 netplan: restore the Pi-identical comment; rollback re-runs van-br0-setup
- ap/50-van-wan.yaml: revert the comment to "see STARLINK_IFACE in deploy.conf" so the
  rendered file is byte-identical to the Pi 5's installed netplan (it otherwise reports
  "differs" forever); note in deploy.sh next to render_wan_netplan.
- check 14: baseline 3d117e7, keep byte-identity for wan.conf, assert no /etc/vanlink.conf;
  the failure branch no longer aborts the suite under pipefail.
- helper restore(): restart van-br0-setup (unit present, timeout 30, non-fatal) after the
  re-apply, before the connectivity re-check; asserted in the rollback sandbox scenario.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:54:25 -04:00
andreasandClaude Opus 5.5 3fce6a7907 apply-network: final-review fixes (diagnostics, NM off the uplink until handover, preflight, stricter stage 2)
I-1 helper logs diagnostics (nmcli, DHCP routers, networkctl -n 0, ip addr, ip route; each
    under timeout 5) before a stage 1/2 restore, and the port's networkctl list line on success
    (information only, never gating).
I-2 ap/nm-uplink-pending.conf -> /etc/NetworkManager/conf.d/zz-van-wan-pending.conf keeps NM
    off STARLINK_IFACE while the WAN netplan is missing; installed before network-manager,
    removed once the netplan matches, left as is when it differs (port already handed to NM).
    apply_network backs it up as nm-pending.conf; the helper removes it + reloads NM conf right
    before netplan generate/apply, restore() puts it back and reloads after the re-apply.
    --wan-plan prints "uplink NM pending conf: ...".
I-3 nm_wan_state_netplan: "unreadable" (0600 file, non-root); --wan-plan and post-check say so
    without warning.
I-4 apply_preflight_problems (+ hidden --apply-preflight, VANLINK_HOSTNAME test knob ignored as
    root): port absent / conf of another host -> refused without --force. Stage 2 also needs
    van-failover's own "proto static" default route on the port.
M-1 helper restarts van-br0-setup (if the unit exists) after the forward netplan apply.
M-3 nm_pkg_installed (dpkg-query Status) in deploy, --wan-plan and --apply-network.
M-5 header documents VANLINK_CONF; stale test comment fixed.
M-6 cellular_profile_exists ignores VANLINK_NM_DIR as root.
M-7 tests: NM-off files installed before network-manager; read-only sub-commands never apt-get.
M-8 an existing, differing WAN netplan is shown (redact_secrets now masks YAML password:) and
    refused without --force.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:41:02 -04:00
andreasandClaude Sonnet 5 5c18bcdad6 Spec: record review-driven amendments to the NM WAN design
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:16:12 -04:00
andreasandClaude Sonnet 5 8baddceb96 apply-network: ignore VANLINK_WAN_NETPLAN; pin with a test
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:13:43 -04:00
andreasandClaude Sonnet 5 698f9ee446 post-check: failover check warns only on link without NM connection; retry, stub-nmcli tests
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:11:55 -04:00
andreasandClaude Sonnet 5 2601472576 post-check and docs for NetworkManager WANs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:06:43 -04:00
andreasandClaude Sonnet 5 50ac006894 deploy: apply helper hardening (signal ordering, timeout -k, self-cleanup, checked pristine mv)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 19:01:25 -04:00
andreasandClaude Sonnet 5 cefca06dac deploy: apply helper gateway from DHCP routers, trap/timeouts, running status, per-stamp files
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:55:04 -04:00
andreasandClaude Sonnet 5 ca7d22384b deploy: apply helper reboots only when the rollback itself failed
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:46:16 -04:00
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 640d6d245c Add implementation plan: NetworkManager-owned WANs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:25:49 -04:00
andreasandClaude Sonnet 5 223652b834 Add design spec: NetworkManager-owned WANs provisioned by deploy.sh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
2026-09-23 18:06:44 -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 3d117e714c Backup scripts read device/UUID/target from the host config
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 14:36:46 -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
andreasandClaude Sonnet 5 ab6c3b7c64 Add implementation plan for host-local /etc/vanlink.conf
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 13:42:57 -04:00
andreasandClaude Sonnet 5 06a16568f7 Spec: LAN_IFACE rename, host files in repo via /etc/vanlink.conf symlink
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 13:35:12 -04:00
andreasandClaude Sonnet 5 97dd23f5a6 Add design spec for host-local /etc/vanlink.conf
Moves host-specific configuration out of the repo so the Pi 5 and R5C
can share one git checkout, with feature flags and template checks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 13:08:08 -04:00
andreasandClaude Sonnet 5 ebb2bcc626 Adapt sync-sd-backup.sh to eMMC-primary R5C layout
The eMMC is now the boot/root device and the SD card is a manual
failsafe. U-Boot has no persistent env and always prefers an SD with a
boot.scr, so the SD's boot script is kept dormant as
boot-failesafe-rename-to:boot.scr.

- Locate the SD by root UUID instead of /dev/mmcblk0p2
- Preserve the SD's dormant boot script; never create a live boot.scr
  and refresh the dormant copy from the eMMC
- Copy fstab and armbianEnv.txt with the root UUID rewritten to the SD's
- Add rsync -x; drop the Pi-specific /boot/firmware exclude

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 12:26:03 -04:00
andreas 4b7c360095 Document R5C boot failure and recovery plan
SD card filesystem corrupted: ext4 journal version incompatible with
standard e2fsck (1.47.2 from Linux host). Filesystem inaccessible.

Root cause: Podman homeassistant container startup during network
instability and system reconfiguration caused unclean shutdown and
filesystem corruption.

Recovery: Flash fresh Armbian 6.18, run deploy.sh with fixes:
- DNS resolution fix added to HOMEASSISTANT.md
- resolv.conf fix should be added to deploy.sh post-processing
- Deploy containers after network is stable

All scripts and configs are ready and committed. Only need fresh SD card.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 15:37:25 -04:00
andreas 6d9c4f69cd Fix DNS resolver after disabling systemd-resolved
Root cause: /etc/resolv.conf was a broken symlink to systemd-resolved's
stub resolver, which doesn't exist after disabling the service.

Fixed by creating proper /etc/resolv.conf pointing to dnsmasq on 10.42.1.1
and upstream resolvers (1.1.1.1, 8.8.8.8).

This fix allows apt-get to work again and enables podman installation.

**Result: ✅ podman installed, homeassistant container starting**
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 13:52:05 -04:00
andreas a12869ceb1 Document homeassistant migration and network blocker
Added HOMEASSISTANT.md with migration steps and configuration details.
Home Assistant config copied to R5C at /srv/homeassistant.

**BLOCKED**: podman installation fails on R5C due to extreme network latency
(1000+ ms Starlink connection) and DNS resolution failures. Package downloads
fail consistently.

Migration can proceed once R5C network is stable enough for apt-get to complete.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 13:46:22 -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 c8eca9c09c Fix nftables NAT configuration
Fixed two issues in nftables.conf:
1. Unsubstituted placeholder @GATEWAY_NETWORK@ - hardcoded to 10.42.1.0/24
2. Missing semicolon on masquerade rule

NAT now working - clients can access internet through R5C gateway.
Masquerade rule: traffic from 10.42.1.0/24 not destined for br0 is NATed
to the outgoing interface (Starlink/Ethernet uplink).

Verified:
- R5C gateway: 10.42.1.1/24
- Dual-band WiFi: 5GHz (ch 149) + 2.4GHz (ch 6)
- DHCP: 3+ active leases
- Internet: R5C can ping 1.1.1.1, clients ready for internet access
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 11:22:31 -04:00
andreas 753c929e3d Enable dual-band WiFi AP: 5GHz + 2.4GHz
Fixed hostapd-2g.conf to properly specify interface wlx3c3332002066 (D-Link)
for 2.4GHz AP. Both APs now operational:

- 5GHz: wlp1s0 (MT7925E), channel 149, 802.11ac/ax
- 2.4GHz: wlx3c3332002066 (D-Link), channel 6, 802.11n

Both bridged to br0 (10.42.1.0/24), served by dnsmasq DHCP.
D-Link interface usb-modeswitch now working properly (no CDROM mode).

DHCP clients can connect to either band and receive addresses in
the 10.42.1.10-254 range with gateway 10.42.1.1.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 11:16:05 -04:00
andreas 817b21c237 Fix DHCP and service startup issues
Fixed three critical issues preventing DHCP from working:

1. Config file rendering: Placeholders (@GATEWAY_IP@, etc.) weren't being
   substituted. Using direct heredoc writes instead of sed for reliability.

2. Service dependency blocking: van-br0-setup was blocked waiting for
   hostapd.service to start, preventing bridge members from being added.
   Changed to only depend on systemd-networkd so boot completes.

3. Port 53 conflict: systemd-resolved was listening on port 53, blocking
   dnsmasq from binding. Disabled DNS in systemd-resolved config.

R5C now operational:
- 5GHz AP on channel 149
- Bridge: 10.42.1.1/24 with enP2p33s0 + wlp1s0
- DHCP: 10.42.1.10-254 (4+ active leases)
- van-ap-dnsmasq service: running and serving DHCP
- hostapd-2g: disabled (interface wlx3c3332002066 not available)

Disabled hostapd-2g.service until D-Link RTL8188GU is fixed (stuck in CDROM mode).
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 11:12:30 -04:00
andreas 474e567ace Enable 5GHz AP mode with MT7925E support
Updated hostapd.conf to run 5GHz AP on channel 149 with MT7925E (mt76 driver).
Now supports full 802.11ac (VHT) and 802.11ax (WiFi 6) capabilities.

Also fixed deploy.sh rendering issue that left unsubstituted placeholders in
network configs, causing Ethernet flaps. Configs are now properly deployed.

- hw_mode=a (5GHz), channel=149
- VHT and HE (WiFi 6) capabilities enabled
- Proper bridge configuration with gateway IP 10.42.1.1/24
- DHCP range 10.42.1.10-254 verified working
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 10:39:22 -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 4d33d1a208 Document MT7925E WiFi card swap - 5GHz AP now fully functional
Replaced RTL8822CE with Mediatek MT7925E PCIe WiFi card. The mt76 driver
(MT7925E) properly supports AP bridge mode, unlike rtw88 (RTL8822CE).

R5C is now PRODUCTION-READY:
- 5GHz AP on channel 149 with 802.11ac/ax support
- WiFi clients bridge properly and receive DHCP
- Ethernet failover fully functional
- NAT/routing configured

RTL8822CE limitation: bridging in AP mode not supported by rtw88 driver.
MT7925E solution: mt76 driver stack supports full bridge forwarding.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 09:34:52 -04:00
andreasandClaude Haiku 4.5 f2d4cdd099 Fix dnsmasq startup dependency: require bridge setup before DHCP
dnsmasq was failing to start or staying inactive because it was starting
before the bridge members were added. Updated van-ap-dnsmasq.service to
depend on van-br0-setup.service, ensuring the bridge is ready before
dnsmasq binds to br0.

Fixes: DHCP not provisioning addresses on boot.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 08:11:12 -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 f372469cdf Armbian 6.18 R5C deployment: update interface names and enable 5GHz AP
- Upgrade R5C from Debian to Armbian 6.18 fixes RTL8822CE 5GHz limitation
- Updated deploy.conf with Armbian's systemd network interface names:
  - wlan1/wlan2 → wlp1s0 (single WiFi chip; both APs on same interface)
  - eth0/eth1 → enP2p33s0/enP1p17s0 (MAC-derived naming)
- 5GHz AP now working on channel 149 with 802.11ac/ax support
- DHCP functional: devices receiving IPs from 10.42.1.10-254 range
- One test device successfully provisioned with lease at 10.42.1.66

Status: R5C AP operational, ready for production failover role
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 08:02:41 -04:00
andreasandClaude Haiku 4.5 34c1b51006 R5C final config: 2.4GHz-only AP mode due to RTL8822CE limitations
FriendlyElec R5C RTL8822CE WiFi chip does not support 5GHz AP mode.
Both wlan0 and wlan1 locked to 2.4GHz-only (mode 2) by firmware/driver.

Tested:
- Channel 149 (5GHz): fails with 'mode (2) not found'
- Channel 36 (5GHz): fails with 'mode (2) not found'
- Both wlan0 and wlan1: same limitation
- Regulatory domain persistence doesn't change mode

Solution: Configure hostapd for 2.4GHz (hw_mode=g, channel 6)
- VanLink2 now on wlan1, 2.4GHz channel 6
- VanLink2-2G still on wlan2, 2.4GHz channel 6
- Both working stably

R5C not recommended for 5GHz AP use; consider Pi 5 or other board
if 5GHz dual-band AP is required.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 18:52:46 -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 2b00157642 Fix RTL8822CE kernel panic on 5GHz AP with VHT
Problem: RTL8822CE driver caused kernel panic (watchdog hard LOCKUP) when
hostapd tried to use VHT 802.11ac with 80MHz channel width on channel 149.

Root cause: Driver/firmware instability with VHT capabilities on this chip.

Solution: Disable VHT, use HT40+ (802.11n) only.
- Removes ieee80211ac (VHT), ieee80211ax (802.11ax), and 80MHz channel width
- Keeps HT40+ with Short GI for reasonable performance
- Stable operation on channel 149 (5745 MHz)

This allows the 5GHz AP to start and beacon without lockup on R5C hardware.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 18:27:23 -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 7d68991c37 Update deploy.conf comments for R5C hardware (RTL8822CE 5GHz AP)
Clarify that WIFI_5G_IFACE=wlan1 uses the built-in RTL8822CE chip on
FriendlyElec R5C with rtl88x2ce driver, not the RTL8852BU from the Pi 5.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-18 17:42:35 -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 4aae62372e deument last change 2026-07-12 12:22:45 -04:00