1---
2title: Doppler
3description: Load a Doppler config into your Stack — log in with the browser on your machine, use a service token in CI.
4---
5
6[Doppler](https://www.doppler.com) organises secrets into projects,
7each with configs such as `dev`, `stg`, and `prd`. `Doppler.Secrets`
8downloads one config into the stack's
9[secret providers](/environments/secret-providers), without writing
10anything to `process.env` or to disk.
11
12```typescript
13import * as Doppler from "alchemy/Doppler";
14
15secrets: [
16 Doppler.Secrets(({ stage }) => ({
17 project: "my-app",
18 config: stage === "prod" ? "prd" : "dev",
19 })),
20],
21```
22
23Browser login and personal tokens are not scoped to a single config,
24so `project` and `config` are required with those. A
25[service token](https://docs.doppler.com/docs/service-tokens) is
26scoped to one config, so both may be omitted. Doppler's
27[branch configs](https://docs.doppler.com/docs/branch-configs) map
28neatly onto preview stages if `pr-42` should inherit from `dev`.
29
30## Connect your account
31
32Run `alchemy profile edit --add Doppler`. **Login** opens the Doppler
33dashboard; approve the request and the token is stored in your
34[profile](/environments/profiles). It shows up in Doppler as
35`Alchemy (<your hostname>)`, and
36`alchemy profile edit --remove Doppler` revokes it. **API token**
37takes a service or
38[personal token](https://docs.doppler.com/docs/personal-tokens) you
39already have. Non-interactively:
40
41```sh
42alchemy profile edit --add Doppler --method api-token --set token=env:DOPPLER_TOKEN
43```
44
45## In CI
46
47Profiles are never consulted in CI; the environment decides. The
48simplest is a service token in `DOPPLER_TOKEN`:
49
50```yaml
51- run: bun alchemy deploy --stage prod --yes
52 env:
53 DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN }}
54```
55
56On Doppler's Team and Enterprise plans, use OIDC to avoid storing a
57long-lived Doppler token. Create a
58[service account identity](https://docs.doppler.com/docs/service-account-identities)
59that trusts your platform's OIDC issuer and set `DOPPLER_IDENTITY_ID`;
60Alchemy exchanges the platform's own identity token for a short-lived
61Doppler token on every run:
62
63```yaml
64jobs:
65 deploy:
66 permissions:
67 id-token: write # lets the job request an OIDC token
68 contents: read
69 steps:
70 - run: bun alchemy deploy --stage prod --yes
71 env:
72 DOPPLER_IDENTITY_ID: ${{ vars.DOPPLER_IDENTITY_ID }}
73```
74
75Alchemy detects GitHub Actions, Vercel, and supported
76Google Cloud runtimes. Each platform must be configured to issue a token
77whose issuer, subject, and audience match the Doppler identity's trust policy.
78Use your job's actual subject claim when configuring that policy; it can
79vary with the repository, branch, environment, and organization settings.
80
81For GitLab, name the token in the job's
82[`id_tokens`](https://docs.gitlab.com/ci/secrets/id_token_authentication/)
83block `DOPPLER_OIDC_TOKEN` and set its `aud` to the audience trusted by
84Doppler. `SIGSTORE_ID_TOKEN` is also detected when `GITLAB_CI` is set.
85On other platforms, `DOPPLER_OIDC_TOKEN` accepts an explicitly supplied token.
86
87`DOPPLER_OIDC_AUDIENCE` sets the requested audience on GitHub Actions
88and Google Cloud. It is required for Google's
89[metadata identity endpoint](https://docs.cloud.google.com/docs/authentication/get-id-token).
90It does not change the audience of tokens already supplied by Vercel,
91GitLab, or `DOPPLER_OIDC_TOKEN`.
92
93`DOPPLER_TOKEN` wins over `DOPPLER_IDENTITY_ID`, and either wins over
94a profile, so a teammate can deploy with a token they were handed.
95`alchemy provider check-env` lists these variables.
96
97## Where next
98
99- [Secret providers](/environments/secret-providers) — ordering, mixing sources, and per-stage callbacks.
100- [Profiles](/environments/profiles) — where the login lives.
101- [Doppler docs](https://docs.doppler.com) — projects, configs, and access control.