How to Use GitHub Secrets for Actions

Share
How-To Guide

How to Use GitHub Secrets

Secure your CI/CD workflows with encrypted secrets

TL;DR

TL;DR: Go to Repository Settings → Secrets and variables → Actions. Add secrets with descriptive names like STRIPE_SECRET_KEY . Access them in workflows using $ . GitHub automatically masks secret values in logs.

Types of GitHub Secrets

TypeScopeBest For
Repository secretsSingle repoProject-specific keys
Environment secretsSpecific environmentProduction vs staging keys
Organization secretsMultiple reposShared API keys across projects

Step-by-Step Setup

1

Open repository settings

Go to your GitHub repository and click SettingsSecrets and variablesActions.

2

Create a new secret

Click New repository secret and enter:

  • Name: Use SCREAMING_SNAKE_CASE (e.g., STRIPE_SECRET_KEY)
  • Value: The actual secret value

Click Add secret to save.

3

Use secrets in your workflow

Reference secrets in your .github/workflows/*.yml files:

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Vercel
        env:
          VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
        run: vercel --prod --token=$VERCEL_TOKEN

      - name: Run tests with API key
        env:
          STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
        run: npm test

Common Workflow Examples

Deploy to Vercel

- name: Deploy
  env:
    VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
    VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
    VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
  run: |
    npm i -g vercel
    vercel pull --yes --token=$VERCEL_TOKEN
    vercel build --prod --token=$VERCEL_TOKEN
    vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN

Push to Docker Registry

- name: Login to Docker Hub
  uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push
  uses: docker/build-push-action@v5
  with:
    push: true
    tags: user/app:latest

Environment-Specific Secrets

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Deploy
        env:
          # Uses staging-specific secret
          API_KEY: ${{ secrets.API_KEY }}
        run: ./deploy.sh

  deploy-production:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy
        env:
          # Uses production-specific secret
          API_KEY: ${{ secrets.API_KEY }}
        run: ./deploy.sh

Setting Up Environments

For different secrets per environment (staging, production):

  1. Go to Settings → Environments
  2. Create environments (e.g., "staging", "production")
  3. Add secrets to each environment
  4. Reference the environment in your workflow with environment: production

Pro tip: Add protection rules to production environments, like requiring manual approval before deploying.

Security Best Practices

  • Use specific names: STRIPE_SECRET_KEY not API_KEY
  • Limit scope: Use repository secrets unless you need org-wide access
  • Rotate regularly: Update secrets periodically and after any exposure
  • Never echo secrets: Don't use echo $SECRET in workflows
  • Be careful with forks: Secrets aren't available in fork PRs by default

Secrets and Pull Requests

For security, secrets are not passed to workflows triggered by pull requests from forks. This prevents malicious PRs from stealing your secrets. Use pull_request_target carefully if you need secrets in PR workflows.

Using GitHub CLI

# Set a secret
gh secret set STRIPE_SECRET_KEY

# Set from a file
gh secret set GOOGLE_CREDENTIALS < credentials.json

# List secrets (names only, not values)
gh secret list

# Delete a secret
gh secret delete OLD_SECRET

# Set an environment secret
gh secret set API_KEY --env production

Can I see the value of a secret after saving?

No, GitHub encrypts secrets and never displays them again. If you need to verify or change a secret, you must update it with the new value. There's no way to retrieve the original.

Are secrets visible in workflow logs?

GitHub automatically masks secret values in logs, replacing them with ***. However, if your code transforms the secret (base64 encode, split, etc.), the transformed value might not be masked.

What's the difference between secrets and variables?

Secrets are encrypted and hidden, used for sensitive data like API keys. Variables are plain text and visible, used for non-sensitive configuration like feature flags or environment names.

Related guides:How to Hide API Keys · How to Enable Secret Scanning · Environment Variables Guide

How-To Guides

How to Use GitHub Secrets for Actions