Umgebungsdatei-Formatierer
Formatieren und validieren Sie .env-Dateien mit Syntaxhervorhebung
What is .env File Formatting?
Environment file formatting transforms inconsistently structured .env files into a clean,
readable format with consistent spacing, proper quoting, logical grouping, and standardized line endings.
The .env file format — popularized by the twelve-factor app methodology — stores application
configuration as KEY=VALUE pairs that are loaded into environment variables at runtime.
While the format appears trivially simple, real-world .env files accumulate formatting
inconsistencies over time: mixed quoting styles, irregular spacing around equals signs, missing
blank lines between logical sections, and trailing whitespace that causes subtle parsing differences
across dotenv implementations.
A well-formatted environment file improves readability during code reviews, reduces merge conflicts
in version control, and prevents parsing bugs caused by invisible characters or inconsistent quoting.
This tool normalizes your .env files to follow community conventions without altering
the semantic content — variable names and their effective values remain identical after formatting.
The .env File Format and KEY=VALUE Syntax
The .env format originated with the Ruby dotenv gem and has since been
adopted across virtually every language ecosystem — Node.js (dotenv), Python
(python-dotenv), Go (godotenv), PHP (vlucas/phpdotenv),
and Rust (dotenvy). Despite widespread use, there is no formal specification — behavior
varies between implementations. The core syntax rules that most parsers agree on are:
-
Basic assignment:
KEY=valueassigns the stringvalueto the variableKEY. No spaces around the equals sign in most implementations —KEY = valuemay be interpreted differently (some parsers include the spaces in the key or value). -
Comments: Lines starting with
#are comments and ignored by parsers. Inline comments after values (KEY=value # comment) are supported by some implementations (Docker Compose, bash) but not others (Node.js dotenv treats everything after=as the value). -
Quoting: Values can be unquoted, single-quoted, or double-quoted. Double-quoted
values support escape sequences (
\n,\t,\\) and variable interpolation in some parsers. Single-quoted values are treated as literal strings with no escape processing. Unquoted values are trimmed of trailing whitespace by most parsers. -
Empty values:
KEY=sets the variable to an empty string. Omitting the equals sign entirely (KEY) is handled inconsistently — some parsers skip it, others set it to an empty string. Best practice is to always include the equals sign. -
Multiline values: Double-quoted values can span multiple lines in most implementations.
The newlines are preserved as literal
\ncharacters in the variable value. This is commonly used for private keys, certificates, and JSON configuration blobs.
Common Formatting Issues and How the Formatter Resolves Them
Environment files degrade over time as different developers add variables with inconsistent styles. A formatter normalizes these inconsistencies while preserving semantic meaning:
- Inconsistent quoting: Some values quoted, others not — even when quoting is unnecessary. The formatter applies a consistent quoting strategy: quote values that contain spaces, special characters, or hash symbols; leave simple alphanumeric values unquoted.
-
Spacing around
=: MixingKEY=value,KEY =value, andKEY = valuein the same file. The formatter removes all spaces around the equals sign to follow the most portable convention supported by all parsers. - Trailing whitespace: Invisible spaces or tabs at the end of lines cause values to include unexpected whitespace in some parsers. The formatter strips all trailing whitespace.
-
Missing section separators: Related variables (database config, API keys, feature flags)
grouped together without blank lines between sections. The formatter can insert blank lines between
logical groups detected by variable name prefixes (e.g.,
DB_,AWS_,SMTP_). -
Inconsistent line endings: Mixed
\r\n(Windows) and\n(Unix) line endings that cause diff noise in version control. The formatter normalizes to\nfor maximum compatibility with Docker, Linux servers, and CI environments. - Duplicate keys: The same variable defined multiple times — later definitions silently override earlier ones in most parsers, leading to confusion. The formatter detects and flags duplicates so developers can resolve them intentionally.
Docker and docker-compose Environment Variable Handling
Docker has its own conventions for environment variables that extend beyond the basic dotenv format.
Understanding these differences is essential when formatting .env files used in
containerized deployments:
-
docker-compose
env_filedirective: Docker Compose loads.envfiles specified in theenv_filesection of each service. It uses its own parser that supports inline comments (KEY=value # comment), which differs from Node.js dotenv. The formatter preserves comment positions that are valid in Docker contexts. -
The project-level
.envfile: Docker Compose automatically reads a.envfile in the project root for variable substitution indocker-compose.yml. Variables defined there are used to expand${VARIABLE}references in the Compose file — they are not automatically injected into containers unless also listed inenvironmentorenv_file. -
Build-time vs runtime variables:
ARGin Dockerfiles are build-time variables that do not persist in the final image.ENVdirectives bake values into image layers permanently. For secrets, prefer runtime injection viadocker run --env-filerather than embedding in build layers. -
Variable interpolation: Docker Compose supports
${VAR:-default}syntax for default values and${VAR:?error}for required variables. These shell-style expansions should not be altered by the formatter — they are intentional syntax, not formatting issues.
Node.js dotenv Ecosystem and Parsing Behavior
The Node.js dotenv package (70+ million weekly npm downloads) is the de facto standard
for loading .env files in JavaScript applications. Understanding its parsing behavior
helps write .env files that work reliably across the Node.js ecosystem:
-
No inline comments: Unlike Docker Compose, the standard
dotenvpackage does not support inline comments. WritingPORT=3000 # HTTP portsets the value to3000 # HTTP port— the entire string after the equals sign. Use full-line comments above the variable instead. -
Variable expansion: The
dotenv-expandcompanion package enables${VARIABLE}references within values. Without it,$characters are treated as literal text. The formatter preserves these references without modification. -
Multiline handling: Double-quoted values can span lines:
PRIVATE_KEY="-----BEGIN RSA...\n...\n-----END RSA...". Thedotenvparser processes\nescape sequences inside double quotes into actual newline characters. Single-quoted values preserve\nas the literal two-character sequence. -
Precedence: By default,
dotenvdoes not override existing environment variables. IfPORTis already set in the shell environment, the.envvalue is ignored. This behavior ensures deployment environment variables take precedence over development defaults, but can cause confusion during debugging. -
Framework conventions: Next.js, Vite, and Create React App prefix client-exposed
variables with
NEXT_PUBLIC_,VITE_, orREACT_APP_respectively. Only prefixed variables are embedded in client bundles — all others remain server-side only. The formatter preserves and recognizes these prefixes as logical grouping boundaries.
Code Examples
Well-Formatted .env File Following Community Conventions
# ==================================
# Application Configuration
# ==================================
NODE_ENV=production
APP_NAME=my-api
APP_PORT=3000
APP_URL=https://api.example.com
# ==================================
# Database Configuration
# ==================================
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp_production
DB_USER=app_user
DB_PASSWORD="p@ss\"word with special chars"
# ==================================
# External Services
# ==================================
REDIS_URL=redis://cache.internal:6379/0
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASSWORD="SG.xxxxxxxxxxxxxxxxxxxx"
# ==================================
# Feature Flags
# ==================================
ENABLE_CACHE=true
ENABLE_RATE_LIMIT=true
MAX_UPLOAD_SIZE=10485760
# Multiline value (private key for JWT signing)
JWT_PRIVATE_KEY="-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIODr...base64content...
-----END EC PRIVATE KEY-----"Output:
# Formatting conventions applied:
# - No spaces around = sign
# - Section headers with blank line separators
# - Logical grouping by prefix (DB_, SMTP_, etc.)
# - Double quotes only when value contains special characters
# - Comments on their own line (not inline)
# - Consistent Unix line endings (LF)
# - No trailing whitespaceLoading .env Files in Node.js with dotenv
// Load .env file into process.env
import 'dotenv/config';
// Or with explicit configuration
import { config } from 'dotenv';
import { expand } from 'dotenv-expand';
const env = config({ path: '.env.production' });
expand(env); // Enable ${VARIABLE} expansion
// Access formatted environment variables
const dbConfig = {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || '5432', 10),
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
};
// Validate required variables are present
const required = ['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASSWORD'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required env vars: ${missing.join(', ')}`);
}Docker Compose with .env File Integration
# docker-compose.yml — uses .env file for variable substitution
version: "3.8"
services:
api:
build: .
ports:
- "${APP_PORT:-3000}:3000"
env_file:
- .env # Loaded into container environment
- .env.local # Override for local development
environment:
- NODE_ENV=production # Explicit override
- DB_HOST=db # Container networking override
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata: