Two bugs found bringing the nyc3 segment live (citron hub + lime spoke):
- Hub render ended in `[ -n "$miss" ] && echo`, which returns 1 when no spokes
are unkeyed; under `set -e` that silently aborted `render_conf > tmp` on the
apply path (spokes were fine — they end in printf). Use an if-block.
- `wg syncconf <(wg-quick strip)` used bash process substitution but the script
runs under /bin/sh (dash) — replaced with a POSIX temp file.
Also: nyc3 endpoint -> citron's bound public IP (104.248.9.88), not the reserved
IP (143.244.223.5) — DO routes the reserved IP in but WG replies from the
primary, so the reserved IP can't be a WG endpoint without anchor source-routing.
Verified live: lime<->citron handshake, ping 10.9.0.7 0% loss, citron dnsmasq
resolving *.wg on 10.9.0.7.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>