dotenv-vault
Version:
A secrets manager for .env files – from the same people that pioneered dotenv.
865 lines (626 loc) • 22.2 kB
Markdown
`dotenv-vault` is a cli to *sync .env files across machines, environments, and team members*.
[](https://npmjs.org/package/dotenv-vault)
> [!NOTE]
> dotenv-vault is a **paid only cloud service for syncing your .env files** (as of May 2025).
>
> *Looking for a free cloud-less alternative?* See my new product [dotenvx](https://github.com/dotenvx/dotenvx) – that lets you:
> - encrypt your .env files
> - commit them to code
> - and securely sync them over git
## 🌱 Install
It works with a single command. Run `npx dotenv-vault@latest push`.
```sh
npx dotenv-vault@latest push
```
```
remote: Securely pushing (.env)... done
remote: Securely pushed development (.env)
remote: Securely built vault (.env.vault)
```
That's it. You securely synced your `.env` file. Next, tell your teammate to run `npx dotenv-vault@latest pull`
```sh
npx dotenv-vault@latest pull
```
Nice!
See further [usage](#%EF%B8%8F-usage) and [commands](#-commands).
## 🏗️ Usage
When you make a change to your `.env` file, push it up.
```bash
$ npx dotenv-vault@latest push
```
Commit your `.env.vault` file safely to code.
```bash
$ git add .env.vault
$ git commit -am "Add .env.vault"
$ git push
```
Now your teammate can pull the latest `.env` changes.
```bash
$ git pull
$ npx dotenv-vault@latest pull
```
That's it!
<a href="https://www.dotenv.org/docs/quickstart?r=1">Learn more about usage</a>
## 🚀 Deploying
Stop scattering your production secrets across multiple third-parties and tools. Instead, use an encrypted `.env.vault` file.
Generate your encrypted `.env.vault` file.
```bash
$ npx dotenv-vault@latest build
```
Fetch your production `DOTENV_KEY`.
```bash
$ npx dotenv-vault@latest keys production
remote: Listing .env.vault decryption keys... done
dotenv://:key_1234…@dotenv.org/vault/.env.vault?environment=production
```
Set `DOTENV_KEY` on your server.
```bash
# heroku example
heroku config:set DOTENV_KEY=dotenv://:key_1234…@dotenv.org/vault/.env.vault?environment=production
```
Commit your `.env.vault` file safely to code and deploy.
```bash
$ git add .env.vault
$ git commit -am "Update .env.vault"
$ git push
$ git push heroku main # heroku example
```
That's it! On deploy, your `.env.vault` file will be decrypted and its secrets injected as environment variables – just in time.
<a href="https://www.dotenv.org/docs/quickstart?r=1">Learn more about deploying</a>
## 🌴 Manage Multiple Environments
After you've pushed your `.env` file, dotenv-vault automatically sets up multiple environments. Manage multiple environments with the included UI. [learn more](/docs/tutorials/environments)
```
$ npx dotenv-vault@latest open production
```
That's it! Manage your ci, staging, and production secrets from there.
Would you also like to pull your production `.env` to your machine? Run the command:
```
$ npx dotenv-vault@latest pull production
```
<a href="https://www.dotenv.org/docs/tutorials/environments?r=1">Learn more about environments</a>
## 📚 Examples
<table>
<tbody>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/platforms/vercel">
<img src="https://api.iconify.design/devicon/vercel.svg" alt="Vercel", width="20" />
Vercel
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/platforms/heroku">
<img src="https://api.iconify.design/skill-icons/heroku.svg" alt="Heroku", width="20" />
Heroku
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/cis/github-actions">
<img src="https://api.iconify.design/devicon/github.svg" alt="GitHub", width="20" />
GitHub Actions
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/gitlab-ci">
<img src="https://api.iconify.design/devicon/gitlab.svg" alt="GitLab", width="20" />
GitLab CI/CD
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/platforms/netlify">
<img src="https://api.iconify.design/skill-icons/netlify-light.svg" alt="Netlify", width="20" />
Netlify
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/platforms/docker">
<img src="https://api.iconify.design/skill-icons/docker.svg" alt="Docker", width="20" />
Docker
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/express/docker-compose">
<img src="https://api.iconify.design/skill-icons/docker.svg" alt="Docker Compose", width="20" />
Docker Compose
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/cis/circleci">
<img src="https://api.iconify.design/logos/circleci.svg" alt="CircleCI", width="20" />
CircleCI
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/serverless/aws-lambda">
<img src="https://api.iconify.design/logos/serverless.svg" alt="Serverless", width="20" />
Serverless
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/railway">
<img src="https://api.iconify.design/simple-icons/railway.svg" alt="Railway", width="20" />
Railway
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/render">
<img src="https://api.iconify.design/simple-icons/render.svg" alt="Render", width="20" />
Render
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/travis-ci">
<img src="https://api.iconify.design/simple-icons/travisci.svg" alt="Travis CI", width="20" />
Travis CI
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/cis/google-cloud-build">
<img src="https://api.iconify.design/devicon/googlecloud.svg" alt="Google Cloud", width="20" />
Google Cloud
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/platforms/fly">
<img src="https://api.iconify.design/logos/fly-icon.svg" alt="Fly.io", width="20" />
Fly.io
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/addons/slack">
<img src="https://api.iconify.design/devicon/slack.svg" alt="dotenv-vault + Slack", width="20" />
Slack
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/buddy">
<img src="https://api.iconify.design/logos/buddy.svg" alt="Buddy", width="20" />
Buddy
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/cloud66">
<img src="https://api.iconify.design/simple-icons/cloud66.svg" alt="Cloud66", width="20" />
Cloud66
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/digital-ocean">
<img src="https://api.iconify.design/devicon/digitalocean.svg" alt="Digital Ocean", width="20" />
Digital Ocean
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/dagger">
<img src="https://dagger.io/img/logo-alt-2.svg" alt="Dagger", width="20" />
Dagger
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/bitbucket">
<img src="https://api.iconify.design/devicon/bitbucket.svg" alt="Bitbucket", width="20" />
Bitbucket
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs">
<img src="https://api.iconify.design/devicon/nodejs.svg" alt="Node.js", width="20" />
Node.js
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/express">
<img src="https://api.iconify.design/devicon/express.svg" alt="Express", width="20" />
Express
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/nextjs">
<img src="https://api.iconify.design/devicon/nextjs.svg" alt="NextJS", width="20" />
NextJS
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/remix">
<img src="https://api.iconify.design/skill-icons/remix-dark.svg" alt="Remix", width="20" />
Remix
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/astro/netlify">
<img src="https://api.iconify.design/devicon/astro.svg" alt="Astro", width="20" />
Astro
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/rails">
<img src="https://api.iconify.design/logos/rails.svg" alt="Rails", width="20" />
Rails
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/ruby">
<img src="https://api.iconify.design/logos/ruby.svg" alt="Ruby", width="20" />
Ruby
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/sinatra/heroku">
<img src="https://api.iconify.design/logos/sinatra.svg" alt="Sinatra", width="20" />
Sinatra
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/flask/heroku">
<img src="https://api.iconify.design/devicon/flask.svg" alt="Flask", width="20" />
Flask
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/python">
<img src="https://api.iconify.design/devicon/python.svg" alt="Python", width="20" />
Python
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/integrations/supabase/nodejs?r=1">
<img src="https://api.iconify.design/devicon/supabase.svg" alt="Supabase", width="20" />
Supabase
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/languages/nodejs/pulumi">
<img src="https://api.iconify.design/vscode-icons/file-type-pulumi.svg" alt="Pulumi", width="20" />
Pulumi
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/angular/vercel">
<img src="https://api.iconify.design/devicon/angular.svg" alt="Angular", width="20" />
Angular
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/nuxtjs">
<img src="https://api.iconify.design/logos/nuxt-icon.svg" alt="Nuxt", width="20" />
Nuxt
</a>
</td>
<td align="left" valign="middle">
<a href="https://www.dotenv.org/docs/frameworks/vite/vercel">
<img src="https://api.iconify.design/devicon/vite.svg" alt="Vite", width="20" />
Vite
</a>
</td>
</tr>
</tbody>
</table>
<a href="https://www.dotenv.org/docs/">See more integration guides</a>
## 📖 Commands
```
$ npx dotenv-vault@latest help
```
* [new](#new)
* [login](#login)
* [logout](#logout)
* [push](#push)
* [pull](#pull)
* [open](#open)
* [whoami](#whoami)
* [build](#build)
* [keys](#keys)
* [rotatekey](#rotatekey)
* [decrypt](#decrypt)
* [versions](#versions)
### `new`
Create your project at Dotenv Vault.
Example:
```bash
$ npx dotenv-vault@latest new
```
##### ARGUMENTS
*[DOTENV_VAULT]*
Set .env.vault identifier. Defaults to generated value.
```
$ npx dotenv-vault@latest new vlt_6beaae5…
local: Adding .env.vault (DOTENV_VAULT)... done
local: Added to .env.vault (DOTENV_VAULT=vlt_6beaa...)
```
##### FLAGS
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
---
### `login`
Log in to dotenv-vault.
Example:
```bash
$ npx dotenv-vault@latest login
```
##### ARGUMENTS
*[DOTENV_ME]*
Set .env.me identifier. Defaults to generated value.
```
$ npx dotenv-vault@latest login me_00c7fa…
```
##### FLAGS
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest login -y
```
---
### `logout`
Log out of dotenv-vault.
Example:
```bash
$ npx dotenv-vault@latest logout
```
##### FLAGS
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest logout -y
```
---
### `push`
Push `.env` securely.
Example:
```bash
$ npx dotenv-vault@latest push
```
##### ARGUMENTS
*[ENVIRONMENT]*
Set environment to push to. Defaults to development
```
$ npx dotenv-vault@latest push production
```
*[FILENAME]*
Set input filename. Defaults to .env for development and .env.{environment} for other environments
```
$ npx dotenv-vault@latest push production .env.production
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest push --dotenvMe=me_b1831e…
```
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest push -y
```
---
### `pull`
Pull `.env` securely.
Example:
```bash
$ npx dotenv-vault@latest pull
```
##### ARGUMENTS
*[ENVIRONMENT]*
Set environment to pull from. Defaults to development
```
$ npx dotenv-vault@latest pull production
```
*[FILENAME]*
Set output filename. Defaults to .env for development and .env.{environment} for other environments
```
$ npx dotenv-vault@latest pull production .env.production
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest pull --dotenvMe=me_b1831e…
```
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest pull -y
```
If you want to pull a specific version you can do so. For example,
```
npx dotenv-vault@latest pull development@v14
```
---
### `open`
Open project page.
Example:
```bash
$ npx dotenv-vault@latest open
```
##### ARGUMENTS
*[ENVIRONMENT]*
Set environment to open to. Defaults to development.
```
$ npx dotenv-vault@latest open production
```
##### FLAGS
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest open -y
```
---
### `whoami`
Display the current logged in user.
Example:
```bash
$ npx dotenv-vault@latest whoami
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest whoami dotenvMe=me_b1831e…
```
---
### `build`
Build .env.vault file.
Example:
```bash
$ npx dotenv-vault@latest build
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest build dotenvMe=me_b1831e…
```
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest build -y
```
---
### `keys`
List .env.vault decryption keys.
Example:
```bash
$ npx dotenv-vault@latest keys
```
##### ARGUMENTS
*[ENVIRONMENT]*
Set environment. Defaults to all.
```
$ npx dotenv-vault@latest keys production…
remote: Listing .env.vault decryption keys... done
dotenv://:key_899..@dotenv.org/vault/.env.vault?environment=production
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest keys dotenvMe=me_b1831e…
```
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest keys -y
```
---
### `rotatekey`
Rotate DOTENV_KEY.
Example:
```bash
$ npx dotenv-vault@latest rotatekey production
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest rotatekey dotenvMe=me_b1831e…
```
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest rotatekey -y
```
---
### `decrypt`
Decrypt .env.vault locally.
Example:
```bash
$ npx dotenv-vault@latest decrypt dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development
```
##### ARGUMENTS
*[DOTENV_KEY]*
Set `DOTENV_KEY` to decrypt .env.vault. Development key will decrypt development, production will decrypt production, and so on.
```
$ npx dotenv-vault@latest decrypt dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development
```
---
### `versions`
List version history.
Example:
```bash
$ npx dotenv-vault@latest versions
```
##### ARGUMENTS
*[ENVIRONMENT]*
Set environment to check versions against. Defaults to development.
```
$ npx dotenv-vault@latest versions production
```
##### FLAGS
*-m, --dotenvMe*
Pass .env.me (DOTENV_ME) credential directly (rather than reading from .env.me file)
```
$ npx dotenv-vault@latest versions dotenvMe=me_b1831e…
```
*-y, --yes*
Automatic yes to prompts. Assume yes to all prompts and run non-interactively.
```
$ npx dotenv-vault@latest versions -y
```
If you want to pull a specific version you can do so. For example,
```
npx dotenv-vault@latest pull development@v14
```
## ❓ FAQ
### Why is the `.env.vault` file not decrypting my environment variables successfully?
First, make sure you are using `dotenv@16.1.0` or greater. (If you are using a different language make sure you have installed one of its [libraries](#what-languages-does-this-work-with).)
Second, test decryption is working locally.
```bash
$ npx dotenv-vault@latest decrypt dotenv://:key_1234..@dotenv.local/vault/.env.vault?environment=production
# outputs environment variables
```
Third, test decryption on boot is working locally.
```bash
$ DOTENV_KEY='dotenv://:key_1234..@dotenv.local/vault/.env.vault?environment=production' npm start
# boots your app with production envs
```
### Should I commit my `.env.vault` file?
Yes. It is safe and recommended to do so. DO commit your `.env.vault` file to code. DO NOT commit your `.env` file. The `.env.vault` file contains ciphertext generated using AES-256. AES-256 is trusted by the US Government to transmit top-secret information and has a brute-force timescale of about a billion years.
### I accidentally leaked my `DOTENV_KEY`, what can I do?
Does that attacker also have access to your `.env.vault` file?
* No: good, the attacker cannot do any damage. They need both the `DOTENV_KEY` and `.env.vault` file to access your secrets. This extra layer of security sets the `.env.vault` file apart as a superior solution to other SecretOps solutions.
* Yes: IMMEDIATELY start rotating your secrets at your third-party API providers. This scenario would be the same no matter what SecretOps solution you use.
After completing the above, rotate your `DOTENV_KEY` using the [rotatekey](#rotatekey) command, rebuild your `.env.vault` file, and redeploy.
### Is it safe to store my secrets with dotenv-vault?
It safer than scattering your secrets across multiple cloud providers. Those providers are focused on code deployment and server performance over secrets security.[1]
Dotenv Vault's singular focus is secrets security, and as a result we go to great lengths to make sure your secrets are safe. Afterall, we keep our secrets here too.[2]
* [[1] CircleCI Breach](https://techcrunch.com/2023/01/05/circleci-breach/)
* [[2] Security at Dotenv Vault](https://www.dotenv.org/security)
### What languages does this work with?
The `.env.vault` file and its encryption algorithm is language-agnostic so technically it works with any language. We've built convenience libraries for it in a handful of languages and are adding more quickly.
* [Go](https://github.com/dotenv-org/godotenvvault)
* [Kotlin](https://github.com/dotenv-org/dotenv-vault-kotlin)
* [NodeJS](https://github.com/motdotla/dotenv)
* [PHP](https://github.com/dotenv-org/phpdotenv-vault)
* [Python](https://github.com/dotenv-org/python-dotenv-vault)
* [Ruby](https://github.com/dotenv-org/dotenv-vault-ruby)
### Migrating to Dotenvx
With dotenvx you put your development, staging, ci, and production secrets IN your code - as encrypted `.env.*` files. So for example, to do production you would
1. Create `.env.production` with `HELLO=production` (or in dotenv-vault's case `npx dotenv-vault@latest pull production`)
2. Run `dotenvx encrypt -f .env.production` to encrypt it
3. Commit that to code
Then when deploying your codebase you put `dotenvx run --` out front of your run command.
1. Add `dotenvx run -- yourstartcommand`
2. Set `DOTENV_PRIVATE_KEY_PRODUCTION` on the server
3. On boot `dotenvx run` will read the private key and use it to decrypt and inject your secrets just in time as environment variables
Here's a [quickstart guide](https://dotenvx.com/docs/quickstart#add-encryption)
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
## Changelog
See [CHANGELOG.md](CHANGELOG.md)
## License
MIT