Based on the definition from official Cfengine.org web-site: Cfengine is an automated tool for configuring and maintaining Unix-like computers.
This tutorial is created to help system administrators who need to manage multiple servers and would like to have the ability to manage server configurations in a centrally managed manner.
This tutorial assumes:
- the reader is already familiar with basic system administration.
- the reader heard at least what Cfengine is, and would like to try it in a test environment of his or hers.
- OS choice is the Redhat, Centos or Fedora Linux distributions
- the reader knows basic Subversion.
- the reader is willing to accomodate a few way-of-doing-things that is forced upon the reader
This tutorial also includes:
- a minimal cfengine configuration
- a simple application deployment via cfengine: name services.
Obviously other operating systems are supported, and you can deploy any application you want with Cfengine, however to be consistent with the title of this document, we will keep things as simple as possible.
Throughout this tutorial we will assume that all Cfengine services runs on all servers that you will deploy Cfengine to. However one of the servers will be Cfengine server (let's say srv01) and the rest of them will be Cfengine clients (let's say dns01 and dns02). In addition within this tutorial we will show how to force clients to get updates irregularly. This tutorial consists of following sections:
- Cfengine Installation
- Cfengine Minimal Configuration
- First application deployment using Cfengine
- Cfrun: central push
One last note: at a very minimum you can think of cfengine server as a configuration file server, and cfengine client as a cron job that wakes up every so often to connect to that file server (pull strategy) and compare if the client is up-to-date with those configurations. Obviously cfengine does much more than that. But this is at a minimum what you can think cfengine does if you don't know what it is. There is a way to avoid the pull strategy, and make cfengine server interfere with the execution timing or commands, namely utilizing cfrun.
A. Cfengine Installation
All systems that will be managed by cfengine needs to get the Cfengine installed and have cfengine services running:
- Install cfengine for your distribution on all cfengine servers and cfengine clients. One way to obtain the cfengine is to use Dag's repo for cfengine: http://dag.wieers.com/rpm/packages/cfengine. Go to that URL and identify which cfengine RPM you need and install it via:
- After installation, enable all cfengine services on both servers and clients. The cfservd component on cfengine clients will later be utilized for cfrun:
# rpm -ivh http://dag.wieers.com/rpm/packages/cfengine/cfengine-2.2.1-1.<distro>.rf.<arch>.rpm
# chkconfig cfenvd on # chkconfig cfexecd on # chkconfig cfservd on
The description of daemons are:
- cfservd: This is the cfengine server process that lets the clients to connect to. In the case of a server pushing something to the client, this process on the client accepts the request from the server.
- cfenvd: This provides machine learning support for cfengine. This requires no configuration.
- cfexecd: This is a wrapper to execute the cfagent binary on regular intervals. Instead of running this you can have a cron entry to run cfagent as well. Cfagent binary is the client program that connects to the cfservd.
The description of important binaries are:
- cfagent: the binary that does all the magic on the client side. You can execute this manually as well, you don't need to wait cfexecd to execute this.
- cfrun: this binary is to send commands to cfengine clients as long as the clients are running cfservd.
B. Cfengine minimum configuration for Redhat, Centos or Fedora
Here, we recommend to use subversion or any other version controlling solution to keep track of the versioning. It is up to the reader to skip the subversion steps, but it is not recommended to skip these steps by the author.
- Here we will create a subversion trunk so that our configurations will have versioning and thus ability to roll-back changes when there is need to. In the subversion trunk we will have the following directory structure:
trunk ---> info |-> build ---> <role #1> | |-> <role #2> ---> etc | |-> <other unix directories if necessary> |-> cfengine
- Directory "info": this is to put notes in such as how to install cfengine on a cfengine client, etc which cannot be automated by cfengine.
- Directory "build": this is where we will keep the configuration files or other files that cfengine will be deploying to the cfengine server or clients.
- Directory "cfengine": this is where we will keep the cfengine configuration files.
Now that what we decided on the directory structure, let's create our subversion trunk. You can do this on any computer: on your laptop, on your workstation, on your cfengine server itself, namely wherever you want. Let's say our svn repository will be called "admin".
$ cd ~/src $ mkdir admin $ chdir admin $ mkdir info build cfengine $ <create a svn repo for your cfengine configurations> $ svn import -m "Initial import" . <newly created svn repo URL>/trunk
$ cd ~/src $ rm -rf admin $ svn co <newly created svn repo URL>/trunk $ mv trunk admin
- cfagent.conf : all the cfengine servers and clients will have their cfagent (the binary that implements the cfengine magic) use this configuration.
- cfservd.conf: this is the configuration file for cfservd daemon.
- update.conf: this is for the cfagent as well, but it tells the cfagent where to connect and get cfengine initial configuration files.
- cfrun.hosts: this is for cfrun binary to specify which cfengine clients to connect to and how many at a time to execute commands on, etc.
Additionally we will divide and conquer the cfengine configurations by creating include files. The first one that we will create is:
- cfagent.global.conf: this include file will be included by all cfengine servers and clients.
Below are example configuration files contents to get you started. Go through them and ensure that IP block, domain-names are to your liking:
cfagent.conf: (see inside for description of fields)
cfservd.conf: (see inside for description of fields)
update.conf: (see inside for description of fields)
cfrun.hosts: (see inside for description of fields)
cfagent.global.conf: (see inside for description of fields)
Now create all these files in this directory
$ cd ~/src/admin/cfengine $ vi cfagent.conf $ vi cfservd.conf $ vi update.conf $ vi cfrun.hosts $ vi cfagent.global.conf $ svn add * $ cd ~/src/admin/build $ mkdir all # create a role called "all" to put files that will be deployed $ mkdir all/etc $ vi all/etc/sudoers # copy your sudoers file $ svn add all $ cd ~/src/admin $ svn commit -m "created initial bare minimum cfengine configuration files"
srv01# cd /export srv01# svn export <newly created svn repo URL>/trunk srv01# mv trunk admin-r2 srv01# ln -s admin-r2 admin
srv01# cp /export/admin/cfengine/* /var/cfengine/inputs
srv01# scp /export/admin/cfengine/update.conf dns01:/var/cfengine/inputs/ srv01# scp /export/admin/cfengine/update.conf dns02:/var/cfengine/inputs/ dns01# cfagent dns02# cfagent
C. Deploy our first application: Bind
Now let's setup a basic name server to be deployed using Cfengine to the servers dns01 and dns02.
- Let's update the cfengine configurations in our svn trunk and upload our DNS configurations. Let's say we are deploying a caching only DNS server with default settings.
- Now check out this subversion trunk under /export/admin-rXXX and update the symlink /export/admin to it.
- Now let's deploy the dns configuration to clients now by either waiting until the next hour or running it manually on all servers. Note that sometimes you might have to execute it multiple times due to ActionSequence. Note that due to the cfagent.global.conf configuration we set for SPlayTime, you will need to wait 1 minute to elapse before the next cfagent can run.
We need to update cfagent.conf: (see the updates in bold)
We need to add cfagent.dns.conf: (see inside for description of fields)
$ cd ~/src/admin/cfengine $ vi cfagent.conf $ vi cfagent.dns.conf $ svn add * $ cd ~/src/admin/build $ mkdir dns # create a role called "dns" to put files that will be deployed $ mkdir -p dns/var/named $ cp -r <some location>/named dns/var/named # copy your bind configs $ svn add dns $ cd ~/src/admin $ svn commit -m "created initial dns deployment"
srv01# cd /export srv01# svn export <newly created svn repo URL>/trunk srv01# mv trunk admin-r3 srv01# rm -f admin srv01# ln -s admin-r3 admin
dns01# cfagent dns02# cfagent
Now your DNS servers are configured and ready to go.
D. Cfrun: central push
In the above DNS configuration example, in order to manually deploy we had to logon to each server and run cfagent manually. However, since we have configured cfservd to run on all client systems, we can use cfrun to manually run cfagent on all client servers that are listed in our cfrun.hosts
To do one at a time: srv01# cfrun -f /export/admin/cfengine/cfrun.hosts dns01 srv01# cfrun -f /export/admin/cfengine/cfrun.hosts dns02 To do all at once: srv01# cfrun -f /export/admin/cfengine/cfrun.hosts
CFengine Reference Documentation
How-to Version: 1.00