Noundry.DotEnvX

Secure, feature-complete .env file management for .NET with encryption, vault support, dependency injection, and a powerful CLI tool.

# Install
$ dotnet add package Noundry.DotEnvX

Quick Start

Get up and running in seconds. Create a .env file and load it in your application.

1. Create a .env file

DATABASE_URL=postgresql://localhost/mydb
API_KEY=sk-1234567890abcdef
DEBUG=true
PORT=3000

2. 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}");

3. ASP.NET Core Integration

using Noundry.DotEnvX.Core.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Add to configuration pipeline
builder.Configuration.AddDotEnvX();

// Register DI service
builder.Services.AddDotEnvX(options =>
{
 options.Path = new[] { ".env", $".env.{builder.Environment.EnvironmentName}" };
 options.Overload = true;
});

Core Features

ECIES Encryption

Protect sensitive values with secp256k1 + AES-256-GCM encryption. Encrypted values are safe to commit to source control.

Vault Files

Encrypt entire .env files into a single .env.vault for secure multi-environment deployment.

Dependency Injection

Thread-safe IDotEnvService with read, write, reload, and change notification support.

Configuration Provider

Integrates with IConfiguration and supports hot reload when .env files change.

Variable Expansion

Reference other variables using ${VAR} syntax with fallback to process environment.

Static API (DotEnv Class)

The DotEnv static class provides the primary entry point for loading, parsing, and managing environment variables.

Config / ConfigAsync

// Basic usage
var result = DotEnv.Config();

// With options
var result = DotEnv.Config(new DotEnvOptions
{
 Path = new[] { ".env", ".env.production" },
 Overload = true,
 Strict = true,
 PrivateKey = "abc..."
});

// Async usage
var result = await DotEnv.ConfigAsync(options, cancellationToken);

// Check result
if (result.Error != null)
 Console.WriteLine($"Error: {result.Error.Message}");

DotEnvOptions Reference

Option Default Description
Path[".env"]Files to load
OverloadfalseOverride existing environment variables
StrictfalseThrow on errors
IgnorenullError codes to ignore
PrivateKeynullPrivate key for decryption
EnvKeysFile".env.keys"Keys file path
DotEnvKeynullDOTENV_KEY for vault decryption
ConventionnullLoading convention ("nextjs" or "flow")

Set / Get

// Set a value
DotEnv.Set("API_KEY", "my-secret-key");

// Set with encryption
DotEnv.Set("DB_PASSWORD", "secret123", new SetOptions { Encrypt = true });

// Get a value (requires Config() first)
DotEnv.Config();
var value = DotEnv.Get("API_KEY");

// Get with strict mode (throws if not found)
var value = DotEnv.Get("API_KEY", new GetOptions { Strict = true });

Dependency Injection

Register the thread-safe IDotEnvService for production-ready environment variable access.

Registration

// Basic registration
services.AddDotEnvX();

// With configuration
services.AddDotEnvX(options =>
{
 options.Path = new[] { ".env", ".env.local" };
 options.Overload = true;
});

// With encryption
services.AddEncryptedDotEnvX(privateKey, ".env", ".env.production");

// With vault
services.AddDotEnvXVault(dotEnvKey, ".env.vault");

IDotEnvService Usage

public class MyService
{
 private readonly IDotEnvService _env;

 public MyService(IDotEnvService env) => _env = env;

 public void Example()
 {
 var apiKey = _env.Get("API_KEY"); // null if missing
 var dbUrl = _env.GetOrDefault("DB_URL", "localhost"); // default if missing
 var secret = _env.GetRequired("SECRET"); // throws if missing

 if (_env.Contains("FEATURE_FLAG"))
 // Feature is enabled

 _env.Set("LAST_UPDATE", DateTime.UtcNow.ToString("O"));
 _env.Set("SECRET", "value", encrypt: true);
 }
}

Encryption

DotEnvX uses ECIES (Elliptic Curve Integrated Encryption Scheme) with secp256k1 and AES-256-GCM for military-grade encryption of environment variables.

Encryption Details

  • Curve: secp256k1 (256-bit, same as Bitcoin)
  • Symmetric Cipher: AES-256-GCM
  • Key Derivation: SHA-256 from ECDH shared secret
  • Nonce: 12 bytes (96-bit, randomly generated)
  • Tag: 16 bytes (128-bit authentication tag)

Encryption Workflow

// 1. Generate keypair (one-time setup)
var keypair = DotEnv.GenerateKeypair();
File.WriteAllText(".env.keys", $"DOTENV_PRIVATE_KEY={keypair.PrivateKey}");

// 2. Set encrypted values
DotEnv.Set("DB_PASSWORD", "secret123", new SetOptions { Encrypt = true });
DotEnv.Set("API_KEY", "sk-abc123", new SetOptions { Encrypt = true });

// 3. Load in application (auto-decrypts using .env.keys)
DotEnv.Config();
var dbPassword = Environment.GetEnvironmentVariable("DB_PASSWORD");
// Returns: "secret123" (decrypted!)

Vault Files

Vault files encrypt entire .env files into a single .env.vault file that is safe to commit. Use DOTENV_KEY to decrypt specific environments at deploy time.

// Create vault from multiple environments
var result = DotEnv.CreateVault(new Dictionary<string, string>
{
 { "production", ".env.production" },
 { "staging", ".env.staging" },
 { "development", ".env.development" }
}, ".env.vault");

// Save DOTENV_KEYs to secure secret management
foreach (var (env, key) in result.EnvironmentKeys)
 Console.WriteLine($"DOTENV_KEY_{env.ToUpper()}={key.DotEnvKey}");

// Load from vault in production
DotEnv.Config(new DotEnvOptions
{
 Path = new[] { ".env.vault" },
 DotEnvKey = productionDotEnvKey
});

File Types & Best Practices

File Purpose Commit?
.envDefault environment variablesYes (if encrypted)
.env.localLocal overridesNo
.env.{environment}Environment-specificYes (if encrypted)
.env.keysPrivate keys for decryptionNEVER
.env.vaultEncrypted vault for deploymentYes
.env.exampleTemplate showing required variablesYes

Error Handling

// Pattern 1: Check result error
var result = DotEnv.Config();
if (result.Error != null)
{
 if (result.Error is DotEnvError envError)
 Console.WriteLine($"[{envError.Code}] {envError.Message}");
}

// Pattern 2: Strict mode (throws on error)
try
{
 DotEnv.Config(new DotEnvOptions { Strict = true });
}
catch (DotEnvError ex)
{
 Console.WriteLine($"[{ex.Code}] {ex.Message}");
}

// Pattern 3: Ignore specific errors
DotEnv.Config(new DotEnvOptions
{
 Ignore = new[] { "MISSING_ENV_FILE" }
});

Error Codes

MISSING_ENV_FILE - .env file not found
DECRYPTION_FAILED - Failed to decrypt value
INVALID_DOTENV_KEY - Malformed DOTENV_KEY
MISSING_PRIVATE_KEY - Private key required
KEY_NOT_FOUND - Variable not found
ENV_FILE_WRITE_ERROR - Failed to write file

Related Packages