CFEngine 3.2.0 extended change log


Finally, we are ready for the CFEngine 3.2.0 release and we’ll have a look at the major changes. In 3.2.0, an exciting CFEngine Nova feature is brought into the community edition, and a set of out-of-the-box policies are released to standardise and simplify CFEngine installations. This will make bootstrapping new CFEngine’d hosts a breeze. Also, as usual, a bunch of new features and bug fixes also made it into the release.

We will cover the following items this time.

  • The brand new cf-agent bootstrap feature
  • More convenient use of ifvarclass
  • Package-promises improvements
  • Editors to support the CFEngine language



If you look at cf-agent --help, you will notice that a new option, --boostrap (-B), has been added to the community edition. Also note the --policy-server (-s) option – they go hand-in-hand. These options, when combined, allows you to specify the IP address of a policy server on the command line. The IP address will then be used when the bootstrapped node pulls for policy updates. So this is easier than the conventional way  to put a new node under management; manually deploying a custom policy and running cf-agent.

So say we have a policy server running at On a fresh client, we run /var/cfengine/bin/cf-agent -Bs Let’s break cf-agent‘s actions down into a series of steps, to see what is actually happening.

  1. Write the address from the --policy-server (-s) option to /var/cfengine/policy_server.dat
  2. Check if /var/cfengine/inputs/ exists, run it and exit if it does
  3. Write an embedded failsafe policy to /var/cfengine/inputs/ (we’ll explore this in a moment)
  4. Run the embedded failsafe policy
  5. The embedded failsafe pulls down a new policy from and starts cf-execd
  6. Bootstrapping is now finished and the new node is under CFEngine management!

This means that all you need to have is a policy server sharing a policy under /var/cfengine/masterfiles and then run one command at the clients to put them under management!


Embedded policy

So how does this embedded policy look? It is actually a very simple policy mainly consisting of a  file-copy promise and a promise to start cf-execd. You can actually see the embedded failsafe as after a host has been successfully bootstrapped.

Since it is embedded in the CFEngine binaries, it is not very pretty with respect to indentation and Knowledge Management features, but it does the job. For your convenience and curiosity needs, I have uploaded the CFEngine embedded Also note that it cannot be changed since it is embedded (and this is why it is so simple), but the policy that gets pulled down is of course entirely up to you.


Bootstrapping the policy server

Until now, we have assumed that the policy server is already set up for us in advance. But, as a matter of fact, bootstrapping the policy server is almost exactly as easy. It will just use its own IP address, thus all hosts will use the exact same bootstrap command. However, /var/cfengine/masterfiles should be populated with the desired policy before bootstrapping it (otherwise, it has no policy to grab!). But CFEngine 3.2.0 also gives you a head start with the bundled policy.


The bundled policy

So what do you put in /var/cfengine/masterfiles on the policy server prior to doing any bootstrapping? In order to get policy updates, it should contain a promise to check for updates from the policy server, and the policy server needs to grant access to the directory with the policy updates (/var/cfengine/masterfiles by convention). But there are also a few other items users always want, like a policy with the bundlesequence and inputs. Also, you might want to configure cf-execd‘s email functionality. And then there’s the cf-serverd access configuraion..

CFEngine 3.2.0 is distributed with a skeleton policy that allows to change these normal parameters without needing to write your own version of everything — just plug in the data in the right place. If grab a tarball, you will find the bundled policy in the masterfiles subdirectory after you unpack it. Otherwise, you can always get it from the CFEngine core subversion repository.

Before starting using it, you can look through to adjust it to your needs. In particular, have a look at the bundle common def. The acl slist there determines the access rules for cf-serverd.


What about trust?

As we know, simplicity and security are often conflicting. In order to make our easy bootstrapping work, two kinds of trust are assumed.

  • Bootstrapping host trusts the policy server’s public key and the policy it holds
  • Policy server trust the new client’s public key and gives access to the policy

The first item is implicit from running the bootstrap command. We are essentially asking the client go to the given IP address for policy updates. If we do not want to assume this kind of trust for some reason, we have to revert to the old way of copying the policy and/or the policy-server’s public key manually. An automatic bootstrap procedure will not be useful to us in this case.

However, we can do something with the second item. First off, we can allow only certain time windows of client trust in the server. We can also limit the (ranges of) IP-addresses we accept. By default we allow the Class B network to access the policy server. See the acl slist in bundle common def in to configure it.

