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.
- bin/magento setup:install generates env.php 01
- Magento boots and reads env.php BEFORE any DB connection 02
- config.php commits to git, env.php does not 03
- Multi-host clusters coordinate via env.php 04
- Updating env.php on a running site 05
Most common mistake Committing env.php to source control
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.
-
01
bin/magento setup:installgenerates env.phpsetup:installtakes the DB host, name, user and password, the admin frontName and the base URL as options, and writes them intoapp/etc/env.phpas a plain PHPreturn [ ... ]array, along with a new randomcrypt.key. The same array getsinstall.date, thesession.savebackend and thecache_typeson/off map. There is no admin screen for it. To change values later I usebin/magento setup:config:set(for example--session-save=redis) or edit the file by hand, never a second setup:install. -
02
Magento boots and reads env.php BEFORE any DB connection
Magento’s deployment config reader loads
app/etc/env.phpandconfig.phpearly 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). -
03
config.php commits to git, env.php does not
Magento’s default
.gitignorealready listsapp/etc/env.php.app/etc/config.php, with the enabled-modules array and any settings you dumped withbin/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. -
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.keyandMAGE_MODEmust 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. -
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 runbin/magento cache:flush. A credential change alone does not need setup:upgrade. For the crypt key usebin/magento encryption:key:change, which also re-encrypts the stored values that used the old key. For the mode usebin/magento deploy:mode:set productionrather than editingMAGE_MODEby hand. Then reload PHP-FPM, because opcache may still serve the old file.
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:installI open env.php and check three things. The DB user is notrootbut a dedicated user with rights only on the Magento database. Thecrypt.keyis a long random string and not copied from another environment. Andbackend.frontNameis notadminbut 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,passwordanddbname, pointcache.frontend.*.backend_options.serverat the new Redis andqueue.amqp.hostat the new RabbitMQ, then runbin/magento cache:flushand reload PHP-FPM. config.php comes along with git. Thecrypt.keyhas 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.frontNamefromadminto a random slug. Setsession.savetoredis(file sessions don’t scale and leak to disk). Configurecache.frontend.default.backendtoMagento\Framework\Cache\Backend\Rediswith a dedicated DB index. Setlock.providertodbso cron locks survive across web nodes. SetMAGE_MODEtoproduction. File permissions on env.php should be440owned 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.
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 adminbackend.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, runencryption:key:change, renamebackend.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
mysqldumpis only half a backup. Magento encrypts payment tokens, third-party integration credentials, OAuth secrets, and a handful of other sensitive DB columns using thecrypt.keyfrom 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 thecrypt.keyrotation 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.saveordb.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 examplesystemctl reload php8.3-fpm, the service name depends on the server) and then runbin/magento cache:flush.
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 anenv.php.examplefile 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 beforebin/magento setup:upgraderuns. -
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?
Editdb.connection.default.passwordin 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-Toolsbuild:generatestep 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.phprequiresapp/etc/env.phpvia a relative path resolved againstBP(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.phpon the host, then symlinkapp/etc/env.php -> /srv/secrets/env.phpin 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 viarequire, 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.
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.