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 Stephan H Wissel on 24 August 2026 | Comments (0) | categories: Development GitHub