DEV Community

Alex Spinov
Alex Spinov

Posted on

Doppler Has a Free API — Here's How to Manage Secrets Across All Your Environments

A team lead told me: 'We had 47 .env files across 12 services. When we rotated the database password, we missed 3 services. Production was down for 2 hours.' Doppler solved this — one source of truth for all secrets.

What Doppler Offers for Free

Doppler free tier:

  • 5 team members
  • Unlimited projects and secrets
  • All environments — dev, staging, production
  • CLI and REST API
  • Integrations — Vercel, Netlify, AWS, GCP, GitHub Actions, Docker
  • Secret references — share secrets between projects
  • Audit logs — who accessed what, when
  • Automatic restarts — when secrets change

Quick Start

# Install CLI
brew install dopplerhq/cli/doppler

# Login
doppler login

# Setup in your project
doppler setup

# Run your app with secrets injected
doppler run -- node server.js
# DATABASE_URL, API_KEY, etc. are now environment variables
Enter fullscreen mode Exit fullscreen mode

REST API

# List secrets
curl 'https://api.doppler.com/v3/configs/config/secrets' \
  -u 'dp.st.YOUR_SERVICE_TOKEN:' \
  --data-urlencode 'project=myapp' \
  --data-urlencode 'config=prd'

# Get a specific secret
curl 'https://api.doppler.com/v3/configs/config/secret' \
  -u 'dp.st.YOUR_TOKEN:' \
  --data-urlencode 'project=myapp' \
  --data-urlencode 'config=prd' \
  --data-urlencode 'name=DATABASE_URL'

# Set a secret
curl -X POST 'https://api.doppler.com/v3/configs/config/secrets' \
  -u 'dp.st.YOUR_TOKEN:' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "myapp",
    "config": "prd",
    "secrets": {
      "DATABASE_URL": "postgres://user:pass@host:5432/db",
      "REDIS_URL": "redis://host:6379"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Node.js SDK

// With Doppler CLI — secrets are env vars, no code change needed
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
// That's it. Doppler injects them via `doppler run`.

// Or use the REST API for dynamic secret fetching
async function getSecret(name) {
  const res = await fetch(
    `https://api.doppler.com/v3/configs/config/secret?project=myapp&config=prd&name=${name}`,
    { headers: { 'Authorization': `Bearer dp.st.${process.env.DOPPLER_TOKEN}` } }
  );
  const { value } = await res.json();
  return value.raw;
}
Enter fullscreen mode Exit fullscreen mode

Docker Integration

# Install Doppler CLI in Docker
RUN apt-get update && apt-get install -y curl gnupg && \
    curl -sLf --retry 3 --tlsv1.2 --proto "=https" 'https://packages.doppler.com/public/cli/gpg.DE2A7741A397C129.key' | gpg --dearmor -o /usr/share/keyrings/doppler-archive-keyring.gpg && \
    echo "deb [signed-by=/usr/share/keyrings/doppler-archive-keyring.gpg] https://packages.doppler.com/public/cli/deb/debian any-version main" > /etc/apt/sources.list.d/doppler-cli.list && \
    apt-get update && apt-get install -y doppler

CMD ["doppler", "run", "--", "node", "server.js"]
Enter fullscreen mode Exit fullscreen mode

GitHub Actions

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dopplerhq/secrets-fetch-action@v1
        id: secrets
        with:
          doppler-token: ${{ secrets.DOPPLER_TOKEN }}
          doppler-project: myapp
          doppler-config: prd
      - run: npm run deploy
        env:
          DATABASE_URL: ${{ steps.secrets.outputs.DATABASE_URL }}
Enter fullscreen mode Exit fullscreen mode

Secret References (Share Between Projects)

# In project 'shared', config 'prd':
# DATABASE_URL = postgres://...

# In project 'api', config 'prd':
# DATABASE_URL = ${shared.prd.DATABASE_URL}
# One source of truth — change it once, propagates everywhere
Enter fullscreen mode Exit fullscreen mode

Need secure web scraping? Check out my web scraping actors on Apify — managed and secure data collection.

Need help with secrets management? Email me at spinov001@gmail.com.

Top comments (0)