envmap is a local env manager that helps you:
- Keep environment variables in sync with the (multiple) remote secret stores.
- Makes the
.envfile an ephemeral artifact, to keep secrets providers the source of truth. I.e. "envmap --sync" to produce a newly updated.envfile. - Comes with metadata on each key stored to inform when those keys were last changed/created.
- Improve security than storing secrets in a plaintext
.envfile. If you have remote secret stores setup - the data is handled in memory and never touches disk. If you want to use it completely locally, the localstore is encrypted. - Runs completely local + opensource for security audits with your team.
- Backups are possible and easy - env information is kept in a single encrypted localstore file instead of multiple
.envfiles that are gitignored by design.
- Engineers working in infra/devops with multiple
.envvariants like.env.prod, .env.dev, .env.staging, this is going to help you eliminate variants because you can just change to the desired.envwith a single command.
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ ./envmap sync --env prod
Wrote .env (1 secrets)
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ cat .env
# generated by envmap sync 2025-12-01T07:49:20Z
testkey=apishofih123
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ ./envmap sync --env dev
Wrote .env (1 secrets)
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ cat .env
# generated by envmap sync 2025-12-01T07:50:07Z
testkey=test123
- Engineers working a long list of env variables just wants a thin toll that helps you manage that increases dev velocity by making sure you have metadata
- People who think, it's wild to store secrets in a plaintext file called ``.env
.Well, you can run without a .env at all with the `envmap run --env dev -- npm start` to inject the variables into the process.
go install github.com/binsquare/envmap@latest# install into /usr/local/bin (requires sudo)
curl -sSfL "https://github.com/binsquare/envmap/releases/latest/download/envmap_$(uname -s)_$(uname -m).tar.gz" \
| sudo tar -xz -C /usr/local/bin envmap
# or install into ~/.local/bin (no sudo; ensure it's on PATH)
mkdir -p ~/.local/bin
curl -sSfL "https://github.com/binsquare/envmap/releases/latest/download/envmap_$(uname -s)_$(uname -m).tar.gz" \
| tar -xz -C ~/.local/bin envmap
# (optional) verify checksum (adjust path if using ~/.local/bin)
curl -sSfL "https://github.com/binsquare/envmap/releases/latest/download/envmap_$(uname -s)_$(uname -m).tar.gz.sha256" \
| sha256sum --check -If you use the ~/.local/bin option, make sure your shell loads it (most modern shells already do; otherwise append export PATH="$HOME/.local/bin:$PATH" to your profile).
Restart the shell (or reload the profile) and run envmap --help to verify.
# 1. Generate encryption key (writes to ~/.envmap/key)
envmap keygen
# 2. Configure global provider (wizard; runs keygen if needed)
envmap init --global
# 3. Create project config (wizard)
envmap init
# 4. Add secrets
envmap set --env dev DATABASE_URL --prompt
envmap set --env dev STRIPE_KEY --prompt
# 5. Inspect/export/run
envmap get --env dev --all
eval $(envmap export --env dev)
envmap run --env dev -- npm startPrefer the wizards, but manual config is supported. Use absolute paths (Go does not expand ~ or ${HOME}).
Manual configuration reference
providers:
local-dev:
type: local-file
path: /Users/<you>/.envmap/secrets.db
encryption:
key_file: /Users/<you>/.envmap/keyproject: demo
default_env: dev
envs:
dev:
provider: local-dev
prefix: demo/dev/envmap run [--env <name>] -- <command>– fetch secrets and run the command with them injected as env vars (disk never sees them).envmap export [--env <name>] [--format plain|json]– output suitable foreval, direnv, or tooling.envmap get --env <name> KEY [--raw]– read individual secrets.envmap get --env <name> --all [--raw] [--global]– list all secrets (masked by default);--globaliterates all envs.envmap set --env <name> KEY (--prompt | --file PATH)– write/update secrets without shell history.envmap import PATH --env <name> [--delete]– ingest existing.envfiles.envmap sync --env <name> [--out .env] [--merge] [--keep-local] [--force] [--backup=false]– write a .env file from provider secrets. Provider wins by default; merge keeps extra local-only keys; keep-local preserves local values on conflict; backup writes .bak first.envmap sync --env <name> --check– report drift between provider and .env without writing.envmap keygen [-o PATH]– create a 256-bit key for the local provider.envmap validate– confirm.envmap.yamland global config reference defined providers.envmap init/envmap init --global– interactive project/global configuration.
# .envrc
eval "$(envmap export --env dev)"Then run direnv allow. Every time you enter the directory, direnv will re-run envmap export and populate the shell with fresh secrets without touching disk.
providers:
aws-dev:
type: aws-ssm
region: us-west-2
profile: dev # optional, uses default credential chain
vault-prod:
type: vault
address: https://vault.internal:8200
mount: secret # default: secret
local:
type: local-file
path: ~/.envmap/secrets.db
encryption:
key_file: ~/.envmap/key # must be chmod 600
# or: key_env: ENVMAP_KEYproject: myapp
default_env: dev
envs:
dev:
provider: aws-dev
path_prefix: /myapp/dev/
staging:
provider: aws-dev
path_prefix: /myapp/staging/
local:
provider: local
prefix: myapp/| Type | Auth | Notes |
|---|---|---|
aws-ssm |
IAM (profile/env/instance) | Requires path_prefix. Uses SecureString. |
aws-secretsmanager |
IAM | Full secret names. JSON secrets expanded to name/key. |
gcp-secretmanager |
ADC or service account | Reads latest version. Adds version on write. |
vault |
Token (env/config) | KV v2. Configurable mount path and namespace. |
onepassword |
Connect server | Requires connect_host. Items matched by title. |
doppler |
Service token | Read-only; writes require Doppler CLI. |
local-file |
AES-256-GCM | Key from file (0600) or env var. For local dev. |
- Secrets never touch disk during normal operation. (unless you choose to use localstore to store all your env variables)
- We only have
set --promptandset --fileavoid saving secrets to shell history. - Values are masked by default in
envandgetoutput
| Layer | Implementation |
|---|---|
| Encryption | AES-256-GCM (authenticated) |
| Key derivation | HKDF-SHA256 with purpose binding |
| Nonce | Random 96-bit per write |
| File permissions | Key: 0600, Secrets: 0600, Dir: 0700 |
| Locking | Process-safe file locks (flock) |
| Atomic writes | Write to temp + rename (crash-safe) |
| Minimum key | 16 bytes enforced |
Generate keys with envmap keygen (256 bits from crypto/rand). Store the key file outside your repository.
Contributions and bug reports are welcome—open an issue or submit a PR if you find a bug.
Licensed under the Apache License, Version 2.0. See LICENSE for details.