Bitwarden Secrets Manager for Hermes — Full Setup Guide

Secrets

One bootstrap token replaces N plaintext API keys. Hermes pulls every credential from your Bitwarden vault at every startup — so your keys are never scattered across .env files and never forgotten.

What you’ll learn
Privacy / placeholder note: this guide is public. Values such as <user>, <YOUR_TELEGRAM_USER_ID>, <BOT_TOKEN>, <your-agentmail-inbox>, and <your-tailscale-host>.ts.net are placeholders standing in for the real values on your own machine — usernames, user/chat IDs, tokens, hostnames, and home paths differ on every install and have been removed for privacy. Replace each <placeholder> with the matching value for your system before running any command.
Contents
  1. Why use Bitwarden Secrets Manager?
  2. How it works (one token, N keys)
  3. Prerequisites
  4. Step 1 — Create a machine account, project & secrets (web app)
  5. Step 2 — Run the setup wizard (CLI)
  6. Step 3 — Verify it works
  7. Step 4 — Remove plaintext keys from .env (optional)
  8. Benefits recap
  9. Adding / rotating keys later
  10. Troubleshooting & failure modes

Why use Bitwarden Secrets Manager?

AI agents like Hermes need many API keys to do their job — an LLM provider (e.g. OpenRouter), messaging bots (Telegram, Discord, Signal), an email gateway, a workflow engine (n8n), a decision service (TypeSafe), phone messaging (Twilio), and more. The naive way is to paste them all into a ~/.hermes/.env file. That breeds two recurring problems:

Bitwarden Secrets Manager fixes both. One small bootstrap token replaces all of those keys, they live encrypted in a central vault, and they are injected into every new Hermes process automatically at startup.

How it works (one token, N keys)

The architecture is deliberately simple:

  1. You create a machine account in Bitwarden with read-only access to a project that holds your secrets.
  2. That machine account issues a single access token (BWS_ACCESS_TOKEN) — the only secret stored on your machine.
  3. At every Hermes startup, the CLI reads that token and calls bws secret list <project_id> to fetch the whole project.
  4. Each secret's Name becomes the environment variable name verbatim (e.g. a secret named OPENROUTER_API_KEY sets OPENROUTER_API_KEY), and its value is the key.
  5. Because Bitwarden is set as the source of truth (override_existing: true), vault values win over anything baked into .env.

Result: rotate any credential by changing it once in the Bitwarden web app, and the next Hermes start picks it up automatically. No editing files, no pasting secrets into chat, no "forgetting."

Which keys move? Typical Hermes secrets: OPENROUTER_API_KEY, DISCORD_BOT_TOKEN, TELEGRAM_BOT_TOKEN, N8N_API_KEY, TYPESAFE_API_KEY, PHOTON_PROJECT_ID, PHOTON_PROJECT_SECRET, ELEVENLABS_API_KEY, TWILIO_AUTH_TOKEN, SIGNAL_ACCOUNT, and any other env-var credentials Hermes reads. Plain non-secret config (base URLs, home channels) usually stays in .env as before.

Prerequisites

Step 1 — Create a machine account, project & secrets (web app)

Do this part in the browser at vault.bitwarden.com. (An agent cannot do it for you — it has no browser session with your vault login, and your password must never pass through chat.)

  1. Log in to the vault. Switch to Secrets Manager via the product switcher (top-left).
  2. Projects → New project → name it e.g. Hermes keys → Create. Copy the Project ID (UUID) from the project page — you need it for the CLI step.
  3. Secrets → New secret, for EACH credential:
    • Name = the exact env var name (e.g. OPENROUTER_API_KEY). The name must match the variable exactly — a typo silently loads under the wrong variable.
    • Value = the key value (paste from your ~/.hermes/.env).
    • Project = the project you created.
    • Save. Repeat for every key.
  4. Machine accounts → New machine account → name it e.g. My Hermes machine → Projects tab → grant Read access to the project.
  5. In the machine account, Access tokens → New access token: give it a name (e.g. hermes-1), set an expiry (or none) → Create. Copy the token string now — it is shown only once.
Never paste the token into chat. The next step prompts you for it with hidden input on your own terminal, so it never appears in a chat log. Also remember: BWS_ACCESS_TOKEN is high-value — anyone holding it reads every secret in the project. Keep it only in ~/.hermes/.env, never in config.yaml.

Step 2 — Run the setup wizard (CLI)

Run this yourself in a terminal. It is interactive and prompts for the access token with hidden input:

