Firstly, great question!
-E switch only shows the environment at the time the process is launched, so any changes would be invisible to this method. Thus if the data is loaded into the environment after launching the process, then it will not be discoverable through this method. However, this is likely not a feasible strategy, IMHO, for reasons discussed below.
I agree with the Twelve Factor that the environment variable trick is the way to go. However, there are some important caveats that are not made clear in the Twelve Factor guide, as well as some practical considerations and techniques to get there.
Firstly, environment variables are volatile (non-persistent). All data is lost on reboot. This means that if the configuration isn't persisted somewhere, it will be non- recoverable in the event of a server reboot, unless it is in memory in
/dev/brain0 of the sys-admin (not a gamble I would make with 128-bit keys). If that is the server's private key(s), you have at best a major and at worst a catastrophic problem on your hands (your CA may need to re-issue the keys). This makes a good case that the config must be written down somewhere, and I don't think many people would dispute that. Where/how to store it however, is what is important.
The Twelve Factor App addresses this though not in a straight-forward way. "A litmus test for whether an app has all config correctly factored out of the code is whether the codebase could be made open source at any moment, without compromising any credentials." So we know that we have to write it down somewhere, and that we can't put the config in the codebase. "Another approach to config is the use of config files which are not checked into revision control." This is what I would do.
The Twelve Factor App says, "it’s easy to mistakenly check in a config file to the repo." To counter this, production config (like private keys) should be different than development and test config. They should also be strictly controlled. Some version control systems like
git have blacklists (like a
.gitignore file) that prevent checking in certain files. These should also be used. "There is a tendency for config files to be scattered about in different places and different formats, making it hard to see and manage all the config in one place. Further, these formats tend to be language- or framework-specific." This is countered by simply defining the "environment variables" in the config file. This can then be loaded into the environment at startup by the server.
What I would do:
- Store the production server config info (like the server's private key(s)) in a separate repo that is different and distinct from the main repo
- Protect the production config file(s) very well. Only a few people need to access it, not every developer on the team. QA/DevOps/Sys-admins/etc for example. Treat this file like the keys to the server, because they are probably in it. Development and test environments should have different credentials and keys than production. These can then be stored more loosely
- Have the server's init routine load the config file info into the live environment variables
- Have the app load the config info it needs from the environment variables at runtime