Autonomize · Genesis Downloads

Genesis Downloads · Deployment models

Deployment models

Four ways to get Genesis into a customer cluster: standard Zarf CLI, ArgoCD / GitOps hybrid, CRD pre-apply for restricted clusters, and Helm-only (no Zarf). All paths produce the same end state.


Two bundles, one sequence

The ops bundle must be deployed before the platform bundle in every model. No exceptions — the 5 CRDs and the deploy operator must exist before platform workloads start.

BundleContainsRequired deploy method
genesis-ops-<VER>.tar.zst Genesis Bastion, deploy operator, 5 CRDs, Vin Advisor, health agent, preflight runner, workflow smoke, support-bundle zarf package deploy (imperative — always)
genesis-platform-<VER>.tar.zst Keycloak, APISIX, AI Studio, knowledge center, ~18 services genesis deploy CLI or ArgoCD Application
Ops first, always The platform bundle will fail if ops is not deployed first. The ops bundle is never managed by ArgoCD — it requires zarf package deploy which has side effects (image relocation, in-cluster registry init) that ArgoCD cannot model.

1. Standard model (recommended)

Registry-first CLI path: relocate every image into your registry, let your scanner clear it, then install from there. Scriptable, auditable, and the default for first installs.

# On the gap-host (one-way internet to the portal)
genesis login                                   # paste your sk_... license key
VER=3.6.3                                        # from `genesis releases`
genesis pull $VER -o /tmp/bundles                # both bundles + .sig/.sha256/SBOM
genesis verify /tmp/bundles/genesis-ops-$VER.tar.zst
genesis verify /tmp/bundles/genesis-platform-$VER.tar.zst
genesis push-images --bundle /tmp/bundles/genesis-ops-$VER.tar.zst      --to your-registry.azurecr.io
genesis push-images --bundle /tmp/bundles/genesis-platform-$VER.tar.zst --to your-registry.azurecr.io

# Cross the gap (USB / encrypted SCP), then on the cluster-side host:
genesis verify ./genesis-ops-$VER.tar.zst        # re-verify after transfer
# Deploy ops FROM YOUR REGISTRY — images come through your scanner:
genesis deploy --bundle ./genesis-ops-$VER.tar.zst --registry your-registry.azurecr.io
genesis configure --save --emit-helm-values /tmp/values.yaml
genesis preflight                                # all checks must PASS first
genesis deploy --bundle ./genesis-platform-$VER.tar.zst \
  --registry your-registry.azurecr.io --values /tmp/values.yaml

Bare zarf package deploy also works for ops, but relocates images into Zarf's in-cluster registry (unscanned) — use genesis deploy --registry so the customer scanner sees every image. Full annotated runbook: Install guide.


2. CRD pre-apply (restricted clusters)

For clusters where cluster-admin is unavailable. A DBA or cluster-admin pre-applies the 5 CRDs separately; after that, ops deploy only needs namespace-scoped permissions.

# Pre-apply the CRDs (requires only CRD create permission).
#
# Step 1 — get the ops CHART out of the zarf bundle. The bundle is a
# zstd-compressed tar; the chart is a .tgz nested inside a component tar.
#
# Requires the `zstd` binary (apt-get install zstd / dnf install zstd).
# GNU tar's --zstd flag shells out to the same binary, so it is not an
# alternative. Piping means the bundle's multi-GB image layers are never
# written to disk — only the few MB of chart. It still READS the whole
# stream, so expect this to take a few minutes on a large bundle.
#
# Member paths below are LITERAL on purpose. `components/*.tar` fails on
# GNU tar ("Pattern matching characters used in file names", exit 2)
# unless you add --wildcards, and the ops bundle has three components,
# so a shell glob in step 2 opens the wrong one.
mkdir -p /tmp/genesis-ops-chart && cd /tmp/genesis-ops-chart
zstd -dc /tmp/genesis-ops-$VER.tar.zst | tar -xf - components/ops-chart.tar
tar -xf components/ops-chart.tar
CHART=$(ls */charts/genesis-ops-*.tgz | head -1)
echo "chart: $CHART"

