Admin Guide
You are a platform admin. You've already installed the operator (see the Operator Guide); now you're using the dashboard day-to-day. This guide walks through the tasks you'll actually do, grouped by "what are you trying to accomplish".
Tour
The dashboard has two sidebar groups (both admin-only):
- Platform — the app-platform CRDs. App Registrations and Operator
Configs control onboarding; Platform Secrets controls the ghcr-credentials fanout.
- Flux — read-only views into GitRepositories, Kustomizations,
ImageRepositories/Policies/Automations. Useful when an app deploy looks wrong and you need to see which resource is stuck.
Above that, the per-app sidebar (populated once you select an app) has Deployments, Secrets, and Namespaces — scoped to whichever app is selected.
Onboard a new app
- Pick a name. Use kebab-case, no prefixes — the operator adds
the apps. / -platform bits.
- Create an AppPlatformRegistration. Either:
- Dashboard: *Platform → App Registrations → Create*, or - Git: commit a YAML file under appplatformregistrations/<app>.yaml in the flux repo. Sample:
apiVersion: labrats.work/v1alpha1
kind: AppPlatformRegistration
metadata:
name: my-app
spec:
displayName: My App
namespaces: [my-app-prod]
access:
- { group: myapp-ops, role: admin }
- Wait for Ready=True on the APR. The operator creates the
GitHub platform repo, generates an age keypair + deploy key, and scaffolds the repo contents. The APR surfaces the SSH URL and deploy-key ID on status. OIDC clients are registered separately via labeled Secrets in the <app>-platform namespace (see the Developer Guide).
- Hook the app repo up. In
apps.<app>, push images with
semver tags (no v prefix) and let image-automation in <app>-platform pick them up. See Developer Guide.
Rotate a secret
The operator-managed secrets (deploy key, age key, OIDC client hash) rotate automatically on re-reconcile. For upstream-sourced secrets (anything fanned out by a ClusterExternalSecret or pulled from the ESO store), the flow is:
- Rotate the value in the upstream store (1Password, whatever
the ClusterSecretStore points to).
- Hit *Platform → Platform Secrets →
app-platform-ghcr-credentials
→ Force Sync*. This stamps the force-sync annotation and ESO refetches immediately (skipping the 1h refreshInterval).
- Roll dependent workloads if they don't auto-reload (most do).
For per-app managed secrets committed to the platform repo as platform/*-secret.sops.yaml, edit the SOPS file with sops, commit, and Flux reapplies within 5 minutes.
Force a sync
Several situations need an immediate reconcile:
- After a Flux dep untangle. Annotate a Kustomization:
kubectl annotate kustomization <name> -n flux-system reconcile.fluxcd.io/requestedAt="$(date -u +%FT%TZ)" --overwrite. For ExternalSecrets, use the Force Sync button in the dashboard.
- After rotating an upstream secret — see above.
- After fixing a broken platform repo — edit the APR (even a
no-op annotation change) to trigger operator reconcile.
An app is broken. What do I look at?
In order, cheapest diagnostic first:
- App URL — curl it. 200 / 3xx is fine; 503 means the pod
isn't Running; 401/403 means Authelia redirect.
- Deployments panel on the app's dashboard page — read
top-to-bottom. The first non-green node is the problem. Green GitRepository → Kustomization → Deployment → Pods means the app is healthy.
/api/apps/<app>/pods— via dashboard or curl. Shows
container state + last exit reason.
/api/apps/<app>/events— recent Warning events scoped
to the app's namespaces. Usually tells you FailedToRetrieveImagePullSecret, PolicyViolation, CreateContainerConfigError, etc.
- Operator logs (
kubectl logs -n app-platform deploy/app-platform)
filtered by app name — catches reconcile-level failures the pod events don't see.
- Flux Kustomization status (*Flux* sidebar → Kustomizations)
— health check failed messages name the resource blocking the apply.
For everything else, the disaster-recovery runbook has ten symptom→fix entries for incidents we've actually hit.
Delete an app
- Delete the APR (dashboard or
kubectl delete appplatformregistration <app>).
- The operator finalizer runs best-effort cleanup: removes the
Authelia OIDC client, deletes the GitHub platform repo + deploy key + GHCR packages, drops the platform namespace + RBAC.
- App namespaces are preserved — only RBAC is stripped. If you
want the data gone too, delete each <app>-<env> namespace manually.
What you can't do from the dashboard (yet)
- Create new GitRepositories / ImageRepositories — these are
scaffolded by the operator, read-only in the UI.
- Rotate the cluster-wide age key. Requires rekeying every
per-app SOPS file. Contact the operator maintainers.
- Promote a dev app to prod. Create a new APR in the prod instance
and cut over — there's no in-place switch.