Setting Up Doppler for Local Development
Get a project running with Doppler-injected secrets in four commands:
Bash# 1. Install CLI (macOS example) brew install dopplerhq/cli/doppler # 2. Authenticate (once per machine) doppler login # 3. Scope this directory to a Doppler project/config doppler setup # 4. Run your app with secrets injected as env vars doppler run -- npm start
No .env file required. Secrets never touch disk.
Progress:
- Install Doppler CLI for the target OS
- Authenticate with
doppler login - Run
doppler setupin project root (or commit adoppler.yaml) - Wrap the app's start command with
doppler run -- - Add a
doppler-runscript topackage.json(or IDE equivalent) - For containers, pass a short-lived
DOPPLER_TOKENat runtime - Decide if signal forwarding and/or auto-restart-on-change are needed
1. Install & authenticate
Install the CLI, then doppler login once per workstation. This opens a browser for OAuth — no long-lived credentials stored in the repo.
2. Scope the project
Run doppler setup inside each project directory to bind it to a Doppler project + config (e.g. dev_personal). Optionally commit a doppler.yaml:
YAMLsetup: - project: example config: dev_personal
3. Inject secrets at runtime
Replace direct start commands with doppler run -- <command>. Secrets become env vars only for the lifetime of that process.
4. Wire into package.json
Add a dedicated script rather than modifying start directly, so the command still works without Doppler if needed:
JSON{ "scripts": { "start": "node ./src/server", "doppler-run": "doppler run --forward-signals -- npm start" } }
5. Handle containers Docker and Docker Compose don't get CLI auth context automatically — pass a token explicitly:
Bashdocker run --rm -it \ -e DOPPLER_TOKEN="$(doppler configs tokens create docker --max-age 1m --plain)" \ your-image
6. Choose runtime flags deliberately
--forward-signals: propagates SIGTERM/SIGINT to the child process for graceful shutdown. Always safe to include; needed explicitly when output isn't a TTY.--watch: restarts the process automatically when secrets change (Team/Enterprise only). Use in long-running local dev servers where live secret updates matter; skip for one-off scripts or CI.- They're independent and can be combined.
Example 1: Basic Node app
Input: "I have npm start running node ./src/server, want Doppler-managed secrets."
Output:
JSON{ "scripts": { "start": "node ./src/server", "doppler-run": "doppler run --forward-signals -- npm start" } }
Run with npm run doppler-run.
Example 2: Vite app
Input: "Vite dev server needs secrets as import.meta.env vars."
Output: No script wrapper needed — invoke directly:
Bashdoppler run -- vite
Example 3: Docker Compose Input: "Need secrets available to a service in docker-compose.yml without baking them into the image." Output:
BashDOPPLER_TOKEN="$(doppler configure get token --plain)" \ docker-compose -f docker-compose.yml up
Compose service reads DOPPLER_TOKEN from the environment and Doppler's Docker integration resolves secrets at container start.
Example 4: Choosing between flags
Input: "My local dev server hangs on Ctrl+C, and I also want it to pick up new secrets without manual restarts."
Output: Use both — doppler run --forward-signals --watch -- npm run dev (requires Team/Enterprise plan for --watch).
- Prefer a dedicated
doppler-runscript over overwritingstart/dev, so contributors without Doppler access can still run the app manually. - Use per-developer configs (e.g.
dev_personal) so individual overrides don't leak into shareddevconfig. - Generate short-lived, scoped tokens (
--max-age) for containers and CI instead of reusing a personal CLI token. - Commit
doppler.yamlfor project/config scoping sodoppler setupis reproducible across the team. - Always include
--forward-signalsin containerized or process-managed contexts to avoid orphaned processes on shutdown.
- Assuming
--watchworks on all plans — it requires Team/Enterprise; free/personal plans will fail silently or error. - Forgetting that Docker containers don't inherit the host's
doppler loginsession — aDOPPLER_TOKENmust be passed explicitly. - Wrapping
startdirectly withdoppler runand breaking local workflows for teammates not yet onboarded to Doppler. - Using long-lived personal tokens in CI/Docker instead of scoped, expiring service tokens.
- Confusing
--forward-signals(signal propagation) with--watch(secret-change auto-restart) — they solve unrelated problems and are often needed together, not as alternatives.