GitOps & the app-of-apps
Ultron Infra runs on one idea: Git is the desired state, and a controller
continuously makes the cluster match it. You never kubectl apply by hand — you
commit YAML, push, and Argo CD reconciles. This is
GitOps, and it applies the same way to every app on the
platform.
The reconcile loop
Section titled “The reconcile loop”flowchart LR Dev([You]) -->|git push| Repo[(gitops repo)] Repo -->|polls / webhook| Argo[Argo CD] Argo -->|diff desired vs live| K8s[(Kubernetes)] K8s -->|actual state| Argo Argo -->|apply changes| K8s Argo -.->|out of sync? self-heal| K8s
Argo CD compares the manifests in Git against what’s live in the cluster. If they
differ, it applies the difference (and with selfHeal, it reverts any manual drift).
App-of-apps
Section titled “App-of-apps”A single root Application points at the apps/ directory. Every file in apps/
is itself an Argo CD Application that installs one component. So you bootstrap the
entire platform by applying one manifest; everything else cascades.
flowchart TD Root[root Application] --> A[apps/cnpg-operator] Root --> B[apps/keycloak-operator] Root --> C["apps/<app><br/>(e.g. penvoice)"] Root --> D[apps/keycloak-test] A --> A1[CloudNativePG operator] C --> C1[API Rollout + Postgres + ingress] D --> D1[Keycloak instance + Postgres]
Shared infrastructure (operators, the auth server) lives alongside per-app
entries. Each onboarded app — Penvoice today, with Ayde, Talon, and Sonke coming —
is just one more apps/<app> file.
Why it matters: adding a new app is just a new file in apps/ + a folder in
workloads/. Rebuilding from scratch is “install Argo CD → apply the root app →
everything reconciles.” See Onboard an app for the recipe.