Files
Lucas WintherandClaude Opus 5.5 665ac7d52f Render stack secrets from OpenBao in compose_stack
stack_secrets reads KV v2 on the target host and writes the stack's .env at
0600, failing loudly on a sealed vault, a bad token, a missing field or an
unsafe value. Adds an example OpenBao stack on app and moves webapp onto it;
metrics keeps a hand-placed .env.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 15:15:04 +02:00

54 lines
2.3 KiB
YAML

---
# OpenBao: the secret store the other stacks read their credentials from, and so
# imported in site.yml before any stack that sets stack_secrets.
#
# It deliberately declares no stack_secrets. It is the root of trust and cannot
# depend on itself.
#
# data/ is the file storage backend. The image runs as uid 100, gid 1000 and
# never as root, so unlike an image that starts as root and chowns its own data,
# it cannot fix the directory from inside the container — a bind mount Docker
# created would be root-owned and OpenBao could not write its storage at all.
# owner and group name that uid outright. No mode: recursing one over live
# storage would rewrite the permissions of the keyring.
#
# Setting owner is what makes the role escalate, so the host has to have been
# bootstrapped with -e deploy_sudo=true.
#
# It runs on app, the only host with a stack that sets stack_secrets. The role
# reads from 127.0.0.1 on the target, so a second host that wants secrets needs
# its own vault or a vault_addr it can reach — see docs/secrets.md.
#
# Init and unseal are manual and stay manual — see docs/secrets.md. After a
# reboot the vault is sealed and every deploy that reads a secret fails until
# somebody unseals it. That is the accepted cost of hosting the vault on the
# host it serves.
- name: Deploy OpenBao
hosts: app
gather_facts: false
tags: [openbao]
roles:
- role: compose_stack
vars:
stack_name: openbao
stack_dirs:
- path: "{{ stack_dest }}/data"
owner: "100"
group: "1000"
post_tasks:
# Not a restart. Restarting OpenBao seals it, so an automatic restart in the
# middle of a site.yml run would seal the vault and fail every stack
# imported after this one. Say what happened and let a person pick when.
- name: Report that the payload changed and OpenBao needs a restart
ansible.builtin.debug:
msg: >-
The OpenBao payload changed on {{ inventory_hostname }}, and the
running container is still on the old configuration. Restart it when
you are ready to unseal again:
`docker compose -f {{ stack_root }}/openbao/docker-compose.yml restart`,
then `docker exec -it openbao bao operator unseal` three times. See
docs/secrets.md.
when: compose_stack_synced | default(false)