Cfengine is a declarative system configuration tool. This helps apply standards to system configuration. The configuration files specify the desired configuration and the engine applies these specifications to the system. It is useful to:
- Distribute configuration files;
- Install standard packages (including on Debian and Ubuntu with code provided here);
- Cleanup old files; and
- Ensure certain programs are/are not running.
This documentation applies to Cfengine version 2. Version 3 has made significant changes to the scripting structure but maintains the capability to run the version 2 format files.
The configuration is done with text files which are distributed from one or more configuration masters. The configuration files on the master server should be stored in a version control system such as CVS, Subversion, GIT.
An alternative tool is
puppet. Reliable scripted file editing in either tool is difficult to do correctly. I maintain the files on the server and let Cfengine push out changes as required.
There are a few files required to configure Cfengine. These are:
cfserver.conf– Configures the server.
update.conf– Simple definitions to update the configuration.
cfagent.conf– The major configuration file.
cfrun.hosts– A list of hosts running cfengine.
The configuration item reads as follows:
action-type: class:: definition sequence or action sequence....
Suggested Configuration Structure
After a few tries, I have found the following structure enables management of the configuration by area of concern. The configuration is done in package groups such as
cfagent.conf file consists only of imports of
cfagent.defs, and the definition files for package groups (
main.cf, etc). The definition file for a package group should always conditionally import
The actions for a group have a default extension of
.actions. If there are multiple action definition files for different packages, then the extension reflects the target of the file.
I arrange the files for Cfengine as follows:
- inputs – configuration files for Cfengine. They belong in
- group/package/… – other files are arranged by package with general grouping. If there is only one package in the group, the package sub-directory may be omitted. Use additional sub-directories to simplify file management as required. A package directory may include scripts that will be copied to binary directories.
- user/… – files that belong in the user’s directory. Arranged in target-related sub-directories as required.
- os/package/… – O/S specific binaries by not distributed as packages by package. These may also be copied or installed from a binary server. I haven’t used this structure extensively.
For a package such as nut (Network UPS Tool) the file are distributed as follows:
inputs/monitor.cf– variable definitions for the monitoring packages.
inputs/monitor.ups– actions required to configure NUT (ups).
monitor/ups/*– configuration files for NUT (ups monitoring). Host-specific files have the hostname added as an additional extension. Host group-specific file may have a host group extension if required.
Debian and Ubuntu
Most of the systems I manage with Cfengine are have Debian based operating systems. This includes Ubuntu distributions. Cfengine provides some support for package management. It provides limited support for version number comparison, which can be used to determine which packages need installation.
apt tool requires a special setup to prevent interaction with the user during installation. This will force defaults to be used on installation when available. Some packages may require pre-seeding or post-installation manual intervention to enable Debian to complete the installation.
/etc/cfengine/apt-get.sh file provides the appropriate setup for package installation.:
#!/bin/sh # apt-get.sh - Cfengine wrapper for apt-get install DEBIAN_FRONTEND=noninteractive; export DEBIAN_FRONTEND if [ $# -gt 0 ]; then /usr/bin/logger -p local0.notice "$0: $*" /usr/bin/apt-get -y -q $* fi # EOF
Before Cfengine can reliably install packages, the
apt-get.sh file must be installed. This can be done with this
copy: debian:: $(MasterFiles)/debian/sbin r=1 dest=/usr/local/sbin include=* ignore=CVS server=$(FileServer) mode=755 owner=root group=root
The following definition segment from
cfengine.defs will configure Cfengine to use the above script for installing and removing packages.
debian:: DefaultPkgMgr = ( dpkg ) DPKGInstallCommand = ( "/usr/local/sbin/cf_apt-get.sh install %s" ) DPKGRemoveCommand = ( "/usr/local/sbin/cf_apt-get.sh remove %s" )