OpenBao (an open-source fork of HashiCorp Vault) is where your secrets live: API keys, database passwords, registry tokens, certificates. It runs on the service cluster at secrets.<CUSTOMER_ID>.truefullstaq.cloud.

The golden rule: secrets never go in Git or in container images. They are written to OpenBao, and the External Secrets Operator pulls them into your production cluster as native Kubernetes Secrets at runtime.

Secrets flow: you write to OpenBao on the service cluster; the External Secrets Operator on the production cluster reads from OpenBao and creates a Kubernetes Secret, consumed by your pod

This page covers putting secrets into OpenBao. For consuming them in your workloads, see External Secrets Operator.

# Signing in

# Web UI

Open https://secrets.<CUSTOMER_ID>.truefullstaq.cloud, choose the OIDC method, and sign in with TrueFullstaq SSO. You land with the customer-admin policy, which gives you full control over your secrets.

# CLI

Install the bao client (releases), then:

export BAO_ADDR=https://secrets.<CUSTOMER_ID>.truefullstaq.cloud   # your CUSTOMER_ID

# Sign in with SSO (opens a browser)
bao login -method=oidc

# Confirm
bao token lookup

The bao CLI is command-compatible with vault. If you already have the vault binary, export VAULT_ADDR=... and use vault instead; the commands below are identical.

# How secrets are organised

Your secrets live in a KV v2 engine mounted at secret/. A path is just a folder-like key you choose, conventionally secret/<app> or secret/<team>/<app>. Each path holds a set of key/value pairs and keeps version history.

secret/
├── api/                 # secret/api
│   ├── DB_PASSWORD
│   └── JWT_SIGNING_KEY
└── web-frontend/        # secret/web-frontend
    └── STRIPE_API_KEY

# Writing a secret

# Put (creates or replaces all keys at this path as a new version)
bao kv put secret/api \
  DB_PASSWORD='s3cr3t-pw' \
  JWT_SIGNING_KEY='abc123'

# Patch a single key without touching the others
bao kv patch secret/api DB_PASSWORD='new-pw'

From a file (handy for multi-line values like certificates):

bao kv put secret/api/tls cert=@server.crt key=@server.key

In the UI: secret engine → Create secret → set the path and key/value pairs.

# Reading and inspecting

# Read all keys at a path
bao kv get secret/api

# Just one value (scriptable)
bao kv get -field=DB_PASSWORD secret/api

# As JSON
bao kv get -format=json secret/api

# List child paths
bao kv list secret/

# Versioning and rollback

KV v2 keeps history, so a bad write is recoverable:

# See versions
bao kv metadata get secret/api

# Read a specific older version
bao kv get -version=3 secret/api

# Restore (promote) an old version to be current
bao kv rollback -version=3 secret/api

# Rotating a secret

  1. Write the new value:

    bao kv patch secret/api DB_PASSWORD='rotated-pw'
    
  2. The External Secrets Operator syncs it into the cluster Secret within its refresh interval (typically ~1 minute).

  3. Pods read most secrets at startup, so restart them to pick up the change:

    kubectl rollout restart deployment/api -n api
    

# Deleting

# Soft-delete the latest version (recoverable)
bao kv delete secret/api

# Permanently destroy specific versions
bao kv destroy -versions=1,2 secret/api

# Remove the path and all history entirely
bao kv metadata delete secret/api

# Good practice

  • One path per app or component: keeps access and rotation simple.
  • Reference, don’t copy: let the External Secrets Operator pull values in; don’t paste them into manifests or ConfigMaps.
  • Rotate on exposure: if a value may have leaked, patch a new one and restart the consuming pods.

➡️ Next: wire these secrets into your workloads with the External Secrets Operator.