# (Alternative, no zstd binary needed: `zarf tools archiver decompress
#  /tmp/genesis-ops-$VER.tar.zst /tmp/genesis-ops` — but it unpacks the
#  ENTIRE bundle, images included, which needs many GB of free disk.)

# Step 2 — render the CRDs. No cluster access, no values, no credentials.
#
# --kube-version is REQUIRED: the chart pins kubeVersion >=1.28.0-0, and
# `helm template` checks that against your helm BINARY's built-in default,
# never against your cluster. Without it, helm <=3.12 fails with a
# confusing "incompatible with Kubernetes v1.26.0".
#
# `kubectl apply -f chart/templates/crds/` does NOT work: the CRDs are Helm
# templates carrying a `` guard, not plain manifests.

# Apply CRDs (requires only apiextensions.k8s.io/customresourcedefinitions: create)
helm template "$CHART" --show-only 'templates/crds/*' --kube-version 1.28.0 \
  | kubectl apply -f -

# Verify all 5 are served
kubectl get crd | grep genesis
#   genesisdeployments.genesis.autonomize.ai
#   genesisupgrades.genesis.autonomize.ai
#   preflightreports.genesis.autonomize.ai
#   healthreports.genesis.autonomize.ai
#   workflowsmokereports.genesis.autonomize.ai

# Step 2 — deploy ops bundle (no CRD create needed; they exist).
# Registry-first (scanner-gated) — same as the standard model:
genesis deploy --bundle ./genesis-ops-$VER.tar.zst --registry your-registry.azurecr.io
# Or bare Zarf (unscanned in-cluster registry) — pass the LOCAL init
# package you transferred; a bare `zarf init` pulls from ghcr.io and fails
# air-gapped:
#   zarf init ./zarf-init-amd64-<ZARF_VER>.tar.zst --confirm
#   zarf package deploy genesis-ops-$VER.tar.zst --confirm

After this point, day-2 operations only need namespace-scoped access to the genesis namespace.


3. ArgoCD / GitOps hybrid

Ops bundle is deployed once imperatively (always). Platform bundle can be managed by ArgoCD after ops is deployed.

The Bastion generates the Application for you You do not hand-write the ArgoCD Application. In the Configuration step, choose Install method → ArgoCD; after preflight passes, the wizard's Export screen renders a complete Application with your config inlined as valuesObject (no external values.yaml to host). Download it and kubectl apply it. Full walkthrough: runbook-argocd.md.
Why ops is imperative-only zarf init creates a zarf-state Secret and starts an in-cluster registry. zarf package deploy relocates image references to point at that registry. These are ordered, stateful side effects that ArgoCD cannot model without custom Lua scripts. Ops is deployed once; do not add it to ArgoCD.
# Step 1 — ops bundle: one-time imperative (same as standard model).
# Registry-first so images pass your scanner:
genesis deploy --bundle ./genesis-ops-$VER.tar.zst --registry your-registry.azurecr.io
# (bare Zarf alternative — pass the LOCAL init package, never a bare
#  `zarf init` which reaches ghcr.io: zarf init ./zarf-init-*.tar.zst --confirm)

# Step 2 — Configuration → Install method = ArgoCD, then Preflight (adds
#          argocd-pull-secret + argocd-chart-reachable checks). Reach the
#          Bastion by port-forward:
kubectl -n genesis port-forward deploy/genesis-bastion 8020:8020
# open http://localhost:8020 → Configuration → Preflight → Export

# Step 3 — register an OCI credential in YOUR ArgoCD first (else sync 401s).
#          Apply a credential TEMPLATE (not the UI "Connect Repo" entry, which
#          rejects a path in the URL on ArgoCD 3.x):
#            kubectl create secret generic genesis-helm-oci-creds -n argocd \
#              --from-literal=type=helm \
#              --from-literal=url=oci:///helm \
#              --from-literal=enableOCI=true \
#              --from-literal=username= --from-literal=password= \
#              --dry-run=client -o yaml \
#              | kubectl label --local -f - argocd.argoproj.io/secret-type=repo-creds -o yaml \
#              | kubectl apply -f -
#          (matches the Application's oci:///helm/genesis by prefix)

