dotenv README

The project's README from github.com/motdotla/dotenv. As one markdown file: README.md.

If you like dotenv, you will probably love dotenvx – for encrypting .env files. Thank you for using dotenv. 🙏

dotenv NPM version downloads

dotenv

Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.

Watch the tutorial

 

Usage

Install it.

npm install dotenv --save

Create a .env file in the root of your project:

# .env
HELLO="Dotenv"
OPENAI_API_KEY="your-api-key-goes-here"

As early as possible in your application, import and configure dotenv:

// index.js
require('dotenv').config()
// or import 'dotenv/config' // for esm

console.log(`Hello ${process.env.HELLO}`)
$ node index.js
◇ injected env (2) from .env
Hello Dotenv

That's it. process.env now has the keys and values you defined in your .env file.

 

Advanced

ES6

Import with ES6:

import 'dotenv/config'

DOTENV_CONFIG_ENCODING, DOTENV_CONFIG_PATH, DOTENV_CONFIG_QUIET, DOTENV_CONFIG_DEBUG, DOTENV_CONFIG_OVERRIDE, DOTENV_CONFIG_SECURE, and DOTENV_CONFIG_FAST provide defaults for config() and dotenv run. Options/flags passed directly take precedence.

bun
bun add dotenv
yarn
yarn add dotenv
pnpm
pnpm add dotenv
deno
deno add dotenv
Monorepos

For monorepos with a structure like apps/backend/app.js, put it the .env file in the root of the folder where your app.js process runs.

# app/backend/.env
S3_BUCKET="YOURS3BUCKET"
SECRET_KEY="YOURSECRETKEYGOESHERE"
Multiline Values

If you need multiline variables, for example private keys, those are now supported (>= v15.0.0) with line breaks:

PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
Kh9NV...
...
-----END RSA PRIVATE KEY-----"

Alternatively, you can double quote strings and use the \n character:

PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n"
Comments

Comments may be added to your file on their own line or inline:

# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # comment
SECRET_HASH="something-with-a-#-hash"

Comments begin where a # exists, so if your value contains a # please wrap it in quotes. This is a breaking change from >= v15.0.0 and on.

Parsing

The engine which parses the contents of your file containing environment variables is available to use. It accepts a String or Buffer and will return an Object with the parsed keys and values.

const dotenv = require('dotenv')
const buf = Buffer.from('BASIC=basic')
const config = dotenv.parse(buf) // will return an object
console.log(typeof config, config) // object { BASIC : 'basic' }
Run

Use dotenv run -- to run a command with environment variables from your .env file.

$ dotenv run -- node index.js
◇ injected env (2) from .env

Use -f to select one or more .env files.

$ dotenv run -f .env.local -f .env -- node index.js
◇ injected env (2) from .env.local, .env

Use --quiet to suppress the injected env message.

$ dotenv run --quiet -- node index.js

Use --override to overwrite existing environment variables, and --debug for debug logging.

$ dotenv run --override --debug -- node index.js

Use --secure or config({ secure: true }) to decrypt via dotenvx.

$ npm i @dotenvx/dotenvx
$ dotenv run --secure -- node index.js
require('dotenv').config({ secure: true })

Or with an environment variable:

$ DOTENV_CONFIG_SECURE=true dotenv run -- node index.js
$ DOTENV_CONFIG_SECURE=true node -e "require('dotenv').config()"

dotenv run --secure resolves local @dotenvx/dotenvx then dotenvx on your PATH. config({ secure: true }) requires a local @dotenvx/dotenvx install.

If your .env contains encrypted: values and you run without --secure / secure: true, dotenv warns and leaves them encrypted.

The same DOTENV_CONFIG_* environment variables formerly used by preload still work with the CLI. CLI flags take precedence.

$ DOTENV_CONFIG_PATH=./.env.local DOTENV_CONFIG_QUIET=true dotenv run -- node index.js

Use --fast (or config({ fast: true })) for the faster character-scanner parser (~2x). Default remains the classic regex parser.

$ dotenv run --fast -- node index.js
require('dotenv').config({ fast: true })

Supported: DOTENV_CONFIG_PATH, DOTENV_CONFIG_ENCODING, DOTENV_CONFIG_QUIET, DOTENV_CONFIG_DEBUG, DOTENV_CONFIG_OVERRIDE, DOTENV_CONFIG_SECURE, DOTENV_CONFIG_FAST.

Variable Expansion

Use dotenvx for 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
⟐ injected env (2) from .env · [email protected]
DATABASE_URL postgres://username@localhost/my_database
Command Substitution

Use dotenvx for 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
⟐ injected env (1) from .env · [email protected]
DATABASE_URL postgres://yourusername@localhost/my_database
Encryption

Use dotenvx for encryption.

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

$ dotenvx set HELLO Production -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
⟐ injected env (2) from .env.production · [email protected]
Hello Production

learn more

Multiple Environments

Use dotenvx to manage multiple environments.

Run any environment locally. Create a .env.ENVIRONMENT 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
Hello production
> ^^

or with multiple .env files

