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)
From crates.io
From source
Pre-built binaries
Download pre-built binaries from the releases page.
Quick Start
1. Generate a keypair
This generates a public/private keypair for encryption.
2. Encrypt your .env file
# Create a .env file
# Encrypt it
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
Environment variables are automatically decrypted and injected.
Usage
Commands
keypair - Generate a new keypair
Output:
DOTENV_PUBLIC_KEY="034af93e93708b994c10f236c96ef88e..."
DOTENV_PRIVATE_KEY="ec9e80073d7ace817d35acb8b7293cbf..."
encrypt - Encrypt environment variables
# Encrypt default .env file
# Encrypt specific file
# Encrypt specific keys only
# Exclude certain keys
decrypt - Decrypt environment variables
# Decrypt default .env file
# Decrypt specific file
set - Set an environment variable (encrypted by default)
# Set encrypted variable
# Set plain text variable
# Set in specific file
get - Get an environment variable value
# Get specific variable
# Get all variables
# From specific file
ls - List all .env files
# List in current directory
# List in specific directory
run - Run command with environment variables
# Run with default .env
# Run with specific files (last wins)
# Override existing environment variables
printenv - Print environment variables for shell evaluation
# Print all variables in bash format (default)
# Print from specific file
# Print from multiple files (last wins)
# Use with eval to set environment variables
# Output in different formats
The printenv command is quiet by default, making it suitable for shell evaluation:
# Bash/Zsh
# Fish
|
# 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:
[]
= "0.1"
Example:
use ;
use DotenvParser;
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
Test
# Run all tests
# Run with output
# Run specific test
Lint
# Format code
# Lint
Coverage
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