Skip to Content
✨ Check out our new MCP server! (tech preview)
OpenBao Logo

Get started

OpenBao  provides centralized, well-audited privileged access and secret management for mission-critical data whether you deploy systems on-premises, in the cloud, or in a hybrid environment. The project originated as a community-driven fork of HashiCorp Vault and is currently developed under the stewardship of the Linux Foundation.

Before exploring the chart characteristics, let’s start by deploying the default configuration:

helm install <release-name> oci://dp.apps.rancher.io/charts/openbao \ --set global.imagePullSecrets={application-collection}

Please check our authentication guide if you need to configure Application Collection OCI credentials in your Kubernetes cluster.

Chart overview

The OpenBao Helm chart distributed in Application Collection is based on the official OpenBao Helm chart  and adapted to include our best practices. As such, any chart-related documentation provided by upstream will work out of the box with our chart. In addition to the upstream chart repository, you can check the official OpenBao documentation .

By default, the chart will deploy a single OpenBao server in standalone mode  with a 10Gi volume for data storage and an OpenBao Agent Injector admission webhook controller.

Server modes

The OpenBao server can be deployed in 3 modes:

  • Development: this mode does not require initialization or unsealing setup and it is intended for experimentation only. Data is not persisted. The Helm parameters that control this mode are server.dev.*. Read more on this in the official documentation .
  • Standalone: this is the default mode. It deploys a single replica and persists the data in a volume by using the “file” backend. OpenBao needs to be initialized after Helm installation. The Helm parameters that control this mode are server.standalone.*.
  • High-Availability: in HA mode, multiple OpenBao servers are deployed. By default, Consul is configured as storage backend but others can be configured manually, such as the integrated Raft storage. The Helm parameters that control this mode are server.ha.*. More information can be found in the official documentation .

Chart configuration

To view the supported configuration options and documentation, run:

helm show values oci://dp.apps.rancher.io/charts/openbao

Refer to the OpenBao Helm chart documentation  to learn more about configuring the Helm chart.

Development mode

The simplest way to start experimenting with the OpenBao application is activating the development mode when installing the Helm chart. As an example, you would provide the Helm chart values below to activate this mode. A root token can be specified from the Helm chart values for ease of use:

dev.yaml
server: dev: enabled: true devRootToken: admin
helm install <release-name> oci://dp.apps.rancher.io/charts/openbao \ --set global.imagePullSecrets={application-collection} \ --values dev.yaml

A single replica StatefulSet  is deployed without requiring any further initialization steps:

$ kubectl get statefulset/<release-name> NAME READY AGE <release-name> 1/1 21s

To confirm that the provided root token is being applied, run the command below:

$ kubectl exec statefulset/<release-name> -- bao print token admin

Secrets can be created and retrieved via CLI and API:

$ kubectl exec statefulset/<release-name> -- bao kv put -mount=secret test foo=bar == Secret Path == secret/data/test ...
$ kubectl port-forward svc/<release-name> 8200 $ curl --header "X-Vault-Token: admin" http://localhost:8200/v1/secret/data/test {"request_id":"160b676c-a566-f0c9-b344-2258e7d80355","lease_id":"","renewable":false,"lease_duration":0,"data":{"data":{"foo":"bar"},"metadata":{"created_time":"2026-09-17T09:43:46.104771593Z","custom_metadata":null,"deletion_time":"","destroyed":false,"version":1}},"wrap_info":null,"warnings":null,"auth":null}

OpenBao keeps the X-Vault-Token header and the bao CLI’s VAULT_* environment variables working for backward compatibility with existing Vault tooling, alongside their BAO_-prefixed equivalents.

Standalone mode

If you install OpenBao using the default standalone setup, you’ll need to complete a few extra steps to finish setting it up:

helm install <release-name> oci://dp.apps.rancher.io/charts/openbao \ --set global.imagePullSecrets={application-collection}

The logs show that the server is pending to be initialized and unsealed:

$ kubectl logs statefulset/<release-name> ... 2026-09-17T09:44:48.119Z [INFO] core: security barrier not initialized 2026-09-17T09:44:48.119Z [INFO] core: seal configuration missing, not initialized ...

Run operator init and operator unseal to finish the setup:

$ kubectl exec statefulset/<release-name> -- bao operator init -key-shares=1 -key-threshold=1 Unseal Key 1: <generated_unseal_key> ...

Copy the unseal key (<generated_unseal_key>) and run the operator unseal command with it. The command shows that OpenBao is now initialized and unsealed:

$ kubectl exec statefulset/<release-name> -- bao operator unseal <generated_unseal_key> Key Value --- ----- Seal Type shamir Initialized true Sealed false ...

The installation is now ready:

$ kubectl get statefulset/<release-name> NAME READY AGE <release-name> 1/1 2m32s

High-Availability mode

The High-Availability (HA) mode deploys multiple OpenBao server replicas. To illustrate it with an example, the Raft storage backend will be used. You can configure this mode and storage backend via Helm chart parameters:

ha.yaml
server: # Uncomment this line if your cluster has a single node: this schedules all pods in the same node # affinity: "" ha: enabled: true replicas: 3 raft: enabled: true
helm install <release-name> oci://dp.apps.rancher.io/charts/openbao \ --set global.imagePullSecrets={application-collection} \ --values ha.yaml

Initialize the first replica and copy the credentials:

$ kubectl exec <release-name>-0 -- bao operator init -key-shares=1 -key-threshold=1 Unseal Key 1: <generated_unseal_key> Initial Root Token: <some_initial_root_token> ...

Run these commands to finish the initialization of the OpenBao cluster:

