# Environment and secrets

> Set environment values for your build and your running app, choose where each one goes, and know when a change takes effect.

Source: https://docs.fortly.com/deploy/environment

Environment values are the API keys, passwords and configuration your project needs without writing them into its code. Fortly encrypts each value before storing it and never hands it back: the API and the console show names, scopes and dates, never values. You choose, per value, whether it goes to your build, your running app, or both.

## Set a value

**Console**

### Open the environment
Open your project, go to **Deployments**, and choose the **Environment** tab.

### Add a value
Under **Add a value**, enter the **Name** and the **Value**, and choose **Where it may be used**: **Runs only**, **Builds only**, or **Builds and runs**.

### Save it
The value is stored encrypted and cannot be shown again. It appears under **Set on this project** with its scope and the date it was set.

**API**

```bash
curl -X POST https://api.fortly.com/projects/my-app-ada/secrets \
  -H "Authorization: Bearer $FORTLY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "STRIPE_SECRET_KEY", "value": "sk_live_...", "scope": "runtime"}'
```

- `name` (string, required) — Capital letters, digits and underscores, 1 to 64 characters, not starting with a digit.
- `value` (string, required) — The value, up to 64 KB. An empty value is refused — delete the name instead.
- `scope` (string, optional) — `runtime`, `build` or `both`. Defaults to `runtime`.

The reply is `201` with `{"name": "STRIPE_SECRET_KEY", "scope": "runtime"}`. Setting a name that already exists replaces its value and its scope. Use the project's full API name, such as `my-app-ada` — see [Deploying your code](https://docs.fortly.com/deploy#deploy-an-archive). The full reference is in [Secrets API](https://docs.fortly.com/api/secrets).

## Choose where a value goes

| Scope | Console label | Given to | Use it for |
| --- | --- | --- | --- |
| `runtime` | Runs only | Your running app | Database passwords, payment keys, anything only your server reads |
| `build` | Builds only | Your build, not your running app | Values a framework bakes into its output at build time |
| `both` | Builds and runs | Both | A value the build embeds and the server also reads |

`runtime` is the default because it hands a value to the fewest places. A build runs your project's own install scripts, so keep a value out of it unless the build needs it.

> **Public configuration for a frontend:**
>
> Frameworks like Next.js read variables such as `NEXT_PUBLIC_API_URL` while they build and write them into the files they produce. Give those values the `build` or `both` scope. A value the build cannot see ends up missing from the site, which then fails in the visitor's browser rather than at deploy time.

A scope you spell wrong is refused rather than read as `runtime`: `"runtme" is not a secret scope; use one of runtime, build, both`.

## When a change takes effect

Setting or removing a value takes effect without a deploy for values your running app already reads: Fortly clears the project's cached responses, and the next request runs with the new set of values.

Two cases need a new deploy:

- **A value with the `build` or `both` scope.** It is read while the build runs, so output that is already built keeps the value it was built with. Deploy again to rebuild with the new one.
- **A new name for a server-rendered app or Node server.** A release built into a Worker receives the `runtime` and `both` values whose names existed when it was built. After adding a new name, deploy again so the new release picks it up. Changing or removing a value for an existing name does not need this.

A static site has no running server, so only its build-time values matter to it.

## List and remove values

```bash
curl https://api.fortly.com/projects/my-app-ada/secrets \
  -H "Authorization: Bearer $FORTLY_TOKEN"
```

Each entry in `secrets` has `name`, `created_at` and `scope`. There is no route that returns a value: if you lose one, set a new one.

```bash
curl -X DELETE https://api.fortly.com/projects/my-app-ada/secrets/STRIPE_SECRET_KEY \
  -H "Authorization: Bearer $FORTLY_TOKEN"
```

Removing answers `204`, or `404` with `no secret by that name`.

- `GET /projects/{name}/secrets` — Names, scopes and dates — never the values
- `POST /projects/{name}/secrets` — Set one, or replace it
- `DELETE /projects/{name}/secrets/{key}` — Remove one

## Names Fortly reserves

These names are reserved for the platform, and setting one is refused with `PORT is set by Fortly and cannot be replaced` (naming the one you tried):

| Group | Names |
| --- | --- |
| Process | `PORT`, `HOST`, `PATH` |
| Fortly | `FORTLY_API`, `FORTLY_TOKEN` |
| Database | `DATABASE_URL`, `DATABASE_TRANSACTION_URL`, `PGHOST`, `PGPORT`, `PGDATABASE`, `PGUSER`, `PGPASSWORD`, `PGSSLMODE` |

The database names are reserved so that no value of yours can stand in for the connection details the platform manages for your project's database. A name that only contains one of these, such as `MY_DATABASE_URL`, is yours to use.

Other names are refused when they break the naming rule: `a name cannot start with a digit`, or `a name can use capital letters, digits and underscores — for example DATABASE_URL`.

## How values are protected

- **Encrypted at rest** with AES-256-GCM. The key is held outside the database, so a copy of the database does not carry readable values.
- **Never returned.** No API route and no console page shows a value after it is set.
- **Given only where their scope says.** A build receives `build` and `both` values; a running app receives `runtime` and `both` values.
- **Masked in logs.** A value 8 characters or longer that appears in your project's log is replaced with `[redacted]`. Shorter values are not masked, because they cannot be told apart from ordinary words.

## Related

- [How builds work](https://docs.fortly.com/deploy/builds): What a build does with the values it receives.
- [Deploying your code](https://docs.fortly.com/deploy): Deploy again when a build-time value changes.
- [Secrets API](https://docs.fortly.com/api/secrets): Every secrets route, its parameters and its responses.
- [Logs and metrics](https://docs.fortly.com/deploy/logs): Where masked values would otherwise have appeared.
