configurator-ng- The next generation of configuration management

MaintainerLeon P Smith <>
Safe HaskellNone




A simple (yet powerful) library for working with configuration files.

Note that while the Data.Configurator.Parser and Data.Configurator.FromValue should be quite stable at this point, this module is likely to be subjected to significant breaking changes in subsequent versions of configurator-ng. So please do file an issue if you have any opinions or especially needs with regards to configuration (re)loading, change notifications, etc.


Configuration file format

A configuration file consists of a series of directives and comments, encoded in UTF-8. A comment begins with a "#" character, and continues to the end of a line.

Files and directives are processed from first to last, top to bottom.

Binding a name to a value

A binding associates a name with a value.

 my_string = "hi mom! \u2603"
 your-int-33 = 33
 his_bool = on
 HerList = [1, "foo", off]

A name must begin with a Unicode letter, which is followed by zero or more of a Unicode alphanumeric code point, hyphen "-", or underscore "_".

Bindings are created or overwritten in the order in which they are encountered. It is legitimate for a name to be bound multiple times, in which case the last value wins.

 a = 1
 a = true
 # value of a is now true, not 1

Value types

The configuration file format supports the following data types:

  • Booleans, represented as on or off, true or false. These are case sensitive, so do not try to use True instead of true!
  • Decimal fractions, expressed in scientific notation.
  • Unicode strings, represented as text (possibly containing escape sequences) surrounded by double quotes.
  • Heterogeneous lists of values, represented as an opening square bracket "[", followed by a series of comma-separated values, ending with a closing square bracket "]".

The following escape sequences are recognised in a text string:

  • \n - newline
  • \r - carriage return
  • \t - horizontal tab
  • \\ - backslash
  • \" - double quote
  • \uxxxx - Unicode character from the basic multilingual plane, encoded as four hexadecimal digits
  • \uxxxx\uxxxx - Unicode character from an astral plane, as two hexadecimal-encoded UTF-16 surrogates

String interpolation

Strings support interpolation, so that you can dynamically construct a string based on data in your configuration or the OS environment.

If a string value contains the special sequence "$(foo)" (for any name foo), then the name foo will be looked up in the configuration data and its value substituted. If that name cannot be found, it will be looked up in the OS environment.

For security reasons, it is an error for a string interpolation fragment to contain a name that cannot be found in either the current configuration or the environment.

To represent a single literal "$" character in a string, double it: "$$".

Grouping directives

It is possible to group a number of directives together under a single prefix:

   a = 1

   # groups support nesting
   nested {
     b = "yay!"

The name of a group is used as a prefix for the items in the group. For instance, the value of "a" above can be retrieved using lookup by supplying the name "my-group.a", and "b" will be named "my-group.nested.b".

Importing files

To import the contents of another configuration file, use the import directive.

 import "$(HOME)/etc/myapp.cfg"

Absolute paths are imported as is. Relative paths are resolved with respect to the file they are imported from. It is an error for an import directive to name a file that does not exist, cannot be read, or contains errors.

If an import appears inside a group, the group's naming prefix will be applied to all of the names imported from the given configuration file.

Supposing we have a file named "foo.cfg":

 bar = 1

And another file that imports it into a group:

 hi {
   import "foo.cfg"

This will result in a value named "".


data Worth a Source




worth :: a


worth :: a


Loading configuration data



:: AutoConfig

Directions for when to reload and how to handle errors.

-> [Worth FilePath]

Configuration files to load.

-> IO (ConfigCache, ThreadId) 

Load a ConfigCache from the given FilePaths, and start a reload thread.

At intervals, a thread checks for modifications to both the original files and any files they refer to in import directives, and reloads the ConfigCache if any files have been modified.

If the initial attempt to load the configuration files fails, an exception is thrown. If the initial load succeeds, but a subsequent attempt fails, the onError handler is invoked.

File names have any environment variables expanded prior to the first time they are opened, so you can specify a file name such as "$(HOME)/myapp.cfg".

autoConfig :: AutoConfigSource

Defaults for automatic Config reloading when using autoReload. The interval is one second, while the onError action ignores its argument and does nothing.

Notification of configuration changes

To more efficiently support an application's need to dynamically reconfigure, a subsystem may ask to be notified when a configuration property is changed as a result of a reload, using the subscribe action.

prefix :: Text -> PatternSource

A pattern that matches on a prefix of a property name. Given "foo", this will match "", but not "foo" or "foobar".

exact :: Text -> PatternSource

A pattern that must match exactly.

subscribe :: ConfigCache -> Pattern -> ChangeHandler -> IO ()Source

Subscribe for notifications. The given action will be invoked when any change occurs to a configuration property matching the supplied pattern.

Low-level loading functions

load :: [Worth FilePath] -> IO ConfigCacheSource

Create a ConfigCache from the contents of the named files. Throws an exception on error, such as if files do not exist or contain errors.

File names have any environment variables expanded prior to the first time they are opened, so you can specify a file name such as "$(HOME)/myapp.cfg".

loadGroups :: [(Name, Worth FilePath)] -> IO ConfigCacheSource

Create a ConfigCache from the contents of the named files, placing them into named prefixes. If a prefix is non-empty, it should end in a dot.

reload :: ConfigCache -> IO ()Source

Forcibly reload a ConfigCache. Throws an exception on error, such as if files no longer exist or contain errors.

addToConfig :: [Worth FilePath] -> ConfigCache -> IO ()Source

Add additional files to a ConfigCache, causing it to be reloaded to add their contents.

addGroupsToConfig :: [(Name, Worth FilePath)] -> ConfigCache -> IO ()Source

Add additional files to named groups in a ConfigCache, causing it to be reloaded to add their contents. If the prefixes are non-empty, they should end in dots.

Helper functions

display :: ConfigCache -> IO ()Source

Perform a simple dump of a ConfigCache to stdout.

readConfig :: ConfigCache -> IO ConfigSource

Read the current configuration stored in the cache.