Bootstrap and reconciliation
flux/ is the GitOps entrypoint. flux/cluster.yaml — the FluxInstance CR — is applied
once by ansible/roles/flux_bootstrap, and Flux does not reconcile the flux/ directory
itself, to avoid watching its own bootstrap.
Everything else under flux/ is reconciled. flux/infra/ks.yaml and flux/nodes/ks.yaml
are the two Flux Kustomization CRs that point Flux at the matching repo-root directories,
./infra and ./nodes. Those two keep their full spec rather than being patched like every
other ks.yaml, because flux/ has no kustomization.yaml of its own — Flux auto-generates
one from cluster.yaml’s sync.path: flux, and adding a real one would pull cluster.yaml
itself into reconciliation. The rest of the naming and layout rules are in
Layout and naming.
Bootstrap sequence
Run by task ans:k0s (ansible/playbooks/k0s.yml):
k0s_cluster— renderk0sctl.yamlfrom inventory,k0sctl apply, fetch the kubeconfig intoansible/.generated/.local_path_provisioner— install thelocal-pathStorageClass. OpenBao’s StatefulSet needs it to bind its PVC on the very first reconcile, and nothing in the Flux-managed tree can provision it, since OpenBao is the root of that graph.openbao’sprep.yml— create theopenbaoNamespace and the seal Secret (KMIP endpoint, key id, mTLS material, all from Proton Pass) before Flux exists.infra/openbao’s StatefulSet needs both mounted on its first reconcile. See Startup ordering.flux_bootstrap:- Install the Flux Operator via Helm.
- Apply the
flux-system/git-deploy-keySecret, withknown_hostsbuilt from GitHub’s published host keys rather than a blindssh-keyscan. - Wait for the Flux Operator to be ready.
- Push the
edge-ipsConfigMap — the public-ingress node’s public and mesh addresses, straight into the cluster and never into git. See Secrets. - Apply
flux/cluster.yaml. Flux takes over from here, reconcilingopenbaofirst and everything else behind it.
Once OpenBao is up and auto-unsealed, run task bao:policy-sync to finish the
namespace, mount, auth and policy bootstrap. It is idempotent and safe to re-run. It is not
part of the automated sequence above because it needs the OpenBao pod already running.
Day-to-day
task fx:get # every Kustomization and its sync status
task fx:failing # only what isn't Ready
task fx:reconcile # force-reconcile everything, or `-- <name>` for one
task fx:logs # tail kustomize-controller
The full list is in Task reference.