1. Overview

Sensitive information such as API keys, database credentials, and other confidential data shouldn’t be stored carelessly. Accidental exposure can lead to security breaches that can compromise individuals and organizations. With environment variables, we can manage this information outside of code. However, securely integrating them into automated workflows can be challenging.

In this tutorial, we’ll explore various ways to use an env file to securely store and manage environment variables within the GitHub Actions workflow.

2. Understanding Environment Variables

Environment variables dynamically influence the behavior of running processes. In essence, they serve as containers for configuration settings and sensitive data, such as API keys and database credentials, which are essential for applications to function properly.

2.1. Importance of Environment Variables

Environment variables are important for several reasons:

  • Security: They allow sensitive information to be stored outside the source code, reducing the risk of exposure
  • Configuration Management: Environment variables make managing configurations for different environments easier; for example, development, staging, or production
  • Portability: They enable applications to be more portable and adaptable to different environments; it is particularly useful in CI/CD pipelines, containerization, and cloud deployments where applications need to run in various contexts

2.2. How Environment Variables Work

Applications and scripts can access environment variables during runtime. These dynamic configurations enhance security and flexibility, especially in CI/CD pipelines like GitHub Actions.

For instance, GitHub Actions leverages environment variables to dynamically tailor pipeline setup, such as specifying environments or providing deployment details:

name: Deploy Application

on:
    push:
        branches:
            - main

jobs:
    deploy:
        runs-on: ubuntu-latest
        env:
            ENVIRONMENT: production
            DEPLOYMENT_URL: https://baeldung.com
        steps:
            - name: Checkout code
              uses: actions/checkout@v4

            - name: Deploy to Server
              run: |
                  curl -X POST ${{ env.DEPLOYMENT_URL }} \
                  -H "Content-Type: application/json" \
                  -d '{"environment":"${{ env.ENVIRONMENT }}"}'

This example defines ENVIRONMENT and DEPLOYMENT_URL as environment variables directly within the workflow. The deployment step then dynamically uses these variables to specify the target environment and deployment URL.

2.3. Best Practices

To ensure optimal security and flexibility, we can follow these key practices when managing environment variables:

  • Avoid hardcoding sensitive data
  • Use a consistent naming convention
  • Document variables
  • Limit the scope of variables; only expose the necessary environment variables to the scope that requires them

Understanding and properly managing environment variables enhances applications’ security and flexibility.

3. Storing Environment Variables in GitHub Actions

GitHub Actions offers several methods for managing environment variables, ensuring both security and efficiency in workflows. Primarily, we can define environment variables directly within the workflow configuration or leverage GitHub Secrets for sensitive data.

3.1. Using the env Key in Workflow Files

We can define environment variables directly in the workflow file using the env key. This method is straightforward and suitable for non-sensitive data.

Firstly, let’s create a directory and navigate to it:

$ mkdir gh-action-env-files && cd gh-action-env-files

Next, we create a new GitHub Actions workflow file in the .github/workflows directory:

$ mkdir -p .github/workflows
$ touch .github/workflows/env-key-example.yml

Now, let’s add the following code to the env-key-example.yml file:

name: Env Key Example

on: [push]

jobs:
    create-env-file:
        runs-on: ubuntu-latest
        env:
            SOME_API_KEY: "123456abcdef"
        steps:
            - name: Checkout repository
              uses: actions/checkout@v3

            - name: Create .env file
              run: echo "SOME_API_KEY=${{ env.SOME_API_KEY }}" > .env 

The env-key-example.yml file defines a GitHub Actions workflow named Env Key Example, triggered upon any push to the repository. This workflow contains a single job titled create-env-file that is configured to run on the latest Ubuntu environment.

Within the job, we defined SOME_API_KEY,  an environment variable with the value 123456abcdef. The workflow includes two steps. Firstly, it checks out the repository using the actions/checkout action, which ensures that the repository’s content is available in the workflow environment. Secondly, it creates an env file using the echo command to write the value of SOME_API_KEY into the file.

3.2. Pushing to GitHub

After defining the workflow, we can push the changes to a GitHub repository to trigger the workflow and see it in action. Firstly, let’s create a new GitHub repository. Next, we push to GitHub:

$ git init
$ git add .
$ git commit -m "Add GitHub Actions workflow to use env key"
$ git branch -M main
$ git remote add origin <your-github-repo-url>
$ git push -u origin main

With these changes pushed to GitHub, we can navigate to the Actions tab in the GitHub repository to see the workflow in action:

Workflow env key

