ENV Tools

Convert between .env and JSON formats

Essential for modern application configuration and secrets management. ENV files (.env) are the standard for storing environment variables in development. Our tools help you convert, validate, and generate secure .env.example files, ensuring sensitive data stays protected while maintaining consistent configuration across environments.

What are ENV Files?

ENV files (.env) are simple text files containing environment variables in KEY=VALUE format. They've become the de facto standard for managing application configuration, especially secrets and environment-specific settings, following the twelve-factor app methodology.

History & Creation

The .env file convention was popularized by the Ruby dotenv library created by Brandon Keepers in 2012. It was inspired by the twelve-factor app methodology, which advocates for storing config in the environment. The pattern quickly spread to other languages and frameworks, becoming a universal standard for development configuration.

Where ENV Files are Used

  • Node.js applications (dotenv)
  • Docker and Docker Compose
  • Python projects (python-dotenv)
  • PHP frameworks (Laravel, Symfony)
  • Ruby on Rails applications
  • CI/CD pipelines
  • Serverless functions
  • Kubernetes ConfigMaps

Benefits of ENV Files

  • Security: Keep secrets out of code repositories
  • Flexibility: Different configs for dev, staging, production
  • Simplicity: Plain text, easy to read and edit
  • Portability: Works across languages and platforms
  • 12-Factor Compliance: Follows modern app development principles
  • Version Control: .env.example can be committed, .env stays local

Security Best Practices

⚠️ Critical Security Rules

  • NEVER commit .env files to version control
  • Always add .env to .gitignore
  • Use .env.example with dummy values for documentation
  • Rotate secrets regularly
  • Use secret management services in production
  • Encrypt .env files if they must be shared

Working with ENV Files Across Platforms

🟒 Node.js

  • dotenv package
  • process.env access
  • Built into many frameworks
  • npm scripts integration

🐳 Docker

  • docker run --env-file
  • Docker Compose env_file
  • Build-time ARG values
  • Runtime ENV values

☸️ Kubernetes

  • ConfigMaps
  • Secrets
  • Sealed Secrets
  • External Secrets Operator

ENV ↔ JSON Converter

Convert between environment variable files and JSON

ENV File Examples & Best Practices

ENV files are crucial for secure application configuration. Here are comprehensive examples demonstrating proper usage, security practices, and common patterns.

Basic ENV File Structure

Simple Application .env

Basic environment variables for a web application

# Application Settings
NODE_ENV=development
APP_NAME="My Awesome App"
APP_VERSION=1.0.0
PORT=3000
HOST=localhost

# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp_dev
DB_USER=postgres
DB_PASSWORD=secretpassword123

# API Keys
API_KEY=sk_test_abcdef123456789
SECRET_KEY=your-secret-key-here

# Feature Flags
ENABLE_DEBUG=true
ENABLE_ANALYTICS=false
LOG_LEVEL=debug

Production .env with URLs

Environment variables for production deployment

# Production Environment
NODE_ENV=production
APP_URL=https://api.example.com
FRONTEND_URL=https://app.example.com
ALLOWED_ORIGINS=https://app.example.com,https://www.example.com

# Database (Using Connection String)
DATABASE_URL=postgresql://user:pass@prod-db.example.com:5432/myapp?sslmode=require

# Redis Cache
REDIS_URL=redis://:password@redis.example.com:6379/0

# AWS Configuration
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
S3_BUCKET=my-app-uploads

# Monitoring
SENTRY_DSN=https://abc123@o123456.ingest.sentry.io/1234567
LOG_LEVEL=error

Complex Configuration Examples

Multi-line Values and Special Characters

Handling complex values in ENV files

# Multi-line values (not all parsers support this)
RSA_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3Uk/tUQ...
...rest of key...
-----END RSA PRIVATE KEY-----"

# JSON in environment variables
FIREBASE_CONFIG='{"apiKey":"AIza...","authDomain":"myapp.firebaseapp.com","projectId":"myapp-12345"}'

# URLs with query parameters
WEBHOOK_URL="https://api.example.com/webhook?token=abc123&type=env"

# Paths with spaces (use quotes)
LOG_PATH="/var/log/My Application/app.log"

# Special characters
PASSWORD_WITH_SPECIAL="P@ssw0rd#2024!"
REGEX_PATTERN="^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,}$"

Docker Compose with .env

Using ENV files with Docker Compose

# .env file for Docker Compose
COMPOSE_PROJECT_NAME=myapp

# App Configuration
APP_PORT=3000
APP_ENV=development

# Database
POSTGRES_VERSION=14
POSTGRES_DB=myapp
POSTGRES_USER=postgres
POSTGRES_PASSWORD=secretpassword
DB_PORT=5432

# Redis
REDIS_VERSION=7-alpine
REDIS_PORT=6379

# Volumes
DATA_PATH=./data
LOGS_PATH=./logs

# docker-compose.yml usage:
# version: '3.8'
# services:
#   app:
#     ports:
#       - "${APP_PORT}:3000"
#   db:
#     image: postgres:${POSTGRES_VERSION}
#     environment:
#       POSTGRES_DB: ${POSTGRES_DB}
#       POSTGRES_USER: ${POSTGRES_USER}
#       POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

Environment-Specific Configurations

.env.example Template

Template file safe to commit to version control

# Application Configuration
NODE_ENV=development
APP_NAME="Your App Name"
APP_URL=http://localhost:3000
PORT=3000

# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=your_database_name
DB_USER=your_database_user
DB_PASSWORD=your_database_password

# Or use connection string
# DATABASE_URL=postgresql://user:pass@localhost:5432/dbname

# Authentication
JWT_SECRET=your_jwt_secret_key_here
SESSION_SECRET=your_session_secret_here
REFRESH_TOKEN_SECRET=your_refresh_token_secret

# Third-party Services
STRIPE_SECRET_KEY=sk_test_your_stripe_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret

# Email Service
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password

# Cloud Storage
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
AWS_REGION=us-east-1
S3_BUCKET=your-s3-bucket-name

# OAuth Providers
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret

# Feature Flags
ENABLE_REGISTRATION=true
ENABLE_OAUTH=true
MAINTENANCE_MODE=false

Microservices Configuration

ENV configuration for microservices architecture

# Service Discovery
SERVICE_NAME=user-service
SERVICE_PORT=3001
CONSUL_HOST=consul.service.consul
CONSUL_PORT=8500

# Inter-service Communication
AUTH_SERVICE_URL=http://auth-service:3000
NOTIFICATION_SERVICE_URL=http://notification-service:3002
PAYMENT_SERVICE_URL=http://payment-service:3003

# Message Queue
RABBITMQ_URL=amqp://user:pass@rabbitmq:5672
QUEUE_NAME=user-events

# Service Mesh
ENABLE_TRACING=true
JAEGER_AGENT_HOST=jaeger
JAEGER_AGENT_PORT=6831

# Circuit Breaker
CIRCUIT_BREAKER_TIMEOUT=3000
CIRCUIT_BREAKER_THRESHOLD=5
CIRCUIT_BREAKER_RESET_TIMEOUT=10000

# Rate Limiting
RATE_LIMIT_WINDOW=60000
RATE_LIMIT_MAX_REQUESTS=100

Working with ENV Files in Different Languages

Node.js - Using dotenv

Loading and using ENV files in Node.js applications

// Load .env file
require('dotenv').config();

// Or with ES6 modules
import dotenv from 'dotenv';
dotenv.config();

// Load from custom path
require('dotenv').config({ path: '.env.local' });

// Access environment variables
const config = {
  app: {
    name: process.env.APP_NAME || 'DefaultApp',
    port: parseInt(process.env.PORT, 10) || 3000,
    env: process.env.NODE_ENV || 'development'
  },
  database: {
    url: process.env.DATABASE_URL,
    // Parse database URL
    ...parseDbUrl(process.env.DATABASE_URL)
  },
  features: {
    enableDebug: process.env.ENABLE_DEBUG === 'true',
    logLevel: process.env.LOG_LEVEL || 'info'
  }
};

// Validate required variables
const requiredEnvVars = ['DATABASE_URL', 'JWT_SECRET'];
const missingVars = requiredEnvVars.filter(v => !process.env[v]);

if (missingVars.length > 0) {
  throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
}

// Type-safe config with validation
const envSchema = {
  NODE_ENV: z.enum(['development', 'staging', 'production']),
  PORT: z.string().transform(Number),
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string().min(32)
};

const env = envSchema.parse(process.env);

Python - Using python-dotenv

Loading ENV files in Python applications

import os
from dotenv import load_dotenv
from pathlib import Path

# Load .env file
load_dotenv()

# Load from specific path
env_path = Path('.') / '.env.production'
load_dotenv(dotenv_path=env_path)

# Load and override existing variables
load_dotenv(override=True)

# Access environment variables
config = {
    'app_name': os.getenv('APP_NAME', 'DefaultApp'),
    'port': int(os.getenv('PORT', 3000)),
    'debug': os.getenv('DEBUG', 'False').lower() == 'true',
    'database_url': os.environ['DATABASE_URL']  # Raises error if missing
}

# Using with Django
# settings.py
from pathlib import Path
from dotenv import load_dotenv

# Build paths inside the project
BASE_DIR = Path(__file__).resolve().parent.parent

# Load environment variables
load_dotenv(BASE_DIR / '.env')

SECRET_KEY = os.environ['SECRET_KEY']
DEBUG = os.getenv('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '').split(',')

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ['DB_NAME'],
        'USER': os.environ['DB_USER'],
        'PASSWORD': os.environ['DB_PASSWORD'],
        'HOST': os.getenv('DB_HOST', 'localhost'),
        'PORT': os.getenv('DB_PORT', '5432'),
    }
}

Docker - ENV File Usage

Using ENV files with Docker and Docker Compose

# 1. Docker run with env file
docker run --env-file .env myapp

# 2. Docker Compose with .env
# docker-compose.yml
version: '3.8'

services:
  app:
    image: myapp:latest
    env_file: .env  # Load all variables from .env
    environment:
      # Override specific variables
      NODE_ENV: production
    ports:
      - "${APP_PORT:-3000}:3000"

  db:
    image: postgres:14
    env_file:
      - .env
      - .env.db  # Multiple env files
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}

# 3. Multi-stage build with build args
# Dockerfile
FROM node:16 AS builder
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:16-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .

# Use --build-arg to pass values during build
# docker build --build-arg NODE_ENV=development -t myapp .

Production Best Practices

Security Checklist

  • βœ“ Never commit .env files containing real secrets
  • βœ“ Use .env.example as documentation
  • βœ“ Validate all environment variables on startup
  • βœ“ Use strong, unique values for secrets
  • βœ“ Rotate credentials regularly
  • βœ“ Use secret management services in production
  • βœ“ Encrypt .env files at rest
  • βœ“ Audit access to environment variables

Production Secret Management

Using secret management services instead of .env files

// AWS Secrets Manager
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();

async function getSecret(secretName) {
  try {
    const data = await secretsManager.getSecretValue({ 
      SecretId: secretName 
    }).promise();
    
    return JSON.parse(data.SecretString);
  } catch (error) {
    console.error('Failed to retrieve secret:', error);
    throw error;
  }
}

// HashiCorp Vault
const vault = require('node-vault')({
  endpoint: process.env.VAULT_ADDR,
  token: process.env.VAULT_TOKEN
});

async function getVaultSecret(path) {
  const result = await vault.read(path);
  return result.data;
}

// Azure Key Vault
const { SecretClient } = require("@azure/keyvault-secrets");
const { DefaultAzureCredential } = require("@azure/identity");

const client = new SecretClient(
  process.env.KEY_VAULT_URL,
  new DefaultAzureCredential()
);

async function getAzureSecret(secretName) {
  const secret = await client.getSecret(secretName);
  return secret.value;
}

// Kubernetes Secrets (mounted as files)
const fs = require('fs');
const dbPassword = fs.readFileSync('/var/run/secrets/db-password', 'utf8');

Common Patterns and Solutions

Environment Variable Validation

Validating and parsing environment variables

// TypeScript with Zod validation
import { z } from 'zod';

const envSchema = z.object({
  // Required variables
  NODE_ENV: z.enum(['development', 'staging', 'production']),
  PORT: z.string().regex(/^\d+$/).transform(Number),
  DATABASE_URL: z.string().url(),
  
  // Optional with defaults
  LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
  ENABLE_CORS: z.string().transform(v => v === 'true').default('false'),
  
  // Complex validation
  ALLOWED_ORIGINS: z.string().transform(v => v.split(',')),
  MAX_FILE_SIZE: z.string().regex(/^\d+[KMG]?B?$/i).default('10MB'),
  
  // Conditional requirements
  SMTP_HOST: z.string().optional(),
  SMTP_PORT: z.string().regex(/^\d+$/).transform(Number).optional(),
  SMTP_USER: z.string().optional(),
  SMTP_PASS: z.string().optional(),
}).refine(
  data => {
    // If SMTP_HOST is provided, all SMTP fields are required
    if (data.SMTP_HOST) {
      return data.SMTP_PORT && data.SMTP_USER && data.SMTP_PASS;
    }
    return true;
  },
  { message: 'All SMTP fields required when SMTP_HOST is set' }
);

// Parse and validate
const env = envSchema.parse(process.env);

// Export typed config
export const config = {
  app: {
    env: env.NODE_ENV,
    port: env.PORT,
  },
  database: {
    url: env.DATABASE_URL,
  },
  features: {
    cors: env.ENABLE_CORS,
  },
  email: env.SMTP_HOST ? {
    host: env.SMTP_HOST,
    port: env.SMTP_PORT,
    user: env.SMTP_USER,
    pass: env.SMTP_PASS,
  } : undefined,
} as const;

ENV File Do's and Don'ts

βœ“ Do's
  • Use descriptive variable names
  • Group related variables with prefixes
  • Document variables in .env.example
  • Validate variables on app startup
  • Use appropriate data types
  • Keep .env files simple and flat
βœ— Don'ts
  • Never commit real secrets
  • Don't use spaces around = sign
  • Avoid complex nested structures
  • Don't rely on .env files in production
  • Never share .env files via email/chat
  • Don't mix concerns in one file