Where should I store .env files securely?
The honest answer is: the least risky place is often “not in your repository at all” — while still letting your runtime read configuration the Twelve-Factor way (config in the environment). This guide maps where .env belongs on a developer machine, when it is acceptable, and what to use instead for high-value secrets on macOS.
1. Hook: the repo folder feels “private”
Your project lives in ~/Projects/acme/api/. You create .env next to package.json because every tutorial says so. Over months:
- The folder gets zipped for a contractor.
- Time Machine backs up the whole tree.
- Someone runs
git add .under pressure.
The file was never “public,” but it was copied more often than you think. For how leaks happen in practice, read Why your .env setup is probably leaking.
2. What “secure” means here (threat model)
| Threat | Is .env in the project folder OK? | Better pattern |
|---|---|---|
| Accidental Git commit | Risky — history is forever | .gitignore + templates + keep secrets out of Git |
| Backup / sync copying the repo | Risky | Exclude secrets or use OS-backed store |
| Malware on an unlocked Mac | Weak — plaintext is easy to read | Assume breach; minimize lifetime & scope |
| Lost laptop (powered off) | Better if FileVault on | Full-disk encryption + strong login password |
| Shoulder surfing | OK with screen privacy | Not a storage-layer problem |
OWASP’s Secrets Management Cheat Sheet is clear: do not embed secrets in source and encrypt secrets at rest when stored.
3. Recommended locations (ranked)
Option A — Canonical secrets in a local vault, .env only as a session export (strongest for laptops)
- Store real values in an encrypted, macOS-native vault with optional Keychain backing — e.g. PassStore (Security overview).
- When you start work, copy or export into a gitignored
.envorexportin a dedicated terminal tab you close afterward.
Why: the source of truth is not a long-lived plaintext file sitting next to src/ for months.
Option B — .env in the project directory, strictly gitignored (common, acceptable with eyes open)
Path example:
~/Projects/acme/api/.env # gitignored, never committed
Requirements:
- Verified ignore rules (see below).
- No cloud sync folder (Dropbox/iCloud) wrapping the repo root without exclusions.
- Rotation after any doubt.
Verify Git is not tracking secrets:
cd ~/Projects/acme/api
git check-ignore -v .env || echo "WARNING: .env is NOT ignored"
git ls-files --error-unmatch .env 2>/dev/null && echo "WARNING: .env is tracked" || true
Option C — Outside the repo tree (reduces “zip the project” leaks)
Example:
~/.config/acme/api.env
Point your tooling at it explicitly (Compose env_file, custom loader script, or symlink only if you understand symlink + backup implications).
Option D — Team / cloud secret manager for shared non-prod (when policy requires)
Doppler, Vault, cloud vendor stores — see Local-first vs cloud secret managers. This is not “where .env lives” but replaces ad-hoc file sharing.
4. .gitignore baseline (copy-paste)
# Secrets — never commit
.env
.env.*
!.env.example
!.env.sample
!.env.template
# Local overrides
*.local.env
env.local
credentials.json
secrets.yml
Pair with a committed .env.example — placeholders only:
# .env.example (safe to commit)
DATABASE_URL=postgresql://USER:PASSWORD@localhost:5432/myapp_dev
API_KEY=replace_me_in_your_local_env
5. Docker and Compose
Keep docker-compose.yml in Git; keep .env out:
services:
api:
env_file:
- .env
Document every required key in README.md. For production, use orchestrator secrets, not a file in the image — see Docker secrets overview for Swarm; Kubernetes uses Secret objects.
6. Best way to manage environment variables locally (habits)
- One mental map: “This workspace = this product” — mirror that in your vault; see organize secrets across multiple projects.
- Separate dev / staging / prod-like groups so you do not paste prod URLs into a dev shell — multiple
.envfiles. - Never put server secrets in
NEXT_PUBLIC_*orVITE_*— prevent API keys leaking in frontend apps.
7. macOS-specific hardening
- Enable FileVault (full-disk encryption).
- Use a strong login password and short screen lock delay.
- Prefer Keychain-backed storage for long-lived dev tokens — macOS Keychain for developers.
8. Soft CTA
If you want one encrypted place on your Mac for developer secrets, with workspace grouping and Keychain integration options, try PassStore — download and read is it safe to store secrets in .env files? for a direct yes/no breakdown.