Noundry.DotEnvX
1.0.0
dotnet add package Noundry.DotEnvX --version 1.0.0
NuGet\Install-Package Noundry.DotEnvX -Version 1.0.0
<PackageReference Include="Noundry.DotEnvX" Version="1.0.0" />
<PackageVersion Include="Noundry.DotEnvX" Version="1.0.0" />
<PackageReference Include="Noundry.DotEnvX" />
paket add Noundry.DotEnvX --version 1.0.0
#r "nuget: Noundry.DotEnvX, 1.0.0"
#:package Noundry.DotEnvX@1.0.0
#addin nuget:?package=Noundry.DotEnvX&version=1.0.0
#tool nuget:?package=Noundry.DotEnvX&version=1.0.0
Noundry.DotEnvX for .NET
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.
๐ Why Noundry.DotEnvX?
- ๐ Built-in Encryption - Protect sensitive data with ECIES encryption (secp256k1 + AES-GCM)
- ๐ ๏ธ CLI Tool - Powerful command-line interface for managing .env files
- ๐ Dependency Injection - Thread-safe, production-ready ASP.NET Core integration
- ๐ฆ Vault Support - Encrypt entire .env files for secure deployment
- ๐ Multiple Files - Load environment-specific configurations
- ๐ Variable Expansion - Reference other variables with
${VAR}syntax - ๐ Hot Reload - Automatically reload configuration when .env files change
- โ Production Ready - Comprehensive test coverage with 69+ unit tests
๐ฆ Installation
Core Library
dotnet add package Noundry.DotEnvX
CLI Tool (Global)
dotnet tool install --global Noundry.DotEnvX.Tool
Note: The
Noundry.DotEnvXpackage includes both core functionality and ASP.NET Core integration. No separate packages needed!
๐ Quick Start
Try the Samples
cd samples/DotEnvX.Samples
dotnet run
The samples project contains 9 comprehensive examples demonstrating:
- Basic usage and advanced options
- Parsing and encryption/decryption
- Dependency injection and configuration provider
- Variable expansion and multiple files
- Example generation
Basic Usage
Create a .env file:
DATABASE_URL=postgresql://localhost/mydb
API_KEY=sk-1234567890abcdef
DEBUG=true
PORT=3000
Load in your application:
using Noundry.DotEnvX.Core;
// Load .env file
DotEnv.Config();
// Access variables
var dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
Console.WriteLine($"Database: {dbUrl}");
ASP.NET Core Integration
using Noundry.DotEnvX.Core.Extensions;
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();
Thread-Safe DI Service
Inject IDotEnvService for thread-safe access to environment variables:
public class MyService
{
private readonly IDotEnvService _env;
public MyService(IDotEnvService env)
{
_env = env;
}
public void DoWork()
{
// Safe methods
var apiKey = _env.Get("API_KEY");
var dbUrl = _env.GetOrDefault("DATABASE_URL", "localhost");
var secret = _env.GetRequired("SECRET"); // Throws if missing
if (_env.Contains("FEATURE_FLAG"))
{
// Feature enabled
}
// Set values (persists to .env file)
_env.Set("LAST_RUN", DateTime.UtcNow.ToString("O"));
// Async support
await _env.SetAsync("STATUS", "running");
// Get all keys and count
var keys = _env.GetKeys();
Console.WriteLine($"Loaded {_env.Count} variables");
}
}
Hot Reload Support
Enable automatic reloading when .env files change:
// Configuration provider with hot reload
builder.Configuration.AddDotEnvXWithReload(options =>
{
options.Path = new[] { ".env", ".env.local" };
});
// Or subscribe to reload events via DI service
var env = app.Services.GetRequiredService<IDotEnvService>();
env.Reloaded += (sender, e) =>
{
Console.WriteLine($"Added: {string.Join(", ", e.AddedKeys)}");
Console.WriteLine($"Changed: {string.Join(", ", e.ChangedKeys)}");
Console.WriteLine($"Removed: {string.Join(", ", e.RemovedKeys)}");
};
// Manual reload
env.Reload();
await env.ReloadAsync();
๐ Encryption
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!)
๐ ๏ธ CLI Tool
The ndotenvx command provides powerful environment management compatible with the original dotenvx:
Core Commands
set - Set Environment Variables
# Set single value
ndotenvx set DATABASE_URL=postgresql://localhost/mydb
# Set multiple values
ndotenvx set API_KEY=secret DEBUG=true PORT=3000
# Set with encryption
ndotenvx set API_SECRET=supersecret --encrypt
# Force overwrite existing values
ndotenvx set KEY=value --force
# Specify file
ndotenvx set KEY=value -f .env.production
get - Retrieve Values
# Get specific value
ndotenvx get DATABASE_URL
# Get all values
ndotenvx get --all
# Output formats
ndotenvx get API_KEY --format plain # Plain text (default)
ndotenvx get API_KEY --format shell # export KEY="value"
ndotenvx get API_KEY --format eval # export KEY="value"
ndotenvx get --all --format json # JSON output
# Pretty print JSON
ndotenvx get --all --format json --pretty-print
run - Execute with Environment
# Basic usage
ndotenvx run -- dotnet run
ndotenvx run -- node app.js
# Override existing environment variables
ndotenvx run --overload -- dotnet run
# Use framework conventions
ndotenvx run --convention=nextjs -- node server.js
# Multiple files (later files override earlier)
ndotenvx run -f .env -f .env.local -- dotnet run
# Verbose output
ndotenvx run --verbose -- dotnet run
# Debug mode
ndotenvx run --debug -- dotnet run
# Quiet mode (suppress output)
ndotenvx run --quiet -- dotnet run
# Strict mode (fail on missing files)
ndotenvx run --strict -- dotnet run
Encryption Commands
keypair - Generate Keys
# Generate and display keypair
ndotenvx keypair
# Generate and save to files
ndotenvx keypair --save
encrypt - Encrypt Values
# Encrypt all unencrypted values
ndotenvx encrypt
# Encrypt specific keys
ndotenvx encrypt --keys API_KEY DATABASE_PASSWORD
# Specify file
ndotenvx encrypt -f .env.production
decrypt - Decrypt Values
# Decrypt to console
ndotenvx decrypt
# Decrypt to file
ndotenvx decrypt --output .env.decrypted
# Specify source file
ndotenvx decrypt -f .env.production
rotate - Rotate Encryption Keys
# Rotate keys and re-encrypt all values
ndotenvx rotate
# Rotate for specific file
ndotenvx rotate -f .env.production
๐ฆ Vault Files
Vault files allow you to encrypt entire .env files for secure deployment. Create a .env.vault containing encrypted versions of your environments:
using Noundry.DotEnvX.Core;
// Create vault from multiple environments
var result = DotEnv.CreateVault(new Dictionary<string, string>
{
{ "production", ".env.production" },
{ "staging", ".env.staging" },
{ "development", ".env.development" }
});
// Save the DOTENV_KEYs securely (e.g., in CI/CD secrets)
foreach (var (env, key) in result.EnvironmentKeys)
{
Console.WriteLine($"{env}: {key.DotEnvKey}");
}
Load vault files in production:
// Set DOTENV_KEY environment variable or pass directly
Environment.SetEnvironmentVariable("DOTENV_KEY", "dotenv://:key...@dotenvx.com/vault/.env.vault?environment=production");
// Load from vault
DotEnv.Config(new DotEnvOptions
{
Path = new[] { ".env.vault" }
});
Or use the convenience methods:
// Decrypt vault content directly
var envContent = DotEnv.DecryptVault(".env.vault", "production", privateKey);
// Rotate vault keys
var newKey = DotEnv.RotateVaultKey(".env.vault", "production", currentPrivateKey);
// List available environments
var environments = DotEnv.ListVaultEnvironments(".env.vault");
// Returns: ["production", "staging", "development"]
DI integration with vault:
// Using DI with vault
builder.Services.AddDotEnvXVault(
Environment.GetEnvironmentVariable("DOTENV_KEY")!,
".env.vault"
);
File Management Commands
list/ls - List Variables
# List all variables (masks sensitive values)
ndotenvx list
ndotenvx ls # alias
# Show actual values
ndotenvx list --values
ndotenvx ls -v
# Output as JSON
ndotenvx list --json
# Specify file
ndotenvx list -f .env.production
scan - Scan for .env Files
# Scan current directory
ndotenvx scan
# Scan specific directory
ndotenvx scan --directory /path/to/project
ndotenvx scan -d ./myapp
validate - Validate Syntax
# Validate .env file
ndotenvx validate
# Validate specific file
ndotenvx validate -f .env.production
example - Generate .env.example
# Generate .env.example from .env
ndotenvx example
# Specify source file
ndotenvx example -f .env.production
Extension Commands (ext)
ext genexample - Generate Example File
# Generate .env.example
ndotenvx ext genexample
# Specify file
ndotenvx ext genexample -f .env.production
ext gitignore - Add .gitignore Patterns
# Add default patterns
ndotenvx ext gitignore
# Add custom patterns
ndotenvx ext gitignore --pattern .env --pattern .env.local --pattern .env.keys
ndotenvx ext gitignore -p .env.secret
ext precommit - Setup Pre-commit Hooks
# Show info about pre-commit hooks
ndotenvx ext precommit
# Install pre-commit hook
ndotenvx ext precommit --install
ext prebuild - Setup Prebuild Configuration
# Show prebuild configuration for .NET projects
ndotenvx ext prebuild
ext scan - Scan for Issues
# Scan for .env configuration issues
ndotenvx ext scan
Global Options
All commands support the following global options:
-f, --file <path> # Specify .env file path (default: .env)
Command Examples
Development Workflow:
# 1. Generate keypair
ndotenvx keypair --save
# 2. Add encrypted secrets
ndotenvx set DATABASE_PASSWORD=secret123 --encrypt
ndotenvx set API_KEY=sk_live_abc123 --encrypt
# 3. Validate configuration
ndotenvx validate
# 4. Run application
ndotenvx run -- dotnet run
Production Deployment:
# 1. Encrypt production secrets
ndotenvx set DB_PASSWORD=prod_secret -f .env.production --encrypt
# 2. Validate
ndotenvx validate -f .env.production
# 3. Generate example for documentation
ndotenvx example -f .env.production
Key Rotation:
# 1. Rotate encryption keys
ndotenvx rotate
# 2. Verify decryption works
ndotenvx decrypt
# 3. Remove old keys backup
rm .env.keys.old
Team Setup:
# 1. Add .gitignore patterns
ndotenvx ext gitignore
# 2. Setup pre-commit validation
ndotenvx ext precommit --install
# 3. Scan for issues
ndotenvx scan
๐ Advanced Features
Async API Support
For better performance in I/O-intensive scenarios, use the async API variants:
// Async configuration loading
var result = await DotEnv.ConfigAsync(new DotEnvOptions
{
Path = new[] { ".env", ".env.local" },
Overload = true
});
// In ASP.NET Core startup
public async Task Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Load config asynchronously
await DotEnv.ConfigAsync();
var app = builder.Build();
app.Run();
}
Multiple Environments
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
});
Variable Expansion
BASE_URL=https://api.example.com
API_V1=${BASE_URL}/v1
USER_ENDPOINT=${API_V1}/users
FULL_URL=${USER_ENDPOINT}/profile
Dependency Injection
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...
}
}
Configuration Provider
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"));
๐๏ธ Production Deployment
Docker
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"]
CI/CD (GitHub Actions)
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 Noundry.DotEnvX.Tool
ndotenvx decrypt --output .env
- name: Build
run: dotnet build --configuration Release
- name: Test
run: dotnet test
- name: Deploy
run: dotnet publish
๐ Security Best Practices
Never commit secrets
.env .env.local .env.keys .env.*.local *.env.keysUse encryption for sensitive values
ndotenvx set API_KEY=secret --encryptSeparate 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:
๐ API Reference
Core Methods
DotEnv.Config(options)
Load environment files synchronously.
DotEnv.ConfigAsync(options, cancellationToken)
Load environment files asynchronously (recommended for better I/O performance).
Options:
| 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) |
Parsing Methods
DotEnv.Parse(content, options)
Parse .env content into dictionary without loading into environment.
Variable Management
DotEnv.Set(key, value, options)
Set environment variable in .env file.
DotEnv.Get(key, options)
Get environment variable from .env file.
Encryption Methods
DotEnv.GenerateKeypair()
Generate a new ECIES keypair for encryption.
DotEnv.Encrypt(value, publicKey)
Encrypt a value using a public key.
DotEnv.Decrypt(encryptedValue, privateKey)
Decrypt a value using a private key.
Utility Methods
DotEnv.Ls(directory, envFile, excludeEnvFile)
List all .env files in a directory.
DotEnv.GenExample(directory, envFile)
Generate a .env.example file from an existing .env file.
๐งช Testing
# Run all tests
dotnet test
# Run with coverage
dotnet test /p:CollectCoverage=true
# Run specific tests
dotnet test --filter "FullyQualifiedName~Encryption"
๐ฆ Package Structure
Noundry.DotEnvX/
โโโ src/
โ โโโ DotEnvX.Core/ # Core library with DI extensions
โ โโโ DotEnvX.Tool/ # Global CLI tool
โโโ tests/
โ โโโ DotEnvX.Tests/ # Unit tests
โโโ samples/
โ โโโ DotEnvX.Samples/ # Comprehensive sample application
โโโ docs/ # Documentation
NuGet Packages:
Noundry.DotEnvX- Core library with DI extensions (consolidated)Noundry.DotEnvX.Tool- Global CLI tool (dotenvxcommand)
๐ค Contributing
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
๐ Roadmap
- Vault file support (.env.vault) - Full implementation with create, update, rotate, and decrypt
- Thread-safe DI service with hot reload support
- Cloud provider integrations (Azure Key Vault, AWS Secrets Manager)
- GUI tool for managing .env files
- VSCode extension
- Additional encryption algorithms
- Performance optimizations
๐ License
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
๐ง Dependencies
Core Library (Noundry.DotEnvX):
- BouncyCastle.Cryptography 2.4.0 - Modern cryptographic library for ECIES encryption
- Microsoft.Extensions.Configuration 8.0.0
- Microsoft.Extensions.DependencyInjection.Abstractions 8.0.0
CLI Tool (Noundry.DotEnvX.Tool):
- Spectre.Console - Beautiful terminal output
- System.CommandLine - Command-line parsing
๐ Acknowledgments
- Original dotenvx by @motdotla
- BouncyCastle for cryptography
- Spectre.Console for beautiful CLI output
- System.CommandLine for command parsing
- The .NET community
๐ Status
| Component | Status | Tests | Coverage |
|---|---|---|---|
| Core | โ Stable | 24+ | Full coverage |
| Encryption | โ Stable | 11 | 100% |
| DI Extensions | โ Stable | 22+ | Thread-safe, production-ready |
| Vault | โ Stable | 15+ | Full implementation |
| CLI Tool | โ Stable | Manual | N/A |
| Samples | โ Complete | Manual | N/A |
Overall Status: Production Ready - All components are stable with comprehensive test coverage (69+ unit tests).
๐ Links
๐ Noundry.DotEnvX vs dotnet user-secrets
Why Choose Noundry.DotEnvX?
While dotnet user-secrets is great for basic development scenarios, Noundry.DotEnvX provides a comprehensive solution for both development and production environments.
Feature Comparison
| Feature | Noundry.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 | โ ๏ธ Limited |
| CLI tools | โ Comprehensive | โ ๏ธ Basic |
| Team collaboration | โ Via encryption | โ ๏ธ Manual sharing |
| File format | โ Industry standard | โ ๏ธ JSON only |
| VS integration | โ ๏ธ Via extension | โ Built-in |
Key Advantages of Noundry.DotEnvX
- 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
When to Use Each
Use Noundry.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
Migration from user-secrets
// Before (user-secrets)
builder.Configuration.AddUserSecrets<Program>();
// After (Noundry.DotEnvX)
builder.Configuration.AddDotEnvX(options =>
{
options.Path = new[] { ".env", ".env.local" };
options.Overload = true;
});
<div align="center"> Made with โค๏ธ for the .NET community <br> Star โญ this repo if you find it useful! </div>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- BouncyCastle.Cryptography (>= 2.4.0)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
-
net8.0
- BouncyCastle.Cryptography (>= 2.4.0)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- System.Security.Cryptography.Cng (>= 5.0.0)
-
net9.0
- BouncyCastle.Cryptography (>= 2.4.0)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.FileSystemGlobbing (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- System.Security.Cryptography.Cng (>= 5.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 230 | 3/4/2026 |