$ 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
Hello local

more environment examples

Production

Use dotenvx for production deploys.

Create a .env.production file.

$ echo "HELLO=production" > .env.production

Encrypt it.

$ dotenvx encrypt -f .env.production

Set DOTENV_PRIVATE_KEY_PRODUCTION (found in .env.keys) on your server.

$ heroku config:set DOTENV_PRIVATE_KEY_PRODUCTION=value

Commit your .env.production file to code and deploy.

$ git add .env.production
$ git commit -m "encrypted .env.production"
$ git push heroku main

Dotenvx will decrypt and inject the secrets at runtime using dotenvx run -- node index.js.

Syncing

Use dotenvx to sync your .env files.

Encrypt them with dotenvx encrypt -f .env and safely include them in source control. Your secrets are securely synced with your git.

This still subscribes to the twelve-factor app rules by generating a decryption key separate from code.

More Examples

See examples of using dotenv with various frameworks, languages, and configurations.

 

FAQ

Should I commit my `.env` file?

No.

Unless you encrypt it with dotenvx. Then we recommend you do.

What about variable expansion?

Use dotenvx.

Should I have multiple `.env` files?

We recommend creating one .env file per environment. Use .env for local/development, .env.production for production and so on. This still follows the twelve factor principles as each is attributed individually to its own environment. Avoid custom set ups that work in inheritance somehow (.env.production inherits values from .env for example). It is better to duplicate values if necessary across each .env.environment file.

In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.

– The Twelve-Factor App

Additionally, we recommend using dotenvx to encrypt and manage these.

How do I use dotenv with `import`?

Import dotenv/config before modules that read environment variables.

// index.mjs (ESM)
import 'dotenv/config'
import express from 'express'

This loads environment variables before the rest of your application modules are initialized. You can also use the CLI to inject them before Node starts:

dotenv run -- node index.mjs
Can I customize/write plugins for dotenv?

Yes! dotenv.config() returns an object representing the parsed .env file. This gives you everything you need to continue setting values on process.env. For example:

const dotenv = require('dotenv')
const variableExpansion = require('dotenv-expand')
const myEnv = dotenv.config()
variableExpansion(myEnv)
What rules does the parsing engine follow?

The parsing engine currently supports the following rules:

  • BASIC=basic becomes {BASIC: 'basic'}
  • empty lines are skipped
  • lines beginning with # are treated as comments
  • # marks the beginning of a comment (unless when the value is wrapped in quotes)
  • empty values become empty strings (EMPTY= becomes {EMPTY: ''})
  • inner quotes are maintained (think JSON) (JSON={"foo": "bar"} becomes {JSON:"{\"foo\": \"bar\"}")
  • whitespace is removed from both ends of unquoted values (see more on trim) (FOO= some value becomes {FOO: 'some value'})
  • single and double quoted values are escaped (SINGLE_QUOTE='quoted' becomes {SINGLE_QUOTE: "quoted"})
  • single and double quoted values maintain whitespace from both ends (FOO=" some value " becomes {FOO: ' some value '})
  • double quoted values expand new lines (MULTILINE="new\nline" becomes
{MULTILINE: 'new
line'}
  • backticks are supported (BACKTICK_KEY=`This has 'single' and "double" quotes inside of it.`)
What about syncing and securing .env files?

Use dotenvx to unlock syncing encrypted .env files over git.

How do I specify config options with ES6 import?

Pass options directly to config().

// index.mjs
import dotenv from 'dotenv'

dotenv.config({
  path: '/custom/path/to/.env',
  debug: true
})

import express from 'express'

If imported modules read environment variables during initialization, use a tiny wrapper file.

Create load-env.mjs:

import dotenv from 'dotenv'
dotenv.config({ path: '/custom/path/to/.env', debug: true })

Then in your main file:

import './load-env.mjs'
import express from 'express'
What if I accidentally commit my `.env` file to code?

Remove it, remove git history and then install the git pre-commit hook to prevent this from ever happening again.

npm i -g @dotenvx/dotenvx
dotenvx precommit --install
What happens to environment variables that were already set?

By default, we will never modify any environment variables that have already been set. In particular, if there is a variable in your .env file which collides with one that already exists in your environment, then that variable will be skipped.

If instead, you want to override process.env use the override option.

require('dotenv').config({ override: true })
How can I prevent committing my `.env` file to a Docker build?

Use the docker prebuild hook.

# Dockerfile
...
RUN curl -fsS https://dotenvx.sh/ | sh
...
RUN dotenvx prebuild
CMD ["dotenvx", "run", "--", "node", "index.js"]
How come my environment variables are not showing up for React?

Your React code is run in Webpack, where the fs module or even the process global itself are not accessible out-of-the-box. process.env can only be injected through Webpack configuration.

If you are using react-scripts, which is distributed through create-react-app, it has dotenv built in but with a quirk. Preface your environment variables with REACT_APP_. See this stack overflow for more details.

If you are using other frameworks (e.g. Next.js, Gatsby...), you need to consult their documentation for how to inject environment variables into the client.

Why is the `.env` file not loading my environment variables successfully?

Most likely your .env file is not in the correct place. See this stack overflow.

Turn on debug mode and try again..

require('dotenv').config({ debug: true })

You will receive a helpful error outputted to your console.

Why am I getting the error `Module not found: Error: Can't resolve 'os|path'`?

You are using dotenv on the front-end and have not included a polyfill. Webpack < 5 used to include these for you. Do the following:

npm install node-polyfill-webpack-plugin

Configure your webpack.config.js to something like the following.

require('dotenv').config()

const path = require('path');
const webpack = require('webpack')

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new NodePolyfillPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        HELLO: JSON.stringify(process.env.HELLO)
      }
    }),
  ]
};

