ConfigurationEnvironment variables and secrets

Secrets and environment variables

A secret is a named value, such as a database password, stored in one environment and injected into deploys as an environment variable. Values are write-only: once saved, neither the dashboard nor the API will show them again.

How secrets are scoped#

Secrets belong to an environment. There are no organisation-wide or project-wide secrets: staging and production each hold their own set, even when the names match.

Organisation └── Project ├── staging │ ├── DATABASE_URL │ └── API_KEY └── production ├── DATABASE_URL └── API_KEY

A deploy can only reference secrets in the environment it runs in. That lets the same build run in both environments with different credentials: give each environment a DATABASE_URL, and each deploy picks up its own.

Plain variables and secret references#

A deploy's Environment variables list holds two kinds of row:

Row typeWhat you enterWhere the value lives
PlainA KEY and a valueOn the deploy itself. Visible to anyone who can edit the deploy.
SecretThe name of a secret in the deploy's environmentIn the environment's secret store. Never shown after saving.

Use plain variables for non-sensitive settings such as LOG_LEVEL=info or PORT, and secrets for anything you'd rotate if it leaked. The deploys table summarises each deploy's list in its Variables column, for example “2 vars · 1 secret”.

Create a secret#

Setting and deleting secrets needs the Manager or Admin role. Members with the User role see the list of keys but not the form.

  1. Open Secrets and pick the environment

    Secrets (under Infrastructure), then choose the Project and Environment.

  2. Fill in Set a secret

    Enter a Name such as DATABASE_URL and the Value. The value field is masked.

  3. Save

    Choose Save secret. You'll see “Secret "DATABASE_URL" saved.” and the key appears under Existing secrets.

With the API (values go in the request body, never the URL):

API
POST /v1/projects/{project_id}/environments/{environment_id}/secrets/DATABASE_URL
{"value": "postgres://app:••••@db.internal:5432/app"}

Naming rules#

  • Letters, numbers and . _ = - only. No spaces, slashes or other characters.
  • At most 253 characters.
  • The dashboard checks the name as you type and won't let you save an invalid one.

Because the secret's name becomes the environment variable's name (see below), stick to the usual UPPER_SNAKE_CASE your application expects.

Reference a secret from a deploy#

  1. Open DeploymentsNew deploy, or Edit an existing deploy.
  2. Under Environment variables, choose + Secret.
  3. Pick the secret from the — select secret — list. It lists the keys stored in the environment you selected for the deploy.
  4. Choose Create deploy or Save deploy.

The container receives an environment variable with the same name as the secret. A secret row stores only the name, so the value is read from the environment's store rather than copied onto the deploy.

Inside the container
$ printenv DATABASE_URL
postgres://app:••••@db.internal:5432/app

Update a secret#

Saving a secret under an existing name replaces its value. In Existing secrets, choose Set value next to the key: the name is filled in for you, and you enter the new value and choose Save secret.

When an updated value takes effect#

Environment variables are read when a container starts, so running replicas keep the value they started with until they are replaced.

Delete a secret#

Choose Delete next to the key and confirm “Delete secret "…" from this environment?”. Remove the matching row from any deploy that references it first.

Security behaviour#

  • Write-only values. The API never returns a secret's value; listing an environment's secrets returns keys only. The dashboard never shows a value after saving.
  • Encrypted by the platform. The dashboard states that values are stored encrypted.
  • Role-gated writes. Only Managers and Admins can set or delete secrets. See Members and permissions.
  • Visible to your code. Once injected, a secret is an ordinary environment variable in your container. Anything your application logs, the Watch logs viewer shows, so don't print secrets at start-up.

Common errors#

“Use only letters, numbers, and . _ = -”
The name has a space, slash or other character. Rename it, for example API KEY → API_KEY.
“Name must be at most 253 characters.”
Shorten the name.
No Set a secret form
Your role is User. Ask a Manager or Admin, or ask an Admin to change your role on the Team page.
“No environment”
The selected project has no environment yet. Create one on the Projects page.
“Secrets referenced by deploys”
The secret list couldn't be loaded, so the page shows the keys your deploys reference instead. Values are still never shown. Refresh later.
Secret missing from the deploy form
The deploy is in a different environment from the secret. Secrets don't cross environments; set it in the deploy's environment too.