Skip to main content

Overview

OpenBao is the Linux Foundation’s open-source (MPL-2.0) fork of HashiCorp Vault: an identity-based secrets engine with a Vault-compatible API and CLI, covering KV v2 storage, dynamic secrets, PKI and transit encryption. This template deploys one OpenBao server with integrated raft storage on a persistent volume and auto-unseal, so the server comes back unsealed on its own after every restart with no operator action. If you are choosing between catalog templates: OpenBao is the Vault-compatible engine for workloads that need dynamic secrets, PKI, transit or existing Vault tooling, while Infisical is an application-secrets workflow platform with a team-oriented web UI. The two solve different problems and can run side by side.
This template deploys into an existing GVC that you already have. It does not create or manage a GVC.

What Gets Created

The template creates no unseal key and no OpenBao credentials of its own. In the default static seal mode the unseal key lives in a secret you create; the root token and recovery keys exist only in the output of the one-time initialization you run.

Prerequisites

What must exist before install depends on the seal mode (seal.type). The default is static.

Static Seal

One opaque secret must exist before you install. Secrets are org-level, so no GVC flag is involved.
1

Create the unseal-key secret

An opaque secret with encoding plain whose payload is a 32-byte key. OpenBao accepts the key hex-encoded, which is what openssl rand -hex 32 produces:
Set seal.static.secretName to this name. Use printf, not echo — echo appends a newline that becomes part of the key.
2

Keep a copy of the key outside Control Plane

The key wraps OpenBao’s encryption barrier: without it the raft data on the volume cannot be read. Read it back with cpln secret reveal SECRET_NAME -o yaml (a bare reveal prints only a summary table) and store a copy in a second system, such as a password manager or offline vault.
The unseal key is write-once. Never change or delete this secret. The chart configures a single static key with no previous-key fallback, so rotating the value in place, or losing it, makes every stored secret permanently unrecoverable — a reinstall cannot bring them back.
Create the secret before installing, or the deployment wedges silently. The chart refuses to render when seal.static.secretName is blank, but a name pointing at a secret that does not exist installs successfully and then never starts. The container never runs, so cpln logs returns zero lines. The one place the reason appears is status.versions[].message:
Use get-deployments — plain cpln workload get has no versions key. Creating the missing secret repairs the deployment on its own within several minutes, or run cpln workload force-redeployment RELEASE_NAME-openbao --gvc GVC_NAME to skip the wait.

KMS Auto-unseal Setup

Skip this section if you keep the default static seal. The awskms and gcpckms modes need no unseal-key secret: the server encrypts and decrypts its barrier key through your KMS key, and the workload identity reaches the key through a Control Plane cloud account, so no cloud credential is stored in the container or in your values.
The chart binds the identity to your cloud account with your IAM policy (alongside the platform’s cpln-connector policy), so the identity is usable as soon as it is created and no post-install step is needed.
1

Create or pick a symmetric KMS key

Set seal.aws.kmsKeyId to the key ARN (a key ID or alias also works) and seal.aws.region to the key’s region.
2

Register a Cloud Account

If you do not have one, create an AWS Cloud Account. Set seal.aws.cloudAccountName to its name.
3

Create a key-scoped IAM policy

Create a customer-managed IAM policy with the JSON below, replacing the resource with your key ARN, and set seal.aws.policyName to the policy name. These are the three actions the awskms seal uses; grant them on the one key, never with a broad managed policy.
4

Install with seal.type set to awskms

Pass --set seal.type=awskms together with the four seal.aws.* values. The server boots ready and uninitialized, exactly as in static mode — continue with First Run.

Installation

Install the chart from the marketplace registry, pointing the default static seal at the unseal-key secret you created:
For a KMS seal, set seal.type and the matching seal.aws.* or seal.gcp.* keys instead of seal.static.secretName — see KMS Auto-unseal Setup. Or follow the instructions for your preferred method:

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

Each block below is the shipped default for that part of values.yaml.

OpenBao Server

The image is pinned to the 2.6.x line on purpose: OpenBao 2.7 moves the built-in KMS auto-unseal mechanisms into external plugins, so a blind bump would break the awskms and gcpckms seal modes. Raise maxMemory for large secret sets or heavy PKI use.
On a stateful workload the ratio of maxCpu to minCpu may not exceed 4:1, and the defaults sit exactly at that limit. Raising maxCpu without raising minCpu crosses it and is rejected when the workload is applied.

Seal and Auto-unseal

