feat(vpn): enable vpn-egress on OpenVPN-UDP; align docs to ADR-0013 amendment
Gluetun cannot do PIA over WireGuard (upstream unsupported; live "provider name is not valid for Wireguard"). Operator approved OpenVPN-UDP and ADR-0013 was amended in the spec. This aligns the impl: - platform/kustomization.yaml: re-enable `- vpn-egress` (Phase 3, OpenVPN-UDP) - gluetun-gateway.yaml: clean stale WireGuard comments (header, image note, VPN_TYPE/creds comments); config already VPN_TYPE=openvpn - README.md: PIA-over-OpenVPN, status=enabled, steering iface wg0 -> tun0 - DECISIONS-LOG.md: disk/drive incident (k3s -> NVMe; failing Seagate) + Phase-3 OpenVPN resolution Stale WireGuard comments inside the operator's encrypted pia-credentials.sops.yaml header left untouched (editing breaks the SOPS MAC; cosmetic). Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
41da3d96e5
commit
015b423353
4 files changed
+60
-21
No files matched your search
@@ -17,8 +17,8 @@ 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 creds provisioned via SOPS) ----
|
||||
- vpn-egress # shared Gluetun PIA/WireGuard egress gateway + kill-switch (ADR-0013)
|
||||
# ---- Phase 3 — Egress / VPN (PIA creds provisioned via SOPS; OpenVPN-UDP per ADR-0013 amendment) ----
|
||||
- vpn-egress # shared Gluetun PIA/OpenVPN-UDP egress gateway + kill-switch (ADR-0013)
|
||||
# ---- 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 ----
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
# platform/vpn-egress — shared VPN egress gateway (Phase 3, ADR-0013)
|
||||
|
||||
Single shared **Gluetun** gateway: **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**.
|
||||
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**.
|
||||
|
||||
> **STATUS: authored, NOT deployed.** Not wired into `platform/kustomization.yaml` yet. Deploy needs
|
||||
> (a) the `pia-credentials` SOPS secret, and (b) validation of the egress-steering mechanism below,
|
||||
> which cannot be tested without a live PIA tunnel.
|
||||
> **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.
|
||||
|
||||
## 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 derives the WireGuard config at runtime.
|
||||
- `pia-credentials` (SOPS) — PIA username/password only; Gluetun ships PIA's OpenVPN configs.
|
||||
|
||||
## Operator hand-off (when deploying Phase 3)
|
||||
1. Provision `pia-credentials` (see `bootstrap/sops/secret-templates/pia-credentials.yaml.example`,
|
||||
@@ -35,8 +36,8 @@ natively route through a *pod's* tunnel. Options considered:
|
||||
|
||||
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 WireGuard interface (`wg0`). If the tunnel drops, `wg0` is gone →
|
||||
traffic has no egress path → **fail-closed** (the kill-switch behavior R-NET-06 needs). This is the
|
||||
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 +
|
||||
@@ -44,7 +45,7 @@ natively route through a *pod's* tunnel. Options considered:
|
||||
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).
|
||||
|
||||
**Plan:** validate option 1 against a live PIA tunnel (confirm `wg0` on the Gluetun node + a
|
||||
**Plan:** validate option 1 against a live PIA tunnel (confirm `tun0` on the Gluetun node + a
|
||||
`CiliumEgressGatewayPolicy` steering `egress-class=vpn` pods, then run the `egress-class` (R-NET-05/07)
|
||||
and `vpn-killswitch` (R-NET-06) conformance tests). Fall back to option 2 if the interface isn't
|
||||
addressable. The `CiliumEgressGatewayPolicy` is intentionally NOT committed until validated, to avoid
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
# Gluetun — the single shared in-cluster VPN egress gateway (ADR-0013): PIA over WireGuard, with
|
||||
# Gluetun — the single shared in-cluster VPN egress gateway (ADR-0013): PIA over OpenVPN-UDP, with
|
||||
# Gluetun's built-in kill-switch/firewall (fail-closed), health checks, auto-reconnect, and native
|
||||
# port forwarding for qBittorrent. `vpn`-class pods are steered through this gateway (see README.md
|
||||
# "Egress steering" — the Cilium-native mechanism, pending live validation with PIA creds).
|
||||
#
|
||||
# Credentials: the `pia-credentials` SOPS Secret (keys: username, password). Gluetun uses PIA's
|
||||
# username/password (via OPENVPN_USER/OPENVPN_PASSWORD — legacy env names it uses for PIA on BOTH
|
||||
# protocols) to authenticate to PIA's API and derive the WireGuard config at runtime — so WireGuard
|
||||
# needs no extra key material (ADR-0013).
|
||||
# username/password (via OPENVPN_USER/OPENVPN_PASSWORD) to authenticate to PIA. Gluetun ships PIA's
|
||||
# OpenVPN server configs, so no manual `.ovpn` is needed (ADR-0013 amendment: OpenVPN-UDP — Gluetun
|
||||
# does NOT support PIA over WireGuard).
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
@@ -29,9 +29,9 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: gluetun
|
||||
image: qmcgaw/gluetun:v3.41.0 # pinned; Renovate bumps. NOTE: PIA+WireGuard support
|
||||
# requires >= v3.41 (v3.40.0 rejects "private internet
|
||||
# access" as a WireGuard provider — verified at deploy).
|
||||
image: qmcgaw/gluetun:v3.41.0 # pinned; Renovate bumps. PIA is OpenVPN-only in Gluetun
|
||||
# (WireGuard for PIA is unsupported upstream — ADR-0013
|
||||
# amendment; thrnz/docker-wireguard-pia is the WG fallback).
|
||||
securityContext:
|
||||
capabilities:
|
||||
add: ["NET_ADMIN"] # required for the tunnel + firewall
|
||||
@@ -39,8 +39,8 @@ spec:
|
||||
- name: VPN_SERVICE_PROVIDER
|
||||
value: "private internet access"
|
||||
- name: VPN_TYPE
|
||||
value: "openvpn" # UDP — satisfies "protocol != TCP" (R-NET); upgrade over OpenVPN
|
||||
# PIA credentials from the SOPS secret (Gluetun's PIA creds env, used for WireGuard too):
|
||||
value: "openvpn" # OpenVPN-UDP — satisfies "protocol != TCP" (R-NET); ADR-0013 amended
|
||||
# PIA credentials from the SOPS secret (Gluetun's PIA OpenVPN creds env):
|
||||
- name: OPENVPN_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
|
||||
Reference in new issue
Block a user