Installs into .claude/skills of the current project.
Are you the author of Doppler?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-doppler)
---
name: doppler
description: "Expert agent for Doppler SaaS secrets manager. Covers project/environment/config hierarchy, CLI integration, service tokens, EHR (Encrypted HTTP Relay), Kubernetes operator, native sync integrations (AWS, Vercel, GitHub), and audit logging. WHEN: \"Doppler\", \"Doppler CLI\", \"Doppler project\", \"Doppler service token\", \"Doppler sync\", \"Doppler Kubernetes\", \"Doppler environment\", \"doppler run\"."
license: MIT
---
# Doppler
This skill covers Doppler, the SaaS secrets management platform. It has deep knowledge of Doppler's hierarchy model, access controls, integrations, CLI tooling, and Kubernetes patterns.
## How to Approach Tasks
When you receive a request:
1. **Classify** the request:
- **Setup/onboarding** — Project/environment/config structure guidance
- **Application integration** — CLI, SDK, service token guidance
- **Kubernetes** — Operator and sync patterns
- **CI/CD** — GitHub Actions, GitLab, CircleCI integration
- **Cloud sync** — AWS, Azure, Vercel, Netlify integrations
- **Access control** — Roles, service tokens, project-level permissions
- **Audit** — Activity logs and monitoring guidance
2. **Identify integration context** — Language/framework (Node.js, Python, Go), deployment target (K8s, Lambda, EC2, Vercel), CI/CD system.
## Hierarchy Model
Doppler organizes secrets in a three-level hierarchy:
```
Workspace (organization)
└── Project (e.g., "backend-api", "frontend-app", "data-pipeline")
└── Config (environment + branch, e.g., "production", "staging", "dev/feature-x")
└── Secrets (KEY=VALUE pairs)
```
**Config inheritance**: Configs within a project can inherit from a root config. Overrides are defined at the more specific level:
```
project: backend-api
root config: BASE_URL=https://api.example.com, FEATURE_FLAG_X=false
production: inherits BASE_URL, FEATURE_FLAG_X=true, DB_URL=prod-db
staging: inherits BASE_URL, FEATURE_FLAG_X=false, DB_URL=staging-db
```
### Best Practice: Config Naming
Use the environment naming convention that matches your deployment pipeline:
```
production → production deployments
staging → pre-production validation
development → shared development environment
dev_personal → personal developer override configs (branch configs)
ci → CI/CD pipeline secrets
```
## CLI
### Installation and Setup
```bash
# Install Doppler CLI
# macOS
brew install dopplerhq/cli/doppler
# Linux
(curl -Ls --tlsv1.2 --proto "=https" --retry 3 https://cli.doppler.com/install.sh || wget -t 3 -qO- https://cli.doppler.com/install.sh) | sh
# Windows (scoop)
scoop bucket add doppler https://github.com/DopplerHQ/scoop-doppler.git
scoop install doppler
# Authenticate (interactive, opens browser)
doppler login
# Set project and config scope
doppler setup --project backend-api --config production
```
### Running Commands with Secrets Injected
```bash
# Inject secrets as environment variables and run command
doppler run -- node server.js
doppler run -- python app.py
doppler run -- npm start
# Run with specific project/config (overrides .doppler.yaml)
doppler run --project backend-api --config staging -- node server.js
# Print secrets as environment variable export statements
doppler secrets download --no-file --format env
# Download secrets to a .env file
doppler secrets download --format env --no-file > .env
# Download as JSON
doppler secrets download --format json > secrets.json
```
### Managing Secrets
```bash
# List all secrets in current config
doppler secrets
# Get a specific secret value
doppler secrets get DB_PASSWORD
# Set a secret
doppler secrets set DB_PASSWORD="new-password"
# Set multiple secrets from stdin (JSON)
echo '{"DB_PASSWORD":"s3cr3t","API_KEY":"abc123"}' | doppler secrets upload
# Delete a secret
doppler secrets delete DEPRECATED_KEY
# Compare secrets across configs
doppler secrets --config production
doppler secrets --config staging
```
## Service Tokens
Service tokens are non-expiring (or optionally expiring) credentials that grant read access to a specific config. Use for applications and CI/CD pipelines.
```bash
# Generate a service token
doppler configs tokens create --project backend-api --config production --name "k8s-deployment"
# Returns: dp.st.production.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Use service token in application
DOPPLER_TOKEN=dp.st.production.xxx doppler secrets download --no-file --format env
# Or set as environment variable
export DOPPLER_TOKEN=dp.st.production.xxx
doppler run -- node server.js
```
**Token types**:
- **Service token**: Read-only, scoped to a single config. For applications.
- **Personal token**: Read/write, scoped to user permissions. For developer tooling.
- **Service account token**: Tied to a service account (not a user). For CI/CD.
- **CLI token**: Interactive login token stored in `~/.doppler`.
## Kubernetes Integration
### Doppler Kubernetes Operator
The operator syncs Doppler secrets into Kubernetes Secrets and auto-rotates them:
```bash
# Install operator via Helm
helm repo add doppler https://helm.doppler.com
helm install doppler-operator doppler/doppler-kubernetes-operator \
--namespace doppler-operator-system \
--create-namespace
```
```yaml
# Create secret with Doppler service token
kubectl create secret generic doppler-token-secret \
--namespace doppler-operator-system \
--from-literal=serviceToken="dp.st.production.xxxxxxxxx"
---
# DopplerSecret resource
apiVersion: secrets.doppler.com/v1alpha1
kind: DopplerSecret
metadata:
name: myapp-secrets
namespace: my-namespace
spec:
tokenSecret:
name: doppler-token-secret
managedSecret:
name: myapp-k8s-secrets
namespace: my-namespace
type: Opaque
```
The operator syncs secrets from Doppler into the `myapp-k8s-secrets` Kubernetes Secret. Deployments that mount or reference this Secret get auto-restarted when it changes (via annotation).
```yaml
# Annotate deployment for auto-restart on secret change
apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
annotations:
secrets.doppler.com/reload: "true"
```
### CSI Driver Alternative
Use the Secrets Store CSI Driver with Doppler provider for direct volume mounting:
```bash
helm install doppler-csi-driver doppler/doppler-csi-driver \
--namespace kube-system
```
```yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: doppler-secrets
spec:
provider: doppler
parameters:
serviceToken: <base64-encoded-token>
config: production
project: backend-api
format: env
```
## CI/CD Integrations
### GitHub Actions
```yaml
# .github/workflows/deploy.yml
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Doppler CLI
uses: dopplerhq/cli-action@v3
- name: Deploy with Doppler secrets
run: doppler run -- ./deploy.sh
env:
DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }}
# DOPPLER_TOKEN is a service token stored in GitHub repo secrets
```
### Alternative: Fetch Secrets to GitHub Secrets
Use Doppler's native GitHub sync to push secrets directly to GitHub Actions secrets, eliminating the need for the DOPPLER_TOKEN in the workflow:
```
Doppler Integration → GitHub Actions Secrets sync
Doppler Config: backend-api/ci
→ GitHub repo secrets: DB_PASSWORD, API_KEY, etc.
(Synced automatically when Doppler secrets change)
```
## Native Sync Integrations
Doppler can push secrets to cloud-native stores and platforms:
| Integration | Sync Direction | Use When |
|---|---|---|
| AWS Secrets Manager | Doppler → AWS SM | Apps already use AWS SM SDK |
| AWS Parameter Store | Doppler → SSM | Apps use Parameter Store |
| AWS Lambda | Doppler → Lambda env vars | Serverless functions |
| Azure Key Vault | Doppler → AKV | Azure apps using AKV SDK |
| Vercel | Doppler → Vercel env vars | Next.js / Vercel deployments |
| Netlify | Doppler → Netlify env vars | Netlify deployments |
| GitHub Actions | Doppler → GitHub secrets | CI/CD workflows |
| Heroku | Doppler → Heroku config vars | Heroku apps |
Configure integrations in the Doppler dashboard under Integrations.
## EHR (Encrypted HTTP Relay)
Doppler's EHR is the security mechanism for the secret fetch API:
- All communication is TLS-encrypted (TLS 1.2+)
- Service tokens are never logged by Doppler in plaintext
- Doppler uses zero-knowledge architecture: secrets are encrypted at rest, decrypted only at delivery time
- SOC 2 Type II certified
## Access Control
### Roles (Workspace level)
| Role | Permissions |
|---|---|
| Owner | Full access including billing and deletion |
| Admin | Full access except billing and workspace deletion |
| Member | Access to assigned projects only |
| Viewer | Read-only access to assigned projects |
### Project-Level Access
Within a project, assign users/groups:
- **Admin**: Full project access, can manage configs and integrations
- **Collaborator**: Read/write secrets in assigned configs
- **Viewer**: Read-only in assigned configs
### SCIM / SSO
Doppler supports SCIM for automated user provisioning with Okta, Azure AD, and other IdPs. SSO via SAML 2.0.
## Audit Logs
All secret access and modifications are logged:
```
Audit log events:
SECRET_READ: who read which secret, when, from which token
SECRET_UPDATE: who changed a secret value
TOKEN_CREATED: new service token created
CONFIG_CLONED: config was duplicated
INTEGRATION_SYNCED: sync to external system completed
```
Access audit logs via Dashboard → Workplace → Audit Logs, or via API:
```bash
# Export audit logs via API (Enterprise)
curl -H "Authorization: Bearer $DOPPLER_TOKEN" \
"https://api.doppler.com/v3/logs?page=1&per_page=100"
```
## Common Patterns
### Twelve-Factor App Integration
```bash
# In production: use Doppler service token + doppler run
DOPPLER_TOKEN=dp.st.xxx doppler run -- node server.js
# In CI: set DOPPLER_TOKEN as a CI secret, no .env file needed
# In development: doppler login + doppler setup + doppler run
```
### Docker Integration
```dockerfile
# Option 1: Install Doppler CLI in image (for doppler run)
RUN curl -Ls --tlsv1.2 --proto "=https" --retry 3 https://cli.doppler.com/install.sh | sh
CMD ["doppler", "run", "--", "node", "server.js"]
# Option 2: Pass DOPPLER_TOKEN as runtime env var
# docker run -e DOPPLER_TOKEN=dp.st.xxx myimage
```
### Secret Reference vs. Secret Value
Doppler references (similar to AKV references) allow some integrations to reference secret names rather than values, resolving dynamically. Check specific integration docs for support.