DynConf: My Approach to Configuration Files 2018-06-24

Today marks the first release of DynConf which I’ve developed in the past few weeks. The first paragraph from its README gives a high-level overview:

DynConf is a small program to apply recipes to configuration files. This can be used to dynamically alter a configuration without diverging from the defaults: When there is an update you simply re-run DynConf to produce a new configuration file. In this case the recipes describe which lines should be deleted, replaced, or appended.

It get’s to the heart of my requirement out of which DynConf was born: I don’t like diverging configuration files where you have to align your modifications to new default values of a new version. I use Arch Linux, which is a rolling-release distribution, so updates hit my systems pretty regularly. That’s why I developed some custom scripts over time, using sed and friends to modify vanilla configuration files to my needs. However writing and maintaining shell scripts is no fun, so DynConf uses recipes written in YAML (the format is described in the linked README). The synopsis is that you can specify regular expressions which should be enough for most purposes.

My shell scripts already used a “trick” which I ported to DynConf: Some package managers (at least Arch Linux’ pacman and rpm) detect when you modified a configuration file. In that case they put the new version into a file suffixed with .pacnew / .rpmnew. So all DynConf needs to do is to pick up that new version and transform it according to the given recipe. In addition DynConf keeps a .orig version of the configuration file so that subsequent calls are idempotent.

Doing these things in shell scripts has some nasty corner cases: What if something fails / the user kills the script / there is an issue with the filsystem? In the worst case you might end up with a broken configuration file.1 So DynConf commits changes in an atomic fashion:

  1. Create a .orig if there is none (and no .*new either) so that future invocations can work from the same starting point.
  2. Atomically replace the content of the “main” configuration file.
  3. Rename a found .*new file to .orig.

The last step also ensures that the user can compare the new version after an update with the previous version. If you are interested in the details feel free to have a look at the implementation!

Future Changes

I already identified some features that might get implemented for future releases:

  1. Some configuration files use a hierarchical format where a single line might be interpreted differently based on the context. Currently all regular expressions are applied to a single line so these cases cannot be handled (see issue #3).
  2. New configuration files could introduce options that are matched by existing regular expressions. It might be helpful to specify how often a regular expression is expected to be found. This information would allow DynConf to throw an error when such cases are hit (see issue #4).

If you have issues using DynConf or it’s missing a feature please get in touch with me via the GitHub repository. I also welcome contributions, the code is released as open source under the GPLv3.

  1. I never actually ran into this problem. But after thinking about it I figured it might be worth eliminating that possibility from the beginning. 

You do not need to agree with my opinions expressed in this blog post, and I'm fine with different views on certain topics. However, if there is a technical fault please send me a message so that I can correct it!