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>
This commit is contained in:
2026-09-18 17:31:18 -04:00
co-authored by Claude Haiku 4.5
parent ec5130ea7d
commit ad199fb0b0
5 changed files with 44 additions and 23 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
# The LAN gateway IP now lives on the bridge, not on the AP wlan (which is just a # The LAN gateway IP now lives on the bridge, not on the AP wlan (which is just a
# bridge member). ConfigureWithoutCarrier keeps 10.42.0.1 up even before any wired # bridge member). ConfigureWithoutCarrier keeps 10.42.1.1 up even before any wired
# device is plugged, exactly as it was on the wlan-only setup. # device is plugged, exactly as it was on the wlan-only setup.
[Match] [Match]
Name=br0 Name=br0
@@ -8,7 +8,7 @@ Name=br0
RequiredForOnline=no RequiredForOnline=no
[Network] [Network]
Address=10.42.0.1/24 Address=@GATEWAY_IP@/@GATEWAY_PREFIX@
ConfigureWithoutCarrier=yes ConfigureWithoutCarrier=yes
# Resolve .local (mDNS) for devices on the van's own LAN (ESPHome nodes, # Resolve .local (mDNS) for devices on the van's own LAN (ESPHome nodes,
# etc.) — scoped to br0 only, not the WAN links, since mDNS is link-local # etc.) — scoped to br0 only, not the WAN links, since mDNS is link-local
+1 -1
View File
@@ -6,6 +6,6 @@ delete table ip van_router_nat
table ip van_router_nat { table ip van_router_nat {
chain postrouting { chain postrouting {
type nat hook postrouting priority srcnat; policy accept; type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.42.0.0/24 oifname != "br0" masquerade ip saddr @GATEWAY_NETWORK@ oifname != "br0" masquerade
} }
} }
+4 -4
View File
@@ -4,9 +4,9 @@ except-interface=lo
domain-needed domain-needed
bogus-priv bogus-priv
dhcp-authoritative dhcp-authoritative
dhcp-range=10.42.0.10,10.42.0.254,255.255.255.0,12h dhcp-range=@DHCP_RANGE_START@,@DHCP_RANGE_END@,255.255.255.0,12h
# Home Assistant runs natively on this host (Podman, host network, :8123) — # Home Assistant runs natively on this host (Podman, host network, :8123) —
# "homeassistant" is just another name for the router address. # "homeassistant" is just another name for the router address.
host-record=homeassistant,10.42.0.1 host-record=homeassistant,@GATEWAY_IP@
dhcp-option=option:router,10.42.0.1 dhcp-option=option:router,@GATEWAY_IP@
dhcp-option=option:dns-server,10.42.0.1 dhcp-option=option:dns-server,@GATEWAY_IP@
+17 -4
View File
@@ -10,20 +10,23 @@
# `ip -br link` (wired). USB vendor ID: `lsusb`. # `ip -br link` (wired). USB vendor ID: `lsusb`.
# Preview a rendered file without deploying: `sudo ./deploy.sh render <file>` # Preview a rendered file without deploying: `sudo ./deploy.sh render <file>`
SKIP_COCKPIT=1
# 5GHz AP radio (currently: Realtek RTL8852BU, driver rtw89_8852bu) # 5GHz AP radio (currently: Realtek RTL8852BU, driver rtw89_8852bu)
WIFI_5G_IFACE=wlxc83a35a4ee55 #WIFI_5G_IFACE=wlxc83a35a4ee55
WIFI_5G_IFACE=wlan1
# 2.4GHz AP radio (currently: D-Link DWA-171, RTL8821CU, driver rtw88_8821cu) # 2.4GHz AP radio (currently: D-Link DWA-171, RTL8821CU, driver rtw88_8821cu)
#WIFI_2G_IFACE=wlx3c3332002066 #WIFI_2G_IFACE=wlx3c3332002066
WIFI_2G_IFACE=wlxf4f26d1760a7 WIFI_2G_IFACE=wlan2
# Wired LAN port, USB-attached gigabit adapter (RTL8153-family) # Wired LAN port, USB-attached gigabit adapter (RTL8153-family)
LAN_USB_IFACE=enx00e04c331140 LAN_USB_IFACE=eth0
# Starlink dish uplink, USB-attached gigabit adapter (RTL8153-family) # Starlink dish uplink, USB-attached gigabit adapter (RTL8153-family)
#STARLINK_IFACE=enxd8ec5eeb3512 # White Belkin dongle #STARLINK_IFACE=enxd8ec5eeb3512 # White Belkin dongle
#STARLINK_IFACE=enx6c1ff7d210a5 # UGreen 8-port hub's built-in Ethernet (ASIX AX88179B) #STARLINK_IFACE=enx6c1ff7d210a5 # UGreen 8-port hub's built-in Ethernet (ASIX AX88179B)
STARLINK_IFACE=enx3c8cf861752b # TrendNet USB dongle STARLINK_IFACE=eth1
# Cellular modem USB vendor ID (Quectel EC25-AF) # Cellular modem USB vendor ID (Quectel EC25-AF)
MODEM_USB_VENDOR=2c7c MODEM_USB_VENDOR=2c7c
@@ -33,3 +36,13 @@ MODEM_USB_VENDOR=2c7c
# entirely; see ap/van-wan-dns.conf + ap/99-van-router-dns.conf). Keeps # entirely; see ap/van-wan-dns.conf + ap/99-van-router-dns.conf). Keeps
# resolution identical on Wapana, Starlink, or cellular. # resolution identical on Wapana, Starlink, or cellular.
DNS_RESOLVERS="1.1.1.1 8.8.8.8" DNS_RESOLVERS="1.1.1.1 8.8.8.8"
# IP address configuration for this router
# When deploying to different hardware, change GATEWAY_IP, DHCP_RANGE_START/END, and GATEWAY_NETWORK.
# Pi 5 (main): 10.42.0.1/24 with DHCP 10.42.0.10-254
# R5C (failover): 10.42.1.1/24 with DHCP 10.42.1.10-254
GATEWAY_IP="10.42.1.1"
GATEWAY_PREFIX="24"
GATEWAY_NETWORK="10.42.1.0/24"
DHCP_RANGE_START="10.42.1.10"
DHCP_RANGE_END="10.42.1.254"
+20 -12
View File
@@ -23,6 +23,11 @@ render() { # render <file> -> stdout, with @TOKEN@ placeholders substituted
-e "s|@STARLINK_IFACE@|$STARLINK_IFACE|g" \ -e "s|@STARLINK_IFACE@|$STARLINK_IFACE|g" \
-e "s|@MODEM_USB_VENDOR@|$MODEM_USB_VENDOR|g" \ -e "s|@MODEM_USB_VENDOR@|$MODEM_USB_VENDOR|g" \
-e "s|@DNS_RESOLVERS@|$DNS_RESOLVERS|g" \ -e "s|@DNS_RESOLVERS@|$DNS_RESOLVERS|g" \
-e "s|@GATEWAY_IP@|$GATEWAY_IP|g" \
-e "s|@GATEWAY_PREFIX@|$GATEWAY_PREFIX|g" \
-e "s|@GATEWAY_NETWORK@|$GATEWAY_NETWORK|g" \
-e "s|@DHCP_RANGE_START@|$DHCP_RANGE_START|g" \
-e "s|@DHCP_RANGE_END@|$DHCP_RANGE_END|g" \
"$1" "$1"
} }
install_rendered() { # install_rendered <src> <dst> [mode] install_rendered() { # install_rendered <src> <dst> [mode]
@@ -160,18 +165,21 @@ install -D -m0644 modem/van-sms-watch.service /etc/systemd/system/van-sms-watch.
# are PolicyKit-gated). Not a service, just a tool: sudo van-sms-send <number> <text> # are PolicyKit-gated). Not a service, just a tool: sudo van-sms-send <number> <text>
install -D -m0755 modem/van-sms-send /usr/local/sbin/van-sms-send install -D -m0755 modem/van-sms-send /usr/local/sbin/van-sms-send
echo "== cockpit plugin ==" if [ "$SKIP_COCKPIT" -ne "1" ]; then
install -d /usr/share/cockpit/vanrouter echo "== cockpit plugin =="
for f in cockpit/vanrouter/*; do install -d /usr/share/cockpit/vanrouter
b=$(basename "$f") for f in cockpit/vanrouter/*; do
if [ "$b" = "vanrouter.js" ]; then b=$(basename "$f")
install_rendered "$f" "/usr/share/cockpit/vanrouter/$b" if [ "$b" = "vanrouter.js" ]; then
else install_rendered "$f" "/usr/share/cockpit/vanrouter/$b"
install -m0644 "$f" "/usr/share/cockpit/vanrouter/$b" else
fi install -m0644 "$f" "/usr/share/cockpit/vanrouter/$b"
done fi
# Bridge fd headroom (Python bridge frees spawn pipes only at GC; 1024 is too tight) done
install -D -m0644 cockpit/cockpit-session-nofile.conf /etc/systemd/system/cockpit-session@.service.d/nofile.conf # Bridge fd headroom (Python bridge frees spawn pipes only at GC; 1024 is too tight)
install -D -m0644 cockpit/cockpit-session-nofile.conf /etc/systemd/system/cockpit-session@.service.d/nofile.conf
fi
# The Starlink card queries the dish's gRPC API; grpcurl isn't packaged in apt. # The Starlink card queries the dish's gRPC API; grpcurl isn't packaged in apt.
command -v grpcurl >/dev/null 2>&1 \ command -v grpcurl >/dev/null 2>&1 \
|| warn "grpcurl missing (Starlink card will say so): install linux_arm64 binary from github.com/fullstorydev/grpcurl/releases" || warn "grpcurl missing (Starlink card will say so): install linux_arm64 binary from github.com/fullstorydev/grpcurl/releases"