Install the operator

Evaluate unreleased main through the edge channel or deploy a development image from source.

Updated 21 October 2026 · 8 min read

On this page

Next tracks unreleased behavior on main. Use the edge channel for an executable evaluation install, or build from source when you are developing the operator. Do not treat either path as a stable production contract.

Before you begin

Choose namespace Pod Security label ownership

In multi-tenant mode, the Provisioner sets the namespace labels pod-security.kubernetes.io/enforce, pod-security.kubernetes.io/audit, and pod-security.kubernetes.io/warn to restricted by default.

If a platform controller owns these labels or an admission policy restricts their updates, configure external ownership before onboarding a namespace. Add this fragment to the operator’s Helm values file:

tenancy:
  namespacePodSecurityLabels:
    mode: external

This setting applies to all tenant namespaces served by the installation; it is not an OpenBaoTenant field. The chart removes namespace update and patch permissions from the Provisioner and configures admission to deny its namespace updates. Existing labels remain unchanged. The platform team must apply the required Pod Security policy. The operator still manages tenant RBAC, Secret allowlists, ResourceQuota, and LimitRange.

Rancher is one example: its webhook requires separate authorization to update Pod Security labels. See Rancher’s namespace admission guidance. Other platform controllers and admission policies can impose similar restrictions.

The generated edge installer and default source deployment use enforce mode. Helm values do not configure those manifests. Use the edge Helm chart or local Helm rendering for external label ownership.

Install an edge chart

Edge charts use oci://ghcr.io/kubebao/charts-edge/openbao-operator. This repository is not registered in Artifact Hub. Each package contains the CRDs, RBAC, and admission policies from the candidate commit and pins the controller, Provisioner, and default helper images to the verified image digests. OpenBao server images remain cluster configuration.

Use this procedure for a new Helm installation or an existing edge Helm release. It does not adopt an installation created with the generated manifest. Store your Helm overrides in operator-values.yaml; use an empty mapping ({}) if you do not need overrides.

  1. Download the current channel metadata and inspect the candidate.

    inspect

    Select an edge candidate

    curl --fail --silent --show-error \
      https://docs.kubebao.org/edge/latest/metadata.json \
      --output edge-metadata.json
    jq '{sha, chart, images}' edge-metadata.json
    export EDGE_CHART=oci://ghcr.io/kubebao/charts-edge/openbao-operator
    export EDGE_CHART_DIGEST="$(jq -er '.chart.digest' edge-metadata.json)"

    The chart version has the form 0.0.0-edge.<CI-run-id>.<attempt>.g<commit>. The 0.0.0 base is independent of stable and planned release versions. Retain the metadata with your evaluation configuration. Pin the chart digest in GitOps so a new merge does not change the selected candidate.

    Earlier edge charts used a release-derived base such as 0.5.1. SemVer orders the new 0.0.0-edge versions below those older versions. Select the new version or digest directly when switching; do not rely on a highest-version selector. Previously published versions and digests remain available.

  2. Verify the chart publisher identity.

    verify

    Verify the edge chart signature

    cosign verify --new-bundle-format=true \
      --certificate-identity \
        https://github.com/kubebao/openbao-operator/.github/workflows/publish-edge.yml@refs/heads/main \
      --certificate-oidc-issuer https://token.actions.githubusercontent.com \
      "${EDGE_CHART#oci://}@${EDGE_CHART_DIGEST}"

    Cosign must report successful verification. The channel’s provenance-index.json also records the chart digest and GitHub attestation identity.

  3. Apply the CRDs from the selected chart before installing or upgrading the controller.

    apply

    Apply the matching edge CRDs

    helm show crds "${EDGE_CHART}@${EDGE_CHART_DIGEST}" > edge-crds.yaml
    kubectl apply --server-side --field-manager=openbao-operator-crds -f edge-crds.yaml

    Helm does not upgrade existing CRDs. Review any field ownership conflict before changing the existing CRD manager. An older controller or Helm rollback does not restore a previous CRD schema.

  4. Install the selected chart and reapply your current overrides.

    apply

    Install the pinned edge chart

    helm upgrade --install openbao-operator "${EDGE_CHART}@${EDGE_CHART_DIGEST}" \
      --namespace openbao-operator-system \
      --create-namespace \
      --reset-values \
      --values operator-values.yaml \
      --wait --timeout 5m

    Use --reset-values on edge upgrades so the new package supplies its image pins. Reapply intentional custom values from the values file. Avoid --reuse-values, which can retain image defaults from the previous candidate. Overriding image or helperImages, or setting helper image environment variables through controller.extraEnv, can replace the package’s candidate image selection.

  5. Verify both deployments in multi-tenant mode.

    verify

    Verify the edge Helm installation

    kubectl -n openbao-operator-system rollout status deployment/openbao-operator-controller --timeout=2m
    kubectl -n openbao-operator-system rollout status deployment/openbao-operator-provisioner --timeout=2m
    kubectl -n openbao-operator-system get deployments \
      -o 'custom-columns=NAME:.metadata.name,IMAGE:.spec.template.spec.containers[0].image'

    Both deployments must use the manager digest in edge-metadata.json. Single-tenant mode runs only the controller. Continue with namespace onboarding.

Published edge charts and their referenced images have no automatic expiry under the current retention policy. They remain evaluation artifacts with no production support commitment. Nightly Helm charts are not published yet.

Install the generated edge manifest

