Skip to content
IsMyENVPublic

Fundamentals · 7 min read

What is a .env file?

Learn what .env files are, how the KEY=value format works, which frameworks load them, and why an environment file must never be served by your web server.

Last updated

The short answer

A .env file is a plain-text file that stores configuration for an application as KEY=value pairs. When the application starts, a loader reads the file and exposes each pair as an environment variable. Code then reads settings such as a database host or an API key from the environment instead of hard-coding them.

The idea comes from the Twelve-Factor App methodology, which recommends keeping configuration that changes between deployments in the environment, separate from the code. The .env file is a convenient way to provide those variables during development and on simple servers. Loader libraries named "dotenv" exist for Ruby, Node.js, PHP, Python, Go and many other languages.

The format

There is no single formal specification, but most loaders agree on the basics:

.envdotenv
# Comments start with a hash
APP_ENV=production
APP_URL=https://example.com

# Values with spaces are quoted
MAIL_FROM_NAME="Example Shop"

# Some loaders accept an "export" prefix, so the file can also be sourced by a shell
export DB_HOST=db.internal
DB_PORT=5432
DB_PASSWORD=change-me
  • Keys are usually upper-case with underscores. Names are case-sensitive.
  • Everything after the first = is the value. Quoting rules, escape sequences and multi-line values differ between loaders.
  • Some loaders support variable expansion such as DATABASE_URL=postgres://${DB_HOST}/app. Others treat it as a literal string.
  • Most loaders do not overwrite variables that are already set in the real environment, so a value configured on the server takes precedence over the file.

.env, .env.local, .env.production and friends

Many frameworks load several files in a defined order so that you can combine shared defaults with machine-specific or environment-specific overrides:

FileTypical purpose
.envBase configuration or defaults. In some frameworks (for example Symfony) it is committed with safe defaults.
.env.localLocal overrides and real secrets for one machine. Never committed.
.env.production, .env.prodValues for the production environment, often loaded when the app runs in production mode.
.env.exampleA template listing required keys without real values. Safe to commit.

That is why IsMyENVPublic checks /.env, /.env.local, /.env.production and /.env.prod: they are the names most likely to hold real production values.

Which tools read .env files

  • Laravel loads .env from the project root through the phpdotenv library.
  • Symfony loads .env, .env.local, .env.$APP_ENV and .env.$APP_ENV.local.
  • Node.js projects use the dotenv package, and Node.js itself can load a file with node --env-file=.env app.js since version 20.6.
  • Next.js and Vite load .env, .env.local and mode-specific files such as .env.production.
  • Django, Flask and Rails projects commonly use python-dotenv, django-environ or dotenv-rails.
  • Docker Compose reads a .env file next to the compose file for variable substitution.

Why the file is sensitive

A production .env usually collects the most valuable secrets of an application in one place:

  • database hosts, user names and passwords,
  • application encryption and signing keys, such as Laravel's APP_KEY or a JWT secret,
  • cloud credentials such as AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY,
  • API keys for payment providers, mail services, error tracking and AI services,
  • internal hostnames that reveal how the infrastructure is built.

With these values, an attacker may be able to read or change the database, send email in your name, forge session cookies, or run up costs on your cloud account, without exploiting any vulnerability in the code.

Scanners look for it constantly

Requests for /.env are among the most common automated probes on the internet. If you look at the access log of almost any public web server, you will find them. An exposed file is usually found within hours or days, not months.

How .env files become public

The file is harmless as long as the web server never serves it. Exposure almost always comes from one of these mistakes:

  • Wrong document root. The web server publishes the project root instead of its public/ directory, so every file in the project is downloadable. This is common on shared hosting when an application is uploaded into public_html.
  • Missing deny rule. The server serves static files by default, and nothing tells it that dotfiles are off-limits.
  • Static file middleware on the wrong folder. A Node.js server calls express.static on the project directory.
  • Deployment artifacts. The file is copied into a static export, a Docker image that serves files, or a publicly readable storage bucket.

Git is a related risk: a committed .env exposes secrets to anyone with access to the repository, and a publicly served .git/ directory can leak it as well.

Good practice

  • Commit a .env.example with key names only, and add .env and .env.*.local to .gitignore.
  • Keep the file outside the directory your web server publishes, and readable only by the application user.
  • Add a web server rule that denies dotfiles as a second line of defense. See the Nginx and Apache guides.
  • On platforms that support it, prefer real environment variables or a secrets manager over a file on disk in production.
  • Use separate credentials per environment, so a leaked development file doesn't unlock production.

Remediation checklist

  • .env is listed in .gitignore and has never been committed
  • The web server's document root is a dedicated public folder, not the project root
  • A web server rule denies access to dotfiles (except /.well-known/)
  • File permissions restrict the file to the application user (for example chmod 600 or 640)
  • Production uses different credentials from development
  • The IsMyENVPublic check reports no exposure after each deployment change

Frameworks

Node.js .env security

Static file middleware, public env prefixes in bundlers, Docker images and secret managers.

9 min read

Frameworks

Laravel .env security

Point the document root at public/, disable debug mode, cache config and rotate APP_KEY safely.

9 min read