← Back to Blog

How to Share .env Files With New Developers (Without Committing Them to Git)

A new engineer starts Monday. To get the app running locally, they need API keys for three SaaS vendors, a database password, and a dev-only Stripe key. The lazy path is "I will just email them my .env" — and that is how teams end up with seven former engineers still possessing live credentials six months after they left. Here is the actual secure onboarding workflow.

Why Emailing .env Is Worse Than You Think

When you email a .env file, you create several overlapping problems:

  • Persistence. Email sits in inboxes, Sent folders, backup systems, mobile device caches, and archive servers indefinitely.
  • No audit. You have no record of who accessed the secrets after the initial receipt.
  • No revocation. If the engineer leaves, turns their laptop in, or gets compromised, you cannot revoke the file — only the underlying credentials, and only if you rotate them all.
  • Plaintext in transit. Email TLS is not end-to-end. Your mail provider, their mail provider, and anything in between can decrypt it.
  • Phishing amplification. If someone ever impersonates you and asks for that .env again, the precedent makes the new hire comply.

Our companion post on what happens when a .env file leaks covers the downstream impact in detail.

Three Workflows, Ranked

From best to acceptable:

Tier 1: Per-Developer Vault Entries

The gold standard. Each engineer has their own set of credentials in a team vault, provisioned at onboarding and revoked at offboarding — nobody shares a single .env.

Tools that do this well:

  • Doppler — developer-friendly, CLI-first, free tier available
  • Infisical — open source, self-hosted or managed
  • 1Password Developer Tools — integrates with op run to inject secrets at runtime
  • HashiCorp Vault — enterprise-grade, supports dynamic secrets that auto-expire

Developer workflow example with Doppler:

# Onboarding: invite user to project, assign role
doppler invite usman@example.com --project api --role dev

# Developer runs the app without ever touching .env
doppler run -- npm run dev

The secrets never hit disk. When the engineer leaves, revoking their vault access instantly cuts off all credentials — no hunt-and-peck across .env files.

Tier 2: Encrypted, Expiring Links

When Tier 1 is not practical (contractor, short-lived project, legacy app that insists on reading from .env), use a zero-knowledge encrypted paste with a short TTL.

Requirements:

  • Client-side encryption — the service never sees the plaintext
  • Expiration — 1–24 hours is typical; do not default to "never"
  • Burn-after-read — the link 404s after first retrieval, preventing re-use
  • Optional password — an extra factor delivered through a different channel
  • Audit log — you know who opened it and when

Workflow:

  1. Generate a fresh dev-only .env with credentials specific to this engineer (not your personal keys).
  2. Upload to an encrypted paste tool with a 4-hour TTL and burn-after-read enabled.
  3. Send the URL via your normal secure channel (Slack DM is okay for the URL because the URL alone is useless without the decryption key in the fragment).
  4. If using a password, send the password through a different channel (SMS, call, in-person).
  5. Confirm retrieval with the engineer — once they have loaded it into their vault/password manager, the work is done.

Send .env Files With Encrypted, Expiring Links

SecureBin creates zero-knowledge pastes with client-side AES-256 encryption, burn-after-read, and TTL control. The server never sees your secrets. Free, no signup.

Send Secrets Securely

Tier 3: Dynamic Secrets (Vault Dev Mode)

For teams already running HashiCorp Vault or similar, you can skip the sharing problem entirely. Configure dynamic secrets so each developer's environment generates its own short-lived credentials on startup:

# App startup pulls credentials from Vault with a 1-hour lease
vault kv get -format=json secret/dev/payments | jq .data.data > .env.runtime
# .env.runtime is gitignored and rotates every hour

The engineer never holds a long-lived credential. When their session ends, the credential dies.

The Correct Onboarding Checklist

Put this in your internal runbook:

  1. Create scoped credentials — per-environment, per-developer where possible. Do not reuse production keys in dev.
  2. Add them to the team vault with role-based access for the new hire.
  3. If vault is not an option, generate a fresh .env scoped to this engineer. Never send them your personal .env.
  4. Verify .gitignore includes .env, .env.local, .env.*.local on the repo they will clone.
  5. Send via zero-knowledge, TTL-bound, burn-after-read link. Never email.
  6. Confirm retrieval and that the app runs locally.
  7. Document in an internal ticket: who was onboarded, what was shared, when the link expired.
  8. Add the new hire to your offboarding checklist right now, while you are already in the system.

