Skip to content
5.0 Upwork, 100+ reviews Adobe Certified since 2021 New: become your own Magento developer Learn more →
Magento glossary

What is Magento env.php?

Short answer app/etc/env.php is the Magento 2 config file that belongs to one environment only. bin/magento setup:install writes it, and Magento’s default .gitignore keeps it out of git. It holds the database credentials, the crypt key used to encrypt stored secrets, the admin frontName, MAGE_MODE and the Redis, RabbitMQ and cache settings. Its partner is app/etc/config.php, which is committed and lists enabled modules and shared settings. I think of it simply: shared config goes in config.php and git, secrets and server details stay in env.php.

How it works
  1. bin/magento setup:install generates env.php 01
  2. Magento boots and reads env.php BEFORE any DB connection 02
  3. config.php commits to git, env.php does not 03
  4. Multi-host clusters coordinate via env.php 04
  5. Updating env.php on a running site 05
Each step is explained below

Most common mistake Committing env.php to source control

How it works

Five steps from setup:install to a hardened, multi-host env.php

env.php is a small file, but a wrong value in it can take the whole store down. This is how it is created, when Magento reads it, and how I change it on a live site without surprises.

  1. 01

    bin/magento setup:install generates env.php

    setup:install takes the DB host, name, user and password, the admin frontName and the base URL as options, and writes them into app/etc/env.php as a plain PHP return [ ... ] array, along with a new random crypt.key. The same array gets install.date, the session.save backend and the cache_types on/off map. There is no admin screen for it. To change values later I use bin/magento setup:config:set (for example --session-save=redis) or edit the file by hand, never a second setup:install.

  2. 02

    Magento boots and reads env.php BEFORE any DB connection

    Magento’s deployment config reader loads app/etc/env.php and config.php early in every request, before the database connection is opened and before modules run. MySQL, Redis cache, Redis sessions and RabbitMQ all take their connection details from it. So a syntax error or a wrong host in env.php breaks every page at once, not just one feature. Opcache keeps the compiled file in memory, which matters when you change it (see step 05).

  3. 03

    config.php commits to git, env.php does not

    Magento’s default .gitignore already lists app/etc/env.php. app/etc/config.php, with the enabled-modules array and any settings you dumped with bin/magento app:config:dump, is meant to be committed. In a deploy pipeline env.php comes from somewhere safe: a file that already lives on the server, or a secrets manager such as AWS Secrets Manager or HashiCorp Vault. On Adobe Commerce Cloud it is built from environment variables during deploy.

  4. 04

    Multi-host clusters coordinate via env.php

    With several web servers, each node has its own env.php, and they all point at the same database, Redis and RabbitMQ hosts. config.php is the same everywhere because it comes from git. Within one environment the crypt.key and MAGE_MODE must be identical on every node. If one node has a different key, anything it encrypts cannot be read by the others, and you get random failures that are hard to trace.

  5. 05

    Updating env.php on a running site

    For a new DB, cache or queue host I update env.php (by hand or with setup:config:set) and run bin/magento cache:flush. A credential change alone does not need setup:upgrade. For the crypt key use bin/magento encryption:key:change, which also re-encrypts the stored values that used the old key. For the mode use bin/magento deploy:mode:set production rather than editing MAGE_MODE by hand. Then reload PHP-FPM, because opcache may still serve the old file.

When to use

Four scenarios where env.php is the file you actually touch

Most days you never open env.php. These four moments are the exception, and each one needs care.

  • First install, audit the freshly-generated env.php

    Right after setup:install I open env.php and check three things. The DB user is not root but a dedicated user with rights only on the Magento database. The crypt.key is a long random string and not copied from another environment. And backend.frontName is not admin but a random slug, so bots guessing admin URLs do not find the login page. All three take minutes to fix on day one and much longer once the store is live.

  • After migrating hosting

    When I move a store to a new server, env.php is where most of the work happens. I update db.connection.default.host, username, password and dbname, point cache.frontend.*.backend_options.server at the new Redis and queue.amqp.host at the new RabbitMQ, then run bin/magento cache:flush and reload PHP-FPM. config.php comes along with git. The crypt.key has to be copied from the old env.php. Without it, every encrypted value in the database (payment credentials in config, integration secrets, saved tokens) can no longer be decrypted.

  • Hardening a production install

    A lot of production hardening happens in env.php. Change backend.frontName from admin to a random slug. Set session.save to redis (file sessions don’t scale and leak to disk). Configure cache.frontend.default.backend to Magento\Framework\Cache\Backend\Redis with a dedicated DB index. Set lock.provider to db so cron locks survive across web nodes. Set MAGE_MODE to production. File permissions on env.php should be 440 owned by the deploy user, readable only by deploy + php-fpm groups.

  • Disaster recovery

    env.php + database dump + media folder are the three artefacts you need to fully restore a Magento store from cold. Lose env.php and you lose the crypt.key, which means every saved payment token, every integration secret, every encrypted DB column becomes unrecoverable, you’d need to re-issue every API key, force every customer to re-add their card, and re-link every third-party integration. Back up env.php with every DB dump, encrypted and stored separately from it, and test a full restore on a fresh server from time to time.

Common mistakes

Three env.php mistakes that turn into incidents

