Mode: operator-assisted Last validated: 2026-04-24 UTC Validation method: read-only-docs Average duration: 6m Required role: superadmin
Applies to: legacy INFISICAL_SERVICE_TOKEN and any new machine-identity tokens minted for Raxx infrastructure. Used by Heroku apps, CI workflows, and the console to read secrets from vault.raxx.app.
Migration in progress: Infisical service tokens are deprecated in favor of machine identities. New tokens should be machine-identity tokens; legacy service tokens should be migrated on next rotation cycle. Track legacy tokens in the routing matrix with a "migrate to machine-identity" flag.
https://vault.raxx.app/login via SSO# Confirm current token works (using Infisical CLI)
INFISICAL_TOKEN="$CURRENT_TOKEN" infisical secrets list --projectId="$INFISICAL_PROJECT_ID" --env=prod | head -3
# Expect: a list of secret names (no values needed for this check)
Machine identity (preferred):
1. Navigate to https://vault.raxx.app/.
2. Project → Access Control → Machine Identities.
3. Click Create identity (if creating a new one) or select an existing identity → Auth Configuration → Token Auth → Create token.
4. Configure:
- Name: raxx-prod-rotation-2026-04-24
- Auth method: Token Auth (simplest service-token replacement)
- TTL: 90 days (matches rotation cadence)
- Permissions: scoped to read-only on the project
5. Click Create. Copy the token value immediately.
Legacy service token (deprecated — only use for direct in-place rotation of an existing legacy token, not for new tokens): 1. Project → Access Control → Service Tokens (legacy section, may be hidden behind a deprecation banner). 2. Generate new service token with the same scope as the old one. 3. Copy.
NEW_TOKEN="..."
INFISICAL_TOKEN="$NEW_TOKEN" infisical secrets list --projectId="$INFISICAL_PROJECT_ID" --env=prod | wc -l
# Expect: a count matching step 1.
For machine-identity tokens, also confirm the token's auth method works for the consumer:
# CLI-based check
INFISICAL_TOKEN="$NEW_TOKEN" infisical secrets get HEROKU_API_KEY --projectId="$INFISICAL_PROJECT_ID" --env=prod --plain | head -c 8
# Expect: the first 8 chars of the secret value (sanity that the token can read).
The new Infisical token is itself a secret — but we use Infisical to store secrets. Avoiding circularity:
# Option A: store the new Infisical token in Infisical (works because the OLD token is still valid until step 7)
infisical secrets set INFISICAL_SERVICE_TOKEN="$NEW_TOKEN" \
--projectId="$INFISICAL_PROJECT_ID" --env=prod \
--token="$OLD_TOKEN"
For first-time bootstrap or if no working token exists, the operator stores the token in their secrets manager (1Password, OS keychain) directly.
| Consumer | How |
|---|---|
| Heroku apps (Raptor, console, etc.) | heroku config:set INFISICAL_SERVICE_TOKEN="$NEW_TOKEN" -a <app> |
| GitHub Actions (workflows that pull from Infisical) | gh secret set INFISICAL_SERVICE_TOKEN -b "$NEW_TOKEN" |
| Operator local zshrc | DM via Slack D0AJ7K184TV |
# After dyno restart, the consumer should successfully fetch its other secrets at boot
heroku logs --tail -a raxx-api-prod | grep -iE 'infisical|secret_fetch'
# Expect: successful secret fetch logs, no 401s.
# Test the application's actual workload
curl -sS https://api.raxx.app/health/dependencies | jq '.infisical'
# Expect: {"ok": true}
Machine identity:
1. https://vault.raxx.app/ → Project → Access Control → Machine Identities → old identity → Revoke (or delete the specific token under it, leaving the identity active).
Legacy service token: 1. Project → Access Control → Service Tokens (legacy section) → old token → Delete.
Verify:
INFISICAL_TOKEN="$OLD_TOKEN" infisical secrets list --projectId="$INFISICAL_PROJECT_ID" --env=prod
# Expect: 401 / unauthorized
action: secret.rotate.completed
actor: <admin_id>
context: {
"secret_name": "INFISICAL_SERVICE_TOKEN",
"token_type": "machine-identity" or "service-token-legacy",
"method": "operator-assisted-vault-ui"
}
Until step 7, both old and new tokens are valid. To roll back: 1. Revert Heroku config vars to OLD token (operator may need to recover it from local secret store if Infisical-stored history is unavailable due to bootstrap chicken-and-egg). 2. Restart consumers. 3. Skip step 7. Investigate.
After step 7 (revoke), the old token is dead. Generate a fresh new token — be aware of the bootstrap problem if no other working token exists.
https://vault.raxx.app/vault.raxx.app is down, rotation cannot proceed. Coordinate with vault host runbook (docs/ops/runbooks/vault.md — to be created if absent) before scheduling.infisical login (or unset INFISICAL_TOKEN) to ensure fresh auth on operator workstation.