Secure, feature-complete .env file management for .NET with encryption, vault support, dependency injection, and a powerful CLI tool.
Get up and running in seconds. Create a .env file and load it in your application.
DATABASE_URL=postgresql://localhost/mydb
API_KEY=sk-1234567890abcdef
DEBUG=true
PORT=3000using Noundry.DotEnvX.Core;
// Load .env file
DotEnv.Config();
// Access variables
var dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
Console.WriteLine($"Database: {dbUrl}");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;
});Protect sensitive values with secp256k1 + AES-256-GCM encryption. Encrypted values are safe to commit to source control.
Encrypt entire .env files into a single .env.vault for secure multi-environment deployment.
Thread-safe IDotEnvService with read, write, reload, and change notification support.
Integrates with IConfiguration and supports hot reload when .env files change.
Reference other variables using ${VAR} syntax with fallback to process environment.
The DotEnv static class provides the primary entry point for loading, parsing, and managing environment variables.
// 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}");| Option | Default | Description |
|---|---|---|
Path | [".env"] | Files to load |
Overload | false | Override existing environment variables |
Strict | false | Throw on errors |
Ignore | null | Error codes to ignore |
PrivateKey | null | Private key for decryption |
EnvKeysFile | ".env.keys" | Keys file path |
DotEnvKey | null | DOTENV_KEY for vault decryption |
Convention | null | Loading convention ("nextjs" or "flow") |
// 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 });Register the thread-safe IDotEnvService for production-ready environment variable access.
// 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");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);
}
}DotEnvX uses ECIES (Elliptic Curve Integrated Encryption Scheme) with secp256k1 and AES-256-GCM for military-grade encryption of environment variables.
// 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 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 | Purpose | Commit? |
|---|---|---|
.env | Default environment variables | Yes (if encrypted) |
.env.local | Local overrides | No |
.env.{environment} | Environment-specific | Yes (if encrypted) |
.env.keys | Private keys for decryption | NEVER |
.env.vault | Encrypted vault for deployment | Yes |
.env.example | Template showing required variables | Yes |
// 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" }
});MISSING_ENV_FILE - .env file not foundDECRYPTION_FAILED - Failed to decrypt valueINVALID_DOTENV_KEY - Malformed DOTENV_KEYMISSING_PRIVATE_KEY - Private key requiredKEY_NOT_FOUND - Variable not foundENV_FILE_WRITE_ERROR - Failed to write file