Environment and Secrets Management Across Deployment Targets
Agent deployments fail loudly when keys are missing and fail expensively when keys leak or are shared without caps.
Use this cheatsheet to keep config, secrets, and environments consistent across laptop, serverless, containers, and VPS.
How to Use This Cheatsheet
- Treat every row as a gate before promoting a release.
- Separate non-secret config (model slug, log level) from secrets (API keys, DB passwords).
- Prefer one naming scheme (
AGENT_MODEL,OPENROUTER_API_KEY) across all hosts. - Re-audit after adding a new tool that needs credentials.
A - Secret Classes
| Class | Examples | Handling |
|---|---|---|
| Model provider keys | OpenRouter, OpenAI, Anthropic | Secret store; per-env keys; spend caps |
| Tool credentials | GitHub PAT, Slack bot, Stripe | Least privilege; scoped to tool identity |
| Data stores | DB URL, Redis URL | Secret; rotate with app deploy |
| Signing / session | JWT secret, webhook HMAC | Secret; never log |
| Non-secret config | AGENT_MODEL, LOG_LEVEL, PORT | Plain env or config map OK |
B - Injection by Target
| Target | Prefer | Avoid |
|---|---|---|
| Local dev | .env (gitignored) + direnv/dotenv | Committing .env |
| Docker CLI | -e, --env-file, orchestrator secrets | ENV KEY=secret in Dockerfile |
| Compose | ${VAR} from host env or secrets | Hard-coded keys in compose committed files |
| Vercel | Project env (Production / Preview / Development) | Same key for preview + prod |
| AWS Lambda | Function env + Secrets Manager/SSM | Long-lived keys when IAM role works |
| Kubernetes | Secret → env or volume mount | Base64 Secrets without encryption at rest / RBAC |
| VPS systemd | EnvironmentFile= mode 600 | World-readable unit drop-ins with keys |
| CI | OIDC to cloud / short-lived tokens | Long-lived cloud keys in plain CI vars when avoidable |
C - Environment Matrix
| Variable | Local | Preview/Staging | Production |
|---|---|---|---|
OPENROUTER_API_KEY | Dev-capped key | Staging key | Prod key |
AGENT_MODEL | Cheap default | Prod-like | Prod pin |
LOG_LEVEL | debug | info | info/warn |
ENV / APP_ENV | development | staging | production |
| Tool write credentials | Mock or sandbox | Sandbox | Prod least privilege |
Never let staging share production write credentials "for convenience."
D - Naming and Loading Pattern
# pattern: explicit required secrets in production
import os
def require(name: str) -> str:
val = os.environ.get(name)
if not val:
raise RuntimeError(f"missing required env: {name}")
return val
ENV = os.environ.get("APP_ENV", "development")
MODEL = os.environ.get("AGENT_MODEL", "openai/gpt-4o-mini") # verify at build
API_KEY = require("OPENROUTER_API_KEY") if ENV == "production" else os.environ.get("OPENROUTER_API_KEY", "")| Rule | Detail |
|---|---|
| Prefix consistently | AGENT_* for app, provider-native names when SDKs expect them |
| Fail fast in prod | Missing key → non-zero exit before serving traffic |
| Never log secrets | Redact Authorization headers and connection strings |
| Document defaults | README or ops runbook lists every var |
E - Rotation and Blast Radius
| Control | Checklist |
|---|---|
| Per-environment keys | [ ] Dev / CI / staging / prod isolated |
| Per-agent keys | [ ] High-risk tools use separate credentials |
| Spend caps | [ ] Provider and internal budgets set |
| Rotation drill | [ ] Can replace a key without redeploying code images (config-only roll) |
| Leak response | [ ] Disable key, rotate, review logs, open incident |
| Git history | [ ] Secret scanners on CI; rewrite if committed |
Pair with Scoping API Keys and Credentials Passed to an Agent.
F - What Must Never Be in the Image or Repo
.envwith real keys- Private keys and kubeconfigs
- Customer tokens dumped into prompts/logs
- "Temporary" prod keys in PR previews
- Dockerfile
ENV OPENROUTER_API_KEY=sk-...
# .dockerignore / .gitignore essentials
.env
.env.*
!.env.example
*.pemShip .env.example with empty or fake values only.
G - Quick Verification Commands
# Fail if a secret pattern is tracked (illustrative)
git grep -nE 'sk-or-|sk-ant-|AKIA' && echo "possible secret" && exit 1 || true
# Container should not contain .env
docker run --rm your-image:tag ls -la /app | grep -i env && exit 1 || true
# Runtime sees key without printing it
docker run --rm -e OPENROUTER_API_KEY your-image:tag \
python -c "import os; assert os.getenv('OPENROUTER_API_KEY'); print('key present')"H - Cross-Target Consistency Checklist
- Same variable names on every host
- Separate secrets per environment
- Non-secret config documented and defaulted safely
- Production fails closed without secrets
- Preview/staging cannot call prod-only side effects
- CI uses short-lived credentials where possible
- Rotation runbook exists and was tested once
- Agents never receive blanket cloud admin credentials
- Tool credentials scoped to least privilege
- Logs/metrics redaction verified with a test event
FAQs
Is putting secrets in env vars safe enough?
Env vars are standard but visible to the process and sometimes to platform UIs/logs. Combine with RBAC, short-lived credentials, and never print them. Some teams prefer file mounts with tighter permissions.
Should model names be secrets?
No. Treat model slugs as config. Still pin and change them deliberately for cost/quality.
How do I share config with contractors?
Staging keys only, capped spend, no prod data. Prefer time-limited access.
Can I inject secrets at build time for faster cold starts?
Do not bake secrets into build artifacts. Cold-start gains are not worth permanent key leakage in image layers.
What about client-side keys in web agents?
Browser-exposed keys are public. Use server-side routes or provider proxies; never ship provider master keys to the client.
How often should we rotate?
On leak immediately; otherwise on a schedule your threat model requires (many teams: 90 days or on role change). Automate where the platform allows.
Do orchestrator "sealed secrets" replace discipline?
They help encryption and distribution. You still need naming, least privilege, and rotation process.
Where does this meet production security review?
Use Security Checklist Before Shipping an Agent to Production alongside this page.
Related
Related: Deploying Agents Basics
Related: Containerizing an Agent with Docker
Related: Deploying an Agent to Vercel or AWS Lambda Serverless Functions
Related: Long-Running Agents on a VPS: Process Management and Restarts
Related: Deploying Agents Best Practices
Related: Scoping API Keys and Credentials Passed to an Agent
Related: Security Checklist Before Shipping an Agent to Production
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.