Background
bootroot currently operates OpenBao using a manual unseal method based on Shamir secret sharing (3 shares, threshold 2). This works fine in air-gapped environments, but when operating remotely over the internet, it becomes impractical because an operator must manually enter unseal keys every time OpenBao restarts.
Goal
Provide opt-in support for auto-unseal via Cloud KMS when the user chooses to use it. The default remains the existing Shamir method. This issue covers new installations only; migrating existing Shamir deployments to auto-unseal will be tracked in a separate issue.
Supported KMS Providers
- AWS KMS
- GCP Cloud KMS
- Azure Key Vault
Korean cloud providers' KMS (NHN, Naver Cloud, Kakao Cloud, etc.) are excluded from the current scope because OpenBao does not officially support them. Expansion will be considered once OpenBao completes its Auto Unseal Plugin support.
Authentication Methods
Calling Cloud KMS APIs requires cloud authentication. Two methods are supported depending on the deployment environment.
1. Running on a Cloud VM
Authenticate automatically without credentials using each cloud's VM permission features. This works by obtaining temporary tokens from the metadata endpoint inside the VM.
| Cloud |
Feature Name |
| AWS |
IAM Role (Instance Profile) |
| GCP |
Service Account |
| Azure |
Managed Identity |
- This is the recommended approach for security since there are no credentials to manage separately.
- The metadata endpoint must be accessible from inside the Docker container (note AWS IMDSv2 hop limit, etc.).
2. Running outside a Cloud VM (on-premises, different cloud, etc.)
Authenticate by passing credentials via environment variables.
- AWS:
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
- GCP:
GOOGLE_APPLICATION_CREDENTIALS (service account key file path — the JSON file must be volume-mounted into the container)
- Azure:
AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET
While cloud-side controls (IP restrictions, audit logs, credential deactivation, periodic rotation) offer more safeguards than raw unseal keys, KMS credentials remain high-risk credentials as the seal trust root. They require the same level of protection as unseal keys.
Caveat: KMS Lifecycle Dependency
Auto-unseal provides operational convenience, but creates a strong dependency between OpenBao's data and the KMS key. If the KMS key is deleted or becomes inaccessible, OpenBao data may be unrecoverable even with backups. This risk must be documented in operational guides, along with KMS key protection policies (deletion protection, multi-region replication, etc.).
Scope of Changes
Seal configuration is read when OpenBao starts, so it must be configured before bootroot infra up. Therefore, this feature spans both the infra and init layers.
bootroot infra up (seal configuration)
- Add seal type options (e.g.,
--seal-type=awskms, --kms-key-id=..., --kms-region=...)
- Add credential configuration options depending on whether running on a Cloud VM
- Conditionally insert a
seal stanza into openbao.hcl before starting the OpenBao container
- e.g.,
seal "awskms" { kms_key_id = "..." region = "..." }
- Also consider injecting
VAULT_SEAL_TYPE env var + provider-specific env vars into Compose
- For non-Cloud VM + GCP environments, configure the volume mount path for the credential JSON file
Seal Configuration Persistence
Currently, openbao/openbao.hcl is a static file bind-mounted as read-only in Compose. The dynamically configured seal settings for auto-unseal must persist across subsequent infra up restarts. The source of truth for seal configuration is the rendered HCL or pre-infra up artifacts such as Compose overrides/.env. The following design decisions are needed:
- Convert
openbao.hcl to a rendered file and persist the output on disk
- Or store seal-related environment variables in a Compose override file/
.env
state.json is not the source of truth for seal configuration; it is used only as metadata so that post-init commands (rotate, etc.) can identify the current seal mode.
bootroot init (initialization flow)
- When using auto-unseal, change the
/sys/init request model:
- Shamir:
secret_shares, secret_threshold
- Auto-unseal:
stored_shares, recovery_shares, recovery_threshold
- The meaning of keys in the response changes: process as recovery keys instead of unseal keys
- Skip the unseal step and wait for auto-unseal completion instead
- Branch terminology in CLI output and summary: use "recovery key" instead of "unseal key"
rotate openbao-recovery
- In OpenBao 2.4,
sys/rekey/* was deprecated, and in 2.5, unauthenticated rekey endpoints are disabled by default
- Use new authenticated endpoints depending on seal type:
- Shamir share rotation:
/sys/rotate/root/*
- Auto-unseal recovery key rotation:
/sys/rotate/recovery/*
- Root token issuance/rotation is a separate flow from the above endpoints and retains the existing approach
- Note: This endpoint change also needs to be applied to the existing Shamir mode
rotate openbao-recovery (handle in a separate issue or together with this one)
CLI Flag Terminology Transition
The current CLI flags for rotate openbao-recovery (--rotate-unseal-keys, --unseal-key, --unseal-key-file) and help text are written for Shamir. In auto-unseal mode:
--rotate-unseal-keys → change behavior to recovery key rotation (or add --rotate-recovery-keys)
--unseal-key / --unseal-key-file → change meaning to recovery key input (or add --recovery-key / --recovery-key-file)
- Display correct terminology in help text based on seal type
- Decide on backward compatibility during implementation (whether to keep existing flags as aliases)
Docker Compose
- Configure a path to pass credential environment variables to the OpenBao container in non-Cloud VM environments
- Add credential JSON file volume mount for GCP
state.json
- Add a
seal_type field so subsequent commands can identify the current seal mode (not the source of truth for seal configuration)
- Track recovery key provisioning status
Out of Scope
- Transit auto-unseal (using the Transit engine of a separate OpenBao instance)
- Korean cloud KMS support (no official OpenBao support)
- Migrating existing Shamir deployments to auto-unseal (tracked in a separate issue)
Background
bootroot currently operates OpenBao using a manual unseal method based on Shamir secret sharing (3 shares, threshold 2). This works fine in air-gapped environments, but when operating remotely over the internet, it becomes impractical because an operator must manually enter unseal keys every time OpenBao restarts.
Goal
Provide opt-in support for auto-unseal via Cloud KMS when the user chooses to use it. The default remains the existing Shamir method. This issue covers new installations only; migrating existing Shamir deployments to auto-unseal will be tracked in a separate issue.
Supported KMS Providers
Korean cloud providers' KMS (NHN, Naver Cloud, Kakao Cloud, etc.) are excluded from the current scope because OpenBao does not officially support them. Expansion will be considered once OpenBao completes its Auto Unseal Plugin support.
Authentication Methods
Calling Cloud KMS APIs requires cloud authentication. Two methods are supported depending on the deployment environment.
1. Running on a Cloud VM
Authenticate automatically without credentials using each cloud's VM permission features. This works by obtaining temporary tokens from the metadata endpoint inside the VM.
2. Running outside a Cloud VM (on-premises, different cloud, etc.)
Authenticate by passing credentials via environment variables.
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGIONGOOGLE_APPLICATION_CREDENTIALS(service account key file path — the JSON file must be volume-mounted into the container)AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRETWhile cloud-side controls (IP restrictions, audit logs, credential deactivation, periodic rotation) offer more safeguards than raw unseal keys, KMS credentials remain high-risk credentials as the seal trust root. They require the same level of protection as unseal keys.
Caveat: KMS Lifecycle Dependency
Auto-unseal provides operational convenience, but creates a strong dependency between OpenBao's data and the KMS key. If the KMS key is deleted or becomes inaccessible, OpenBao data may be unrecoverable even with backups. This risk must be documented in operational guides, along with KMS key protection policies (deletion protection, multi-region replication, etc.).
Scope of Changes
Seal configuration is read when OpenBao starts, so it must be configured before
bootroot infra up. Therefore, this feature spans both theinfraandinitlayers.bootroot infra up(seal configuration)--seal-type=awskms,--kms-key-id=...,--kms-region=...)sealstanza intoopenbao.hclbefore starting the OpenBao containerseal "awskms" { kms_key_id = "..." region = "..." }VAULT_SEAL_TYPEenv var + provider-specific env vars into ComposeSeal Configuration Persistence
Currently,
openbao/openbao.hclis a static file bind-mounted as read-only in Compose. The dynamically configured seal settings for auto-unseal must persist across subsequentinfra uprestarts. The source of truth for seal configuration is the rendered HCL or pre-infra upartifacts such as Compose overrides/.env. The following design decisions are needed:openbao.hclto a rendered file and persist the output on disk.envstate.jsonis not the source of truth for seal configuration; it is used only as metadata so that post-initcommands (rotate, etc.) can identify the current seal mode.bootroot init(initialization flow)/sys/initrequest model:secret_shares,secret_thresholdstored_shares,recovery_shares,recovery_thresholdrotate openbao-recoverysys/rekey/*was deprecated, and in 2.5, unauthenticated rekey endpoints are disabled by default/sys/rotate/root/*/sys/rotate/recovery/*rotate openbao-recovery(handle in a separate issue or together with this one)CLI Flag Terminology Transition
The current CLI flags for
rotate openbao-recovery(--rotate-unseal-keys,--unseal-key,--unseal-key-file) and help text are written for Shamir. In auto-unseal mode:--rotate-unseal-keys→ change behavior to recovery key rotation (or add--rotate-recovery-keys)--unseal-key/--unseal-key-file→ change meaning to recovery key input (or add--recovery-key/--recovery-key-file)Docker Compose
state.jsonseal_typefield so subsequent commands can identify the current seal mode (not the source of truth for seal configuration)Out of Scope