Noundry.DotEnvX 1.0.0

dotnet add package Noundry.DotEnvX --version 1.0.0
                    
NuGet\Install-Package Noundry.DotEnvX -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Noundry.DotEnvX" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Noundry.DotEnvX" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Noundry.DotEnvX" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Noundry.DotEnvX --version 1.0.0
                    
#r "nuget: Noundry.DotEnvX, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Noundry.DotEnvX@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Noundry.DotEnvX&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Noundry.DotEnvX&version=1.0.0
                    
Install as a Cake Tool

Noundry.DotEnvX for .NET

NuGet License .NET Build Status

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.DotEnvX package 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

  1. Never commit secrets

    .env
    .env.local
    .env.keys
    .env.*.local
    *.env.keys
    
  2. Use encryption for sensitive values

    ndotenvx set API_KEY=secret --encrypt
    
  3. Separate keys from values

    • .env โ†’ Can be committed (with encrypted values)
    • .env.keys โ†’ Never commit (contains private keys)
  4. Use environment-specific files

    • Development: .env.development
    • Production: Vault files or environment variables

๐Ÿ“Š 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 (dotenvx command)

๐Ÿค Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. 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

๐Ÿ“Š 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).

๐Ÿ†š 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

  1. Production-Ready Encryption: ECIES encryption allows safe storage of encrypted secrets in source control, with separate key management
  2. Universal Format: .env files work across all platforms and languages, perfect for polyglot teams
  3. Advanced Features: Variable expansion, multiple file support, and environment-specific configurations
  4. DevOps Friendly: Designed for modern CI/CD pipelines and container deployments
  5. 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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