Laravel Environment Variables 5.3 setup - php

By default, Laravel git ignores the .env file that contains environment settings and configuration.
I would like to have a local .env, and a production .env that CAN be committed to my server so that I don't need to manually create production settings or touch the .env file at all and can use push to deploy techniques.
Anyone got any good solution for this? It seems a strange design decision to make developers always manually create the production settings in a single file, and not make it easy to switch between production and local settings. I was considering using git hooks to rename .production to .env but this seems like overkill, and I want to check that this functionality isn't available out of the box and I've missed it.
Bonus points for explaining why having three files .local.env, .production.env and .env (which switches between the two) files is a bad idea, and one the original team avoided.
I'm using the latest version of Laravel (5.3).

The reasons behind this design are mainly:
Security concerns
Different environments might need different settings
Laravel makes use of the DotEnv PHP library by Vance Lucas to provide the .env functionality, so you can read more about it there as well as in the officiall Laravel docs:
Your .env file should not be committed to your application's source
control, since each developer / server using your application could
require a different environment configuration.
If you are developing with a team, you may wish to continue including
a .env.example file with your application. By putting place-holder
values in the example configuration file, other developers on your
team can clearly see which environment variables are needed to run
your application.
And from DotEnv:
The .env file is generally kept out of version control since it can
contain sensitive API keys and passwords. A separate .env.example file
is created with all the required environment variables defined except
for the sensitive ones, which are either user-supplied for their own
development environments or are communicated elsewhere to project
collaborators. The project collaborators then independently copy the
.env.example file to a local .env and ensure all the settings are
correct for their local environment, filling in the secret keys or
providing their own values when necessary. In this usage, the .env
file should be added to the project's .gitignore file so that it will
never be committed by collaborators. This usage ensures that no
sensitive passwords or API keys will ever be in the version control
history so there is less risk of a security breach, and production
values will never have to be shared with all project collaborators.
In summary, if you're certain that you will deploy to only one system and settings will always be the same, and there is no sensitive data inside the .env (or you're OK with everyone involved seeing it), then you could probably go ahead with your solution.
As a side node: Since you were asking for design decisions specifically, DotEnv was apparently inspired by The Twelve-Factor App, which advocates strict separation of config from code among other factors.

Related

Multiple production environments with multiple configs

For the first time I'm making a new web app in Laravel 7 which is going to be deployed on more than one server. Every server has it's own environment variables.
From my previous experiences in Zend framework, all variables were in one config file under some kind of paragraphs. First, there were variables that are common for all environments. After that, every environment have their own overwritten variables. Specific environment was set in index.php and index.php was not deployed. So it's very easy to use and to constantly deploy changes.
My question is, what is the best solution for this purpose in Laravel. So, I need some kind of basic configuration that can be inherited and possibly overwritten in some parts. If there is no something similar, what do you advise me?
Typically, configuration inheritance is a tricky thing to do. If you do not have complete overview over the configurations used, you can end up like one of the companies that send a push notification to the wrong users.
Laravel is built in a way where the default configuration can be set in the config folder and overridden using the .env file. This is how Laravel is intended to be used, so I suggest doing that.
Or, if you prefer, you can have a folder of .env files and then moving the correct one to the root on deployment.

What are the advantages of storing info on .env files as opposed to .php files?

Considering storing settings information on a .env file, outside the document root folder, as the best practices suggest... What would be the advantages of using .env files as opposed to .php files?
.env files would be parsed by a library and stored on ENV variables.
.php files don't need parsing and will store info on ENV variables.
Thanks!
When developing you will have a set of keys that you configure on your local environment or whichever other enviroment you are developing. These keys (password to databases, email services, etc) you do not wish to share with other developers that work along side you. Neither if you are sharing the code with the world.
.env files where created in order for you to have a working environment without having to share those keys with the world or the rest of your team. They are supposed to be singular to the environment the project is settled.
When you create keys that are going to be used across the project, besides of adding them to your .env file you also should add them to the .env.example which is pushed to the repository. Leave the keys present in there while keeping the values empty for the .env.example so other developers understand what are the required keys for the project to work and what they should add in there while not giving a hint of what your local passwords are.
Also when you are working on local environments you normally use local passwords. A problem arises when you are deploying to a production server where real passwords that contain sensitive information will exist. So you do not want these to exist on your repository and definitely you do not desire these to be permanently stored in your repository (this comes with profession responsibility, specially when you are tagged just as a developer and not a sys admin, in the case where the sysadmin will add the keys once the project is deployed on the production environment).
It is a elegant way to bypass these problems above
In response to your second question in the comments
To be honest you can do it both ways if you end up following what I explained above. The main goal is to keep your variables protected. But you can just refuse to push the php file to repo.
In my opinion on why you should use .env instead of .php goes as follow:
1. with .env you immediately know it is a environment variable holder. .php regardless of how you name it is not as direct in understanding;
2. .env will be an ocult file when listing a directory;
3. It is easier, when working whit other developers in the same repo, to quickly identify and understand something should not be pushed on that commit (think even on the case of adding extra layer of security on a hook to make sure .env is not pushed on the commit. It is harder and you have to hardcode this for .php files);
I guess in your argument level these will be a few of the Go Tos when deciding between files. I would leave the .php files to be precisely that, php programming files instead of configs;
Now if you ask me between .env or .yml etc, I would say go with the one you are familiar/feel comfortable. At the end you avoided the .php the same :)
PS: Also, if you think on how you will reference them within the code whenever you need one of the environment variables it jumps way quicker to the eye when you see something like:
getenv('YOUR_VARIABLE_HERE');
.env files were created to make development more easy, and is not only used in PHP, as example in ruby you can use .env files https://github.com/bkeepers/dotenv.
If we take a look at the twelve factor principles. The following is stated:
The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.
https://12factor.net/config
So dotenv is just a tool to make this easy for the developers

How to keep CodIgniter application and config in their own in git repos?