Now, let’s see the details of this workflow file. Firstly, click on the Add GitHub Actions workflow to use env key commit message as shown in the previous image. This will expand the details of the workflow run.

Next, click on the create-env-file job and on the Create .env file step to view the specific actions taken during this part of the workflow:

Workflow env test

We can now verify that the SOME_API_KEY environment variable was correctly used and that the .env file was successfully created.

Using environment variables directly within a GitHub Actions workflow via the env key effectively handles non-sensitive data. In the next section, let’s see how to manage sensitive data securely using GitHub Secrets.

3.3. Using GitHub Secrets

When handling sensitive information like API keys, database credentials, or any other confidential data, it’s crucial to ensure that this information is not exposed in the source code or the workflow files. GitHub Secrets provide a secure way to store and manage this data within GitHub Actions.

These secrets are encrypted and can be referenced within workflows. This allows sensitive information to be used without being exposed in plain text. To start using GitHub Secrets, let’s navigate to the Settings tab. Expand the Secrets and variables in the sidebar, and click on Actions:

GitHub Secrets Directions

Next, let’s click on the green New repository secret button, and enter a name for the secret in the Name field. Here we can use TEST_SECRETS and the following dummy secrets in the Secret input:

SECRET_KEY=your_sample_secret_key
DATABASE_URL=your_sample_database_url
API_KEY=your_sample_api_key
AWS_ACCESS_KEY_ID=your_sample_access_key_id
AWS_SECRET_ACCESS_KEY=your_sample_secret_access_key
GOOGLE_CLIENT_ID=your_sample_client_id
GOOGLE_CLIENT_SECRET=your_sample_client_secret
TWITTER_API_KEY=your_sample_api_key
TWITTER_API_SECRET=your_sample_api_secret
FACEBOOK_APP_ID=your_sample_app_id
FACEBOOK_APP_SECRET=your_sample_app_secret
GITHUB_TOKEN=your_sample_github_token
MAILGUN_API_KEY=your_sample_api_key
SENDGRID_API_KEY=your_sample_api_key
SLACK_API_TOKEN=your_sample_api_token
STRIPE_SECRET_KEY=your_sample_secret_key
TWILIO_ACCOUNT_SID=your_sample_account_sid
TWILIO_AUTH_TOKEN=your_sample_auth_token
MONGODB_URI=your_sample_mongodb_uri
REDIS_URL=your_sample_redis_url

Add GitHub Secrets

With these updates, let’s click on the Add secret button to save the secrets to the repository.

Once the secrets are stored in the repository, we can use them in a workflow file. Firstly, let’s create a new workflow file in the .github/workflows directory:

$ touch .github/workflows/using-github-secrets.yml

Next, let’s add the following code to the using-github-secrets.yml file:

name: Using GitHub Secrets

on: [push]

jobs:
    using-github-secrets:
        runs-on: ubuntu-latest
        steps:
            - name: Checkout repository
              uses: actions/checkout@v3

            - name: Create .env file
              run: |
                  touch .env
                  echo "${{secrets.TEST_SECRETS}}" >> .env

            - name: Test printing your secret (Remove this step in production)
              run: |
                  cat .env

Similarly, we can trigger this workflow by any push event to the repository. It has a single job named using-github-secrets, which runs on the latest Ubuntu environment (runs-on: ubuntu-latest).

The first step uses the actions/checkout@v3 action to clone the repository, making the files available to the workflow. The next step, Create .env file, creates an empty .env file using touch .env. After this, we append the value of the TEST_SECRETS secret to the .env file.

With the secrets appended, we print the contents of the .env file. This step is primarily for testing purposes to ensure the secret was correctly processed.

3.4. Pushing to GitHub

Now, let’s push to GitHub:

$ git add . && git commit -m "Use GitHub Secrets" && git push origin main

After that, let’s navigate to the Actions tab, select the Use GitHub Secrets commit message, and view the contents of the workflow:

Using GitHub Secrets

Here, we can see the secrets masked to protect their values. This ensures that sensitive information remains secure, even when reviewing logs or debugging issues.

4. Conclusion

In this article, we learned how to manage environment variables in GitHub Actions using an env file. Firstly, we discussed the importance of protecting sensitive information like API keys and configuration settings. Then, we checked out how to use the env to directly define non-sensitive data.

For more sensitive information, we leveraged GitHub Secrets, which offers an encrypted and secure way to store and reference these variables within workflows.

In addition, the optimal approach to managing environment variables depends on the sensitivity of the data involved. GitHub Actions offers flexibility, but careful consideration is essential. The complete code for this article is available on GitHub.