fix(netbird-rotation): match key settings (ephemeral+dns), fill group, enable

Testing #304 end-to-end revealed the minted setup key had the WRONG settings vs the ingress key: ephemeral=false (should be true — peers must be auto-reaped; these DaemonSet peers re-enroll fresh each restart) and allow_extra_dns_labels=false (should be true — the DNS capability). Remediated live and fixed the payload:
- add ephemeral: true, allow_extra_dns_labels: true to the setup-keys POST.
- NB_AUTO_GROUPS = d8umic2oc9cs73d4e1f0 (k8s-ingress-router).
- KEEP the 1y expiry (intentional: an auto-rotated key should expire so a broken rotation surfaces — do NOT match the original's never-expire).
- suspend: false (tested + enabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015K7gLUVVnutvDnzV2TrMRJ
This commit is contained in:
2026-07-19 09:06:50 +02:00
co-authored by Claude Opus 4.8
parent 30561a62a3
commit bbdd488710
@@ -9,18 +9,12 @@
# the netbird-ingress DaemonSet so its peers re-enroll with the new key. Setup
# keys are disposable/reusable by design, so this is inherently low-risk.
#
# ┌─ SUSPENDED (spec.suspend: true) ─────────────────────────────────────────┐
# │ This is UNTESTED scaffolding. Before enabling: │
# │ 1. Provision the bootstrap PAT (see rotator-netbird.hcl). │
# │ 2. FILL IN NB_AUTO_GROUPS below with your real NetBird group IDs — the │
# │ new setup key MUST assign peers to the same groups as the current one │
# │ (GET {mgmt}/api/groups with the PAT to find them), or re-enrolled │
# │ ingress peers land in the wrong group and routing breaks. │
# │ 3. Test on-demand: `kubectl -n openbao create job │
# │ --from=cronjob/netbird-secret-rotate netbird-secret-rotate-test`, │
# │ inspect logs + the resulting key, verify a daemonset pod re-enrolls. │
# │ 4. Only then set spec.suspend: false. │
# └───────────────────────────────────────────────────────────────────────────┘
# Tested + enabled 2026-07-19. The minted key MUST match the ingress key's
# settings: ephemeral=true (peers auto-reaped when offline — these DaemonSet peers
# re-enroll fresh on every restart) and allow_extra_dns_labels=true (the `DNS`
# capability), in the k8s-ingress-router group. It KEEPS a bounded 1y expiry on
# purpose: an auto-rotated key SHOULD expire, so a silently-broken rotation
# eventually surfaces (new enrollments fail) instead of a key living forever.
apiVersion: v1
kind: ServiceAccount
metadata:
@@ -41,7 +35,7 @@ metadata:
app.kubernetes.io/name: netbird-ingress
app.kubernetes.io/component: secret-rotator
spec:
suspend: true # UNTESTED — see header; enable only after bootstrap + manual test
suspend: false # tested + enabled 2026-07-19
schedule: "0 4 1 1,4,7,10 *" # quarterly, Europe/Berlin
timeZone: Europe/Berlin
concurrencyPolicy: Forbid
@@ -83,9 +77,9 @@ spec:
value: http://openbao.openbao.svc.cluster.local:8200
- name: NB_MANAGEMENT_URL
value: "https://netbird.renner.uno"
# FILL IN: comma-separated NetBird group IDs for the new key.
# NetBird group ID(s) for the new key — the k8s-ingress-router group.
- name: NB_AUTO_GROUPS
value: "REPLACE_WITH_GROUP_IDS"
value: "d8umic2oc9cs73d4e1f0"
command: ["python3", "-c"]
args:
- |
@@ -109,7 +103,8 @@ spec:
# 3. mint a new reusable setup key via the NetBird mgmt API
key = call("POST", mgmt + "/api/setup-keys", {"Authorization": "Token " + pat},
{"name": "ingress-rotated", "type": "reusable", "expires_in": 31536000,
"usage_limit": 0, "auto_groups": groups})["key"]
"usage_limit": 0, "ephemeral": True, "allow_extra_dns_labels": True,
"auto_groups": groups})["key"]
# 4. patch the new key into OpenBao (KV v2 merge-patch)
call("PATCH", bao + "/v1/homelab/data/infrastructure/netbird-ingress",
{"X-Vault-Token": tok}, {"data": {"setup-key": key}}, "application/merge-patch+json")