Install the operator in the mode you actually intend to run.
Choose a supported install path, keep the rendered namespace and identity explicit, and verify the controller wiring before you create your first OpenBaoCluster.
Prerequisites
- Kubernetes: v1.33+ (see Compatibility)
- kubectl: Installed and configured
- Permissions: Cluster-admin access for CRDs, RBAC, and ValidatingAdmissionPolicies
- Helm (optional): v3.12+ for Helm-based installation
The operator supports two deployment modes:
- Multi-Tenant (default): Platform teams providing OpenBao-as-a-Service
- Single-Tenant: Individual teams deploying OpenBao for their application
See Single-Tenant Mode for single-tenant deployments.
Install Profiles
Use this table to choose the supported install path before you start changing values or overlays. For most environments, the default answer is Helm plus multi-tenant mode unless your namespace ownership model says otherwise.
Decision matrix
Supported installation paths
| Intent | Recommended path | Change these settings | Verify these outputs |
|---|---|---|---|
| Default shared production install | Helm, multi-tenant mode | release namespace, image tag, controller/provisioner sizing | controller and provisioner pods in the rendered operator namespace |
| Dedicated team namespace | Helm, tenancy.mode=single | tenancy.targetNamespace, optional release namespace | only the controller pod runs; WATCH_NAMESPACE matches the target namespace |
| Dedicated team namespace with custom Helm identity | Helm, tenancy.mode=single plus custom release name or fullnameOverride | release name or fullnameOverride, tenancy.targetNamespace, optional release namespace | rendered controller ServiceAccount name, single-tenant RoleBinding subject, admission-policy identity variables, JWT audience |
| Raw multi-tenant install with default identity | config/default | operator namespace only if you want to fork the default base | rendered namespace, controller and provisioner ServiceAccount names, admission policies |
| Raw multi-tenant install with custom identity | config/overlays/custom-identity | namespace, optional namePrefix | rendered ServiceAccount names, RoleBinding subjects, admission-policy identity variables, JWT audience |
| Raw single-tenant install | config/overlays/single-tenant | operator namespace in the overlay, target namespace in target_namespace_config.yaml | rendered operator namespace, WATCH_NAMESPACE, single-tenant RoleBinding subject |
| Raw single-tenant install with custom identity | config/overlays/single-tenant-custom-identity | namespace, optional namePrefix, target namespace in target_namespace_config.yaml | rendered operator namespace, controller ServiceAccount name, WATCH_NAMESPACE, single-tenant RoleBinding subject, admission-policy identity variables |
Use config/overlays/single-tenant when you only need a custom operator namespace or target namespace.
Use config/overlays/single-tenant-custom-identity when you also need a custom operator identity, such as an extra namePrefix.
Start with Helm, keep the default multi-tenant mode, pin the image tag for production, and leave admission policies enabled. Deviate from that path only when raw-manifest control or single-tenant namespace ownership is an explicit requirement.
Installation
- Helm (Recommended)
- OpenShift
- YAML Manifests
- Developer (Source)
Install the operator using the official Helm chart:
The examples below use the default release namespace openbao-operator-system. If you install the chart into another namespace, replace it consistently in the commands and later verification steps.
Apply
Install the Helm chart
helm install openbao-operator oci://ghcr.io/dc-tec/charts/openbao-operator \
--namespace openbao-operator-system \
--create-namespace
Common Configuration
Configure
Pin a release and right-size the controller
helm install openbao-operator oci://ghcr.io/dc-tec/charts/openbao-operator \
--namespace openbao-operator-system \
--create-namespace \
--set image.tag=1.0.0 \
--set controller.replicas=2 \
--set controller.resources.limits.memory=512Mi
- Pin to a specific version for production deployments.
- Run multiple replicas for high availability.
- Adjust resource limits based on cluster size.
Single-Tenant With Custom Helm Identity
Helm already supports the equivalent of the raw-manifest custom-identity overlays through the release name and fullnameOverride.
Configure
Install in single-tenant mode with a custom identity
helm install team-bao oci://ghcr.io/dc-tec/charts/openbao-operator \
--namespace platform-operators \
--create-namespace \
--set tenancy.mode=single \
--set tenancy.targetNamespace=openbao \
--set fullnameOverride=team-bao-operator
Confirm with helm template or helm get manifest that:
- the controller
ServiceAccountname matches the rendered Helm fullname - the single-tenant
RoleBindingsubject points at that rendered controllerServiceAccount - admission-policy variables reference the same rendered operator namespace and controller
ServiceAccountname OPENBAO_JWT_AUDIENCEon the controller still matches the projectedopenbao-tokenaudience
The chart does not expose per-component custom ServiceAccount names. Use the release name or fullnameOverride to customize the operator identity while keeping the rendered RBAC and admission-policy references aligned.
Artifact Hub
Discover package metadata and install snippets on Artifact Hub:
Artifact Hub indexing can lag shortly after a release is published.
Full Values Reference
| Parameter | Description | Default |
|---|---|---|
image.repository | Operator image repository | ghcr.io/dc-tec/openbao-operator |
image.tag | Image tag (defaults to appVersion) | "" |
image.pullPolicy | Image pull policy | IfNotPresent |
imagePullSecrets | Registry credentials | [] |
platform | Target platform (auto, kubernetes, openshift) | auto |
tenancy.mode | multi or single | multi |
tenancy.targetNamespace | Target namespace (single-tenant only) | "" |
controller.replicas | Controller replica count | 1 |
controller.resources | Controller resource requests/limits | See values.yaml |
provisioner.replicas | Provisioner replica count | 1 |
provisioner.resources | Provisioner resource requests/limits | See values.yaml |
admissionPolicies.enabled | Enable ValidatingAdmissionPolicies | true |
metrics.enabled | Enable metrics endpoints | true |
To use private registries for the operator and its sidecars (init, backup, upgrade), see the Air-Gapped / Private Registries guide.
For Red Hat OpenShift clusters, the operator defaults to platform auto-detection. You can optionally force the platform mode to ensure compatibility with Security Context Constraints (SCC):
Configure
Force OpenShift platform mode
helm install openbao-operator oci://ghcr.io/dc-tec/charts/openbao-operator \
--namespace openbao-operator-system \
--create-namespace \
--set platform=openshift
This setting instructs the chart/operator to omit pinned runAsUser / fsGroup IDs in generated Pods, allowing OpenShift's SCC admission controller to inject namespace-scoped IDs automatically.
Apply the installer manifest directly from the GitHub Release:
Apply
Apply the released installer manifest
kubectl apply -f https://github.com/dc-tec/openbao-operator/releases/latest/download/install.yaml
This installs CRDs, RBAC, ValidatingAdmissionPolicies, and the operator deployments in openbao-operator-system.
Raw-manifest installs have three supported starting points:
config/default: default multi-tenant installconfig/overlays/custom-identity: multi-tenant install with custom operator namespace ornamePrefixconfig/overlays/single-tenant: direct single-tenant install without the provisionerconfig/overlays/single-tenant-custom-identity: direct single-tenant install without the provisioner plus custom operator identity support
For raw-manifest installs with a custom operator namespace or extra name prefix, start from config/overlays/custom-identity. Set namespace there and optionally add namePrefix. The controller and provisioner ServiceAccount identities, RoleBinding subjects, and admission-policy identity checks follow the installed ServiceAccounts automatically.
For direct single-tenant installs, start from config/overlays/single-tenant. That overlay owns the operator namespace and target namespace wiring instead of relying on manual WATCH_NAMESPACE patches.
If you need single-tenant mode and a custom operator identity, such as an extra namePrefix, start from config/overlays/single-tenant-custom-identity. That overlay keeps the single-tenant namespace wiring and the controller admission-policy identity rewrites aligned in one supported path.
If you use custom raw-manifest identities together with manual OpenBao JWT configuration or self-init OIDC bootstrap, verify the rendered controller ServiceAccount name and namespace first. See Operator Authentication.
For local development and contribution:
Apply
Install from source for development
# Install CRDs
make install
# Deploy operator (uses Kustomize)
make deploy IMG=ghcr.io/dc-tec/openbao-operator:dev
Render Verification
Use this checklist for raw-manifest installs before you apply the manifests.
Multi-Tenant With Custom Identity
Render the overlay:
Inspect
Render the custom-identity overlay
kubectl kustomize config/overlays/custom-identity
Confirm:
- the rendered operator namespace is the namespace you expect
- the controller and provisioner
ServiceAccountnames match your intended install identity RoleBindingandClusterRoleBindingsubjects point at those rendered ServiceAccounts- admission-policy variables reference the same rendered namespace and ServiceAccount names
OPENBAO_JWT_AUDIENCEon the controller matches the projectedopenbao-tokenaudience
See Operator Authentication for the OpenBao-side JWT binding checks.
Single-Tenant Raw Manifests
Render the overlay:
Inspect
Render the single-tenant overlay
kubectl kustomize config/overlays/single-tenant
Confirm:
- the rendered operator namespace matches
config/overlays/single-tenant/kustomization.yaml WATCH_NAMESPACEon the controller matchesconfig/overlays/single-tenant/target_namespace_config.yaml- the single-tenant
RoleBindingnamespace matches the same target namespace - the controller
ServiceAccountsubject in thatRoleBindingpoints at the rendered operator namespace
If you customize the single-tenant overlay beyond those supported fields, treat the render output as the source of truth.
Single-Tenant With Custom Identity
Render the overlay:
Inspect
Render the single-tenant custom-identity overlay
kubectl kustomize config/overlays/single-tenant-custom-identity
Confirm:
- the rendered operator namespace matches
config/overlays/single-tenant-custom-identity/kustomization.yaml - the rendered controller
ServiceAccountname matches the same overlay after anynamePrefix WATCH_NAMESPACEon the controller matchesconfig/overlays/single-tenant-custom-identity/target_namespace_config.yaml- the single-tenant
RoleBindingsubject points at the rendered controllerServiceAccount - controller admission-policy variables reference the same rendered namespace and
ServiceAccountname
Verify Installation
Check that the operator pods are running:
Verify
Check that the operator pods are running
kubectl get pods -n <operator-namespace>
Expected output (multi-tenant mode):
Output
Expected output in multi-tenant mode
NAME READY STATUS RESTARTS AGE
<controller-pod> 1/1 Running 0 1m
<provisioner-pod> 1/1 Running 0 1m
A good install checkpoint is more than pods in Running:
- the controller and provisioner pods match the tenancy mode you chose
- the rendered namespace and ServiceAccount names match your install plan
- admission policies are installed when they are supposed to be
- in the default multi-tenant path, you know which namespace will receive the first
OpenBaoTenant - your next step is tenant onboarding or cluster creation, not more install debugging
Upgrading
Helm Upgrades
Helm does not automatically upgrade CRDs. For releases with CRD changes:
- Apply CRDs from the release assets first:
kubectl apply -f https://github.com/dc-tec/openbao-operator/releases/download/X.Y.Z/crds.yaml - Then upgrade the Helm release:
helm upgrade openbao-operator oci://ghcr.io/dc-tec/charts/openbao-operator \
--namespace openbao-operator-system
YAML Manifest Upgrades
kubectl apply -f https://github.com/dc-tec/openbao-operator/releases/download/X.Y.Z/install.yaml
For custom raw-manifest installs, use your rendered namespace, ServiceAccount names, and policy names rather than assuming the repository defaults.
Uninstallation
- Helm
- YAML Manifests
helm uninstall openbao-operator --namespace openbao-operator-system
Helm does not delete CRDs by design. To fully remove:
kubectl delete crd openbaoclusters.openbao.org openbaorestores.openbao.org openbaotenants.openbao.org
kubectl delete -f https://github.com/dc-tec/openbao-operator/releases/latest/download/install.yaml
Next Steps
Next actions
This version tracks a prerelease build. Features and behavior may change before the next stable release.
Was this page helpful?
Use Needs work to open a structured GitHub issue for this page. The Yes button only acknowledges the signal locally.