Skip to main content

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

TaskStatus
Enable KV v2 secrets engine at secret/Done
Create admin policyDone
Store high-priority API keysDone

Phase 2: Core Secrets - COMPLETE

Secret1Password ItemOpenBao PathStatus
Anthropic API KeyAnthropic API Keysecret/api-keys/anthropicDone
OpenAI API Key.envsecret/api-keys/openaiDone
Deepgram API KeyDeepgram API Keysecret/api-keys/deepgramDone
ElevenLabs API KeyElevenLabs API Keysecret/api-keys/elevenlabsDone
Google Maps API Key.envsecret/api-keys/google-mapsDone
Linear API KeyLinear API Keysecret/api-keys/linearDone
PostgreSQL.envsecret/database/postgresDone
Redis.envsecret/database/docs/infrastructure/redisDone
SlackSlack App - The Nornssecret/integrations/slackDone
TwilioTwiliosecret/integrations/twilioDone
GitLab.envsecret/integrations/gitlabDone
AWSAWSsecret/infrastructure/awsDone
LangfuseLangfusesecret/services/langfuseDone
LiveKitLiveKitsecret/services/livekitDone

Phase 3: Service Integration - COMPLETE

ServiceAuth MethodStatus
Norns AgentAppRoleDone - Reading from OpenBao
Norns ExecutorAppRoleDone - Reading from OpenBao
n8nAppRoleConfigured, not yet integrated
BifrostAppRoleConfigured, not yet integrated
Voice GatewayAppRoleConfigured, not yet integrated

Phase 4: Full Integration - PENDING

TaskStatus
n8n reading from OpenBaoPending
Bifrost reading from OpenBaoPending
Voice Gateway reading from OpenBaoPending
Remove secrets from .env filesPending

Phase 5: Dynamic Secrets - FUTURE

TaskStatus
Enable database secrets engineFuture
Configure dynamic PostgreSQL credentialsFuture
Implement automatic rotationFuture

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

CategoryExamplesReason
SSH Keysravenhelm-homelabHuman interactive use
PasswordsHomebridge, Pihole adminWeb UI logins
OIDC Client SecretsNorns OIDC, Portal OIDCManual rotation, infrequent access
Recovery KeysOpenBao Root KeysEmergency access only
AppRole CredentialsOpenBao 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:

  1. Services Fall Back: vault-entrypoint.sh uses existing env vars if vault auth fails
  2. 1Password Backup: All credentials remain in 1Password
  3. .env Files: Original .env files preserved
  4. 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)