Projects/Personal Site/Architecture Decisions

ADR 035: Doppler

Context

As the number of external service integrations grows beyond the current minimal set (Cloudflare Pages/Images, Terraform Cloud), secret management complexity increases proportionally. Each integration requires API keys, and following the principle of least privilege means each subsystem should have appropriately scoped credentials rather than a single god-mode token.

Currently, GitHub Secrets (ADR 018) handles secret management well for CI/CD pipelines. However, as integrations expand, several challenges emerge:

  1. Secret Sprawl: Managing dozens of scoped API keys across multiple environments becomes cumbersome in GitHub's UI
  2. Local Development: Developers need access to secrets locally without copying them into .env files (which risk accidental commits)
  3. Secret Rotation: Updating a rotated credential requires manual updates across multiple GitHub repositories/environments
  4. Audit Trail: Limited visibility into what secrets were changed and when
  5. Cross-Platform Sync: Secrets may need to be shared across CI/CD systems, local development, and cloud functions

Doppler is a specialized secret management platform designed for developers, offering centralized secret storage with excellent DX.

Decision

I propose using Doppler for centralized secret management, while maintaining GitHub Secrets for the "Secret Zero" problem.

Implementation Strategy

  1. Doppler as Source of Truth: All application secrets (API keys, database credentials, etc.) are stored in Doppler with appropriate environment scoping (development, staging, production)
  2. GitHub Secrets for Bootstrap: A single DOPPLER_TOKEN is stored in GitHub Secrets to authenticate GitHub Actions to Doppler
  3. Scoped Access: Within Doppler, create separate service tokens for different subsections of the system (e.g., separate tokens for Cloudflare Workers vs. Pages vs. Images) following the principle of least privilege
  4. Local Development: Use the Doppler CLI to inject secrets into local development sessions without storing them on disk

This approach aligns with:

  • Minimize Platforms: While adding a platform, it consolidates secret management that would otherwise sprawl across multiple dashboards
  • Fast Feedback Loops: Standardizes how sensitive configuration is handled across all environments, preventing credential management from becoming a friction point that slows down development or integration testing

The "Secret Zero" Problem

The Secret Zero Problem (also called the "Bootstrap Secret Problem") is the fundamental challenge that you need a secret to access your secrets vault. Doppler doesn't eliminate this problem—it shifts it:

  • GitHub Actions needs a DOPPLER_TOKEN to authenticate to Doppler
  • This bootstrap token must be stored somewhere (GitHub Secrets)
  • If GitHub is compromised, the attacker gains access to Doppler

This is why Doppler complements GitHub Secrets rather than fully replacing it. GitHub's native integration provides the trust anchor, while Doppler handles the complexity of managing dozens of application secrets.

Alternatives Considered

GitHub Secrets (Current Approach)

  • Pros: Native platform integration, solves Secret Zero by being the identity provider itself, supports OIDC for keyless authentication
  • Cons: Limited visibility once saved, poor UX for managing many secrets, no local development story, manual rotation process
  • Decision: Keep for Secret Zero, use alongside Doppler

HashiCorp Vault

  • Pros: Enterprise-grade, extremely powerful policy engine, supports dynamic secrets
  • Cons: Requires dedicated infrastructure, suffers from the same Secret Zero problem, massive operational overhead for a solo developer
  • Decision: Rejected due to operational complexity

AWS Secrets Manager / GCP Secret Manager

  • Pros: Native cloud integration, good security model
  • Cons: Requires committing to a Cloud Service Provider, introduces massive overhead (IAM, billing, org structure) just to store strings, conflicts with Minimize Platforms
  • Decision: Rejected to avoid cloud lock-in for a cross-cutting concern

Infisical

  • Pros: Open-source Doppler alternative, can self-host
  • Cons: Self-hosting adds operational burden, smaller community/ecosystem than Doppler
  • Decision: Rejected in favor of managed solution (Doppler's free tier eliminates cost concern)

1Password Secrets Automation

  • Pros: Integrates with existing 1Password subscription, good developer experience
  • Cons: Primarily designed for human-to-app secrets rather than app-to-app, less specialized for CI/CD workflows than Doppler
  • Decision: Rejected in favor of purpose-built developer tool

Consequences

Positive

  • Scalability: Easily manage hundreds of secrets across multiple environments without GitHub UI limitations
  • Developer Experience: Doppler CLI provides seamless local development without .env file risks
  • Secret Rotation: Update a secret in one place, it propagates everywhere (CI/CD, local, cloud functions)
  • Audit Trail: Comprehensive logging of secret access and modifications
  • Principle of Least Privilege: Easy to create scoped service tokens for different subsections (e.g., different Cloudflare API keys for Workers vs. Pages vs. Images)
  • Free for Solo Dev: Doppler's free tier is sufficient for individual developers
  • Reduced Risk: Secrets are never written to disk in plain text during local development

Negative

  • Platform Dependency: Adds another platform to manage, contradicting Minimize Platforms
  • Secret Zero Persists: Still requires DOPPLER_TOKEN in GitHub Secrets, so we haven't eliminated the bootstrap problem
  • Vendor Lock-in: Migrating away from Doppler requires rewriting secret injection across all pipelines
  • Internet Dependency: Local development requires network access to Doppler (though CLI supports caching)
  • Premature Optimization: Currently only have 2-3 integrations, so the complexity may not yet justify the additional platform

When This Becomes Necessary

This transition should be considered when:

  • Secret Rotation Pain: Manually rotating secrets becomes a frequent, painful task
  • Team Growth: Multiple developers need synchronized access to secrets
  • Multi-Environment Complexity: Running staging/preview environments with different secret scopes

Until then, maintaining the status quo (GitHub Secrets only) may be the better adherence to Lean & Agile (YAGNI).