Skip to content

Integrating with GitOps operators

ConfigHub deploys by publishing, not by pushing. You publish the configuration ConfigHub manages as an immutable bundle on its built-in OCI endpoint, and a GitOps operator already running in your cluster — Argo CD, Flux, or Sveltos — pulls that bundle and reconciles the cluster.

Compared with committing rendered manifests to a Git repository, the operator's role is unchanged. What changes is where it pulls from: ConfigHub becomes the source of the configuration, with versioning, validation, policy enforcement, review, and approval applied before anything is published.

The direction matters. ConfigHub never connects to your cluster. The operator initiates every connection and holds the cluster credentials, exactly as it did before, so ConfigHub needs no access to your infrastructure at all.

The quickest path

cub cluster up provisions a local kind cluster with Argo CD installed and wired to ConfigHub, and cub variant create --target creates the Argo CD Application for each deployment automatically. If that fits, the tutorial walks through it end to end and you can skip the rest of this page.

The sections below cover doing it by hand, against a cluster you already run.

1. Create a Target for the cluster

A Target is the cluster's entry in ConfigHub: a named destination.

cub target create --space platform-dev cluster

2. Point a Space at the Target

Releases are published per Space, and a Space's release Target has to exist before the Space is created — so the Target generally lives in its own Space, as above.

cub space create --release-target platform-dev/cluster app-dev

Units created in app-dev inherit that Target, so they are picked up by a Release with no per-Unit configuration. If you create the Space as a deployment variant instead, cub variant create <name> <base> --target platform-dev/cluster does the same thing.

Find the Space's OCI repository URL:

cub space get app-dev -o jq='.ReleaseURL'

It has the form oci://<host>:<port>/space/<space-slug>.

3. Give the operator a credential

A Space's Releases are served only to callers with permission to view them, and that permission is granted on the Target a Release was published for: to anyone with ViewChildren permission on it. Permissions on the Space are not consulted, so whoever administers the cluster's Target also decides who can pull from it.

The operator's identity is a server Worker: a worker record with no process behind it, whose ID and secret are presented by the operator as registry credentials. Create it with no organization role, so that its access is exactly what has been granted, and give it View and ViewChildren permission on the Target — ViewChildren to pull the Releases, View to find the Target:

cub worker create --space platform-dev --is-server-worker --org-role none argo
ARGO_USER=$(cub worker get --space platform-dev argo -o jq=.BridgeWorker.UserID --quiet)
cub target update --space platform-dev cluster --permission "View:$ARGO_USER" --permission "ViewChildren:$ARGO_USER"

cub cluster up writes the same grants for the worker it creates. argobot, running as that worker, finds its Targets by these grants.

Read the credential back with cub worker get-envs --space platform-dev argo. It prints CONFIGHUB_WORKER_ID and CONFIGHUB_WORKER_SECRET, which are the username and password below.

4. Configure the operator to pull

Argo CD

Create an Application whose source is the Space's release URL. This is the same manifest cub variant create generates:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-dev
  namespace: argocd
spec:
  project: default
  source:
    repoURL: oci://oci.hub.confighub.com:443/space/app-dev
    targetRevision: latest
    path: .
  destination:
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      selfHeal: true
      allowEmpty: true

targetRevision: latest follows the Space's most recent Release, so publishing is what triggers a rollout. To pin a deployment to an exact bundle, use a manifest digest instead — see choosing what the operator follows.

allowEmpty: true matters more than it looks: it lets Argo sync the Application before the first Release is published. The endpoint serves an empty bundle until then, and without it the resource-less sync is an error.

Argo authenticates to the endpoint with a repo-creds Secret in the argocd namespace whose url is a prefix of the Application's repoURL. This is the Secret cub cluster up creates:

apiVersion: v1
kind: Secret
metadata:
  name: confighub-oci-creds
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repo-creds
type: Opaque
stringData:
  type: oci
  url: oci://oci.hub.confighub.com:443
  enableOCI: "true"
  username: <CONFIGHUB_WORKER_ID>
  password: <CONFIGHUB_WORKER_SECRET>

Flux

Create an OCIRepository pointing at the same URL, and a Kustomization that applies it. For Flux, the same credential goes in a kubernetes.io/dockerconfigjson Secret for oci.hub.confighub.com:443, with the worker ID and secret as username and password, referenced from the OCIRepository through secretRef.

Note

The Argo CD manifest above is the one ConfigHub generates itself, so it is exact. The Flux equivalent is not yet generated by any ConfigHub command and should be treated as a starting point — verify it against your Flux version before relying on it.

apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
  name: app-dev
  namespace: flux-system
spec:
  interval: 1m
  url: oci://oci.hub.confighub.com:443/space/app-dev
  ref:
    tag: latest
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: app-dev
  namespace: flux-system
spec:
  interval: 5m
  prune: true
  sourceRef:
    kind: OCIRepository
    name: app-dev
  path: ./

5. Publish

Nothing is live until you publish a Release:

cub release publish app-dev

This bundles every Unit in app-dev assigned to the Space's release Target, captured at each Unit's head revision, and serves it as an immutable OCI artifact. The operator picks it up on its next reconcile.

Publishing is deliberate and separate from editing. Changing configuration in ConfigHub does not change what is running; only a Release does. That separation is what makes review, approval, and controlled promotion possible — see promoting changes and publishing Releases.

To publish a Release pinned to a tagged revision of each Unit rather than its head, pass --revision <tag>. For the full command reference, see Publishing Releases.

Choosing what the operator follows

latest is the newest Release published for the Space's current release Target, which is what most deployments want: publish, and the cluster converges. If the Space is pointed at a different Target, latest starts over for that Target; Releases published for the old one remain pullable by digest.

Following a specific manifest digest instead gives you an explicitly pinned deployment that no publish can move. That is useful for production environments where the rollout should be a deliberate edit to the operator's own configuration. Get the digest from:

cub release list --space app-dev -o wide

Rolling back works either way: publish a Release built from the earlier revisions, or — if a Release for those revisions already exists — move the operator to that Release's digest.

What ConfigHub knows about the result

Exactly which revision of each Unit went into each Release is recorded, so "what is published for this cluster?" always has a precise answer.

What happened after the operator pulled can also come back, if you run something in the cluster that reports it. ConfigHub never connects to your cluster itself.

For Argo CD, that something is argobot — an open-source event consumer that syncs the Application as soon as a Release is published, so a deploy lands immediately instead of at the next reconcile interval, and reports each Application's sync status, health, and operation phase back to ConfigHub as the LiveStatus of the Release the Application is running.

cub cluster up installs argobot by default; pass --no-argobot to skip it. On a cluster you set up yourself it is optional, and without it ConfigHub knows only what it published.

Either way, ConfigHub does not reconcile drift. Argo CD detects drift and self-heals from its source; ConfigHub takes no action on it and offers no way to pull cluster changes back into configuration. See live resources.