ADR-0015: VPN egress steering — node-level tunnel + Cilium Egress Gateway
The in-cluster Gluetun-pod gateway (ADR-0013) cannot be steered: a pod's tun0 is invisible to the node datapath, and hostNetwork Gluetun hijacks the node's own default route (breaks k3s/etcd). The tunnel itself works (PIA egress validated), but not the steering. New decision (ADR-0015): move the tunnel to a HOST OpenVPN systemd service on egress-gateway node(s) (Ansible-managed, split-tunnel so it doesn't touch the node default route), steer egress-class=vpn pods with a CiliumEgressGatewayPolicy (native eBPF, no client-pod changes), and enforce the kill-switch with a host nftables rule (fail-closed independent of Cilium). PIA/OpenVPN-UDP provider decision (ADR-0013) stands; the .ovpn transfers over; PF re-solved host-side (Phase 6). Amended for consistency: ADR-0013 (client+steering superseded), decisions/README, docs/00, docs/01, docs/03, docs/07, agents/task-board. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
0ba06ec25b
commit
7598cff945
8 files changed
+130
-38
No files matched your search
@@ -50,8 +50,8 @@ Seeded from [`../roadmap/phases.md`](../roadmap/phases.md) + [`../roadmap/workst
|
||||
|---|---|---|---|---|---|---|
|
||||
| T-3.0 | L3 fault-injection harness — **in-cluster Chainsaw Job** (CI-triggered, scoped test SA) using `script`/`try`/`finally` (force tunnel down, kill node, inject bad image, trigger restore) | WS-TEST | R-TEST-05, R-SEC-02 | T-0.4 | — | todo |
|
||||
| T-3.1 | Egress classes; Cilium Egress Gateway wiring (steer `vpn` pods → gateway) | WS-NET | R-NET-04/05 | T-2.2 | — | todo |
|
||||
| T-3.2p | **Prereq:** provide **PIA username/password**; store SOPS-encrypted (PIA purchased) | WS-SEC | R-NET-05 | — | — | todo |
|
||||
| T-3.2 | **Single shared in-cluster PIA/Gluetun gateway** (OpenVPN-UDP, active/standby) + built-in kill-switch + native PF (`qbittorrent-natmap` port-sync) (ADR-0013) | WS-NET | R-NET-05/06 | T-3.1, T-3.2p | — | todo |
|
||||
| T-3.2p | **Prereq:** provide **PIA username/password + `.ovpn`**; store in **Ansible vault** on the egress-gateway node(s) (ADR-0015) | WS-SEC | R-NET-05 | — | — | todo |
|
||||
| T-3.2 | **Node-level PIA/OpenVPN tunnel** (host systemd, Ansible, split-tunnel) on egress-gateway node(s) + **CiliumEgressGatewayPolicy** steering `egress-class=vpn` + **host nftables kill-switch** + host PF helper for qBittorrent (ADR-0015) | WS-NET | R-NET-05/06 | T-3.1, T-3.2p | — | todo |
|
||||
| ~~T-3.3~~ | ~~Edge-router multi-WAN split~~ — **out of scope** (single WAN, dumb SOHO edge; OQ-1) | WS-NET | R-NET-04 | — | — | won't-do |
|
||||
| T-3.4 | Prove: VPN IP egress, **kill-switch fail-closed (central)**, egress-class flip via git | WS-NET | R-NET-05/06/07 | T-3.0, T-3.2 | — | todo |
|
||||
|
||||
@@ -102,6 +102,6 @@ Seeded from [`../roadmap/phases.md`](../roadmap/phases.md) + [`../roadmap/workst
|
||||
|---|---|---|---|
|
||||
| OQ-1 | WAN count + edge router | — | ✅ resolved: 1 WAN, dumb SOHO edge; multi-WAN out of scope; VPN + segmentation in-cluster |
|
||||
| OQ-2 | Bulk-media home | — | ✅ resolved: media outside cluster, backing TBD later (not blocking) |
|
||||
| OQ-3 | VPN provider/protocol | — | ✅ resolved: **PIA** via Gluetun, single shared in-cluster tunnel, **OpenVPN-UDP** + native PF (ADR-0013 amended 2026-08-22; WireGuard not supported for PIA in Gluetun, supersedes 0012) |
|
||||
| OQ-3 | VPN provider/protocol + egress steering | — | ✅ resolved: **PIA over OpenVPN-UDP** (ADR-0013); steering = **node-level host tunnel + Cilium Egress Gateway + host nftables kill-switch** (ADR-0015, supersedes the in-cluster-Gluetun steering — a Gluetun pod's tun0 can't be steered by Cilium egress gateway) |
|
||||
| OQ-4 | DNS-01 challenge access | — | ✅ resolved: scoped **Cloudflare API token** (Zone·DNS·Edit), SOPS-encrypted; drives cert-manager + ExternalDNS. Operator provides token (T-2.4p) |
|
||||
| **OQ-BKP** | **Off-cluster DR backup target** (S3/NFS endpoint) | T-4.3 | ⛔ **OPEN** — needed by Phase 4, not Phase 2 |
|
||||
Reference in new issue
Block a user