Skip to content

plsft/DotEnvX

Repository files navigation

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 DotEnvX?

  • πŸ” 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

πŸ“¦ Installation

Core Library

dotnet add package DotEnvX

ASP.NET Core Integration

dotnet add package DotEnvX.Extensions.DependencyInjection

CLI Tool (Global)

dotnet tool install --global DotEnvX.Tool

πŸš€ Quick Start

Basic Usage

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

ASP.NET Core Integration

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();

πŸ” 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 dotenvx command provides powerful environment management:

Setting Values

# 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

Managing Encryption

# 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

Utility Commands

# 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

πŸ“š Advanced Features

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 DotEnvX.Tool
        dotenvx 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

    dotenvx 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

DotEnv.Config(options)

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)

DotEnv.Parse(content, options)

Parse .env content.

DotEnv.Set(key, value, options)

Set environment variable.

DotEnv.Get(key, options)

Get environment variable.

DotEnv.GenerateKeypair()

Generate encryption keypair.

DotEnv.Encrypt(value, publicKey)

Encrypt a value.

DotEnv.Decrypt(encryptedValue, privateKey)

Decrypt a value.

πŸ§ͺ Testing

# Run all tests
dotnet test

# Run with coverage
dotnet test /p:CollectCoverage=true

# Run specific tests
dotnet test --filter "FullyQualifiedName~Encryption"

πŸ“¦ Package Structure

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

🀝 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)
  • 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.

πŸ™ Acknowledgments

πŸ“Š Status

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

πŸ”— Links

πŸ†š DotEnvX vs dotnet user-secrets

Why Choose DotEnvX?

While dotnet user-secrets is great for basic development scenarios, DotEnvX provides a comprehensive solution for both development and production environments.

Feature Comparison

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 ⚠️ 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 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 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 (DotEnvX) 
builder.Configuration.AddDotEnvX(options =>
{
    options.Path = new[] { ".env", ".env.local" };
    options.Overload = true;
});

Made with ❀️ for the .NET community
Star ⭐ this repo if you find it useful!

About

A secure .env file loader for .NET with encryption support - port of dotenvx

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages