-
Notifications
You must be signed in to change notification settings - Fork 1
Key Rotation
Procedures for rotating all credentials associated with a strut stack — SSH keys, API keys, database passwords, GitHub secrets, and environment variables.
| Category | Storage | CLI Prefix | Affects |
|---|---|---|---|
| SSH keys | VPS authorized_keys + keys/ssh-keys.json
|
keys ssh:* |
VPS access, CI/CD |
| API keys |
.env SEMANTIC_API_KEYS + keys/api-keys.json
|
keys api:* |
External consumers |
| Database passwords |
.env + live DB |
keys db:rotate |
All services |
| GitHub secrets | GitHub repo secrets | keys github:* |
CI/CD pipelines |
| Env var secrets |
.env file |
keys env:* |
All services |
The keys/ directory in each stack stores metadata only (fingerprints, masked values, dates) — never actual secrets.
# Inventory all tracked keys
strut my-stack keys inventory --env prod
# Discover secrets (local + VPS + GitHub)
strut my-stack keys discover --env prod
# Validate env file completeness
strut my-stack keys env:validate --env prod
# Audit SSH keys
strut my-stack keys ssh:audit --env prodWork through each step in order — database passwords require a redeploy, so batch changes.
strut my-stack keys env:backup --env prod
strut my-stack backup all --env prodstrut my-stack keys ssh:rotate <username> --env prod
strut my-stack keys ssh:audit --env prod
# Push new VPS deploy key to repos
strut my-stack keys github:rotate-vps-key \
--repos "org/repo1,org/repo2,org/repo3"strut my-stack keys db:rotate postgres --env prod
strut my-stack keys db:rotate neo4j --env prod
# Redeploy immediately (services need new passwords)
strut my-stack deploy --env prod
strut my-stack health --env prod# Auto-rotatable secrets
strut my-stack keys env:rotate --env prod
# Third-party keys (rotate in external service first, then update)
strut my-stack keys env:set MISTRAL_API_KEY "new-key" --env prod
strut my-stack keys env:set GH_PAT "ghp_new..." --env prodstrut my-stack keys api:list
strut my-stack keys api:rotate <key-name>while IFS= read -r repo; do
[[ "$repo" =~ ^# ]] && continue
[[ -z "$repo" ]] && continue
strut my-stack keys github:sync --repo "$repo" --from .prod.env
done < stacks/my-stack/repos.confstrut my-stack keys env:validate --env prod
strut my-stack keys env:diff --local .prod.env --remote --env prod
strut my-stack health --env prod --json
strut my-stack keys ssh:audit --env prodFor new stacks or CI pipeline setup, use the dedicated commands to generate a deploy keypair and push all required secrets to your CI provider in one step.
strut my-stack ssh:keygen --name ci --env prodThis will:
- Generate an ED25519 keypair named
ci(stored locally at~/.ssh/strut_<host>_ciand~/.ssh/strut_<host>_ci.pub) - Append the public key to the VPS host's
authorized_keys - Display the key fingerprint for verification
The --name flag lets you maintain multiple deploy keys per stack (e.g. ci, backup-agent, monitoring).
strut my-stack ci:init --provider github --env prodThis reads the stack's required_vars, the generated deploy key, and host connection details, then pushes them as repository secrets (or environment secrets) to the specified provider. Supported providers:
| Provider | Secrets Target |
|---|---|
github |
GitHub Actions repository secrets (via gh CLI) — default |
gitlab |
GitLab CI/CD variables (via glab CLI) |
manual |
Prints the secrets for manual entry (no provider write) |
Use --dry-run to preview without writing:
strut my-stack ci:init --dry-run --env prodOutput shows each secret name and its source (env file, generated key, topology) without exposing values.
# 1. Generate the deploy keypair
strut my-stack ssh:keygen --name ci --env prod
# 2. Preview what ci:init would set
strut my-stack ci:init --provider github --dry-run --env prod
# 3. Push secrets to GitHub Actions
strut my-stack ci:init --provider github --env prod
# 4. Verify the pipeline can connect
# (trigger a CI run or use `strut my-stack keys ssh:audit`)
strut my-stack keys ssh:audit --env prodWhen rotating SSH keys (Step 2 above), you can regenerate the CI deploy key and re-run ci:init to update the provider in one pass:
strut my-stack ssh:keygen --name ci --env prod
strut my-stack ci:init --provider github --env prodThis replaces the manual loop over keys github:sync for the CI-specific keypair.
Rotate Docker registry pull tokens (e.g. GitHub Container Registry PATs) across all VPS hosts in one pass.
strut my-stack keys rotate-registry --registry ghcr.io --env prodThis will:
- Prompt for the new token (input hidden, never logged)
- Deliver it to each configured host via
docker login --password-stdin - Record rotation metadata in
keys/registry-credentials.json
Options:
-
--hosts h1,h2— target specific hosts (default: all from VPS_HOST) -
--username <user>— registry username (default: GHCR_USER from env) -
--revoke-old— print guidance for revoking the old PAT after rotation -
--dry-run— preview without executing
strut my-stack keys registry-status --env prod
strut my-stack keys registry-status --jsonShows per-host: reachability, login state (from ~/.docker/config.json), last rotation date, and username.
# 1. Generate a new fine-grained PAT in GitHub UI
# 2. Rotate credentials across all hosts
strut my-stack keys rotate-registry --env prod
# 3. Verify
strut my-stack keys registry-status --env prod
# 4. Revoke old PAT in GitHub settings
# (strut prints the URL with --revoke-old)| Secret Type | Interval | Also Rotate On |
|---|---|---|
| SSH keys | 90 days | Team member departure |
GH_PAT |
90 days | GitHub expiry warning |
| Database passwords | 90 days | Suspected breach |
| API keys | 90 days | Consumer offboarding |
| Third-party API keys | Per provider | Suspected exposure |
Audit log: stacks/<stack>/keys/key-audit.log
strut my-stack logs --tail 100 --env prod
# Most common: services didn't pick up new DB password → redeploy
strut my-stack deploy --env prodstrut my-stack keys ssh:audit --env prod
ssh -i ~/.ssh/strut-<stack>-vps ubuntu@<VPS_HOST> "echo ok"# Restore from backup
ls .env.backup-*
cp .env.backup-YYYYMMDD-HHMMSS .prod.env
strut my-stack deploy --env prodstrut · v0.28.0 · Report an Issue
Getting Started
Core Concepts
Operations
- Deployment
- Ship and Rebuild
- GitHub Action
- Webhook Automation
- Remote Host Setup
- Provisioning
- Blue-Green Deploy
- Deploy Rollback
- Database Backups
- Secrets Management
- Stack Groups
- Lifecycle Hooks
- Notifications
- Key Rotation
- Drift Detection
- Domain and SSL
- Certificate Management
- Gateway Management
- Monitoring
- Volume Management
Advanced
- Security Posture
- VPS Audit and Migration
- Stack Validation
- Data Anonymization
- Debugging
- Local Development
Extending
Contributing