by Juliet Kemp

First up: check out the O'Reilly "Women in Tech" series - especially my article :)

Lately I have mostly been playing with Puppet, a piece of software for centrally managing host configuration. (I have various roll-your-own solutions for aspects of this, as ever, but this looks like a better way of doing it.)

One very nice thing about Puppet from my point of view is that it will take its node definitions from LDAP. (In Puppet, a node is any individual machine.)

How this works is that instead of having your node definitions in site.pp, you keep them in LDAP as the puppetclass attribute. You can have as many of these attributes per host as you like - for example, my web server has webserver, ftpserver, and server as puppetclass attributes.

site.pp therefore has only import statements, not node definitions, and you put your class definitions in /etc/puppet/manifests/classes (or wherever suits you), and import them in site.pp.

You probably want to start with something along the lines of the setup I have, as described below, with base.pp, desktop.pp, and server.pp classes (the latter two inherit from the first). These correspond to desktop and server as puppetclass attributes (the inheritance structure means there is no need to specify base). Then add further puppetclasses as required for your site.

The wiki has some information on how to do the LDAP integration; this is how I did it:

  • Install libldap-ruby1.8 on the Puppet server (Debian package).
  • Add the Puppet schema to your LDAP schema directory (/etc/ldap/schema/ for me), add it to your slapd.conf, and restart slapd. The schema seems to be a little hard to get hold of through official channels at present, so I reproduce it here:
    # These OIDs are all fake.  No guarantees there won't be conflicts.
    # $Id$
    attributetype ( NAME 'puppetclass'
            DESC 'Puppet Node Class'
            EQUALITY caseIgnoreIA5Match
            SYNTAX )
    attributetype ( NAME 'parentnode'
         DESC 'Puppet Parent Node'
         EQUALITY caseIgnoreIA5Match
         SYNTAX )
    objectclass ( NAME 'puppetClient' SUP top AUXILIARY
         DESC 'Puppet Client objectclass'
         MAY ( puppetclass $ parentnode ))
  • Modify all existing host LDAP entries so they have objectClass: puppetClient, a puppetclass attribute (my initial ones were server and desktop, and a parentnode attribute (I have baseserver and basedesktop).
  • Create baseserver and basedesktop LDAP entries. It is not entirely clear to me if these really have a purpose; but I gave them the appropriate puppetclass and will investigate further in due course.
  • In /etc/puppet/puppetmasterd.conf, add:
    ldapnodes = true
    ldapserver = ldapserver.example.com
    ldapbase = dc=example,dc=com
  • That's it!

A note: if you're changing the puppetmaster config, or any other puppet setup stuff, it can be useful to stop the running puppetmaster process, and restart it interactively with the verbose option: puppetmasterd --verbose. This helps a lot with debugging.