When SSH to a Pi targets a WireGuard tunnel address, reachability depends on three things that each fail independently: the unit starting at boot, the NAT mapping staying open, and the peer hostname still resolving. Rebooting onto a network with no route to the endpoint previously meant no way back in. - wg-quick@wg0.service.d/10-boot-resilience.conf: retry a failed boot-time up forever (Restart=on-failure, RestartSec=15, StartLimitIntervalSec=0) and cap endpoint resolution (WG_ENDPOINT_RESOLUTION_RETRIES=60, TimeoutStartSec=120) instead of hanging on the stock infinity. - wg0-watchdog: POSIX sh healer, oldest symptom first - missing interface or peer restarts the unit, a missing PersistentKeepalive is set directly, a stale handshake re-points the peer at a freshly resolved endpoint, and a very stale one restarts. Restarts are gap-limited so a broken network cannot make the unit flap, endpoint resolution falls back to the kernel endpoint and then to a last-known-good cache (tunnel DNS may only be reachable through the tunnel), and nothing it did not create is ever removed. Supports --dry-run. - wg0-watchdog.service/.timer: oneshot on a 60s timer, first check 30s after boot, Persistent=true to catch up after downtime, TimeoutStartSec=120 and Nice=10 so a restart cannot wedge the watchdog. - wg0.conf.template: documents /etc/wireguard/wg0.conf with placeholders only. Deliberately omits the DNS key so name resolution does not depend on the tunnel (Debian wg-quick has no `DNS = none`), and sets PersistentKeepalive 25 to hold the NAT mapping for inbound SSH. - wireguard.md: runbook for the placeholder table, failure modes, deploy, and verification. The real wg0.conf and key material never enter the repo. LLM-Generated: true
18 lines
714 B
Plaintext
18 lines
714 B
Plaintext
# /etc/systemd/system/wg-quick@wg0.service.d/10-boot-resilience.conf
|
|
# The stock unit already has After=/Wants=network-online.target nss-lookup.target.
|
|
# This makes a boot-time failure (DHCP/DNS not ready yet, endpoint host offline)
|
|
# retry forever instead of leaving the tunnel down until someone logs in.
|
|
[Unit]
|
|
# Unlimited retries: do not let the start rate limiter give up on us.
|
|
StartLimitIntervalSec=0
|
|
|
|
[Service]
|
|
# Fail fast instead of hanging forever on endpoint resolution (stock value is
|
|
# infinity), then let Restart= try again. Same variable as the stock unit,
|
|
# later assignment wins.
|
|
Environment=WG_ENDPOINT_RESOLUTION_RETRIES=60
|
|
TimeoutStartSec=120
|
|
TimeoutStopSec=30
|
|
Restart=on-failure
|
|
RestartSec=15
|