A secure, feature-complete port of dotenvx for modern .NET applications. Load environment variables from .env
files with support for encryption, multiple environments, and variable expansion.
- π Built-in Encryption - Protect sensitive data with ECIES encryption
- π οΈ CLI Tool - Powerful command-line interface for managing .env files
- π Dependency Injection - First-class support for ASP.NET Core
- π Multiple Files - Load environment-specific configurations
- π Variable Expansion - Reference other variables with
${VAR}
syntax - β Production Ready - Battle-tested with comprehensive samples
dotnet add package DotEnvX
dotnet add package DotEnvX.Extensions.DependencyInjection
dotnet tool install --global DotEnvX.Tool
Create a .env
file:
DATABASE_URL=postgresql://localhost/mydb
API_KEY=sk-1234567890abcdef
DEBUG=true
PORT=3000
Load in your application:
using DotEnvX.Core;
// Load .env file
DotEnv.Config();
// Access variables
var dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
Console.WriteLine($"Database: {dbUrl}");
using DotEnvX.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Add to configuration
builder.Configuration.AddDotEnvX();
// Or with DI and options
builder.Services.AddDotEnvX(options =>
{
options.Path = new[] { ".env", $".env.{builder.Environment.EnvironmentName}" };
options.Overload = true;
});
var app = builder.Build();
app.MapGet("/", () => new
{
Environment = app.Environment.EnvironmentName,
Database = Environment.GetEnvironmentVariable("DATABASE_URL")
});
app.Run();
Protect sensitive values with military-grade encryption:
// Generate keypair
var keypair = DotEnv.GenerateKeypair();
// Save keys
File.WriteAllText(".env.keys", $"DOTENV_PRIVATE_KEY={keypair.PrivateKey}");
File.AppendAllText(".env", $"#DOTENV_PUBLIC_KEY={keypair.PublicKey}\n");
// Encrypt a value
DotEnv.Set("API_SECRET", "super-secret-value", new SetOptions
{
Path = new[] { ".env" },
Encrypt = true
});
Your .env
file will contain:
#DOTENV_PUBLIC_KEY=04abc123...
API_SECRET="encrypted:BDb7t3QkTRp2..."
Values are automatically decrypted when loaded:
DotEnv.Config(); // Auto-decrypts using .env.keys
var secret = Environment.GetEnvironmentVariable("API_SECRET");
// secret = "super-secret-value" (decrypted!)
The dotenvx
command provides powerful environment management:
# Set single value
dotenvx set DATABASE_URL=postgresql://localhost/mydb
# Set multiple values
dotenvx set API_KEY=secret DEBUG=true PORT=3000
# Set with encryption
dotenvx set API_SECRET=supersecret --encrypt
# Force overwrite
dotenvx set KEY=value --force
# Generate keypair
dotenvx keypair --save
# Encrypt all values
dotenvx encrypt
# Encrypt specific keys
dotenvx encrypt --keys API_KEY DATABASE_PASSWORD
# Decrypt to console
dotenvx decrypt
# Decrypt to file
dotenvx decrypt --output .env.decrypted
# List variables (masks sensitive values)
dotenvx list
dotenvx ls # alias
# Show all values
dotenvx list --values
# Output as JSON
dotenvx list --json
# Get specific value
dotenvx get DATABASE_URL
# Validate syntax
dotenvx validate
# Generate example file
dotenvx example
# Run command with env loaded
dotenvx run -- node app.js
dotenvx run -- dotnet run
var env = builder.Environment.EnvironmentName;
DotEnv.Config(new DotEnvOptions
{
Path = new[]
{
".env", // Shared
$".env.{env}", // Environment-specific
".env.local", // Local overrides
$".env.{env}.local" // Local environment overrides
},
Overload = true
});
BASE_URL=https://api.example.com
API_V1=${BASE_URL}/v1
USER_ENDPOINT=${API_V1}/users
FULL_URL=${USER_ENDPOINT}/profile
public class WeatherService
{
private readonly IDotEnvService _dotEnv;
public WeatherService(IDotEnvService dotEnv)
{
_dotEnv = dotEnv;
}
public async Task<Weather> GetWeatherAsync()
{
var apiKey = _dotEnv.Get("WEATHER_API_KEY");
var apiUrl = _dotEnv.Get("WEATHER_API_URL");
// Use values...
}
}
var configuration = new ConfigurationBuilder()
.AddDotEnvX(options =>
{
options.Path = new[] { ".env", ".env.production" };
options.Overload = true;
})
.Build();
// Bind to strongly-typed options
services.Configure<AppSettings>(configuration.GetSection("AppSettings"));
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY . .
# Don't include sensitive files
RUN rm -f .env.keys .env.local
# Use environment variable for production key
ENV DOTENV_KEY=$DOTENV_KEY
ENTRYPOINT ["dotnet", "MyApp.dll"]
name: Deploy
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Setup environment
env:
DOTENV_PRIVATE_KEY: ${{ secrets.DOTENV_PRIVATE_KEY }}
run: |
echo "DOTENV_PRIVATE_KEY=$DOTENV_PRIVATE_KEY" > .env.keys
dotnet tool install --global DotEnvX.Tool
dotenvx decrypt --output .env
- name: Build
run: dotnet build --configuration Release
- name: Test
run: dotnet test
- name: Deploy
run: dotnet publish
-
Never commit secrets
.env .env.local .env.keys .env.*.local *.env.keys
-
Use encryption for sensitive values
dotenvx set API_KEY=secret --encrypt
-
Separate keys from values
.env
β Can be committed (with encrypted values).env.keys
β Never commit (contains private keys)
-
Use environment-specific files
- Development:
.env.development
- Production: Vault files or environment variables
- Development:
Load environment files.
Option | Type | Description |
---|---|---|
Path |
string[] |
Files to load |
Overload |
bool |
Override existing vars |
Strict |
bool |
Throw on missing files |
Ignore |
string[] |
Error codes to ignore |
EnvKeysFile |
string |
Path to keys file |
Convention |
string |
Use convention (nextjs, etc) |
Parse .env content.
Set environment variable.
Get environment variable.
Generate encryption keypair.
Encrypt a value.
Decrypt a value.
# Run all tests
dotnet test
# Run with coverage
dotnet test /p:CollectCoverage=true
# Run specific tests
dotnet test --filter "FullyQualifiedName~Encryption"
DotEnvX/
βββ DotEnvX.Core/ # Core library
β βββ Parser/ # .env file parser
β βββ Encryption/ # ECIES encryption
β βββ Services/ # Core services
β βββ Models/ # Data models
βββ DotEnvX.Extensions.DependencyInjection/ # ASP.NET Core integration
β βββ ServiceCollectionExtensions.cs # DI extensions
β βββ DotEnvConfigurationSource.cs # IConfiguration provider
βββ DotEnvX.Tool/ # CLI tool
β βββ Program.cs # Command definitions
βββ DotEnvX.Samples/ # Sample applications
βββ DotEnvX.Tests/ # Unit tests
Contributions are welcome! Please see CONTRIBUTING.md for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
- Vault file support (.env.vault)
- Cloud provider integrations (Azure Key Vault, AWS Secrets Manager)
- GUI tool for managing .env files
- VSCode extension
- Additional encryption algorithms
- Performance optimizations
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
- Original dotenvx by @motdotla
- BouncyCastle for cryptography
- Spectre.Console for beautiful CLI output
- System.CommandLine for command parsing
- The .NET community
Component | Status | Tests | Coverage |
---|---|---|---|
Core | β Stable | 11/22 | 50% |
Encryption | β Stable | 11/11 | 100% |
DI Extensions | β Stable | N/A | N/A |
CLI Tool | β Stable | Manual | N/A |
Samples | β Complete | Manual | N/A |
While dotnet user-secrets
is great for basic development scenarios, DotEnvX provides a comprehensive solution for both development and production environments.
Feature | DotEnvX | dotnet user-secrets |
---|---|---|
Development secrets | β Excellent | β Excellent |
Production support | β Full support | β Dev only |
Encryption | β ECIES encryption | β Plain text |
Source control | β Safe (encrypted) | β Cannot commit |
CI/CD integration | β Excellent | β Not suitable |
Multi-language support | β Universal .env | β .NET only |
Docker/containers | β Native support | β Not suitable |
Variable expansion | β
${VAR} syntax |
β Not supported |
Multiple environments | β Built-in layering | |
CLI tools | β Comprehensive | |
Team collaboration | β Via encryption | |
File format | β Industry standard | |
VS integration | β Built-in |
- Production-Ready Encryption: ECIES encryption allows safe storage of encrypted secrets in source control, with separate key management
- Universal Format: .env files work across all platforms and languages, perfect for polyglot teams
- Advanced Features: Variable expansion, multiple file support, and environment-specific configurations
- DevOps Friendly: Designed for modern CI/CD pipelines and container deployments
- Team Collaboration: Encrypted secrets can be shared via Git with secure key distribution
Use DotEnvX when you need:
- Production-grade secret management
- Encrypted secrets in source control
- Multi-environment deployments
- Cross-platform compatibility
- Docker/Kubernetes deployments
- Team collaboration on secrets
Use dotnet user-secrets when:
- Working on simple .NET-only projects
- Only need local development secrets
- Prefer built-in Visual Studio integration
- Don't need production deployment
// Before (user-secrets)
builder.Configuration.AddUserSecrets<Program>();
// After (DotEnvX)
builder.Configuration.AddDotEnvX(options =>
{
options.Path = new[] { ".env", ".env.local" };
options.Overload = true;
});
Star β this repo if you find it useful!