OpenBao Secrets
OpenBao provides self-service secret management for project teams. Unlike agenix (which encrypts secrets in git), OpenBao stores secrets centrally and delivers them to hosts at runtime.
When to Use What
| Use Case | Tool |
|---|---|
| Bootstrap credentials (AppRole, etc.) | agenix |
| Infrastructure secrets (ACME, Tofu tokens) | agenix |
| Project/application secrets | OpenBao |
Architecture
- Developers log in via Keycloak OIDC to manage secrets
- Hosts authenticate via AppRole auth to fetch secrets at runtime
bao-agentruns on each host and renders secrets to/run/secrets/<name>.env
For Developers
Accessing OpenBao
export BAO_ADDR=https://secrets2.scottylabs.orgbao login -method=oidcYour access depends on your Keycloak group membership:
/projects/<project>→ read/writesecret/projects/<project>/dev/*/projects/<project>/admins→ read/writesecret/projects/<project>/prod/*/projects/devops→ full admin access
Managing Secrets
# Write secretsbao kv put secret/projects/my-project/prod/env \ DATABASE_URL="postgres://..." \ API_KEY="..."
# Read secretsbao kv get secret/projects/my-project/prod/env
# List secretsbao kv list secret/projects/my-project/prodFor Operators
Setting Up a New Host
After adding a host to hosts in flake.nix and deploying, the AppRole is created automatically. You need to generate credentials:
- Get the role ID (on infra-01 after tofu-identity runs):
sudo journalctl -u tofu-identity | grep '"<hostname>"' | tail -1- Generate a secret ID:
export BAO_ADDR=https://secrets2.scottylabs.orgbao login -method=oidcbao write -f auth/approle/role/<hostname>/secret-id # requires devops group membership- Add to
secrets.nix:
"secrets/<hostname>/bao-role-id.age".publicKeys = admins ++ [ <hostname> ];"secrets/<hostname>/bao-secret-id.age".publicKeys = admins ++ [ <hostname> ];- Create the agenix secrets:
agenix -e secrets/<hostname>/bao-role-id.ageagenix -e secrets/<hostname>/bao-secret-id.ageAdding a Project to a Host
In the host’s service config:
scottylabs.bao-agent = { enable = true; secrets.<service-name> = { project = "<project-name>"; user = "<service-user>"; };};
services.<service-name> = { enable = true; environmentFile = "/run/secrets/<service-name>.env";};
systemd.services.<service-name> = { after = [ "bao-agent.service" ]; wants = [ "bao-agent.service" ];};The host automatically gets read access to secret/projects/<project>/prod/*.
Adding a New Project
- (temporary) Add to
tofu/identity/projects.json:
["discord-verify", "new-project"]-
Push and wait for
tofu-identityto apply -
(temporary) Add users to the Keycloak group
/projects/new-project(or/projects/new-project/adminsfor prod access)