Skip to main content

GitOps Overview

Purpose

Lumie's infrastructure repo uses Argo CD's app-of-apps pattern to reconcile the cluster from lumie-infra. Ansible only performs the first install of Argo CD and a small set of bootstrap secrets; after that, desired state is expected to flow from Git into Argo CD Applications and then into namespaced workloads.

This page is an overview document for developers changing lumie-infra, bootstrap automation, or the GitOps delivery path. For controller-specific detail, see Argo CD, CI/CD, Gitea, Tekton, and Zot.

Source Paths

PathRole
lumie-infra/provision/ansible/roles/argocd-bootstrap/tasks/main.ymlFirst-install path for Argo CD, bootstrap namespaces, and static MinIO or Vault secrets
lumie-infra/provision/ansible/roles/argocd-bootstrap/defaults/main.ymlRoot app list Ansible applies after Argo CD is ready
lumie-infra/bootstrap/application.yamlRoot Application for the bootstrap subtree, synced at wave -1
lumie-infra/bootstrap/kustomization.yamlBootstrap child order: MinIO, Zot, Vault, then Gitea
lumie-infra/{platform,storage,security,observability,applications}/application.yamlRoot Applications for the remaining GitOps layers
lumie-infra/applications/kustomization.yamlApplication subtree registration, including Tekton, Argo CD self-management, and Lumie services
lumie-infra/applications/cluster-bootstrap/**Cluster-scoped one-shot resources such as ClusterIssuer and default StorageClass

Ownership Boundaries

LayerSource of truthNotes
First installprovision/ansible/roles/argocd-bootstrap/**Installs Argo CD with a minimal Helm release and applies the root Application manifests
Root GitOps treebootstrap/, platform/, storage/, security/, observability/, applications/Each directory owns one root Application CR and the subtree beneath it
Child applicationsapplications/**, platform/**, and peer directoriesIndividual apps own namespace-scoped workload manifests and Helm values
Build outputapplications/tekton/ci-cd/**Tekton builds images and updates deployment values; Argo CD performs the actual rollout

The cluster is not meant to be hand-configured after bootstrap. If a controller, secret, queue, or ingress is required long-term, the desired state should exist in lumie-infra rather than only in the live cluster.

Runtime Flow

The sync ordering visible in code is:

StageEvidence
Root bootstrap subtree before the restbootstrap/application.yaml sets argocd.argoproj.io/sync-wave: "-1"
Cluster-scoped bootstrap before normal applicationsapplications/cluster-bootstrap/argocd.yaml sets sync wave -2
Bootstrap internalsbootstrap/kustomization.yaml orders minio -> zot -> vault -> gitea

Operational Notes

  • All root Applications use automated sync with prune: true and selfHeal: true.
  • applications/argocd/argocd.yaml makes Argo CD self-managed after the initial Ansible install.
  • GitOps access patterns are split: Argo CD root Applications still pull lumie-infra from https://github.com/Lumie-Edu/lumie-infra.git, while the CI/CD path clones and updates repos through in-cluster Gitea. See CI/CD and Gitea.

Contract Drift

Inspected sources do not fully agree on the current GitOps boundary:

SourceClaim
provision/ansible/roles/argocd-bootstrap/defaults/main.ymlBootstrap still lists web-apps/application.yaml in app_of_apps_paths
lumie-infra repo treeNo web-apps/application.yaml path exists in the inspected repo
Live cluster on June 14, 2026Only six root Applications exist; no web-apps root Application is present

Document the six-root model as the active contract until the bootstrap defaults are cleaned up.

There is also a Git host split that needs to stay visible:

SourceClaim
Root Argo CD Applications and Ansible bootstrapPull lumie-infra from GitHub
applications/tekton/ci-cd/manifests/tasks/git-update-values.yamlPushes deployment value changes to http://gitea-http.gitea.svc.cluster.local:3000/Lumie-Edu/lumie-infra.git

The repo does not contain the bridge between those two locations. Treat that as an operational dependency outside the inspected GitOps manifests.

Verification

Use repo and cluster checks together when changing the GitOps slice:

cd lumie-infra
rg -n "sync-wave|app_of_apps_paths|repoURL: https://github.com/Lumie-Edu/lumie-infra.git" \
bootstrap applications platform storage security observability provision/ansible
kubectl get applications -n argocd
kubectl get applications bootstrap platform storage security observability applications -n argocd -o wide

Success signals:

  • Repo checks still show the six checked-in root Application paths plus the cluster-bootstrap child application under applications/.
  • The live cluster shows the six active root applications bootstrap, platform, storage, security, observability, and applications.
  • No root Application named web-apps exists unless the stale Ansible default is reintroduced and backed by a real repo path.