| 1 | --- |
| 2 | title: Profiles |
| 3 | description: Use profiles to select cloud accounts and credentials for each environment. |
| 4 | --- |
| 5 | |
| 6 | A **profile** is a named bundle of provider authentication settings. |
| 7 | The non-secret manifest lives in `~/.alchemy/profiles.json`; secret |
| 8 | material lives separately under `~/.alchemy/credentials/<profile>/`. |
| 9 | Profiles let you: |
| 10 | |
| 11 | - Keep work and personal accounts separate |
| 12 | - Use a different IAM role for `prod` vs `dev` |
| 13 | - Rotate or refresh tokens without losing other configurations |
| 14 | |
| 15 | Profiles are independent from [Stages](/environments/stages). A stage |
| 16 | controls **what** is deployed; a profile controls **how alchemy |
| 17 | authenticates** to deploy it. |
| 18 | |
| 19 | ## Profile selection |
| 20 | |
| 21 | Alchemy selects a profile in this order: |
| 22 | |
| 23 | 1. The command's `--profile <name>` option |
| 24 | 2. `$ALCHEMY_PROFILE` from configuration: an explicit `--env-file` first, |
| 25 | then the process environment, with `.env` as a fallback when no file is specified |
| 26 | 3. The built-in `default` profile |
| 27 | |
| 28 | Stacks that explicitly declare [secret providers](/environments/secret-providers) |
| 29 | pin `ALCHEMY_PROFILE` to `--profile` or the process environment, so a secrets |
| 30 | provider cannot redirect credential selection. Stacks that omit `secrets` |
| 31 | retain the existing selection above, including injected configuration. |
| 32 | |
| 33 | This is the same model as the AWS CLI: a profile named `default` always |
| 34 | exists, cannot be renamed or deleted, and is what every command uses unless |
| 35 | you name another profile explicitly. There is no stored "default selection" |
| 36 | to switch — to use a different profile, pass `--profile` or set |
| 37 | `ALCHEMY_PROFILE`. |
| 38 | |
| 39 | ```sh |
| 40 | alchemy profile edit |
| 41 | # connect accounts to the `default` profile |
| 42 | |
| 43 | alchemy profile create work |
| 44 | alchemy profile edit --profile work |
| 45 | alchemy deploy --profile work |
| 46 | # uses profile `work`; plain `alchemy deploy` uses `default` |
| 47 | ``` |
| 48 | |
| 49 | ## How credentials get there |
| 50 | |
| 51 | Run `alchemy profile edit`, choose providers to add, reconfigure, or remove, |
| 52 | then complete each provider's login flow. |
| 53 | |
| 54 | To re-run that flow at any time: |
| 55 | |
| 56 | ```sh |
| 57 | # Add, re-configure, or remove accounts in the current profile |
| 58 | alchemy profile edit |
| 59 | |
| 60 | # Re-configure one account directly |
| 61 | alchemy profile edit --profile work --reconfigure Cloudflare |
| 62 | |
| 63 | # Log into a separate profile |
| 64 | alchemy profile create prod |
| 65 | alchemy profile edit --profile prod |
| 66 | ``` |
| 67 | |
| 68 | Refreshing credentials is separate from reconfiguration. Refresh preserves the |
| 69 | selected authentication method, account, and scopes: |
| 70 | |
| 71 | ```sh |
| 72 | # Refresh every connected provider |
| 73 | alchemy profile refresh |
| 74 | |
| 75 | # Refresh only AWS SSO |
| 76 | alchemy profile refresh --profile work --provider AWS |
| 77 | ``` |
| 78 | |
| 79 | Alchemy refreshes supported credentials lazily. If interaction is required, |
| 80 | the command tells you which `alchemy profile refresh` command to run. |
| 81 | |
| 82 | Profile commands include Alchemy's built-in providers even outside a project. |
| 83 | They also import `alchemy.run.ts`, when present, to discover custom providers. |
| 84 | Use `--config <path>` for another entrypoint. A missing conventional |
| 85 | `alchemy.run.ts` is ignored, but errors in an existing entrypoint or an explicit |
| 86 | custom path fail the command instead of hiding its providers. Each |
| 87 | provider's prompts and credential resolution are implemented by its |
| 88 | [Auth Provider](/environments/auth-providers). |
| 89 | |
| 90 | ## Inspecting a profile |
| 91 | |
| 92 | Use `alchemy profile show` to see what's stored (credentials are |
| 93 | redacted): |
| 94 | |
| 95 | ```sh |
| 96 | alchemy profile show |
| 97 | alchemy profile show --profile prod |
| 98 | ``` |
| 99 | |
| 100 | Sample output: |
| 101 | |
| 102 | ```text |
| 103 | Profile: work |
| 104 | |
| 105 | ── AWS ── |
| 106 | accessKeyId: ASIA**** |
| 107 | secretAccessKey: Pj5T**** |
| 108 | region: us-west-2 |
| 109 | source: sso - company |
| 110 | |
| 111 | ── Cloudflare ── |
| 112 | accessToken: Xl06**** |
| 113 | expires: in 59m 58s 999ms |
| 114 | accountId: 123456789... |
| 115 | source: oauth |
| 116 | ``` |
| 117 | |
| 118 | ## Switching profiles |
| 119 | |
| 120 | The `default` profile is your normal local choice. Use `--profile` for one |
| 121 | command, or `ALCHEMY_PROFILE` for a shell or automation environment: |
| 122 | |
| 123 | ```sh |
| 124 | alchemy profile current |
| 125 | |
| 126 | alchemy deploy --stage prod --profile prod |
| 127 | alchemy destroy --stage pr-42 --profile work |
| 128 | |
| 129 | export ALCHEMY_PROFILE=work |
| 130 | alchemy deploy |
| 131 | ``` |
| 132 | |
| 133 | Rename a profile without disconnecting its accounts (the built-in `default` |
| 134 | profile cannot be renamed): |
| 135 | |
| 136 | ```sh |
| 137 | alchemy profile rename work company |
| 138 | ``` |
| 139 | |
| 140 | This moves the profile's credential directory. It does not rewrite an |
| 141 | `ALCHEMY_PROFILE` environment variable. |
| 142 | |
| 143 | ### Environment variables outside CI |
| 144 | |
| 145 | Provider credentials in the environment always win. When every required |
| 146 | variable in a provider's contract is set — in the process environment, a |
| 147 | `.env` file, or `--env-file` — alchemy resolves that provider from the |
| 148 | variables and never consults the profile, whether or not `--profile` or |
| 149 | `ALCHEMY_PROFILE` selected one. It logs which variables it used: |
| 150 | |
| 151 | ```text |
| 152 | Cloudflare: using environment variables (CLOUDFLARE_API_TOKEN, |
| 153 | CLOUDFLARE_ACCOUNT_ID) instead of the profile. |
| 154 | ``` |
| 155 | |
| 156 | The decision is per provider, so mixing is fine: a Cloudflare token in |
| 157 | `.env` overrides only Cloudflare, while AWS, Neon, or any other provider in |
| 158 | the same run still resolves from the profile. Unset the variables to use the |
| 159 | profile's stored credentials for that provider too. A partial set (a required |
| 160 | variable missing) is ignored and the profile applies. |
| 161 | |
| 162 | ### CI |
| 163 | |
| 164 | CI does not use profiles. When `CI=true`, provider credentials are resolved |
| 165 | directly from environment variables and nothing is read from or written to |
| 166 | `~/.alchemy`. GitHub Actions sets `CI=true` automatically: |
| 167 | |
| 168 | ```yaml |
| 169 | - run: bun alchemy deploy --stage prod --yes |
| 170 | env: |
| 171 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} |
| 172 | CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} |
| 173 | ``` |
| 174 | |
| 175 | ### CI environment variables by provider |
| 176 | |
| 177 | | Provider | Required credentials | Optional configuration | |
| 178 | | --- | --- | --- | |
| 179 | | AWS | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_REGION` or `AWS_DEFAULT_REGION` | `AWS_SESSION_TOKEN`; `AWS_ACCOUNT_ID` avoids an STS `GetCallerIdentity` lookup | |
| 180 | | Cloudflare | `CLOUDFLARE_ACCOUNT_ID` and either `CLOUDFLARE_API_TOKEN`, or `CLOUDFLARE_API_KEY` with `CLOUDFLARE_EMAIL`/`CLOUDFLARE_ACCOUNT_EMAIL` | None | |
| 181 | | GitHub | `GITHUB_ACCESS_TOKEN` or `GITHUB_TOKEN`; enterprise hosts may instead use `GH_ENTERPRISE_TOKEN` or `GITHUB_ENTERPRISE_TOKEN` | `GITHUB_BASE_URL`, `GITHUB_API_URL`, or `GH_HOST` selects a GitHub Enterprise host | |
| 182 | | Neon | `NEON_API_KEY` | None | |
| 183 | | PlanetScale | `PLANETSCALE_API_TOKEN_ID`, `PLANETSCALE_API_TOKEN`, `PLANETSCALE_ORGANIZATION` | `PLANETSCALE_API_BASE_URL` | |
| 184 | | Prisma | `PRISMA_SERVICE_TOKEN` or `PRISMA_API_TOKEN` | `PRISMA_API_URL` or `PRISMA_MANAGEMENT_API_URL` | |
| 185 | | Axiom | `AXIOM_TOKEN` or `AXIOM_API_KEY` | `AXIOM_ORG_ID` (required when the token is a personal access token), `AXIOM_URL` for self-hosted or regional deployments | |
| 186 | | Fly | `FLY_API_TOKEN` | `FLY_API_HOSTNAME` overrides the Machines API root | |
| 187 | | Hetzner | `HCLOUD_TOKEN` | `HCLOUD_ENDPOINT` overrides the API base URL | |
| 188 | | Railway | `RAILWAY_API_TOKEN` (account or workspace token) | `RAILWAY_API_URL` overrides the GraphQL host | |
| 189 | | Doppler | `DOPPLER_TOKEN`, or `DOPPLER_IDENTITY_ID` to log in with the platform's OIDC token | `DOPPLER_OIDC_TOKEN`, `DOPPLER_OIDC_AUDIENCE` — see [Doppler](/environments/doppler) | |
| 190 | | Infisical | `INFISICAL_TOKEN`, or `INFISICAL_IDENTITY_ID` to log in with the platform's OIDC token | `INFISICAL_OIDC_TOKEN`, `INFISICAL_OIDC_AUDIENCE`, `INFISICAL_API_URL` — see [Infisical](/environments/infisical) | |
| 191 | |
| 192 | These variables are a CI credential source, not a profile authentication |
| 193 | method. They are never persisted into `profiles.json` or the credentials |
| 194 | directory. Each provider declares machine-readable `environment` metadata for |
| 195 | the variables its CI resolver consumes. See |
| 196 | [Custom Auth Providers](/environments/custom-auth-provider). |
| 197 | |
| 198 | ## Where profiles live |
| 199 | |
| 200 | Profile settings live in `~/.alchemy/profiles.json`. Credentials live in |
| 201 | permission-restricted files under `~/.alchemy/credentials/<profile>/`. |
| 202 | |
| 203 | Set `ALCHEMY_HOME` to relocate profile data. |
| 204 | |
| 205 | Profile names are portable filesystem-safe identifiers: they must start |
| 206 | with a letter or number, may contain letters, numbers, `.`, `_`, and |
| 207 | `-`, and may be at most 64 characters. |
| 208 | |
| 209 | Use `alchemy profile edit` instead of editing the manifest manually. |
| 210 | |
| 211 | ## Where next |
| 212 | |
| 213 | - [Auth Providers](/environments/auth-providers) explains lazy credential resolution and refresh. |
| 214 | - [Stages](/environments/stages) — environment isolation; profiles pick the credentials, stages pick the instance. |
| 215 | - [Secrets & Config](/environments/secrets) — bind env vars and secrets onto your deploy targets. |
| 216 | - [CI](/environments/ci) explains deployment with environment credentials and no local profile state. |
| 217 | - [CLI](/cli) lists every `profile` subcommand and `--profile` flag. |