Your .env file,
but it's a vault.
Drop-in replacement for dotenv. One key in your environment, everything else encrypted remotely. AES-256-GCM. Per-device secrets. Hot reload. Zero config migration.
Three steps. No config files.
If you know dotenv, you know vault-env. The migration takes about 90 seconds.
Replace one import
Swap load_dotenv() for load_vault(). Same API, same behavior. Your code doesn't change.
# Before from dotenv import load_dotenv load_dotenv() # After from vaultdotenv import load_vault load_vault()
Push your secrets
Your existing .env gets encrypted with AES-256-GCM and stored remotely. The .env file becomes a single VAULT_KEY.
$ vault-env push Encrypting 14 secrets... Pushed to production (v1) $ cat .env VAULT_KEY=vk_proj123_a1b2c3...
Deploy with one key
Set VAULT_KEY in your environment. Secrets are pulled and decrypted at boot. Each device gets its own encryption layer.
$ vault-env register-device Device "web-01" registered. Secret saved to ~/.vault/proj123.key # That's it. App boots, secrets load.
Watch for changes
Rotate a key, update a connection string — running processes pick up the change in seconds. No redeploy, no restart.
import vaultdotenv
vaultdotenv.load_vault()
vaultdotenv.watch(
interval=30,
on_change=lambda changed, all:
print("Rotated:", list(changed.keys())),
)Security without the ceremony
Everything you need to stop committing secrets. Nothing you don't.
AES-256-GCM encryption
Secrets are encrypted before they leave your machine. The vault server never sees plaintext.
Per-device secrets
Each machine gets a unique device key. Revoke a laptop without rotating every secret.
HMAC-signed requests
Every API call is signed with a time-stamped HMAC. No bearer tokens flying around.
Hot reload
Change a secret in the dashboard, it propagates to running processes. No redeploys.
Encrypted cache
Secrets are cached locally with AES-256-GCM. If the vault is unreachable, your app still boots.
Zero config migration
Run vault-env push. Your .env becomes a VAULT_KEY. That's the entire migration.
Change a secret.
Skip the redeploy.
vault-env watches for changes and updates process.env in-place. Rotate an API key from the dashboard and every running process picks it up within seconds. No restart, no downtime.
- Lightweight polling — only checks a version number, no secrets transferred until something changes
- onChange callback with the diff — reconnect databases, refresh tokens, whatever you need
- Background thread (Python) or unref'd timer (Node.js) — won't keep your process alive
const vault = require('vault-env');
await vault.config();
vault.watch({
interval: 30000,
onChange(changed, allSecrets) {
console.log('Updated:', Object.keys(changed));
// Reconnect DB, refresh tokens, etc.
},
});import vaultdotenv
vaultdotenv.load_vault()
vaultdotenv.watch(
interval=30.0,
on_change=lambda changed, all:
print("Updated:", list(changed.keys())),
)Simple, honest pricing
No per-seat charges. No request metering. No surprises.
Free
Enough to ship something real.
- 10 secrets
- 2 environments
- 1 project
- 2 devices
- Encrypted cache
- Community support
Pro
For solo devs and small teams.
- 30 secrets
- 3 environments
- 3 projects
- 5 devices
- Hot reload
- Version history
- Email support
Team
For teams who ship to prod.
- Unlimited secrets
- Unlimited environments
- 10 projects
- Unlimited devices
- Hot reload
- Version history
- Audit log
- Priority support