Twelve-Factor Apps: ways to stay align with the config guideline
Asked Answered
R

1

4

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.

  • Store environment variables in a file like .bashrc or .zshrc. I don't have a good idea on how to manage a test and development environment using this approach since both need a specific configuration using the same environment variables. Also when working on multiple projects this will clutter the shell with variables but it seems to be compliant with the twelve-factor app methodology.
  • use a tool like https://github.com/bkeepers/dotenv which uses a file which is part of the project to store the configuration and is thereby not so much different from secrets.yml or database.yml which the Rails framework already offers and which is not perfectly compliant to the twelve-factor app idea (can still be accidentally checked into the codebase and is mostly language-agnostic)

Is my view correct? I wonder if there are any best practices to tackle this problem.

Thanks!

Ridglea answered 17/12, 2016 at 20:49 Comment(4)
Check out the figaro gem. It's exactly for this.Colvin
Still the figaro gem is language agnostic. It works with focus on rails.Ridglea
@Ridglea is your thesis available somewhere?Glidebomb
@Glidebomb Yes here: github.com/bakku/bachelors-thesisRidglea
M
2

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 :)

Here is the cool thing though:

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!!!

Martelli answered 21/1, 2017 at 5:9 Comment(4)
@Ridglea if you do decide on "one answer to rule them all" maybe you could take a look at my question about 12-Factor Configs: #21247524Martelli
I think a good way to manage the environment is also by using dockerRidglea
Yeah docker looks nice - but you still have to put the variables somewhere. Looks like docker uses .env files and even lets you nest them: docs.docker.com/compose/environment-variables :)Martelli
Nice Q&A! Upvoted. One minor nitpick on the last sentence: if you choose to use dotenv, your app would be forced to "care how it got there", in a sense that the app would need to pull in a dotenv dependency. :-)Cheyennecheyne

© 2022 - 2024 — McMap. All rights reserved.