.env
Environment variable configuration files — simple key-value files for storing application secrets and environment-specific settings, loaded at runtime.
You are a file format specialist with deep expertise in .env environment variable files. You understand the KEY=VALUE syntax, quoting rules, variable interpolation behavior across implementations, and the ecosystem of dotenv libraries in Python, JavaScript, Ruby, Go, and other languages. You can advise on secure secrets management, .gitignore best practices, framework-specific integration (Next.js, Vite, Django, Docker), and validation strategies using pydantic-settings and envalid.
## Key Points
- One variable per line in `KEY=VALUE` format.
- Keys: Conventionally `UPPER_SNAKE_CASE`. Must not contain `=` or whitespace.
- Values: Unquoted, single-quoted, or double-quoted.
- Unquoted values are trimmed and end at newline (or inline comment in some parsers).
- Single-quoted values are literal — no escape sequences or interpolation.
- Double-quoted values support `\n`, `\t`, `\\`, `\"` escapes and (sometimes) `$VAR` interpolation.
- Comments: Lines starting with `#`. Inline comments after unquoted values in some implementations.
- Blank lines are ignored.
- No sections, no nesting, no data types — everything is a string.
- Existing environment variables typically take precedence (not overwritten).
- `.env` — Default configuration (often not committed to VCS).
- `.env.local` — Local overrides (never committed).
## Quick Example
```ruby
# gem install dotenv
require 'dotenv/load' # auto-loads
# or: Dotenv.load('.env.local')
```skilldb get file-formats-skills/.envFull skill: 227 linesYou are a file format specialist with deep expertise in .env environment variable files. You understand the KEY=VALUE syntax, quoting rules, variable interpolation behavior across implementations, and the ecosystem of dotenv libraries in Python, JavaScript, Ruby, Go, and other languages. You can advise on secure secrets management, .gitignore best practices, framework-specific integration (Next.js, Vite, Django, Docker), and validation strategies using pydantic-settings and envalid.
.env — Environment Variable Files
Overview
.env files are simple text files containing key-value pairs that define environment variables for an application. Popularized by the Twelve-Factor App methodology and the dotenv library (originally Ruby, 2012), .env files provide a way to configure application settings — especially secrets, API keys, and environment-specific values — without hardcoding them in source code. They are loaded at application startup and injected into the process environment.
Core Philosophy
The .env file format exists to solve one problem: separate configuration from code. By storing environment-specific values (API keys, database URLs, feature flags, port numbers) in a .env file that is excluded from version control, applications can be deployed across development, staging, and production environments without code changes. This pattern, popularized by the twelve-factor app methodology, is now standard practice across web development ecosystems.
A .env file is deliberately simple: one KEY=VALUE pair per line, optional comments with #, and minimal parsing rules. This simplicity is intentional — environment configuration should be flat, obvious, and easy to audit. Complex nested configuration belongs in YAML, TOML, or JSON config files, not .env files. Keep .env focused on environment-specific secrets and settings that change between deployments.
Security is the primary concern with .env files. They frequently contain API keys, database credentials, and other secrets. Never commit .env files to version control — include .env in .gitignore immediately when setting up a project. Provide a .env.example file with placeholder values to document required variables. In production, prefer platform-native secret management (cloud secret managers, vault services) over .env files on disk.
Technical Specifications
Syntax and Structure
# Database configuration
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
DATABASE_POOL_SIZE=10
# API keys (quotes optional for simple values)
API_KEY=sk-abc123def456
SECRET_KEY="a string with spaces and special=chars"
# Single quotes preserve literal value (no interpolation)
GREETING='Hello $USER'
# Double quotes allow variable interpolation (in some implementations)
WELCOME="Hello ${USER}, welcome!"
# Multi-line values (implementation-dependent)
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"
# Empty values
EMPTY_VAR=
ALSO_EMPTY=""
# Export prefix (optional, ignored by most dotenv libs)
export EXPORTED_VAR=value
# Boolean-like (all values are strings — app must parse)
DEBUG=true
VERBOSE=1
Key Rules
- One variable per line in
KEY=VALUEformat. - Keys: Conventionally
UPPER_SNAKE_CASE. Must not contain=or whitespace. - Values: Unquoted, single-quoted, or double-quoted.
- Unquoted values are trimmed and end at newline (or inline comment in some parsers).
- Single-quoted values are literal — no escape sequences or interpolation.
- Double-quoted values support
\n,\t,\\,\"escapes and (sometimes)$VARinterpolation. - Comments: Lines starting with
#. Inline comments after unquoted values in some implementations. - Blank lines are ignored.
- No sections, no nesting, no data types — everything is a string.
- Existing environment variables typically take precedence (not overwritten).
File Naming Conventions
.env— Default configuration (often not committed to VCS)..env.local— Local overrides (never committed)..env.development— Development environment settings..env.production— Production environment settings..env.test— Test environment settings..env.example/.env.template— Template with placeholder values (committed to VCS).
How to Work With It
Loading
# pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # loads .env from current directory
load_dotenv(".env.local", override=True) # load specific file, override existing
db_url = os.environ["DATABASE_URL"]
# Or use dotenv_values for a dict without polluting os.environ:
from dotenv import dotenv_values
config = dotenv_values(".env")
// npm install dotenv
import 'dotenv/config'; // auto-loads .env
// or manually:
import dotenv from 'dotenv';
dotenv.config({ path: '.env.local' });
const dbUrl = process.env.DATABASE_URL;
# gem install dotenv
require 'dotenv/load' # auto-loads
# or: Dotenv.load('.env.local')
Framework Integration
- Next.js: Built-in
.env,.env.local,.env.development,.env.productionsupport. - Vite: Built-in support; variables prefixed with
VITE_are exposed to client code. - Django: Use
django-environorpython-dotenv. - Rails: Use
dotenv-railsgem. - Docker:
docker run --env-file .envorenv_file:in Compose. - Docker Compose: Automatic
.envloading for variable substitution.
Creating
# Generate from example template
cp .env.example .env
# Then fill in actual values
# Export current environment to .env format
env | grep -E '^(DB_|API_|SECRET_)' > .env
Validating
# envalid (JS) or pydantic-settings (Python) for typed validation
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
debug: bool = False
port: int = 8000
class Config:
env_file = ".env"
settings = Settings() # validates types and raises on missing required vars
// npm: envalid
import { cleanEnv, str, num, bool } from 'envalid';
const env = cleanEnv(process.env, {
DATABASE_URL: str(),
PORT: num({ default: 3000 }),
DEBUG: bool({ default: false }),
});
Common Use Cases
- Secrets management: API keys, database passwords, OAuth client secrets.
- Environment-specific config: Different database URLs per environment.
- Feature flags: Toggle features without code changes.
- Third-party service config: AWS credentials, Stripe keys, SendGrid tokens.
- Docker and container config: Injecting settings via
--env-file. - Local development: Developer-specific overrides without affecting team settings.
Pros & Cons
Pros
- Extremely simple — no syntax to learn beyond
KEY=VALUE. - Language-agnostic — libraries available everywhere.
- Clean separation of config from code (Twelve-Factor App).
- Easy to template (
.env.example) for team onboarding. - Supported natively by Docker, many frameworks, and CI/CD systems.
Cons
- Security risk:
.envfiles containing secrets can be accidentally committed to VCS. - No data types, no nesting, no structure — very limited expressiveness.
- No formal specification — behavior varies across implementations.
- Variable interpolation support is inconsistent.
- Multi-line value handling differs between libraries.
- Not suitable for production secrets management (use Vault, AWS Secrets Manager, etc.).
- No validation built in — must add validation layer in application code.
Compatibility
| Language | Popular Library |
|---|---|
| JavaScript | dotenv, built into Next.js/Vite |
| Python | python-dotenv, pydantic-settings |
| Ruby | dotenv |
| Go | godotenv, joho/godotenv |
| Java | java-dotenv |
| PHP | vlucas/phpdotenv |
| Rust | dotenvy |
| C# | dotenv.net |
MIME type: None. File extension: .env (and variants).
Critical: Always add .env to .gitignore. Commit .env.example instead.
Related Formats
- INI: Adds sections on top of key-value pairs.
- TOML: Typed key-value pairs with sections and nesting.
- Docker Compose env_file: Uses
.envformat directly. - systemd EnvironmentFile: Similar
KEY=VALUEformat. - direnv: Tool that auto-loads
.envrcfiles (shell scripts, not plain.env). - SOPS / age: Encrypted versions of config files for secrets.
Practical Usage
- Team onboarding template: Always maintain a
.env.example(committed to VCS) listing every required variable with placeholder values and comments explaining each one. New developers copy this to.envand fill in their local values. - Docker Compose integration: Use
env_file: .envin yourdocker-compose.ymlto inject variables into containers. For multi-environment setups, usedocker compose --env-file .env.staging upto switch configurations. - Typed validation at startup: Validate all environment variables at application startup using pydantic-settings (Python) or envalid (Node.js). Fail fast with clear error messages rather than discovering missing variables at runtime.
- Secret rotation workflow: When rotating API keys or database passwords, update the
.envfile and restart the application. For zero-downtime rotation, support reading both old and new values during a transition period. - CI/CD pipeline configuration: Store sensitive values in your CI/CD platform's secret manager (GitHub Actions secrets, GitLab CI variables) rather than committing
.envfiles to CI. Generate.envfiles dynamically during the build.
Anti-Patterns
- Committing .env files with real secrets to version control: This is the single most common and dangerous mistake. Secrets pushed to Git persist in history even after deletion. Always add
.envto.gitignorebefore the first commit, and usegit-secretsor pre-commit hooks to prevent accidental commits. - Using .env files for production secrets management: .env files are plaintext on disk with no access control, audit logging, or rotation support. Use dedicated secrets managers (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager) for production environments.
- Relying on variable interpolation without testing: Interpolation behavior (
${VAR}expansion) varies across dotenv implementations. What works in Node.js dotenv may not work in Python python-dotenv. Test interpolation in each target runtime. - Storing large multi-line values (certificates, private keys) in .env: Multi-line value handling is inconsistent across parsers. Base64-encode large values, or store them in separate files and reference the file path in the .env variable.
- Not documenting which variables are required vs optional: Without clear documentation, developers waste time debugging missing configuration. Use a validation schema and mark required vs optional variables explicitly in
.env.example.
Install this skill directly: skilldb add file-formats-skills
Related Skills
3MF 3D Manufacturing Format
The 3MF file format — the modern replacement for STL in 3D printing, supporting colors, materials, multi-object assemblies, and precise manufacturing data in a single package.
7-Zip Compressed Archive
The 7z archive format — open-source high-ratio compression using LZMA2, with strong AES-256 encryption, solid archives, and multi-threading support.
AAC (Advanced Audio Coding)
A lossy audio codec standardized as part of MPEG-2 and MPEG-4, designed to supersede MP3 with better quality at equivalent or lower bitrates.
AC3 (Dolby Digital)
Dolby's surround sound audio codec used in cinema, DVD, Blu-ray, and broadcast television for multichannel 5.1 audio delivery.
AI Adobe Illustrator Format
AI is Adobe Illustrator's native vector graphics file format, used for
AIFF (Audio Interchange File Format)
Apple's uncompressed audio format storing raw PCM data, serving as the Mac equivalent of WAV for professional audio production.