I'm writing a thesis about twelve-factor apps and I wonder if you can help me out here.
The third factor of twelve-factor apps states: Store config in the environment. (https://12factor.net/config). According to the page all configuration which might vary between deploys should be extracted to environment variables.
I am wondering how to apply during development when creating e.g. a Rails app. Currently I see two ways which are both not perfect in my opinion.
Is my view correct? I wonder if there are any best practices to tackle this problem.
Thanks!
Basically, Environment Variables are accessible based on your context. The user running the process, the system, the application, all can modify the set of variables you can access at any given time/place in your app. So, where you put them depends on the needs of your app - do you need to isolate different apps on the same server? Do you need to effectively manage dozens of apps? Do you need to provision and populate new server Environments? Etc.
As for options here is what I have experienced:
The .*rc
files are fine for this kind of config, even though you may not like the flavor of it. These make them available to the user whose Environment runs the files, so it might not work for you if your login user is ubuntu
but your services run as other users, like www-data
or httpd
.
Dotenv is also fine, because it injects the variables into the actual ENV when it runs. Not perfect, but still acceptable imho (assuming you never commit those variables to vc, as you point out). This makes them available to the single application using Dotenv.
Other ways are (for web apps) to put them in the Apache or Nginx (or other web server) configuration. They can be put into the Environment at the virtualhost definition layer, or at the service/daemon configuration layer (though Nginx I think doesn't support vhost Environments). This makes the variables available to any apps started by these services. This is common for a website or web app.
You can also set the Environment server-wide: /etc/profile
or /etc/environment
. This makes them available to any service on the entire system.
Beyond this (multi-server apps, complex hosting, etc) is more a question of Ops - managing multiple configuration sets is still relevant to the 12-Factor App, but won't have a simple answer :)
You don't have to decide right away! Using Environment Variables is a very flexible approach! You can use DotEnv on your Development Macbook, put them in Apache on your Staging environment, use .bashrc
for your Test/Integration server, and put them in /etc/environment
on your custom-built Lighttpd Production server. Having your app expect your config to be in ENV means your app doesn't have to care about how it got there!!!