Can anybody tell me what kind of workflow should I follow to keep my application source and configuration tracked in Git? I want to keep my config separate from my source is because there is one config for development, another for production enviroment and, and a third for local testing.
It's not unheard of to have a repo just for configuration files (just make sure that git repo does NOT HAVE PUBLIC ACCESS (so, not github unless you have private repos enabled). You end up with a repo for code, and a repo for configuration files, sometimes maintained by a different team (say, the deployment team).
The problem you have is that as far as I'm aware, git doesn't particularly like having multiple repos at the same level.
I don't know anything about CI, but I think it stores its configuration files in application/config.
Two options I can think of:
You can convert all application/config to a git repo and gitignore that folder from the main development repo.
If converting the whole folder into a repo is not feasible (say, some of the configuration files actually belong to the application repo), maintain a separate repo folder somewhere else in the system and symlink your necessary configuration files to application/config (and gitignore those symlinks in your code repo)
There is no need to use separate Git repositories. CodeIgniter supports the idea of environments:
Developers often desire different system behavior depending on whether an application is running in a development or production environment. For example, verbose error output is something that would be useful while developing an application, but it may also pose a security issue when "live".
The ENVIRONMENT Constant
By default, CodeIgniter comes with the environment constant set to use the value provided in $_SERVER['CI_ENV'], otherwise defaults to 'development'.
Set the CI_ENV environment variable for each server process to tell CodeIgniter which environment you're on. Depending on your stack this could involve using Apache's SetEnv, a shell export, or other mechanism.
Then you can set up environment-specific configuration files:
To create an environment-specific configuration file, create or copy a configuration file in application/config/{ENVIRONMENT}/{FILENAME}.php
For example, to create a production-only config.php, you would:
Create the directory application/config/production/
Copy your existing config.php into the above directory
Edit application/config/production/config.php so it contains your production settings
When you set the ENVIRONMENT constant to ‘production’, the settings for your new production-only config.php will be loaded.
Additionally, you may want to load certain settings directly from the environment, as described by the The Twelve-Factor App. (This isn't something that I've seen people do with CodeIgniter before, but it's a useful idea in general.)
For example, it might make sense to keep API keys or database connection information out of your config files, or to leave development-friendly values in your config files and override them with values loaded from environment variables.
An answer from a similar question will help you, it is answer by SO user #dwilkins.
Mr dwikins answer is simple, clear and effective. He suggest gitignore any conf you don't want, but remember to create "conf.sample" sample file.
Mr #alex-stuckey comment to add README file to guide other team member to use the "sample" file.
The following workflow was used back when i was a system administrator and we made scripts that depended on a config preset.
Basically, the main script was always the same, and the script's actions would depend on a config file that would hang from the master branch as so:
Master
|----Script.py
|----config_template.cfg
From Master we would take a branch that looked like so
Mimulation_machine
|----Script.py
|----simulation.cfg-------------->this was the modified config file
The workflow was to switch to master and create a new branch, that would eventually hold the configuration files. It is important that the branches would never merge back to master though. This may not be the best answer nor the most correct but it worked, and allowed us to switch to different configurations with a simple checkout.
Mind you that is an oversimplified verion of what we really had going on, we had a complex structure made out of gitignores and so.

How to better setup production env settings for a Laravel project?

As stated in the documentation, Laravel 5 uses a cool system called DotEnv. It enables us to configure all sorts of environment variables which will be available inside the project. As it may contain keys, it should be ignored in the source code.
Also, as its name is default, each machine/developer should have its own .env file.
Here comes the trouble: first, this is a private project. So I don't really mind stashing keys in the repository. Second, from other frameworks (Symfony? Yii?), I'm used to having separate settings for prod/stg/dev environments. But as the file is unique, this is not possible. Finally, I didn't want to mess with the production machine.
What's the best way to set those things up?
It's typical to exclude the .env file from your repository using a .gitignore file so that they may be configured differently for different environments.
You can create multiple .env files and manually upload them to your staging/testing/production environments. You would only need to do this once and change your settings depending on your environment.
Once in place, future deployments from your repository will not deploy your .env files and your environments will have separate configurations.
Years passed and after some more experience, I can still say both approaches (ignored and non-ignored) env files have their good points.
The best approach on Laravel, for private projects, is to keep the shared keys in .env.example, together with sane defaults (such as APP_ENV=prod or APP_DEBUG=false) and leave to the developer installing the project the task to configure some of those variables, and those that are empty (i.e. logging channels or personal keys).

Production, development, staging configs in ZF2?

I've read several tutorial on the subject, but still don't completely get what's expected from the developer wanting to make ZF2 app environment aware:
http://blog.evan.pro/environment-specific-configuration-in-zend-framework-2
http://www.spiffyjr.me/2012/06/17/how-does-configuration-work-in-zf2/comment-page-1/
ZF2 s not aware of environment concept by design - it's left to a developer to implement. I'm not entirely clear on how it's supposed to be done...
Reading through Evan's post it seems like there are 2 mechanism - and preferred one is not to use APPLICATION_ENV constant, just .local, .global files?
How should that work? Could someone describe a process they go though to make ZF2 environment aware? And what you do when code is to be pushed to different environment?
It seems like the idea is right now to have for ex: module1.local.php.dist-testing, module1.local.php.dist-production, module1.local.php.dist-development and when code is moved to different environment the idea is that these should be copy-renamed for that environment and passwords filled in manually? Am I correct?
The idea is that you provide some sensible default configuration with your application, but you do not store anything for a concrete environment with your code, nor in your version control system.
If you have for example two servers, one for production, one for development, you provide only the configuration details for one single environment in such a .local file. This way, your development server cannot know e.g. the master password for the production database. So it cannot accidentally happen that you get a new development server, and somebody forgets to set APPLICATION_ENV, and you start developing and mess up your production database, because the application knew the passwords.
Or the other way around, a new production server cannot accidentally access the development database.
So your application is aware of the environment automatically by reading the file that is present - and there is only one file per environment present that has all the details.
This puts the burden of ensuring that the correct file is present to the administrator - or the puppet script that configures everything. But the environment specific configuration will not be deployed within the application.

Categories