Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

a better dotenv–from the creator of `dotenv`

License

NotificationsYou must be signed in to change notification settings

dotenvx/dotenvx

Repository files navigation

dotenvx

a better dotenv–from the creator ofdotenv.

  • run anywhere (cross-platform)
  • multi-environment
  • encrypted envs

Read the whitepaper

 

Quickstartnpm versiondownloadstest suite

Install and use it in code just likedotenv.

npm install @dotenvx/dotenvx --save
// index.jsrequire('@dotenvx/dotenvx').config()// or import '@dotenvx/dotenvx/config' // for esmconsole.log(`Hello${process.env.HELLO}`)

 

or install globally -unlocks dotenv for any language, framework, or platform!

with curl 🌐
curl -sfS https://dotenvx.sh| shdotenvxhelp

curl installs

 

with brew 🍺
brew install dotenvx/brew/dotenvxdotenvxhelp

brew installs

 

with docker 🐳
docker run -it --rm -v$(pwd):/app dotenv/dotenvxhelp

docker pulls

 

with github releases 🐙
curl -L -o dotenvx.tar.gz"https://github.com/dotenvx/dotenvx/releases/latest/download/dotenvx-$(uname -s)-$(uname -m).tar.gz"tar -xzf dotenvx.tar.gz./dotenvxhelp

github releases

 

or windows 🪟
winget install dotenvxdotenvxhelp

 

Run Anywhere

$echo"HELLO=World"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ node index.jsHello undefined# without dotenvx$ dotenvx run -- node index.jsHello World# with dotenvx> :-D

seeextended quickstart guide

More examples

  • TypeScript 📘
    // package.json{"type":"module","dependencies": {"chalk":"^5.3.0"  }}
    // index.tsimportchalkfrom'chalk'console.log(chalk.blue(`Hello${process.env.HELLO}`))
    $ npm install$echo"HELLO=World"> .env$ dotenvx run -- npx tsx index.tsHello World
  • Deno 🦕
    $echo"HELLO=World"> .env$echo"console.log('Hello ' + Deno.env.get('HELLO'))"> index.ts$ deno run --allow-env index.tsHello undefined$ dotenvx run -- deno run --allow-env index.tsHello World

    [!WARNING]Some of you are attempting to use the npm module directly withdeno run. Don't, because deno currently has incomplete support for these encryption ciphers.

    $ deno run -A npm:@dotenvx/dotenvx encryptUnknown cipher

    Instead, usedotenvx as designed, by installing the cli as a binary - via curl, brew, etc.

  • Bun 🥟
    $echo"HELLO=Test"> .env.test$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ bun index.jsHello undefined$ dotenvx run -f .env.test -- bun index.jsHello Test
  • Python 🐍
    $echo"HELLO=World"> .env$echo'import os;print("Hello " + os.getenv("HELLO", ""))'> index.py$ dotenvx run -- python3 index.pyHello World

    seeextended python guide

  • PHP 🐘
    $echo"HELLO=World"> .env$echo'<?php echo "Hello {$_SERVER["HELLO"]}\n";'> index.php$ dotenvx run -- php index.phpHello World

    seeextended php guide

  • Ruby 💎
    $echo"HELLO=World"> .env$echo'puts "Hello #{ENV["HELLO"]}"'> index.rb$ dotenvx run -- ruby index.rbHello World

    seeextended ruby guide

  • 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.goHello World

    seeextended go guide

  • 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 runHello World

    seeextended rust guide

  • 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.javaHello World
  • Clojure 🌿
    $echo"HELLO=World"> .env$echo'(println "Hello" (System/getenv "HELLO"))'> index.clj$ dotenvx run -- clojure -M index.cljHello World
  • Kotlin 📐
    $echo"HELLO=World"> .env$echo'fun main() { val hello = System.getenv("HELLO") ?: ""; println("Hello $hello") }'> index.kt$ kotlinc index.kt -include-runtime -d index.jar$ dotenvx run -- java -jar index.jarHello World
  • .NET 🔵
    $ dotnet new console -n HelloWorld -o HelloWorld$cd HelloWorld$echo"HELLO=World"| Out-File -FilePath .env -Encoding utf8$echo'Console.WriteLine($"Hello {Environment.GetEnvironmentVariable("HELLO")}");'> Program.cs$ dotenvx run -- dotnet runHello World
  • Bash 🖥️
    $echo"HELLO=World"> .env$ dotenvx run --quiet -- sh -c'echo Hello $HELLO'Hello World
  • Fish 🐠
    $echo"HELLO=World"> .env$ dotenvx run --quiet -- sh -c'echo Hello $HELLO'Hello World
  • Cron ⏰
    # run every day at 8am0 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

    seeframework guides

  • Docker 🐳
    $ docker run -it --rm -v$(pwd):/app dotenv/dotenvx run -- node index.js

    Or in any image:

    FROM node:latestRUNecho"HELLO=World"> .env&&echo"console.log('Hello ' + process.env.HELLO)"> index.jsRUN curl -fsS https://dotenvx.sh/install.sh| shCMD ["dotenvx","run","--","echo","Hello$HELLO"]

    seedocker guide

  • CI/CDs 🐙
    name:buildon:[push]jobs:build:runs-on:ubuntu-lateststeps:    -uses:actions/checkout@v3    -uses:actions/setup-node@v3with:node-version:16    -run:curl -fsS https://dotenvx.sh/install.sh | sh    -run:dotenvx run -- node build.jsenv:DOTENV_KEY:${{ secrets.DOTENV_KEY }}

    seegithub actions guide

  • Platforms
    # herokuheroku buildpacks:add https://github.com/dotenvx/heroku-buildpack-dotenvx# dockerRUN curl -fsS https://dotenvx.sh/install.sh| sh# vercelnpm install @dotenvx/dotenvx --save

    seeplatform guides

  • Process Managers
    // pm2"scripts":{"start":"dotenvx run -- pm2-runtime start ecosystem.config.js --env production"},

    seeprocess manager guides

  • 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@1.X.X] injecting env (1) from .env.productionHello World
  • asdf
    # use dotenvx with asdf$ asdf plugin add dotenvx$ asdf install dotenvx latest

    thank you@jgburet of Paris 🇫🇷

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

    # .envUSERNAME="username"DATABASE_URL="postgres://${USERNAME}@localhost/my_database"
    // index.jsconsole.log('DATABASE_URL',process.env.DATABASE_URL)
    $ dotenvx run --debug -- node index.js[dotenvx@0.14.1] injecting env (2) from .envDATABASE_URL postgres://username@localhost/my_database
  • Command Substitution

    Add the output of a command to one of your variables in your .env file.

    # .envDATABASE_URL="postgres://$(whoami)@localhost/my_database"
    // index.jsconsole.log('DATABASE_URL',process.env.DATABASE_URL)
    $ dotenvx run --debug -- node index.js[dotenvx@0.14.1] injecting env (1) from .envDATABASE_URL postgres://yourusername@localhost/my_database

 

