The recommended public-preview install path is the Helm chart package attached
to the GitHub Release. It installs the CRDs, controller Deployment,
ServiceAccount, RBAC, admission webhooks, and baseline approval service
together. The 0.6.0 chart defaults to
ghcr.io/kapro-dev/kapro-operator:v0.6.0.
- Kubernetes cluster access with permission to create CRDs and cluster-scoped RBAC.
- Helm 3.
- Docker, Kind, and
kubectlwhen you want to run the local examples on a disposable cluster. - Go 1.25+ when you want the optional
kaproCLI from source. - ORAS when you want to run OCI artifact examples locally.
The chart has no other dependencies. By default the admission webhook uses an auto-generated self-signed serving certificate, so cert-manager is not required to install. Production clusters that already run cert-manager can opt back in (see below).
For production change windows, verify the pinned chart, image signatures, SBOM attestations, and provenance before installing. See Release Verification.
KAPRO_VERSION=0.6.0
KAPRO_CHART="https://github.com/Kapro-dev/kapro/releases/download/v${KAPRO_VERSION}/kapro-operator-${KAPRO_VERSION}.tgz"
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--waitThat is the full install for kind, k3d, EKS without the cert-manager add-on, and any other cluster where you do not have cert-manager installed.
For development from a local checkout, set
KAPRO_CHART=charts/kapro-operator instead of using the release URL.
The remaining Helm examples use the same KAPRO_CHART value.
The operator can be used with kubectl alone. Install the CLI when you want
guided repository scaffolding, existing-repo discovery, promotion creation, or
diagnostics:
git clone --branch main https://github.com/Kapro-dev/kapro.git
cd kapro
make build
export PATH="$PWD/bin:$PATH"
kapro bootstrap guideThis source-built path intentionally tracks main until the bootstrap command
is included in a tagged CLI release.
From an existing local checkout:
make build
export PATH="$PWD/bin:$PATH"
kapro bootstrap guideIf you already run cert-manager (≥ 1.5) and prefer its certificate lifecycle, enable the cert-manager path:
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set webhook.certManager.enabled=trueThe chart then emits a cert-manager Issuer + Certificate and annotates the webhook configs for caBundle injection. No chart-managed Secret is created in that mode.
If you want the smallest possible install (no webhook = no admission validation of CRD invariants), turn the webhook off entirely:
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set webhook.enabled=falseNot recommended for production — the webhook is where multi-tenancy
ownership labels, controller-only writes to PromotionRun, and
Plan DAG validity is enforced.
Useful baseline settings:
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set externalURL=https://kapro.example.com \
--set hubAPIURL=https://hub.example.com:6443externalURL is used in approval links and optional Decision API callbacks.
hubAPIURL should be the hub API server URL reachable from spoke clusters.
The default install runs the ADR-0010 core controllers plus the 0.6 substrate
readiness controllers: fleet, plan, promotion, promotionrun, cluster,
deliveryunit, substrateclass, and substrate. The target controller is an implicit
dependency of promotionrun and starts with it. Users normally author
DeliveryUnit, Fleet, Plan, and Promotion; controllers derive Source
and Trigger objects and generate or update Cluster, PromotionRun, and
Target records.
Preview surfaces are available for early adopters but should be enabled or exposed deliberately:
| Surface | Default | Enablement |
|---|---|---|
Decision API and Policy |
Disabled | decisionAPI.enabled=true and explicit Kubernetes RBAC. |
| SubstrateClass status controller | Enabled | Keep substrateclass in controllers when using Substrate.spec.classRef and typed substrate config CRDs. |
| Substrate readiness controller | Enabled | Keep substrate in controllers and wait for Substrate Ready before applying generated Cluster objects. |
| Approval controller | Disabled | Add approval to controllers when human approval objects should unblock gates. |
| Trigger controller | Disabled | Add trigger to controllers for autonomous artifact-driven promotions. |
| Plugin controller | Disabled | Add plugin to controllers so Plugin.status readiness is reconciled. |
| Plugin gateway runtime dispatch | Disabled | pluginGateway.enabled=true plus plugin in controllers, installed plugin services, and Plugin objects. |
| Hub Gateway service exposure | Internal only | hubGateway.service.enabled=true; place Kubernetes authn/authz or an identity-aware proxy in front of production exposure. |
| Spoke CSR bootstrap controller | Disabled | Add cluster-bootstrap to controllers and set hubAPIURL to the hub API server URL reachable from spokes. |
If you override controllers, include the default substrate readiness
controllers:
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set controllers='{deliveryunit,fleet,plan,promotion,promotionrun,cluster,substrateclass,substrate}'| Fleet auto-import providers | GCP and static lists implemented | Add clustertemplate to controllers when using ClusterTemplate; AWS, Azure, RHACM, and CAPI sources report SourceNotImplemented until their discoverers land. |
| Inline gate notifications | Runtime | Notification routing is configured inside gate/stage policy; there is no separate public notification provider/policy CRD. |
See Preview Controllers for the full controller key map and compatibility aliases.
Choose the smallest substrate path that matches the delivery system you already run:
| Path | Use when | Example |
|---|---|---|
| Direct | Kapro should generate rendered Kubernetes manifests for direct apply. | Direct Apply Quickstart |
| Flux | Spokes already reconcile with Flux or Flux Operator. | Flux Quickstart |
| Argo CD | Argo CD owns one Application per target cluster. | Argo CD Quickstart |
| OCI | Spokes must pull OCI artifacts without Flux or Argo CD. | OCI Quickstart |
For a guided CLI decision tree, run:
kapro bootstrap guideThe same paths are documented in the Adoption Guide, including observe-first Argo CD and Flux existing-repo onboarding.
Use ClusterTemplate.spec.source.static when clusters are already known and
represented by kubeconfig Secrets instead of a cloud fleet API. This is the
lowest-friction path for on-prem, edge, and existing platform environments
while AWS, Azure, RHACM, and CAPI discoverers remain preview stubs.
kubectl apply -f examples/04-substrates/03-clustertemplate/clustertemplate.yamlEach imported Cluster gets spec.provider.kind=kubeconfig plus
secretName and secretNamespace provider parameters from the static entry.
The template still owns only the objects carrying Kapro's managed-by labels;
hand-authored Cluster objects with the same name are left untouched.
The operator chart can render an opt-in NetworkPolicy for locked-down
clusters:
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set networkPolicy.enabled=trueBy default the policy limits ingress to the operator's health, metrics,
webhook, approval, and hub-gateway ports. Set networkPolicy.ingress.from
to restrict source namespaces or pods. Enable
networkPolicy.egress.enabled=true only after confirming the cluster's
NetworkPolicy implementation and API-server/DNS reachability requirements.
The approval HTTP server is installed for signed human approval links. The
machine-facing Decision API under /api/v1 is disabled by default.
Enable it only after granting Kubernetes RBAC to the ServiceAccounts that should read promotion context or submit decisions:
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set decisionAPI.enabled=trueEvery Decision API request must include a Kubernetes bearer token. The operator
validates the token with TokenReview and checks each requested action with
SubjectAccessReview before reading fleet state, writing
Target.status, or creating Approval objects.
Read endpoints are bounded. GET /api/v1/fleet and
GET /api/v1/promotionruns/{name}/context accept limit, labelSelector, and
phase query parameters and return page.truncated=true when more matching
objects exist than were returned or when sparse filters exhaust the server scan
budget.
Example approver RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kapro-decision-approver
rules:
- apiGroups: ["runtime.kapro.io"]
resources: ["promotionruns", "targets"]
verbs: ["get"]
- apiGroups: ["runtime.kapro.io"]
resources: ["targets/status"]
verbs: ["update", "patch"]
- apiGroups: ["kapro.io"]
resources: ["approvals"]
verbs: ["create"]Bind this role only to the agent or human-facing ServiceAccount that is allowed to decide or override promotions.
kubectl -n kapro-system rollout status deployment/kapro-kapro-operator
kubectl get crd | grep kapro.io
kubectl -n kapro-system get deploy,svc,sa
kubectl auth can-i get promotionruns.runtime.kapro.io \
--as=system:serviceaccount:kapro-system:kapro-kapro-operatorFor clean-clone or release-candidate verification, use the repository helper:
scripts/verify-install.sh render
scripts/verify-install.sh clusterrender checks Helm CRD drift, helm lint, helm template --include-crds,
and kubectl kustomize config/default. cluster installs the chart into the
current cluster and verifies the operator Deployment, CRDs, ServiceAccount, and
basic PromotionRun read access.
For a fresh clone check of the current docs, examples, and scripts:
tmpdir="$(mktemp -d)"
git clone --branch main https://github.com/Kapro-dev/kapro "${tmpdir}/kapro"
cd "${tmpdir}/kapro"
scripts/verify-install.sh renderFor a disposable Kind install check:
kind create cluster --name kapro-install-verify
kubectl config use-context kind-kapro-install-verify
scripts/verify-install.sh cluster
kind delete cluster --name kapro-install-verifyFor a release image that is not the chart default:
KAPRO_IMAGE_REPOSITORY=ghcr.io/kapro-dev/kapro-operator \
KAPRO_IMAGE_TAG=v0.6.0 \
scripts/verify-install.sh clusterFor a render-only check against the published chart artifact:
scripts/verify-install.sh release-renderFor cryptographic artifact checks before installation, use the Release Verification workflow.
For a disposable Kind install check against the published chart artifact:
kind create cluster --name kapro-release-verify
kubectl config use-context kind-kapro-release-verify
KAPRO_VERIFY_CLEANUP=true scripts/verify-install.sh release-cluster
kind delete cluster --name kapro-release-verifyTo combine the published chart install with the quickstart object model, run the release install check first, then apply the starter manifests from the same checkout:
kind create cluster --name kapro-release-quickstart
kubectl config use-context kind-kapro-release-quickstart
KAPRO_VERIFY_CLEANUP=false scripts/verify-install.sh release-cluster
kubectl apply -f examples/01-quickstarts/00-flux/substrates/flux.yaml
kubectl apply -f examples/01-quickstarts/00-flux/deliveryunit.yaml
kubectl apply -f examples/01-quickstarts/00-flux/plan.yaml
kubectl apply -f examples/01-quickstarts/00-flux/kapro.yaml
kubectl apply -f examples/01-quickstarts/00-flux/promotion.yaml
kubectl get promotions.kapro.io,promotionruns.runtime.kapro.io,targets.runtime.kapro.io
kind delete cluster --name kapro-release-quickstartThat proves the released chart can install the current public quickstart API
shape. Full PromotionRun=Complete and Target=Converged checks are covered by
the Kind smoke fixture below, which injects synthetic substrate health.
Heavier validation targets are available when you need substrate coverage:
KAPRO_CI_QUICKSTARTS=direct,flux,argo,oci scripts/ci-kind-smoke.sh
scripts/verify-install.sh kind-demo
scripts/verify-install.sh argo-e2e
scripts/verify-install.sh flux-git-e2e
scripts/verify-install.sh flux-e2eRender checks that do not require a cluster:
helm lint charts/kapro-operator
helm template kapro charts/kapro-operator --namespace kapro-system --include-crds
kubectl kustomize config/default!!! warning "Upgrading from prototype builds" The 0.6 API is a clean public-preview reset. Follow the pre-0.6 API reset guide before applying 0.6 CRDs; the chart does not serve older prototype schemas or run automatic conversion.
Apply CRD changes first, then upgrade the chart. For the release package, pull and unpack the chart before applying CRDs:
tmpdir="$(mktemp -d)"
helm pull "${KAPRO_CHART}" --untar --untardir "${tmpdir}"
kubectl apply -f "${tmpdir}/kapro-operator/crds"
helm upgrade kapro "${KAPRO_CHART}" --namespace kapro-system
kubectl -n kapro-system rollout status deployment/kapro-kapro-operatorFrom a source checkout, kubectl apply -f charts/kapro-operator/crds is the
equivalent CRD apply path.
Kapro supports a pull-mode spoke agent (kapro-cluster-controller) that
runs inside each workload cluster and reports back to the hub. To register a
new spoke see cluster-bootstrap.md. The existing push-
mode flow (kapro spoke add) is unchanged.
helm uninstall kapro --namespace kapro-systemHelm does not delete CRDs on uninstall. After backing up or deleting Kapro custom resources, remove CRDs explicitly:
kubectl delete -f charts/kapro-operator/crds
kubectl delete namespace kapro-systemFor a packaged release install without a source checkout, pull the chart before deleting CRDs:
helm pull https://github.com/Kapro-dev/kapro/releases/download/v0.6.0/kapro-operator-0.6.0.tgz --untar
kubectl delete -f kapro-operator/crds
kubectl delete namespace kapro-systemThe plugin gateway is an opt-in runtime preview. Enabling it only sets
KAPRO_ENABLE_PLUGIN_GATEWAY=true; it does not install any plugin service or
demo Plugin.
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set pluginGateway.enabled=true \
--set controllers='{deliveryunit,fleet,plan,promotion,promotionrun,cluster,plugin}'Install your plugin service, then apply a Plugin manifest such as:
kubectl apply -f examples/05-plugins/03-slo-gate/registration.yamlThe plugin controller probes Plugin objects continuously. Ready plugins
with a fresh status.observedGeneration are hot-loaded into the actuator, gate,
and planner registries when the gateway is enabled; stale, incompatible, or
deleted plugins are unloaded without restarting the operator.
kubectl get plugins.kapro.ioThe Hub Gateway is a lightweight facade for UI and CLI clients. It reads and
creates Kapro CRDs; it does not mutate delivery substrates directly. The graph
endpoint is bounded and supports resource, labelSelector, phase, and
limit query parameters.
The built-in bearer token is suitable for local development and port-forwarded use only. Production exposure should terminate identity through Kubernetes authentication and authorization or an identity-aware reverse proxy before traffic reaches the gateway.
helm upgrade --install kapro \
"${KAPRO_CHART}" \
--namespace kapro-system \
--create-namespace \
--set hubGateway.service.enabled=trueThe repository also keeps a Kustomize bundle for simple local installs:
kubectl apply -k config/default
kubectl -n kapro-system rollout status deployment/kapro-operatorThe Kustomize bundle disables admission webhooks and uses the published operator image. Use Helm for configurable production installs.