Managing .env Files Across Environments

Managing .env Files Across Environments

21 October 2026 · By Laravel Git · 2 min read

Every Laravel app has the same three-way split: your laptop, a staging server, production. Each needs its own .env, and the .env itself must never be committed - What Not to Commit covers why. What is worth deciding deliberately is how the values get to each environment and how the team learns about new keys.

.env.example is the contract#

Commit .env.example with every key and a safe placeholder value, and treat it as part of every pull request that adds configuration:

MAIL_MAILER=
QUEUE_CONNECTION=
INVOICE_SIGNING_KEY=

A new hire runs cp .env.example .env, fills in the blanks, and the app boots. A reviewer sees the new key in the PR diff without seeing its value. When someone adds a key to their local .env without updating the example, the next person’s setup breaks quietly - so make “PR adds a key to .env.example” as automatic as “PR includes a migration”.

Getting values to servers#

Servers have no checkout step where you can edit a file by hand, so pick a delivery mechanism:

  • The deploy tool’s secrets store (most managed deploy platforms have one).
  • A file written by your deploy script from your password manager or vault - never from the repo.
  • On a self-hosted box you administer: a plain .env in the shared directory of your releases structure, permissions 600, owned by the deploy user.

All three share one property: the value’s home is outside Git, and changing it does not require a commit.

After changing values#

Laravel caches config aggressively in production, so a changed .env does nothing until you rebuild the cache:

php artisan config:cache

Fold that into the deploy script and “I changed it but nothing happened” stops being a genre of bug report. Also restart the queue workers - they hold the old config in memory, same lesson as the deploy post’s queue:restart.

The audit habit#

Once a quarter, diff each environment’s keys against .env.example: keys present on servers but missing from the example are undocumented config, and keys in the example that no environment sets are dead weight. Two minutes with comm on sorted key lists keeps the contract honest.

Secrets stay out of history - and if one ever lands there, A Secret Got Committed. Now What? is the cleanup drill.

Share this post

Our network