Centralizing Secrets: Repo Settings → Vault → OpenBao
Moving secrets out of GitLab repo settings into HashiCorp Vault (KV-v2), then to OpenBao after the licensing change — keeping the API contract stable so apps and pipelines needed no rewrite.
Problem
Secrets lived in GitLab repo/CI settings — scattered, hard to rotate, and easy to over-expose. We first centralized them in HashiCorp Vault (KV-v2). Then Vault's move to the BSL license pushed us to an open-source path forward we could self-host without licensing ambiguity, while preserving everything that already depended on the Vault API: apps, CI/CD jobs, and operators.
Constraint
- Zero secret exposure during migration — nothing in plaintext in logs, CI output, or transit.
- Minimal application change: many consumers read secrets via the Vault HTTP API and auth methods.
- Auditable cutover with a clear rollback point.
- No downtime for services that read secrets at startup and at runtime.
Architecture
OpenBao is API-compatible with Vault at the version we targeted, so the client contract — auth methods, KV-v2 paths, policies — stays the same. I stood up OpenBao alongside Vault, replicated policies and secret engines, then repointed consumers behind a single configurable address.
Migration sequence:
- Centralize scattered secrets into Vault KV-v2 with scoped policies.
- Stand up OpenBao; import secret engines, policies, and auth-method config.
- Dual-read validation — confirm OpenBao returns identical secrets for a representative path set.
- Repoint consumers via a single environment-driven address (no hardcoded endpoints).
- Decommission the old source once every consumer is verified.
Decision / Trade-off
- API compatibility over a clean-slate redesign. Keeping the contract meant apps and pipelines changed an endpoint, not their code — small blast radius, trivial rollback.
- Ran both systems briefly. The overlap cost some operational complexity but bought a safe, verifiable cutover instead of a risky big-bang switch.
Result
- Secrets moved out of repo settings into a centralized store, then onto OpenBao with no application code rewrites — endpoint change only.
- Zero plaintext secret exposure in logs or CI throughout.
- Rollback stayed one config change away until decommissioning.
- Eliminated licensing ambiguity by standardizing on an open-source secret store.
What I'd watch next: prefer short-lived dynamic credentials where possible, and alert on secret-engine / auth-method drift between environments.