diff --git a/scripts/felhom-peersync.sh b/scripts/felhom-peersync.sh index b961021..891a0c5 100644 --- a/scripts/felhom-peersync.sh +++ b/scripts/felhom-peersync.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash -# felhom-peersync v1.0.0 — the offsite endpoint's WG peer-list reconcile script (S1, doc 06 §5). +# felhom-peersync v1.0.1 — the offsite endpoint's WG peer-list reconcile script (S1, doc 06 §5). +# +# v1.0.1 (S2): `wg-quick strip` moved OUT of process substitution — `<(...)` hides the inner +# exit code, so a strip failure (e.g. corrupt head file) could feed syncconf empty/partial input +# that WIPES the live peer set while the script exits 0. Strip now writes a temp file and its +# failure aborts before wg is ever invoked. # # Runs as the SSH forced command for the hub's `felhom-peersync` user (via sudo — see # documentation/runbooks/offsite-endpoint.md step 5). Reads the hub's declarative payload on @@ -58,9 +63,11 @@ jq -r '.peers[] | "\n[Peer]\nPublicKey = \(.pubkey)\nAllowedIPs = \(.allowed_ip) <<<"$payload" >> "$tmp" chmod 600 "$tmp" -# 4. Apply from the TMP file first. On failure we exit here (set -e): the previous good -# LIVE_CONF is still in place — runtime and boot config never diverge in the bad direction. -wg syncconf "$IFACE" <(wg-quick strip "$tmp") || err "wg syncconf failed; live conf untouched" +# 4. Apply from the TMP file first. On failure we exit here: the previous good LIVE_CONF is +# still in place — runtime and boot config never diverge in the bad direction. Strip runs as +# its own step (NOT process substitution, which would swallow its exit code — v1.0.1). +wg-quick strip "$tmp" > "$tmpdir/stripped" || err "wg-quick strip failed; live state untouched" +wg syncconf "$IFACE" "$tmpdir/stripped" || err "wg syncconf failed; live conf untouched" # 5. Persist only after a successful apply (same-fs mv = atomic). mv "$tmp" "$LIVE_CONF"