Why I stopped using .env files for secrets (mostly)

I did not stop because .env is evil. I stopped because I am human — and .env files are too easy to duplicate, too easy to commit under stress, and too easy to open in the wrong screen share.

This is a workflow article: the engineering justification is in why .env leaks and is .env safe?.


1. The near-miss that stuck

The pattern: Friday deploy, someone runs git add ., and .env was newly created in a subdirectory not covered by the root ignore rule. CI did not catch it; GitHub push protection did — once. The other time, it was git log archaeology and rotation at 22:00.

After that, “gitignored” stopped feeling like a guarantee.


2. Backup sprawl is silent

Time Machine does not care about your security policy. Neither does zip -r handoff.zip ./project. A plaintext .env in the tree means every backup of that folder is a secret backup.


3. Wrong terminal, wrong DATABASE_URL

With one mega env file, tab three might still export staging while you think you are on local. The failure mode is subtle data corruption, not a dramatic hack.

Structured workspace grouping fixed the cognitive bug for me — organize across projects.


4. What I do instead (hybrid)

  1. Canonical secrets live in PassStore on my Mac — per-repo workspaces, Keychain options (Security).
  2. When a tool requires a file, I generate a gitignored .env for the session or export in one terminal tab I close after work.
  3. Runtime still uses environment variables — I did not abandon 12-factor; I changed storage.

5. When I still use .env files

  • Ephemeral local-only sandboxes I can delete.
  • CI-generated files that never touch my disk on laptop.
  • Docker compose dev flows where compose expects env_file — file is short-lived and scoped.

6. Soft CTA

If your story rhymes with mine, try PassStore — download and read stop storing secrets in .env files for a more prescriptive take.


Related