name: dotenvx version: "1.0.0" description: dotenvx - secure environment variable management with encryption. Use for encrypting .env files, multi-environment configuration, cross-platform secret management, and migrating from plaintext dotenv.
dotenvx Skill
dotenvx is a secure dotenv from the creator of the original dotenv package. It adds encryption, multi-environment support, and cross-platform compatibility to environment variable management. Think of it as "dotenv with encryption" - your secrets are encrypted at rest and can be safely committed to version control.
Core Value Proposition: Encrypt your .env files so they can be safely committed to git, while keeping decryption keys separate and secure.
When to Use This Skill
This skill should be triggered when:
- Setting up secure environment variable management
- Encrypting .env files for version control
- Managing secrets across multiple environments (dev, staging, production)
- Migrating from plaintext .env to encrypted secrets
- Deploying applications with encrypted configuration
- Configuring dotenvx in CI/CD pipelines
- Troubleshooting dotenvx encryption/decryption issues
When NOT to Use This Skill
- For basic dotenv usage without encryption (use standard dotenv docs)
- For cloud-native secrets managers (AWS Secrets Manager, HashiCorp Vault)
- For Kubernetes secrets management (use k8s secrets/sealed-secrets)
Core Concepts
The Security Problem
Traditional .env files are plaintext - if committed to git or exposed, all secrets are compromised. dotenvx solves this by:
- Encrypting secrets with AES-256 and Secp256k1 elliptic curve cryptography
- Separating the encrypted file (safe to commit) from the decryption key (kept secure)
- Decrypting automatically at runtime when the private key is available
Architecture
┌─────────────────────────────────────────────────────────────┐
│ dotenvx WORKFLOW │
└─────────────────────────────────────────────────────────────┘
.env (plaintext) .env.keys (NEVER commit)
┌──────────────────┐ ┌──────────────────────────┐
│ HELLO=World │ │ DOTENV_PRIVATE_KEY=... │
│ API_KEY=secret │ │ DOTENV_PUBLIC_KEY=... │
└────────┬─────────┘ └────────────┬─────────────┘
│ │
▼ dotenvx encrypt │
┌──────────────────┐ │
│ HELLO="encrypted:│◄───────────────────────┘
│ BE9Y5L..." │ Uses public key to encrypt
│ API_KEY="encrypt │
│ ed:CGY8..." │
└────────┬─────────┘
│
▼ Safe to commit to git!
┌──────────────────┐
│ Git Repository │
└────────┬─────────┘
│
▼ dotenvx run (at runtime)
┌──────────────────┐
│ Decrypts using │◄── Private key from:
│ private key │ - .env.keys file
│ │ - DOTENV_PRIVATE_KEY env var
└────────┬─────────┘
│
▼
┌──────────────────┐
│ process.env.HELLO│
│ = "World" │
└──────────────────┘
Key Files
| File | Purpose | Git? |
|---|---|---|
.env | Development environment variables | ✅ Yes (when encrypted) |
.env.production | Production environment variables | ✅ Yes (when encrypted) |
.env.keys | Private decryption keys | ❌ Never |
.env.local | Local overrides | ❌ No |
Installation
npm (Recommended for Node.js projects)
npm install @dotenvx/dotenvx --save
Homebrew (macOS/Linux global install)
brew install dotenvx/brew/dotenvx
Shell Script (Universal)
curl -sfS https://dotenvx.sh | sh
Docker
docker run -it --rm -v $(pwd):/app dotenv/dotenvx help
Windows
winget install dotenvx
npx (No install)
npx @dotenvx/dotenvx help
CLI Commands Reference
run - Inject Environment Variables
Run any command with environment variables injected:
# Basic usage
dotenvx run -- node index.js
# Specify environment file
dotenvx run -f .env.production -- node index.js
# Multiple files (earlier takes precedence)
dotenvx run -f .env.local -f .env -- node index.js
# Use framework conventions (Next.js, etc.)
dotenvx run --convention=nextjs -- npm run build
# Override existing environment variables
dotenvx run --overload -- node index.js
encrypt - Encrypt .env Files
Convert plaintext .env to encrypted format:
# Encrypt default .env file
dotenvx encrypt
# Encrypt specific file
dotenvx encrypt -f .env.production
# Encrypt all .env* files
dotenvx encrypt -f .env*
Result: Creates/updates .env.keys with encryption keys.
decrypt - Decrypt .env Files
Revert encrypted .env to plaintext:
# Decrypt default .env file
dotenvx decrypt
# Decrypt specific file
dotenvx decrypt -f .env.production
set - Set Encrypted Variables
Add or update encrypted variables:
# Set a variable (encrypts automatically)
dotenvx set HELLO World
# Set in specific environment
dotenvx set HELLO production -f .env.production
# Set from stdin (for sensitive values)
echo "supersecret" | dotenvx set API_KEY
get - Retrieve Variable Values
# Get single variable
dotenvx get HELLO
# Get from specific file
dotenvx get HELLO -f .env.production
# Get all variables as JSON
dotenvx get --all --format json
keypair - Manage Encryption Keys
# Show public/private key pair
dotenvx keypair
# Show for specific environment
dotenvx keypair -f .env.production
Multi-Environment Setup
Recommended Structure
project/
├── .env # Development (encrypted)
├── .env.production # Production (encrypted)
├── .env.staging # Staging (encrypted)
├── .env.local # Local overrides (not committed)
├── .env.keys # All private keys (NEVER commit)
└── .gitignore
.gitignore Configuration
# Never commit private keys
.env.keys
# Never commit local overrides
.env.local
.env.*.local
# DO commit encrypted .env files
# (remove these from .gitignore if present)
# .env
# .env.production
# .env.staging
Environment-Specific Keys
Each environment gets its own key pair:
# .env.keys after encrypting multiple environments
DOTENV_PRIVATE_KEY="ec9d6..." # For .env
DOTENV_PRIVATE_KEY_PRODUCTION="a]c8..." # For .env.production
DOTENV_PRIVATE_KEY_STAGING="3d5f..." # For .env.staging
Loading Order with Conventions
# Next.js convention loads in this order:
# .env.local → .env.development → .env
dotenvx run --convention=nextjs -- npm run dev
Integration Examples
Node.js Application
package.json:
{
"scripts": {
"dev": "dotenvx run -- node index.js",
"start": "dotenvx run -f .env.production -- node index.js"
}
}
index.js:
// Option 1: Use dotenvx as drop-in replacement
require('@dotenvx/dotenvx').config()
console.log(process.env.HELLO)
// Option 2: Use dotenvx.get() for explicit access
const dotenvx = require('@dotenvx/dotenvx')
dotenvx.config()
console.log(dotenvx.get('HELLO'))
Next.js
package.json:
{
"scripts": {
"dev": "dotenvx run --convention=nextjs -- next dev",
"build": "dotenvx run -f .env.production -- next build",
"start": "dotenvx run -f .env.production -- next start"
}
}
Docker
Dockerfile:
FROM node:20-alpine
# Install dotenvx
RUN curl -sfS https://dotenvx.sh | sh
WORKDIR /app
COPY . .
RUN npm install
# Run with dotenvx (provide DOTENV_PRIVATE_KEY at runtime)
CMD ["dotenvx", "run", "--", "node", "index.js"]
docker-compose.yml:
services:
app:
build: .
environment:
- DOTENV_PRIVATE_KEY_PRODUCTION=${DOTENV_PRIVATE_KEY_PRODUCTION}
GitHub Actions
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dotenvx
run: curl -sfS https://dotenvx.sh | sh
- name: Build with secrets
env:
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
run: dotenvx run -f .env.production -- npm run build
Vercel
- Encrypt production secrets:
dotenvx set API_KEY "production-secret" -f .env.production
- Add private key to Vercel:
vercel env add DOTENV_PRIVATE_KEY_PRODUCTION
# Paste the key from .env.keys
- Update build command in vercel.json:
{
"buildCommand": "dotenvx run -f .env.production -- npm run build"
}
.env File Syntax
Basic Format
# Comments start with #
HELLO=World
DATABASE_URL=postgres://localhost/mydb
# Quoted values
MESSAGE="Hello, World!"
SINGLE_QUOTED='No $expansion here'
# Multiline with backticks
PRIVATE_KEY=`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----`
Variable Expansion
# Reference other variables
BASE_URL=https://api.example.com
API_ENDPOINT=${BASE_URL}/v1
# Default values
PORT=${PORT:-3000}
# Alternate if set
DEBUG_MODE=${DEBUG:+enabled}
Command Substitution
# Embed command output
HOSTNAME=$(hostname)
USER=$(whoami)
TIMESTAMP=$(date +%s)
Encrypted Values
After running dotenvx encrypt:
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY="034a..."
# Encrypted values
HELLO="encrypted:BE9Y5L3OxAOOmfq..."
API_KEY="encrypted:CGY8BDMHfq..."
Security Best Practices
Key Management
- Never commit
.env.keys- Add to.gitignoreimmediately - Store private keys in secrets manager - GitHub Secrets, Vercel Env, AWS SSM
- Rotate keys periodically - Re-encrypt with new keys
- Use environment-specific keys - Different keys for dev/staging/production
CI/CD Security
# Set private key as environment variable
export DOTENV_PRIVATE_KEY_PRODUCTION="your-private-key"
# dotenvx automatically uses it for decryption
dotenvx run -f .env.production -- npm run build
Team Workflow
# Developer 1: Encrypts new secret
dotenvx set NEW_API_KEY "secret123"
git add .env
git commit -m "Add NEW_API_KEY (encrypted)"
git push
# Developer 2: Pulls and runs (has .env.keys locally)
git pull
dotenvx run -- npm run dev # Works automatically
Sharing Keys Securely
# Option 1: Secure channel (1Password, Signal, etc.)
cat .env.keys | pbcopy # Copy to clipboard
# Option 2: In-person/video call
# Option 3: Company secrets manager
# Store DOTENV_PRIVATE_KEY in vault
Troubleshooting
"Missing private key"
Error: Missing private key for .env.production
Solution: Set the private key:
# Option 1: Create/restore .env.keys file
echo 'DOTENV_PRIVATE_KEY_PRODUCTION="abc123..."' > .env.keys
# Option 2: Set environment variable
export DOTENV_PRIVATE_KEY_PRODUCTION="abc123..."
"Cannot decrypt"
Cause: Wrong private key or corrupted encrypted value
Solution:
# Verify key matches
dotenvx keypair -f .env.production
# Re-encrypt if needed
dotenvx decrypt -f .env.production # If you have the right key
dotenvx encrypt -f .env.production
Variables Not Loading
# Debug: Show what dotenvx is loading
dotenvx run --debug -- node -e "console.log(process.env)"
# Check file is being read
dotenvx run -f .env.production --verbose -- echo "loaded"
Encrypted Values in Wrong File
# Check which file has encrypted values
grep "encrypted:" .env*
# Ensure matching .env.keys entries
cat .env.keys
Migration from dotenv
Step 1: Install dotenvx
npm install @dotenvx/dotenvx --save
npm uninstall dotenv
Step 2: Update Code
// Before
require('dotenv').config()
// After (drop-in replacement)
require('@dotenvx/dotenvx').config()
Step 3: Encrypt Existing .env
# Encrypt current .env file
dotenvx encrypt
# Verify encryption worked
cat .env # Should show encrypted: values
# Save .env.keys somewhere secure!
cat .env.keys
Step 4: Update Scripts
{
"scripts": {
"dev": "dotenvx run -- node index.js",
"start": "dotenvx run -f .env.production -- node index.js"
}
}
Resources
Official Documentation
Integrations
Language Support
- Node.js, Python, Ruby, Go, PHP, Rust, Java
- Frameworks: Next.js, Express, Flask, Rails, Laravel
Version History
- 1.0.0 (2026-01-11): Initial skill release
- Complete dotenvx overview and installation
- CLI commands reference (run, encrypt, decrypt, set, get, keypair)
- Multi-environment configuration
- Integration examples (Node.js, Next.js, Docker, CI/CD)
- .env file syntax reference
- Security best practices
- Migration guide from dotenv