Cfengene3 on Debian Squeeze for local management

Dialling the nerd factor up to 11, I’ve decided to store configuration for my VPS server in git and manage it with Cfengine3. Joking aside, this is a sound decision: having the VCS repo makes backups simple and trustworthy, and configurationĀ managementĀ motivates me to keep on using that repository.

On Debian Squeeze it’s a simple case of apt-get install cfengine3, with the caveat of this packaging bug meaning I hacked /etc/cfengine3 to symlink from /var/lib/cfengine3/inputs.

[Edit: A colleague of mine, David, suggests that the package should link cfengine3's masterfiles to /etc, and I'm inclined to agree.]

Anyone familiar with Cfengine2 will have a good head start on the Cfengine3 configuration, however it’s still a bit of a learning curve (but we know complex problems rarely have simple solutions). The first file read is which can include other files (“inputs“, in any order), and lists the promise bundles and their order of execution:

body common control {
    bundlesequence  => {

    inputs => {

The file is simply a bunch of macros or templates. For example, the built-in copy_from command is augmented with some sane defaults and named local_copy:

body copy_from local_copy(from) {
    source  => "$(from)";
    compare => "digest";
    copy_backup => false;

This is then used in my file to install some cron jobs:

bundle agent main {
        "repo" string => "/path/to/git/repo";

            handle => "cron_files",
            comment => "copy crontab files to /etc/cron.d",

            copy_from => local_copy("$(repo)/etc/cron.d"),
            depth_search => recurse("inf"),
            perms => p("root","444");

This is a trivial example, and could be made better. For example all files in the target directory have their permissions changed (via the “p” macro), whereas it makes sense only to set those files we copy, not any already existing.

Hopefully this post shows that Cfengine3 configuration isn’t that hairy, and once the principles are installed in your head it’s a case of browsing the reference manual and building up promise libraries.


I’d like to note that the Cfengine3 configuration mini-language could be better designed. Some statements are terminated by semicolons as in the body, above, others separated by commas but still semicolon-terminated, as in the bundle, and braced sections inconsistently semicolon-terminated. This leads to awkward syntax errors when designing new promises :-(

Furthermore, I feel the language would benefit from some noise keywords, for example:

body copy_from local_copy(from) {


body copy_from as local_copy(from) {

The latter makes it slightly more clear which is the base primitive and which the new macro name. I’m a great fan of the use of syntactic sugar, in moderation, and intuitive configuration mini-languages.

This entry was posted in devops, linux. Bookmark the permalink.

2 Responses to Cfengene3 on Debian Squeeze for local management

  1. Philip Hands says:

    As mentioned in a recent comment to the bug to which you refer, the problem is that the example config refers to the symlink rather than directly to /etc/cfengine3 — so the bug is in the example rather than cfengine itself.