> For the complete documentation index, see [llms.txt](https://circleci.com/docs/llms.txt)

# Introduction to environment variables

## Introduction

Use environment variables to set up various configuration options, and keep your set-up secure with secrets, private keys, and contexts. Environment variables in CircleCI are governed by an [order of precedence](#order-of-precedence), allowing control at each level in your configuration.

See the [Set an environment variable](https://circleci.com/docs/guides/security/set-environment-variable/) page for guidance on the different ways to set an environment variable.

If you have existing environment variables (or contexts) and you would like to rename your organization or repository, follow the [Rename organizations and repositories](https://circleci.com/docs/guides/security/rename-organizations-and-repositories/) guide. The recommended steps ensure you do not lose access to environment variables or contexts in the process.

## Built-in environment variables

All projects have access to CircleCI’s built-in environment variables. These environment variables are scoped at the job level, so they can be used with the `context` key in a job, but they do not exist at a pipeline level.

For a full list of built-in environment variables, see the [Project values and variables](https://circleci.com/docs/reference/variables/#built-in-environment-variables) page.

## Private keys and secrets

To add private keys or secrets as environment variables for use throughout your project, navigate to **Project Settings**  **Environment Variables** in the [CircleCI web app](https://app.circleci.com/). You can find step-by-step instructions of this process on the [Environment variables](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-project) page. The variable values are neither readable nor editable in the app after they are set. To change the value of an environment variable, delete the current variable, and add it again with the new value.

Private environment variables enable you to store secrets safely, even when your project is public. Refer to the [Building open source projects](https://circleci.com/docs/guides/integration/oss/) page for associated security and settings information.

## Secrets masking

Environment variables and contexts may hold project secrets or keys that perform crucial functions for your applications. Secrets masking provides added security within CircleCI by obscuring environment variables in the job output when `echo` or `print` is used.

Secrets masking is applied to environment variables set within **Project Settings** or **Contexts** in the web app.

The value of the environment variable or context will _not_ be masked in the job output if:

*   the value of the environment variable is less than 4 characters
    
*   the value of the environment variable is equal to one of `true`, `True`, `false`, or `False`
    

Secrets masking will only prevent values from appearing in your job output. Invoking a bash shell with the `-x` or `-o xtrace` options may inadvertently log unmasked secrets (refer to [Using shell scripts](https://circleci.com/docs/guides/orchestrate/using-shell-scripts/)). If your secrets appear elsewhere, such as test results or artifacts, they will not be masked. Additionally, values are still accessible to users [debugging builds with SSH](https://circleci.com/docs/guides/execution-managed/ssh-access-jobs/).

The secrets masking feature exists as a preventative measure to catch unintentional display of secrets at the output. Best practice is to avoid printing secrets to the output. The are many ways that secrets masking could be bypassed, either accidentally or maliciously. For example, any process that reformats the output of a command or script could remove secrets masking.

## Environment variable usage options

CircleCI uses Bash, which follows the POSIX naming convention for environment variables. Valid characters include letters (uppercase and lowercase), digits, and the underscore. The first character of each environment variable name must be an alpha character or an underscore, **not** a digit.

### Order of precedence

Environment variables are used according to a specific precedence order, as follows:

1.  Environment variables declared [inside a shell command](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-shell-command) in a `run` step, for example `FOO=bar make install`.
    
2.  Environment variables declared with the `environment` key [for a `run` step](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-step).
    
3.  Environment variables set with the `environment` key [for a job](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-job).
    
4.  Special CircleCI environment variables defined in the [CircleCI Built-in environment variables](https://circleci.com/docs/reference/variables/#built-in-environment-variables) document.
    
5.  Context environment variables (assuming the user has access to the context). See the [Contexts](https://circleci.com/docs/guides/security/contexts/) documentation for more information.
    
6.  [Project-level environment variables](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-project) set on the **Project Settings** page in the web app.
    

Environment variables declared inside a shell command `run step`, for example `FOO=bar make install`, will override environment variables declared with the `environment` and `contexts` keys. Environment variables added on the **Contexts** page in the web app will take precedence over variables added on the **Project Settings** page.

### Example configuration of environment variables

Consider the example `.circleci/config.yml` below:

`````````
version: 2.1

jobs: # basic units of work in a run
  build:
    docker: # use the Docker executor
      # CircleCI Node images available at: https://circleci.com/developer/images/image/cimg/node
      - image: cimg/node:18.11.0
    steps: # steps that comprise the `build` job
      - checkout # check out source code to working directory
      # Run a step to setup an environment variable
      # Redirect MY_ENV_VAR into $BASH_ENV
      - run:
          name: "Setup custom environment variables"
          command: echo 'export MY_ENV_VAR="FOO"' >> "$BASH_ENV"
      - run: # print the name of the branch we're on
          name: "What branch am I on?"
          command: echo ${CIRCLE_BRANCH}
      # Run another step, the same as above; note that you can
      # invoke environment variable without curly braces.
      - run:
          name: "What branch am I on now?"
          command: echo $CIRCLE_BRANCH
      - run:
          name: "What was my custom environment variable?"
          command: echo ${MY_ENV_VAR}
      - run:
          name: "Print an env var stored in the Project"
          command: echo ${PROJECT_ENV_VAR}
      - run:
          name: "Print an env var stored in a Context"
          command: echo ${CONTEXT_ENV_VAR}

workflows: # a single workflow with a single job called build
  build:
    jobs:
      - build:
          context: Testing-Env-Vars
`````````

The above `.circleci/config.yml` demonstrates the following:

*   Setting custom environment variables.
    
*   Reading a built-in environment variable that CircleCI provides (`CIRCLE_BRANCH`).
    
*   How variables are used (or interpolated) in your `.circleci/config.yml`.
    
*   Secrets masking, applied to environment variable set in the project or within a context.
    

When the above configuration runs, the output looks like the image below. Notice the environment variables stored in the project is masked, and displays as `****`:

Notice there are two similar steps in the above image and configuration - "What branch am I on?" These steps illustrate two different methods to read environment variables.

In the example configuration above, two syntax variants are used: `${VAR}` and `$VAR`. Both syntax variants are supported. You can read more about shell parameter expansion in the [Bash documentation](https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion).

### Parameters and the Bash environment

In general, CircleCI does not support interpolating environment variables in the configuration. Values used are treated as literals. This can cause issues when defining `working_directory`, modifying `PATH`, and sharing variables across multiple `run` steps.

In the example below, `$ORGNAME` and `$REPONAME` will not be interpolated.

`````````
working_directory: /go/src/github.com/$ORGNAME/$REPONAME
`````````

An exception to this interpolation rule is using project environment variables to pull [private images](https://circleci.com/docs/guides/execution-managed/private-images/).

You can reuse pieces of configuration across your `.circleci/config.yml` file. By using the `parameters` declaration, you can pass values into reusable `commands`, `jobs`, and `executors`:

`````````
version: 2.1 # version 2.1 is required for reusing configuration

jobs:
  build:
    parameters:
      org_name:
        type: string
        default: my_org
      repo_name:
        type: string
        default: my_repo
    docker:
      - image: cimg/go:1.17.3
    steps:
      - run: echo "project directory is go/src/github.com/<< parameters.org_name >>/<< parameters.repo_name >>"

workflows:
  my_workflow:
    jobs:
      - build:
          org_name: my_organization
          repo_name: project1

      - build:
          org_name: my_organization
          repo_name: project2
`````````

For more information, read the documentation on [using the parameters declaration](https://circleci.com/docs/reference/reusing-config/#using-the-parameters-declaration).

Another possible method to interpolate values into your configuration is to use a `run` step to export environment variables to `BASH_ENV`, as shown below.

The `$BASH_ENV` workaround only works with `bash`, and has not been confirmed to work with other shells.

`````````
steps:
  - run:
      name: Setup Environment Variables
      command: |
        echo 'export PATH="$GOPATH"/bin:"$PATH"' >> "$BASH_ENV"
        echo 'export GIT_SHA1="$CIRCLE_SHA1"' >> "$BASH_ENV"
`````````

In every step, CircleCI uses `bash` to source `BASH_ENV`. This means that `BASH_ENV` is automatically loaded and run, allowing you to use interpolation and share environment variables across `run` steps.

### Environment variable substitution

The CircleCI environment CLI offers a wrapper around the [`envsubst`](https://github.com/a8m/envsubst) tool, available both locally as well as in all jobs running on CircleCI. `envsubst` is a command-line utility used to replace environment variables in text strings. You can also refer to the full [Environment CLI usage guide](https://circleci.com/docs/guides/toolkit/environment-cli-usage-guide/).

CLI command:

`````````
circleci env subst
`````````

#### Usage

The `circleci env subst` command can accept text input from `stdin` or as an argument.

Within your repository create a file such as `template.json`, with value replaced by environment variable strings

`````````
{
  "foo": "$FOO",
  "provider": "${PROVIDER}"
}
`````````

`envsubst` can convert all types of environment variable strings, including those encased in curly braces (`{}`).

The config example below shows the corresponding environment variables as if they were defined directly within a step in the config. However, we strongly recommend creating the environment variables in the CircleCI app, either in [Project Settings](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-project) or as a [context](https://circleci.com/docs/guides/security/contexts/).

`````````
version: 2.1
jobs:
  process-template:
    docker:
      - image: cimg/base:current
    steps:
      - checkout
      - run:
          name: Process template file
          environment:
            # Environment variables would typically be served via a context
            FOO: bar
            PROVIDER: circleci
          command: |
            circleci env subst < template.json > deploy.json
            cat deploy.json
workflows:
  env-subst-workflow:
    jobs:
      - process-template
`````````

In this example:

*   The `<` symbol is used to redirect the contents of the `template.json` file as _input_ to the `env subst` command.
    
*   The `>` symbol is used to redirect the output of the `env subst` command to the `deploy.json`.
    

You could alternatively pass input to the `circleci env subst` command as an argument: `circleci env subst "hello \$WORLD"`

Output:

`````````
{
  "foo": "bar",
  "provider": "circleci"
}
`````````

For instructions on installing the CircleCI CLI locally, read the [Installing the CircleCI local CLI](https://circleci.com/docs/guides/toolkit/local-cli/) guide.

### Alpine Linux

An image that has been based on [Alpine Linux](https://alpinelinux.org/) (like [Docker](https://hub.docker.com/_/docker)), uses the `ash` shell.

To use environment variables with `bash`, add the `shell` and `environment` keys to your job.

`````````
version: 2.1

jobs:
  build:
    shell: /bin/sh -leo pipefail
    environment:
      BASH_ENV: /etc/profile
`````````

## Notes on security

Do not add secrets or keys inside the `.circleci/config.yml` file. The full text of `.circleci/config.yml` is visible to developers with access to your project on CircleCI. Store secrets or keys in the CircleCI web app under one of the following:

*   In [Project settings](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-project).
    
*   In a [context](https://circleci.com/docs/guides/security/set-environment-variable/#set-an-environment-variable-in-a-context).
    

For more information, see the [Encryption](https://circleci.com/docs/guides/security/security/#encryption) section of the security page.

Running scripts within configuration may expose secret environment variables. See the [Using shell scripts](https://circleci.com/docs/guides/orchestrate/using-shell-scripts/#shell-script-best-practices) page for best practices for secure scripts.

## Contexts

You can further restrict access to environment variables using [contexts](https://circleci.com/docs/guides/security/contexts/). Contexts are set from the **Organization Settings** in the CircleCI web app.

## See also

*   [Security recommendations](https://circleci.com/docs/guides/security/security-recommendations/)
    
*   [Set an environment variable](https://circleci.com/docs/guides/security/set-environment-variable/)
    
*   [Inject variables using the CircleCI API](https://circleci.com/docs/guides/security/inject-environment-variables-with-api/)