OpenBao
Open-source secrets management platform (Vault fork). Includes automated initialization, auto-unseal CronJob, agent injector, Raft/file storage, Web UI, and ESO integration for centralized secret management.
Architecture
OpenBao Server - Secrets engine, auth backends, policies (:8200)
Agent Injector - Sidecar-based secret injection into pods
Init Job - One-time initialization: unseal keys, admin user, KV engine, ESO policy
Unseal CronJob - Runs every 5 min to auto-unseal after pod restarts
Web UI - Browser-based management interface
Attributes
| Attribute |
Example |
Where It Impacts |
namespace REQ |
openbao |
All manifests, service DNS, init-keys secret namespace |
admin_password REQ |
****** |
Init Job: userpass admin password |
port |
8200 |
helm-values.yaml API listener port, init/unseal jobs VAULT_ADDR |
replicas |
1 |
helm-values.yaml server replicas |
pvc_size |
10Gi |
helm-values.yaml persistent volume claim size |
storageclass |
standard |
helm-values.yaml storageClassName |
service_type |
ClusterIP |
helm-values.yaml K8s service type |
mem_request / mem_limit |
256Mi / 512Mi |
helm-values.yaml resources.requests/limits.memory |
cpu_request / cpu_limit |
250m / 500m |
helm-values.yaml resources.requests/limits.cpu |
openbao_helm_version |
0.25.6 |
helm/generate-yaml.sh chart version |
openbao_app_version |
2.5.1 |
Unseal CronJob container image tag |
Init Job (init-job.yaml)
One-time Kubernetes Job that runs on first deploy to bootstrap OpenBao:
1. Wait for OpenBao to be reachable (30 retries, 10s interval)
2. Initialize OpenBao if not already initialized (key-shares=1, key-threshold=1)
3. Store unseal key + root token in K8s Secret ({name}-init-keys)
4. Unseal if sealed
5. Enable KV v2 secrets engine at secret/
6. Enable userpass auth + create admin user
7. Create ESO read-only policy (eso-read) for ExternalSecret access
RBAC:
ServiceAccount: {name}-init | Role: secrets read/create/update/delete
TTL: 600s | backoffLimit: 5
Auto-Unseal CronJob (unseal-cronjob.yaml)
Runs every 5 minutes to ensure OpenBao stays unsealed after pod restarts:
1. Check if OpenBao is reachable (10s timeout, exits cleanly if not)
2. If sealed: reads unseal key from {name}-init-keys K8s Secret, unseals
3. If already unsealed: skips
Schedule: */5 * * * * | concurrencyPolicy: Forbid | TTL: 120s
Links
| Link |
Direction |
Generated Output |
| Prometheus → OpenBao |
Inbound |
Enables service-monitor.yaml for Prometheus metrics scraping |
| Istio → OpenBao |
Inbound |
Enables istio-injection label on namespace.yaml |
| ESO → OpenBao |
Inbound |
Triggers auto-seed Job in ESO template that populates OpenBao with all component secrets |
Generated Files
| File |
Condition |
Content |
| k8s/deploy/base/namespace.yaml |
Always |
Namespace definition with optional istio-injection label |
| k8s/deploy/base/init-job.yaml |
Always |
Init Job: initialize, unseal, enable KV/auth, create admin, ESO policy + RBAC |
| k8s/deploy/base/unseal-cronjob.yaml |
Always |
CronJob: auto-unseal every 5 min after pod restarts |
| k8s/deploy/base/service-monitor.yaml |
prometheus-openbao link |
ServiceMonitor for Prometheus metrics scraping |
| k8s/deploy/base/kustomization.yaml |
Always |
Kustomize resources + secretGenerator |
| k8s/deploy/base/secret/openbao.env |
Always |
Admin credentials (SOPS encrypted) |
| k8s/deploy/base/secret/registry.json |
Always |
Container registry credentials (SOPS encrypted) |
| helm/helm-values.yaml |
Always |
Helm values: storage, HA, injector, UI, resources, listeners |
| helm/generate-yaml.sh |
Always |
Helm template rendering script |
Ports
| Port |
Service |
Protocol |
| 8200 |
OpenBao API + Web UI |
HTTP/HTTPS |
| 8201 |
Cluster communication (Raft) |
TCP |
Internal Endpoints
API: http://{name}.{namespace}.svc:8200
Web UI: http://{name}.{namespace}.svc:8200/ui
Init Keys Secret: {name}-init-keys (unseal-key, root-token)