The edge publisher promotes images and generates manifests from the same successful main commit. Inspect the channel metadata before applying it so you know the exact commit and image digests under evaluation.

  1. Set the edge channel URL and inspect its metadata.

    inspect

    Review the current edge build

    export EDGE_ROOT=https://docs.kubebao.org/edge/latest
    curl --fail --silent --show-error "${EDGE_ROOT}/metadata.json"

    Record the sha, generated time, and image digests. Follow the supply-chain verification procedure when the evaluation requires provenance verification.

  2. Apply the generated multi-tenant installer.

    apply

    Install the edge manifest

    kubectl apply -f "${EDGE_ROOT}/install.yaml"
  3. Wait for both multi-tenant controllers.

    verify

    Verify the controller and Provisioner

    kubectl -n openbao-operator-system rollout status \
      deployment/openbao-operator-controller --timeout=2m
    kubectl -n openbao-operator-system rollout status \
      deployment/openbao-operator-provisioner --timeout=2m
  4. Verify the installed APIs and admission policies.

    verify

    Verify cluster-scoped resources

    kubectl get crd \
      openbaoclusters.openbao.org \
      openbaotenants.openbao.org \
      openbaorestores.openbao.org
    kubectl get validatingadmissionpolicies
  5. Verify the controller identity.

    inspect

    Inspect the controller identity

    kubectl -n openbao-operator-system get serviceaccount \
      openbao-operator-controller
    kubectl -n openbao-operator-system get deployment \
      openbao-operator-controller -o yaml

    Confirm that the Deployment uses the rendered ServiceAccount and projected openbao-token. Continue with operator authentication when you customize the JWT audience or identity.

Deploy from source

Use a source deployment when you need a local change or an exact checkout that has not reached the edge channel.

  1. Check out the intended commit and prepare the toolchain.

    configure

    Prepare the source checkout

    git clone https://github.com/kubebao/openbao-operator.git
    cd openbao-operator
    git checkout <commit>
    make bootstrap
  2. Build and push an image that the cluster can pull.

    build

    Publish the development image

    export IMG=<registry>/openbao-operator:<commit>
    make docker-build docker-push IMG="${IMG}"

    For a local Kind cluster, load the image into every node instead of pushing it, then use the same image reference for deployment.

  3. Deploy the generated resources and the selected image.

    apply

    Deploy the source build

    make deploy IMG="${IMG}" OPERATOR_VERSION=edge

Render the local Helm contract

Use the checked-out chart when you need to evaluate Helm rendering, including the single-tenant or OpenShift paths. The edge image and operator version keep helper-image selection aligned with the unreleased build.

Save any overrides in operator-values.yaml, including label ownership when required. If you do not need overrides, create an empty file with touch operator-values.yaml.

inspect

Render the local edge chart

helm template openbao-operator charts/openbao-operator \
  --namespace openbao-operator-system \
  --values operator-values.yaml \
  --include-crds \
  --set image.tag=edge \
  --set operatorVersion=edge

Review the controller and Provisioner ServiceAccounts, RoleBinding subjects, admission-policy identities, projected token audience, images, and namespaces before applying the render.

helm template omits CRDs unless you pass --include-crds. When applying rendered manifests directly, create the operator namespace and wait for the CRDs to become Established before starting the controllers or applying OpenBao custom resources. Configure the same ordering when a GitOps controller applies the manifests.

Select the target platform

The chart defaults to platform=auto. The controller checks the API groups during startup and selects OpenShift when security.openshift.io is present. A failed discovery request or a request that exceeds 10 seconds blocks startup. Check API server connectivity and discovery permissions before restarting the controller.

To bypass discovery, set the chart value to platform=kubernetes or platform=openshift. OpenShift mode omits fixed runAsUser and fsGroup IDs so the Security Context Constraint can assign namespace-scoped IDs.

The chart sets OPERATOR_PLATFORM. This environment variable takes precedence over the deprecated --platform controller flag. Accepted values are auto, kubernetes, and openshift; other values block startup.

Refresh an edge installation

The edge channel is mutable. Re-read metadata.json, then apply CRDs before the complete installer when the recorded commit changes.

upgrade

Refresh to the current edge build

kubectl apply -f "${EDGE_ROOT}/crds.yaml"
kubectl apply -f "${EDGE_ROOT}/install.yaml"

Re-render custom identities and review OpenBao-side policy changes before refreshing. Self-init does not update existing OpenBao policies.

Remove the source or edge deployment

Use the same generated manifest that installed the operator. Inventory every OpenBaoCluster, OpenBaoTenant, and OpenBaoRestore before deleting CRDs because CR deletion can trigger lifecycle behavior.

remove

Remove the edge deployment

kubectl delete -f "${EDGE_ROOT}/install.yaml"

Troubleshoot installation

SymptomCheck
no matches for kind "OpenBaoCluster"Verify that the CRDs are installed and Established. Include --include-crds when rendering the chart with helm template.
Controller starts but Provisioner is absentConfirm that you did not render tenancy.mode=single
Tenant provisioning fails on a namespace label updateInspect the tenant error and configure label ownership if the platform restricts Pod Security label updates
Pods cannot pull the source imagePush it to a cluster-reachable registry or load it into every local node
Pods run but admission rejects ordinary resourcesInspect policy bindings, rendered identity variables, and API-server ValidatingAdmissionPolicy support
Custom names break reconciliationCompare every ServiceAccount, RoleBinding subject, admission variable, and JWT bound subject
OpenShift rejects Pod identity fieldsRender platform=openshift, then review SCC ownership

In multi-tenant mode, continue with namespace onboarding.

Search the handbook

Try “install”, “threat model”, or “compatibility”.