Vault
Purpose
Vault is Lumie's shared secret store, and Vault Secrets Operator (VSO) is the default in-cluster projection path from Vault KV data into Kubernetes Secrets. The repo also keeps a small amount of legacy compatibility scaffolding around older External Secrets usage, but new manifests are expected to use VaultStaticSecret.
This page is a reference document for developers changing secret projection, bootstrap auth, or the boundaries between GitOps-managed Vault resources and manual Vault runtime setup.
Source Paths
| Path | Role |
|---|---|
lumie-infra/bootstrap/vault/argocd.yaml | Argo CD application that installs Vault, VSO, the common wrapper chart, and local auth manifests |
lumie-infra/bootstrap/vault/helm-values.yaml | Vault server config, probes, service, and resource settings |
lumie-infra/bootstrap/vault/vso-helm-values.yaml | Vault Secrets Operator controller configuration |
lumie-infra/bootstrap/vault/common-values.yaml | Shared RBAC and legacy clusterSecretStore compatibility block |
lumie-infra/bootstrap/vault/manifests/vault-auth.yaml | Shared VaultConnection and VaultAuth resources |
lumie-infra/charts/common/templates/vault-static-secrets.yaml | Reusable template for projecting VaultStaticSecret resources from app values |
lumie-infra/provision/ansible/roles/argocd-bootstrap/tasks/main.yml | Creates vault-config-secret before Argo CD takes over |
lumie-infra/bootstrap/vault/OIDC-SETUP.md | Manual, non-GitOps setup for Vault's OIDC auth mount |
Public Surface
| Surface | Contract |
|---|---|
| Vault service | ClusterIP service on port 8200 in namespace vault |
| UI | Enabled, but no ingress is declared in the inspected repo; external access is expected through Teleport |
| Shared VSO auth | VaultConnection vault-connection plus VaultAuth vault-auth |
| Projection template | App teams declare common.vaultStaticSecrets and charts/common renders VaultStaticSecret CRs |
Runtime Flow
Shared Auth Contract
The shared auth surface is small but important:
kind: VaultAuth
metadata:
name: vault-auth
namespace: vault
spec:
allowedNamespaces:
- "*"
kubernetes:
role: vault-secrets-operator
serviceAccount: default
Important details from the inspected sources:
vault-authis shared across namespaces throughallowedNamespaces: ["*"].vault-auth-localexists as a vault-namespace workaround for anallowedNamespacesbug.charts/common/templates/vault-static-secrets.yamldefaultsvaultAuthReftovault/vault-auth, so most app values files do not repeat that wiring.- bootstrap Ansible creates
vault-config-secret, which points Vault's storage backend at the MinIOvaultbucket.
Bootstrap And Runtime Boundaries
| Responsibility | Owner |
|---|---|
vault-config-secret, initial namespace creation, first Argo CD install | Ansible bootstrap role |
| Vault server deployment and VSO controller | bootstrap/vault/argocd.yaml and Helm values |
| Secret projection into workloads | VaultStaticSecret resources declared directly or rendered from charts/common |
| Vault initialization, unseal, and OIDC auth mount | Manual runtime procedure in bootstrap/vault/OIDC-SETUP.md and Ansible task notes |
Vault is not fully self-bootstrapping. A new cluster still requires vault operator init, unseal, and any OIDC auth setup outside the GitOps manifests.
Mutating bootstrap work is intentionally out of scope for this reference page. Use lumie-infra/bootstrap/vault/OIDC-SETUP.md and the Ansible bootstrap role as the handoff surface when you need to initialize, unseal, or wire runtime auth.
Failure Modes And Drift
| Failure point | Behavior |
|---|---|
| Vault sealed or uninitialized | VSO cannot refresh destination Secrets |
Missing vault-config-secret | Vault server cannot mount its MinIO-backed config |
Missing VaultStaticSecret projection | Workloads fail on missing environment variables or Secret mounts |
rolloutRestartTargets omitted where required | Secret refresh does not automatically restart pods that only read env vars at startup |
Inspected sources also disagree on the legacy secret-management story:
| Source | Claim |
|---|---|
lumie-infra/AGENTS.md | Says SealedSecrets and ExternalSecrets are forbidden and Vault-only is the rule |
bootstrap/vault/common-values.yaml | Still renders a compatibility clusterSecretStore and says it remains during an ESO to VSO migration |
lumie-infra/README.md | Still describes the secret layer as HashiCorp Vault + External Secrets Operator |
Treat VSO plus VaultStaticSecret as the active contract. The compatibility blocks and README text are legacy drift.
Verification
cd lumie-infra
rg -n "VaultStaticSecret|vault-auth|vault-connection|clusterSecretStore|vault-config-secret" \
bootstrap/vault charts/common provision/ansible applications platform security storage
kubectl get vaultconnections,vaultauth,vaultstaticsecrets -A
kubectl get application vault -n argocd -o yaml
kubectl get statefulset,svc,secret -n vault
kubectl port-forward -n vault svc/vault 8200:8200
curl -sS -o /dev/null -w "%{http_code}\n" \
"http://127.0.0.1:8200/v1/sys/health?standbyok=true&sealedcode=204&uninitcode=204"
Success signals:
- The
vaultArgo CD application isHealthyandSynced. VaultConnectionvault-connectionplusVaultAuthvault-authexist in namespacevault.- The
vault-config-secretbootstrap secret is present and thevaultStatefulSet exists. - The health probe returns
200for an active node or204during the pre-init or sealed bootstrap state that the chart is explicitly configured to tolerate.