Three tools dominate local secret management — HashiCorp Vault (dev mode), dotenv-vault, and SOPS — and picking the wrong one means either commit churn from encrypted blobs or a daemon nobody wants to run. This decision guide is part of local secret vaults and rotation within the environment sync, secrets and CI parity baseline.

The decision in one table

Dimension HashiCorp Vault (dev) dotenv-vault SOPS
Setup cost High — run a server/container Low — npm package + login Low — single binary
Encryption model Server-held, in-transit Service-managed keys Client-side (age/KMS/PGP)
Git-friendliness Not committed (live store) Encrypted .env.vault committed Encrypted files committed
Rotation First-class (leases, TTL) Manual re-push Manual re-encrypt
Team scaling Strong (policies, identities) Good (managed access) Good (per-recipient keys)
CI integration Token/AppRole auth Service DOTENV_KEY Decrypt with KMS/age in CI
Offline use Needs running server Needs service for pull Fully offline
Best fit Mirroring prod secret infra Small teams wanting zero ops Git-native, infra-as-code shops

How they actually differ

HashiCorp Vault (dev mode) runs a real secret server locally and most closely mirrors a production secret backend. Secrets live in the running store, never in git, and you get genuine leases and TTL-driven rotation. The cost is operational: someone has to run the container and bootstrap the KV engine, as covered in the local secret vaults and rotation parent. Choose it when local must behave like staging.

dotenv-vault keeps an encrypted .env.vault file in the repo and decrypts it via a service-held DOTENV_KEY. Setup is the lightest of the three and onboarding is "log in and pull", but you depend on the dotenv service and rotation means re-pushing. Good for small teams who want secret distribution without operating anything.

SOPS encrypts the values inside otherwise-readable YAML/JSON/ENV files using age, PGP, or a cloud KMS, and you commit the encrypted file. It is fully offline, git-native, and pairs naturally with infrastructure-as-code. Rotation is manual re-encryption, and key distribution is on you. Choose it when you want secrets versioned alongside config with no running service.

Minimal setup for each

#!/usr/bin/env bash
# HashiCorp Vault dev mode
set -euo pipefail
docker run --rm -p 8200:8200 \
  -e VAULT_DEV_ROOT_TOKEN_ID=local-dev-token \
  hashicorp/vault:1.15
#!/usr/bin/env bash
# dotenv-vault: encrypt local .env and commit the vault file
set -euo pipefail
npx dotenv-vault@latest login
npx dotenv-vault@latest push
git add .env.vault && git commit -m "Update encrypted env"
# .sops.yaml — route which files SOPS encrypts and with which key
creation_rules:
  - path_regex: secrets/.*\.yaml$
    age: age1qxyz0examplekeyreplaceme
#!/usr/bin/env bash
# SOPS: encrypt in place, commit the ciphertext, decrypt on demand
set -euo pipefail
sops --encrypt --in-place secrets/local.yaml
sops --decrypt secrets/local.yaml > /tmp/local.env

Decision guidance

  • Want local secrets to behave exactly like production, with real rotation and per-developer identities, and you can tolerate running a service: HashiCorp Vault.
  • Want the lowest-effort path for a small team and are comfortable depending on a managed service: dotenv-vault.
  • Want secrets versioned in git, offline-capable, and tied to your IaC workflow: SOPS.

A common hybrid: SOPS for committed, slow-changing config secrets and Vault dev for short-lived credentials that need rotation without restarting containers.

Apple Silicon (ARM64): Vault and SOPS publish arm64 builds; verify dotenv-vault's optional native deps install, or pin --platform linux/amd64 when running it inside a container. WSL2: keep age/PGP keyrings and .env.vault on the Linux filesystem so decryption hooks fire reliably and key permissions are honored.