.env.vault.local: The Missing Link in Secure Dev WorkflowsIf you’ve been working with modern frameworks (like Remix, Nuxt, or SvelteKit) or secure-by-design platforms (like Doppler or Dotenv Vault), you might have stumbled upon a file that looks like a typo: .env.vault.local.
At first glance, it seems redundant. We have .env.local for local overrides, and .env.vault for encrypted secrets. Why combine them?
Let’s break down what this file is, why it exists, and how it can save your team from the dreaded "It works on my machine" syndrome.
.env.vault.local?At its core, .env.vault.local is a machine-specific, encrypted secrets vault file. It is a sibling to the standard .env.vault file. .env.vault.local
To understand it, let’s break down the naming convention:
.env : The standard file containing key/value pairs (e.g., DATABASE_URL=postgres://...)..vault : Indicates that the file is encrypted. You cannot read its contents without a decryption key..local : Signifies that this file is specific to your local development machine..env.vault.local) : An encrypted vault for your local-only environment variables that should never leave your workstation.While the standard .env.vault file is designed to be safely committed to Git (yes, committed, because it’s encrypted), the .env.vault.local file is explicitly designed to stay out of version control. It is the entry in your .gitignore that protects your personal development secrets.
How many times has a bug been caused by a missing STRIPE_SECRET_KEY on a colleague's laptop? Traditional .env files require manual sharing via Slack, email, or USB drives. .env.vault.local automates this by syncing encrypted secrets via a central service (like Dotenv Vault), but still allows you to override them with local-only values (e.g., a local database vs. a staging database). Demystifying
Here's an example of what .env.vault.local might look like:
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=myuser
DB_PASSWORD=mypassword
API_KEY=myapikey
In this example, the .env.vault.local file stores sensitive environment variables for a local database and API key.
While the contents are encrypted, the metadata is often plaintext. A typical .env.vault or .env.vault.local file looks like this: While the standard
# .env.vault.local
DOTENV_VAULT_PRODUCTION="YOUR_ENCRYPTED_STRING_HERE"
DOTENV_VAULT_CI="ANOTHER_ENCRYPTED_STRING"
DOTENV_VAULT_DEVELOPMENT="MORE_ENCRYPTED_DATA"
DOTENV_VAULT_LOCAL="ENCRYPTED_LOCAL_ONLY_VALUES"
The Decryption Key (DOTENV_KEY)
The actual secrets are unlocked using a DOTENV_KEY. This key is never stored in the vault file. Instead, it is set as an environment variable on your local machine or CI server.
DEVELOPMENT environment, you use a DOTENV_KEY for development.LOCAL environment, you use a DOTENV_KEY for local..env.vault.local FileUnlike a standard .env file, this file does not contain plaintext. It contains a JSON structure with encrypted blobs.
Example .env.vault.local content:
"DOTENV_VAULT_SIG": "12345abcde",
"DOTENV_VAULT_DECRYPTION_KEY": "none",
"development":
"ciphertext": "U2FsdGVkX1/abcdefghijklmnop...",
"iv": "e3b0c44298fc1c14",
"tag": "c1c14e3b0c44298f"
,
"production":
"ciphertext": "U2FsdGVkX1/zxywvutsrqponmlk..."
You don't write this by hand. You generate it via CLI tools:
npx dotenv-vault local push # Encrypt and push local overrides to .env.vault.local