Cfengine 2 for Debian and Ubuntu

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. . The latest version has made significant changes to the scripting structure, but maintains the capability to run the version 2 format files.

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.

Required Files

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.

Configuration Overview

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. Configuration is done in package groups such as debian, main, site, ldap, monitor, and root.

The main 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 cfagent.defs.

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 files target.

I arrange the files for Cfengine as follows:

  • inputs – configuration files for Cfengine. They belong in /etc/cfengine.
  • group/package/… – other files that 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 which 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 host name 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.

The Debian apt tool requires 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.

The following /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 statement:

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" )