← knowledge.oriz.in

Env pattern — .env is single source, MCPs read system env vars

decision decisionenvmcpsecretssopsauth

.env single source, MCPs read system env

Decision

.env is the sole authoritative store of every secret consumed by MCP servers and agents. .env.enc (sops+age) is the committed encrypted form. Windows Scheduled Task exports every key to user-scope env at logon + daily 09:00. Every MCP config references secrets via ${env:VAR_NAME} only.

Why

Six problems this solves at once:

  1. No secret duplication — one .env.enc, one export flow, N MCPs read from same env.
  2. No per-agent auth-file sprawl — CC's settings.local.json, OpenCode's auth.json, Kilo's SecretStorage all read from same env vars.
  3. Portable across machines — clone workspace, import age key from Bitwarden, run bootstrap → all secrets flow.
  4. Rotation friendly — update .env.enc, commit, push → other machines pull, next daily task picks up.
  5. Fleet-agnostic — adding a new agent adds a new MCP config that references ${env:VAR} — no new secret-management code.
  6. CI-friendly — GHA sets same env vars from repo secrets; workflows unchanged when secrets rotate.

What NOT this decision covers

Alternatives rejected

Alternative Why not
Doppler (single-source secrets service) Card-on-file required for team tier past 3 users. Free tier fine for solo but limits growth.
Bitwarden CLI direct-lookup at MCP launch Latency (login roundtrip) + Bitwarden session unlock UX friction on every MCP restart.
Per-agent auth files, gitignored Duplication; every new agent adds a new secret-management surface.
Committed .env (public repos!) Never.
.env in private submodule Reintroduces private-repo complexity + card cost tradeoffs. .env.enc in public workspace is equivalent security with zero cost.

Scripts

Related