Make the k3s API tunnel-only (ADR-005), stop declaring Flannel VXLAN open to Anywhere, tag the base role so firewall can be scoped, and schedule the Goss declared-vs-live check. CoulombCore sets ufw_manage false so a converge cannot enable UFW there. T02 still needs operator approval for make converge-firewall HOST=Railiance01.
2.1 KiB
ADR-005 — k3s API is tunnel-only
Status: Accepted
Date: 2026-08-15
Deciders: implementation of RAIL-HO-WP-0009-T04
Workplans: RAIL-HO-WP-0009
Context
Operator addresses on this network rotate with the ISP lease. A public UFW
allowlist for 6443/tcp is therefore a treadmill:
- miss a rotation and
kubectlbreaks mid-session - leave the old grant standing and it becomes a grant to a stranger
- hand-add the new address and the declaration drifts again
That cycle produced this workplan. The live allowlist drifted by hand during
the session that was fixing allowlist drift, and again before the next
session (89.244.90.248 appeared undeclared). On 2026-08-15 the workstation
egress address was 85.132.220.102 — already on the revoked list as a
"historic" operator address.
docs/deploy-stack.md already documents API access over the ops-bridge SSH
tunnel for CoulombCore (k3s-api-coulombcore, local port 16443). The same
tunnel already exists for Railiance01 (k3s-api-railiance01, local port
16444). SSH itself stays public, so the host remains recoverable.
Decision
The public k3s API allowlist is empty. Operator and agent kubectl access
uses the ops-bridge tunnels:
| Cluster | Tunnel | Local port | Remote |
|---|---|---|---|
| CoulombCore | k3s-api-coulombcore |
16443 | 6443 |
| Railiance01 | k3s-api-railiance01 |
16444 | 6443 |
bridge up k3s-api-railiance01
# kubeconfig server: https://127.0.0.1:16444
Trade: every operator kubectl action depends on ops-bridge. That is accepted.
A rotating public allowlist is the worse dependency.
Emergency break-glass remains SSH: ssh railiance01 -- sudo k3s kubectl ….
Do not re-open 6443/tcp to Anywhere.
Consequences
k3s_api_allowed_sourcesstays[].- Former public grants live in
k3s_api_revoked_sourcesso a firewall-tagged converge deletes them. - Goss asserts the 6443 allowlist size is exactly the declared length (zero) and that no revoked address remains.
- Amending this ADR is required before adding any new public 6443 source.