Automating Security with GNU cfengine

A sysadmin tool for automating changes across many machines, recording update information and making them all safer.

Many years ago, I had a small revelation that I'm sure many of you have experienced yourselves. I realized that maintaining 10 systems requires a good bit more work than administering a single computer. But, it doesn't have to take that much more work--assuming the proper tools and methodologies are used.

When you want to make a change to a single system, you simply decide what to change and poke around until everything works properly. Three months later, you may not even remember what it was you did or why you did it. Does that matter? Not usually.

But when you have to make those changes to several systems, do you really want to perform manually the same task numerous times? If you had 10 systems but now have 11, will you remember to make all of the same changes to the new arrival? Maybe the new system is slightly different--or maybe none of your systems are the same. Wouldn't it be nice to know exactly what you did and why you did it?

This is where GNU cfengine, by Mark Burgess, comes into play. It allows you to affect changes effortlessly across any number of dissimilar systems. Perhaps even more important, it provides automatic documentation of exactly what you did. You even can use a few comments to explain why you did it. Each of your systems become a member of one or more classes, and changes are made on a per-class basis. If a new system arrives, it automatically acquires the changes previously made to other members of its class.

Once cfengine is installed (from and running, making changes to your group of systems becomes almost as easy as changing a single system. This gives you more time to decide what to do and how to do it, something that remains the primary responsibility of an administrator to this day.

Getting Started

As with many programs, the most difficult part about using cfengine is getting started. For this reason, we are going to set up a basic environment, with one client and one server. You should perform these steps on a couple of test systems, if possible, to follow along with the examples. Later, you can expand this framework to build your own cfengine environment.

I believe you always should start a new adventure with the simplest practical configuration. In this case, the systems are assumed to each have a single, static IP address and the proper DNS entries (forward and reverse). The setup process can be summarized as follows:

  • 1. Create master configuration files on the master server (cfservd.conf, update.conf and cfagent.conf).

  • 2. Create public/private keys on each system and distribute appropriately.

  • 3. Start cfservd on at least the server, and run cfexecd on all systems.

Configuration Server

Let's start with the master server. It should have the directory /usr/local/var/cfengine/inputs containing the master set of configuration files. It must run the cfservd dæmon, and it must have a valid cfservd.conf configuration file, as follows:

   domain = ( )
   AllowUsers = ( root )
   cfrunCommand = ( "/var/cfagent/bin/cfagent" )

   /usr/local/var/cfengine/inputs *
   /var/cfagent/bin/cfagent       *

This simple configuration file does little more than allow all hosts from to download the master set of configuration files. It also allows remote systems to execute the cfagent command using cfrun, a useful feature you should explore once you have things up and running.

Configuration Distribution

We now can move on to update.conf, which is processed and executed first when cfagent is run on any system. This file's primary function is to transfer the master configuration files to the local system. It must be kept simple and reliable, as any errors in this file have to be repaired manually on each system.

Listing 1. Sample update.conf

   actionsequence = ( copy tidy )
   domain         = ( )
   workdir        = ( /var/cfengine )
   policyhost     = ( )
   master_cfinput = 
                  ( /usr/local/var/cfengine/inputs )
   cf_install_dir = ( /usr/local/sbin )

   $(master_cfinput)     dest=$(workdir)/inputs




   $(workdir)/outputs pattern=* age=7

The file shown in Listing 1 should be all you need in most environments; simply replace with the hostname of your cfengine server. When executed, this update.conf file creates a local copy of the required cfengine binaries in /var/cfengine/bin (from /usr/local/sbin, which is assumed to be an NFS filesystem, or similar).

More importantly, the configuration files are copied from the server that runs cfservd to /var/cfengine/inputs on every system, including the server itself. The configuration files are compared bit-by-bit with the master file (type=binary), while the binaries are updated if their checksums don't match the master copies.

Finally, the tidy section removes output logfiles that are more than seven days old to keep your drive from filling up. The tidy section also can be used in the main cfagent.conf to clean up a variety of other files on your systems.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Excellent article

Mark Wolf's picture

This is by far the best basic setup article I have found. I have tried to follow several other articles and was not successful in getting things to work. I have got a cfengine configuration setup and running on three servers using keys and classes etc...Woohoo...

Very nice indeed

Thank you



Stefan2's picture

I say "Woohho....", too.
thank you for this great article...
it would help me to understand cfengines functionality...

sorry for my english but I wanted to say this now ;-)


Automating Security with GNU cfengine

sts's picture

just wanted to leave a link to our cfengine wiki. maybe that might be helpful to anyone.

regards. stefan.

Re: Automating Security with GNU cfengine

Anonymous's picture

This is an excellent, in depth, clear, concise article on a great application ( cfengine ). I have recently been asked to set-up and configure cfengine at work.

I found that although cfengine is well documented, the docs are missing some very key points in actual implementation, (like a. do this. b. now do this. c. now do this. d. your done. i.e. for installation it said ./configure, make , make install - ok great, now what, then you had to read all the 'advanced' command line switches and possible params without a clear sequence of events. 30+ pages, additionally it would not make on my box, Red Hat 9.0 Shrike, or Slackware 9.2 kept getting "must have Berkeley3.2 or later", i was running Berkeley4.2,..." errors, i filled a bug report with the author, I had to install a rpm)

It was very diffucult to find google results on actual working implementations of this tool. I did find a few and with all the docs and example files after 2 days had a pretty decent idea about my set-up, except for a few key details. ( like how to get a new cfengine.conf on each host, before running cfengine, kind of like chicken/egg,... )
Then i discovered this excellent article, which i think should be included on the cfengine site, or have links to it, like a "step-by-step" example implementation.

Thanks for this great article.

Re: Automating Security with GNU cfengine

Anonymous's picture

Actually the only thing i would append to my comment, is that the Mr. Bauer did not include which version this article is based on. It sounds as if it's based on a pre 2.0 version but it's hard to tell. (I don't know exactely vor what version the cfengine change took place but it moved everything from /usr/local/cfengine to /var/cfengine, which can lead to some confusion when reading articles describe configuration). :)

Re: Automating Security with GNU cfengine

Anonymous's picture

sorry, to append my post again, actually with this comment
"this creates the files and localhost.priv in the /var/cfengine/ppkey" - it has to be >= 2.0. sorry about that. (It would still be cool if in the header of the article it stated "based on a 2.1.1 cfengine or whatever,..."
thanks again