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>
This commit is contained in:
@@ -105,6 +105,17 @@ case "${1:-}" in
|
||||
rm -f "$tmp"
|
||||
[ "$rc" -eq 0 ] && echo "check OK: $(template_files | wc -l) templates render cleanly"
|
||||
exit "$rc" ;;
|
||||
--diff) # ./deploy.sh --diff [conf] — what would change in /etc, without installing
|
||||
load_conf "${2:-$VANLINK_CONF}"
|
||||
grep -E '^[[:space:]]*install_rendered +[^" ]+ +/' deploy.sh | while read -r _ src dst _; do
|
||||
if [ ! -e "$dst" ]; then
|
||||
echo "NEW $dst"
|
||||
elif ! diff -q <(render "$src") "$dst" >/dev/null; then
|
||||
echo "CHANGED $dst"
|
||||
diff -u "$dst" <(render "$src") | sed 's/^/ /' || true
|
||||
fi
|
||||
done
|
||||
exit 0 ;;
|
||||
render)
|
||||
[ -n "${2:-}" ] || { echo "Usage: $0 render <file>"; exit 1; }
|
||||
load_conf "$VANLINK_CONF"
|
||||
@@ -135,8 +146,10 @@ REQUIRED_PACKAGES=(
|
||||
python3-paho-mqtt
|
||||
mobile-broadband-provider-info
|
||||
zerotier-one
|
||||
podman
|
||||
)
|
||||
if [ "$ENABLE_HA" = 1 ]; then
|
||||
REQUIRED_PACKAGES+=(podman)
|
||||
fi
|
||||
OPTIONAL_PACKAGES=(
|
||||
)
|
||||
for pkg in "${REQUIRED_PACKAGES[@]}"; do
|
||||
@@ -175,6 +188,12 @@ write_warnings() {
|
||||
} > "$WARNINGS_FILE"
|
||||
}
|
||||
|
||||
# A host file with uncommitted edits means this deploy uses unreviewed values.
|
||||
conf_real=$(readlink -f "$VANLINK_CONF")
|
||||
if git -c safe.directory='*' -C "$(dirname "$conf_real")" status --porcelain -- "$conf_real" 2>/dev/null | grep -q .; then
|
||||
warn "$conf_real has uncommitted changes — commit it so the host config stays reviewable"
|
||||
fi
|
||||
|
||||
echo "== netplan drift check =="
|
||||
# Netplan is never installed by this script (applying it flaps the uplinks —
|
||||
# see note below), so it's easy to edit ap/50-van-wan.yaml and forget the
|
||||
@@ -300,7 +319,7 @@ if [ "$ENABLE_COCKPIT" = 1 ]; then
|
||||
done
|
||||
# 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
|
||||
fi
|
||||
|
||||
# The Starlink card queries the dish's gRPC API; grpcurl isn't packaged in apt.
|
||||
command -v grpcurl >/dev/null 2>&1 \
|
||||
@@ -321,7 +340,6 @@ python3 -c 'import paho.mqtt' 2>/dev/null \
|
||||
install -D -m0644 router-status/mosquitto-listener.conf /etc/mosquitto/conf.d/van-listener.conf
|
||||
# Restart limit drop-ins: prevent infinite restart loops that trigger hardware watchdog
|
||||
install -D -m0644 router-status/van-gps-owntracks-restart-limit.conf /etc/systemd/system/van-gps-owntracks.service.d/restart-limit.conf
|
||||
install -D -m0644 li3/van-li3-battery-restart-limit.conf /etc/systemd/system/van-li3-battery.service.d/restart-limit.conf
|
||||
|
||||
echo "== gps (cellular modem GNSS -> gpsd) =="
|
||||
if dpkg -s gpsd >/dev/null 2>&1; then
|
||||
@@ -344,20 +362,23 @@ python3 -c 'import gps' 2>/dev/null \
|
||||
python3 -c 'import paho.mqtt' 2>/dev/null \
|
||||
|| warn "python3-paho-mqtt missing (apt install python3-paho-mqtt) — van-gps-owntracks won't start"
|
||||
|
||||
echo "== li3 (RV house battery BMS -> MQTT/HA) =="
|
||||
# NOT the laptop's own AC/battery monitor — that's power/van-battery (different
|
||||
# hardware, different concern). This is the Lithionics Li3 12V LiFePO4 house
|
||||
# battery, over its BLE HM-10 UART module (no pairing) -> Home Assistant MQTT
|
||||
# discovery. Broker + creds live only on the system (0600, seeded from
|
||||
# li3/config.json.example — same pattern as gps/pushover).
|
||||
install -D -m0755 li3/van-li3-battery /usr/local/sbin/van-li3-battery
|
||||
install -D -m0644 li3/van-li3-battery.service /etc/systemd/system/van-li3-battery.service
|
||||
if [ ! -f /etc/van-li3/config.json ]; then
|
||||
install -D -m0600 li3/config.json.example /etc/van-li3/config.json
|
||||
warn "seeded /etc/van-li3/config.json (EDIT IT: add MQTT username + password)"
|
||||
if [ "$ENABLE_LI3" = 1 ]; then
|
||||
echo "== li3 (RV house battery BMS -> MQTT/HA) =="
|
||||
# NOT the laptop's own AC/battery monitor — that's power/van-battery (different
|
||||
# hardware, different concern). This is the Lithionics Li3 12V LiFePO4 house
|
||||
# battery, over its BLE HM-10 UART module (no pairing) -> Home Assistant MQTT
|
||||
# discovery. Broker + creds live only on the system (0600, seeded from
|
||||
# li3/config.json.example — same pattern as gps/pushover).
|
||||
install -D -m0755 li3/van-li3-battery /usr/local/sbin/van-li3-battery
|
||||
install -D -m0644 li3/van-li3-battery.service /etc/systemd/system/van-li3-battery.service
|
||||
install -D -m0644 li3/van-li3-battery-restart-limit.conf /etc/systemd/system/van-li3-battery.service.d/restart-limit.conf
|
||||
if [ ! -f /etc/van-li3/config.json ]; then
|
||||
install -D -m0600 li3/config.json.example /etc/van-li3/config.json
|
||||
warn "seeded /etc/van-li3/config.json (EDIT IT: add MQTT username + password)"
|
||||
fi
|
||||
python3 -c 'import bleak' 2>/dev/null \
|
||||
|| warn "python3-bleak missing (apt install python3-bleak) — van-li3-battery won't start"
|
||||
fi
|
||||
python3 -c 'import bleak' 2>/dev/null \
|
||||
|| warn "python3-bleak missing (apt install python3-bleak) — van-li3-battery won't start"
|
||||
|
||||
echo "== thermal monitor =="
|
||||
install -D -m0755 power/van-thermal /usr/local/sbin/van-thermal
|
||||
@@ -370,24 +391,30 @@ if [ ! -f /etc/van-battery/pushover.json ]; then
|
||||
warn "seeded /etc/van-battery/pushover.json (EDIT IT: add Pushover token + user)"
|
||||
fi
|
||||
|
||||
echo "== nvme watchdog =="
|
||||
install -D -m0755 power/van-nvme-watch /usr/local/sbin/van-nvme-watch
|
||||
install_rendered power/nvme-watch-config.json /etc/van-nvme-watch/config.json
|
||||
install -D -m0644 power/van-nvme-watch.service /etc/systemd/system/van-nvme-watch.service
|
||||
if [ "$ENABLE_NVME_WATCH" = 1 ]; then
|
||||
echo "== nvme watchdog =="
|
||||
install -D -m0755 power/van-nvme-watch /usr/local/sbin/van-nvme-watch
|
||||
install_rendered power/nvme-watch-config.json /etc/van-nvme-watch/config.json
|
||||
install -D -m0644 power/van-nvme-watch.service /etc/systemd/system/van-nvme-watch.service
|
||||
fi
|
||||
|
||||
echo "== home assistant =="
|
||||
# Native HA (Podman Quadlet, replaced the ha_van VM). daemon-reload below
|
||||
# regenerates homeassistant.service; started (not restarted) at the end so a
|
||||
# deploy never bounces HA — after editing the .container, restart it manually.
|
||||
install -D -m0644 ha/homeassistant.container /etc/containers/systemd/homeassistant.container
|
||||
install -d -m0755 /srv/homeassistant
|
||||
# ESPHome dashboard (sibling container, same rationale as HA above — no
|
||||
# Supervisor/add-on store here).
|
||||
install -D -m0644 ha/esphome.container /etc/containers/systemd/esphome.container
|
||||
install -d -m0755 /srv/esphome
|
||||
if [ "$ENABLE_HA" = 1 ]; then
|
||||
install -D -m0644 ha/homeassistant.container /etc/containers/systemd/homeassistant.container
|
||||
install -d -m0755 /srv/homeassistant
|
||||
# ESPHome dashboard (sibling container, same rationale as HA above — no
|
||||
# Supervisor/add-on store here).
|
||||
install -D -m0644 ha/esphome.container /etc/containers/systemd/esphome.container
|
||||
install -d -m0755 /srv/esphome
|
||||
fi
|
||||
# Frigate NVR (sibling container, same rationale as HA/ESPHome above).
|
||||
install -D -m0644 ha/frigate.container /etc/containers/systemd/frigate.container
|
||||
install -d -m0755 /srv/frigate/config /srv/frigate/storage
|
||||
if [ "$ENABLE_FRIGATE" = 1 ]; then
|
||||
install -D -m0644 ha/frigate.container /etc/containers/systemd/frigate.container
|
||||
install -d -m0755 /srv/frigate/config /srv/frigate/storage
|
||||
fi
|
||||
|
||||
echo "== hardware watchdog =="
|
||||
install -D -m0644 power/10-vanlink-watchdog.conf /etc/systemd/system.conf.d/10-vanlink-watchdog.conf
|
||||
@@ -410,24 +437,41 @@ systemctl mask systemd-networkd-wait-online.service >/dev/null 2>&1 || true
|
||||
systemctl unmask hostapd >/dev/null 2>&1 || true
|
||||
# Disable system dnsmasq.service to avoid port 53 conflicts — van-ap-dnsmasq owns AP DHCP
|
||||
systemctl disable dnsmasq.service >/dev/null 2>&1 || true
|
||||
systemctl enable regdomain.service van-br0-setup.service hostapd hostapd-2g van-ap-dnsmasq nftables systemd-networkd van-failover van-thermal van-nvme-watch van-ap-watchdog van-ap-watchdog-2g van-wlan-watchdog van-modem-watch van-sms-watch van-gps-owntracks van-li3-battery van-router-mqtt >/dev/null 2>&1 || true
|
||||
ENABLE_UNITS=(regdomain.service van-br0-setup.service hostapd hostapd-2g van-ap-dnsmasq nftables systemd-networkd van-failover van-thermal van-ap-watchdog van-ap-watchdog-2g van-wlan-watchdog van-modem-watch van-sms-watch van-gps-owntracks van-router-mqtt)
|
||||
if [ "$ENABLE_NVME_WATCH" = 1 ]; then
|
||||
ENABLE_UNITS+=(van-nvme-watch)
|
||||
fi
|
||||
if [ "$ENABLE_LI3" = 1 ]; then
|
||||
ENABLE_UNITS+=(van-li3-battery)
|
||||
fi
|
||||
systemctl enable "${ENABLE_UNITS[@]}" >/dev/null 2>&1 || true
|
||||
# bluetooth: host BlueZ serves the onboard hci0 to the HA container over D-Bus
|
||||
systemctl enable --now bluetooth >/dev/null 2>&1 || true
|
||||
systemctl start homeassistant || warn "homeassistant failed to start (podman/quadlet — check journalctl -u homeassistant)"
|
||||
systemctl start esphome || warn "esphome failed to start (podman/quadlet — check journalctl -u esphome)"
|
||||
systemctl start frigate || warn "frigate failed to start (podman/quadlet — check journalctl -u frigate)"
|
||||
if [ "$ENABLE_HA" = 1 ]; then
|
||||
systemctl start homeassistant || warn "homeassistant failed to start (podman/quadlet — check journalctl -u homeassistant)"
|
||||
systemctl start esphome || warn "esphome failed to start (podman/quadlet — check journalctl -u esphome)"
|
||||
fi
|
||||
if [ "$ENABLE_FRIGATE" = 1 ]; then
|
||||
systemctl start frigate || warn "frigate failed to start (podman/quadlet — check journalctl -u frigate)"
|
||||
fi
|
||||
systemctl restart van-thermal
|
||||
systemctl restart van-nvme-watch
|
||||
if [ "$ENABLE_NVME_WATCH" = 1 ]; then
|
||||
systemctl restart van-nvme-watch
|
||||
fi
|
||||
systemctl restart van-sms-watch
|
||||
systemctl restart van-gps-owntracks
|
||||
systemctl restart van-li3-battery
|
||||
if [ "$ENABLE_LI3" = 1 ]; then
|
||||
systemctl restart van-li3-battery
|
||||
fi
|
||||
systemctl restart van-router-mqtt
|
||||
# Pick up unmanaged-devices changes so NM releases/keeps the right interfaces.
|
||||
nmcli general reload 2>/dev/null || systemctl reload NetworkManager 2>/dev/null || true
|
||||
# restart in dependency order: bridge + members first, then hostapd enslaves the
|
||||
# radios, then dnsmasq binds br0, then NAT/failover
|
||||
systemctl restart systemd-networkd
|
||||
systemctl restart van-ap-dnsmasq nftables van-failover van-wlan-watchdog
|
||||
for u in van-ap-dnsmasq nftables van-failover van-wlan-watchdog; do
|
||||
systemctl restart "$u" || warn "$u failed to restart (journalctl -xeu $u)"
|
||||
done
|
||||
# The AP radios live on the USB hub and may be absent; the start then fails but
|
||||
# Restart=always keeps retrying and claims them the moment they enumerate.
|
||||
systemctl restart hostapd hostapd-2g \
|
||||
|
||||
@@ -69,4 +69,32 @@ else
|
||||
ok "van: unmanaged-devices has no eth0"
|
||||
fi
|
||||
|
||||
# 6. flagged units/paths only appear inside their ENABLE_* guard in deploy.sh.
|
||||
# Convention: guards are column-0 `if [ "$ENABLE_X" = 1 ]; then` ... `fi`,
|
||||
# contents indented (so a nested `fi` never sits in column 0).
|
||||
if awk '
|
||||
BEGIN {
|
||||
need["van-li3-battery"]="ENABLE_LI3"
|
||||
need["van-nvme-watch"]="ENABLE_NVME_WATCH"
|
||||
need["nvme-watch-config"]="ENABLE_NVME_WATCH"
|
||||
need["homeassistant"]="ENABLE_HA"
|
||||
need["esphome"]="ENABLE_HA"
|
||||
need["frigate"]="ENABLE_FRIGATE"
|
||||
need["cockpit"]="ENABLE_COCKPIT"
|
||||
}
|
||||
/^if \[ "\$ENABLE_[A-Z0-9_]+" = 1 \]/ { match($0, /ENABLE_[A-Z0-9_]+/); guard=substr($0, RSTART, RLENGTH); next }
|
||||
/^fi([[:space:]]|$)/ { guard=""; next }
|
||||
/^[[:space:]]*(#|echo)/ { next }
|
||||
{ for (u in need) if (index($0, u) && guard != need[u]) {
|
||||
printf " deploy.sh:%d mentions %s outside an %s guard: %s\n", NR, u, need[u], $0; bad=1 } }
|
||||
END { exit bad }
|
||||
' deploy.sh; then ok "flagged units are only touched inside their ENABLE_* guard"; else bad "flag gating"; fi
|
||||
|
||||
# 8. ./deploy.sh --diff runs (no root) and lists rendered files
|
||||
if out=$(./deploy.sh --diff hosts/van.conf 2>&1) && echo "$out" | grep -qE '^(NEW|CHANGED) '; then
|
||||
ok "deploy.sh --diff hosts/van.conf"
|
||||
else
|
||||
bad "deploy.sh --diff hosts/van.conf"; echo "$out" | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
exit "$fail"
|
||||
|
||||
Reference in New Issue
Block a user