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