hermes secrets bitwarden setup

The wizard will: install bws if absent → prompt for the access token (hidden) → store it in ~/.hermes/.env as BWS_ACCESS_TOKEN → ask for the Bitwarden region (US Cloud = vault.bitwarden.com) → list the projects your machine account can see → pick the one (e.g. Hermes keys). Then it tests a fetch.

There is also a non-interactive equivalent (useful in automation — the token is passed via env, never typed in chat):

BWS_ACCESS_TOKEN="$BWS_ACCESS_TOKEN" hermes secrets bitwarden setup \
  --access-token "$BWS_ACCESS_TOKEN" \
  --server-url https://vault.bitwarden.com \
  --project-id 

Step 3 — Verify it works

hermes secrets bitwarden status      # config + binary version + token valid?
hermes secrets bitwarden sync        # dry-run: show what would be applied
hermes secrets bitwarden sync --apply # pull + export into current shell

On the first fresh Hermes start with secrets applied you'll see a one-line summary in stderr. Then restart Hermes (or start a new hermes invocation, gateway, or cron job) so the fetched secrets land in the process environment.

Sanity check: launch a pristine one-shot with an empty environment. If Hermes can make a real provider call using only a Bitwarden-sourced key, the whole chain works:
env -i HOME=$HOME PATH="$PATH" \
  HERMES_HOME=$HOME/.hermes \
  /path/to/venv/bin/hermes chat -q "Reply with exactly: BITWARDEN_KEY_OK"

Step 4 — Remove plaintext keys from .env (optional, recommended)

After verifying status is green and a restarted process picked up the keys, strip the migrated secrets from ~/.hermes/.env for a single source of truth. Keep the non-secret config entries. If you'd rather keep a plaintext fallback for offline safety, leave them — Bitwarden wins anyway thanks to override_existing: true.

Benefits recap

BenefitWhat it means day-to-day
Keys never "forgotten"Every fresh Hermes process pulls all secrets from the vault at startup — a key can't silently go missing from a local file.
One token replaces N keysOne small BWS_ACCESS_TOKEN instead of a dozen formats on disk.
Central, encrypted storageSecrets live in your Bitwarden vault, not scattered as plaintext in .env files, backups, or git history.
Instant rotationChange a value once in the web app; the next start picks it up. Revoke a leaked key in seconds.
No secrets in chatThe wizard's hidden-input prompt keeps BWS_ACCESS_TOKEN and all keys out of chat logs.
Never blocks startupIf Bitwarden is unreachable, Hermes logs a one-line warning and continues with whatever .env already had (a local cache covers offline boots).

Adding / rotating keys later

Config reference (~/.hermes/config.yaml)

secrets:
  bitwarden:
    enabled: true            # master switch
    access_token_env: BWS_ACCESS_TOKEN
    project_id: "<project-uuid>"   # set by wizard
    server_url: "https://vault.bitwarden.com"   # US; EU = vault.bitwarden.eu; empty = US default
    cache_ttl_seconds: 300
    encrypted_cache:
      enabled: false
      max_stale_seconds: 0
    override_existing: true  # Bitwarden wins over .env
    auto_install: true

Troubleshooting & failure modes

SymptomCauseFix
BWS_ACCESS_TOKEN is not setEnabled but token missing from .envre-run hermes secrets bitwarden setup
invalid_clientToken revoked/expired, machine deleted, or region mismatch (EU token hitting US endpoint)hermes secrets bitwarden token; check server_url
bws exited 1: invalid access tokenToken revoked/wronghermes secrets bitwarden token
bws timed outNetwork blocked to api.bitwarden.comcheck connectivity / proxy
bws binary not availableNo package manager + no binary on PATHhermes secrets bitwarden install
Key loads under wrong variableSecret Name doesn't exactly match the env var namerename the secret in the web app to the exact env var name
Good to know: bw (personal vault CLI) and bws (Secrets Manager CLI) are different tools. Hermes uses bws only. Also, Hermes refuses to let Bitwarden overwrite BWS_ACCESS_TOKEN itself — if you store it inside the project it is silently skipped, so don't bother.

Published by diyyourdata AI Automation · Diy Your Data · Melbourne
Canonical: this page

Bottom line
one access token in ~/.hermes/.env replaces every plaintext key; rotate anything in the vault and the next Hermes start picks it up.
📍 Location Tracking
We use your IP address (country/city only) for analytics. No personal data collected.