GitHub Actions
Bootstrap an ephemeral machine inside your GitHub Actions workflow and pull SikkerKey secrets as environment variables at runtime.
SikkerKey integrates with GitHub Actions through a workflow-time bootstrap. The dashboard generates a shell script and a workflow snippet that you commit to your repository. At runtime, the script registers an ephemeral machine bound to an enrollment token's policy, fetches the granted secrets, and exposes them as environment variables for subsequent workflow steps.
Prerequisites
- An enrollment token scoped to the projects and secrets your workflow needs
- Repository admin access (to add an Actions secret)
- A runner image with
curlandnpmavailable (ubuntu-latestincludes both)
1. Add the enrollment token to GitHub
Copy the enrollment token plaintext. The plaintext is shown only once at creation; if you've lost it, revoke the token and create a new one.
In your repository on GitHub:
Settings → Secrets and variables → Actions → New repository secret
Set the name to SIKKERKEY_ENROLLMENT_TOKEN and paste the plaintext as the value.
2. Generate the bootstrap script
In the SikkerKey dashboard, go to Integrations and click Build on the GitHub Actions row. Paste the same enrollment token plaintext into the modal. SikkerKey verifies it server-side and renders two files:
sikkerkey-init.sh: the bootstrap script. Commit it at the root of your repository..github/workflows/your-workflow.yml: the workflow snippet. Paste the relevant pieces into your existing workflow file (or create a new one).
3. Use it in your workflow
The full shape of a workflow that uses SikkerKey looks like this:
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fetch SikkerKey secrets
env:
SIKKERKEY_ENROLLMENT_TOKEN: ${{ secrets.SIKKERKEY_ENROLLMENT_TOKEN }}
run: sh ./sikkerkey-init.sh
- name: Deploy
run: ./your-deploy-command.sh
The enrollment token is scoped to the Fetch SikkerKey secrets step, so subsequent steps don't see it in their environment. After that step runs, every later step in the same job sees the granted secrets as environment variables.
What happens at runtime
- The script reads
SIKKERKEY_ENROLLMENT_TOKENfrom the workflow environment. - It calls the SikkerKey enrollment endpoint, which generates a one-time Ed25519 keypair on the runner and registers an ephemeral machine bound to the token's policy.
- It installs the SikkerKey CLI via npm.
- It unlocks each project the token grants.
- It exports the granted secrets to a temporary dotenv file.
- It reads the file, masks each value in workflow logs via
::add-mask::, appends each entry to$GITHUB_ENV, and deletes the file.
Multiple jobs
Each GitHub Actions job runs on a fresh runner. If you have multiple jobs that need secrets, add the Fetch SikkerKey secrets step to each. Every job produces its own ephemeral machine that disappears when the runner is destroyed.
Security model
- Scoped token. The enrollment token can only register machines bound to its configured policy: projects, secrets, source CIDR, hostname pattern, machine TTL, and max uses. It cannot read secrets directly.
- Ephemeral machine. Each workflow run produces a unique machine identity, generated on the runner. The private key lives only in the runner's filesystem and is gone when the runner is torn down.
- Hash-only storage. SikkerKey stores only the SHA-256 hash of the enrollment token. The plaintext lives in GitHub's encrypted secret store and is never sent back to you through SikkerKey.
- Audit trail. Every enrollment, every secret read, and every machine action is recorded in your audit log, attributed to the parent token along with the runner's IP and timestamp.
Troubleshooting
./sikkerkey-init.sh: Permission denied (exit code 126). The committed script doesn't have the execute bit. The generated workflow snippet invokes the script via sh ./sikkerkey-init.sh, which doesn't require it. If you've modified the snippet to drop the sh prefix, restore it.
Enrollment token not found (404). The plaintext you pasted into the dashboard modal doesn't match any token in your account. The plaintext is shown only once at creation. If you've lost it, revoke the token and create a new one.
Token has been revoked / expired / no remaining enrollments (410). The token can no longer enroll machines. Create a new token from Enrollment Tokens, regenerate the script, replace the SIKKERKEY_ENROLLMENT_TOKEN value in your repository secrets, and re-run the workflow.
Secrets not available in the same step that runs the script. $GITHUB_ENV writes only take effect for subsequent workflow steps. Put your secret-using commands in a step after Fetch SikkerKey secrets.