Skip to content

OpenBao

OpenBao is the heezy secrets manager (self-hosted HashiCorp Vault fork).

Access

URL: https://openbao.heezy.info

Internal only — resolves via dnsmasq to 192.168.1.25 (SWAG). Never goes through Cloudflare.

Prerequisite: DNS

Your machine must use 192.168.1.29 as its DNS server.

macOS: System Settings → Network → active interface → Details → DNS → add 192.168.1.29

Verify: dig openbao.heezy.info should return 192.168.1.25

Sign In With Google

The UI has a OIDC method backed by Google. Pick it, leave the role field blank, and sign in with the Google account. That is the whole flow, no token fetching.

  • Token lasts 8 hours, policy admin (full access, revocable, and it shows in the audit log as a login rather than as the barrier's own root token).
  • Only trentnielsen84@gmail.com and trent@mittentechconsulting.com are accepted, and Google must report the address as verified.
  • CLI: BAO_ADDR=https://openbao.heezy.info bao login -method=oidc, which opens a browser and returns on http://localhost:8250/oidc/callback.

The OAuth client is a console object in GCP project onyx-incentive-497913-i9. Its credentials are stored at secret/production/heezy/openbao/google-oidc. Google has no API for creating consumer OAuth clients, so it is not in Terraform. The OpenBao side is replayed by heezy-k8s/apps/openbao/configure-google-oidc.sh and is covered by the daily Raft snapshot. See Recreating the Google login.

Get a Login Token

Fallback when Google is unreachable or the OIDC role is broken. AppRole is also what machines use:

curl -sk -X POST https://openbao.heezy.info/v1/auth/approle/login \
  -H 'Content-Type: application/json' \
  -d "{\"role_id\":\"$VAULT_ROLE_ID\",\"secret_id\":\"$VAULT_SECRET_ID\"}" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['auth']['client_token'])"

VAULT_ROLE_ID and VAULT_SECRET_ID come from the q-mcp/.env file the MCP container reads, not from this page. In the UI: select Token, paste the token, click Sign In. The MCP agent can also generate one on demand.

This page used to publish the AppRole credentials

A literal role_id and secret_id pair were pasted into this command until 2026-08-11. They remain in the git history of heezy-docs and, per mcp-server.js, the same values are the hardcoded fallback used when the env vars are absent. Rotate that AppRole, then update q-mcp/.env. A Vault AppRole rotation silently breaks postgres_query, fortinet_config, and the Cisco switch SSH path until .env is updated, so do both in the same change.

Architecture

Browser → https://openbao.heezy.info
  → dnsmasq: openbao.heezy.info → 192.168.1.25 (SWAG VIP)
  → SWAG terminates TLS → openbao.openbao.svc.cluster.local:8200
  → OpenBao pod (openbao namespace)
  • K8s namespace: openbao
  • Services: openbao-lb LoadBalancer 192.168.1.32:8200, openbao-nodeport 30820, plus ClusterIP openbao, openbao-internal (headless), openbao-ui
  • Storage: data-openbao-0 PVC, 5Gi Longhorn (Raft backend)
  • Auto-unseal: CronJob openbao-unseal runs every 5 min

Secret Paths

All secrets are KV v2 under secret/data/. Verified 2026-08-11 against the ExternalSecrets in heezy-k8s and the roles in ansible-heezy.

Consumed by ExternalSecrets in the cluster

Path Contents
production/heezy/postgres/heezy-credentials Postgres credentials for heezy-finance and receipts
production/heezy/gitea/postgres Gitea's Postgres credentials
production/heezy/gmail/oauth Gmail OAuth client id, secret, refresh token
production/heezy/receipts/aws-credentials Textract IAM creds
all/heezy/discord/webhooks Discord webhooks, including claude-code and budget alerts
production/heezy/gluetun/nordvpn NordVPN credentials for the gluetun sidecars
production/heezy/slskd slskd API key
production/heezy/tailscale Tailscale auth key
production/heezy/swag/cloudflare SWAG DNS-01 token
production/heezy/heezy-blog/cloudflare, production/heezy/heezy-info/cloudflare cloudflared tunnel tokens
production/heezy/oauth-callback/config OAuth callback service config

Consumed by Ansible, Terraform, and the MCP server

Path Contents
production/heezy/terraform/fortigate/secret FortiGate API credentials (Terraform)
production/heezy/network/fortigate FortiGate credentials (fortinet_config MCP tool)
production/heezy/network/ruckus Ruckus credentials
production/heezy/cisco-switch/secret Cisco switch password (sshpass path in mcp-server.js)
production/heezy/ssh/mcp-admin-private-key MCP admin SSH private key
production/heezy/backup/aws-credentials S3 backup IAM creds
production/heezy/github/runner-token, production/heezy/github_runner/aws_credentials Runner registration and AWS access
production/heezy/microk8s/aws_credentials ECR pull credentials refresher
production/heezy/grafana/discord-webhook, .../discord-events-webhook Grafana contact points
production/heezy/big-boi/plex, .../steam-headless, .../discord big-boi compose service secrets
production/heezy/ubuntu/cloud-init-credentials Ubuntu VM default credentials
production/heezy/windows/administrator/credentials Windows admin credentials
production/heezy/uptime-kuma Uptime Kuma credentials

Paths that used to be documented here and do not exist

production/heezy/postgres-credentials, production/heezy/gmail/oauth-credentials, production/heezy/gitea/runner-pat, all/heezy/aws/ecr-credentials, and production/heezy/cloudflare/pages-token. The first two were renamed; the rest have no consumer in any repo. all/heezy/ubuntu/cloud-init-credentials is under production/, not all/.

Troubleshooting

Can't reach the URL: - dig openbao.heezy.info must return 192.168.1.25 - If not, set DNS to 192.168.1.29

Token expired: - Generate a new one with the curl command above

Sealed:

curl -sk https://openbao.heezy.info/v1/sys/health \
  | python3 -c "import sys,json; d=json.load(sys.stdin); print('sealed:', d['sealed'])"
sealed: False = healthy. The unseal CronJob recovers it within 5 minutes automatically.