When Symfony 4.0 was released, the .env
file was introduced as a way to set
environment variables. The core of the system has not changed. But, thanks to
recent updates to some core Symfony recipes, .env
loading has some new features
that can be enjoyed on any Symfony Flex project!
If you have an existing Symfony app (started before today), your app does not require any changes to keep working. But, if/when you are ready to take advantage of these improvements, you will need to make a few small updates.
What Changed Exactly?
But first, what changed? On a high-level, not much. Here's a summary of the most important changes:
- A) The
.env.dist
file no longer exists. Its contents should be moved to your.env
file (see the next point). - B) The
.env
file is now committed to your repository. It was previously ignored via the.gitignore
file (the updated recipe does not ignore this file). Because this file is committed, it should contain non-sensitive, default values. Basically, the.env.dist
file was moved to.env
. - C) A
.env.local
file can now be created to override environment variables for your machine. This file is ignored in the new.gitignore
. - D) When testing, your
.env
file is now read, making it consistent with all other environments. You can also create a.env.test
file for test-environment overrides.
Point (D) is one of the main motivations behind these changes: it makes setting
and overriding environment variables for your test
environment a delight.
These improvements can be used in any Symfony Flex project (Symfony 3.4 or higher). Changes to the recipes (see below) make it possible to take advantage of the Symfony 4.2 feature - Define env vars per environment - in lower versions.
To take advantage of these, you will need to modify a few files in your existing app.
Updating My Application
Updating your existing application is optional, but just requires modifying a few files. To update, see: DotEnv: Update my Application in the Symfony Docs.
Bonus: --env & --no-debug Console Deprecations Removed
The --env
and --no-debug
were recently deprecated. However, based on
community feedback and work on these new .env
features, the deprecation
has been reverted: the --env
and --no-debug
options will continue to work!
And, the proper .env
files will be loaded. For example, want to create the
schema in your test
environment using a customized DATABASE_URL
in your
.env.test
file? That will work just like you expect:
1
$ php bin/console doctrine:schema:create --env=test
Have any questions? Let us know!
❤️ The Symfony Community
I'm still a bit lost as to the point of these changes, but it seems enough people understand it, so I'll get stuck in as part of upgrading to 4.2! In this example, should
.env.test
be committed? Is there a corresponding.env.test.local
or.env.local.test
? What is the order of precedence?This isn't an improvement I could apply to my project, as we also use docker-compose and a
.env
file to automatically load environment variables handled as secrets that cannot be committed to the repo.There was one big issue that needed to be fixed: the .env file was not loaded in the test environment, which meant that you needed to duplicate all of your env vars in phpunit.xml.dist. That was basically a "bug" that needed to be fixed.
The fix for that was to add the ability for Symfony to load .env.{env} files (e.g. .env.test)... and that's all we really needed. But, several other (less important) features were also added, like the ability to have .env.test.local, and also the decision to move away from the .env.dist file in favor of committing the .env file. That last part was really unrelated to fixing the above "bug", and I think its the part the will be the most difficult - we need to re-teach the purpose of the .env file, and (while it's really nice) this one part doesn't give us any new concrete feature.
To summarize:
And you probably won't need to create any other files. You CAN create other files (e.g. .env.test.local), but I don't think there will be common cases for this. Any files matching
.env.*.local
are ignored in .gitignore.Let me know if you have other questions!
It was I was already doing! Happy to see it in by default.
Will DotEnv check if we're overriding locally the existing (correct) env variable? Will these files be synchronized somehow?
By "existing (correct) env variables" are you referring to "real" env vars that you may have set? If so, that behavior hasn't changed: the DotEnv component (which loads all these .env files) will never override a "real" environment variable that you have set. So, for example, if you are in the "test" environment, Symfony will load .env and .env.test. But, if any of the env vars set in those files already exists as a true environment variable, the value in the file will NOT override the real environment variable value :).
Cheers!
@ryan ok, thank you! :)
Finally! Testing environment was my main issue when I started using .env files and had to do some nasty hacks to solve all the issues.
It's good to see the deprecation being reverted too.
What do I need to update to use the new .env.test? Just symfony/flex? Is it in stable already?
Really good news for the testing environment (which was a real problem when it comes to env variables).
Small question about the production environment, if we can't use env variables (maybe due to a lack of SSH, etc), can a
.env.prod
file can be defined ?As Docker use the .env file, I think you can continue to keep it out of the Git index and keep a .env.dist which is the structure for the .env file, plus, as Symfony use a .env.local file, the content of the .env file isn't really "important" (mainly because you can use both .env.test and .env.local in order to overload the env variables, finally, the .env.local can be used as the only source of truth (without using a .env file for Symfony), this way, you can keep your secrets in the .env file without breaking all your infrastructure).
Check out the details for how to update here: https://symfony.com/doc/current/configuration/dot-env-changes.html#updating-my-application
Basically, you just need to modify a few files to match the changes that were made in the recipes :)
Yep! Except, instead of .env.prod, just create a .env.local on your production machine. .env.prod would also work - but it doesn't make as much sense (e.g. if you, for some reason wanted to execute a console command in the "dev" environment on production, the .env.local would STILL be read, but a .env.prod would not).
In general, if setting real env vars works well with your deployment environment, use those. If they do not, there is no significant disadvantage to creating a .env.local file.
@Ryan Weaver: Thanks for the feedback, I'm gonna check this in my old projects that I move to Sf 4 :)
We utilze bootstrap file injecting dist by default for testing purposes. For e2e tests we run docker-compose with env_file: [.env.dist] so we have full control of what's happening.
New changes are confusing and break current best-practices about .env files
I just tried it and it works well. I now have 3 files .env, .env.local and .env.prod.
Thanks
This post does confuse me a little bit.
Do I need Dotenv in prod? I thought it was for dev only.
When I am in prod and calling a command should I source a file with envvars or using .env.local? What approach is more best practice?
Do I need Dotenv in prod? I thought it was for dev only.
When I am in prod and calling a command should I source a file with envvars or using .env.local? What approach is more best practice?"
In fact, in production (except if you don't have full access to the terminal), you should use env variables (using vhosts or server env), the .env.local is really linked to the development case.
A little repeat answer, but just to make sure it's really clear:
You do not need Dotenv in prod. You can use it if you want to, but it's up to you. If Symfony sees a real APP_ENV environment variable set to "prod", it will not load your .env files.
When you're on prod, you will either choose to: A) Create real environment variables or B) Create a .env.local file with your production-environment env var values
You can choose either setup - whatever works best for you. When you run a command, you don't need to do anything: if you're using real env vars, those will naturally be used. And if you've chosen a .env.local setup (i.e. not setting real environment variables), that file will be loaded like normal. There's nothing special about running commands.
Cheers!
Thanks Loulier Guillaume and Ryan Weaver for making it clear!
Some strange change. It's not much use, but it's confusing.
I have made the changes as advised in https://symfony.com/doc/current/configuration/dot-env-changes.html#updating-my-application
I have symfony/dotenv v4.1.4 symfony/framework-bundle v4.1.9
I have
.env .env.local .env.test
If I try and run this command
APP_ENV=dev php bin/console doctrine:database:create -n
It does not load the .env.local
I also tried
APP_ENV=local php bin/console doctrine:database:create -n
Also the .env.test is not used if I run
APP_ENV=test php bin/console doctrine:database:create -n
However, the following DO clear the caches for the correct environment
APP_ENV=dev bin/console cache:clear APP_ENV=test bin/console cache:clear
I have tried restarting Apache