back to work

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.

SecretsOpenBaoHashiCorp VaultSecurityMigration

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:

  1. Centralize scattered secrets into Vault KV-v2 with scoped policies.
  2. Stand up OpenBao; import secret engines, policies, and auth-method config.
  3. Dual-read validation — confirm OpenBao returns identical secrets for a representative path set.
  4. Repoint consumers via a single environment-driven address (no hardcoded endpoints).
  5. 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.