YAML-powered configuration management for Erlang
Pull request Compare This branch is 19 commits ahead of Spawnfest2012:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


  ____   _  ____    __  __  ____    ______
 |    \ | ||    \  |  |/ / |    \  |___   |
 |     \| ||     \ |     \ |     \  .-`.-`

       making sysops happier one at a time!

Is it any good? Build Status

Yes. And very useful!

Why do I need it?

Let's admit it, configuring Erlang applications is a pain. Not only because configuration files are usually just a bunch of Erlang terms, which are hard to both read and modify for mere humans, but also because, in a lot of cases, configured values are more complex than the primitives Erlang provides. So, how can nakaz help?

Here're the highlights:

  • YAML human-readable configuration files;
  • extensible typing and validation framework;
  • on-the-fly config reloading
  • ... and more!

Still not convinced? check out our screencast to see nakaz in action!

Is there an example of this library's use?

Of course, here it is: https://github.com/HollyBrolly/nakaz_example

How can I use it?

(hopefuly) the usage of nakaz is pretty straighforward, though you still have to keep in mind two things:

  • nakaz uses YAML as base configuration format;
  • nakaz requires you to structure your YAML config in a special way, which is described bellow.

The basic configuration unit in nakaz is a section, which is represented as a named mapping on the YAML side. Each configured application can have one or more sections, for example:

    conn_type: http

    log: "priv/log.txt"
    severity: debug

Here, example application defines a two sections, named log_conf and srv_conf. So, as you might have noticed, the expected structure is simple:

  • applications are defined on the top level of the configuration file,
  • with sections, residing on the second level.

"Enough YAML, show me some Erlang code, dude?!"

Configuration path

For flexibility reasons nakaz doesn't allow you to actually read configuration file from the code, instead, it handles reading and parsing internally, and all you have to do is pass path to the configuration file via command line:

$ erl -nakaz path/to/config.yaml

Note: the current implementation doesn't allow using multiple configuration files, but this might change in the future versions.


As we've already mentioned, nakaz represents your application configuration as sections; what we haven't mentioned is that every section will be parsed into a typed Erlang record! Here's an example:

-compile({parse_transform, nakaz_pt}).


-type filename() :: string().

-record(srv_conf, {conn_type :: http | ssl}).
-record(log_conf, {log :: filename(),
                   severity :: debug | info | error}).

%% Application callbacks

-export([start/2, stop/1]).

%% Application callbacks

start(_StartType, _StartArgs) ->
    case ?NAKAZ_ENSURE([#srv_conf{}, #log_conf{}]) of
        ok -> example_sup:start_link();
        {error, Msg} -> io:format(Msg)

stop(_State) ->

What happens here? First thing to notice is {parse_transform, nakaz_pt}, this is required for all the record-related magic to happen. Second, ?NAKAZ_ENSURE macro. As the name suggests, this macro ensures that the configration file actually contains all of the sections, required by your application. Moreover, ?NAKAZ_ENSURE also checks that the values in those sections exactly match the types you've declared in the record specs!

If anything goes wrong, the Msg term will contain an understable description of the error.

Why records?

Probably, the use of records in ?NAKAZ_ENSURE call looks a little supprising, and you might be thinking "wtf is wrong with those crazy russians?!". Here's the deal, forcing arguments to be records we actually make sure that each of them is a valid record and is available in the module scope (which is just what nakaz_pt needs!).

Accessing config sections

Whenever you need to access a specific section from the configuration file, simply call ?NAKAZ_USE passing section name as an argument:

%% IMPORTANT: without this line your module won't be notified of any
%% configuration changes!

init([]) ->
    SrvConf = ?NAKAZ_USE(#srv_conf{}),
    LogConf = ?NAKAZ_USE(#log_conf{}),
    {ok, #state{srv_conf=SrvConf,

Three awesome facts about ?NAKAZ_USE:

  • it only allows using ensured sections, any other sections simply don't exist;
  • the returned section is guaranteed to be 100% valid, because ?NAKAZ_ENSURE already did all the hard work of type checking and validating configuration values;
  • the caller will be notified of section changes, see nakaz_user documentation for details.

Why the name?

This is the dumbest name we could come up with, which roughly translates to mandate from old-Russian.