Cilium PR2: Hubble UI on hubble.fzymgc.house — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Expose the existing hubble-ui ClusterIP service on hubble.fzymgc.house behind Authentik forward-auth, gated by a new hubble-users group.
Architecture: Dedicated hubble namespace owns Cert + Middleware + IngressRoute; IngressRoute cross-references hubble-ui.kube-system.svc:80. A new ArgoCD Application (in argocd/cluster-app/templates/hubble-ui.yaml) carries resources-finalizer.argocd.argoproj.io and CreateNamespace=true. Authentik integration via tf/authentik/hubble-ui.tf mirrors the temporal.tf pattern (groups → forward_single proxy provider → application → policy bindings); the embedded outpost on authentik-server auto-discovers the new provider — no outpost-registration step required.
Tech Stack: ArgoCD (GitOps), Traefik (IngressRoute + forward-auth Middleware), cert-manager (Certificate via vault-issuer), Authentik (proxy provider + application + groups), Hubble (already deployed via Cilium chart).
Spec: docs/engineering/specs/2026-05-12-cilium-post-migration-hardening-design.md §“PR2: Hubble UI on hubble.fzymgc.house”.
File Structure
Section titled “File Structure”| Path | Action | Purpose |
|---|---|---|
argocd/app-configs/hubble-ui/namespace.yaml | CREATE | Namespace hubble (managed by ArgoCD’s CreateNamespace=true, but explicit manifest keeps labels/annotations declarative) |
argocd/app-configs/hubble-ui/certificate.yaml | CREATE | cert-manager Certificate hubble-tls (vault-issuer ClusterIssuer) |
argocd/app-configs/hubble-ui/traefik-middleware.yaml | CREATE | Traefik Middleware modern-auth (forwardAuth → authentik-server embedded outpost) |
argocd/app-configs/hubble-ui/ingress-route.yaml | CREATE | Traefik IngressRoute hubble-ui (cross-ns service ref to hubble-ui.kube-system.svc:80, router-hosts.fzymgc.house/enabled annotation) |
argocd/app-configs/hubble-ui/kustomization.yaml | CREATE | Bundle the 4 resources |
argocd/cluster-app/templates/hubble-ui.yaml | CREATE | ArgoCD Application for argocd/app-configs/hubble-ui/. MUST include resources-finalizer.argocd.argoproj.io and CreateNamespace=true |
tf/authentik/hubble-ui.tf | CREATE | authentik_group.hubble_users, authentik_group.hubble_admin, authentik_provider_proxy.hubble, authentik_application.hubble, two authentik_policy_binding resources |
docs/operations/hubble-ui.md | CREATE | Operator runbook: how to access, common queries, debugging recipes |
mkdocs.yml | MODIFY | Add nav entry for docs/operations/hubble-ui.md (memory: mkdocs-nav-curated) |
Pre-flight
Section titled “Pre-flight”Task 0: Verify Pre-State and Capture Baseline
Section titled “Task 0: Verify Pre-State and Capture Baseline”Files: none (verification only).
- Step 0.1: Confirm you are in the correct workspace
Run:
jj --no-pager workspace list 2>&1 | head -6pwdExpected: working from a worktree on top of trunk(), no in-flight commits.
- Step 0.2: Confirm Hubble UI is deployed and reachable in-cluster
Run:
kubectl get svc -n kube-system hubble-ui -o jsonpath='{.spec.type}{"\t"}{.spec.clusterIP}{"\t"}{.spec.ports[0].port}{"\n"}'kubectl get pod -n kube-system -l k8s-app=hubble-ui -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'Expected:
- Line 1:
ClusterIP <ip> 80 - Line 2: at least one
hubble-ui-* Runningpod.
If Hubble UI is not running, STOP. The plan assumes it’s deployed via the Cilium chart and reachable cluster-internal.
- Step 0.3: Confirm
hubble.fzymgc.housedoes not yet resolve to anything cluster-routed
Run:
dig +short hubble.fzymgc.houseExpected: empty (no existing route), OR returns a CNAME / A record but kubectl shows no matching IngressRoute (the host is fresh). If a previous attempt exists, surface it before continuing.
- Step 0.4: Confirm the embedded outpost auto-discovery path is healthy
Run:
kubectl run -it --rm authentik-check --image=curlimages/curl --restart=Never --quiet -- \ curl -sS -o /dev/null -w "%{http_code}\n" \ "http://authentik-server.authentik.svc/outpost.goauthentik.io/auth/traefik" \ -H "X-Original-URL: https://temporal.fzymgc.house"Expected: HTTP 302 (redirect to login) — confirms the embedded outpost is serving forward-auth requests. Any other status → investigate before proceeding.
- Step 0.5: Read the existing temporal Authentik integration end-to-end
Run:
cat tf/authentik/temporal.tfYou will pattern-match tf/authentik/hubble-ui.tf on this file. Confirm the structure: group → admin group with parent → proxy provider (forward_single) → application → two policy bindings.
Kubernetes Manifests (commit 1)
Section titled “Kubernetes Manifests (commit 1)”Task 1: Create app-configs/hubble-ui/ Directory
Section titled “Task 1: Create app-configs/hubble-ui/ Directory”Files: all 5 new under argocd/app-configs/hubble-ui/.
- Step 1.1: Start a new commit
Run:
jj --no-pager new -m "feat(hubble-ui): expose Hubble UI on hubble.fzymgc.house via Authentik forward-auth
Adds ArgoCD-managed Hubble UI ingress in a dedicated 'hubble' namespace.The IngressRoute cross-references the existing hubble-ui ClusterIP servicein kube-system (deployed by the Cilium chart). Authentik forward-auth iswired via the existing embedded outpost in authentik-server.
Companion Terraform changes in tf/authentik/hubble-ui.tf provision theAuthentik proxy provider, application, and access groups.
Refs spec: docs/engineering/specs/2026-05-12-cilium-post-migration-hardening-design.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"- Step 1.2: Create the namespace manifest
Write file argocd/app-configs/hubble-ui/namespace.yaml:
apiVersion: v1kind: Namespacemetadata: name: hubble labels: app.kubernetes.io/name: hubble app.kubernetes.io/component: ui-ingress- Step 1.3: Create the Certificate manifest
Write file argocd/app-configs/hubble-ui/certificate.yaml:
# TLS certificate for Hubble UIapiVersion: cert-manager.io/v1kind: Certificatemetadata: name: hubble-tls namespace: hubblespec: secretName: hubble-tls issuerRef: name: vault-issuer kind: ClusterIssuer dnsNames: - hubble.fzymgc.house usages: - server authRationale: matches argocd/app-configs/service-ingresses/longhorn-dashboard.yaml Certificate stanza. vault-issuer is the in-cluster CA backed by Vault PKI (per tf/vault/policy-cert-manager.tf and similar).
- Step 1.4: Create the Traefik Middleware manifest
Write file argocd/app-configs/hubble-ui/traefik-middleware.yaml:
apiVersion: traefik.io/v1alpha1kind: Middlewaremetadata: name: modern-auth namespace: hubblespec: forwardAuth: address: http://authentik-server.authentik.svc/outpost.goauthentik.io/auth/traefik trustForwardHeader: true authResponseHeaders: - Remote-User - Remote-Groups - Remote-Email - Remote-Name - X-authentik-username - X-authentik-groups - X-authentik-entitlements - X-authentik-email - X-authentik-name - X-authentik-uid - X-authentik-jwt - X-authentik-meta-jwks - X-authentik-meta-outpost - X-authentik-meta-provider - X-authentik-meta-app - X-authentik-meta-versionRationale: matches argocd/app-configs/service-ingresses/traefik-dashboard.yaml Middleware (the most complete header allowlist of the existing patterns — strictly a superset of the longhorn header list).
- Step 1.5: Create the IngressRoute manifest
Write file argocd/app-configs/hubble-ui/ingress-route.yaml:
apiVersion: traefik.io/v1alpha1kind: IngressRoutemetadata: name: hubble-ui namespace: hubble annotations: router-hosts.fzymgc.house/enabled: "true"spec: entryPoints: - websecure routes: - match: Host(`hubble.fzymgc.house`) kind: Rule middlewares: - name: modern-auth namespace: hubble services: - name: hubble-ui namespace: kube-system port: 80 tls: secretName: hubble-tlsNote the cross-namespace service reference: name: hubble-ui, namespace: kube-system, port: 80. Traefik must be configured to allow cross-namespace IngressRoute service refs (it is, in this cluster — traefik-dashboard.yaml and longhorn-dashboard.yaml use same-namespace refs but the Helm chart’s providers.kubernetesCRD.allowCrossNamespace is true by default in upstream and confirmed by previous integrations).
- Step 1.6: Create the kustomization manifest
Write file argocd/app-configs/hubble-ui/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomization
resources: - namespace.yaml - certificate.yaml - traefik-middleware.yaml - ingress-route.yaml- Step 1.7: yamllint the new directory
Run:
yamllint argocd/app-configs/hubble-ui/echo "exit: $?"Expected: exit 0.
- Step 1.8: kustomize build sanity check
Run:
kubectl kustomize argocd/app-configs/hubble-ui/ >/tmp/hubble-ui-render.yaml 2>&1echo "exit: $?"grep -c "^kind:" /tmp/hubble-ui-render.yamlExpected: exit 0; kind: count exactly 4 (Namespace + Certificate + Middleware + IngressRoute).
- Step 1.9: Verify commit diff
Run:
jj --no-pager diff --summaryExpected: 5 A entries, all under argocd/app-configs/hubble-ui/.
ArgoCD Application Template (commit 2)
Section titled “ArgoCD Application Template (commit 2)”Task 2: Add hubble-ui Application to cluster-app
Section titled “Task 2: Add hubble-ui Application to cluster-app”Files:
-
Create:
argocd/cluster-app/templates/hubble-ui.yaml -
Step 2.1: Start a new commit
Run:
jj --no-pager new -m "feat(hubble-ui): ArgoCD Application template with cascading finalizer
Adds the hubble-ui Application under cluster-app/templates/, carryingresources-finalizer.argocd.argoproj.io so future teardown cascadescleanly to all child resources (memory: argocd-application-deletion).
syncPolicy uses automated prune+selfHeal and CreateNamespace=true sothe dedicated 'hubble' namespace is bootstrapped on first sync.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"- Step 2.2: Write the Application template
Write file argocd/cluster-app/templates/hubble-ui.yaml:
# SPDX-License-Identifier: MIT-0# ArgoCD Application for Hubble UI ingress# Exposes the Cilium-deployed hubble-ui service on hubble.fzymgc.house# behind Authentik forward-auth. Authentik integration is provisioned# separately by tf/authentik/hubble-ui.tf.apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: hubble-ui namespace: argocd annotations: # Deploy in the standard wave (no special ordering) argocd.argoproj.io/sync-wave: "0" finalizers: - resources-finalizer.argocd.argoproj.iospec: project: observability sources: - repoURL: https://github.com/fzymgc-house/selfhosted-cluster targetRevision: HEAD path: argocd/app-configs/hubble-ui destination: server: https://kubernetes.default.svc namespace: hubble syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true - ServerSideApply=trueThe observability AppProject already groups the cluster’s monitoring-related Applications (grafana-operator, monitoring-prometheus, uptime-kuma, etc.). Hubble UI fits there naturally.
- Step 2.3: Helm-template render of cluster-app
Run (per memory cluster-app-helm-template-trap):
helm template argocd/cluster-app --name-template cluster-app --namespace argocd >/tmp/cluster-app-render.yaml 2>&1echo "exit: $?"grep -A 3 "name: hubble-ui$" /tmp/cluster-app-render.yaml | head -10Expected: exit 0; the Application is in the rendered output with finalizer, syncPolicy, and CreateNamespace=true.
- Step 2.4: yamllint
yamllint argocd/cluster-app/templates/hubble-ui.yamlecho "exit: $?"Expected: exit 0.
- Step 2.5: Verify commit diff
jj --no-pager diff --summaryExpected: 1 A argocd/cluster-app/templates/hubble-ui.yaml.
Authentik Integration (commit 3)
Section titled “Authentik Integration (commit 3)”Task 3: Create tf/authentik/hubble-ui.tf
Section titled “Task 3: Create tf/authentik/hubble-ui.tf”Files:
-
Create:
tf/authentik/hubble-ui.tf -
Step 3.1: Start a new commit
Run:
jj --no-pager new -m "feat(tf/authentik): hubble-ui proxy provider, application, and access groups
Mirrors the temporal.tf integration pattern:- hubble-users group (base) + hubble-admin group (parented)- authentik_provider_proxy in forward_single mode for hubble.fzymgc.house- authentik_application bound to the provider- Two policy bindings (one per group)
The embedded outpost on authentik-server auto-discovers forward_singleproviders, so no outpost registration is needed.
HCP Terraform will plan + apply on PR merge.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"- Step 3.2: Read temporal.tf one more time for line-by-line reference
cat tf/authentik/temporal.tfConfirm the structure you’ll mirror.
- Step 3.3: Write tf/authentik/hubble-ui.tf
# Hubble UI Forward Auth Integration# Provides SSO and group-based access control for the Cilium Hubble UI dashboard# exposed via Traefik ingress at https://hubble.fzymgc.house# (manifests under argocd/app-configs/hubble-ui/, ArgoCD Application# under argocd/cluster-app/templates/hubble-ui.yaml).
# Groups for Hubble UI access controlresource "authentik_group" "hubble_users" { name = "hubble-users"
lifecycle { prevent_destroy = true }}
resource "authentik_group" "hubble_admin" { name = "hubble-admin" parents = [authentik_group.hubble_users.id] is_superuser = false
lifecycle { prevent_destroy = true }}
# Proxy Provider for Hubble UI (Forward Auth mode)resource "authentik_provider_proxy" "hubble" { name = "Provider for Hubble UI" external_host = "https://hubble.fzymgc.house" mode = "forward_single" authorization_flow = data.authentik_flow.default_provider_authorization_explicit_consent.id invalidation_flow = data.authentik_flow.default_provider_invalidation_flow.id
# Token validity access_token_validity = "hours=24"}
# Hubble UI Applicationresource "authentik_application" "hubble" { name = "Hubble UI" slug = "hubble" protocol_provider = authentik_provider_proxy.hubble.id meta_launch_url = "https://hubble.fzymgc.house" meta_description = "Cilium network flow observability dashboard" meta_icon = "https://cilium.io/favicon-32x32.png"
# Policy engine mode: "any" allows access if any bound policy passes policy_engine_mode = "any"}
# Policy to restrict access to hubble-users groupresource "authentik_policy_binding" "hubble_access" { target = authentik_application.hubble.uuid group = authentik_group.hubble_users.id order = 0}
# Grant hubble-admin direct access (workaround for broken group hierarchy)# See: https://github.com/goauthentik/authentik/issues/15159resource "authentik_policy_binding" "hubble_admin_access" { target = authentik_application.hubble.uuid group = authentik_group.hubble_admin.id order = 1}- Step 3.4: Validate Terraform
cd tf/authentik && terraform fmt -check -diff hubble-ui.tf && terraform validate 2>&1; cd -Expected: exit 0. If terraform validate reports a missing provider plugin, run terraform init -backend=false once in tf/authentik/ and retry.
- Step 3.5: Verify commit diff
jj --no-pager diff --summaryExpected: 1 A tf/authentik/hubble-ui.tf.
Documentation (commit 4)
Section titled “Documentation (commit 4)”Task 4: Add Operations Runbook + mkdocs Nav
Section titled “Task 4: Add Operations Runbook + mkdocs Nav”Files:
- Create:
docs/operations/hubble-ui.md - Modify:
mkdocs.yml(nav) - Step 4.1: Start a new commit
Run:
jj --no-pager new -m "docs(hubble-ui): operations runbook + mkdocs nav entry
Adds a short operator-facing runbook covering how to reach Hubble UI,common debugging queries, and the access-group model. Updates themkdocs.yml nav so the new doc is discoverable (memory: mkdocs-nav-curated).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"- Step 4.2: Write docs/operations/hubble-ui.md
# Hubble UI Operations
Operator guide for the Cilium Hubble UI dashboard exposed at[https://hubble.fzymgc.house](https://hubble.fzymgc.house).
## Access
- Auth: Authentik forward-auth via Traefik- Required group: `hubble-users` (or `hubble-admin`)- Add yourself: in Authentik UI (`auth.fzymgc.house`) → Directory → Groups → `hubble-users` → Add member
## Architecture
| Component | Location ||---|---|| Hubble UI service | `hubble-ui.kube-system.svc:80` (deployed by Cilium chart) || TLS certificate | `hubble-tls` Secret in `hubble` namespace (issued by `vault-issuer`) || Forward-auth middleware | `modern-auth` Middleware in `hubble` namespace || IngressRoute | `hubble-ui` IngressRoute in `hubble` namespace, host `hubble.fzymgc.house` || Authentik proxy provider | `Provider for Hubble UI` (forward_single mode) || ArgoCD Application | `hubble-ui` (under `argocd/cluster-app/templates/hubble-ui.yaml`) |
## Common queries
The UI supports filtering live flow data by namespace, source/destination pod,verdict (forwarded vs dropped), HTTP method, and L4 port. Useful operatorqueries:
- **Dropped flows in any namespace** — set Verdict filter to `DROPPED`. Catches policy mismatches and connectivity issues.- **Flows to/from a specific namespace** — set Namespace filter. Use when validating a new CiliumNetworkPolicy rollout (PR3+).- **Service Map view** — visualizes pod-to-pod traffic patterns. Useful for understanding actual cross-namespace dependencies before writing policies.
## Debugging
If `https://hubble.fzymgc.house` returns 502 or stays at the Authentik login:
1. Check the IngressRoute and Middleware exist:
```bash kubectl get ingressroute,middleware -n hubble ```
2. Confirm cert is Ready:
```bash kubectl get certificate -n hubble hubble-tls ```
3. Confirm the upstream Hubble UI service:
```bash kubectl get svc -n kube-system hubble-ui kubectl get pod -n kube-system -l k8s-app=hubble-ui ```
4. Test forward-auth directly against the embedded outpost:
```bash curl -sI -H "X-Original-URL: https://hubble.fzymgc.house" \ http://authentik-server.authentik.svc/outpost.goauthentik.io/auth/traefik ```
Expected: 302 to Authentik login flow.
## Removing access
To revoke a user, remove them from the `hubble-users` group in Authentik UI.Group membership changes propagate within ~60s (Authentik session re-evaluateson next forward-auth request).- Step 4.3: Add nav entry to mkdocs.yml
Edit mkdocs.yml. Find the Operations: section (under nav:). Add a Hubble UI entry, in alphabetical position within the Operations sub-list. The exact line to add (alphabetical placement):
- Hubble UI: operations/hubble-ui.mdIf unsure of the alphabetical spot, run grep -n "operations/" mkdocs.yml and slot the new line so the file paths under Operations: remain alphabetical.
- Step 4.4: rumdl + mkdocs build
rumdl check docs/operations/hubble-ui.mdecho "exit: $?"uvx --with mkdocs-material mkdocs build --strict 2>&1 | tail -10echo "exit: $?"Expected: rumdl exit 0; mkdocs may abort if optional plugins (e.g., git-revision-date-localized) aren’t installed locally, but it MUST NOT report a missing-file error for operations/hubble-ui.md or an unresolved nav entry.
- Step 4.5: Verify commit diff
jj --no-pager diff --summaryExpected: A docs/operations/hubble-ui.md, M mkdocs.yml.
Verification, Push, and PR
Section titled “Verification, Push, and PR”Task 5: Pre-Push Sanity
Section titled “Task 5: Pre-Push Sanity”Files: none (verification only).
- Step 5.1: Full PR contents review
jj --no-pager log -r 'trunk()..@'jj --no-pager diff -r 'trunk()..@' --summaryExpected: 4 commits, file summary:
- 5
Afiles underargocd/app-configs/hubble-ui/ - 1
Afile:argocd/cluster-app/templates/hubble-ui.yaml - 1
Afile:tf/authentik/hubble-ui.tf - 1
Afile:docs/operations/hubble-ui.md - 1
Mfile:mkdocs.yml
Total: 8 A + 1 M.
- Step 5.2: Confirm no incidental files
jj --no-pager diff -r 'trunk()..@' --summary | grep -vE "^A (argocd|tf|docs)|^M mkdocs.yml"Expected: empty. If anything matches, restore it out.
- Step 5.3: lefthook pre-commit
lefthook run pre-commit 2>&1 | tail -20echo "exit: $?"Expected: exit 0.
- Step 5.4: No regression in existing Authentik integrations
Read each tf/authentik/*.tf file you DID NOT create:
ls tf/authentik/ | grep -v hubble-ui.tfYou should not have touched any of these. Confirm with:
jj --no-pager diff -r 'trunk()..@' --summary | grep "tf/authentik"Expected: exactly one line, A tf/authentik/hubble-ui.tf.
Task 6: Push, Open PR, Watch the Rollout
Section titled “Task 6: Push, Open PR, Watch the Rollout”Files: none (push + PR + post-merge verification).
- Step 6.1: Create the bookmark and push
jj --no-pager bookmark create feat/cilium-pr2-hubble-ui -r @jj --no-pager git push -b feat/cilium-pr2-hubble-ui- Step 6.2: Open the PR
gh pr create --head feat/cilium-pr2-hubble-ui --title "feat(hubble-ui): expose Hubble UI on hubble.fzymgc.house (PR2/5)" --body "$(cat <<'EOF'## Summary
Second PR of the cilium-post-migration-hardening initiative. Exposes the existing `hubble-ui` ClusterIP service on `hubble.fzymgc.house` behind Authentik forward-auth.
**Plan:** `docs/engineering/plans/2026-05-12-cilium-pr2-hubble-ui.md` (committed in this PR).
## Changes
Four commits:
1. **Hubble UI manifests** — new `argocd/app-configs/hubble-ui/` directory with Namespace, Certificate (vault-issuer), forward-auth Middleware, and cross-namespace IngressRoute to `hubble-ui.kube-system.svc:80`.2. **ArgoCD Application** — new `argocd/cluster-app/templates/hubble-ui.yaml` with `resources-finalizer.argocd.argoproj.io` and `CreateNamespace=true`.3. **Authentik integration** — new `tf/authentik/hubble-ui.tf` mirroring the temporal.tf pattern: `hubble-users` + `hubble-admin` groups, forward_single proxy provider, application, two policy bindings.4. **Docs** — operator runbook + mkdocs nav entry.
## Test plan
- [ ] HCP Terraform Authentik workspace plan shows: create 2 groups, 1 proxy provider, 1 application, 2 policy bindings. **No destroys.**- [ ] Post-merge: `kubectl get application hubble-ui -n argocd` shows `Synced/Healthy`.- [ ] Post-merge: `kubectl get cert -n hubble hubble-tls` reaches `Ready=True`.- [ ] Post-merge: `dig +short hubble.fzymgc.house` resolves via Traefik.- [ ] Post-merge: anonymous `curl -sI https://hubble.fzymgc.house/` returns `302` to Authentik login.- [ ] Post-merge: after adding self to `hubble-users` group in Authentik UI, browser request to `https://hubble.fzymgc.house` loads the Hubble UI with live flow data.
Refs: spec in `docs/engineering/specs/2026-05-12-cilium-post-migration-hardening-design.md`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)EOF)"Expected: PR URL printed.
- Step 6.3: Verify HCP Terraform plan
Wait for HCP Terraform to comment (~2 min). Confirm the Authentik workspace plan shows:
- 2 creates:
authentik_group.hubble_users,authentik_group.hubble_admin - 1 create:
authentik_provider_proxy.hubble - 1 create:
authentik_application.hubble - 2 creates:
authentik_policy_binding.hubble_access,authentik_policy_binding.hubble_admin_access - No destroys. No drift on other resources.
If any unexpected change appears, STOP; ask before merging.
- Step 6.4: Merge
gh pr merge --squash- Step 6.5: Watch the rollout
Run a state-change monitor (per memory cluster-reconciliation-monitoring) for the hubble-ui Application + namespace + certificate readiness. Exit when all three reach a healthy terminal state:
prev=""; while true; do app=$(kubectl get application hubble-ui -n argocd -o jsonpath='{.status.sync.status}/{.status.health.status}' 2>&1) ns=$(kubectl get ns hubble -o jsonpath='{.status.phase}' 2>&1) cert=$(kubectl get certificate -n hubble hubble-tls -o jsonpath='{range .status.conditions[?(@.type=="Ready")]}{.status}{end}' 2>&1) ingress=$(kubectl get ingressroute -n hubble hubble-ui -o jsonpath='{.metadata.name}' 2>&1) cur="app=$app ns=$ns cert=$cert ingress=$ingress" if [ "$cur" != "$prev" ]; then echo "$(date +%H:%M:%S) $cur"; prev="$cur"; fi echo "$app $ns $cert" | grep -q "Synced/Healthy.*Active.*True" && { echo "TERMINAL: healthy"; break; } sleep 20doneExpected: within ~3 min, app=Synced/Healthy, ns=Active, cert=True, ingress=hubble-ui.
- Step 6.6: End-to-end browser test
-
In Authentik UI (
auth.fzymgc.house), add yourself to thehubble-usersgroup. -
Open
https://hubble.fzymgc.housein a browser. -
Confirm: redirected to Authentik login, log in, redirected back, Hubble UI loads with live flow data.
-
Anonymous (unauthenticated) check from CLI:
Terminal window curl -sI https://hubble.fzymgc.house/ | head -5Expected: HTTP 302 redirect to
auth.fzymgc.house.
- Step 6.7: File no follow-up beads (none expected)
Unlike PR1, PR2 has no orphaned artifacts that defer to follow-ups. The ArgoCD finalizer + label-keyed namespace means future teardown cascades cleanly. Confirm by closing the PR2 tracking bead (filed at start of execution).
Self-Review
Section titled “Self-Review”This implementation plan was checked against the spec on 2026-05-12.
-
Spec coverage — All “Repo changes” items in spec §“PR2: Hubble UI on hubble.fzymgc.house” map to tasks above:
argocd/app-configs/hubble-ui/directory with namespace, certificate, middleware, ingress-route, kustomization → Task 1argocd/cluster-app/templates/hubble-ui.yamlwith finalizer + CreateNamespace=true → Task 2tf/authentik/proxy provider + application + group restriction → Task 3- Documentation runbook + mkdocs nav update (spec §“PR2: Hubble UI … Documentation Pointers”) → Task 4
-
Surface area beyond the spec — none expected; all changes contained to the directories spec named. If audit during implementation surfaces additional references, fold into the appropriate commit.
-
Placeholder scan — no TBDs. Every step has exact commands and exact content.
-
Type/name consistency — Confirmed across tasks:
hubblenamespace name consistent across Task 1.2, 1.3, 1.4, 1.5, 2.2.hubble-tlsCertificatesecretNameand IngressRoutetls.secretNamematch.modern-authMiddleware name consistent with namespace ref in IngressRoute.hubble-users/hubble-admingroup names consistent across Task 3 resources and docs/operations/hubble-ui.md.- Bookmark name
feat/cilium-pr2-hubble-uiconsistent in Task 6.1 and 6.2.