Revoking Access When the Engineer Leaves

The payoff for doing onboarding right is that offboarding is trivial. The difference:

Wrong way (emailed .env): you must rotate every credential the engineer ever received, across every project, because you have no idea which ones they still have. Realistically, most teams never finish this — they just wait and hope.

Right way (vault + scoped creds): revoke the engineer's vault access. Rotate anything that was flagged during exit interview as "this engineer had direct contact with." Done in 30 minutes, documented in the offboarding ticket.

Our credential sharing policy template covers the offboarding checklist in full.

What Should Be in a Dev .env Anyway?

Cleanse before you share. A dev .env should contain:

  • Test-mode keys for external services (Stripe test keys, Twilio test credentials, etc.) — never live mode
  • Dev database credentials pointing to a local or isolated dev DB, never production
  • OAuth client IDs for dev-only applications (separate apps registered in Google/GitHub/etc. for dev use)
  • Feature flags and local config

It should NEVER contain:

  • Production database URLs
  • Live-mode API keys for billing or payment processors
  • Cloud provider root access keys
  • Anything that could cause customer-visible impact if misused

If your dev .env needs production credentials to function, that is a sign of an architectural problem — your dev environment is too entangled with production.

Common Mistakes

1. Sharing your personal .env. Your file accumulates credentials over years of work. Generate a fresh one for each hire.

2. Using Slack DMs or attachments for the file itself. Slack retention varies by plan but is effectively permanent on most paid tiers.

3. Using git submodules or private repos to "store" the .env. You are just moving the problem. Git history is searchable, and leaked repo access = leaked secrets forever.

4. Putting secrets in environment-specific config files (like config.dev.yml) that do get committed. Even if they are "dev", that is still a credential in git history.

5. Not rotating on offboarding. "We will rotate if there is a problem" is reactive security. Anything the engineer had direct contact with rotates on exit, mandatory.

6. Sharing the decryption password in the same channel as the link. If you are using a password-protected paste, deliver the password out of band. SMS, phone call, in-person. Not the same Slack DM.

Frequently Asked Questions

What if the app absolutely requires a physical .env file on disk?

Use a secret manager CLI that writes the file just-in-time: Doppler's doppler run, 1Password's op run, or AWS Secrets Manager with a script. The file can live in tmpfs so it does not persist after reboot.

How do I prevent developers from committing .env accidentally?

Three layers: .gitignore entry, pre-commit hook with gitleaks, and repo-wide secret scanning (GitHub Secret Scanning or GitLab's equivalent). See our guide on detecting secrets in GitHub repositories.

Can I just use Bitwarden or LastPass for this?

Password managers work for individual credential sharing but are awkward for full .env files. Team-focused tools (1Password Developer, Doppler, Infisical) integrate better with local development workflows.

What about environment variables set in the shell profile?

Same rule: scoped per developer, not shared. Better: load from a vault at shell startup, not static export lines in .zshrc.

Is it okay to commit a sample .env.example file?

Yes, strongly encouraged. Commit an .env.example with variable names and empty or obviously-fake values so new engineers know what they need. Just never commit the real .env.

How often should dev credentials be rotated?

Quarterly at minimum, plus immediately on any offboarding. Some teams automate this by using dynamic secrets with 24-hour leases, eliminating the rotation question entirely.

Key Takeaways

  • Never email .env files. Emails live forever and cannot be revoked.
  • Prefer a team vault (Doppler, Infisical, 1Password Developer, Vault) over file-based sharing.
  • When file sharing is needed, use a zero-knowledge, TTL-bound, burn-after-read link.
  • Scope dev credentials per engineer and rotate on every offboarding.
  • Never put production credentials in a dev .env.
  • Commit .env.example, never the real .env.

Related reading: What Happens When a .env File Leaks, The Danger of Exposed .env Files, Credential Sharing Policy Template, Secrets Management for DevOps Teams, Prevent Secrets Leaks in CI/CD Logs.

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.