13.2 Environment setup: local dev, env vars, secrets
Overview and links for this section of the guide.
On this page
- Goal: a repeatable local dev environment
- Principles: reproducible, minimal, safe
- The environment model (dev vs staging vs prod)
- Environment variables (the right mental model)
- Using
.envand.env.example - Secrets hygiene (non-negotiable rules)
- Rotation and incident response (assume leaks)
- Local runtime setup (practical commands)
- Config layering pattern (no spaghetti config)
- Checklists you can reuse
- Where to go next
Goal: a repeatable local dev environment
Your project is not “exported” until another person (or future-you) can run it from a clean machine with predictable steps.
This page helps you set up:
- a clean local dev loop,
- environment variables for configuration,
- secrets hygiene that prevents accidental leaks,
- a config structure that won’t turn into spaghetti.
Good env setup keeps iteration fast: fewer “works on my machine” failures, fewer broken sessions, fewer weird auth issues.
Principles: reproducible, minimal, safe
- Reproducible: one README path to run and test.
- Minimal: the smallest set of environment variables required.
- Safe: secrets never appear in prompts, code, or logs.
Most “environment issues” are really “missing documentation” or “hidden secrets” issues.
The environment model (dev vs staging vs prod)
Even if you’re solo, think in environments:
- dev: local machine; fast iteration; verbose logs; lower risk.
- staging: a pre-production environment; realistic configs; safer debug controls.
- prod: real users; strict security; minimal logging; reliable behavior.
Many incidents happen because “dev settings” silently ship to prod (or prod secrets leak into dev prompts).
Even a single variable like APP_ENV=dev|staging|prod helps you reason about safety, logging, and behavior.
Environment variables (the right mental model)
Environment variables are a way to configure behavior without hardcoding it into source code. For AI apps, env vars typically include:
- model provider credentials (API keys or project creds),
- model name,
- timeouts and retry limits,
- prompt version selection,
- feature flags for experiments.
Practical rule
If a value changes between machines or environments, it belongs in configuration, not in code.
Hardcoded keys will leak. It’s not “if,” it’s “when.” Use env vars or a secret manager.
Using .env and .env.example
A common, practical pattern:
.env: local machine only (ignored by git), contains real values..env.example: committed, contains variable names and safe placeholders.
Example .env.example
# Environment
APP_ENV=dev
# Model settings (example names)
MODEL_NAME=...
MODEL_TEMPERATURE=0.2
MODEL_TIMEOUT_MS=30000
MODEL_MAX_RETRIES=3
# Credentials (do not commit real values)
GOOGLE_API_KEY=REDACTED
This pattern makes onboarding easy without leaking secrets.
Use names that tell you what they control: MODEL_TIMEOUT_MS is clearer than TIMEOUT.
Secrets hygiene (non-negotiable rules)
These rules prevent most early leaks:
- No secrets in prompts: never paste keys into AI Studio conversations.
- No secrets in git: ignore
.env, credentials files, and local config. - No secrets in logs: redact or avoid logging raw headers/payloads.
- Least privilege: keys should be scoped to minimal permissions.
- Separate dev/prod: different credentials per environment.
Prompts are often stored, exported, or shared. Even if you trust the platform, you’re building a habit—make it a safe one.
Rotation and incident response (assume leaks)
Plan for leaks by making rotation boring:
- store secrets in one place (env vars or secret manager),
- avoid copying keys into multiple configs,
- keep keys environment-specific,
- be able to revoke/rotate without code changes.
If you suspect a leak:
- revoke/rotate the secret,
- search git history and logs for exposure,
- invalidate any derived credentials,
- add guardrails (pre-commit checks, secret scanning) to prevent repeats.
Local runtime setup (practical commands)
These are common patterns; adapt to your stack.
Python (example)
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python -m pytest
Node.js (example)
npm install
npm test
npm run dev
If your project requires 12 environment variables to start, you’ve increased friction and failure surface. Start with the minimum and add only when necessary.
Config layering pattern (no spaghetti config)
A simple layering pattern prevents config chaos:
- Defaults in code: safe, non-secret defaults (timeouts, retry caps).
- Overrides via env vars: environment-specific values.
- Secrets via env vars / secret manager: credentials and sensitive settings.
Make config loading a single module (e.g., config.py or config.ts) so the rest of your code imports a typed config object instead of reading env vars everywhere.
Read env vars once at startup. Everywhere else, use a config object.
Checklists you can reuse
Export environment checklist
- README includes run/test commands.
.envis gitignored;.env.exampleis committed.- Secrets are not in code, prompts, or logs.
- Config is loaded in one place and passed through the app.
- Dev/prod credentials are separated.
Secrets checklist
- No secrets in prompts.
- No secrets in git history.
- Rotation path exists (revoke + replace).
- Least privilege enforced.