Files
automations/deployments/openbao/docker-compose.yml
T
57_WolveandClaude Opus 5 f8c839a163 feat(openbao): pin 2.6.2, and correct the mlock and recovery-path claims
2.5.5 was two releases behind. Verified against the openbao/openbao source at
tag v2.6.2 that the bump is safe for an existing vault: raft's on-disk format
is unchanged (identical bbolt / hashicorp-raft / raft-boltdb pins,
byte-identical physical/raft/types.proto), snapshots restore in both
directions, and every stanza this config.hcl uses still parses -- the config
parser only moved import paths and the listener diff is additive.

Three corrections that came out of that check.

deploy.sh's printed crash-loop recovery command was already broken by 2.6.0.
That release adds `USER openbao` to the alpine image, so the container no
longer starts as root; the `docker run ... --entrypoint sh ... chown` it tells
the operator to run now executes as uid 100 and fails. Added `--user 0:0`, and
dropped the stale 2.5.5 literal from the same string. The detection logic
itself is unaffected -- `id -u openbao` still reads /etc/passwd and still
returns 100, verified by extracting the passwd layer from both published
images -- so a02524a holds and the volume does not need re-chowning.

The mlock story was wrong, and was already wrong on 2.5.5. OpenBao removed
mlock support: its own config parser carries "OpenBao has dropped support for
mlock. Please remove the line disable_mlock = false from your config and
disable or encrypt swap instead." So `cap_add: [IPC_LOCK]` and
`ulimits: memlock: -1` are inert, and config.hcl's "mlock keeps key material
off swap -- REQUIRED" was describing something that does not happen. The
BEHAVIOUR was right all along, because deploy.sh disables swap, which is the
actual mitigation; only the explanation was wrong. Corrected in config.hcl,
docker-compose.yml and the README. The two compose settings stay: they are
harmless, and removing them would recreate every deployed container for no
gain.

The built-in `seal "pkcs11"` stanza is deprecated in 2.6.0 for removal in
v2.7.0, and the HSM distribution is discontinued by then; PKCS#11 auto-unseal
continues only via the external `plugin "kms" "pkcs11" {}`. Noted where the
commented-out stanza lives, since a stack relying on it has to move before
taking 2.7.x.

Also worth recording and NOT acting on: do not switch to the openbao-distroless
image variant. It ships no shell, which breaks every `docker compose run
--entrypoint sh` probe deploy.sh uses.

Upgrading a LIVE vault is not automatic -- snapshot first, and the restart
comes back sealed. That is the next commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 09:10:20 -05:00

60 lines
2.7 KiB
YAML

# OpenBao stack — hardened tape-encryption key store for Kanrisha.
#
# Topology (same-LAN, NO reverse proxy):
# Kanrisha tape host --https--> openbao:8200 (native TLS on the vault itself)
#
# Unlike the other stacks in this repo there is no Caddy / Let's Encrypt: a
# secrets store terminates TLS itself and is reached over the LAN, not the
# public internet. TLS is a self-signed cert (deploy.sh generates it) or a
# CA-signed pair you drop in ./tls (e.g. via your Smallstep CA over ACME).
name: openbao
volumes:
openbao-data: # raft integrated storage — the vault's persistent state
services:
openbao:
image: openbao/openbao:${OPENBAO_TAG:-2.6.2}
container_name: openbao
command: server -config=/openbao/config/config.hcl
restart: unless-stopped
# These two are INERT. OpenBao dropped mlock support entirely, so nothing in
# the container locks memory and `disable_mlock = false` in config.hcl is a
# hard startup error. They are kept only because they are harmless and
# removing them would recreate every deployed container for no gain.
# Key material is kept off disk by DISABLING SWAP, which deploy.sh does.
cap_add:
- IPC_LOCK
ulimits:
memlock: -1
ports:
# Native-TLS API. Publish on the LAN IP only (OPENBAO_BIND) so it is not
# exposed on unrelated interfaces. NOTE: a Docker-published port is DNAT'd
# and bypasses the host INPUT firewall, so a source restriction there does
# NOT gate it — narrow access with OPENBAO_BIND + the optional mTLS
# (tls_require_and_verify_client_cert) stanza in config.hcl, and initialise
# the vault immediately (an uninitialised vault can be init'd by anyone who
# can reach it). deploy.sh defaults OPENBAO_BIND to OPENBAO_ADDR when it is
# an IP.
- "${OPENBAO_BIND:-0.0.0.0}:8200:8200"
volumes:
- ./config.hcl:/openbao/config/config.hcl:ro
- ./tls:/openbao/tls:ro
- openbao-data:/openbao/data
environment:
# PKCS#11 auto-unseal PIN — only read when the seal "pkcs11" stanza is
# enabled in config.hcl. Harmless (unused) otherwise.
BAO_HSM_PIN: "${OPENBAO_HSM_PIN:-}"
# HA / multi-node only: advertise this node's reachable LAN address.
# BAO_API_ADDR: "https://${OPENBAO_ADDR}:8200"
# BAO_CLUSTER_ADDR: "https://${OPENBAO_ADDR}:8201"
# 0 = unsealed (healthy); 2 = sealed -> unhealthy so a node needing an unseal
# is visible. -tls-skip-verify because the listener may use a self-signed cert.
healthcheck:
test: ["CMD", "bao", "status", "-address=https://127.0.0.1:8200", "-tls-skip-verify"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s