Automate with API Keys
Run tvault from CI and scripts with a least-privilege tvkey_ API key.
Use an API key when a pipeline or script needs more than reading credentials, for example creating tokens or agents. Give it only the scopes the job needs.
1. Create the key
Run this as yourself, once:
tvault keys create --name ci --scopes tokens:create-read,agents:create --expires 90d
# tvkey_... <- printed once, never retrievable2. Store it as a CI secret
gh secret set TVAULT_KEY --body "tvkey_..."3. Use it in GitHub Actions
jobs:
provision:
runs-on: ubuntu-latest
steps:
- name: Install tvault
run: curl -fsSL https://raw.githubusercontent.com/c-lgrant/tvault/main/install.sh | bash
- name: Log in
env:
TVAULT_KEY: ${{ secrets.TVAULT_KEY }}
run: printf %s "$TVAULT_KEY" | tvault login --key-stdin --as ci
- name: Show identity
run: tvault whoami
- name: Create a token
run: tvault tokens create --service deploy-svc --value "${{ secrets.DEPLOY_VALUE }}"The value goes from the runner straight to your webhook on a signed store ticket. Token Vault never sees it.
4. Mint a scoped agent for a job
With agents:create, the key can create agents, each limited to a subset of its own scopes:
tvault agents create --name job-agent --kind scoped --scopes tokens:createRotate and revoke
tvault keys rotate <id> # then update the TVAULT_KEY secret
tvault keys revoke <id> # kills this key only; what it created keeps workingtvault keys revoke <id> --force (aliases --yes, -y) skips the confirmation prompt in scripts.
A key can rotate itself with no scope. A scheduled CI job can rotate its own key and store the new one (the CLI switches its context to the new key and prints it once on stdout):
printf %s "$TVAULT_KEY" | tvault login --key-stdin --as ci
NEW_KEY=$(tvault keys rotate --self)
# Store $NEW_KEY in your secret manager as TVAULT_KEY, then discard it. Never log it.Rotating another key is always a human action; a key can only rotate itself (--self). Revoking
another key needs keys:revoke, and only a human can give a key that scope. Revoking a key does not
revoke what it created: use "Created by" to find those and revoke them too.
Failure handling
A failing step exits with a distinct code: 8 scope denied, 9 human only, 10 expired,
11 suspended, 12 invalid key. See exit codes.