What is Dotenvx? Dotenvx encrypts your .env files—limiting their attack vector while retaining their benefits.
dotenvx-rs is a Rust command-line toolchain for dotenvx to make .env files secure and easy to use, and it's also a crate to load encrypted .env files in your Rust applications.
Please read dotenvx cheat sheet for quick overview.
Run cargo add dotenvx-rs
to add the dotenvx library to your Rust project.
use dotenvx_rs::dotenvx;
#[test]
fn test_dotenv_load() {
// Load the .env file
dotenvx::dotenv().ok();
// Check if the environment variable is set
let value = env::var("HELLO").unwrap();
println!("HELLO={}", value);
}
- Install: Run
cargo binstall dotenvx-rs
orbrew install linux-china/tap/dotenvx-rs
or download it from releases - Initialize: Run
dotenvx init
to create.env
and save private to global$HOME/.dotenvx/.env.keys.json
file - Encrypt .env file: Run
dotenvx encrypt
to encrypt the.env
file. - Decrypt .env file: Run
dotenvx decrypt
to decrypt the.env
file.
dotenvx Rust CLI is almost a drop-in replacement for the original dotenvx CLI, with some differences:
- Smaller and faster and written in Rust: the
dotenvx
executable is only 4MB. - Global keys store:
$HOME/.dotenvx/.env.keys.json
to prevent AI Agent to scan.env.keys
file in the project directory. - Spring Boot support: dotenvx CLI can read
application.properties
and spring profile. - Global
--profile
as first citizen to make it easy to manage different environments - More smaller features
- No ext sub command
If you have .env files already, you just run dotenvx init
, and dotenvx CLI will create .env
file with Dotenvx
format,
and save the private key to $HOME/.dotenvx/.env.keys.json
file.
Every .env file has three sections: metadata (front matter), public key, and environment variables.
Example as following:
# ---
# uuid: f7580ac5-0b24-4385-b3ff-819225b687f3
# name: identify-your-dotenv-file
# group: com.example.dotenvx
# sign: +1+y3Eio5OHPcp9xiP125qfXl/CX4Zuxhft91aW59WtTjZJoSDmFs4KPZ2nDop07VdYkE8vF2BWuUpneCU1xlA==
# ---
DOTENV_PUBLIC_KEY="02b4972559803fa3c2464e93858f80c3a4c86f046f725329f8975e007b393dc4f0"
# Environment variables. MAKE SURE to ENCRYPT them before committing to source control
HELLO=encrypted:BNexEwjKwt87k9aEgaSng1JY6uW8OkwMYEFTwEy/xyzDrQwQSDIUEXNlcwWi6rnvR1Q60G35NO4NWwhUYAaAON1LOnvMk+tJjTQJaM8DPeX2AJ8IzoTV44FLJsbOiMa77RLrnBv7
Explanation:
- Metadata section (front matter): starts with
# ---
and ends with# ---
- .env file UUID: a unique identifier for the .env file, used to track changes and versions
- sign: a signature for the .env file, used to verify the integrity of the file and make sure the file is not tampered
- DOTENV_PUBLIC_KEY: the public key used to encrypt data and verify the signature
- Environment variables: the encrypted environment variables, starts with
encrypted:
prefix
In metadata section, you can add any key-value pairs to describe the .env file, such as name
, group
, etc.
For .env.keys
files, and spec is similar, and metadata section and keys section are as following:
# ---
# uuid: 8499c5c3-cee3-4c94-99a4-9c86b2ed5dd9
# name: input your name here
# group: demo
# ---
# Private decryption keys. DO NOT commit to source control
DOTENV_PRIVATE_KEY="9e70188d351c25d0714929205df9bxxx"
DOTENV_PRIVATE_KEY_EXAMPLE="a3d15e4b69c4a942c381xxx"
A profile is a way to manage different environments in dotenvx CLI, and you can specify the profile with the following ways:
- Use
--profile <profile_name>
option to specify the profile, such asdotenvx -p prod encrypt
- Get profile from .env file, such as
.env.prod
forprod
profile,.env.test
fortest
profile, etc. - GEt profile from environment variables:
NODE_ENV
,RUN_ENV
,APP_ENV
,SPRING_PROFILES_ACTIVE
.
Different profiles have different .env
files, such as .env.prod
, .env.test
, .env.dev
, etc.,
and different profiles have different private keys for encryption and decryption,
such as DOTENV_PRIVATE_KEY_PROD
, DOTENV_PRIVATE_KEY_TEST
, etc.
If no profile is specified, the CLI will use the .env
file and DOTENV_PRIVATE_KEY
private key by default.
Tips: you can create alias for a profile, such as alias prod-env='dotenvx -p prod'
to manage secrets for
production profile.
In dotenvx, three profile styles are supported:
- project specific profile: such as
test
,prod
,dev
, etc., and you can use.env.test
,.env.prod
,.env.dev
files to manage different environments. - global profile: such as
g_github
,g_ai
, etc., and profile name start withg_
to indicate it's a global profile, and you can use.env.g_github
,.env.g_ai
files to manage different global environments. - namespace profile: such as
region1_dev
,region2_prod
, etc., and profile name start withregion1
to indicate it's a namespace profile, and you can use.env.region1_dev
,.env.region2_prod
files to manage different namespace environments.
The CLI looks for the private key in the following order:
- Check the
.env
orproperties
file to find the public key. - Find the private key from global
$HOME/.dotenvx/.env.keys.json
file. - If not found, find from
.env.keys
file in the current directory and parent directories recursively, and$HOME/.env.keys
will be checked as well. - Find from
DOTENV_PRIVATE_KEY
orDOTENV_PRIVATE_KEY_PROFILE_NAME
environment variable
If you want to use a unified private key for different environments, and you can use the following environment variables:
DOTENV_PRIVATE_KEY
for.env
file and local developmentDOTENV_PRIVATE_KEY_PROD
for.env.prod
file and productionDOTENV_PRIVATE_KEY_TEST
for.env.test
file and testing
Tips: you can use dotenvx init --stdout
to generate a key pair.
Attention: Some AI agents read environment variables for code generation by default, so you should avoid using
DOTENV_PRIVATE_KEY
, and use global $HOME/.dotenvx/.env.keys.json
. For CI/CD, production deployment,
environment variable for a private key is still a good choice.
dotenvx CLI uses profile style to manage private keys, and you can use following practices to manage private keys:
- Project specific private keys: use
dotenvx init
to create.env
file in the project's directory and save the private key to the$HOME/.dotenvx/.env.keys.json
file. - Global private: use
dotenvx init --global
to create a global$HOME/.env.keys
file to manage unified private keys for different projects. If you usedotenvx set <key> <value>
in a directory, it will create a.env
with public key derived fromDOTENV_PRIVATE_KEY
from$HOME/.env.keys
file. - Team/Production global private keys: use
ABC_TEST
,REGION1_PROD
as profile names to manage private keys for different teams, products, or regions.
If you don't want to use private key from environment variables, or you want to rotate your private key,
you can use the dotenvx rotate
command to generate a new key pair, examples:
- Rotate the private key for
.env
file:dotenvx rotate
- Rotate the private key for
.env.prod
file:dotenvx rotate -f .env.prod
You can use the dotenvx decrypt --export
command to decrypt the dotenv file and output as a shell script.
eval $( dotenvx decrypt --stdout --format shell )
command will decrypt a dotenv file and export the variables to the current shell.eval $( dotenvx get key --format shell )
command will export key's value from .env as environment variable.
Tips: if you use direnv, and you can add eval $( dotenvx decrypt --stdout --format shell )
to the .envrc
file to automatically load .env as the environment variables when you enter the directory.
If you use mise, and you can use dotenvx as environment provider by adding the following to the
mise.toml
file:
[env]
_.source = "scripts/env.sh"
And create a scripts/env.sh
file as following:
eval $( dotenvx decrypt --stdout --format shell )
You can integrate dotenvx CLI with any language SDK by using dotenvx decrypt --stdout --format shell
command to load
.env
into the environment variables.
For example, Node.js, Bun and Deno, you can create a wrapper script to integrate Dotenvx support,
such as node
, denow
, bunw
, and example as following:
#!/bin/bash
# load .env by dotenvx
eval $( dotenvx decrypt --stdout --format shell )
# Execute bun command with arguments
exec $HOME/.bun/bin/bun "$@"
In VS Code or WebStorm, then choose nodew
, denow
, bunw
as the interpreter.
Dotenvx has built-in support for Python virtual environment, you can use dotenvx link .venv/bin/python
to create a wrapper script as python interpreter.
Tips: you can use luaw
, phpw
, perlw
etc. to manage other language SDKs.
Dotenvx symbolic link is a way to run the command with injected environment variables by dotenvx.
For example, you want to run a lua script with environment variables from .env
file,
you can create a symbolic link dotenvx link bin/lua
, and then run ./bin/lua demo.lua
to run the lua script with
environment variables from .env
file.
Another example is to mysql
, psql
command. For example, you have database config in .env
file already,
and you want to log in mysql, and you should use mysql -h host -u user -p db
and input password interactively.
Why not read db config and help me log in mysql directly? I can't remember the long password for DB.
You can create a symbolic link dotenvx link bin/mysql
, and then run ./bin/mysql
to log in mysql automatically.
Attention: symbolic link name should be the same as the command name. Now only mysql
and psql
are supported.
DuckDB has built-in Secrets Manager, but you can use dotenvx to manage the secrets for DuckDB as well.
In .env
file, you can add the following key-value pairs:
DUCKDB__HTTP_SECRET=secret
DUCKDB__HTTP_SECRET__TYPE=http
DUCKDB__HTTP_SECRET__BEARER_TOKEN=xxxx
The above env variables will be detected and convert to CREATE SECRET http_secret ( TYPE http, BEARER_TOKEN 'xxx');
.
Use dotenvx link bin/duckdb
to create a symbolic link for duckdb
command, and then run ./bin/duckdb
to start
duckdb with secrets support.
You can attach encrypt-database introduced by DuckDB 1.4.0 with the following env variables:
DUCKDB__SECRET_DB=attach
DUCKDB__SECRET_DB__TYPE=duckdb
DUCKDB__SECRET_DB__URL=encrypted.db
DUCKDB__SECRET_DB__ENCRYPTION_KEY=123456
You can use dotenvx set <key> <value>
to write an encrypted key-value pair to the .env
file.
If you don't want to shell history to record the sensitive value,
you can use dotenvx set <key> -
to read the value from standard input (stdin),
and press Ctrl+D on Linux/macOS or Ctrl+Z on Windows to finish input.
Tips: you can use dotenvx set --encrypt my_private_pem - < ./xxx.pem
to encrypt any text file as a key-value pair
in the .env
file.
The .env
file still text file, and other people or tools can modify it, and let the application load the modified
.env
file, which may cause security issues.
For example, you have an email, which is a PayPal account to receive payments. Of course, you don't want others to change the email address to their own PayPal account, and then you will lose your money.
To prevent this, the .env
file is signed with a signature(secp256k1) and put in the metadata section of the file.
When you load the .env
file, the CLI will verify the signature with the public key in the .env
file.
How the signature works:
- The author run
dotenvx encrypt --sign
to sign the.env
file with the private key, and the signature will be added to the metadata section of the file. - Signature: SHA256 hash of the
.env
trimmed .env file content (without sign line), and then sign the hash with the private key to get the signature, and signature is a base64 encoded string and added to the metadata section of the file. - Verification: Load the
.env
file, extract the public key and signature from the metadata section, SHA256 hash the .env file-trimmed content (without sign line), and then verify the signature with the public key and the hash.
With this signature, you can ensure that the .env
file is not tampered, and other people/tools can trust the
.env
file content and use it safely.
Attention: dotenvx will overwrite the environment variables with the values from the .env
file,
and priority is given to the .env
file over the environment variables.
dotenvx CLI uses private keys to sign/decrypt the .env
files, and these private keys are very important and should not
be leaked to the public.
dotenvx CLI read the private keys from $HOME/.dotenvx/.env.keys.json
, $HOME/.env.keys
files or DOTENV_PRIVATE_KEY
,
DOTENV_PRIVATE_KEY_XXX
environment variables, and these private keys are still as plain text, which is not secure
enough.
With dotenvx --seal
and dotenvx --unseal
, you can encrypt the $HOME/.dotenvx/.env.keys.json
and $HOME/.env.keys
file with AES256 and a password, and other people/tools cannot read the encrypted .env.keys.aes
file without knowing
the password.
Attention: You should remember the password, and it will be used by dotenvx --unseal
to decrypt the
$HOME/.env.keys.aes
file.
You can use the dotenvx diff key1,key2
command to display the difference values from .env files,
and dotenvx will search all .env files in the current directory and compare the values of the specified keys.
Tips: you can use dotenvx diff --format csv key1,key2
to output the difference in CSV format,
and use other tools to process the CSV data for further analysis.
Please add uses: linux-china/setup-dotenvx@main
to your workflow file to set up dotenvx CLI,
and add DOTENV_PRIVATE_KEY
secret to the Repository secrets
.
Example workflow file to use dotenvx cli:
jobs:
dotenvx-demo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: linux-china/setup-dotenvx@main
- run: npm install
- run: $HOME/.cargo/bin/dotenvx run -- node index.js
env:
DOTENV_PRIVATE_KEY: ${{ secrets.DOTENV_PRIVATE_KEY }}
If you use act for local GitHub Actions test, please use
act -j dotenvx-demo --secret-file .env.keys
.
Some applications use .env.example
file to describe the environment variables, and you should create a new
.env
file from .env.example
file for local development.
Now you can use dotenvx sync .env.example .env
command will create a new .env
file from .env.example
file,
and the new .env
file will have the same keys as .env.example
file with new public key and metadata section.
Please use dotenvx completion --shell bash|zsh|fish|powershell
to generate shell completion script.
For oh-my-zsh, please follow the steps to install the completion script:
$ mkdir ~/.oh-my-zsh/custom/plugins/dotenvx
$ dotenvx completion --shell zsh > ~/.oh-my-zsh/custom/plugins/dotenvx/_dotenvx
Then add dotenvx
to the plugin list in your .zshrc
file:
plugins=(dotenvx ...)
- Dotenvx: encrypts your .env files – limiting their attack vector while retaining their benefits.
- ecies-rs: Elliptic Curve Integrated Encryption Scheme for secp256k1/curve25519 in Rust
- dotenvy: a well-maintained fork of the dotenv crate
- Practical Cryptography for Developers: https://cryptobook.nakov.com/
- Command Line Interface Guidelines: https://clig.dev/