Secrets and Variables

Store tokens and passwords as encrypted secrets and read them safely in workflows.

Never hard-code passwords or API tokens in a workflow. Store them as encrypted secrets under Settings → Secrets and variables → Actions.

Using secrets

Read a secret with ${{ secrets.NAME }}. GitHub automatically masks its value in the logs. A built-in GITHUB_TOKEN is provided for each run to interact with your repo.

Variables

Non-sensitive configuration goes in variables, read with ${{ vars.NAME }}.

Example

Example · yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Publish
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          API_URL: ${{ vars.API_URL }}
        run: |
          echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
          npm publish

When to use it

  • A team stores the production database password as a GitHub secret so it never appears in the workflow YAML file or logs.
  • A developer uses a repository variable (non-secret) to store the deployment region, keeping config visible in the Actions UI.
  • An organisation stores a shared Docker Hub token as an organisation-level secret so all repos can push images without duplicating the credential.

More examples

Store and use a secret in a workflow

Maps the GitHub secret into the step's environment; the value is masked in logs and never exposed in workflow YAML.

Example · yaml
# Store via CLI first:
# gh secret set DATABASE_URL

jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - run: npx prisma migrate deploy
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}

Use repository variables for config

Variables (vars context) are not masked and are suitable for non-sensitive configuration values visible in the Actions UI.

Example · yaml
# Set via CLI:
# gh variable set DEPLOY_REGION --body us-east-1

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Region: ${{ vars.DEPLOY_REGION }}"

Rotate a secret without downtime

Overwriting a GitHub secret with gh secret set is instantaneous; the next workflow run picks up the new value automatically.

Example · bash
# Set the new value (overwrites the old secret)
gh secret set API_TOKEN --body "$NEW_TOKEN"

# Verify the secret exists
gh secret list
# NAME        UPDATED
# API_TOKEN   just now

Discussion

  • Be the first to comment on this lesson.