Files
felhom.eu/REPORT.md
T
admin bf099f6a10 docs: SPIKE — offsite-backup connectivity: plain WireGuard wins the ladder (transport decision made)
P0-P7 probe ladder on real ends (demo-felhom PVE host <-> throwaway Hetzner).
Verdict: GO at H1 — plain host-side WG, box-dials-out to a small public endpoint;
Headscale is a separable fleet layer, not a traversal necessity. Line is plain-NAT
(not CGNAT) with zero IPv6 — recorded honestly; CGNAT vantage deferred to Peti VM 110.
Real 2 GiB worst-case PBS backup over the tunnel at the full home uplink, pin intact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-03 22:04:51 +02:00

4.6 KiB
Raw Blame History

felhom.eu — task reports

Overwrite this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in hub/CHANGELOG.md; the scripts history lives in scripts/CHANGELOG.md.


REPORT — SPIKE: offsite-backup connectivity (WireGuard, home-NAT traversal) (2026-07-03)

Docs-only run; evidence doc: documentation/audits/SPIKE-connectivity-wireguard-2026-07-03.md. No production code, no Headscale on the real hub, no agent change, no persistent felhom-pve config.

Verdict

GO at the lowest rung (H1): plain WireGuard, host-side, box-dials-out to a small public endpoint. No coordinator, no relay, no mesh. Headscale (P5: 0.29.2 stood up throwaway) is a separable fleet-management layer — TLS control plane + DB + tailscaled-per-box + Tailscale-hosted DERP by default — not a traversal necessity for hub-and-spoke backup.

Probe ladder results (both ends real: demo-felhom PVE host ⟷ throwaway Hetzner CX23)

  • P0 — the operator's line is plain single-NAT with a fixed public IPv4 (37.191.56.193, catv.fixed.one.hu, AS21334), not CGNAT (no 100.64/10 hop; source IP at the server = egress IP). Zero IPv6 (no address, no egress, 15-min RA capture: 0 packets).
  • P1 (H0 v6-direct) — N/A on this line; keep the production endpoint dual-stack anyway.
  • P2 (H1) — plain WG v4 up on the first try; RTT ~3040 ms; 11.4-min fully-idle hold (keepalive-only, NAT mapping unmoved, instant ping after); PBS 4.2.2 API through the tunnel with the exact-cert pin intact (pin.go model) + negative wrong-pin proof; :8007 tunnel-only by firewall (public probe: unreachable).
  • P3 — uplink is the bottleneck: direct 42 Mbit/s up / 200230 down; tunnel upload ~39 Mbit/s (~5% overhead); PBS TLS benchmark through tunnel 4.94 MB/s = the full uplink; real 2 GiB worst-case (urandom) backup: 4.26 MiB/s sustained, 8 min, zero stalls. First backup 50100 GB ≈ 36 h (overnight window). Oddity recorded: tunnel download (565 Mbit/s, 0 retrans) beat direct TCP (230, 285 retrans) — UDP encapsulation dodges whatever shapes inbound TCP.
  • P4 (H2) — outbound UDP fine on 51820 and 443; no TCP/443 fallback machinery needed.
  • P6 — plain-WG isolation is topological: per-peer /32 AllowedIPs + forwarding off at the endpoint; only the PBS port admitted from the WG interface.
  • P7 — hypothesis refuted with evidence: kernel WG link creation succeeds inside the unprivileged guest (no /dev/net/tun needed — that's confirmed absent and only blocks tailscaled). Host placement therefore stands on architecture: backups originate host-side, the tunnel must survive guest death (cloudflared precedent), the guest keeps zero infra creds.

Architecture recommendation (input to the next task — the production spec)

Host-side agent-managed WG service (cloudflared pattern); per-box keypair minted at install → pubkey to hub, private key 0600 in agent state dir + joins the escrowed IdentityBundle for DR; endpoint = small public dual-stack VM (€48/mo class), two shapes deferred to the spec: PBS-on-VM vs VM-as-rendezvous-relay with DooPlex PBS dialing out too (both ends outbound-only, ciphertext-only transit — also solves DooPlex's no-public-UDP). Trust model preserved: box only dials out; operator-inbound (B) and game-ingress (C) explicitly out of scope.

Honest caveats

CGNAT traversal is argued from mechanism, not proven on this line (it's plain-NAT); second-ISP confirmation deferred to Peti's VM 110 (currently unreachable). Single ISP/evening; no multi-day hold; no home-IP-rotation event observed; Headscale assessed server-side only (no tailscaled on the production host); no restore-direction PBS run.

Cleanup (verified)

demo-felhom: interface/keys/config/dataset gone (keys shredded), iperf3 purged, WG module unloaded, /etc/wireguard untouched-empty, guest probe link deleted — residue-free. Hetzner throwaway: WG + headscale + PBS torn down, secrets shredded, datastore deleted, box powered off (parked for the Peti follow-up or destruction; jarrs.eu box never touched).

Repo changes (docs-only)

  • NEW documentation/audits/SPIKE-connectivity-wireguard-2026-07-03.md (P0P7 verbatim + twelve §7 answers + recommendation).
  • documentation/runbooks/day0-install.md — the "LAN-only until Headscale/WireGuard lands" backlog line now points at the spike (decision made; spec is the remaining gate).
  • CONTEXT.md — transport decision recorded; next task = production connectivity spec.
  • scripts/CHANGELOG.md — docs entry.