The CFEngine 3 reference manual has some more information on key exchange and time windows.


 Improvements for ifvarclass

As you perhaps know, ifvarclass can be used to transform a variable into a class expression. With CFEngine 3.2.0 you can also make convenient expressions and tests directly in the ifvarclass expression using the new special functions and(), not(), or() and concat(). This can save you class definitions that you would use only once.

For example, you might want to copy down some configuration only to hosts having a certain binary. This can now be done easily with one promise, as shown below.

copy_from  => remote_cp(“/var/cfengine/sitefiles/etc/testservice”, “”),
ifvarclass => or( fileexists(“/bin/testservice”) );

Also note that you can wrap any number of function calls, as shown by the dummy-example below.

“/tmp does exist”
ifvarclass => not( not(fileexists(“/tmp”)));

If you would like to test the two examples on your own, you can download them here.


A pack of bugfixes

As usual, the CFEngine developers have been working hard to check and fix bugs reported by the community. In particular, the packages-promises have gotten a facelift.

The addupdate package policy is now fully functioning when using a repository-enabled manager such as yum or aptitude. Previously this policy was only supported when specifying package_file_repositories combined with non-repository package commands such as rpm or dpkg. For example, the following promise will make sure Apache is installed with a version at least 2.2. If Apache 2.2 or newer is already installed, no action is taken.


package_method => generic,
package_version => “2.2.00”,
package_select => “>=”,
package_policy => “addupdate”;

Also, for efficiency reasons, CFEngine caches the list of installed packages and their version (the output from package_list_command) in WORKDIR/state/software_packages.csv. A problem encountered by some users was that CFEngine did not actually update this cache often enough, so CFEngine might actually act on stale information.  To alleviate this problem, package cache invalidation is introduced in this release. Also note that you can define the cache maximum age with the package_list_update_ifelapsed attribute. There were also a few other package-related issues that were addressed in the 3.2.0 release.

For a complete list of the reported issues/feature requests that was resolved in CFEngine 3.2.0, have a look at the Change Log at the bug tracker.

Lastly, some very good news for Emacs users! Ted Zlatanov, an active member of the CFEngine Community, has created and committed cfengine3-mode to Emacs sources. This has also been added to contrib in the CFEngine core repository.

If you are a vim-er, don’t despair! Have a look at the vim syntax highlighting script and the abbreviations and help files. Both are contributed by Neil Watson, also an important member of the CFEngine community.


Get it!

As usual, CFEngine 3.2.0 is provided not only as a source tarball, but also prepackaged for the most popular Linux distributions by logging into the Engine Room (free registration required). Users of the following distributions enjoy free packages, both 32- and 64-bit versions.

  • Debian 5 and 6
  • Fedora 14 and 15
  • Red Hat Enterprise Linux 4, 5 and 6
  • Suse 9, 10 and 11
  • Ubuntu 8, 9, 10 and 11

Note that most distributions also maintain a CFEngine 3 package, but this is usually older and may not be built in a uniform way.

Please do not hesitate to leave a comment if you found this useful, have suggestions for improvements, or would like to see other CFEngine-related get covered.

Go get those hosts CFEngined!

This entry was posted in CFEngine and tagged , , , , , , , , , , , , , , , , , . Bookmark the permalink.

4 Responses to CFEngine 3.2.0 extended change log

  1. Nakarin says:

    I don’t see RHEL3 and Debian 4 packages on the Engine Room. Are they going to be available soon?

  2. author says:

    Sorry, corrected the distro list now.


  3. Afsin Toparlak says:

    I am new to CFE. I installed it on two debian 6 machines. one ist the policy server and the other one the client.

    What are the next simple steps?

    After bootstrapping I changed the mailto adress to my adress on policy-server:/var/cfengine/masterfile/

    Will it be automatically updated on both machines in /var/cfengine/inputs?

    I see till now no changes? Should I wait for some hours?

    That is unclear to me.

    Or should I bootstrap them again?

    Thnx, best regards,

    • author says:

      Hi Afsin,

      Welcome to CFEngine!
      Yes, if you have the policy hub (server) and client bootstrapped correctly, and you modify files in /var/cfengine/masterfiles on the policy hub, you should see them updating on the client after 5-10 minutes.

      Is that what you did (it seems so from your explanation)?

      Can you see the CFEngine processes running on both hosts?
      Try # ps -e|grep cf

Leave a Reply

Your email address will not be published. Required fields are marked *

9 + two =