Bootstrapping Flux
Flux watches a Git repository and continuously reconciles your cluster toward the state declared there. Any drift — a manually applied change, a deleted resource — gets reverted. Infrastructure updates land by pushing to Git, not by running kubectl.
Prerequisites
Section titled “Prerequisites”- A running cluster (k0s or equivalent)
- The
fluxCLI installed - A GitHub personal access token with Contents and Administration read/write permissions
- Secrets initialized via
kb secrets init(creates the encrypted.env.jsonfile)
How the bootstrap command works
Section titled “How the bootstrap command works”kb flux bootstrap reads your GitHub token from the decrypted secrets file and delegates to flux bootstrap github. It never touches your shell environment directly — the token is injected as GITHUB_TOKEN into the child process only.
kb flux bootstrap \ --secrets-file /path/to/.env.json \ --owner RyanGreenup \ --repository kubernetes-template \ --branch main \ --path clusters/valeThe --path flag scopes the cluster sync to a subdirectory of the repository. Multiple clusters can share one repo by using different paths.
Bootstrap is idempotent. Run it again to upgrade Flux controllers or recover from a broken state.
What bootstrap creates
Section titled “What bootstrap creates”Flux commits two files to <path>/flux-system/ in your repository:
gotk-components.yaml— all Flux controller deployments, CRDs, and RBACgotk-sync.yaml— the rootGitRepositoryandKustomizationthat point Flux back at itself
The gotk-sync.yaml for the local cluster looks like this:
apiVersion: source.toolkit.fluxcd.io/v1kind: GitRepositorymetadata: name: flux-system namespace: flux-systemspec: interval: 1m0s ref: branch: main secretRef: name: flux-system url: ssh://git@github.com/RyanGreenup/kubernetes-template---apiVersion: kustomize.toolkit.fluxcd.io/v1kind: Kustomizationmetadata: name: flux-system namespace: flux-systemspec: interval: 10m0s path: ./clusters/local prune: true sourceRef: kind: GitRepository name: flux-systemFlux pulls from Git every minute and reconciles every ten. The prune: true flag means resources removed from Git get deleted from the cluster.
After bootstrap, pull from the remote repository — Flux commits to the remote, not your local working copy.
Wiring infrastructure overlays
Section titled “Wiring infrastructure overlays”The root Kustomization applies everything under clusters/local/. Place additional Kustomization manifests there to point Flux at your overlay directories. The infrastructure Kustomization for the local cluster uses SOPS decryption:
apiVersion: kustomize.toolkit.fluxcd.io/v1kind: Kustomizationmetadata: name: infrastructure namespace: flux-systemspec: decryption: provider: sops secretRef: name: sops-age interval: 10m0s path: ./infrastructure/overlays/local prune: true sourceRef: kind: GitRepository name: flux-systemThe sops-age secret must exist in the flux-system namespace before Flux attempts to apply any encrypted resources. Create it once per cluster from your age private key:
age-keygen | kubectl create secret generic sops-age \ --namespace=flux-system \ --from-file=age.agekey=/dev/stdinStore the private key in KeePass or another secret store. Use one age key per cluster. SOPS supports multiple recipients, so you can encrypt each secret to several age keys at once if you need cross-cluster access.
Day-to-day operations
Section titled “Day-to-day operations”The CLI exposes three additional subcommands for working with Flux after bootstrap:
# Suspend all kustomizations (e.g. before manual intervention)kb flux pause
# Resume reconciliationkb flux resume
# Trigger an immediate reconcile of the infrastructure kustomizationkb flux reconcile infrastructureSuspending stops Flux from reverting manual changes. Always resume when done — leaving Flux paused means cluster drift goes undetected.
Verifying the bootstrap
Section titled “Verifying the bootstrap”Check that all controllers are running and the initial sync succeeded:
flux checkflux get kustomizations -n flux-systemBoth the flux-system and infrastructure kustomizations should show Applied revision: main@sha1:… with a recent timestamp. A False ready status with a message about missing secrets usually means the sops-age secret was not created before bootstrap ran — create it and trigger a reconcile.