Skip to content

Vault sealed after power loss = lab-wide outage: distribute OpenBao unseal keys + add auto-unseal #236

Description

@ccrutchf

Incident (2026-06-16, server-room power outage)

A power outage rebooted the lab. krg-prod came back but Grafana, Authentik, Guacamole, Temporal, and Vaultwarden were all down/degraded. Single root cause:

  • OpenBao (krg-vault) seals on every reboot (Shamir, 5 shares, threshold 3). After the outage it came up Sealed: true, Unseal Progress 0/3.
  • openbao-agent.service on krg-prod sat in activating for 40+ min, looping on approle/login → 503 "Vault is sealed" (backoff ~5 min), so it rendered zero secrets to /run/krg/....
  • The entire krg-prod compose project is requires=openbao-agent.service (fail-closed), so krg-prod.service never started this boot (queued, inactive (dead)). Grafana exited and stayed down; Authentik/Guacamole/Temporal-UI crash-looped on missing /run secrets and on each other.

The lab stayed down until an operator manually retrieved the unseal keys and unsealed krg-vault.

The real finding: the unseal keys are not distributed safely

The 3-of-5 Shamir unseal keys were stored inside Vaultwarden — which runs behind the very stack OpenBao gates. That is a circular root-of-trust: you can't unseal the vault without the keys, and the keys live behind the thing the vault unlocks.

We recovered only by luck: Vaultwarden's master-password login path is independent of both OpenBao and Authentik (its data is on-disk SQLite; SSO_ONLY is unset). Its SSO was 404ing, but master-password still worked. Change one thing — Vaultwarden needing a rendered /run secret to boot, or sharing the stack's Postgres — and the lab is bricked.

Proposed work

  1. Distribute the Shamir shares correctly. One share per admin (chris, dzuberi, shperry, …), held out-of-band in stores that do not depend on krg-vault or the krg-prod stack (personal password manager not behind this SSO, age/GPG-encrypted blob, hardware token, sealed paper). Invariant: ≥ threshold (3) shares must be retrievable with krg-vault AND krg-prod both down. No single store may hold ≥3.
  2. Add auto-unseal so a power-cycle self-heals without a human: a seal stanza in the krg-vault Nix config (transit auto-unseal against a second bao, cloud KMS, or a TPM-backed key). The auto-unseal root of trust must live outside this blast radius. Keep the distributed Shamir shares as recovery keys for break-glass.
  3. Document custody (who holds which share, how to convene 3) in the recovery runbook (see companion issue).

Acceptance criteria

  • Unseal shares re-split and distributed to ≥3 independent custodians/locations; old Vaultwarden-only copy revoked (operator rekey if shares were exposed).
  • Auto-unseal configured in IaC for krg-vault, validated by a reboot that comes back unsealed with no human.
  • Custody + recovery documented; an outage no longer requires tribal knowledge.

Related: companion issues for the recovery runbook and temporal-ui startup resilience; #184 (secret rendering, already done) is the consumer side of this. This is the OpenBao SPOF analogue of the krg-ldap "second DC" item.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:secretsOpenBao/Vault secret management, migration & bootstraparea:securityHost/endpoint hardening (OEC, crowdsec, PVE, SSH, accounts)enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions