a better dotenv–from the creator of dotenv
.
- run anywhere (cross-platform)
- multi-environment
- encrypted envs
Install and use it in code just like dotenv
.
npm install @dotenvx/dotenvx --save
// index.js
require('@dotenvx/dotenvx').config()
console.log(`Hello ${process.env.HELLO}`)
Or install globally
brew install dotenvx/brew/dotenvx
Intall globally as a cli to unlock dotenv for ANY language, framework, or platform. 💥
I am using (and recommending) this approach going forward. – motdotla
$ echo "HELLO=World" > .env
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
$ node index.js
Hello undefined
$ dotenvx run -- node index.js
Hello World
> :-D
More examples
-
TypeScript 📘
// package.json { "type": "module", "dependencies": { "chalk": "^5.3.0" } }
// index.ts import chalk from 'chalk' console.log(chalk.blue(`Hello ${process.env.HELLO}`))
$ npm install $ echo "HELLO=World" > .env $ dotenvx run -- npx tsx index.ts Hello World
-
Deno 🦕
$ echo "HELLO=World" > .env $ echo "console.log('Hello ' + Deno.env.get('HELLO'))" > index.ts $ deno run --allow-env index.ts Hello undefined $ dotenvx run -- deno run --allow-env index.ts Hello World
-
Bun 🥟
$ echo "HELLO=Test" > .env.test $ echo "console.log('Hello ' + process.env.HELLO)" > index.js $ bun index.js Hello undefined $ dotenvx run -f .env.test -- bun index.js Hello Test
-
Python 🐍
$ echo "HELLO=World" > .env $ echo 'import os;print("Hello " + os.getenv("HELLO", ""))' > index.py $ dotenvx run -- python3 index.py Hello World
-
PHP 🐘
$ echo "HELLO=World" > .env $ echo '<?php echo "Hello {$_SERVER["HELLO"]}\n";' > index.php $ dotenvx run -- php index.php Hello World
-
Ruby 💎
$ echo "HELLO=World" > .env $ echo 'puts "Hello #{ENV["HELLO"]}"' > index.rb $ dotenvx run -- ruby index.rb Hello World
-
Go 🐹
$ echo "HELLO=World" > .env $ echo 'package main; import ("fmt"; "os"); func main() { fmt.Printf("Hello %s\n", os.Getenv("HELLO")) }' > main.go $ dotenvx run -- go run main.go Hello World
-
Rust 🦀
$ echo "HELLO=World" > .env $ echo 'fn main() {let hello = std::env::var("HELLO").unwrap_or("".to_string());println!("Hello {hello}");}' > src/main.rs $ dotenvx run -- cargo run Hello World
-
Java ☕️
$ echo "HELLO=World" > .env $ echo 'public class Index { public static void main(String[] args) { System.out.println("Hello " + System.getenv("HELLO")); } }' > index.java $ dotenvx run -- java index.java Hello World
-
.NET 🔵
$ dotnet new console -n HelloWorld -o HelloWorld $ cd HelloWorld $ echo "HELLO=World" > .env $ echo 'Console.WriteLine($"Hello {Environment.GetEnvironmentVariable("HELLO")}");' > Program.cs $ dotenvx run -- dotnet run Hello World
-
Bash 🖥️
$ echo "HELLO=World" > .env $ dotenvx run --quiet -- sh -c 'echo Hello $HELLO' Hello World
-
Cron ⏰
# run every day at 8am 0 8 * * * dotenvx run -- /path/to/myscript.sh
-
Frameworks ▲
$ dotenvx run -- next dev $ dotenvx run -- npm start $ dotenvx run -- bin/rails s $ dotenvx run -- php artisan serve
see framework guides
-
Docker 🐳
$ docker run -it --rm -v $(pwd):/app dotenv/dotenvx run -- node index.js
Or in any image:
FROM node:latest RUN echo "HELLO=World" > .env && echo "console.log('Hello ' + process.env.HELLO)" > index.js RUN curl -fsS https://dotenvx.sh/ | sh CMD ["dotenvx", "run", "--", "echo", "Hello $HELLO"]
see docker guide
-
CI/CDs 🐙
name: build on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - run: curl -fsS https://dotenvx.sh/ | sh - run: dotenvx run -- node build.js env: DOTENV_KEY: ${{ secrets.DOTENV_KEY }}
-
Platforms
# heroku heroku buildpacks:add https://github.com/dotenvx/heroku-buildpack-dotenvx # docker RUN curl -fsS https://dotenvx.sh/ | sh # vercel npm install @dotenvx/dotenvx --save
see platform guides
-
Process Managers
// pm2 "scripts": { "start": "dotenvx run -- pm2-runtime start ecosystem.config.js --env production" },
-
npx
# alternatively use npx $ npx @dotenvx/dotenvx run -- node index.js $ npx @dotenvx/dotenvx run -- next dev $ npx @dotenvx/dotenvx run -- npm start
-
npm
$ npm install @dotenvx/dotenvx --save
{ "scripts": { "start": "./node_modules/.bin/dotenvx run -- node index.js" }, "dependencies": { "@dotenvx/dotenvx": "^0.5.0" } }
$ npm run start > start > ./node_modules/.bin/dotenvx run -- node index.js [dotenvx][info] loading env (1) from .env Hello World
-
Git
# use as a git submodule $ git dotenvx run -- node index.js $ git dotenvx run -- next dev $ git dotenvx run -- npm start
-
Variable Expansion
Reference and expand variables already on your machine for use in your .env file.
# .env USERNAME="username" DATABASE_URL="postgres://${USERNAME}@localhost/my_database"
// index.js console.log('DATABASE_URL', process.env.DATABASE_URL)
$ dotenvx run --debug -- node index.js [[email protected]] injecting env (2) from .env DATABASE_URL postgres://username@localhost/my_database
-
Command Substitution
Add the output of a command to one of your variables in your .env file.
# .env DATABASE_URL="postgres://$(whoami)@localhost/my_database"
// index.js console.log('DATABASE_URL', process.env.DATABASE_URL)
$ dotenvx run --debug -- node index.js [[email protected]] injecting env (1) from .env DATABASE_URL postgres://yourusername@localhost/my_database
Create a
.env.production
file and use-f
to load it. It's straightforward, yet flexible.
$ echo "HELLO=production" > .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
$ dotenvx run -f .env.production -- node index.js
[dotenvx][info] loading env (1) from .env.production
Hello production
> ^^
More examples
-
multiple `.env` files
$ echo "HELLO=local" > .env.local $ echo "HELLO=World" > .env $ dotenvx run -f .env.local -f .env -- node index.js [dotenvx][info] loading env (1) from .env.local,.env Hello local
-
`--overload` flag
$ echo "HELLO=local" > .env.local $ echo "HELLO=World" > .env $ dotenvx run -f .env.local -f .env --overload -- node index.js [dotenvx][info] loading env (1) from .env.local,.env Hello World
-
`--verbose` flag
$ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --verbose -- node index.js [dotenvx][verbose] injecting env from /path/to/.env.production [dotenvx][verbose] HELLO set [dotenvx][info] loading env (1) from .env.production Hello production
-
`--debug` flag
$ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --debug -- node index.js [dotenvx][debug] configuring options [dotenvx][debug] {"envFile":[".env.production"]} [dotenvx][verbose] injecting env from /path/to/.env.production [dotenvx][debug] reading env from /path/to/.env.production [dotenvx][debug] parsing env from /path/to/.env.production [dotenvx][debug] {"HELLO":"production"} [dotenvx][debug] writing env from /path/to/.env.production [dotenvx][verbose] HELLO set [dotenvx][debug] HELLO set to production [dotenvx][info] loading env (1) from .env.production Hello production
-
`--quiet` flag
Use
--quiet
to suppress all output (except errors).$ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --quiet -- node index.js Hello production
-
`--log-level` flag
Set
--log-level
to whatever you wish. For example, to supress warnings (risky), set log level toerror
:$ echo "HELLO=production" > .env.production $ dotenvx run -f .env.production --log-level=error -- node index.js Hello production
Available log levels are
error, warn, info, verbose, debug, silly
-
`--convention` flag
Want to load envs conveniently usng the same convention as Next.js? Set
--convention
tonextjs
:$ echo "HELLO=development local" > .env.development.local $ echo "HELLO=local" > .env.local $ echo "HELLO=development" > .env.development $ echo "HELLO=env" > .env $ dotenvx run --convention=nextjs -- node index.js Hello development local
See next.js environment variable load order
(more conventions available upon request)
Encrypt your secrets to a
.env.vault
file and load from it (recommended for production and ci).
$ echo "HELLO=World" > .env
$ echo "HELLO=production" > .env.production
$ echo "console.log('Hello ' + process.env.HELLO)" > index.js
$ dotenvx encrypt
[dotenvx][info] encrypted to .env.vault (.env,.env.production)
[dotenvx][info] keys added to .env.keys (DOTENV_KEY_PRODUCTION,DOTENV_KEY_PRODUCTION)
$ DOTENV_KEY='<dotenv_key_production>' dotenvx run -- node index.js
[dotenvx][info] loading env (1) from encrypted .env.vault
Hello production
^ :-]
More examples
-
AWS Lambda
coming soon
-
Digital Ocean
coming soon
-
Docker 🐳
Add the
dotenvx
binary to your Dockerfile# Install dotenvx RUN curl -fsS https://dotenvx.sh/ | sh
Use it in your Dockerfile CMD
# Prepend dotenvx run CMD ["dotenvx", "run", "--", "node", "index.js"]
see docker guide
-
Fly.io 🎈
Add the
dotenvx
binary to your Dockerfile# Install dotenvx RUN curl -fsS https://dotenvx.sh/ | sh
Use it in your Dockerfile CMD
# Prepend dotenvx run CMD ["dotenvx", "run", "--", "node", "index.js"]
see fly guide
-
Heroku 🟣
Add the buildpack, installing the
dotenvx
binary to your heroku deployment.heroku buildpacks:add https://github.com/dotenvx/heroku-buildpack-dotenvx
Use it in your Procfile.
web: dotenvx run -- node index.js
see heroku guide
-
Laravel Forge
coming soon
-
Netlify 🔷
Add the
dotenvx
npm modulenpm install @dotenvx/dotenvx --save
Use it in your
package.json scripts
"scripts": { "dotenvx": "dotenvx", "dev": "dotenvx run -- next dev --turbo", "build": "dotenvx run -- next build", "start": "dotenvx run -- next start" },
see netlify guide
-
Railway 🚄
Add the
dotenvx
binary to your Dockerfile# Install dotenvx RUN curl -fsS https://dotenvx.sh/ | sh
Use it in your Dockerfile CMD
# Prepend dotenvx run CMD ["dotenvx", "run", "--", "node", "index.js"]
see railway guide
-
Render
coming soon
-
Vercel ▲
Add the
dotenvx
npm modulenpm install @dotenvx/dotenvx --save
Use it in your
package.json scripts
"scripts": { "dotenvx": "dotenvx", "dev": "dotenvx run -- next dev --turbo", "build": "dotenvx run -- next build", "start": "dotenvx run -- next start" },
see vercel guide
-
CircleCI
coming soon
-
GitHub Actions 🐙
Add the
dotenvx
binary to GitHub Actionsname: build on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - run: curl -fsS https://dotenvx.sh/ | sh - run: dotenvx run -- node build.js env: DOTENV_KEY: ${{ secrets.DOTENV_KEY }}
Integrate tightly with GitHub 🐙 and as a team
$ dotenvx hub login
$ dotenvx hub push
beta: more details coming soon.
Keep your
.env
files safe
dotenvx genexample
– generate.env.example
filedotenvx gitignore
– gitignore your.env
filesdotenvx prebuild
– prevent.env
files from being built into your docker containerdotenvx precommit
– prevent.env
files from being committed to codedotenvx scan
– scan for leaked secrets in code
Convenience
dotenvx get
– return a single environment variabledotenvx set
– set a single environment variabledotenvx ls
– list all .env files in your repodotenvx status
– compare your .env* content(s) to your .env.vault decrypted content(s)dotenvx settings
– print current dotenvx settings
You are using Node 20 or greater and it adds a differing implementation of --env-file
flag support. Rather than warn on a missing .env
file (like dotenv has historically done), it raises an error: node: .env: not found
.
This fix is easy. Replace --env-file
with -f
.
# from this:
./node_modules/.bin/dotenvx run --env-file .env -- yourcommand
# to this:
./node_modules/.bin/dotenvx run -f .env -- yourcommand
You can fork this repo and create pull requests or if you have questions or feedback:
- github.com/dotenvx/dotenvx - bugs and discussions
- @dotenvx 𝕏 (DMs are open)