Better Environment Variable Management in Laravel and Node

I think point 3 of the 12 factor app is one of the most important and easily achievable factors to achieve.

Frameworks like Laravel encourages this behaviour out of the box, with the loading of the .env file and the config directory for the different services the application might do. This file is not committed to the repository as it contains super secret stuff, so a .env.example is provided to assist developers when setting up the application on their local computer or deploying to servers.

However, I feel the process could be improved, especially when adding new environment variables to an existing application, I often find myself running into the following problems:

  • Devs forget to add new variables to .env.example
  • Defaults for variables are hidden inside various config/*.php files
  • Adding new variables to all the environments where the application is deployed

To circumvent some of the above, I created a library called phpdotenv-safe, which would read the .env.example file and create an exception if a variable was not defined in the current environment.

Then I was trying out the new Vue CLI 3 and their approach to env vars. With this approach there are a couple of environment configurations:

  • The checked in .env file and .env.[mode] files
  • The ignored .env.local and .env.[mode].local files

Initially I was sceptical, but as I used this model I realised it solved a number of frustrations I didn’t know existed!

  • Default configuration is now visible in one file
  • New env vars are deployed with the application by default
  • New env vars are rarely forgotten

The first step is to modify your .gitignore file to be like the following:

.̵e̵n̵v̵
.env.local
.env.*.local

With Node applications, this model can be easily replicated, with code like:

require('dotenv').config({ path: '.env.local' })
require('dotenv').config()

With frameworks like Laravel, it gets a little harder, because the framework itself is responsible for loading the variables out of the box, so it takes a little bit of extra work:

In app/Console/Kernel.php and app/Http/Kernel.php add another ‘bootstraper’:

/**
* The bootstrap classes for the application
* @var array
*/
protected $bootstrappers = [
\App\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
...
];

Then create the following file at App\Bootstrap\LoadEnvironmentVariables.php

I did propose this model to Taylor Otwell, but sadly he declined it.

Let me know what you think!

Solutions Architect. Technical Lead. Full-stack Developer. http://craigmorris.io

Solutions Architect. Technical Lead. Full-stack Developer. http://craigmorris.io