Skip to content

GitOps: Gitless Mode

Deploy cluster state via OCI artifacts instead of Git mutations.

Gitless mode is an alternative GitOps delivery model where the GitOps provider (FluxCD) reads reconciled manifests from an OCI registry instead of a Git repository. The gitops repo still exists as the source of truth for authoring, but no commits are pushed to it during CI — instead, CI workflows package manifests into OCI artifacts and push them to the container registry.

The standard Git-based mode writes back to the gitops repo on every build and promotion (updating image tags via git commit + push). This creates noise in git history and requires the CI runner to have write access to the gitops repo on every workflow run.

Gitless mode eliminates those write-backs:

Git modeGitless mode
Cluster state sourcegitops git repoOCI artifact in registry
Build triggers cluster updatevia git commit + pushvia oras push + Flux webhook
Git historyone commit per buildclean — no CI mutations
CI requires git write accessyesno (OCI push only)
Prod gatesuspend: true in binding file, lifted by git commitsame flag, lifted by re-publishing OCI artifact

Instead of FluxCD watching a GitRepository, it watches an OCIRepository — an OCI artifact stored in the container registry. The CI workflows use ORAS and kustomize to build and push manifest bundles directly to the registry.

ArtifactTagContentsUpdated by
<registry>/<org>/gitops-root<env-name>environments/<env>/ treepublish-oci gitops workflow
<registry>/<org>/sample-webapp-devdev-latestkustomize build of overlays/devbuild workflow on merge to main
<registry>/<org>/sample-webapp-prodprod-latestkustomize build of overlays/prodpromote workflow on release
<registry>/<org>/sample-webapp-prpr-<N>-<sha7>kustomize build of overlays/previewpr workflow when preview label added

FluxCD creates an OCIRepository source for each artifact. Each one:

  • Polls the registry every 5 minutes for digest changes
  • Is notified immediately after each oras push via a Flux Receiver webhook called from the CI workflow
  • Uses certSecretRef: name: forgejo-ca-cert to trust the local CA when the registry uses a self-signed certificate

After every oras push, the CI workflow calls the Flux webhook receiver directly via curl:

Terminal window
TOKEN="loko-webhook-v1"
HOOK_PATH=$(echo -n "${TOKEN}" | sha256sum | awk '{print $1}')
PAYLOAD='{}'
SIG=$(echo -n "${PAYLOAD}" | openssl dgst -sha256 -hmac "${TOKEN}" | awk '{print $2}')
curl -sf -X POST \
-H "Content-Type: application/json" \
-H "X-Signature: sha256=${SIG}" \
-d "${PAYLOAD}" \
"http://webhook-receiver.loko-gitops.svc.cluster.local/hook/${HOOK_PATH}"

This is done in-cluster (the runner pods can reach webhook-receiver.loko-gitops.svc.cluster.local) and triggers Flux to reconcile immediately — no waiting for the polling interval.

The webapp-prod Kustomization starts with suspend: true. This prevents any production deployment until an explicit release promotion. On the first promote workflow run:

  1. sed removes suspend: true from the prod binding file (local gitops checkout)
  2. kustomize build overlays/prod packages the manifests with the new image tag
  3. oras push publishes sample-webapp-prod:prod-latestwith the gate removed
  4. oras push re-publishes gitops-root — so the cluster picks up the lifted gate
  5. Flux is notified via webhook and reconciles immediately

Subsequent promotions are gate-free: the sed is a no-op once suspend: true is already gone.

In loko.yaml, set gitless: true under gitops:

gitops:
enabled: true
provider: fluxcd
gitless: true
include-sample-webapp: true
forgejo:
org: my-org

Then re-run init:

Terminal window
loko gitops init

Gitless bootstrap adds one extra step compared to standard mode:

[1/8] Creating GitOps repository...
[2/8] Scaffolding repository...
[3/8] Pushing initial commit...
[4/8] Installing FluxCD...
[5/8] Publishing initial OCI artifact via publish-oci workflow... ← gitless only
[6/8] Registering webhook...
[7/8] Waiting for FluxCD to become ready...
[8/8] Reconciling webhook subscriptions...

Step 5 triggers the publish-oci Forgejo Actions workflow in the gitops repo. This workflow packages the environment manifests and pushes the initial gitops-root OCI artifact so the OCIRepository source has something to read before FluxCD starts reconciling.

The gitops repo scaffolded in gitless mode includes an additional workflow:

gitops/
├── .forgejo/workflows/
│ └── publish-oci.yaml ← gitless only: packages + pushes gitops-root
├── environments/<env>/
│ ├── kustomization.yaml
│ ├── apps/
│ │ ├── webapp-dev.yaml ← OCIRepository + Kustomization (gitless) or Kustomization only
│ │ └── webapp-prod.yaml
│ └── infra/
│ ├── receiver-gitops.yaml
│ ├── receiver-webapp-dev.yaml ← gitless only
│ └── receiver-webapp-prod.yaml ← gitless only
└── init/
├── git-repo.yaml ← OCIRepository in gitless, GitRepository otherwise
└── flux-kustomization.yaml

The publish-oci workflow runs on every push to main in the gitops repo and on workflow_dispatch. This means any manual edit to the gitops repo (such as adding a new app binding) is automatically packaged and pushed to the registry, keeping the OCI artifact in sync with the git state.

The sample-webapp CI workflows behave differently in gitless mode:

StepGit modeGitless mode
Build + push Docker image
Update newTag in gitops overlayvia git commit + pushlocal sed only (no commit)
Package dev manifestskustomize build overlays/dev
Push dev OCI artifactoras push sample-webapp-dev:dev-latest
Notify Fluxvia Forgejo push webhookvia direct curl to Flux receiver
StepGit modeGitless mode
Resolve image tag
Update prod newTagvia git commit + pushlocal sed only
Lift prod gatevia git commitvia OCI re-publish
Push prod OCI artifactoras push sample-webapp-prod:prod-latest
Re-publish gitops-rootoras push gitops-root (with gate removed)
Notify Fluxvia Forgejo push webhooktwo curl calls (prod + gitops-root receivers)

PR preview works the same as in git mode (Docker image push + preview label flow), with one addition: when the preview label is set and the image is pushed, gitless mode also packages the preview overlay manifests and pushes a sample-webapp-pr:<tag> OCI artifact for FluxCD to deploy.