Migrate to Platform Secret Stores
Migrate .env secrets to Doppler, Infisical, Azure Key Vault, Vercel, Heroku, or Railway using evnx migrate.
Prerequisites
Migrate to Platform Secret Stores
For six destinations — Doppler, Infisical, Azure Key Vault, Vercel, Heroku, and Railway — evnx generates CLI commands you review and run. None of these destinations need evnx to hold platform credentials; evnx only knows your .env file.
Before you start
Doppler
Doppler stores secrets in projects and configs. evnx generates one doppler secrets set command per variable.
What evnx generates
doppler secrets set DATABASE_URL='postgres://user:pass@host:5432/db'
doppler secrets set STRIPE_SECRET_KEY='sk_live_…'If --project and --doppler-config are supplied, a --config flag is added:
doppler secrets set --project myapp --config prd DATABASE_URL='postgres://…'Requirements
- ›Doppler CLI installed: docs.doppler.com/docs/cli
- ›Logged in (
doppler login) and a project already created in the Doppler dashboard
Usage
# Interactive — evnx asks for project and config
evnx migrate --to doppler
# Non-interactive
evnx migrate \
--to doppler \
--project myapp \
--doppler-config prd \
--exclude "*_LOCAL"# Pipe and run
evnx migrate \
--to doppler \
--project myapp \
--doppler-config prd \
> doppler-upload.sh && bash doppler-upload.shAfter migration
Replace your .env-based start command with doppler run:
# Before
node server.js
# After
doppler run -- node server.jsInfisical
Infisical works identically to Doppler from evnx's perspective — one infisical secrets set command per variable.
What evnx generates
infisical secrets set DATABASE_URL='postgres://user:pass@host:5432/db'
infisical secrets set STRIPE_SECRET_KEY='sk_live_…'If project and environment are supplied:
infisical secrets set \
--projectId abc123 \
--env prod \
DATABASE_URL='postgres://…'Requirements
- ›Infisical CLI installed: infisical.com/docs/cli/overview
- ›Logged in (
infisical login) and a project created in the Infisical dashboard
Usage
evnx migrate \
--to infisical \
--project abc123 \
--infisical-env prod \
--exclude "*_LOCAL,*_TEST"After migration
infisical run -- node server.jsAzure Key Vault
Azure Key Vault stores secrets individually, and does not allow underscores in secret names.
What evnx generates
evnx converts every _ to - in key names and prints one az keyvault secret set per variable:
az keyvault secret set --vault-name my-vault --name DATABASE-URL --value 'postgres://…'
az keyvault secret set --vault-name my-vault --name STRIPE-SECRET-KEY --value 'sk_live_…'It also prints a rename log so you can see which keys were changed:
Key renames applied:
DATABASE_URL → DATABASE-URL
STRIPE_SECRET_KEY → STRIPE-SECRET-KEY
Key names are transformed. Any code that reads DATABASE_URL from your .env must be updated to read DATABASE-URL from Key Vault, or use an alias/mapping layer in your application.
Requirements
- ›Azure CLI installed: learn.microsoft.com/cli/azure/install-azure-cli
- ›Logged in (
az login) - ›A Key Vault already created in your subscription
Usage
# Interactive — evnx asks for vault name
evnx migrate --to azure-keyvault
# Non-interactive
evnx migrate \
--to azure-keyvault \
--vault-name my-vault \
--exclude "*_LOCAL"evnx migrate \
--to azure \
--vault-name my-vault \
> azure-upload.sh && bash azure-upload.shMinimum permissions
The user or service principal running the commands needs:
- ›
Key Vault Secrets Officerrole on the vault — for creating and updating secrets - ›Or
Key Vault Contributorat the resource group level
Vercel
Vercel stores environment variables per project and environment. evnx generates one vercel env add command per variable using a heredoc so the value is passed through stdin rather than appearing in shell history.
What evnx generates
vercel env add DATABASE_URL production <<'EOF'
postgres://user:pass@host:5432/db
EOF
vercel env add STRIPE_SECRET_KEY production <<'EOF'
sk_live_…
EOFAll secrets are added to the production environment by default.
Requirements
- ›Vercel CLI installed:
npm install -g vercel - ›Logged in (
vercel login) - ›Project linked (
vercel link) or--vercel-projectsupplied
Usage
evnx migrate \
--to vercel \
--vercel-project my-project-id \
--exclude "*_LOCAL,*_TEST"After migration
# Verify secrets were set
vercel env pull .env.local
# Redeploy
vercel --prodHeroku
Heroku uses config vars (environment variables) set per app. evnx generates a single bulk heroku config:set command — one command triggers one dyno restart, rather than one restart per variable.
What evnx generates
heroku config:set \
--app my-app \
DATABASE_URL='postgres://user:pass@host:5432/db' \
STRIPE_SECRET_KEY='sk_live_…' \
REDIS_URL='redis://localhost:6379/0'Requirements
- ›Heroku CLI installed: devcenter.heroku.com/articles/heroku-cli
- ›Logged in (
heroku login) - ›App already created
Usage
# Interactive — evnx asks for app name
evnx migrate --to heroku
# Non-interactive
evnx migrate \
--to heroku \
--heroku-app my-app \
--exclude "*_LOCAL,*_TEST"evnx migrate --to heroku --heroku-app my-app | bashAfter migration
# Verify
heroku config --app my-app
# The dyno restarts automatically after config:setRailway
Railway stores environment variables per project and service. evnx generates a single railway variables set command.
What evnx generates
railway variables set \
DATABASE_URL='postgres://user:pass@host:5432/db' \
STRIPE_SECRET_KEY='sk_live_…'If --railway-project is supplied, a --projectId flag is added.
Requirements
- ›Railway CLI installed:
npm install -g @railway/cli - ›Logged in (
railway login) - ›Project linked (
railway link) or--railway-projectsupplied
Usage
# Interactive
evnx migrate --to railway
# Non-interactive
evnx migrate \
--to railway \
--railway-project my-project-id \
--exclude "*_LOCAL"After migration
# 1. Verify
railway variables
# 2. Deploy
railway upChoosing the right platform
| If you want… | Use |
|---|---|
| A dedicated secret manager with audit logs and role-based access | Doppler or Infisical |
| Azure infrastructure already in use | Azure Key Vault |
| Frontend / serverless deployments on Vercel | Vercel |
| Existing Heroku application | Heroku |
| Railway-hosted services | Railway |
| Full cloud provider integration (IAM, KMS) | AWS or GCP (see separate guides) |
See also
- ›Migration concepts — pipeline, filtering, transforms
- ›GitHub Actions migration
- ›AWS Secrets Manager migration
- ›GCP Secret Manager migration