$ kubectl exec <release-name>-0 -- bao operator unseal <generated_unseal_key> $ kubectl exec <release-name>-1 -- bao operator raft join http://<release-name>-0.<release-name>-internal:8200 Key Value --- ----- Joined true $ kubectl exec <release-name>-1 -- bao operator unseal <generated_unseal_key> $ kubectl exec <release-name>-2 -- bao operator raft join http://<release-name>-0.<release-name>-internal:8200 Key Value --- ----- Joined true $ kubectl exec <release-name>-2 -- bao operator unseal <generated_unseal_key>

Now all the OpenBao cluster replicas should be ready:

$ kubectl exec statefulset/<release-name> -- bao login <some_initial_root_token> $ kubectl exec statefulset/<release-name> -- bao operator raft list-peers Node Address State Voter ---- ------- ----- ----- db4cc75a-99da-9e84-2972-e8f1a61ec7b2 <release-name>-0.<release-name>-internal:8201 leader true 82c35180-0b56-7e2c-06a0-24d19494ebfe <release-name>-1.<release-name>-internal:8201 follower true ccb174a5-5e39-4c97-3208-67639431cf0a <release-name>-2.<release-name>-internal:8201 follower true $ kubectl exec <release-name>-0 -- bao status Key Value --- ----- Seal Type shamir Initialized true Sealed false ... Storage Type raft ... HA Enabled true HA Cluster https://<release-name>-0.<release-name>-internal:8201 HA Mode active ... $ kubectl exec <release-name>-1 -- bao status Key Value --- ----- Seal Type shamir Initialized true Sealed false ... Storage Type raft ... HA Enabled true HA Cluster https://<release-name>-0.<release-name>-internal:8201 HA Mode standby $ kubectl exec <release-name>-2 -- bao status Key Value --- ----- Seal Type shamir Initialized true Sealed false ... Storage Type raft ... HA Enabled true HA Cluster https://<release-name>-0.<release-name>-internal:8201 HA Mode standby $ kubectl get statefulset/<release-name> NAME READY AGE <release-name> 3/3 4m56s

Access the UI

The OpenBao Helm chart can expose the web UI as an independent service that allows you to easily manage its configurations. To create this UI service simply enable it with the Helm chart parameter below:

ui.yaml
# OpenBao UI ui: # True if you want to create a Service entry for the OpenBao UI. enabled: true
helm install <release-name> oci://dp.apps.rancher.io/charts/openbao \ --set global.imagePullSecrets={application-collection} \ --values ui.yaml

OpenBao Agent Injector

The OpenBao Agent Injector is a Kubernetes admission webhook controller  that intercepts pod events and updates their specification based on certain annotations. Thanks to this controller, OpenBao secrets can be injected into pods by mounting them as volumes. This functionality can be controlled by Helm chart parameters (injector.*). Read more on this feature in the official documentation . As an example, you would provide the Helm chart values below to make sure this mode is activated. For simplicity, the development mode is used:

injector.yaml
injector: enabled: true
helm install <release-name> oci://dp.apps.rancher.io/charts/openbao \ --set global.imagePullSecrets={application-collection} \ --values injector.yaml \ --set server.dev.enabled=true

Once the Helm installation finishes, create a new OpenBao secret:

kubectl exec statefulset/<release-name> -- bao kv put -mount=secret test-injector foo=bar

Then, configure Kubernetes authentication and OpenBao policies to interact with that secret:

kubectl exec statefulset/<release-name> -- bao auth enable kubernetes kubectl exec statefulset/<release-name> -- bash -c 'bao write auth/kubernetes/config kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"' kubectl exec -i statefulset/<release-name> -- bao policy write test-injector - <<EOF path "secret/data/test-injector" { capabilities = ["read"] } EOF kubectl exec statefulset/<release-name> -- bao write auth/kubernetes/role/test-injector bound_service_account_names=test-injector bound_service_account_namespaces=default policies=test-injector kubectl create serviceaccount test-injector

To finish, confirm that the secret is automatically mounted into the pods with proper metadata annotations. The injector still relies on the legacy vault.hashicorp.com/* annotation prefix for backward compatibility with existing Vault workflows:

kubectl run test-injector --image dp.apps.rancher.io/containers/nginx:1.31 \ --overrides='{"spec": {"serviceAccount": "test-injector", "imagePullSecrets":[{"name": "application-collection"}]}}' \ --annotations=vault.hashicorp.com/agent-inject=true \ --annotations=vault.hashicorp.com/role=test-injector \ --annotations=vault.hashicorp.com/agent-inject-secret-test.txt=secret/data/test-injector
$ kubectl exec test-injector -c test-injector -- cat /vault/secrets/test.txt data: map[foo:bar] ...

Operations

Upgrade the chart

In general, an in-place upgrade of your OpenBao installation can be performed using the built-in Helm upgrade workflow:

helm upgrade <release-name> oci://dp.apps.rancher.io/charts/openbao

The pods will be upgraded by following the update strategy defined in the values.yaml file.

Be aware that changes from version to version may include breaking changes in OpenBao itself or in the Helm chart templates. In other cases, the upgrade process may require additional steps to be performed. Always check the release notes  and the upgrade guides  before proceeding with an upgrade.

Uninstall the chart

Removing an installed OpenBao Helm chart release is simple:

helm uninstall <release-name>

The OpenBao nodes are deployed as StatefulSets , hence using Volume Claim Templates  to store your most precious resource in a database installation: your data. These PVCs are not directly controlled by Helm and they are not removed when uninstalling the related chart.

When you are ready to remove the PVCs and your data, you will need to explicitly delete them:

kubectl delete pvc --selector app.kubernetes.io/instance=<release-name>

Remember to remove any other resources you deployed during this guide:

kubectl delete pod test-injector kubectl delete serviceaccount test-injector
Last updated on