seal.type selects exactly one mode; only that mode’s sub-block is used and the others are ignored. In every mode the server unseals itself on boot with no operator action. In the KMS modes no unseal key is mounted and no cloud access key is issued to the container.
Do not change seal.type after the server has been initialized. The seal wraps the existing data, so switching modes requires an OpenBao seal migration — it is not a values change, and a server restarted under a different seal cannot unseal its data.

Storage

The volume holds the raft store: every secret, auth mount, policy and the cluster state. Data survives restarts, redeployments and helm upgrade. Uninstalling deletes the volume set (a final snapshot is kept for 7 days), and a reinstall comes up uninitialized.

Access

Public access is off by default: a fresh server is uninitialized and its first login is the root token, so initialize it and configure authentication over a private tunnel first (see First Run), then set publicAccess.enabled: true and upgrade the release when you want the API and web UI on the *.cpln.app endpoint. A change to either access knob can take several minutes to take effect — re-test before concluding it did not apply.

Connecting

The API is Vault-compatible, so existing Vault clients and SDKs work by pointing their address at one of the endpoints above. The bao CLI is present in the container with BAO_ADDR preset, so any bao command runs through cpln workload exec without extra flags. Verify the server is up:
Right after install the output shows Initialized false and Sealed true — that is the expected state until you initialize it.

First Run

The server boots reachable but uninitialized. Initialize it exactly once; from then on every restart auto-unseals.
1

Initialize the server

Because every seal mode in this template is an auto-unseal seal, the command prints recovery keys (five shares, three needed, by default) and the initial root token rather than Shamir unseal keys. Pass -recovery-shares and -recovery-threshold to change the split.
2

Store the output somewhere safe

The recovery keys and root token are shown once, only in your terminal, and are stored nowhere — the template never sees them and cannot recover them. Put the root token and each recovery key share in a password manager or an offline store, ideally with the shares held by different people. If the output is lost before it is saved, the only way back is to wipe the volume and initialize again.
3

Confirm the server unsealed itself

Initialized true and Sealed false means the seal mechanism is working; the server will return to this state on its own after every restart.
4

Log in

Open a tunnel and use the web UI or the bao CLI from your own machine:
In a browser, open http://localhost:8200/ui/, choose the Token method and paste the root token. From a terminal with bao installed, point it at the tunnel and log in — bao login prompts for the token, which keeps it out of your shell history:
5

Set up real authentication and retire the root token

Enable an auth method for people and workloads (for example userpass, oidc or approle), write policies, and then revoke the initial root token as upstream recommends. A new root token can be generated later with the recovery keys if it is ever needed. Only after this is in place consider publicAccess.enabled: true.
Recovery keys do not unseal the server. In every seal mode here the unseal happens through the static key secret or the KMS key; recovery keys only authorize privileged operations such as generating a new root token or migrating the seal. Keep the unseal-key secret (or the KMS key) and the recovery keys both backed up — losing either leaves you locked out in a different way.

Operations

Backing Up

The chart schedules no backups of its own. Two paths are available: Volume set snapshot. Snapshots the raft volume as a whole. Take one before upgrades or risky changes:
Raft snapshot. OpenBao’s own point-in-time export, written as a local file by the bao CLI on your machine through the port-forward tunnel while logged in with a sufficiently privileged token. It needs no file transfer out of the container. This command follows the upstream raft snapshot procedure and the chart’s raft configuration but has not been exercised against this template — rehearse it on a throwaway release first:
Either backup is encrypted by the barrier, so it is only readable by a server unsealed with the same key. In static mode, keep the unseal-key secret backed up alongside it (see Static Seal); in the KMS modes, keep the KMS key.

Restoring a Backup

No restore path has been exercised end to end against this template. The steps are built from the chart’s configuration and upstream documentation. Verify on a throwaway release before relying on them.
  • Raft snapshot. Restore into a release that is initialized, unsealed and running under the same seal key the snapshot was taken under — the same static secret value, or the same KMS key. Through the tunnel, logged in: bao operator raft snapshot restore openbao.snap. Restoring across a different seal key is outside what is documented here.
  • Volume set snapshot. cpln volumeset snapshot restore restores a volume from a snapshot taken above; check cpln volumeset snapshot restore --help for its required --snapshot-name, --location and --volume-index flags. This command has not been exercised against this template.
  • Accidental uninstall. Uninstalling deletes the volume set, and the final snapshot it takes is retained for 7 days. That snapshot, plus the unseal-key secret (which uninstall does not touch), is the only way back.

Scaling and Availability

  • The template deploys a single replica with no replicas knob; raft runs with one member, so there is no failover.
  • A node failure reschedules the server and reattaches the same volume, and the server unseals itself on the way back up. The exposure is a short restart gap, not data loss or a manual unseal.
  • The volume set is snapshotted only when it is deleted (final snapshot, kept 7 days); use Backing Up for point-in-time copies.

