This is an interesting question you have. In fact, there are two
entirely separate questions disguised as one:
How to version control configuration files (with potentially
How to manage configuration files for different
The general consensus for versioning sensitive data is not to
version it at all. For example, The Twelve-Factor App proposes to
keep all configuration settings in environment variables directly
on the machines your application is running. StackOverflow
2 and related)
suggest having a "template" configuration file which is then edited
by each and every developer locally.
As for managing configuration files for different environments,
things depend. If you're using ASP.NET, there's built-in Web.config
Transformations.aspx), which only works for web
applications. If you're not using ASP.NET but you're still
on .NET, you're effectively out of luck since
SlowCheetah (which is a general-purpose XML Transformer) is not
We've here solved this issue by having a single
.config file which looks like this (note the extra
configuration attribute here and there):
This .config file (which we call
_Web.config or _App.config) is then
transformed (in a Pre-Build Step) into a proper
Web.config or App.config by removing all
the elements with configuration attribute that are not
related to the configuration currently being built. For example,
the "Production" configuration gets its own connection string (that
references environment variables) and does not have the
<trace /> element at all. This solution is not
ideal, but is far more elegant than having
Web.Debug/Release/QA.config files with wonky transform
If you're interested, I can elaborate further on this.
Thanks very much for your thoughtful response and the included links.
Yes, I believe you very succinctly captured the essence of the question and I agree, it is two fold. The first question was one that I not sufficiently clued into in my thinking. I have had a number of discussions with colleagues over the years regarding the use of config and ini files with clear text in them and oddly enough no one had ever introduced the idea of env variables. I like that, it seems to add another layer of obfuscation for the critical data. Of course, if the server is hacked at a low enough level, the clever hacker could gain the info, but they'd have to know to look in the first place. Most of work has been for intranet applications behind substantial firewalls so many times people concluded that the firewall is what protects you. That and proper security settings on files and folders. The basic thought being that a hacker would have to violate the firewalls first, then find the internal servers, etc... All of this of course goes out the window when out in the real world (DMZ.)
I would be grateful if you would elaborate some more on your Pre-Build step(s).
I'm assuming and guessing at two things: First, that your web.config files are substantially more complex than seen above. You're just illustrating the point about using the additional "configuration" attribute to be able to identify the server for which this build is intended.
My second guess then is that you have a possibly more elaborate Pre-Build engine (say a Python script or some C# parser?) that then strips out all lines that should not be left in the config file for the intended server build.
When you are stripping the unneeded configuration lines, do you also strip out the configuration attrib information? Or do you just leave it in place since it would appear to do no harm?
I'd be grateful for further elaboration and even sample code for the stripping parser.
I'm a lazy programmer and steal what code I can. :-)
When it comes to storing settings environment variables, a
proper sever automation is key: you really wouldn't want to have
these settings unversioned and manage them manually. Linux world
has Puppet, Chef, Ansible and possibly others.
These tools allow you to declaratively specify the state of your
entire sever fleet and then bring all the machines up-to-date.
Windows, unfortunately, has very limited (if any) support from
these three tools, and Microsoft is kind of offering
PowerShell DSC, but as any server-level "enterprise-grade" tool
from Microsoft, it's a disaster.
What it does is it loops over each and every tag in an XML; if
the tag does not have a configuration attribute, just
copies it over to "output"; if it does, it checks if this attribute
contains a string passed into this XSLT file from the outside via
Configuration parameter and either copies the tag
(sans configuration) attribute, or leaves it out.
Now, you'll need a command-line tool to apply XSLT
transformation to an arbitrary XML file. I use
Finally, just glue these pieces together in a Pre-Build
(Note that both nxslt2.exe and
configuration-transformer.xslt are kept inside the
repository in a top-level /tools directory).
This command basically says: "Hey, nxslt2! Transform
as a transformation passing it the Configuration
parameter and write output to
That's how _Web.config with those "magical"
configuration attributes gets transformed into proper
.NET-compatible Web.config. In fact, you can use this
approach with any XML and any XSLT file -- be it
App.config or anything else, really.
Thank you very much for this information.
It's very helpful.
I read through the 12-Factor website and while their concepts make a lot of sense as best practices, it's, as you point out, not so simply done in the Windows world.
Look forward to your Opsflow package. I believe we would use a package like that almost immediately.
I have looked at Vagrant and it appears to probably be a useful tool once we get past some initial issues (below.)
As best I can tell from only reading, Vagrant gives you the ability to create Virtual environments so that you can then have everyone working under the same environment. This would certainly help with some of the issues we're fighting with given our current systems.
The main issue we are currently struggling with is that there was not a test server in place within our organization. We're implementing one but in doing so finding out that the development and production environments were not kept in synch. Not even at the Framework level. It appears the source was copied from one place to another and then recompiled to match the environment. You can imagine the issues this can lead to...
Your information, examples and help are very useful for us right now.
We should be able to implement them to help get things cleaned up.