Advanced config management
Keep API keys out of plaintext, snapshot your setup before risky changes, and distribute a consistent configuration across your team.
Difficulty: Intermediate Duration: 30 minutes What you’ll build: A team-shareable configuration workflow with an encrypted secrets vault, versioned config snapshots, and a one-command onboarding script for new team members
What you’ll learn
- Store API keys in an AES-256-GCM encrypted vault and reference them with
$secret:syntax - Create point-in-time configuration snapshots with SHA-256 integrity verification
- Restore a previous configuration safely, with automatic pre-restore backup
- Export your current settings as a shareable JSON file for team onboarding
- Apply bulk configuration from a file in a single command
Prerequisites
- DojOps 1.1.6 installed (
npm i -g @dojops/cli) - A project initialized with
dojops init - At least one LLM provider API key to practice with
Workshop steps
Step 1: Understand the default storage problem
By default, dojops init stores your API key in ~/.dojops/config.json as plaintext. Open it to see what that looks like:
cat ~/.dojops/config.json{
"provider": "openai",
"providers": {
"openai": {
"apiKey": "sk-proj-abc123yourrealkey..."
}
}
}That key is readable by any process that can read your home directory. If you ever cat this file in a screen share, it leaks. The encrypted vault replaces this pattern entirely.
Step 2: Store a secret in the vault
The dojops secrets set command encrypts your key using AES-256-GCM and writes it to .dojops/secrets.json. The original key is never stored anywhere in plaintext after this point.
dojops secrets set OPENAI_API_KEY sk-proj-abc123...┌ Secret Stored
│
│ Key: OPENAI_API_KEY
│ Encryption: AES-256-GCM
│ Storage: .dojops/secrets.json
│
└ Encrypted and savedThe encryption key is derived from a random key stored at ~/.dojops/vault-key (or from the DOJOPS_VAULT_KEY env var if set). The secrets file alone is useless without the corresponding key.
Now store your other provider keys if you have them:
dojops secrets set ANTHROPIC_API_KEY sk-ant-api03-...
dojops secrets set DEEPSEEK_API_KEY sk-...
dojops secrets set GEMINI_API_KEY AIza...Step 3: Reference secrets in your config
Once a key is in the vault, update your config to reference it by name instead of value. Open ~/.dojops/config.json and change the apiKey fields:
{
"provider": "openai",
"providers": {
"openai": {
"apiKey": "$secret:OPENAI_API_KEY"
},
"anthropic": {
"apiKey": "$secret:ANTHROPIC_API_KEY"
},
"deepseek": {
"apiKey": "$secret:DEEPSEEK_API_KEY"
}
}
}DojOps resolves $secret: references at runtime by looking up the vault. Your config file can now be committed to version control or shared with teammates without exposing any keys.
Verify the resolution works by running a quick provider check:
dojops check provider✔ Provider: openai
✔ Model: gpt-4o
✔ Connection: OKIf the connection succeeds, the vault lookup is working correctly.
Step 4: Inspect what’s stored
List your vault contents at any time. DojOps shows only the key name and a short prefix of the value — enough to confirm you stored the right key without exposing it.
dojops secrets list┌ Encrypted Secrets
│
│ OPENAI_API_KEY set (sk-proj-abc...)
│ ANTHROPIC_API_KEY set (sk-ant-api0...)
│ DEEPSEEK_API_KEY set (sk-...)
│ GEMINI_API_KEY set (AIza...)
│
└ 4 secrets stored in .dojops/secrets.jsonStep 5: Remove a secret
If you rotate an API key or stop using a provider, remove the old secret:
dojops secrets remove DEEPSEEK_API_KEY┌ Secret Removed
│
│ Key: DEEPSEEK_API_KEY
│ Status: deleted from vault
│
└ 3 secrets remainingAfter removal, any config reference pointing to $secret:DEEPSEEK_API_KEY will fail at runtime with a clear error message — which makes broken references easy to catch.
Step 6: Create a configuration snapshot
Before you make any significant change — switching providers, updating model settings, applying team config — take a snapshot. A snapshot is a tar.gz of your entire .dojops/ directory with a SHA-256 checksum to prove integrity.
dojops backup┌ Backup Created
│
│ Snapshot: backup-2026-03-20-143022.tar.gz
│ Location: ~/.dojops/backups/
│ Size: 24 KB
│ SHA-256: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6...
│
│ Contents:
│ config.json
│ vault.enc
│ context.json
│ scan-history/ (3 files)
│ execution-logs/ (7 files)
│ audit-log.jsonl
│
└ Backup verifiedThe SHA-256 hash is written into the archive metadata. When you restore later, DojOps recomputes it and refuses to restore a corrupted or tampered archive.
Step 7: View all snapshots
dojops backup list┌ Backups
│
│ backup-2026-03-20-143022 24 KB just now
│ backup-2026-03-17-091500 18 KB 3 days ago
│ backup-2026-03-10-160000 12 KB 10 days ago
│
└ 3 snapshots (54 KB total) stored in ~/.dojops/backups/Snapshots accumulate over time. You can keep them indefinitely or prune old ones manually — DojOps doesn’t auto-delete them.
Step 8: Apply a team configuration file
Team configs are JSON files that set provider, model, aliases, and scan defaults. Anyone who applies them gets the same behavior as everyone else on the team, regardless of what they had configured before.
Create team-defaults.json:
{
"provider": "openai",
"model": "gpt-4o",
"temperature": 0,
"fallbackProvider": "anthropic",
"aliases": {
"fast": "gpt-4o-mini",
"smart": "gpt-4o",
"review": "claude-sonnet-4-6"
},
"thinking": "medium",
"scan": {
"defaultCategories": ["security", "deps", "iac"],
"jsonOutput": true
}
}Apply it:
dojops config apply team-defaults.json┌ Config Applied
│
│ Applied from: team-defaults.json
│
│ Changes:
│ provider → openai
│ model → gpt-4o
│ temperature → 0
│ fallbackProvider → anthropic
│ aliases → 3 aliases set (fast, smart, review)
│ thinking → medium
│ scan.categories → security, deps, iac
│ scan.jsonOutput → true
│
└ 8 settings updatedNotice temperature: 0. This is intentional for team configs — zero temperature makes output deterministic, which means two people running the same prompt get equivalent results. Use higher temperatures for exploratory work in personal configs.
Step 9: Restore from a snapshot
Something went wrong after applying the team config. Roll back to your pre-change snapshot:
dojops backup restore backup-2026-03-17-091500┌ Restore
│
│ Restoring: backup-2026-03-17-091500
│ SHA-256: verified ✓
│
│ Restored:
│ config.json
│ vault.enc
│ context.json
│ scan-history/ (2 files)
│ execution-logs/ (5 files)
│ audit-log.jsonl
│
│ Current config backed up to:
│ backup-2026-03-20-pre-restore.tar.gz
│
└ Restore completeDojOps automatically creates a backup of your current state before overwriting it. So even if the restoration takes you somewhere wrong, you can restore again from backup-2026-03-20-pre-restore.tar.gz.
Step 10: Build a team onboarding workflow
Put the pieces together into a reproducible onboarding flow. Export your current config as the team standard:
dojops config export > .dojops/team-config.jsonCheck this file into your repository. It contains no secrets — only model names, aliases, and scan defaults. New team members run:
git clone git@github.com:your-org/your-repo.git
cd your-repo
dojops init
dojops secrets set OPENAI_API_KEY sk-proj-... # their own key
dojops config apply .dojops/team-config.json
dojops check providerAfter those four commands, a new team member has the same model, aliases, and scan settings as everyone else. They bring their own API key; you provide the configuration.
Try it yourself
Challenge 1: Create a second JSON config file called local-dev.json that overrides temperature to 0.7 and model to gpt-4o-mini for local experimentation. Apply it, verify the change, then restore from your snapshot.
Challenge 2: Write a shell script that takes a backup, applies team-defaults.json, runs dojops check provider, and on failure automatically restores the previous backup.
Challenge 3: Add a fourth alias called code mapped to your preferred model for code-heavy tasks. Export the config and check whether the alias survives a config apply round-trip.
Troubleshooting
dojops secrets set fails with “encryption key not found”
The vault encryption key is derived on first use and stored in ~/.dojops/.key. If it’s missing, run dojops init to regenerate it. Don’t delete .key — doing so makes all existing vault entries unreadable.
$secret:OPENAI_API_KEY resolves as the literal string at runtime
The $secret: prefix is case-sensitive. Check your config for $Secret: or $SECRET: typos. Also verify the key was actually stored: dojops secrets list.
Restore fails with “SHA-256 mismatch”
The archive was modified after creation. This is either corruption (disk issue) or tampering. DojOps will not restore a mismatched archive. If you need to recover, check ~/.dojops/backups/ for an older snapshot.
config apply silently ignores some fields
Only known config keys are applied. Unrecognized fields are ignored and logged at the debug level. Run dojops config apply team-defaults.json --verbose to see which keys were accepted and which were skipped.
What you learned
Config management in DojOps is built around three habits: encrypt secrets before they touch disk, snapshot before changes, and share configs as files rather than word-of-mouth. The vault uses AES-256-GCM, the same cipher used by professional password managers. Snapshots are portable and integrity-verified, so you can restore with confidence even weeks later. The config apply pattern gives teams a single source of truth for model behavior without requiring everyone to manually recreate settings. Together, these practices eliminate the two most common config problems: leaked API keys and “works on my machine” model differences.
Next steps
- Provider & Configuration — Full provider management guide including fallback logic
- Model Aliases & Thinking Levels — Route tasks to the right model automatically
- Observability & Learning — Build a feedback loop from your execution history