# Step 4 — download the generated Application from the Export screen and apply
#          it to the argocd namespace, then force the first reconcile:
#          (the manifest sets selfHeal:true, so ArgoCD may begin syncing on
#           apply; `argocd app sync` just runs/observes it immediately)
kubectl apply -f genesis-platform-application.yaml
argocd app sync genesis-platform && argocd app wait genesis-platform --health

The exported Application pins the OCI source oci://<your-registry>/helm/genesis (chart genesis under the helm repo — not genesis-platform under charts, which 404s) with your values inlined as valuesObject.

Two gotchas to pre-empt APISIX CRDs: Helm applies a chart's crds/ only on first install; an ArgoCD sync onto a namespace with a prior release skips them (no matches for kind "ApisixRoute"). Apply the APISIX CRDs cluster-wide once before the first sync. ACR token: az acr login --expose-token expires in ~3h and breaks re-syncs — use an ACR scope-map token (AcrPull) in the repo secret instead. Both are detailed in runbook-argocd.md.

To upgrade: deploy new ops bundle imperatively, then update targetRevision in the ArgoCD Application and sync.


4. Helm-only (no Zarf)

For customers who cannot use Zarf due to policy constraints. Requires manual image mirroring with skopeo or equivalent.

# Decompress bundle
zstd -d genesis-platform-$VER.tar.zst -o genesis-platform-$VER.tar
tar -xf genesis-platform-$VER.tar -C /tmp/genesis-bundle/

# Mirror images into your registry FROM THE BUNDLE — they ship inside the
# .tar.zst. Never pull from the vendor registry: it is unreachable from an
# air-gapped cluster, which is the whole reason you are on this path.
genesis push-images --bundle genesis-platform-$VER.tar.zst \
  --to your-registry.internal
genesis push-images --bundle genesis-ops-$VER.tar.zst \
  --to your-registry.internal
# (equivalent manual loop: skopeo copy from the extracted bundle's OCI
#  image layout — oci:/tmp/genesis-bundle/images:<ref> — to your registry)

# Install ops workloads.
#
# deployOperator.zarfStateNamespace: "" is REQUIRED on this path, on the
# first install AND on every upgrade. The chart grants the operator read
# access to zarf's state Secret through a Role in the `zarf` namespace —
# correct when zarf installed the chart, but here you never run
# `zarf init`, so that namespace does not exist and a Role targeting it
# fails the WHOLE helm operation with:
#
#   Error: namespaces "zarf" not found
#
# Put it in your values file rather than passing --set: helm does not carry
# a --set forward on upgrade unless you also pass --reuse-values, so a flag
# has to be remembered every time and a values file does not.
#
#   # /tmp/genesis-platform-values.yaml
#   deployOperator:
#     zarfStateNamespace: ""
helm install genesis-ops /tmp/genesis-bundle/chart/ \
  --namespace genesis --create-namespace \
  --values /tmp/genesis-platform-values.yaml

# Install platform
helm install genesis-platform /tmp/genesis-bundle/chart/ \
  --namespace genesis \
  --values /tmp/genesis-platform-values.yaml

See the Scan bundle page “Without Zarf” section for the full image mirror command list for a given release.


See also

Install guide

Full CLI runbook: authenticate → pull → push-images → configure → preflight → deploy.

Prerequisites

Infra requirements, database list, resource specs, network ports, RBAC, and domain/TLS needs.

SSO configuration

Bundled Keycloak, Azure AD / Entra ID, and Okta OIDC app registration steps.

Scan bundle

Verify cosign signatures, inspect the CycloneDX SBOM, and run Trivy / Grype against bundle images.