docs(vpn-egress): reflect ADR-0015 node-tunnel egress, retire gluetun narrative

The in-cluster Gluetun gateway is retired; VPN egress is now a node-level host
OpenVPN split-tunnel (Ansible role vpn_egress_gateway) steered by a Cilium
Egress Gateway policy with a host nftables kill-switch (ADR-0015). Credentials
moved host-side to the Ansible vault. Update docs/comments only:

- platform/vpn-egress/README.md: rewrite for ADR-0015 (live + conformance-green);
  drop the resolved "option 1 not viable with Gluetun" finding to a brief history note.
- platform/kustomization.yaml: Phase 3 comment -> node tunnel + Cilium steering.
- platform/kyverno/.../require-egress-class-label.yaml: ADR-0013 -> ADR-0015 steering.
- schemas/servicedefinition.schema.json: egress=vpn description -> node tunnel + Cilium.
- clusters/base/cluster-vars.yaml: reframe PIA_REGION / CLUSTER_POD_CIDR WHY comments
  to ADR-0015 (Cilium excludedCIDRs); both keys retained (still referenced/documented).
- platform/vpn-egress/namespace.yaml: no privileged gateway pod under ADR-0015.
- pia-credentials.sops.yaml / pia-custom-ovpn.sops.yaml: comment headers only note
  they are now UNUSED (creds host-side), retained pending cleanup; payloads untouched.

No runtime manifest behavior, alert exprs, kustomization resources, or SOPS payloads
changed. No spec-repo edits.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-24 14:50:08 -05:00
1 parent 9927b73a5a
commit aafb4ca378
8 files changed
+88 -96

No files matched your search

