# .env
STRIPE_API_KEY=scr_12345
TWILIO_API_KEY=abcd1234
Format
.env files use a simple format – keys and values separated by an equal sign. Here's a complete example covering the common cases:
# .env — keep secrets out of code
# Lines starting with # are comments
# Keys: letters, digits, underscore (must not start with a digit)
DATABASE_URL=postgres://localhost/my_database
API_KEY="quoted value" # inline comment after the value
LITERAL='no ${interpolation}' # single quotes stay literal
# Interpolation (unquoted and double-quoted values)
HOST=localhost
URL=https://${HOST}/api
# Invalid keys — do not use:
# NO-WORK=
# 2MUCH=
# ÜBER=
Load values in your app with process.env (or your language’s equivalent).
console.log('Hello ' + process.env.HELLO)
It's a convenient and widely adopted format for separating your secrets and config from your code.
Use it with dotenvx
Dotenvx loads the values from your .env file and makes them available to your application. Preface your application's command with dotenvx run --.
$ dotenvx run -- your-app-boot-command
Encryption
.env files can be extended to support encryption. Preface each value with encrypted: followed by a secp256k1 encrypted string.
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY="03f98bf6e00bce6fdb933bc47738d671dffb75a916fa8c89854bdfa3483902632f"
# .env
HELLO="encrypted:BCV9qZmblsUm77IxgrEqY9t67qDVWQZg6jpogQhBWa9SaOCtvheEQ5/eUfPCigQ7KB6vN//6vFE+2+orG7LmUorWhe1JapWct6Dz58IY6mXi+ONs51F7TSed6R/T9e+lDBWYH04p"
Include the DOTENV_PUBLIC_KEY inside the .env file and commit it. It's encrypted, safe, and recommended.
$ dotenvx encrypt
Keys
For the sake of portability (and sanity), environment variable names (keys) must consist solely of letters, digits, and the underscore (_) and must not begin with a digit. In regex-speak, the names must match the following pattern:
[a-zA-Z_]+[a-zA-Z0-9_]*
Example keys:
DATABASE_URL # ok
foobar # ok (but not recommended. use upcase)
NO-WORK # <-- invalid !!!
ÜBER # <-- invalid !!!
2MUCH # <-- invalid !!!
Values
Values are to the right of the equals sign. They may be quoted. Using single quotes will prevent variables from being interpolated.
SIMPLE=xyz123
INTERPOLATED="Multiple\nLines"
NON_INTERPOLATED='raw text without variable interpolation'
MULTILINE = `long text here,
e.g. a private SSH key`
Syntax
Cheat sheet — what you write, and what you get:
| Input | Result |
|---|---|
# comment |
Ignored (comment line) |
(blank line) |
Ignored |
VAR=VAL |
VAL (interpolation on) |
VAR="VAL" |
VAL (interpolation on) |
VAR='VAL' |
VAL (literal, no interpolation) |
VAR=VAL # comment |
VAL |
VAR=VAL# not a comment |
VAL# not a comment |
VAR="VAL # not a comment" |
VAL # not a comment |
VAR="VAL" # comment |
VAL |
VAR='$OTHER' |
$OTHER |
VAR='${OTHER}' |
${OTHER} |
\" inside quotes |
Escaped quote |
\n \r \t \\
|
Supported in double-quoted values |
Comments
The hash-tag # symbol denotes a comment when on its own line or when it follows a quoted value. It is not treated as a comment when it appears within quotes.
# This is a comment
SECRET_KEY=YOURSECRETKEYGOESHERE # also a comment
SECRET_HASH="something-with-a-hash-#-this-is-not-a-comment"
Interpolation
Interpolation (also known as variable expansion) is supported in environment files. Interpolation is applied for unquoted and double-quoted values. Both braced (${VAR}) and unbraced ($VAR) expressions are supported.
- Direct interpolation:
${VAR}→ value ofVAR - Default value:
${VAR:-default}→ value ofVARif set and non-empty, otherwisedefault - Alternative value:
${VAR:+alternate}→ value ofalternateifVARis set and non-empty, otherwise empty
Command Substitution
Add the output of a command to one of your variables in your .env file. Command substitution is applied for unquoted and double-quoted values.
DATABASE_URL="postgres://$(whoami)@localhost/my_database"
History
The .env file format was introduced by Heroku in 2012 and popularized by the dotenv node and dotenv ruby libraries in 2013. Encryption support landed in May 2024.
A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could be made open source at any moment, without compromising any credentials. — The Twelve-Factor App