Skip to content

Migrate Kamal secrets from 1Password to Bitwarden (consumer)#168

Merged
fleveque merged 3 commits into
mainfrom
chore/bws-migration
May 24, 2026
Merged

Migrate Kamal secrets from 1Password to Bitwarden (consumer)#168
fleveque merged 3 commits into
mainfrom
chore/bws-migration

Conversation

@fleveque

@fleveque fleveque commented May 24, 2026

Copy link
Copy Markdown
Owner

First of three PRs (one per service repo) migrating deploy secrets from 1Password to consumer Bitwarden Password Manager (free tier, no project caps). 1P access requires a paid Service Account tier; Bitwarden's bw CLI is the free alternative Kamal supports out of the box (--adapter bitwarden). Full plan: ~/.claude/plans/cached-doodling-scroll.md.

Earlier revision of this PR targeted Bitwarden Secrets Manager (BWS), but BWS Free caps at 3 projects per org — too tight as more services land. Switched to consumer Bitwarden (no item cap).

Three commits

  1. Snapshot current 1P-driven .kamal/secrets + .kamal/secrets.beta as .1password.example — verbatim, no behaviour change.
  2. Switch the active secrets files to the bitwarden adapter. Reads a Bitwarden Secure Note item (quantic-prod for prod, quantic-beta for beta) holding all relevant secrets as custom fields. Authentication via BW_CLIENTID + BW_CLIENTSECRET (personal API key) and BW_PASSWORD (master password for vault unlock).
  3. Workflow + docs: deploy workflow installs the bw CLI via npm install -g @bitwarden/cli on each run; env block swapped from OP_* to BW_*; env.sample and README updated.

Before merging — operator prereqs (covers all 3 repos)

  1. Use any personal Bitwarden account (no org needed). Free tier is fine.
  2. In your vault, create two Secure Note items:
    • quantic-prod
    • quantic-beta
  3. On each item, add the relevant secrets as custom fields (text type, hidden-as-password preferred):
    • prod: KAMAL_REGISTRY_PASSWORD, RAILS_MASTER_KEY, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GEMINI_API_KEY, VITE_LOGO_SERVICE_URL, VITE_LOGO_SERVICE_API_KEY, TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_HANDLE, TELEGRAM_WEBHOOK_SECRET, plus the logo-service + pulse keys
    • beta: same minus telegram + minus pulse's LOGO_SERVICE_API_KEY
  4. Generate a personal API key: Bitwarden web vault → Account Settings → Security → Keys → "View API Key". Record client_id and client_secret.
  5. Add to each of the three repos' GitHub Actions secrets: BW_CLIENTID, BW_CLIENTSECRET, BW_PASSWORD (your master password).
  6. Update each repo's local .env with the same three values.

Test plan

  • BWS prereqs done
  • Locally: bundle exec kamal secrets fetch --adapter bitwarden --from quantic-prod KAMAL_REGISTRY_PASSWORD returns the value
  • Locally: bundle exec kamal envify succeeds end-to-end
  • Merge → auto-deploy to prod runs green; container has GEMINI_API_KEY (verify by hitting /api/v1/radar/insights) and TELEGRAM_BOT_TOKEN (verify the Telegram link still works)
  • Push to beta → auto-deploy to beta runs green

Rollback

cp .kamal/secrets.1password.example .kamal/secrets
cp .kamal/secrets.beta.1password.example .kamal/secrets.beta
# Then revert the workflow change manually.

1P vault was never touched — secrets are still there.

Sister PRs

🤖 Generated with Claude Code

Preserve the working 1Password setup so future-you can swap back with a
single cp. The two new files are verbatim copies of .kamal/secrets and
.kamal/secrets.beta as of the last 1P-driven deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same set of secret keys; only the storage backend changes. The kamal
bitwarden adapter shells out to the `bw` CLI, authenticated via personal
API key (BW_CLIENTID + BW_CLIENTSECRET) and unlocked with BW_PASSWORD.

Prod fetches from a Bitwarden item named `quantic-prod`; beta from
`quantic-beta`. Each item holds the relevant secrets as custom fields.

Why consumer Bitwarden over Bitwarden Secrets Manager (BWS): BWS Free
caps at 3 projects per org, which would bite us as more services land.
Consumer has no item cap on the free tier.

This commit alone breaks deploy until the workflow + GitHub Actions
secrets land in the next commit, so don't deploy from this state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fleveque fleveque force-pushed the chore/bws-migration branch from bf2385a to 76f2ac9 Compare May 24, 2026 20:03
@fleveque fleveque changed the title Migrate Kamal secrets from 1Password to Bitwarden Secrets Manager Migrate Kamal secrets from 1Password to Bitwarden (consumer) May 24, 2026
@fleveque fleveque force-pushed the chore/bws-migration branch 2 times, most recently from e04fa4d to bddc907 Compare May 24, 2026 20:47
Replaces the 1Password CLI install step with `npm install -g @bitwarden/cli`,
and the `OP_*` env block with `BW_CLIENTID` + `BW_CLIENTSECRET` +
`BW_PASSWORD` pulled from repo-level GitHub Actions secrets.

env.sample and README updated to reflect the new bootstrap flow.
README also documents how to roll back to 1Password using the
preserved `.kamal/secrets.1password.example` snapshots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fleveque fleveque force-pushed the chore/bws-migration branch from bddc907 to d037c85 Compare May 24, 2026 20:50
@fleveque fleveque merged commit f3f17c9 into main May 24, 2026
5 checks passed
@fleveque fleveque deleted the chore/bws-migration branch May 24, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant