I’ve worked with cfengine in the past and really like it. It really cuts down on management for the systems that used it. For my home network I thought I try something else, that something turned out to be puppet.

I must say that I already like it more than cfengine as you can write much smaller manifests.

goals

I want to centralize the management of the files in /etc and I want to keep track of changes of the file. For the management I’m going with puppet and for the versioning I choose git.

My main puppet server is called elektron.atoom.net. The first client is also elektron.atoom.net so this server is both server and client.

initial setup

First install puppet, I’m not going into much detail here. Next install git. Then:

# cd /etc/puppet
# git-init-db

So you we have created a git-repository in /etc/puppet. The default puppet install on Debian/Ubuntu places some of the following files in /etc/puppet:

files/
fileserver.conf
manifests/
puppetd.conf
puppetmasterd.conf

In files/ you place whole files you want to manage with puppet - I will come to that later. Important now are fileserver.conf, puppetd.conf and puppetmasterd.conf.

Setting up the master

The master daemon is called puppetmasterd and is controlled with the following files:

fileserver.conf:

[files]
  path /etc/puppet/files
      allow 192.168.1.2
      allow 127.0.0.1

The path statement tells puppetmasterd that it can find the files in the /etc/puppet/files directory. I haven’t touch the file puppetmasterd.conf, and gone with my distribution’s default.

The client

The client is called puppetd and uses the puppetd.conf for its configuration. The only important change I’ve made is that I’ve added server=elektron.atoom.net to it.

Writing manifests puppet works by reading manifests which then get ’executed’ on the target system. I’m not following the preferred set of directories as I consider those a bit overkill for my small setup.

In /etc/puppet/manifests I do have the following:

etc.pp 
site.pp 

site.pp is the default file that gets read by puppetmasterd, in there you specify which hosts (called nodes in puppet) get which configuration. As I only configure 1 machine at the moment I only have:

import "etc.pp"
node 'elektron.atoom.net' {
    include etc
}

The file etc.pp defines one class: etc which I include in the configuration for elektron.atoom.net. For my other (soon to be added) machine called “foton” I will need another node-statement. I needed to put the name elektron.atoom.net in single quotes to make this work, double quotes didn’t cut it for me.

etc.pp

The file etc.pp looks like this: (I’ve added line numbers)

 1  class etc {
 2      file { "/etc":
 3          source => "puppet://elektron.atoom.net/files/elektron/etc",
 4          recurse => true
 5      }
 6
 7      file { "/etc/inetd.conf": owner => root, group => root, mode  => 644,
7.5      source => "puppet://elektron.atoom.net/files/elektron/etc/inetd.conf"}
 8      file { "/etc/motd.tail": owner => root, group => root, mode  => 644,
8.5      source => "puppet://elektron.atoom.net/files/elektron/etc/inetd.conf"}
 9      
10      service { inetd:
11          ensure => true,
12          pattern => "/usr/sbin/inetd",
13          subscribe => FILE["/etc/inetd.conf"]
14      }
15
16      exec { "Create /etc/motd":
17          subscribe => FILE["/etc/motd.tail"],
18          logoutput => true,
19          refreshonly => true,
20          command => "/bin/uname -snrvm > /var/run/motd; /bin/cat /etc/motd.tail >> /var/run/motd"
21      }
22  }

I will go by this line-by-line.

  • 1: define a new class called etc.
  • 2: The concerns the file “/etc” - which ofcourse is a directory.
  • 3: This defines what to put in this directory: namely files from /etc/puppet/files/elektron/etc. now all files in that directory will get copied to /etc. Note the source syntax uses /etc/puppet as a basedir, alltough we’ve specified /etc/puppet/files in fileserver.conf.
  • 4: recurse is used to say that all files in files/elektron/etc should be monited.
  • 7: The files are named here so that they can be references by other puppet manifests.
  • 7.5: Because I redefine the file /etc/inetd.conf I must tell puppet where to find it.
  • 8.5: And the same here for /etc/motd.tail.
  • 10: I use this to tell puppet that if the file /etc/inetd.conf changes the service (daeamon) inetd should be restarted.
  • 13: subscribe, watch the file /etc/inetd.conf. My personal preference is to write this with all capitals. For puppet only the first character needs to be uppercased.
  • 16: Now I subscribe to /etc/motd.
  • 20: when the file changes puppet needs to perform the following command.

Now I only need to put my files in /etc/puppet/files/elektron/etc and puppet will miror them in the real `/etc’. Note that ownership and permissions are also exactly copied.

versioning As said I will be using git to version my files. This is relatively easy. First add the files to your repository.

# cd /etc/puppet
# git-add files manifests

And then commit them:

# git-commit -a -m "committing my changes to /etc"

As git doesn’t support the $Id$ tags that you might know from CVS and subversion I just change my files to include the text string ## configured with puppet ##.

Debugging and testing

Just use:

# puppetmasterd -v

on the commandline and watch the output and correct any errors you might see.

The easiest way to debug and test puppetd was also on the commandline, with:

# puppetd -v -o

You will get a lot of output telling you what happens. You can also debug a specific puppet manifest with:

# puppetd -v -o etc.pp