Skip to content

ADR-0010: Secrets handling

  • Status: Accepted
  • Date: 2026-07-25
  • Deciders: El

Context

Client-breaching secrets must never sit in plaintext; per-client OAuth tokens have a different lifecycle from static infra secrets.

Decision

Three tiers: secrets (Ansible Vault, encrypted, injected as environment variables at runtime, never plaintext-committed); infra config (per-tenant .env, templated by Ansible — non-secret config may travel alongside the vault-encrypted file, but anything sensitive stays in the encrypted file); business config (registry, editable via the Console without redeploy). Per-client OAuth tokens are obtained at runtime through a consent flow and stored encrypted in n8n's own database, protected by an n8n encryption key that is itself a Vault-managed secret. The vault key is held in the founders' password manager and supplied at deploy time. Ansible Vault is chosen now (one tool, simplest); upgrade to SOPS or a secrets manager if needs grow.

Consequences

No plaintext secrets on the box or in the repo; a single, simple workflow; OAuth tokens correctly separated (Vault cannot manage dynamically-refreshing tokens); losing the vault key locks out all secrets — hence password-manager storage plus a vault backup.

Alternatives considered

  • Business config or secrets in plaintext env — rejected.
  • SOPS or a secrets manager now — deferred: more setup than needed at current scale.