Isaac.

Environment Variables and Configuration

Manage application settings securely with environment variables.

By EMEPublished: February 20, 2025
environment variablesconfigurationsecurity.envsettings

A Simple Analogy

Environment variables are like notes on a whiteboard. Instead of hardcoding database connection "Server=prod.db.com" in code, you write it on a whiteboard that different environments can read and update. Prod reads one note, dev reads another—same code, different values.


What Are Environment Variables?

Environment variables are key-value pairs that configure application behavior. They hold database URLs, API keys, and settings without embedding them in code.


Why Use Environment Variables?

  • Security: Keep secrets out of source control
  • Flexibility: Different settings per environment
  • Simplicity: Change config without redeploying
  • CI/CD: Pass settings through pipelines
  • 12-factor app: Industry best practice

Setting Environment Variables

Linux/macOS

export DATABASE_URL="postgresql://localhost/myapp"
export API_KEY="secret-key-123"

# Check
echo $DATABASE_URL

# Permanent: Add to ~/.bashrc or ~/.zshrc

Windows

set DATABASE_URL=postgresql://localhost/myapp
set API_KEY=secret-key-123

# Permanent: System Properties → Environment Variables

.NET Usage

var builder = WebApplication.CreateBuilder(args);

// Access environment variables
var dbUrl = builder.Configuration["DATABASE_URL"];
var apiKey = builder.Configuration["API_KEY"];

// From .env file
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddJsonFile(".env.local");

builder.Services.Configure<AppSettings>(options =>
{
    options.DatabaseUrl = builder.Configuration["DATABASE_URL"];
    options.ApiKey = builder.Configuration["API_KEY"];
});

public class AppSettings
{
    public string DatabaseUrl { get; set; }
    public string ApiKey { get; set; }
}

Node.js with dotenv

require("dotenv").config();  // Load from .env file

const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
const port = process.env.PORT || 3000;

console.log(`Connecting to ${dbUrl}`);
app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});

.env File Example

# .env file (never commit to git)
DATABASE_URL=postgresql://user:pass@localhost/myapp
API_KEY=secret-key-12345
ENVIRONMENT=development
LOG_LEVEL=debug
JWT_SECRET=super-secret-jwt-key

.gitignore Configuration

# Never commit secrets
.env
.env.local
.env.*.local
secrets/
*.key
*.pem

Best Practices

  1. Never commit .env: Add to .gitignore
  2. Use .env.example: Show structure without secrets
  3. Name clearly: DATABASE_URL, not DB or DATABASE
  4. Type conversion: Convert strings to appropriate types
  5. Validation: Ensure required variables present

Configuration Hierarchy

// Priority order (highest to lowest)
// 1. Command line arguments
// 2. Environment variables
// 3. appsettings.json
// 4. appsettings.{Environment}.json

builder.Configuration
    .AddJsonFile("appsettings.json")
    .AddJsonFile($"appsettings.{env}.json")
    .AddEnvironmentVariables()
    .AddCommandLine(args);

Related Concepts to Explore

  • Configuration providers
  • Secrets Manager (Azure, AWS)
  • Configuration validation
  • Feature flags with environment-based toggles

Summary

Environment variables externalize configuration, keeping secrets secure and enabling environment-specific settings. Master them to follow 12-factor principles and maintain application security.