4 releases
| 0.2.2 | Nov 26, 2025 |
|---|---|
| 0.2.1 | Nov 26, 2025 |
| 0.2.0 | Nov 26, 2025 |
| 0.1.0 | Nov 26, 2025 |
#806 in Cryptography
91KB
2K
SLoC
dotenvx
A secure environment variable management tool with built-in encryption, written in Rust. This is a complete reimplementation of dotenvx with performance improvements and memory safety guarantees.
Features
- 🔐 Built-in Encryption: ECIES encryption using secp256k1 (same curve as Bitcoin)
- 🚀 High Performance: 10-100x faster than the Node.js version
- 🔒 Memory Safe: Written in Rust with zero unsafe code
- 🌍 Cross-Platform: Works on Linux, macOS, and Windows
- 📦 Small Binary: Self-contained binaries (5-10 MB)
- 🔑 Secure Key Management: Public/private keypair generation and management
- 🔄 Variable Expansion: Supports
${VAR:-default}syntax - 💻 Command Substitution: Execute shell commands in
.envfiles - 🎯 Zero Dependencies: No runtime dependencies required
Installation
Homebrew (macOS)
brew tap fabianopinto/tap
brew install dotenvx
From crates.io
cargo install dotenvx
From source
git clone https://github.com/fabianopinto/dotenvx
cd dotenvx
cargo install --path .
Pre-built binaries
Download pre-built binaries from the releases page.
Quick Start
1. Generate a keypair
dotenvx keypair
This generates a public/private keypair for encryption.
2. Encrypt your .env file
# Create a .env file
echo "DATABASE_PASSWORD=super_secret" > .env
# Encrypt it
dotenvx encrypt
Your .env file now contains encrypted values:
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY="034af93e..."
DATABASE_PASSWORD="encrypted:BG8M6U+GKJGwpGA..."
The private key is stored in .env.keys (automatically added to .gitignore).
3. Run your application
dotenvx run -- your-command
Environment variables are automatically decrypted and injected.
Usage
Commands
keypair - Generate a new keypair
dotenvx keypair
Output:
DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e..."
DOTENV_PRIVATE_KEY="ec9e80073d7ace817d35acb8b7293cbf..."
encrypt - Encrypt environment variables
# Encrypt default .env file
dotenvx encrypt
# Encrypt specific file
dotenvx encrypt -f .env.production
# Encrypt specific keys only
dotenvx encrypt -K API_KEY -K DATABASE_PASSWORD
# Exclude certain keys
dotenvx encrypt -e DEBUG -e LOG_LEVEL
decrypt - Decrypt environment variables
# Decrypt default .env file
dotenvx decrypt
# Decrypt specific file
dotenvx decrypt -f .env.production
set - Set an environment variable (encrypted by default)
# Set encrypted variable
dotenvx set API_KEY "sk_live_123456"
# Set plain text variable
dotenvx set DEBUG "true" --plain
# Set in specific file
dotenvx set DATABASE_URL "postgres://..." -f .env.production
get - Get an environment variable value
# Get specific variable
dotenvx get API_KEY
# Get all variables
dotenvx get
# From specific file
dotenvx get DATABASE_URL -f .env.production
ls - List all .env files
# List in current directory
dotenvx ls
# List in specific directory
dotenvx ls /path/to/project
run - Run command with environment variables
# Run with default .env
dotenvx run -- node server.js
# Run with specific files (last wins)
dotenvx run -f .env -f .env.local -- python app.py
# Override existing environment variables
dotenvx run --overload -- ./my-app
printenv - Print environment variables for shell evaluation
# Print all variables in bash format (default)
dotenvx printenv
# Print from specific file
dotenvx printenv -f .env.production
# Print from multiple files (last wins)
dotenvx printenv -f .env -f .env.local
# Use with eval to set environment variables
eval "$(dotenvx printenv)"
# Output in different formats
dotenvx printenv --format bash
dotenvx printenv --format fish
dotenvx printenv --format powershell
dotenvx printenv --format json
The printenv command is quiet by default, making it suitable for shell evaluation:
# Bash/Zsh
eval "$(dotenvx printenv)"
# Fish
dotenvx printenv --format fish | source
# PowerShell
Invoke-Expression (dotenvx printenv --format powershell)
How It Works
Encryption Flow
- Key Generation: Generate a secp256k1 keypair (same curve as Bitcoin)
- Encryption: Values are encrypted using ECIES (Elliptic Curve Integrated Encryption Scheme)
- Ephemeral keypair is generated for each encryption
- Shared secret is derived using ECDH
- AES-256-GCM is used for symmetric encryption
- Storage:
- Public key is stored in
.envfile - Private key is stored in
.env.keys(gitignored) - Encrypted values are base64-encoded with
encrypted:prefix
- Public key is stored in
Decryption Flow
- Key Lookup: Find private key from
.env.keys, environment variable, or custom path - Decryption: Reverse the encryption process
- Injection: Set decrypted values as environment variables
File Structure
project/
├── .env # Public key + encrypted values (committed)
├── .env.keys # Private keys (gitignored)
├── .env.production # Production environment
└── .env.keys # Production keys (deploy separately)
Library Usage
Add to your Cargo.toml:
[dependencies]
dotenvx = "0.1"
Example:
use dotenvx::crypto::{Keypair, encrypt, decrypt};
use dotenvx::parser::DotenvParser;
fn main() {
// Generate keypair
let keypair = Keypair::generate();
// Encrypt a value
let encrypted = encrypt("secret", &keypair.public_key()).unwrap();
// Decrypt a value
let decrypted = decrypt(&encrypted, &keypair.private_key()).unwrap();
// Parse .env file
let mut parser = DotenvParser::new();
parser.parse_with_processing("KEY=value\nURL=$KEY/path").unwrap();
}
Configuration Files
.env file format
# Comments are supported
KEY=value
export EXPORTED_KEY=value
# Quotes (single, double, or none)
SINGLE='value'
DOUBLE="value"
UNQUOTED=value
# Variable expansion
DATABASE_URL=postgres://${DB_HOST:-localhost}/${DB_NAME}
# Command substitution
CURRENT_USER=$(whoami)
BUILD_TIME=$(date +%s)
# Encrypted values
API_KEY="encrypted:BG8M6U+GKJGwpGA42ml2erb9..."
# Public key (added automatically)
DOTENV_PUBLIC_KEY="034af93e93708b994c10f236..."
.env.keys file format
#/------------------!DOTENV_PRIVATE_KEYS!-------------------/
#/ private decryption keys. DO NOT commit to source control /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
# .env
DOTENV_PRIVATE_KEY=ec9e80073d7ace817d35acb8b7293cbf...
# .env.production
DOTENV_PRIVATE_KEY_PRODUCTION=1fc1cafa954a7a2bf0a6fbff...
Security Best Practices
- Never commit
.env.keys- Add to.gitignoreimmediately - Rotate keys regularly - Generate new keypairs periodically
- Use different keys per environment - Separate development/staging/production
- Store production keys securely - Use secret management systems
- Audit encrypted files - Review what's encrypted regularly
Performance
Compared to the Node.js version:
- Startup time: ~50ms vs ~500ms (10x faster)
- Encryption: ~100x faster for bulk operations
- Memory usage: ~2MB vs ~50MB (25x smaller)
- Binary size: 6MB vs 50MB+ with Node.js
Development
Prerequisites
- Rust 1.70+ (install via rustup)
Build
cargo build --release
Test
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test
cargo test test_encrypt_decrypt
Lint
# Format code
cargo fmt
# Lint
cargo clippy -- -D warnings
Coverage
cargo install cargo-tarpaulin
cargo tarpaulin --out Html
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Acknowledgments
- Original dotenvx by @motdotla
- secp256k1 Rust implementation
- Bitcoin for the secp256k1 curve specification
Links
Dependencies
~19–36MB
~368K SLoC