Skip to content
Browse the site

Deep Dives

AI: Claude and Codex patterns

ConfigHub: Deploy and manage

Configs
Stacks
Apps
Plugins
Guides
Docs

Before and after

See which version runs where in a Flux fleet

This Flux fleet spreads over 3 clusters, 4 layers and 42 files, so which version runs where is a question of reading all of them. The plan makes 10 variants of it, and one line answers that question.

What you need. git and cub with the flux plugin. No account and no cluster.

1. See what you have today

The example is a Flux fleet in confighub/examples, with 46 objects across these directories.

DirectoryFiles
apps/9
clusters/13
image-automation/4
infrastructure/8
tenants/8

Each cluster's directory names the layers it runs, the layers have overlays per environment, and image automation writes new tags into the dev overlay of the app.

2. See what ConfigHub would hold

The plan reads all of it and says what ConfigHub would hold. It runs nothing and changes no cluster.

after: the plan for this Flux fleet
$ cub flux plan . --require Healthy
Flux fleet: 3 clusters, 4 layers, 10 variants
Read 46 objects

Clusters, one stage each, in order: dev-1 (clusters/dev), staging-1 (clusters/staging), prod-1 (clusters/prod)
Reconcile order (dependsOn): infrastructure -> apps, tenants -> image-automation

infrastructure
  base     flux-infrastructure-base  from gitops/flux/expert-fleet/infrastructure/base
  helm     edge-router: chart edge-router 2.4.x from HelmRepository platform-charts
  stage dev
    dev-1       variant flux-infrastructure-dev-1  ->  Target flux-targets/dev-1
                Kustomization flux-system/infrastructure, path gitops/flux/expert-fleet/infrastructure/dev
                  label environment=dev
  stage staging
    staging-1   variant flux-infrastructure-staging-1  ->  Target flux-targets/staging-1
                Kustomization flux-system/infrastructure, path gitops/flux/expert-fleet/infrastructure/staging
                  label environment=staging
                  HelmRelease/edge-router replace /spec/values/replicaCount = 2
  stage prod
    prod-1      variant flux-infrastructure-prod-1  ->  Target flux-targets/prod-1
                Kustomization flux-system/infrastructure, path gitops/flux/expert-fleet/infrastructure/prod
                  label environment=prod
                  GitRepository/fleet-repo replace /spec/ref/branch = production
                  HelmRelease/edge-router replace /spec/values/replicaCount = 3

apps  (after infrastructure)
  base     flux-apps-base  from gitops/flux/expert-fleet/apps/base/apptique
  stage dev
    dev-1       variant flux-apps-dev-1  ->  Target flux-targets/dev-1
                Kustomization flux-system/apps, path gitops/flux/expert-fleet/apps/dev
                  adds namespace.yaml
                  namespace apptique-dev
                  label environment=dev
                  image nginx 1.27.3-alpine (written by image automation)
                  Deployment/frontend replace /spec/replicas = 1
                  substitutes cluster_name=dev-1
                  substitutes environment=dev
                  Flux spec.healthChecks[0].namespace = apptique-dev
  stage staging
    staging-1   variant flux-apps-staging-1  ->  Target flux-targets/staging-1
                Kustomization flux-system/apps, path gitops/flux/expert-fleet/apps/staging
                  adds namespace.yaml
                  namespace apptique-staging
                  label environment=staging
                  image nginx 1.27.2-alpine
                  Deployment/frontend replace /spec/replicas = 2
                  substitutes cluster_name=staging-1
                  substitutes environment=staging
                  Flux spec.healthChecks[0].namespace = apptique-staging
  stage prod
    prod-1      variant flux-apps-prod-1  ->  Target flux-targets/prod-1
                Kustomization flux-system/apps, path gitops/flux/expert-fleet/apps/prod
                  adds namespace.yaml
                  namespace apptique-prod
                  label environment=prod
                  image nginx 1.26.3-alpine
                  Deployment/frontend replace /spec/replicas = 4
                  substitutes cluster_name=prod-1
                  substitutes environment=prod
                  Flux spec.healthChecks[0].namespace = apptique-prod
  in flight  nginx: 1.27.3-alpine on dev-1; 1.27.2-alpine on staging-1; 1.26.3-alpine on prod-1

tenants  (after infrastructure)
  base     flux-tenants-base  from gitops/flux/expert-fleet/tenants/base/team-checkout
  stage dev
    dev-1       variant flux-tenants-dev-1  ->  Target flux-targets/dev-1
                Kustomization flux-system/tenants, path gitops/flux/expert-fleet/tenants/dev
                  label environment=dev
                  GitRepository/team-checkout replace /spec/ref/branch = main
  stage staging
    staging-1   variant flux-tenants-staging-1  ->  Target flux-targets/staging-1
                Kustomization flux-system/tenants, path gitops/flux/expert-fleet/tenants/staging
                  label environment=staging
                  GitRepository/team-checkout replace /spec/ref/branch = main
  stage prod
    prod-1      variant flux-tenants-prod-1  ->  Target flux-targets/prod-1
                Kustomization flux-system/tenants, path gitops/flux/expert-fleet/tenants/prod
                  label environment=prod
                  GitRepository/team-checkout replace /spec/ref/branch = production

