envmap keeps secrets out of your Git history by sourcing them from a provider (local encrypted store, AWS SSM, Vault, etc.) and injecting them directly into the target process. No .env files, no accidental commits, no “who has the latest .env?” in Slack.
.envfiles are easy to leak and hard to rotate across multiple engineers and machines.- Most teams already have a secrets backend (or should); local dev is the messy part.
envmapgives each repo a single, typed mapping from “env name → provider path” and a consistentenvmap run -- <cmd>entrypoint.
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 env
eval $(envmap export --env dev)
envmap run -- 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 -- <command>– fetch secrets for an environment and exec the target process with those env vars (disk never sees them).envmap env [--env <name>] [--raw]– inspect secrets; masked by default,--rawreveals values.envmap export [--env <name>] [--format plain|json]– output suitable foreval, direnv, or tooling.envmap get --env <name> KEY [--raw]– read individual secrets.envmap set --env <name> KEY (--prompt | --file PATH)– write/update secrets without shell history.envmap import PATH --env <name> [--delete]– ingest existing.envfiles.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 local)
set --promptandset --fileavoid shell history- Values masked by default in
envandgetoutput exportoutputs to stdout only, no file writing
| 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.