Skip to content

OpenBao operations guide

Use this guide to initialize, log in to, and operate the Helm-deployed OpenBao instance in this repository. For the active GCP KMS seal, read the auto-unseal runbook first.

The manifests in this repo deploy OpenBao in namespace openbao with the service openbao.openbao.svc:8200 and a single-node Raft backend.

Source manifests live under kubernetes/apps/production/openbao/.

Check prerequisites

  • kubectl is configured for the target cluster
  • bao is available in the OpenBao container or installed locally
  • You have access to the openbao namespace

Check pod status

Before initialization, confirm that the pod exists:

kubectl get pods -n openbao
kubectl get svc -n openbao

For this chart layout, the main pod is usually openbao-0.

Open a shell in the pod

Run bao inside the pod to connect directly to the local listener:

kubectl exec -it -n openbao openbao-0 -- sh

Inside the pod, set:

export BAO_ADDR=http://127.0.0.1:8200

Check the current state:

bao status

Before initialization, the output should show that OpenBao is not initialized.

Initialize OpenBao

Initialize the instance once:

bao operator init

With the active GCP KMS auto-unseal configuration, the command prints:

  • recovery keys
  • initial root token

This output is highly sensitive.

For one recovery key share with a threshold of one:

bao operator init -recovery-shares=1 -recovery-threshold=1

Choose a threshold that matches the recovery process. Do not lower the threshold only to make bootstrap easier.

Unseal OpenBao

The active GCP KMS seal should unseal OpenBao automatically. Skip this section when bao status reports Sealed false.

For a Shamir-sealed installation, unseal with a generated unseal key:

bao operator unseal

Paste one unseal key when prompted.

If you used multiple key shares, repeat with enough keys to meet the threshold.

Check the status again:

bao status

The output should include:

  • Initialized true
  • Sealed false

Log in

Use the initial root token from bao operator init:

bao login

Paste the root token when prompted.

For a non-interactive login, run:

bao login <root-token>

To export the root token for the current shell, run:

export BAO_TOKEN=<root-token>

Confirm access:

bao token lookup

Use the basic CLI

If you need a secrets engine, enable it:

bao secrets enable -path=secret kv-v2

If secret/ already exists, this command fails. Skip the command.

Write a secret:

bao kv put secret/example username=demo password=change-me

Read the secret:

bao kv get secret/example

Read one field:

bao kv get -field=username secret/example

List secrets under a prefix:

bao kv list secret/

Delete a secret version:

bao kv delete secret/example

Use bao from a workstation

Access OpenBao from your workstation with port forwarding:

kubectl port-forward -n openbao svc/openbao 8200:8200

In another shell, use the local end of the port forward:

export BAO_ADDR=http://127.0.0.1:8200
bao status
bao login <root-token>

Use common commands

Check status:

bao status

Show enabled auth methods:

bao auth list

Show enabled secrets engines:

bao secrets list

Enable Kubernetes auth:

bao auth enable kubernetes

Read a policy:

bao policy read default

Follow operational limits

  • Initialize each OpenBao cluster only once.
  • Unseal is required after startup unless you configure auto-unseal.
  • Do not store unseal keys or root tokens unencrypted in Git.
  • Create less-privileged policies and tokens after bootstrap. Do not keep using the root token for normal automation.

Troubleshoot OpenBao

If bao status shows seal configuration missing, not initialized, the server has not been initialized yet.

If bao status shows Sealed true, run bao operator unseal with enough keys.

If the pod runs but is not ready, inspect the logs:

kubectl logs -n openbao openbao-0

The StatefulSet uses an OnDelete update strategy. Restart the pod directly:

kubectl delete pod -n openbao openbao-0

With the active GCP KMS seal, the replacement pod should unseal itself. If it does not, follow the auto-unseal runbook. Do not initialize it again.

Configure the admin policy and OIDC

The following commands create a broad admin policy and an Authentik OIDC role. Run them only after you review the policy and replace blank client credentials.

bao policy write admin - <<'EOF'
path "*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
EOF
bao write auth/oidc/config oidc_discovery_url="https://auth.igresc.com/application/o/open-bao/" oidc_client_id="" oidc_client_secret="" default_role="authentik-admin"
bao write auth/oidc/role/authentik-admin - <<'EOF'
{
  "role_type": "oidc",
  "user_claim": "preferred_username",
  "groups_claim": "groups",
  "oidc_scopes": "openid,profile,email,groups",
  "allowed_redirect_uris": [
    "http://localhost:8250/oidc/callback",
    "https://vault.local.isabelsoler.es/ui/vault/auth/oidc/oidc/callback",
    "https://vault.local.isabelsoler.es/oidc/callback"
  ],
  "policies": ["admin"],
  "ttl": "1h",
  "bound_claims": {
    "groups": ["openbao-admins"]
  }
}
EOF

docs/services/openbao.md