Alternatively, just use dotenv-webpack which does this and more behind the scenes for you.

 

Docs

Dotenv exposes four functions:

Config

config will read your .env file, parse the contents, assign it to process.env, and return an Object with a parsed key containing the loaded content or an error key if it failed.

const result = dotenv.config()

if (result.error) {
  throw result.error
}

console.log(result.parsed)

You can additionally, pass options to config.

Options

path

Default: path.resolve(process.cwd(), '.env')

Specify a custom path if your file containing environment variables is located elsewhere.

require('dotenv').config({ path: '/custom/path/to/.env' })

You can also pass a URL object:

const fileUrl = new URL('file:///custom/path/to/.env')

require('dotenv').config({ path: fileUrl })

By default, config will look for a file called .env in the current working directory.

Pass in multiple files as an array, and they will be parsed in order and combined with process.env (or option.processEnv, if set). The first value set for a variable will win, unless the options.override flag is set, in which case the last value set will win. If a value already exists in process.env and the `options

dotenv (motdotla/dotenv)

Searching Database…

20.5K ·GitHub
Что это такое?Node.js-модуль без единой зависимости, который загружает переменные окружения из файла .env в process.env, следуя принципу Twelve-Factor App: конфигурация хранится отдельно от кода.
Это библиотека или утилита командной строки?В первую очередь это npm-библиотека, которую вы подключаете в своё приложение, но в пакет также входит CLI: команда dotenv run -- запускает любую команду, уже подставив переменные из вашего .env.
Как подключить его в своём проекте?npm install dotenv, добавьте файл .env со строками вида KEY=value в корень проекта, затем настройте его как можно раньше: require('dotenv').config() или import 'dotenv/config'. Все ключи окажутся в process.env.
Нужно ли что-то ещё, кроме установленного Node.js?Нет — у модуля ноль зависимостей, требуется Node.js 12 или новее; ставится через npm, yarn, pnpm, bun или deno.
Что будет, если переменная из моего .env уже задана в системе?dotenv никогда не трогает уже существующие переменные: конфликтующая запись из .env просто пропускается. Если нужно, чтобы значения из .env имели приоритет, передайте override: true (или --override в CLI).
Работает ли это в браузере, например внутри React-приложения?Напрямую нет: во фронтенд-коде нет модуля fs и глобального объекта process, поэтому переменные нужно подставлять через webpack. В react-scripts поддержка dotenv встроена, но наружу выдаются только переменные с префиксом REACT_APP_.
Может ли dotenv зашифровать мой .env-файл, или всё хранится в открытом виде?Обычный dotenv загружает только незашифрованные файлы — шифрование это территория dotenvx. С опцией --secure или config({ secure: true }) он расшифровывает значения encrypted: при загрузке; без неё dotenv лишь выдаёт предупреждение и оставляет их зашифрованными.
Что такое dotenvx и почему README постоянно о нём упоминает?Это сопутствующий инструмент от того же проекта, который закрывает то, что сам dotenv сознательно не делает: шифрование .env-файлов, подстановку переменных, подстановку вывода команд, синхронизацию зашифрованных файлов через git и управление файлами для отдельных окружений вроде .env.production. Сам dotenv остаётся компактным загрузчиком без зависимостей.
Стоит ли коммитить .env-файл в git, как и остальной код?Нет — если только он не зашифрован с помощью dotenvx: в этом случае README даже рекомендует коммитить его, поскольку ключ расшифровки лежит вне репозитория. Если вы случайно закоммитили обычный .env, удалите его, вычистите историю git и добавьте pre-commit-хук.
Что вообще можно писать внутри .env-файла?Строки вида KEY=value, комментарии на отдельной строке или в строке со значением, значения в одинарных и двойных кавычках, обратные кавычки и многострочные значения, например приватные ключи (поддержка с версии v15). Один нюанс: символ # внутри значения без кавычек начинает комментарий, поэтому такие значения берите в кавычки.
Можно ли загрузить сразу несколько .env-файлов?Да — передайте массив путей в config() или используйте флаг -f в CLI. Файлы разбираются по порядку и объединяются, и для каждой переменной остаётся первое найденное значение. В FAQ советуют держать один файл на окружение, а не делать файлы, наследующие друг от друга.
Creator
motdotla
Size
3.3 MB
Stars
20.5K
Updated
CommitOct 16
Age
13y
Commits · 90 Days