Skip to content

BinSquare/envmap

Repository files navigation

envmap logo

GitHub stars Release workflow status Go pkg Reference Go Report Card License: Apache-2.0

envmap

envmap is a local env manager that helps you:

  1. Keep environment variables in sync with the (multiple) remote secret stores.
  2. Makes the .env file an ephemeral artifact, to keep secrets providers the source of truth. I.e. "envmap --sync" to produce a newly updated .env file.
  3. Comes with metadata on each key stored to inform when those keys were last changed/created.
  4. Improve security than storing secrets in a plaintext .env file. 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.
  5. Runs completely local + opensource for security audits with your team.
  6. Backups are possible and easy - env information is kept in a single encrypted localstore file instead of multiple .env files that are gitignored by design.

Who is this for?

  • Engineers working in infra/devops with multiple .env variants like .env.prod, .env.dev, .env.staging, this is going to help you eliminate variants because you can just change to the desired .env with 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.

Installation

Option 1: Go toolchain

go install github.com/binsquare/envmap@latest

Option 2: Prebuilt binary (bash)

# 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.

Quick start (local provider)

# 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 start

Prefer the wizards, but manual config is supported. Use absolute paths (Go does not expand ~ or ${HOME}).

Manual configuration reference

Global config (~/.envmap/config.yaml)

providers:
  local-dev:
    type: local-file
    path: /Users/<you>/.envmap/secrets.db
    encryption:
      key_file: /Users/<you>/.envmap/key

Project config (.envmap.yaml)

project: demo
default_env: dev
envs:
  dev:
    provider: local-dev
    prefix: demo/dev/

Usage

  • 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 for eval, 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); --global iterates all envs.
  • envmap set --env <name> KEY (--prompt | --file PATH) – write/update secrets without shell history.
  • envmap import PATH --env <name> [--delete] – ingest existing .env files.
  • 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.yaml and global config reference defined providers.
  • envmap init / envmap init --global – interactive project/global configuration.

Use with direnv

# .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.

Configuration

Global config (~/.envmap/config.yaml)

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_KEY

Project config (.envmap.yaml)

project: 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/

Built-in providers (WIP)

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.

Security Model

  • Secrets never touch disk during normal operation. (unless you choose to use localstore to store all your env variables)
  • We only haveset --prompt and set --file avoid saving secrets to shell history.
  • Values are masked by default in env and get output

Local provider hardening

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

Contributions and bug reports are welcome—open an issue or submit a PR if you find a bug.

License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

About

Stop using .env files to store secrets locally, use an ENV manager.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages