Puppet Modules and Apt
One of the most exciting features of Puppet is the way it enables the sharing of systems administration tools - “recipes” in the Puppet parlance. Puppet allows us to collect manifests, definitions, and even plugins into modules which can then be shared with others.
David Schmitt is the author of the Complete Configuration found on the Puppet wiki. This is an amazing example of what can be done with Puppet, but can be a bit overwhelming at first. Happily, it is reasonably easy to integrate David’s modules into your Puppet configuration one at a time. Today I’d like to show you how to use David’s apt module to manage the dpkg & apt databases, as well as the keyrings associated with them.
In order to get started with David’s modules, we’ll need to take a few steps. The first step is upgrading to the latest release of Puppet. In an earlier post I advocated using the Debian packages; on further reflection, it might be best to install from source (or roll your own package). Puppet is a bit of a moving target right now, and you’ll definitely want to keep up. Installing from source is easy enough. On Debian Etch, I used the following steps to install from source:
1 2 3 4 5 6 7 8 9 10 | aptitude remove puppet puppetmaster aptitude install libopenssl-ruby libshadow-ruby1.8 libxmlrpc-ruby curl -kO https://reductivelabs.com/downloads/facter/facter-1.3.7.tgz tar xzf facter-1.3.7.tgz curl -O http://reductivelabs.com/downloads/puppet/puppet-0.24.1.tgz tar xzf puppet-0.24.1.tgz cd facter-1.3.7 ruby install.rb cd ../puppet-0.24.1 ruby install.rb |
In short: remove the old version, install the prerequisite ruby libraries, download the latest source of Facter and Puppet, and install them both. The init scripts didn’t work after this, so I rolled my own.
The new version of Puppet allows module authors to distribute plugins within their modules. However, to make use of this, we need to add a couple of lines to the [main] section of our puppet.conf file:
pluginsync = true pluginsource = puppet://$server/plugins
You’ll want to create a “modules” subdirectory to store your modules in. According to the Puppet Best Practices page, this directory should be in the same place as your “manifests” directory. For me, that means /etc/puppet:
total 36K drwxr-xr-x 6 root root 4.0K 2008-01-02 13:47 . drwxr-xr-x 71 root root 4.0K 2008-01-02 13:44 .. drwxr-xr-x 7 root root 4.0K 2008-01-02 13:47 files -rw-r--r-- 1 root root 664 2008-01-02 13:47 fileserver.conf drwxr-xr-x 4 root root 4.0K 2008-01-02 13:57 manifests drwxr-xr-x 4 root root 4.0K 2008-01-02 13:47 modules -rw-r--r-- 1 root root 250 2008-01-02 13:47 puppet.conf
Next, we’ll want to download the modules we wish to use. All of David’s modules depend on the “common” module, so we will want “common” and “apt”. David makes it easy to pull down each module independently. Here’s what I did:
1 2 3 4 5 6 7 8 9 10 11 12 | cd /etc/puppet/modules mkdir common cd common git init git remote add -t common -m common -f origin git://git.black.co.at/manifests/ git pull cd /etc/puppet/modules mkdir apt cd apt git init git remote add -t apt -m apt -f origin git://git.black.co.at/manifests/ git pull |
You should now have local copies of both the “common” module and the “apt” module. If you read the documentation, you will notice that these modules require the installation of the “lsb-release” package. I’m not sure why David doesn’t have the module install the package, but he doesn’t. So, let’s have puppet install it. A new “package” resource in our default node should do the trick:
25 26 27 | package { sudo: ensure => installed } package { lsb-release: ensure => installed } } |
Next, we need to integrate the new modules into our puppet configuration. Now that we’re getting into more complex configurations, we’ll want to start breaking our puppet configuration into separate files. In the same directory as site.pp (/etc/puppet/manifests), create a file called modules.pp containing:
1 2 | import “common” import “apt” |
As you add more modules, you’ll import them here.
We won’t be explicitly using the common module at this time, so all we need to do is add two lines to site.pp. At the top of the file, we’ll want:
1 | import modules.pp |
to pull in the file we just created. We also want to update the default node to make use of the apt module:
7 8 9 10 | node default { include apt file { ‘/root/.ssh/authorized_keys’: |
It turns out that David’s modules also depend on a filebucket resource named “server”. This is a site-wide resource, so site.pp is the ideal place to put it:
3 4 5 6 7 | filebucket { server: server => “server1.example.com” } node default { |
After all these modifications, our site.pp looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import modules.pp filebucket { server: server => “server1.example.com” } node default { include apt file { ‘/root/.ssh/authorized_keys’: owner => root, group => root, mode => 644, source => ‘puppet:///root/.ssh/authorized_keys’ } file { ‘/etc/sudoers’: owner => root, group => root, mode => 440, source => ‘puppet:///etc/sudoers’ require => [ Package[“sudo”] ] } package { sudo: ensure => installed } package { lsb-release: ensure => installed } } |
I had to do one more thing to get this to really work. Reading through David’s module, you would expect /var/lib/puppet/modules/apt to be created by Puppet. Unfortunately, this doesn’t seem to happen. I had to create this directory by hand. I’ll let you know if/when I figure out why.
For basic usage of the module, this is all you need! David’s module defaults to a very sane basic apt configuration. The only tweak I felt was necessary was a modification to modules/apt/templates/sources.list.erb to use a US Debian mirror. You can modify this file to your liking for your default sources.list. You can also use the $custom_sources_list variable in a node definition to provide a customized file for a specific node:
node “oddball.example.com” { $custom_sources_list = “#This box is located in Canada, so use a local mirror deb http://ftp.ca.debian.org/debian etch main contrib non-free deb http://security.debian.org/ etch/updates main contrib non-free” include “apt” }
David has a number of other modules I’d like to try; as I get them working I’ll be sure to share my experiences here.
Hi Paul,
Thanks for your howto.. Only thing you missed was to add the user puppet.
useradd puppet
Cheers,
Andy
Comment by whoarghhh — 7 February, 2008 @ 4:36 pm
Andy,
I guess I wasn’t clear that this post builds on earlier posts and assumes you already have puppet installed, and are just upgrading.
–Paul
Comment by plathrop — 7 February, 2008 @ 6:11 pm