+12 -11
View File
@@ -37,17 +37,18 @@ data:
KYVERNO_FORCE_FAILURE_POLICY_IGNORE: "false" # dev: "true" (chart forceFailurePolicyIgnore = fail-open)
KYVERNO_ADMISSION_REPLICAS: "3" # dev: 1 (no HA needed to iterate)
# --- egress / VPN (Phase 3, ADR-0013) — consumed by platform/vpn-egress/gluetun-gateway.yaml ---
PIA_REGION: "SE Stockholm" # operator's choice (Sweden). PIA's OpenVPN region name is
# "SE Stockholm" — PF-capable (NOT "SE Streaming Optimized",
# which lacks PF; NOT a US region, which also lack PF)
CLUSTER_POD_CIDR: "10.0.0.0/16" # Gluetun FIREWALL_OUTBOUND_SUBNETS (bypass for steered client pods).
# NARROWED from the /8 cluster-pool: /8 overlaps PIA's tunnel gateway
# 10.31.128.1, so gluetun routed PIA's own PF gateway AROUND the tunnel
# → port forwarding timed out. /16 covers actual pod allocations
# (Cilium assigns /24 per node from 10.0.0.0 up) and excludes 10.31.x.
# NOTE: Phase-3 VPN uses PIA's default OpenVPN UDP port + gluetun's server-list UPDATER (the bundled list
# was stale, dialing retired IPs). Port/region are not cluster-vars (see gluetun-gateway.yaml). See DECISIONS-LOG.
# --- egress / VPN (Phase 3, ADR-0015) — node-level host OpenVPN tunnel steered by Cilium Egress
# Gateway (platform/vpn-egress/egress-steering.yaml). No in-cluster gateway pod. ---
PIA_REGION: "SE Stockholm" # PF-capable PIA region (Sweden). Under ADR-0015 the tunnel is
# host-side (Ansible vault / the node's .ovpn per docs/07), so this
# is now a reference default only — retained, not substituted into
# any manifest. ("SE Stockholm" is PF-capable; NOT "SE Streaming
# Optimized" / a US region, which lack PF.)
CLUSTER_POD_CIDR: "10.0.0.0/16" # Documents the Cilium cluster-pool pod CIDR that the egress-steering
# CiliumEgressGatewayPolicy carves out of the tunnel via excludedCIDRs
# (kept on the LOCAL datapath, never SNAT'd out tun0). The policy
# currently excludes the whole /8 RFC1918 range; this /16 records the
# actual pod allocations (Cilium assigns /24 per node from 10.0.0.0 up).
# --- identity / auth (ADR-0014) ---
KEYCLOAK_REPLICAS: "1" # dev 1 | prod 2 (HA)
+4 -5
View File
@@ -17,11 +17,10 @@ resources:
- cert-manager # Let's Encrypt DNS-01 wildcard — needs SOPS `cloudflare-api-token`
- externaldns # auto DNS records — needs SOPS `cloudflare-api-token`
- gateway # Gateway API listeners (ingress; replaces Traefik)
# ---- Phase 3 — Egress / VPN (PIA OpenVPN-UDP, ADR-0013 amendment). Real root cause of the earlier
# failures: gluetun's bundled PIA server list was STALE (dialing retired 46.246.x IPs → timeouts);
# fix = UPDATER_PERIOD (fetch current servers) + OPENVPN_MTU/MSSFIX 1350 for the Cilium-VXLAN 1450
# pod MTU. See DECISIONS-LOG "Phase 3 VPN". ----
- vpn-egress # shared Gluetun PIA/OpenVPN-UDP egress gateway + kill-switch (ADR-0013)
# ---- Phase 3 — Egress / VPN (ADR-0015): node-level host OpenVPN split-tunnel (Ansible role
# vpn_egress_gateway) steered by a Cilium Egress Gateway policy, with a host nftables kill-switch.
# No in-cluster gateway pod (Gluetun retired). See ADR-0015 + DECISIONS-LOG "Phase 3 VPN". ----
- vpn-egress # CiliumEgressGatewayPolicy steering egress-class=vpn pods to the node tun0 (ADR-0015)
# ---- Phase 4 — Observability (creds provisioned via SOPS: grafana-admin, alertmanager-smtp) ----
- monitoring # kube-prometheus-stack + Loki + Alloy + Alertmanager
# ---- Later phases: enabled when their phase opens ----
@@ -2,7 +2,8 @@
# Spec: docs/03 "Egress is a declared property"; docs/13 `egress: internet | vpn`.
#
# The egress class is enforced OUTSIDE the service (Cilium Egress Gateway selects
# pods by label -> steers `vpn` pods through the shared PIA/Gluetun gateway, ADR-0013).
# pods by label -> steers `vpn` pods out the egress-gateway node's host tun0 VPN
# tunnel, ADR-0015).
# For that steering to be possible the label MUST exist on the pod and be one of the
# two valid classes. A missing/typo'd class would silently fall back to the plain
# internet path -- a fail-OPEN egress leak -- so we require it explicitly (fail-closed
+45 -60
View File
@@ -1,70 +1,55 @@
# platform/vpn-egress — shared VPN egress gateway (Phase 3, ADR-0013)
# platform/vpn-egress — VPN egress steering (Phase 3, ADR-0015)
Single shared **Gluetun** gateway: **PIA over OpenVPN-UDP** (ADR-0013 amendment — Gluetun does not
support PIA over WireGuard), built-in kill-switch, native port forwarding. `vpn`-class services
(sonarr, radarr, jackett, qbittorrent) egress **only** through this tunnel; `internet`-class services
go out the normal WAN. Serves **R-NET-05/06/07**.
`vpn`-class services (sonarr, radarr, jackett, qbittorrent) egress **only** through a PIA VPN
tunnel; `internet`-class services go out the normal WAN. Serves **R-NET-05/06/07**.
> **STATUS: enabled in `platform/kustomization.yaml` (Phase 3).** `pia-credentials` SOPS secret is
> provisioned. Remaining work: validate the tunnel comes up + correct egress IP, then the
> egress-steering mechanism below (the hard part) and the kill-switch conformance test.
Egress is realized per **[ADR-0015](../../../home-network-k3s/decisions/adr-0015-vpn-egress-steering-node-tunnel-cilium.md)**
(spec `docs/03`): a **node-level host OpenVPN split-tunnel** on a labeled egress-gateway node, steered
by a **Cilium Egress Gateway** policy, with a **host nftables kill-switch**. There is **no in-cluster
gateway pod** — the tunnel is host infrastructure, not a Flux workload.
## Pieces
- `gluetun-gateway.yaml` — the Gluetun Deployment (`replicas: 1`, `Recreate`) + the `gluetun-control`
Service (control API :8000 for forwarded-port lookup + tunnel-state health). Kill-switch = `FIREWALL=on`.
- `pia-credentials` (SOPS) — PIA username/password only; Gluetun ships PIA's OpenVPN configs.
> **STATUS: live + conformance-green.** The node tunnel was validated end-to-end; the `egress-class`
> (R-NET-05/07) and `vpn-killswitch` (R-NET-06) conformance tests pass against the live cluster.
## Operator hand-off (when deploying Phase 3)
1. Provision `pia-credentials` (see `bootstrap/sops/secret-templates/pia-credentials.yaml.example`,
namespace `vpn-egress`, keys `username`/`password`) → `sops -e -i` → uncomment it in `kustomization.yaml`.
2. cluster-vars (already defined in `clusters/base/cluster-vars.yaml`; a ConfigMap — values are plain
strings under `data:`, injected into the `${...}` tokens by Flux `postBuild.substituteFrom`). Confirm
or override:
- `PIA_REGION` — a **port-forwarding-capable** PIA region (default `Sweden`; e.g. `Netherlands`,
`CA Toronto`, `Switzerland`; NOT a US region — those lack PF). Gluetun `SERVER_REGIONS`.
- `CLUSTER_POD_CIDR` — the **Cilium cluster-pool** pod CIDR (default `10.0.0.0/8`; pods get `10.x`,
confirmed live — NOT the k3s `10.42.0.0/16`). Gluetun `FIREWALL_OUTBOUND_SUBNETS`.
Per-env overrides go in `clusters/<env>/kustomization.yaml` as a cluster-vars JSON patch
(`- op: replace, path: /data/PIA_REGION, value: "…"`). With the self-managing root, a `git push`
auto-applies (no manual `kubectl apply -k`).
3. Enable `- vpn-egress` in `platform/kustomization.yaml` (Phase 3).
## How it works (ADR-0015)
Three layers, two owners:
## Egress steering — the DESIGN DECISION (needs live validation)
The hard part: routing `vpn`-class pods through this ONE shared tunnel. Cilium Egress Gateway
(`CiliumEgressGatewayPolicy`) SNATs matched pods out of a **gateway node's interface** — it does not
natively route through a *pod's* tunnel. Options considered:
- **Tunnel — host OpenVPN (Ansible).** A labeled egress-gateway node runs a **host OpenVPN systemd
service** (PIA over OpenVPN-UDP — provider/protocol still per ADR-0013). It is **split-tunnel**
(`route-noexec` + policy routing): it creates `tun0` but never becomes the node default route, so the
node's own traffic (control plane, image pulls, other pods) stays on the WAN. Managed by the Ansible
role **`infra/ansible/roles/vpn_egress_gateway/`**, like k3s itself — not a cluster workload.
- **Steering — Cilium Egress Gateway (GitOps).** `egress-steering.yaml` holds a
`CiliumEgressGatewayPolicy` that selects pods labeled `homelab.keithjackson.dev/egress-class=vpn`
(Kyverno-enforced) and SNATs them out the gateway node's `tun0`. Native Cilium eBPF — no client-pod
changes, no sidecar, no overlay. `excludedCIDRs` keeps RFC1918 / cluster / LAN traffic on the local
datapath; only public destinations leave via the tunnel.
- **Kill-switch — host nftables (Ansible).** A host nftables rule on the gateway node DROPS the steered
`vpn`-class traffic whenever `tun0` is down (fail-closed, R-NET-06), scoped to vpn-class only so
`internet`-class and node traffic are unaffected.
1. **Cilium Egress Gateway → the Gluetun node's tunnel interface (recommended).** Pin Gluetun to a
node; a `CiliumEgressGatewayPolicy` selects pods labeled `homelab.keithjackson.dev/egress-class=vpn`
and egresses them via that node's tunnel interface (`tun0`, OpenVPN). If the tunnel drops, `tun0`
is gone → traffic has no egress path → **fail-closed** (the kill-switch behavior R-NET-06 needs). This is the
most Cilium-native fit but requires Gluetun's tunnel interface to be visible to the node datapath
(hostNetwork Gluetun, or a shared netns) — the detail to VALIDATE.
2. **Gateway-pod routing:** client pods default-route to the Gluetun pod IP (init-container +
NET_ADMIN, or a Multus secondary interface); Gluetun forwards+NATs via the tunnel. Works without
Cilium egress gateway but is more moving parts and pod-IP-fragile.
3. **Per-pod Gluetun sidecar** — explicitly REJECTED by ADR-0013 (single shared gateway preferred).
## Secrets — host-side now
PIA credentials + the `.ovpn` live **on the gateway node via Ansible vault** (see spec `docs/07`), **not**
a cluster SOPS Secret. SOPS still governs in-cluster secrets; VPN egress simply no longer needs one.
### FINDING (2026-08-23): option 1 is NOT viable with Gluetun — needs an architect decision
With the tunnel now live (custom-mode Gluetun, PIA Stockholm egress), option 1 fails on inspection:
`CiliumEgressGatewayPolicy interface: tun0` requires `tun0` on the **node**, which means running Gluetun
`hostNetwork: true`. But Gluetun *owns its netns routing* — on connect its `[routing]` logic adds
`0.0.0.0/0` via the tunnel. In hostNetwork that would **redirect the NODE's own default route through the
VPN**, breaking k3s/etcd/kubelet on that node. Gluetun has no supported "create tun0 but don't touch the
default route" mode, so option 1 can't expose `tun0` on the node safely. (The external-router-offload
pattern some use — MikroTik/RouterOS policy routing per pod-subnet — is out of scope: ADR-0013 mandates an
*in-cluster* gateway on a dumb SOHO edge.)
The `pia-credentials.sops.yaml` and `pia-custom-ovpn.sops.yaml` secrets in this directory are **now
UNUSED** — leftovers from the retired Gluetun pod, **retained pending a separate cleanup change**.
**→ Escalated.** The remaining viable path is **option 2 (gateway-pod routing)**: `egress-class=vpn` pods
default-route to the Gluetun pod via an init-container (+NET_ADMIN), and Gluetun forwards+NATs out `tun0`.
More moving parts, and it requires Gluetun to forward for *foreign* pods (not its native same-netns model),
so it needs validation. Kill-switch (R-NET-06) then relies on Gluetun's `FIREWALL=on` dropping non-tunnel
egress. Fixtures for the `egress-class`/`vpn-killswitch` conformance tests are authored; the
`CiliumEgressGatewayPolicy` / steering datapath is intentionally NOT committed until the mechanism is chosen
+ validated, to avoid shipping an untested (and potentially node-breaking) datapath.
## Pieces in this directory
- `namespace.yaml` — the `vpn-egress` namespace (now holds only the Cilium policy + the retained,
unused secrets; no privileged gateway pod under ADR-0015).
- `egress-steering.yaml` — the `CiliumEgressGatewayPolicy` (the steering datapath).
- `pia-credentials.sops.yaml`, `pia-custom-ovpn.sops.yaml` — **unused**, retained pending cleanup.
## History (brief)
ADR-0013 originally placed the VPN in a single shared **Gluetun pod** and deferred the steering
mechanism. Implementation proved that a Gluetun-in-a-pod tunnel **cannot be a Cilium Egress Gateway
target**: the policy SNATs out a *node* interface, but the pod's `tun0` lives in the pod netns, and
running Gluetun `hostNetwork` to expose `tun0` on the node hijacks the node's default route (breaking
k3s/etcd/kubelet). ADR-0015 resolved this by moving the tunnel to the **node** (host OpenVPN
split-tunnel) and steering with Cilium's native egress gateway. See ADR-0015 for the full rationale.
## Port forwarding (qBittorrent) — follow-up
PIA assigns a forwarded port that can change on reconnect. A small **port-sync helper**
(`qbittorrent-natmap`) reads the current port from the `gluetun-control` API (:8000
`/v1/openvpn/portforwarded`) and writes it into qBittorrent, keeping it hands-off (R-UPD). Authored
alongside the qBittorrent app (Phase 6 apps / or here when qBittorrent lands).
PIA assigns a forwarded port that can change on reconnect. Under ADR-0015 this is re-solved **host-side**
(a small pf/natpmp helper on the gateway node that publishes the assigned port to the app) — Phase 6,
alongside the qBittorrent app.
+7 -4
View File
@@ -1,8 +1,11 @@
---
# vpn-egress — the single shared VPN egress gateway namespace (ADR-0013, docs/03).
# Platform INFRA, not an application namespace: the Gluetun gateway needs NET_ADMIN + /dev/net/tun,
# so this ns is deliberately NOT labeled `app-namespace=true` (Kyverno restrict-host-namespaces /
# require-*-label policies scope to app namespaces only — see platform/kyverno).
# vpn-egress — the VPN egress namespace (ADR-0015, docs/03).
# Under ADR-0015 there is NO privileged in-cluster gateway pod: the tunnel is a node-level host
# OpenVPN service (Ansible role vpn_egress_gateway). This namespace now holds only the
# CiliumEgressGatewayPolicy (egress-steering.yaml) plus the retained, now-unused pia-* secrets.
# Platform INFRA, not an application namespace, so it is deliberately NOT labeled `app-namespace=true`
# (Kyverno restrict-host-namespaces / require-*-label policies scope to app namespaces only — see
# platform/kyverno).
apiVersion: v1
kind: Namespace
metadata:
+7 -14
View File
@@ -1,19 +1,12 @@
# =============================================================================
# TEMPLATE — NOT APPLIED, NOT ENCRYPTED (.yaml.example is ignored by kustomize
# and never auto-encrypted by SOPS). Reference scaffold only.
# UNUSED after Gluetun retirement (ADR-0015). This Secret was consumed by the
# in-cluster Gluetun gateway, which no longer exists: VPN egress is now a
# node-level host OpenVPN tunnel steered by Cilium Egress Gateway, and PIA
# credentials live HOST-SIDE in the Ansible vault (see spec docs/07), not here.
#
# (a) Copy to: platform/vpn-egress/pia-credentials.sops.yaml
# (b) kustomization: uncomment `- pia-credentials.sops.yaml` in platform/vpn-egress/kustomization.yaml
# (c) Encrypt: sops -e -i platform/vpn-egress/pia-credentials.sops.yaml
# (d) Consumed by: the Phase-3 Gluetun VPN egress gateway (platform/vpn-egress/gluetun-gateway.yaml),
# which maps username->OPENVPN_USER, password->OPENVPN_PASSWORD. [Phase 3]
#
# VALUE NOTES:
# - username: PIA (Private Internet Access) user, form pNNNNNNN.
# - password: PIA password.
# - Protocol is WireGuard (VPN_TYPE=wireguard, UDP — satisfies "not TCP"). PIA on WireGuard STILL
# authenticates with the username/password below (Gluetun derives the WireGuard config from PIA's
# API at runtime), so these two keys are correct as-is — no extra WireGuard key material needed.
# RETAINED temporarily, pending a separate cleanup change that will remove this
# file and drop it from platform/vpn-egress/kustomization.yaml. Do NOT wire it
# into any workload. The encrypted payload below is left intact.
# =============================================================================
apiVersion: v1
kind: Secret
@@ -1,3 +1,13 @@
# =============================================================================
# UNUSED after Gluetun retirement (ADR-0015). This Secret held the PIA .ovpn
# for the in-cluster Gluetun gateway, which no longer exists: VPN egress is now
# a node-level host OpenVPN tunnel steered by Cilium Egress Gateway, and the
# .ovpn now lives HOST-SIDE in the Ansible vault (see spec docs/07), not here.
#
# RETAINED temporarily, pending a separate cleanup change that will remove this
# file and drop it from platform/vpn-egress/kustomization.yaml. Do NOT wire it
# into any workload. The encrypted payload below is left intact.
# =============================================================================
apiVersion: v1
data:
sweden-aes-128-cbc-udp-ip.ovpn: ENC[AES256_GCM,data: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,iv:F6dC6trQxJzYxWScQWgeH3WcD/o3paf3HE4Joa+2Tfg=,tag:ZDUfSj+pu+iZSFYMOHmvjQ==,type:str]
+1 -1
View File
@@ -46,7 +46,7 @@
},
"egress": {
"type": "string",
"description": "Egress class (docs/03; R-NET-05). internet = default WAN route; vpn = steered through the shared in-cluster Gluetun/PIA gateway with a mandatory kill-switch (R-NET-06).",
"description": "Egress class (docs/03; R-NET-05). internet = default WAN route; vpn = steered by Cilium Egress Gateway out the egress-gateway node's host PIA VPN tunnel, with a mandatory host kill-switch (ADR-0015; R-NET-06).",
"enum": ["internet", "vpn"],
"default": "internet"
},