# ADR 035: Doppler

- HTML version: https://robbiepalmer.me/projects/personal-site/adrs/035-doppler
- Project: Personal Site (https://robbiepalmer.me/projects/personal-site.md)
- Status: Proposed
- Date: 2025-12-31

# Context

As the number of external service integrations grows beyond the current minimal set ([Cloudflare Pages](/projects/personal-site/adrs/011-cloudflare-pages)/[Images](/projects/personal-site/adrs/029-cloudflare-images), [Terraform Cloud](/projects/personal-site/adrs/017-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)](/projects/personal-site/adrs/018-github-secrets) 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](https://www.doppler.com/) 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:

* **[Less Is More](/projects?tab=philosophy#less-is-more)**: While adding a platform, it consolidates secret management that would otherwise sprawl across multiple dashboards
* **[Short Feedback Loops](/projects?tab=philosophy#short-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](https://www.vaultproject.io/)

* **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](https://aws.amazon.com/secrets-manager/) / [GCP Secret Manager](https://cloud.google.com/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](https://infisical.com/)

* **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](https://developer.1password.com/docs/service-accounts/)

* **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—[Less Is More](/projects?tab=philosophy#less-is-more)
* **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 [Less Is More](/projects?tab=philosophy#less-is-more)—YAGNI.

---

Markdown index of this site: https://robbiepalmer.me/llms.txt