image-automation  (after apps)
  base     flux-image-automation-base  from gitops/flux/expert-fleet/image-automation
  stage dev
    dev-1       variant flux-image-automation-dev-1  ->  Target flux-targets/dev-1
                Kustomization flux-system/image-automation, path gitops/flux/expert-fleet/image-automation
                  adds imagerepository.yaml
                  adds imagepolicy.yaml
                  adds imageupdateautomation.yaml
  note     one cluster uses this layer, so its whole directory is the base
  note     only on dev-1

Sources
  - HelmRepository platform-charts  oci://ghcr.io/confighub/charts  (gitops/flux/expert-fleet/infrastructure/base/sources/charts.yaml)
  - GitRepository fleet-repo  https://github.com/confighub/examples  (gitops/flux/expert-fleet/infrastructure/base/sources/fleet-repo.yaml)
      branch: dev-1 main, staging-1 main, prod-1 production
  - GitRepository team-checkout  https://github.com/confighub/examples  (gitops/flux/expert-fleet/tenants/base/team-checkout/sync.yaml)
      branch: dev-1 main, staging-1 main, prod-1 production

Writes to Git by itself
  - ImageUpdateAutomation apptique-dev commits to branch main, path gitops/flux/expert-fleet/apps/dev, running on dev-1

Not in Git
  - which chart edge-router runs: HelmRelease edge-router pins it to "2.4.x", so helm-controller decides at reconcile time and what runs can change with no change in ConfigHub. Pin one exact version to close that, and to make a flattening verdict possible
  - what the HelmReleases in infrastructure render: the charts are pulled at reconcile time
  - apps: ${cluster_name}, ${environment}, supplied per cluster by postBuild

Tenants (stay as they are)
  - team-checkout/team-checkout runs as ServiceAccount team-checkout, reading GitRepository team-checkout; governed as part of tenants

Bootstrap (stays outside ConfigHub)
  - gitops/flux/expert-fleet/clusters/dev/flux-system
  - gitops/flux/expert-fleet/clusters/prod/flux-system
  - gitops/flux/expert-fleet/clusters/staging/flux-system

Handover (apply will write it as handover.sh; plan runs nothing)
  1. keep each layer's Flux Kustomization under its own name and switch its sourceRef to an OCIRepository on the ConfigHub gateway, so Flux keeps its inventory and nothing is reinstalled
  2. first prove each variant renders exactly what Git renders today: infrastructure, apps, tenants, image-automation prune, so anything the release lacks is deleted
  3. suspend ImageUpdateAutomation apptique-dev: it would commit to Git that no longer deploys; its tag should become a proposed ConfigHub change on that variant
  4. GitRepository fleet-repo promotes by branch (dev-1 main, staging-1 main, prod-1 production); after handover the ChangeWorkflow's stages decide, not the branch
  5. GitRepository team-checkout promotes by branch (dev-1 main, staging-1 main, prod-1 production); after handover the ChangeWorkflow's stages decide, not the branch
  6. leave flux-system alone: flux bootstrap owns it, like the Sveltos management record

Next
  cub flux apply . --require Healthy --out ./flux-onboarding
  That writes apply.sh, handover.sh and cleanup.sh. It runs nothing.

3. See which version runs where

Each row is a cluster, and each column a layer it runs as a variant in ConfigHub.

Clusterinfrastructureappstenantsimage-automationnginx it runs
dev-1yesyesyesyesnginx 1.27.3-alpine
staging-1yesyesyesnonginx 1.27.2-alpine
prod-1yesyesyesnonginx 1.26.3-alpine

Dev runs the newest version, which image automation wrote there, and staging and prod run older ones, set in their own overlays. In ConfigHub the three clusters are three stages in that order, so a version moves from dev to staging to prod.

4. Try it yourself, with no account

Install cub and the flux plugin as Bring your Flux fleet into ConfigHub shows, first.

# fetch the example at the commit this page was built from
$ git clone https://github.com/confighub/examples.git && git -C examples checkout 7f1b8f2fc849bb6488bc2c58f1469172018fc9dd

$ cd examples/gitops/flux/expert-fleet

# read the plan; it runs nothing
$ cub flux plan . --require Healthy

# write what Flux would run after the handover, and the scripts, to onboard/
$ cub flux apply . --require Healthy --out onboard
See it live in ConfigHub

Everything above runs on your own machine with no account. To see the same example in ConfigHub, load it into your own organization with the commands below.

With your own account

# sign in to your organization
$ cub auth login

# fill ConfigHub with the bases and variants the plan names; it changes no cluster
$ CONFIGHUB_OCI=<gateway> bash onboard/apply.sh

onboard/cleanup.sh takes everything back out. The handover is a separate step in the Flux Guide.

5. Technical notes and disclaimers

  • The plan ran on 2026-10-26 with cub v0.9.0 and flux plugin 0.4.1, inside a checkout of the example. The recorded files and their receipt hold every input and output.
  • The versions are what the repository says each cluster should run, read from its files. Nothing on this page reads a live cluster.