Secrets Migration Plan
Status: Phase 3 Complete - Migrating secrets from 1Password to OpenBao for centralized secrets management.
Overview
This document outlines the migration of secrets from 1Password to OpenBao for programmatic access by services. 1Password remains the source of truth for human-accessed secrets and as a backup.
Migration Status
Phase 1: Setup - COMPLETE
| Task | Status |
|---|---|
Enable KV v2 secrets engine at secret/ | Done |
| Create admin policy | Done |
| Store high-priority API keys | Done |
Phase 2: Core Secrets - COMPLETE
| Secret | 1Password Item | OpenBao Path | Status |
|---|---|---|---|
| Anthropic API Key | Anthropic API Key | secret/api-keys/anthropic | Done |
| OpenAI API Key | .env | secret/api-keys/openai | Done |
| Deepgram API Key | Deepgram API Key | secret/api-keys/deepgram | Done |
| ElevenLabs API Key | ElevenLabs API Key | secret/api-keys/elevenlabs | Done |
| Google Maps API Key | .env | secret/api-keys/google-maps | Done |
| Linear API Key | Linear API Key | secret/api-keys/linear | Done |
| PostgreSQL | .env | secret/database/postgres | Done |
| Redis | .env | secret/database/docs/infrastructure/redis | Done |
| Slack | Slack App - The Norns | secret/integrations/slack | Done |
| Twilio | Twilio | secret/integrations/twilio | Done |
| GitLab | .env | secret/integrations/gitlab | Done |
| AWS | AWS | secret/infrastructure/aws | Done |
| Langfuse | Langfuse | secret/services/langfuse | Done |
| LiveKit | LiveKit | secret/services/livekit | Done |
Phase 3: Service Integration - COMPLETE
| Service | Auth Method | Status |
|---|---|---|
| Norns Agent | AppRole | Done - Reading from OpenBao |
| Norns Executor | AppRole | Done - Reading from OpenBao |
| n8n | AppRole | Configured, not yet integrated |
| Bifrost | AppRole | Configured, not yet integrated |
| Voice Gateway | AppRole | Configured, not yet integrated |
Phase 4: Full Integration - PENDING
| Task | Status |
|---|---|
| n8n reading from OpenBao | Pending |
| Bifrost reading from OpenBao | Pending |
| Voice Gateway reading from OpenBao | Pending |
| Remove secrets from .env files | Pending |
Phase 5: Dynamic Secrets - FUTURE
| Task | Status |
|---|---|
| Enable database secrets engine | Future |
| Configure dynamic PostgreSQL credentials | Future |
| Implement automatic rotation | Future |
OpenBao Path Structure
secret/
├── api-keys/
│ ├── anthropic # api_key
│ ├── openai # api_key
│ ├── deepgram # api_key
│ ├── elevenlabs # api_key
│ ├── google-maps # api_key
│ └── linear # api_key
├── database/
│ ├── postgres # user, password, host, port, database
│ └── redis # password, host, port
├── services/
│ ├── langfuse # public_key, secret_key, host
│ └── livekit # api_key, api_secret, url
├── infrastructure/
│ └── aws # access_key_id, secret_access_key, region
└── integrations/
├── slack # bot_token, signing_secret, app_token
├── twilio # account_sid, auth_token, whatsapp_number
├── gitlab # token, url
├── notion # api_key
└── todoist # api_key
What Stays in 1Password
| Category | Examples | Reason |
|---|---|---|
| SSH Keys | ravenhelm-homelab | Human interactive use |
| Passwords | Homebridge, Pihole admin | Web UI logins |
| OIDC Client Secrets | Norns OIDC, Portal OIDC | Manual rotation, infrequent access |
| Recovery Keys | OpenBao Root Keys | Emergency access only |
| AppRole Credentials | OpenBao AppRole - * | Backup for vault credentials |
Service Access Policies
Norns Policy
path "secret/data/api-keys/*" { capabilities = ["read"] }
path "secret/data/integrations/*" { capabilities = ["read"] }
path "secret/data/database/postgres" { capabilities = ["read"] }
path "secret/data/database/docs/infrastructure/redis" { capabilities = ["read"] }
n8n Policy
path "secret/data/integrations/*" { capabilities = ["read"] }
path "secret/data/api-keys/*" { capabilities = ["read"] }
path "secret/data/database/*" { capabilities = ["read"] }
Bifrost Policy
path "secret/data/database/postgres" { capabilities = ["read"] }
path "secret/data/database/docs/infrastructure/redis" { capabilities = ["read"] }
path "secret/data/services/langfuse" { capabilities = ["read"] }
Voice Gateway Policy
path "secret/data/api-keys/deepgram" { capabilities = ["read"] }
path "secret/data/api-keys/elevenlabs" { capabilities = ["read"] }
path "secret/data/integrations/twilio" { capabilities = ["read"] }
path "secret/data/services/livekit" { capabilities = ["read"] }
Adding New Secrets
1. Store in OpenBao
ROOT_TOKEN=$(op item get "OpenBao Root Keys" --vault ravenmask --fields "Root Token" --reveal)
ssh ravenhelm@100.115.101.81 "docker exec -e BAO_TOKEN=$ROOT_TOKEN openbao bao kv put secret/api-keys/newservice api_key=xxx"
2. Update Policy (if needed)
# Edit policy file
echo 'path "secret/data/api-keys/newservice" { capabilities = ["read"] }' >> /tmp/norns.hcl
# Apply updated policy
ssh ravenhelm@100.115.101.81 "docker exec -e BAO_TOKEN=$ROOT_TOKEN openbao bao policy write norns /tmp/norns.hcl"
3. Update Service Integration
For Norns, update vault-entrypoint.sh to fetch the new secret:
export NEW_API_KEY="${NEW_API_KEY:-$(fetch_secret 'api-keys/newservice' 'api_key')}"
4. Rebuild and Restart
ssh ravenhelm@100.115.101.81 "cd ~/ravenhelm/docs/AI-ML-Platform/norns-agent && docker compose build && docker compose up -d"
Rollback Plan
If migration causes issues:
- Services Fall Back: vault-entrypoint.sh uses existing env vars if vault auth fails
- 1Password Backup: All credentials remain in 1Password
- .env Files: Original .env files preserved
- OpenBao Secrets: Can be deleted without impact
Success Criteria
- KV v2 engine enabled at
secret/ - All Phase 1-2 secrets stored in OpenBao
- At least one service reading from OpenBao (Norns)
- AppRole configured for 4 services
- OIDC configured for human access
- Auto-unseal configured
- All services reading from OpenBao
- .env secrets removed (keeping only vault credentials)
Related Documentation
- OpenBao - Main documentation
- OpenBao AppRole - Service authentication
- OpenBao Norns Integration - Norns integration