wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

This article is part of a mini series. Read them all:

Coming of age - encrypt your environment

Using age in Github actions

Hero image for Using age in Github actions

In the last article I introduced age and a working setup for macOS. Now let's look at Github actions integration

TL/DR

In a nutshell: create an age key just for GitHub actions, commit it to secrets, add the public key to recipients.txt and add it to your github job.

Step by step

There are a few consideration for each step you need to be aware off. Nothing dramatic, just stumbling blocks, I stumbled over, so you don't have to.

Create a key for CI

Generate the key:

age-keygen -o ci-key.txt
chmod 600 ci-key.txt

When you opted for a repo based key, you can save yourself a step by adding it directly to recipients.txt

CIKEY=$(age-keygen -o ci-key.txt 2>&1 | sed -n 's/^Public key: //p')
echo $CIKEY >> recipients.txt
age -d -i <(security find-generic-password -s age-corporate -a "$USER" -w) .env.age \
  | age -R recipients.txt -o .env.age.tmp && mv .env.age.tmp .env.age

Add to GitHub

You have a choice between

  • repository based keys (https://github.com/<your_org_or_user>/<yourrepo>/settings/secrets/actions)
  • organization based keys (https://github.com/organizations/<your_org>/settings/secrets/actions)

Organization based keys are convenient, but allow any repo to decode your secrets. So choose wisely. Give it the name AGE_KEY_CI

You need the line that starts with AGE-SECRET-KEY-1. Once saved, delete ci-key.txt.

Use it in a GitHub Action

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: Install age
        run: sudo apt-get update && sudo apt-get install -y age
      - name: Decrypt secrets
        shell: bash
        env:
          AGE_KEY_CI: ${{ secrets.AGE_KEY_CI }}
        run: |
          set -euo pipefail
          age -d -i <(printf '%s' "$AGE_KEY_CI") .env.age | awk '
            /^export / {
              line = $0; sub(/^export /, "", line)
              key = line; sub(/=.*/, "", key)
              val = line; sub(/^[^=]+=/, "", val); gsub(/^["'"'"']|["'"'"']$/, "", val)
              if (length(val) > 5) print "::add-mask::" val
              print key "=" val >> ENVIRON["GITHUB_ENV"]
            }'

This will make all your variables available in the github environment. The beauty is having a single source of environment truth in .env.age The awkcommand adds the variables to the GitHub environment and ensures that the values are masked.

Next up: Yubikey and SSH.

As usual YMMV


Posted by on 24 August 2026 | Comments (0) | categories: Development GitHub

Comments

  1. No comments yet, be the first to comment