Environment Variables
Environment variables are defined under a variables key. The keys you provide are the names of the environment variables.
A variable is either a plain string or an object, when you need to control build-time availability or mount it as a file.
A top-level variables applies to your whole application, and you can narrow that per resource; see
Scoping environment variables.
variables:
APP_ENV: production
API_KEY:
gitlab: NAME_OF_SECRET_IN_GITLAB
APP_SERVICE_ACCOUNT_JSON:
value: '{"type": "service_account"}'
file: google-creds.json
variables replaces env, the original name for this key. env
still works today, but it will change in a future release, rename the properties whenever possible.
Renaming the key is the whole migration: nothing inside it changes, and your running application sees
the same variables. If both keys are present, the value under variables are taken over env.
Options
These are the keys of the object form. Set either value or gitlab, never both.
| Property | Type | Description | Default |
|---|---|---|---|
value |
string, number or boolean |
The literal value of the variable. See String values. | None |
gitlab |
string, object or null |
Read the value from a GitLab CI/CD variable instead of writing it here. As a string, the name of that variable. See GitLab CI/CD secrets. | The name of the variable itself |
gitlab.name |
string |
The name of the GitLab CI/CD variable to read, written as an object rather than a bare string. | The name of the variable itself |
build |
boolean or 'only' |
Whether the variable is also available while your image is built. true gives you it at build time and at run time, 'only' at build time alone. See Build-time variables. |
false |
file |
string |
A filename. The value is written to a file with this name, and the variable holds the path to it. See Variables as files. | None |
token |
object |
An identity token for your application, mounted as a file. The variable holds the path to that file. Cannot be combined with value, gitlab, file or build. See Identity tokens. |
None |
token.audience |
string |
The service the token is intended for. Required when token is set. |
None |
token.ttl |
integer or string |
How long each issued token is valid for, as seconds or a duration such as 2h. Values below 600 seconds are rejected. See Identity tokens. |
3600 |
String values
The simplest way to define an environment variable is by providing its name as the key and a string as the value.
variables:
APP_ENV: production
LOG_CHANNEL: stack
Alternatively, you can define a basic variable using an object with just the value key. This is functionally identical to the string format:
variables:
DATABASE_HOST:
value: mariadb-p-123.db.ondigitalocean.com
Object values
For scenarios requiring more control, such as making variables available only during build-time or mounting their content as files, you must use the object format.
variables:
MY_VARIABLE:
value: my-value
build: false
file: my-variable.txt
Build-time variables
This variable will be available during the build stage in GitLab CI/CD, but not in the final running container.
variables:
ASSET_COMPILATION_FLAG:
value: "true"
build: only
Variables as files
This is useful for long configuration strings or multi-line values. The APP_SERVICE_ACCOUNT_JSON environment variable will be set to the absolute path of the created file.
variables:
APP_SERVICE_ACCOUNT_JSON:
value: '{"type": "service_account", ...}'
file: google-creds.json
Identity tokens
A token gives your application a short-lived signed token it can present to another service, without you storing or rotating a credential. The token is written to a file and the variable holds the path to it, so your application reads the file when it needs the current token.
The token is replaced automatically before it expires, so read it from the file each time you use it rather than caching it for the lifetime of the process.
variables:
BILLING_TOKEN_PATH:
token:
audience: billing-api
audience names the service you intend to present the token to, and it is required. It is what stops a token issued for one service being accepted by another, so give each service its own audience rather than reusing one everywhere.
Verifying the token
A token is only worth as much as the check the receiving service performs on it. That service must:
- Verify the signature against the OIDC discovery endpoint for your environment. Contact Cloudbear to get it; it is not something you configure yourself.
- Check the
audclaim matches the audience it expects. Without this check any token from your environment is accepted, including one your application minted for an entirely different service.
A service that skips either step is trusting anything presented to it.
The token identifies your environment, not an individual application within it. Do not use it to tell two of your applications in the same environment apart.
Token lifetime
Each token is valid for an hour by default. Set ttl to change that, either as a number of seconds or as a duration such as 30m or 2h:
variables:
BILLING_TOKEN_PATH:
token:
audience: billing-api
ttl: 30m
Values below 600 seconds are rejected. A shorter lifetime does not mean your application has to do anything differently: the token is replaced before it expires either way, so read it from the file each time you use it.
Several tokens
Each token gets its own file, so you can declare several for different services:
variables:
BILLING_TOKEN_PATH:
token:
audience: billing-api
REPORTING_TOKEN_PATH:
token:
audience: reporting-api
token cannot be combined with value, gitlab, file or build.
Scoping environment variables
A top-level variables is global: its variables are added to every part of your application: the HTTP server, workers, cronjobs, migrations, and remote access.
In addition, you can define variables on an individual resource. Those variables are added only to that resource, on top of the global ones. This lets you give a specific worker, cronjob, or the HTTP server its own variables without affecting the others.
These are the places variables can be written:
| Key | What it applies to |
|---|---|
variables |
Every part of your application. |
http.variables |
The web server. See HTTP. |
workers.<name>.variables |
One worker. See Workers. |
cronjobs.<name>.variables |
One scheduled task. See Cronjobs. |
migration.variables |
The migration that runs before a deployment goes live. |
access.variables |
Remote access sessions. See Remote Access. |
loadGenerations.<name>.variables |
One load generation run. |
metrics.variables |
The metrics servers. See The metrics servers. |
# Global: available everywhere.
variables:
APP_ENV: production
LOG_CHANNEL: stack
http:
variables:
# Only on the HTTP server.
SERVE_STATIC: "true"
workers:
emails:
variables:
# Only on the "emails" worker.
MAIL_BATCH_SIZE: "50"
When the same variable name is defined both globally and on a resource, the resource's value wins for that resource. Every value format described below (value, file, gitlab, token, and connection templating) works the same whether the variable is global or scoped to a resource.
The metrics servers
The servers metrics are collected from run the same image as your other web servers and usually need
the same configuration, so they inherit http.variables rather than starting empty, the same way they
inherit http.resources.
Variables of their own are added on top of what they inherit, and a variable named in both takes the value written here:
http:
variables:
SERVE_STATIC: "true"
APP_DEBUG: "false"
metrics:
enable: true
variables:
# SERVE_STATIC is still inherited; APP_DEBUG takes the value below.
METRICS_TOKEN: "{{ svc.db.conn.default.password }}"
APP_DEBUG: "true"
Configuring metrics on an http group instead works the same way: the
group's own variables are added on top of the ones it inherits from http. See
Configure Metrics.
Build-time variables (build: true or build: only) are only read from the
top-level variables. A build variable placed inside a resource's
variables is applied to that resource at run-time but is not made
available to the GitLab CI/CD pipeline. Define build-time variables at the top level.
GitLab CI/CD secrets
You can securely inject secrets defined in your GitLab project's CI/CD settings (Settings > CI/CD > Variables). To do this, use the gitlab key instead of value.
Environment variables should not be set to Hidden in GitLab. We are unable to read these variables at the current time.
Naming the secret
You can specify the name of the secret from GitLab in two ways:
1. As a string:
variables:
MY_SECRET_KEY:
gitlab: NAME_OF_SECRET_IN_GITLAB
2. As an object with a name property:
variables:
MY_SECRET_KEY:
gitlab:
name: NAME_OF_SECRET_IN_GITLAB
Implicit names
If you define the gitlab key but leave it null (~) or omit the name property, the name of your environment variable itself will be used to look up the secret in GitLab.
This is useful for maintaining consistency between your cap config file and GitLab CI/CD variables.
variables:
# This will look for a GitLab secret named "API_KEY"
API_KEY:
gitlab: ~
# This will also look for a GitLab secret named "ANOTHER_SECRET"
ANOTHER_SECRET:
gitlab: {}
Secrets as files
You can also mount GitLab secrets as files by providing the file property with a filename.
variables:
SSH_PRIVATE_KEY:
# Looks for a GitLab secret named "CI_SSH_PRIVATE_KEY"
gitlab: CI_SSH_PRIVATE_KEY
# The SSH_PRIVATE_KEY env var will contain the absolute path to the secret file
file: id_rsa
Connection string templating
You can build a value out of a service's own hostname, port and credentials instead of hardcoding them:
variables:
DATABASE_URL:
value: "mariadb://{{ svc.db.conn.default.username }}:{{ svc.db.conn.default.password }}@{{ svc.db.conn.default.hostname }}:{{ svc.db.conn.default.port }}/{{ svc.db.conn.default.database }}"
See Connections for the syntax and every value available per service.