Most env.php problems I have had to clean up started with one of these three. Check your repo, your backups and your deploy script for them.

  • Committing env.php to source control

    The most common, and most damaging, mistake. Committing env.php leaks the DB password, the crypt.key, the admin backend.frontName, and the queue / cache credentials into git history. Even on a private repo this is a breach: every contractor, every former dev, every CI runner, and every GitHub OAuth app with repo access now has production credentials in their git cache. If it happens, treat it as a confirmed breach: rotate the DB password, run encryption:key:change, rename backend.frontName, rotate every payment-gateway API key referenced in the DB, and rewrite git history to scrub the file (and assume someone already cloned).

  • Backing up the database without backing up env.php

    Your nightly mysqldump is only half a backup. Magento encrypts payment tokens, third-party integration credentials, OAuth secrets, and a handful of other sensitive DB columns using the crypt.key from env.php. Restore the DB dump onto a fresh box without the matching env.php and those columns become unreadable garbage, the store boots, but every saved card, every Stripe customer reference, every integration breaks. ALWAYS back up env.php alongside the DB dump, store them in separate encrypted vaults, and document the crypt.key rotation history so a restore from 6 months ago finds the right key.

  • Editing env.php on production without reloading PHP-FPM

    With opcache set not to check file timestamps (common on production), PHP-FPM workers keep serving the cached env.php after you edit it. So a change to cache.frontend.*, session.save or db.connection.* may only reach some workers. Symptoms: half your requests use the new Redis host, the other half use the old one; sessions get split-brained; users get logged out at random. So after every env.php edit I reload PHP-FPM (for example systemctl reload php8.3-fpm, the service name depends on the server) and then run bin/magento cache:flush.

FAQ

Magento env.php, frequently asked questions

  • Can I store env.php in source control?
    No, env.php contains the DB password, the crypt-key, queue credentials, and the admin frontname. Committing it is treated as a confirmed credentials breach by every Magento agency I know. The standard workaround is to track an env.php.example file in the repo with placeholder values (e.g. DB_PASSWORD_PLACEHOLDER) so other developers can see the expected shape, then inject the real env.php at deploy time from a secrets manager (AWS Secrets Manager, HashiCorp Vault, Cloudflare Secrets, or sealed Kubernetes secrets). On Adobe Commerce Cloud, Adobe handles this automatically via environment variables. On self-hosted, your CI/CD pipeline writes env.php just before bin/magento setup:upgrade runs.
  • What is the difference between env.php and config.php?
    env.php is environment-specific and contains secrets: DB host / user / password, crypt-key, admin frontname, Redis / queue creds, MAGE_MODE, install date. It is gitignored by default. config.php is shared across environments and contains non-sensitive structural config: the enabled-modules array, theme registrations, store / website / view scopes, payment-method enable flags (not credentials), and shipping-method enable flags. config.php IS tracked in git so the same modules and themes are enabled across dev / staging / prod. Together env.php + config.php = the full Magento configuration. The split is deliberate: config travels via git, secrets travel via secrets-manager.
  • How do I rotate the DB password in env.php?
    Edit db.connection.default.password in env.php on every web / app node, then reload PHP-FPM (systemctl reload php-fpm) and flush the Magento cache (bin/magento cache:flush). That’s the entire process, there is no Magento CLI command for DB credential rotation, it’s just a file edit. The order matters: update the DB user’s password in MySQL first, then update env.php on every node within seconds (so the old workers can’t reach MySQL with the stale password), then reload PHP-FPM to flush the opcache-cached env.php. For zero-downtime rotation across many nodes, grant the new password as a second auth method temporarily, rotate the file on each node, then drop the old password from MySQL.
  • Where does Adobe Commerce Cloud store env.php?
    Adobe Commerce Cloud (the managed PaaS) does not store env.php as a file in the project at all, instead, the platform injects env.php contents at container build / start time from encrypted environment variables. You configure DB / Redis / queue endpoints via the project YAML files (.magento.app.yaml, .magento/services.yaml) and via environment-scoped variables in the Adobe Cloud dashboard. The crypt-key is managed automatically by Adobe per environment. When a container boots, Adobe’s ECE-Tools build:generate step writes the templated env.php into the container. This is why Adobe Commerce Cloud env.php questions usually resolve to YAML config questions, not file edits.
  • Can env.php live outside app/etc/?
    No, Magento’s bootstrap path is hard-coded. app/bootstrap.php requires app/etc/env.php via a relative path resolved against BP (the Magento base path constant). There is no configuration knob to relocate it. If you need to keep env.php on a separate volume for security reasons, the standard pattern is to mount the secret volume at /srv/secrets/env.php on the host, then symlink app/etc/env.php -> /srv/secrets/env.php in the deploy step. Magento doesn’t care that it’s a symlink as long as the path resolves and the file is readable. Adobe Commerce Cloud does effectively the same thing via container layer mounts.
  • How do I disable opcache for env.php specifically?
    You don’t need to, env.php is a normal PHP file and opcache handles it correctly. If you’re seeing stale env.php after an edit on production, the issue is NOT opcache validation timestamps (those default to 2 seconds), it’s PHP-FPM workers holding the OLD env.php contents in memory from when they first booted. Magento’s bootstrap reads env.php once per worker process via require, and the parsed array is held in the worker’s memory for the life of that worker (typically 500-1000 requests). The fix is to reload PHP-FPM (systemctl reload php-fpm) after editing env.php, which gracefully recycles all workers. Disabling opcache slows the whole site down by 2-4x and won’t fix the stale-config problem.
env.php audit

Want a security audit of your Magento env.php?

Send me read-only SSH access, I will audit your env.php file permissions, crypt-key rotation history, secrets-manager wiring, backup coverage, and gitignore hygiene, then reply with a written hardening plan, fixed-price quote, and earliest start date. 24-business-hour turnaround.

Kishan Savaliya Online 10 AM to 7 PM IST Chat on WhatsApp