Troubleshooting

Symptom: the install succeeds, RELEASE_NAME-openbao stays not ready indefinitely, and cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-openbao"}' --limit 50 --since 10m returns zero lines.Cause: seal.static.secretName names a secret that does not exist, so the container is never started. The reason is visible only in status.versions[].message:
Fix: create the secret as in Static Seal. The deployment recovers on its own within several minutes, or run cpln workload force-redeployment RELEASE_NAME-openbao --gvc GVC_NAME.
Symptom: the workload is ready, but GET /v1/sys/health returns 501 and bao status reports Initialized false, Sealed true.Cause: this is a fresh server that has not been initialized yet. The readiness probe deliberately treats the uninitialized and sealed states as healthy so the API and UI stay reachable for the one-time initialization — restarting the workload will not change it.Fix: run bao operator init once as described in First Run.
Symptom: cpln helm install reported success, but RELEASE_NAME-openbao restarts repeatedly and cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-openbao"} |= "PermissionDenied"' --limit 50 --since 10m shows PermissionDenied … cloudkms.cryptoKeys.get.Cause: the identity’s service account has not been granted access on the crypto key, or was granted only cryptoKeyEncrypterDecrypter. OpenBao also calls cloudkms.cryptoKeys.get at startup and exits without it. The chart attaches no IAM binding of its own, so this grant is always a post-install step.Fix: grant both roles/cloudkms.cryptoKeyEncrypterDecrypter and roles/cloudkms.viewer on the key to the service account named by the identity’s status.objectName — see KMS Auto-unseal Setup. The workload recovers on its own. Confirm the identity is healthy with cpln identity get RELEASE_NAME-openbao-identity --gvc GVC_NAME -o yaml (status.gcp.usable).
Symptom: in awskms mode the workload is ready and uninitialized, and bao operator init fails with an AWS KMS access or key error instead of printing recovery keys.Cause: seal.aws.kmsKeyId or seal.aws.region does not match the key, or the IAM policy named in seal.aws.policyName does not grant kms:Encrypt, kms:Decrypt and kms:DescribeKey on it. A wrong key does not stop the server from booting; it surfaces at the first seal operation.Fix: check the identity with cpln identity get RELEASE_NAME-openbao-identity --gvc GVC_NAME -o yaml, correct the policy or the values, and upgrade the release. The server has not been initialized, so nothing is lost.
Symptom: every boot in awskms or gcpckms mode logs Support for this Auto Unseal mechanism has been moved into an external plugin.Cause: an upstream deprecation notice. On the pinned 2.6.1 image the built-in KMS seals still work; the notice is why the image is pinned to the 2.6.x line.Fix: none needed. Do not bump openbao.image to 2.7 or later without arranging the external seal plugin — the KMS seal modes would stop working.
Symptom: raft FSM db file has wider permissions than needed appears in the logs on startup.Cause: cosmetic. The data directory is made group-writable so the non-root openbao user can use the volume.Fix: none needed.

Important Notes

  • Static mode: the unseal-key secret must exist before install, and it is write-once. A missing secret wedges the deployment silently; a lost or changed key makes all stored data unrecoverable. Back the key up outside Control Plane.
  • Run bao operator init once after install and store the output — the recovery keys and root token are printed a single time, to your terminal only, and recovery keys cannot unseal the server.
  • Do not switch seal.type after initialization — changing modes requires an OpenBao seal migration, not a values change.
  • gcpckms needs its key grant applied after install — the workload crash-loops on cloudkms.cryptoKeys.get until both roles are granted on the key, then recovers on its own.
  • Keep openbao.image on the 2.6.x line — 2.7 moves the KMS seals into external plugins and would break awskms and gcpckms.
  • Private by default — initialize and configure authentication through cpln port-forward, then set publicAccess.enabled: true to expose the API and web UI on the canonical endpoint.
  • Data survives restarts and upgrades; uninstall deletes the volume set (a final snapshot is kept for 7 days) and leaves your unseal-key secret in place. A reinstall starts uninitialized.
  • No backups are scheduled — take volume set or raft snapshots yourself, and remember a snapshot is only readable under the same seal key.

External References

OpenBao Documentation

Official OpenBao documentation

Seal / Auto-unseal Configuration

Reference for the static, awskms and gcpckms seal stanzas

Raft Storage

The integrated storage backend this template uses

operator init

The one-time initialization command and its options

OpenBao on GitHub

Source, releases and issue tracker