Multiple Environments

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@1.X.X] injecting env (1) from .env.productionHello 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@1.X.X] injecting env (1) from .env.local,.envHellolocal

    Note subsequent files do NOT override pre-existing variables defined in previous files or env. This follows historic principle. For example, abovelocal wins – from the first file.

  • `--overload` flag
    $echo"HELLO=local"> .env.local$echo"HELLO=World"> .env$ dotenvx run -f .env.local -f .env --overload -- node index.js[dotenvx@1.X.X] injecting env (1) from .env.local,.envHello World

    Note that with--overload subsequent files DO override pre-existing variables defined in previous files.

  • `--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] HELLOset[dotenvx@1.X.X] injecting env (1) from .env.productionHello 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] HELLOset[dotenvx][debug] HELLOset to production[dotenvx@1.X.X] injecting env (1) from .env.productionHello production
  • `--quiet` flag

    Use--quiet to suppress all output (except errors).

    $echo"HELLO=production"> .env.production$ dotenvx run -f .env.production --quiet -- node index.jsHello production
  • `--log-level` flag

    Set--log-level to whatever you wish. For example, to suppress warnings (risky), set log level toerror:

    $echo"HELLO=production"> .env.production$ dotenvx run -f .env.production --log-level=error -- node index.jsHello production

    Available log levels areerror, warn, info, verbose, debug, silly

  • `--convention` flag

    Load envs usingNext.js' convention ordotenv-flow convention. Set--convention tonextjs orflow:

    $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.jsHello developmentlocal$ dotenvx run --convention=flow -- node index.jsHello developmentlocal

    (more conventions available upon request)

 

Encryption

Add encryption to your.env files with a single command. Usedotenvx encrypt.

$ dotenvx encrypt✔ encrypted (.env)

encrypted .env

ADOTENV_PUBLIC_KEY (encryption key) and aDOTENV_PRIVATE_KEY (decryption key) are generated using the same public-key cryptography asBitcoin.

More examples

  • `.env`
    $echo"HELLO=World"> .env$ dotenvx encrypt$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (2) from .envHello World
  • `.env.production`
    $echo"HELLO=Production"> .env.production$ dotenvx encrypt -f .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (2) from .env.productionHello Production

    Note theDOTENV_PRIVATE_KEY_PRODUCTION ends with_PRODUCTION. This instructsdotenvx run to load the.env.production file.

  • `.env.ci`
    $echo"HELLO=Ci"> .env.ci$ dotenvx encrypt -f .env.ci$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ DOTENV_PRIVATE_KEY_CI="<.env.ci private key>" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (2) from .env.ciHello Ci

    Note theDOTENV_PRIVATE_KEY_CI ends with_CI. This instructsdotenvx run to load the.env.ci file. See the pattern?

  • combine multiple encrypted .env files
    $ dotenvxset HELLO World -f .env$ dotenvxset HELLO Production -f .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ DOTENV_PRIVATE_KEY="<.env private key>" DOTENV_PRIVATE_KEY_PRODUCTION="<.env.production private key>" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (3) from .env, .env.productionHello World

    Note theDOTENV_PRIVATE_KEY instructsdotenvx run to load the.env file and theDOTENV_PRIVATE_KEY_PRODUCTION instructs it to load the.env.production file. See the pattern?

  • combine multiple encrypted .env files for monorepo
    $ mkdir app1$ mkdir app2$ dotenvxset HELLO app1 -f app1/.env.ci$ dotenvxset HELLO app2 -f app2/.env.ci$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ DOTENV_PRIVATE_KEY_CI="<app1/privat ci key>,<app2/private ci key>" dotenvx run -f app1/.env.ci -f app2/.env.ci -- node index.js[dotenvx@1.X.X] injecting env (2) from app1/.env.ci,app2/.env.ciHello app1$ DOTENV_PRIVATE_KEY_CI="<app1/privat ci key>,<app2/private ci key>" dotenvx run -f app1/.env.ci -f app2/.env.ci --overload -- node index.js[dotenvx@1.X.X] injecting env (2) from app1/.env.ci,app2/.env.ciHello app2

    Note theDOTENV_PRIVATE_KEY_CI (and anyDOTENV_PRIVATE_KEY*) can take multiple private keys by simply comma separating them.

  • `--stdout`
    $echo"HELLO=World"> .env$ dotenvx encrypt --stdout$ dotenvx encrypt --stdout> .env.encrypted
  • other curves

    secp256k1 is a well-known and battle tested curve, in use with Bitcoin and other cryptocurrencies, but we are open to adding support for more curves.

    If your organization's compliance department requiresNIST approved curves or other curves likecurve25519, please reach out atsecurity@dotenvx.com.

 

Advanced

Become adotenvx power user.

CLI 📟

Advanced CLI commands.

  • `run` - Variable Expansion

    Reference and expand variables already on your machine for use in your .env file.

    # .envUSERNAME="username"DATABASE_URL="postgres://${USERNAME}@localhost/my_database"
    // index.jsconsole.log('DATABASE_URL',process.env.DATABASE_URL)
    $ dotenvx run --debug -- node index.js[dotenvx@1.X.X] injecting env (2) from .envDATABASE_URL postgres://username@localhost/my_database
  • `run` - Command Substitution

    Add the output of a command to one of your variables in your .env file.

    # .envDATABASE_URL="postgres://$(whoami)@localhost/my_database"
    // index.jsconsole.log('DATABASE_URL',process.env.DATABASE_URL)
    $ dotenvx run --debug -- node index.js[dotenvx@1.X.X] injecting env (1) from .envDATABASE_URL postgres://yourusername@localhost/my_database
  • `run` - Shell Expansion

    Prevent your shell from expanding inline$VARIABLES before dotenvx has a chance to inject it. Use a subshell.

    $ dotenvx run --env="HELLO=World" -- sh -c'echo Hello $HELLO'Hello World
  • `run` - multiple `-f` flags

    Compose multiple.env files for environment variables loading, as you need.

    $echo"HELLO=local"> .env.local$echo"HELLO=World"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.local -f .env -- node index.js[dotenvx@1.X.X] injecting env (1) from .env.local, .envHellolocal

    Note subsequent files do NOT override pre-existing variables defined in previous files or env. This follows historic principle. For example, abovelocal wins – from the first file.

  • `run --env HELLO=String`

    Set environment variables as a simpleKEY=value string pair.

    $echo"HELLO=World"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run --env HELLO=String -f .env -- node index.js[dotenvx@1.X.X] injecting env (1) from .env, and --env flagHello String
  • `run --overload`

    Override existing env variables. These can be variables already on your machine or variables loaded as files consecutively. The last variable seen will 'win'.

    $echo"HELLO=local"> .env.local$echo"HELLO=World"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.local -f .env --overload -- node index.js[dotenvx@1.X.X] injecting env (1) from .env.local, .envHello World

    Note that with--overload subsequent files DO override pre-existing variables defined in previous files.

  • `DOTENV_PRIVATE_KEY=key run`

    Decrypt your encrypted.env by settingDOTENV_PRIVATE_KEY beforedotenvx run.

    $ touch .env$ dotenvxset HELLO encrypted$echo"console.log('Hello ' + process.env.HELLO)"> index.js# check your .env.keys files for your privateKey$ DOTENV_PRIVATE_KEY="122...0b8" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (2) from .envHello encrypted
  • `DOTENV_PRIVATE_KEY_PRODUCTION=key run`

    Decrypt your encrypted.env.production by settingDOTENV_PRIVATE_KEY_PRODUCTION beforedotenvx run. Alternatively, this can be already set on your server or cloud provider.

    $ touch .env.production$ dotenvxset HELLO"production encrypted" -f .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js# check .env.keys for your privateKey$ DOTENV_PRIVATE_KEY_PRODUCTION="122...0b8" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (2) from .env.productionHello production encrypted

    Note theDOTENV_PRIVATE_KEY_PRODUCTION ends with_PRODUCTION. This instructs dotenvx run to load the.env.production file.

  • `DOTENV_PRIVATE_KEY_CI=key dotenvx run`

    Decrypt your encrypted.env.ci by settingDOTENV_PRIVATE_KEY_CI beforedotenvx run. Alternatively, this can be already set on your server or cloud provider.

    $ touch .env.ci$ dotenvxset HELLO"ci encrypted" -f .env.ci$echo"console.log('Hello ' + process.env.HELLO)"> index.js# check .env.keys for your privateKey$ DOTENV_PRIVATE_KEY_CI="122...0b8" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (2) from .env.ciHello ci encrypted

    Note theDOTENV_PRIVATE_KEY_CI ends with_CI. This instructs dotenvx run to load the.env.ci file. See the pattern?

  • `DOTENV_PRIVATE_KEY=key DOTENV_PRIVATE_KEY_PRODUCTION=key run` - Combine Multiple

    Decrypt your encrypted.env and.env.production files by settingDOTENV_PRIVATE_KEY andDOTENV_PRIVATE_KEY_PRODUCTION beforedotenvx run.

    $ touch .env$ touch .env.production$ dotenvxset HELLO encrypted$ dotenvxset HELLO"production encrypted" -f .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js# check .env.keys for your privateKeys$ DOTENV_PRIVATE_KEY="122...0b8" DOTENV_PRIVATE_KEY_PRODUCTION="122...0b8" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (3) from .env, .env.productionHello encrypted$ DOTENV_PRIVATE_KEY_PRODUCTION="122...0b8" DOTENV_PRIVATE_KEY="122...0b8" dotenvx run -- node index.js[dotenvx@1.X.X] injecting env (3) from .env.production, .envHello production encrypted

    Compose any encrypted files you want this way. As long as aDOTENV_PRIVATE_KEY_${environment} is set, the values from.env.${environment} will be decrypted at runtime.

  • `run --verbose`

    Set log level toverbose. (log levels)

    $echo"HELLO=production"> .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.production --verbose -- node index.jsloading env from .env.production (/path/to/.env.production)HELLOset[dotenvx@1.X.X] injecting env (1) from .env.productionHello production
  • `run --debug`

    Set log level todebug. (log levels)

    $echo"HELLO=production"> .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.production --debug -- node index.jsprocesscommand [node index.js]options: {"env":[],"envFile":[".env.production"]}loading env from .env.production (/path/to/.env.production){"HELLO":"production"}HELLOsetHELLOset to production[dotenvx@1.X.X] injecting env (1) from .env.productionexecuting processcommand [node index.js]expanding processcommand to [/opt/homebrew/bin/node index.js]Hello production
  • `run --quiet`

    Use--quiet to suppress all output (except errors). (log levels)

    $echo"HELLO=production"> .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.production --quiet -- node index.jsHello production
  • `run --log-level`

    Set--log-level to whatever you wish. For example, to suppress warnings (risky), set log level toerror:

    $echo"HELLO=production"> .env.production$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.production --log-level=error -- node index.jsHello production

    Available log levels areerror, warn, info, verbose, debug, silly (source)

  • `run --strict`

    Exit with code1 if any errors are encountered - like a missing .env file or decryption failure.

    $echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.missing --strict -- node index.js[MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)[MISSING_ENV_FILE]? add one with [echo"HELLO=World"> .env.missing]

    This can be useful inci scripts where you want to fail the ci if your.env file could not be decrypted at runtime.

  • `run --ignore`

    Ignore errors likeMISSING_ENV_FILE.

    $echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run -f .env.missing --ignore=MISSING_ENV_FILE -- node index.js...
  • `run --convention=nextjs`

    Load envs usingNext.js' convention. Set--convention tonextjs:

    $echo"HELLO=development local"> .env.development.local$echo"HELLO=local"> .env.local$echo"HELLO=development"> .env.development$echo"HELLO=env"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx run --convention=nextjs -- node index.js[dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.local, .env.development, .envHello developmentlocal

    (more conventions available upon request)

  • `run --convention=flow`

    Load envs usingdotenv-flow's convention. Set--convention toflow:

    $echo"HELLO=development local"> .env.development.local$echo"HELLO=development"> .env.development$echo"HELLO=local"> .env.local$echo"HELLO=env"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ NODE_ENV=development dotenvx run --convention=flow -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.development, .env.local, .envHello developmentlocal

    Further, we recommend usingDOTENV_ENV overNODE_ENV– asdotenvx works everywhere, not just node.

    $ DOTENV_ENV=development dotenvx run --convention=flow -- node index.js [dotenvx@1.X.X] injecting env (1) from .env.development.local, .env.development, .env.local, .envHello developmentlocal
  • `run -fk`

    Specify path to.env.keys. This is useful with monorepos.

    $ mkdir -p apps/app1$ touch apps/app1/.env$ dotenvxset HELLO world -fk .env.keys -f apps/app1/.env$ dotenvx run -fk .env.keys -f apps/app1/.env -- yourcommand
  • `get KEY`

    Return a single environment variable's value.

    $echo"HELLO=World"> .env$ dotenvx get HELLOWorld
  • `get KEY -f`

    Return a single environment variable's value from a specific.env file.

    $echo"HELLO=World"> .env$echo"HELLO=production"> .env.production$ dotenvx get HELLO -f .env.productionproduction
  • `get KEY -fk`

    Specify path to.env.keys. This is useful with monorepos.

    $ mkdir -p apps/app1$ touch apps/app1/.env$ dotenvxset HELLO world -fk .env.keys -f apps/app1/.env$ dotenvx get HELLO -fk .env.keys -f apps/app1/.envworld
  • `get KEY --env`

    Return a single environment variable's value from a--env string.

    $ dotenvx get HELLO --env HELLO=String -f .env.productionString
  • `get KEY --overload`

    Return a single environment variable's value where each found value is overloaded.

    $echo"HELLO=World"> .env$echo"HELLO=production"> .env.production$ dotenvx get HELLO -f .env.production --env HELLO=String -f .env --overloadWorld
  • `get KEY --strict`

    Exit with code1 if any errors are encountered - like a missing key, missing .env file, or decryption failure.

    $ dotenvx get DOES_NOT_EXIST --strict[MISSING_KEY] missing DOES_NOT_EXIST key
  • `get KEY --convention=nextjs`

    Return a single environment variable's value usingNext.js' convention. Set--convention tonextjs:

    $echo"HELLO=development local"> .env.development.local$echo"HELLO=local"> .env.local$echo"HELLO=development"> .env.development$echo"HELLO=env"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ dotenvx get HELLO --convention=nextjsdevelopmentlocal
  • `get KEY --convention=flow`

    Return a single environment variable's value usingdotenv-flow's convention. Set--convention toflow:

    $echo"HELLO=development local"> .env.development.local$echo"HELLO=development"> .env.development$echo"HELLO=local"> .env.local$echo"HELLO=env"> .env$echo"console.log('Hello ' + process.env.HELLO)"> index.js$ NODE_ENV=development dotenvx get HELLO --convention=flowdevelopmentlocal

    Further, we recommend usingDOTENV_ENV overNODE_ENV– asdotenvx works everywhere, not just node.

    $ DOTENV_ENV=development dotenvx get HELLO --convention=flowdevelopmentlocal
  • `get` (json)

    Return a json response of all key/value pairs in a.env file.

    $echo"HELLO=World"> .env$ dotenvx get{"HELLO":"World"}
  • `get --format shell`

    Return a shell formatted response of all key/value pairs in a.env file.

    $echo"HELLO=World"> .env$echo"KEY=value">> .env$ dotenvx get --format shellHELLO=World KEY=value

    This can be useful when combined withenv on the command line.

    $ echo "console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)" > index.js$ env $(dotenvx get --format=shell) node index.jsHello value World

    or withexport.

    $ echo "console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)" > index.js$ export $(dotenvx get --format=shell)$ node index.jsHello value World
  • `get --format eval`

    Return aneval-ready shell formatted response of all key/value pairs in a.env file.

    $echo"HELLO=World"> .env$echo"KEY=value">> .env$ dotenvx get --formatevalHELLO="World"KEY="value"

    Note that this exports newlines and quoted strings.

    This can be useful for more complex .env values (spaces, escaped characters, quotes, etc) combined witheval on the command line.

    $echo"console.log('Hello ' + process.env.KEY + ' ' + process.env.HELLO)"> index.js$eval$(dotenvx get --format=eval) node index.jsHello value World

    Be careful witheval as it allows for arbitrary execution of commands. Preferdotenvx run -- but in some caseseval is a sharp knife that is useful to have.

  • `get --all`

    Return preset machine envs as well.

    $echo"HELLO=World"> .env$ dotenvx get --all{"PWD":"/some/file/path","USER":"username","LIBRARY_PATH":"/usr/local/lib", ...,"HELLO":"World"}
  • `get --all --pretty-print`

    Make the output more readable - pretty print it.

    $echo"HELLO=World"> .env$ dotenvx get --all --pretty-print{"PWD":"/some/filepath","USER":"username","LIBRARY_PATH":"/usr/local/lib",  ...,"HELLO":"World"}
  • `set KEY value`

    Set an encrypted key/value (on by default).

    $ touch .env$ dotenvxset HELLO Worldset HELLO with encryption (.env)
  • `set KEY value -f`

    Set an (encrypted) key/value for another.env file.

    $ touch .env.production$ dotenvxset HELLO production -f .env.productionset HELLO with encryption (.env.production)
  • `set KEY value -fk`

    Specify path to.env.keys. This is useful with monorepos.

    $ mkdir -p apps/app1$ touch apps/app1/.env$ dotenvxset HELLO world -fk .env.keys -f apps/app1/.envset HELLO with encryption (.env)

    Put it to use.

    $ dotenvx get -fk .env.keys -f apps/app1/.env

    Use it with a relative path.

    $cd apps/app1$ dotenvx get -fk ../../.env.keys -f .env
  • `set KEY "value with spaces"`

    Set a value containing spaces.

    $ touch .env.ci$ dotenvxset HELLO"my ci" -f .env.ciset HELLO with encryption (.env.ci)
  • `set KEY -- "- + * ÷"`

    If your value starts with a dash (-), then place two dashes instructing the cli that there are no more flag arguments.

    $ touch .env.ci$ dotenvxset HELLO -f .env.ci --"- + * ÷"set HELLO with encryption (.env.ci)
  • `set KEY value --plain`

    Set a plaintext key/value.

    $ touch .env$ dotenvxset HELLO World --plainset HELLO (.env)
  • `encrypt`

    Encrypt the contents of a.env file to an encrypted.env file.

    $echo"HELLO=World"> .env$ dotenvx encrypt✔ encrypted (.env)✔ key added to .env.keys (DOTENV_PRIVATE_KEY)⮕  next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys⮕  next run [DOTENV_PRIVATE_KEY='122...0b8' dotenvx run -- yourcommand] totest decryption locally
  • `encrypt -f`

    Encrypt the contents of a specified.env file to an encrypted.env file.

    $echo"HELLO=World"> .env$echo"HELLO=Production"> .env.production$ dotenvx encrypt -f .env.production✔ encrypted (.env.production)✔ key added to .env.keys (DOTENV_PRIVATE_KEY_PRODUCTION)⮕  next run [dotenvx ext gitignore --pattern .env.keys] to gitignore .env.keys⮕  next run [DOTENV_PRIVATE_KEY='bff...bc4' dotenvx run -- yourcommand] totest decryption locally
  • `encrypt -fk`

    Specify path to.env.keys. This is useful with monorepos.

    $ mkdir -p apps/app1$echo"HELLO=World"> apps/app1/.env$ dotenvx encrypt -fk .env.keys -f apps/app1/.env✔ encrypted (apps/app1/.env)

    Put it to use.

    $ dotenvx run -fk .env.keys -f apps/app1/.env

    Use with a relative path.

    $cd apps/app1$ dotenvx run -fk ../../.env.keys -f .env
  • `encrypt -k`

    Specify the key(s) to encrypt by passing--key.

    $echo"HELLO=World\nHELLO2=Universe"> .env$ dotenvx encrypt -k HELLO2✔ encrypted (.env)

    Even specify a glob pattern.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt -k"HE*"✔ encrypted (.env)
  • `encrypt -ek`

    Specify the key(s) to NOT encrypt by passing--exclude-key.

    $echo"HELLO=World\nHELLO2=Universe"> .env$ dotenvx encrypt -ek HELLO✔ encrypted (.env)

    Even specify a glob pattern.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt -ek"HO*"✔ encrypted (.env)
  • `encrypt --stdout`

    Encrypt the contents of a.env file and send to stdout.

    $echo"HELLO=World"> .env$ dotenvx encrypt --stdout#/-------------------[DOTENV_PUBLIC_KEY]--------------------/#/            public-key encryption for .env files          /#/       [how it works](https://dotenvx.com/encryption)     /#/----------------------------------------------------------/DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45"# .envHELLO="encrypted:BDqDBibm4wsYqMpCjTQ6BsDHmMadg9K3dAt+Z9HPMfLEIRVz50hmLXPXRuDBXaJi/LwWYEVUNiq0HISrslzQPaoyS8Lotg3gFWJTsNCdOWnqpjF2xNUX2RQiP05kAbEXM6MWVjDr"

    or send to a file:

    $echo"HELLO=World"> .env$ dotenvx encrypt --stdout> somefile.txt
  • `decrypt`

    Decrypt the contents of an encrypted.env file to an unencrypted.env file.

    $echo"HELLO=World"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx decrypt✔ decrypted (.env)
  • `decrypt -f`

    Decrypt the contents of a specified encrypted.env file to an unencrypted.env file.

    $echo"HELLO=World"> .env$echo"HELLO=Production"> .env.production$ dotenvx encrypt -f .env.production✔ encrypted (.env.production)$ dotenvx decrypt -f .env.production✔ decrypted (.env.production)
  • `decrypt -fk`

    Specify path to.env.keys. This is useful with monorepos.

    $ mkdir -p apps/app1$echo"HELLO=World"> apps/app1/.env$ dotenvx encrypt -fk .env.keys -f apps/app1/.env✔ encrypted (apps/app1/.env)$ dotenvx decrypt -fk .env.keys -f apps/app1/.env✔ decrypted (apps/app1/.env)
  • `decrypt -k`

    Decrypt the contents of a specified key inside an encrypted.env file.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx decrypt -k HELLO✔ decrypted (.env)

    Even specify a glob pattern.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx decrypt -k"HE*"✔ encrypted (.env)
  • `decrypt -ek`

    Decrypt the contents inside an encrypted.env file except for an excluded key.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx decrypt -ek HOLA✔ decrypted (.env)

    Even specify a glob pattern.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx decrypt -ek"HO*"✔ encrypted (.env)
  • `decrypt --stdout`

    Decrypt the contents of an encrypted.env file and send to stdout.

    $ dotenvx decrypt --stdout#/-------------------[DOTENV_PUBLIC_KEY]--------------------/#/            public-key encryption for .env files          /#/       [how it works](https://dotenvx.com/encryption)     /#/----------------------------------------------------------/DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45"# .envHELLO="World"

    or send to a file:

    $ dotenvx decrypt --stdout> somefile.txt
  • `keypair`

    Print public/private keys for.env file.

    $echo"HELLO=World"> .env$ dotenvx encrypt$ dotenvx keypair{"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
  • `keypair -f`

    Print public/private keys for.env.production file.

    $echo"HELLO=Production"> .env.production$ dotenvx encrypt -f .env.production$ dotenvx keypair -f .env.production{"DOTENV_PUBLIC_KEY_PRODUCTION":"<publicKey>","DOTENV_PRIVATE_KEY_PRODUCTION":"<privateKey>"}
  • `keypair -fk`

    Specify path to.env.keys. This is useful for printing public/private keys for monorepos.

    $ mkdir -p apps/app1$echo"HELLO=World"> apps/app1/.env$ dotenvx encrypt -fk .env.keys -f apps/app1/.env$ dotenvx keypair -fk .env.keys -f apps/app1/.env{"DOTENV_PUBLIC_KEY":"<publicKey>","DOTENV_PRIVATE_KEY":"<privateKey>"}
  • `keypair DOTENV_PRIVATE_KEY`

    Print specific keypair for.env file.

    $echo"HELLO=World"> .env$ dotenvx encrypt$ dotenvx keypair DOTENV_PRIVATE_KEY<privateKey>
  • `keypair --format shell`

    Print a shell formatted response of public/private keys.

    $echo"HELLO=World"> .env$ dotenx encrypt$ dotenvx keypair --format shellDOTENV_PUBLIC_KEY=<publicKey> DOTENV_PRIVATE_KEY=<privateKey>
  • `ls`

    Print all.env files in a tree structure.

    $ touch .env$ touch .env.production$ mkdir -p apps/backend$ touch apps/backend/.env$ dotenvx ls├─ .env.production├─ .env└─ apps   └─ backend      └─ .env
  • `ls directory`

    Print all.env files inside a specified path to a directory.

    $ touch .env$ touch .env.production$ mkdir -p apps/backend$ touch apps/backend/.env$ dotenvx ls apps/backend└─ .env
  • `ls -f`

    Glob.env filenames matching a wildcard.

    $ touch .env$ touch .env.production$ mkdir -p apps/backend$ touch apps/backend/.env$ touch apps/backend/.env.prod$ dotenvx ls -f**/.env.prod*├─ .env.production└─ apps   └─ backend      └─ .env.prod
  • `ls -ef`

    Glob.env filenames excluding a wildcard.

    $ touch .env$ touch .env.production$ mkdir -p apps/backend$ touch apps/backend/.env$ touch apps/backend/.env.prod$ dotenvx ls -ef'**/.env.prod*'├─ .env└─ apps   └─ backend      └─ .env
  • `rotate`

    Rotate public/private keys for.env file and re-encrypt all encrypted values.

    $echo"HELLO=World"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx rotate✔ rotated (.env)
  • `rotate -f`

    Rotate public/private keys for a specified encrypted.env file and re-encrypt all encrypted values.

    $echo"HELLO=World"> .env$echo"HELLO=Production"> .env.production$ dotenvx encrypt -f .env.production✔ encrypted (.env.production)$ dotenvx rotate -f .env.production✔ rotated (.env.production)
  • `rotate -fk`

    Specify path to.env.keys. This is useful with monorepos.

    $ mkdir -p apps/app1$echo"HELLO=World"> apps/app1/.env$ dotenvx encrypt -fk .env.keys -f apps/app1/.env✔ encrypted (apps/app1/.env)$ dotenvx rotate -fk .env.keys -f apps/app1/.env✔ rotated (apps/app1/.env)
  • `rotate -k`

    Rotate the contents of a specified key inside an encrypted.env file.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx rotate -k HELLO✔ rotated (.env)

    Even specify a glob pattern.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx rotate -k"HE*"✔ rotated (.env)
  • `rotate -ek`

    Rotate the encrypted contents inside an encrypted.env file except for an excluded key.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx rotate -ek HOLA✔ rotated (.env)

    Even specify a glob pattern.

    $echo"HELLO=World\nHOLA=Mundo"> .env$ dotenvx encrypt✔ encrypted (.env)$ dotenvx rotate -ek"HO*"✔ rotated (.env)
  • `rotate --stdout`

    Rotate the contents of an encrypted.env file and send to stdout.

    $ dotenvx rotate --stdout#/-------------------[DOTENV_PUBLIC_KEY]--------------------/#/            public-key encryption for .env files          /#/       [how it works](https://dotenvx.com/encryption)     /#/----------------------------------------------------------/DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e47291066946cce2e8d98c9e02c741ced45"# .envHELLO="encrypted:12345"

    or send to a file:

    $ dotenvx rotate --stdout> somefile.txt
  • `help`

    Output help fordotenvx.

    $ dotenvxhelpUsage: dotenvx run -- yourcommanda better dotenv–from the creator of`dotenv`Options:  -l, --log-level<level>set log level (default:"info")  -q, --quiet                  sets log level to error  -v, --verbose                sets log level to verbose  -d, --debug                  sets log level to debug  -V, --version                output the version number  -h, --help                   displayhelpforcommandCommands:  run                inject env at runtime [dotenvx run -- yourcommand]  get [KEY]return a single environment variableset<KEY><value>set a single environment variable  encrypt            convert .env file(s) to encrypted .env file(s)  decrypt            convert encrypted .env file(s) to plain .env file(s)  keypair [KEY]      print public/private keysfor .env file(s)  ls [directory]     print all .env filesin a tree structure Advanced:   pro                          🏆 pro  ext                          🔌 extensions

    You can get more detailed help per command withdotenvx help COMMAND.

    $ dotenvxhelp runUsage: @dotenvx/dotenvx run [options]inject env at runtime [dotenvx run -- yourcommand]Options:  -e, --env<strings...>            environment variable(s)set as string (example:"HELLO=World") (default: [])  -f, --env-file<paths...>         path(s) to your env file(s) (default: [])  -fv, --env-vault-file<paths...>  path(s) to your .env.vault file(s) (default: [])  -o, --overload                    override existing env variables  --convention<name>               load a .env convention (available conventions: ['nextjs'])  -h, --help                        displayhelpforcommandExamples:  $ dotenvx run -- npm run dev  $ dotenvx run -- flask --app index run  $ dotenvx run -- php artisan serve  $ dotenvx run -- bin/rails sTry it:  $echo"HELLO=World"> .env  $echo"console.log('Hello ' + process.env.HELLO)"> index.js  $ dotenvx run -- node index.js  [dotenvx@1.X.X] injecting env (1) from .env  Hello World
  • `--version`

    Check current version ofdotenvx.

    $ dotenvx --versionX.X.X

Extensions 🔌

CLI extensions.

  • `ext genexample`

    In one command, generate a.env.example file from your current.env file contents.

    $echo"HELLO=World"> .env$ dotenvx ext genexample✔ updated .env.example (1)
    # .env.exampleHELLO=""
  • `ext genexample -f`

    Pass multiple.env files to generate your.env.example file from the combination of their contents.

    $echo"HELLO=World"> .env$echo"DB_HOST=example.com"> .env.production$ dotenvx ext genexample -f .env -f .env.production✔ updated .env.example (2)
    # .env.exampleHELLO=""DB_HOST=""
  • `ext genexample directory`

    Generate a.env.example file inside the specified directory. Useful for monorepos.

    $echo"HELLO=World"> .env$ mkdir -p apps/backend$echo"HELLO=Backend"> apps/backend/.env$ dotenvx ext genexample apps/backend✔ updated .env.example (1)
    # apps/backend/.env.exampleHELLO=""
  • `ext gitignore`

    Gitignore your.env files.

    $ dotenvx ext gitignore✔ ignored .env* (.gitignore)
  • `ext gitignore --pattern`

    Gitignore specific pattern(s) of.env files.

    $ dotenvx ext gitignore --pattern .env.keys✔ ignored .env.keys (.gitignore)
  • `ext precommit`

    Prevent.env files from being committed to code.

    $ dotenvx ext precommit[dotenvx][precommit] .env files (1) protected (encrypted or gitignored)
  • `ext precommit --install`

    Install a shell script to.git/hooks/pre-commit to prevent accidentally committing any.env files to source control.

    $ dotenvx ext precommit --install[dotenvx][precommit] dotenvx ext precommit installed [.git/hooks/pre-commit]
  • `ext prebuild`

    Prevent.env files from being built into your docker containers.

    Add it to yourDockerfile.

    # DockerfileRUN curl -fsS https://dotenvx.sh| sh...RUN dotenvx ext prebuildCMD ["dotenvx","run","--","node","index.js"]
  • `ext scan`

    Usegitleaks under the hood to scan for possible secrets in your code.

    $ dotenvx ext scan    ○    │╲    │ ○    ○ ░    ░    gitleaks100 commits scanned.no leaks found

Library 📦

Use dotenvx directly in code.

  • `config()`

    Use directly in node.js code.

    # .envHELLO="World"
    // index.jsrequire('@dotenvx/dotenvx').config()console.log(`Hello${process.env.HELLO}`)
    $ node index.js[dotenvx@1.X.X] injecting env (1) from .envHello World

    It defaults to looking for a.env file.

  • `config(path: ['.env.local', '.env'])` - multiple files

    Specify path(s) to multiple .env files.

    # .env.localHELLO="Me"
    # .envHELLO="World"
    // index.jsrequire('@dotenvx/dotenvx').config({path:['.env.local','.env']})console.log(`Hello${process.env.HELLO}`)
    $ node index.js[dotenvx@1.X.X] injecting env (1) from .env.local, .envHello Me
  • `config(overload: true)` - overload

    Useoverload to overwrite the prior set value.

    # .env.localHELLO="Me"
    # .envHELLO="World"
    // index.jsrequire('@dotenvx/dotenvx').config({path:['.env.local','.env'],overload:true})console.log(`Hello${process.env.HELLO}`)
    $ node index.js[dotenvx@1.X.X] injecting env (1) from .env.local, .envHello World
  • `config(strict: true)` - strict

    Usestrict to throw if an error is encountered - like a missing .env file.

    # .envHELLO="World"
    // index.jsrequire('@dotenvx/dotenvx').config({path:['.env.missing','.env'],strict:true})console.log(`Hello${process.env.HELLO}`)
    $ node index.jsError: [MISSING_ENV_FILE] missing .env.missing file (/path/to/.env.missing)
  • `config(ignore:)` - ignore

    Useignore to suppress specific errors likeMISSING_ENV_FILE.

    # .envHELLO="World"
    // index.jsrequire('@dotenvx/dotenvx').config({path:['.env.missing','.env'],ignore:['MISSING_ENV_FILE']})console.log(`Hello${process.env.HELLO}`)
    $ node index.js[dotenvx@1.X.X] injecting env (1) from .envHello World
  • `config(envKeysFile:)` - envKeysFile

    UseenvKeysFile to customize the path to your.env.keys file. This is useful with monorepos.

    # .envHELLO="World"
    // index.jsrequire('@dotenvx/dotenvx').config({path:['.env'],envKeysFile:'../../.env.keys'})
  • `parse(src)`

    Parse a.env string directly in node.js code.

    // index.jsconstdotenvx=require('@dotenvx/dotenvx')constsrc='HELLO=World'constparsed=dotenvx.parse(src)console.log(`Hello${parsed.HELLO}`)
    $ node index.jsHello World
  • `parse(src, {processEnv:})`

    Sometimes, you want to runparse without it accessingprocess.env. (You can pass a fake processEnv this way as well - sometimes useful.)

    // index.jsconstdotenvx=require('@dotenvx/dotenvx')constsrc='USER=Me'constparsed=dotenvx.parse(src,{processEnv:{}})console.log(`Hello${parsed.USER}`)
    $ node index.jsHello Me
  • `parse(src, {privateKey:})`

    Decrypt an encrypted.env string withprivateKey.

    // index.jsconstdotenvx=require('@dotenvx/dotenvx')constsrc='HELLO="encrypted:BE9Y7LKANx77X1pv1HnEoil93fPa5c9rpL/1ps48uaRT9zM8VR6mHx9yM+HktKdsPGIZELuZ7rr2mn1gScsmWitppAgE/1lVprNYBCqiYeaTcKXjDUXU5LfsEsflnAsDhT/kWG1l"'constparsed=dotenvx.parse(src,{privateKey:'a4547dcd9d3429615a3649bb79e87edb62ee6a74b007075e9141ae44f5fb412c'})console.log(`Hello${parsed.HELLO}`)
    $ node index.jsHello World
  • `set(KEY, value)`

    Programmatically set an environment variable.

    // index.jsconstdotenvx=require('@dotenvx/dotenvx')dotenvx.set('HELLO','World',{path:'.env'})
  • `get(KEY)` -Decryption at Access

    Programmatically get an environment variable at access/runtime.

    // index.jsconstdotenvx=require('@dotenvx/dotenvx')constdecryptedValue=dotenvx.get('HELLO')console.log(decryptedValue)

    This is known asDecryption at Access and is written about inthe whitepaper.

Whitepaper

Dotenvx: Reducing Secrets Risk with Cryptographic Separation

Abstract. An ideal secrets solution would not only centralize secrets but also contain the fallout of a breach. While secrets managers offer centralized storage and distribution, their design creates a large blast radius, risking exposure of thousands or even millions of secrets. We propose a solution that reduces the blast radius by splitting secrets management into two distinct components: an encrypted secrets file and a separate decryption key.

...

Read the whitepaper

 

Guides

Go deeper withdotenvx – detailed framework and platform guides.

 

FAQ

How does encryption work?

Dotenvx uses Elliptic Curve Integrated Encryption Scheme (ECIES) to encrypt each secret with a unique ephemeral key, while ensuring it can be decrypted using a long-term private key.

When you initialize encryption, a DOTENV_PUBLIC_KEY (encryption key) and DOTENV_PRIVATE_KEY (decryption key) are generated. The DOTENV_PUBLIC_KEY is used to encrypt secrets, and the DOTENV_PRIVATE_KEY is securely stored in your cloud secrets manager or .env.keys file.

Your encrypted .env file is then safely committed to code. Even if the file is exposed, secrets remain protected since decryption requires the separate DOTENV_PRIVATE_KEY, which is never stored alongside it. Readthe whitepaper for more details.

Is it safe to commit an encrypted .env file to code?

Yes. Dotenvx encrypts secrets using AES-256 with ephemeral keys, ensuring that even if the encrypted .env file is exposed, its contents remain secure. The encryption keys themselves are protected using Secp256k1 elliptic curve cryptography, which is widely used for secure key exchange in technologies like Bitcoin.

This means that every secret in the .env file is encrypted with a unique AES-256 key, and that key is further encrypted using a public key (Secp256k1). Even if an attacker obtains the encrypted .env file, they would still need the corresponding private key—stored separately in a secrets manager—to decrypt anything.

Breaking this encryption would require brute-forcing both AES-256 and elliptic curve cryptography, which is computationally infeasible with current technology. Readthe whitepaper for more details.

Why am I getting the errornode: .env: not found?

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

more context

What happened to the.env.vault file?

I've decided we should sunset it as a technological solution to this.

The.env.vault file got us far, but it had limitations such as:

  • Pull Requests - it was difficult to tell which key had been changed
  • Security - there was no mechanism to give a teammate the ability to encrypt without also giving them the ability to decrypt. Sometimes you just want to let a contractor encrypt a new value, but you don't want them to know the rest of the secrets.
  • Conceptual - it takes more mental energy to understand the.env.vault format. Encrypted values inside a.env file is easier to quickly grasp.
  • Combining Multiple Files - there was simply no mechanism to do this well with the.env.vault file format.

That said, the.env.vault tooling will still stick around for at least 1 year underdotenvx vault parent command. I'm still using it in projects as are many thousands of other people.

How do I migrate my.env.vault file(s) to encrypted.env files?

Run$ dotenvx ext vault migrate and follow the instructions.

 

Contributing

You can fork this repo and createpull requests or if you have questions or feedback:


[8]ページ先頭

©2009-2025 Movatter.jp