GitHub Actions secrets, without copy-pasting into every repo.
GitHub's built-in Secrets are fine until you have ten repos and the same DATABASE_URL in each one. Envshed ships a service-token pattern: your workflow pulls the current secrets at run time, every repo reads from one vault, and rotation is one click.
Once you have more than one repo and more than one environment, GitHub's repository secrets start to hurt. You update a key and forget which workflows need it. Organization-level secrets help, but only inside a single GitHub org. Envshed runs one vault per organization, your Actions workflows fetch the current values at job start, and the secret you just rotated is live on the next run — no redeploys, no per-repo UI clicks.
Where GitHub Actions secrets start to bleed
A Stripe key lives in 12 repos' Secrets tabs
Rotating it means 12 PRs, or 12 browser tabs clicked in sequence. By key three, you have stopped double-checking.
Environments collapse into prefixed names
STAGING_DATABASE_URL and PROD_DATABASE_URL share the same Secrets tab. One day someone copies the prod value into staging's slot, and staging writes to production for six hours.
CI log redaction is not a security boundary
GitHub redacts known secret values in logs, but screenshots, downstream services, and cached build artifacts are not protected by a log filter.
One service token in GitHub. Everything else in Envshed
Envshed issues service tokens scoped to a single environment. Your workflow authenticates with that token, pulls the secrets it needs at job start, and they are injected into the process. The service token lives in GitHub Secrets once. Every other value rotates in Envshed and propagates to every workflow on the next run.
A minimal Actions job
One token in GitHub. Every other secret in Envshed.
# .github/workflows/deploy.yml
- name: Install Envshed CLI
run: npm install -g envshed
- name: Deploy with production secrets
env:
ENVSHED_TOKEN: ${{ secrets.ENVSHED_PRODUCTION_TOKEN }}
run: envshed run --env production -- pnpm deployWhat changes when you adopt this
One token per environment
A staging token cannot read production. Revoke the token in Envshed and every workflow using it stops pulling within seconds.
Rotation without PRs
Change a value in the Envshed dashboard. The next workflow run picks it up. No repo changes, no re-deploys of the workflow file.
Read-only by default in CI
Service tokens can pull, not push. Only human operators can change values in Envshed. CI can never write back.
What you get
- Service tokens scoped to an organization, project, and environment
- envshed run --env production -- <cmd> injects values into one child process, no temp files
- Audit trail showing which token pulled what, from which workflow run, at which timestamp
- Short-lived tokens via GitHub OIDC if you would rather not store a long-lived credential
- Free tier supports 2 users and unlimited secret reads — enough to run CI for a side project
GitHub Actions, answered
Does this replace GitHub Actions Secrets entirely?
Almost. You still store the Envshed service token in GitHub Secrets — that single value unlocks everything else. The dozens of individual secrets move out of GitHub and into Envshed, where you can version, rotate, and audit them.
What if my workflow runs on self-hosted runners?
Same CLI, same token flow. The runner needs outbound network access to api.envshed.com on port 443 to pull values.
Does envshed run leak values into logs?
No. envshed run injects values into the child process only. It does not print them, and GitHub's own log masking still works on any value that does surface.
Can I use GitHub OIDC instead of a long-lived token?
Yes. You can issue a short-lived Envshed token from an OIDC claim so the workflow never holds a static credential. See the docs for the exact claim shape.
Give your Actions workflows one vault to read from
Store the service token in GitHub Secrets. Everything else lives in Envshed.
Start freePart of the Envshed.