<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Coherent Ramblings &#187; Puppet</title>
	<atom:link href="http://plathrop.tertiusfamily.net/blog/tag/puppet/feed/" rel="self" type="application/rss+xml" />
	<link>http://plathrop.tertiusfamily.net/blog</link>
	<description>My thoughts on everything from Operations through Parenting and beyond.</description>
	<lastBuildDate>Thu, 03 Jun 2010 17:12:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Debian Packaging Puppet Manifests</title>
		<link>http://plathrop.tertiusfamily.net/blog/2010/05/03/debian-packaging-puppet-manifests/</link>
		<comments>http://plathrop.tertiusfamily.net/blog/2010/05/03/debian-packaging-puppet-manifests/#comments</comments>
		<pubDate>Tue, 04 May 2010 00:57:55 +0000</pubDate>
		<dc:creator>plathrop</dc:creator>
				<category><![CDATA[Puppet]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[packaging]]></category>

		<guid isPermaLink="false">http://plathrop.tertiusfamily.net/blog/?p=39</guid>
		<description><![CDATA[With the (new?) ability for Puppet to have multiple module_dirs, the idea occurred to me: why not package a module as a Debian package?
The packaging process was relatively easy. Check out the results on GitHub.
Enjoy!
]]></description>
			<content:encoded><![CDATA[<p>With the (new?) ability for Puppet to have multiple module_dirs, the idea occurred to me: why not package a module as a Debian package?</p>
<p>The packaging process was relatively easy. Check out the results <a href="http://github.com/plathrop/puppet-module-supervisor/tree/master/debian/">on GitHub</a>.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://plathrop.tertiusfamily.net/blog/2010/05/03/debian-packaging-puppet-manifests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating Puppet Modules</title>
		<link>http://plathrop.tertiusfamily.net/blog/2008/04/18/creating-puppet-modules/</link>
		<comments>http://plathrop.tertiusfamily.net/blog/2008/04/18/creating-puppet-modules/#comments</comments>
		<pubDate>Fri, 18 Apr 2008 23:56:09 +0000</pubDate>
		<dc:creator>plathrop</dc:creator>
				<category><![CDATA[Philosophy]]></category>
		<category><![CDATA[Puppet]]></category>

		<guid isPermaLink="false">http://plathrop.tertiusfamily.net/blog/2008/04/18/creating-puppet-modules/</guid>
		<description><![CDATA[In Puppet parlance, a module is a collection of manifests (including classes and definitions), templates, and files which, taken together, describe a recipe for configuring something via Puppet. Puppet has a number of facilities which make modules incredibly useful and labor-saving.
Modules have a standard internal organization which is described in detail on the ModuleOrganisation wiki [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://puppet.reductivelabs.com">Puppet</a> parlance, a <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#module">module</a> is a collection of <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#manifest">manifests</a> (including <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#class">classes</a> and <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#definition">definitions</a>), <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#templates">templates</a>, and files which, taken together, describe a recipe for configuring something via Puppet. Puppet has a number of facilities which make modules incredibly useful and labor-saving.</p>
<p>Modules have a standard internal organization which is described in detail on the <a href="http://reductivelabs.com/trac/puppet/wiki/ModuleOrganisation">ModuleOrganisation</a> wiki page. A trivial module can be as simple as a <samp>manifests</samp> directory containing only a single manifest: <samp>init.pp</samp>. However, as modules grow more complex, you&#8217;ll want to break up your manifests and add templates in a <samp>templates</samp> directory, files in a <samp>files</samp> directory, and a <samp>README</samp> file which explains how to make use of your module.</p>
<p>I&#8217;m in the process of polishing up several modules, including LDAP, Kerberos, memcached, and ntp modules. In some ways, I&#8217;m duplicating work; several implementations of these modules are available. However, Puppet modules are still evolving, and I wanted to try my hand at module writing. Also, the existing modules did not work quite right for us. Some of them fail to properly isolate site-specific information from the recipe, for example. Others had complex interdependencies that I didn&#8217;t like.</p>
<p>There are several techniques that I think will evolve as &#8220;best practices&#8221; for Puppet module design. These are:</p>
<ol>
<li>Keep site-specific customization out of your modules.
<li>Your module should implement a minimal working configuration &#8220;out of the box&#8221;.
<li>Use variables to make it easier to patch your module for use on other platforms.
<li>Break a module up into sensible classes and defined types to make it easy to customize via inheritance.
<li>Use <samp>init.pp</samp> for module-wide variables and/or common functionality, but break all other classes/defines into separate files.
</ol>
<p>Let&#8217;s take a look at each of these in detail:</p>
<h3>Keep site-specific customization out of your modules.</h3>
<p>Modules are, at heart, meant to be shared with others. Try to write your modules so they are as site-neutral as they can be. Use variables that can be set in a higher-level scope like <samp>site.pp</samp> to control how the module works, instead of baking your site&#8217;s settings into the module. For example, in my LDAP module I do this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ldap::common <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#9966CC; font-weight:bold;">case</span> <span style="color:#ff6633; font-weight:bold;">$ldap_base_dn</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#996600;">&quot;&quot;</span>: <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff6633; font-weight:bold;">$ldap_base_dn</span> = <span style="color:#996600;">&quot;dc=example,dc=com&quot;</span>
      warning<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;ldap_base_dn not set, using default $ldap_base_dn&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">case</span> <span style="color:#ff6633; font-weight:bold;">$ldap_admin_dn</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#996600;">&quot;&quot;</span>: <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff6633; font-weight:bold;">$ldap_admin_dn</span> = <span style="color:#996600;">&quot;cn=admin,$ldap_base_dn&quot;</span>
      warning<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;ldap_admin_dn not set, using default $ldap_admin_dn&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">case</span> <span style="color:#ff6633; font-weight:bold;">$ldap_admin_password</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#996600;">&quot;&quot;</span>: <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#CC0066; font-weight:bold;">fail</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;ldap_admin_password not set!&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Then, in <samp>site.pp</samp>, I set the variables appropriately:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Site Variables</span>
<span style="color:#ff6633; font-weight:bold;">$ldap_server</span>           = <span style="color:#996600;">&quot;ash001.example.com&quot;</span>
<span style="color:#ff6633; font-weight:bold;">$ldap_admin_password</span>   = <span style="color:#996600;">&quot;testing&quot;</span>
<span style="color:#ff6633; font-weight:bold;">$ldap_base_dn</span>          = <span style="color:#996600;">&quot;dc=example,dc=com&quot;</span></pre></div></div>

<h3>Your module should implement a minimal working configuration &#8220;out of the box&#8221;.</h3>
<p>This principle is also tied in with the fact that modules were meant to be shared. When someone is looking for a module, they are going to want something that works with little-to-no configuration, because this will give them confidence that the module will work once it is fully configured. Just like full-blown pieces of software, if a module doesn&#8217;t have an easy initial setup, people will get confused as to whether or not it even works. My LDAP module provides a <samp>ldap::master</samp> class which implements a very basic configuration: the slapd package is installed, a working configuration file is set up (without SSL or any of the other goodies), and the service is started. If the user sets just one variable, <samp>$ldap_admin_password</samp> in their <samp>init.pp</samp> and includes <samp>ldap::master</samp> on a node, they will be able to verify that LDAP is up and running with an example configuration. Even better, if they set the other variables, this configuration will be customized to their site with little effort on their part. It might be better to add in all the bells and whistles (SSL at a minimum), but I&#8217;m not sure yet where I stand on that.</p>
<h3>Use variables to make it easier to patch your module for use on other platforms.</h3>
<p>Currently, in the <samp>init.pp</samp> of my LDAP module, I set variables like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#ff6633; font-weight:bold;">$ldappackage</span>       = <span style="color:#996600;">&quot;slapd&quot;</span>
  <span style="color:#ff6633; font-weight:bold;">$ldapservice</span>       = <span style="color:#996600;">&quot;slapd&quot;</span>
  <span style="color:#ff6633; font-weight:bold;">$ldapdir</span>           = <span style="color:#996600;">&quot;/etc/ldap&quot;</span>
  <span style="color:#ff6633; font-weight:bold;">$ldaputilpackage</span>   = <span style="color:#996600;">&quot;ldap-utils&quot;</span>
  <span style="color:#ff6633; font-weight:bold;">$ldapclientpackage</span> = <span style="color:#996600;">&quot;libnss-ldap&quot;</span></pre></div></div>

<p>and use them like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  package <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#ff6633; font-weight:bold;">$ldappackage</span>:     <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed;
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  file <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;$ldapdir/slapd.conf&quot;</span>:
    content <span style="color:#006600; font-weight:bold;">=&gt;</span> template<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;ldap/slapd.conf.erb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>,
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> Package<span style="color:#006600; font-weight:bold;">&#91;</span>$ldappackage<span style="color:#006600; font-weight:bold;">&#93;</span>,
    notify  <span style="color:#006600; font-weight:bold;">=&gt;</span> Service<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;$ldapservice&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  service <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff6633; font-weight:bold;">$ldapservice</span>:
    <span style="color:#CC0066; font-weight:bold;">require</span>   <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> Package<span style="color:#006600; font-weight:bold;">&#91;</span>$ldappackage<span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#CC00FF; font-weight:bold;">File</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;$ldapdir/slapd.conf&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>,
    <span style="color:#9966CC; font-weight:bold;">ensure</span>    <span style="color:#006600; font-weight:bold;">=&gt;</span> running,
    enable    <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>,
  <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>These variables are set up for Debian now, because that is the distribution I&#8217;ve standardized on. If later I (or someone I&#8217;ve shared the module with) wants to add support for another distribution, they can set up case statements, and not have to modify the rest of the module!</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">case</span> <span style="color:#ff6633; font-weight:bold;">$operatingsystem</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
    debian: <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldappackage</span>       = <span style="color:#996600;">&quot;slapd&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldapservice</span>       = <span style="color:#996600;">&quot;slapd&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldapdir</span>           = <span style="color:#996600;">&quot;/etc/ldap&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldaputilpackage</span>   = <span style="color:#996600;">&quot;ldap-utils&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldapclientpackage</span> = <span style="color:#996600;">&quot;libnss-ldap&quot;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
    centos: <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldappackage</span>       = <span style="color:#996600;">&quot;openldap&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldapservice</span>       = <span style="color:#996600;">&quot;slapd&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldapdir</span>           = <span style="color:#996600;">&quot;/etc/openldap&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldaputilpackage</span>   = <span style="color:#996600;">&quot;openldap-utils&quot;</span>
      <span style="color:#ff6633; font-weight:bold;">$ldapclientpackage</span> = <span style="color:#996600;">&quot;libnss-ldap&quot;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p><em>I have not tested this, as I don&#8217;t use CentOS, so don&#8217;t use these!</em></p>
<h3>Break a module up into sensible classes and defined types to make it easy to customize via inheritance.</h3>
<p>Since you&#8217;ve pulled all the site-specific customization out of your package, and you are providing a minimal working configuration, people are going to want to do other things with your module that are appropriate to their site. If you have everything lumped into one big &#8220;ldap&#8221; class, this is going to be difficult for them. I break thinks up into <samp>ldap::common</samp> for things common to all the other classes, <samp>ldap::client</samp> for things needed to query the LDAP servers, <samp>ldap::master</samp> for the primary LDAP server, and later I&#8217;ll provide <samp>ldap::slave</samp> for replication slaves.</p>
<h3>Use <samp>init.pp</samp> for module-wide variables and/or common functionality, but break all other classes/defines into separate files.</h3>
<p>This is for your sanity as well as the sanity of those who might want to modify your module. I started with everything in one big <samp>init.pp</samp> file and it rapidly went out of control. Puppet does some awesome automagical lookups that you can take advantage of. For example, my <samp>ldap::master</samp> class is defined in a file called <samp>master.pp</samp>; when someone tries to load <samp>ldap::master</samp>, Puppet automatically searches for a <samp>.pp</samp> file named &#8220;master&#8221; in the &#8220;ldap&#8221; module!</p>
<p>So far, this is all the wisdom I have to impart on the subject. I&#8217;ll be sure to post links here when these modules are ready for prime-time.</p>
]]></content:encoded>
			<wfw:commentRss>http://plathrop.tertiusfamily.net/blog/2008/04/18/creating-puppet-modules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Puppet Modules and Apt</title>
		<link>http://plathrop.tertiusfamily.net/blog/2008/01/02/puppet-modules-and-apt/</link>
		<comments>http://plathrop.tertiusfamily.net/blog/2008/01/02/puppet-modules-and-apt/#comments</comments>
		<pubDate>Thu, 03 Jan 2008 00:15:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Puppet]]></category>
		<category><![CDATA[automation]]></category>

		<guid isPermaLink="false">http://plathrop.tertiusfamily.net/blog/?p=11</guid>
		<description><![CDATA[One of the most exciting features of Puppet is the way it enables the sharing of systems administration tools &#8211; &#8220;recipes&#8221; 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 [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most exciting features of Puppet is the way it enables the sharing of systems administration tools &#8211; &#8220;recipes&#8221; in the Puppet parlance. Puppet allows us to collect <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#manifest">manifests</a>, <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#definition">definitions</a>, and even <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#plugin-type">plugins</a> into <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#module">modules</a> which can then be shared with others.</p>
<p>David Schmitt is the author of the <a href="http://reductivelabs.com/trac/puppet/wiki/CompleteConfiguration">Complete Configuration</a> 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&#8217;s modules into your Puppet configuration one at a time. Today I&#8217;d like to show you how to use David&#8217;s <a href="http://git.black.co.at/?p=manifests.git;a=tree;f=modules/apt;hb=HEAD">apt module</a> to manage the dpkg &amp; apt databases, as well as the keyrings associated with them.</p>
<p>In order to get started with David&#8217;s modules, we&#8217;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&#8217;ll definitely want to keep up. Installing from source is easy enough. On Debian Etch, I used the following steps to install from source:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">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</pre></td></tr></table></div>

<p>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&#8217;t work after this, so I rolled my own.</p>
<p>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 <samp>[main]</samp> section of our <samp>puppet.conf</samp> file:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">  pluginsync = true
  pluginsource = puppet://$server/plugins</pre></div></div>

<p>You&#8217;ll want to create a &#8220;modules&#8221; subdirectory to store your modules in. According to the Puppet <a href="http://reductivelabs.com/trac/puppet/wiki/PuppetBestPractice#file-hierarchy">Best Practices</a> page, this directory should be in the same place as your &#8220;manifests&#8221; directory. For me, that means <samp>/etc/puppet</samp>:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">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</pre></div></div>

<p>Next, we&#8217;ll want to download the modules we wish to use. All of David&#8217;s modules depend on the &#8220;common&#8221; module, so we will want &#8220;common&#8221; and &#8220;apt&#8221;. David makes it easy to pull down each module independently. Here&#8217;s what I did:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">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</pre></td></tr></table></div>

<p>You should now have local copies of both the &#8220;common&#8221; module and the &#8220;apt&#8221; module. If you read the documentation, you will notice that these modules require the installation of the &#8220;lsb-release&#8221; package. I&#8217;m not sure why David doesn&#8217;t have the module install the package, but he doesn&#8217;t. So, let&#8217;s have puppet install it. A new &#8220;package&#8221; resource in our default node should do the trick:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>25
26
27
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  package <span style="color:#006600; font-weight:bold;">&#123;</span> sudo: <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed <span style="color:#006600; font-weight:bold;">&#125;</span>
  package <span style="color:#006600; font-weight:bold;">&#123;</span> lsb<span style="color:#006600; font-weight:bold;">-</span>release: <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></td></tr></table></div>

<p>Next, we need to integrate the new modules into our puppet configuration. Now that we&#8217;re getting into more complex configurations, we&#8217;ll want to start breaking our puppet configuration into separate files. In the same directory as <samp>site.pp</samp> (<samp>/etc/puppet/manifests</samp>), create a file called <samp>modules.pp</samp> containing:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">import “common”
import “apt”</pre></td></tr></table></div>

<p>As you add more modules, you&#8217;ll import them here.</p>
<p>We won&#8217;t be explicitly using the common module at this time, so all we need to do is add two lines to <samp>site.pp</samp>. At the top of the file, we&#8217;ll want:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">import modules.<span style="color:#9900CC;">pp</span></pre></td></tr></table></div>

<p>to pull in the file we just created. We also want to update the default node to make use of the apt module:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>7
8
9
10
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">node default <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> apt
&nbsp;
  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’:</pre></td></tr></table></div>

<p>It turns out that David&#8217;s modules also depend on a <a href="http://reductivelabs.com/trac/puppet/wiki/TypeReference#filebucket">filebucket</a>  resource named &#8220;server&#8221;. This is a site-wide resource, so <samp>site.pp</samp> is the ideal place to put it:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>3
4
5
6
7
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">filebucket <span style="color:#006600; font-weight:bold;">&#123;</span> server:
  server <span style="color:#006600; font-weight:bold;">=&gt;</span> “server1.<span style="color:#9900CC;">example</span>.<span style="color:#9900CC;">com</span>”
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
node default <span style="color:#006600; font-weight:bold;">&#123;</span></pre></td></tr></table></div>

<p>After all these modifications, our <samp>site.pp</samp> looks like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>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
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">import modules.<span style="color:#9900CC;">pp</span>
&nbsp;
filebucket <span style="color:#006600; font-weight:bold;">&#123;</span> server:
  server <span style="color:#006600; font-weight:bold;">=&gt;</span> “server1.<span style="color:#9900CC;">example</span>.<span style="color:#9900CC;">com</span>”
<span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
node default <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> apt
&nbsp;
  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’:
    owner <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    group <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    mode <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">644</span>,
    source <span style="color:#006600; font-weight:bold;">=&gt;</span> ‘puppet:<span style="color:#006600; font-weight:bold;">///</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>etc<span style="color:#006600; font-weight:bold;">/</span>sudoers’:
    owner <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    group <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    mode <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">440</span>,
    source <span style="color:#006600; font-weight:bold;">=&gt;</span> ‘puppet:<span style="color:#006600; font-weight:bold;">///</span>etc<span style="color:#006600; font-weight:bold;">/</span>sudoers’
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> Package<span style="color:#006600; font-weight:bold;">&#91;</span>“sudo”<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  package <span style="color:#006600; font-weight:bold;">&#123;</span> sudo: <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed <span style="color:#006600; font-weight:bold;">&#125;</span>
  package <span style="color:#006600; font-weight:bold;">&#123;</span> lsb<span style="color:#006600; font-weight:bold;">-</span>release: <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></td></tr></table></div>

<p>I had to do one more thing to get this to really work. Reading through David&#8217;s module, you would expect <samp>/var/lib/puppet/modules/apt</samp> to be created by Puppet. Unfortunately, this doesn&#8217;t seem to happen. I had to create this directory by hand. I&#8217;ll let you know if/when I figure out why.</p>
<p>For basic usage of the module, this is all you need! David&#8217;s module defaults to a very sane basic apt configuration. The only tweak I felt was necessary was a modification to <samp>modules/apt/templates/sources.list.erb</samp> to use a US Debian mirror. You can modify this file to your liking for your default <samp>sources.list</samp>. You can also use the <samp>$custom_sources_list</samp> variable in a node definition to provide a customized file for a specific node:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">node “oddball.<span style="color:#9900CC;">example</span>.<span style="color:#9900CC;">com</span>” <span style="color:#006600; font-weight:bold;">&#123;</span>
  <span style="color:#ff6633; font-weight:bold;">$custom_sources_list</span> = “<span style="color:#008000; font-style:italic;">#This box is located in Canada, so use a local mirror</span>
deb http:<span style="color:#006600; font-weight:bold;">//</span>ftp.<span style="color:#9900CC;">ca</span>.<span style="color:#9900CC;">debian</span>.<span style="color:#9900CC;">org</span><span style="color:#006600; font-weight:bold;">/</span>debian etch main contrib non<span style="color:#006600; font-weight:bold;">-</span>free
deb http:<span style="color:#006600; font-weight:bold;">//</span>security.<span style="color:#9900CC;">debian</span>.<span style="color:#9900CC;">org</span><span style="color:#006600; font-weight:bold;">/</span> etch<span style="color:#006600; font-weight:bold;">/</span>updates main contrib non<span style="color:#006600; font-weight:bold;">-</span>free” <span style="color:#9966CC; font-weight:bold;">include</span> “apt”
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>David has a number of other modules I&#8217;d like to try; as I get them working I&#8217;ll be sure to share my experiences here.<code></code></p>
]]></content:encoded>
			<wfw:commentRss>http://plathrop.tertiusfamily.net/blog/2008/01/02/puppet-modules-and-apt/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Clarification</title>
		<link>http://plathrop.tertiusfamily.net/blog/2007/12/15/clarification/</link>
		<comments>http://plathrop.tertiusfamily.net/blog/2007/12/15/clarification/#comments</comments>
		<pubDate>Sun, 16 Dec 2007 05:55:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Puppet]]></category>

		<guid isPermaLink="false">http://plathrop.tertiusfamily.net/blog/?p=12</guid>
		<description><![CDATA[As I write these entries about Puppet I want to make it clear that the configurations I post may not necessarily be &#8220;best practices&#8221;. I am attempting to follow a logical evolution of steps involved in becoming familiar with Puppet. As the configuration grows more complex I will introduce the various best practices which make [...]]]></description>
			<content:encoded><![CDATA[<p>As I write these entries about Puppet I want to make it clear that the configurations I post may not necessarily be &#8220;best practices&#8221;. I am attempting to follow a logical evolution of steps involved in becoming familiar with Puppet. As the configuration grows more complex I will introduce the various best practices which make complex Puppet configurations manageable. If you are looking to dive straight in to a fully-realized puppet configuration, take a look at the <a href="http://reductivelabs.com/trac/puppet/wiki/CompleteConfiguration">Complete Configuration</a> page of the Puppet wiki.</p>
]]></content:encoded>
			<wfw:commentRss>http://plathrop.tertiusfamily.net/blog/2007/12/15/clarification/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Managing sudoers With Puppet</title>
		<link>http://plathrop.tertiusfamily.net/blog/2007/12/15/managing-sudoers-with-puppet/</link>
		<comments>http://plathrop.tertiusfamily.net/blog/2007/12/15/managing-sudoers-with-puppet/#comments</comments>
		<pubDate>Sun, 16 Dec 2007 05:45:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Puppet]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[Philosophy]]></category>
		<category><![CDATA[sudo]]></category>

		<guid isPermaLink="false">http://plathrop.tertiusfamily.net/blog/?p=13</guid>
		<description><![CDATA[In my last post, I described how to distribute an SSH authorized_keys file using Puppet. My reasoning for this was to help us utilize our existing set of home-grown scripts to administer machines &#8211; with Puppet we don&#8217;t have to wonder if our keys are set up on every host. Well, I&#8217;m sure a few [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post, I described how to distribute an SSH authorized_keys file using Puppet. My reasoning for this was to help us utilize our existing set of home-grown scripts to administer machines &#8211; with Puppet we don&#8217;t have to wonder if our keys are set up on every host. Well, I&#8217;m sure a few of you spotted the flaw in this. Most of us have learned not to run scripts as root when it isn&#8217;t necessary. Instead we use sudo to grant limited root powers for specific commands. Sudo is a well-designed piece of software; it&#8217;s configuration file, the sudoers file, is setup in such a way that the same sudoers file may be used on many machines. This makes it ripe for management in Puppet.</p>
<p>Building on top of the configuration we created in my last post, here is the <samp>site.pp</samp> manifest after adding sudo to the mix:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">node default <span style="color:#006600; font-weight:bold;">&#123;</span>
  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’:
    owner <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    group <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    mode <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">644</span>,
    source <span style="color:#006600; font-weight:bold;">=&gt;</span> ‘puppet:<span style="color:#006600; font-weight:bold;">///</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>etc<span style="color:#006600; font-weight:bold;">/</span>sudoers’:
    owner <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    group <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    mode <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">440</span>,
    source <span style="color:#006600; font-weight:bold;">=&gt;</span> ‘puppet:<span style="color:#006600; font-weight:bold;">///</span>etc<span style="color:#006600; font-weight:bold;">/</span>sudoers’
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> Package<span style="color:#006600; font-weight:bold;">&#91;</span>“sudo”<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  package <span style="color:#006600; font-weight:bold;">&#123;</span> sudo: <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></td></tr></table></div>

<p>The first definition is mostly familiar; we defined a file resource like it last time. There is something new here, however:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>14
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> Package<span style="color:#006600; font-weight:bold;">&#91;</span>“sudo”<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span></pre></td></tr></table></div>

<p>The <samp>require</samp> parameter describes a dependency. Before this resource is applied, Puppet will look for a <a href="http://reductivelabs.com/trac/puppet/wiki/TypeReference#package">package resource</a> with the name &#8220;sudo&#8221; and apply that resource first. Next we define that package resource:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>17
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  package <span style="color:#006600; font-weight:bold;">&#123;</span> sudo: <span style="color:#9966CC; font-weight:bold;">ensure</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> installed <span style="color:#006600; font-weight:bold;">&#125;</span></pre></td></tr></table></div>

<p>All we want is to make sure that sudo is installed. Perhaps the coolest part of this is that it doesn&#8217;t matter that I am using Debian here, Puppet supports a wide range of package systems under the hood, and it will choose the one most appropriate for the system it is configuring. If I add a FreeBSD machine to my network, I should not have to make any changes to my Puppet configuration &#8211; I can still depend on sudo getting installed!</p>
<p>Next, we need to add an <samp>etc</samp> mount to our Puppet fileserver. Here is the resulting <samp>fileserver.conf</samp>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">[root]
  path /etc/puppet/files/root
  allow 10.0.0.0/8
&nbsp;
[etc]
  path /etc/puppet/files/etc
  allow 10.0.0.0/8</pre></td></tr></table></div>

<p>Put your sudoers file in <samp>/etc/puppet/files/etc</samp> and wait for your clients to check in with <samp>puppetmasterd</samp>. Alternately, you can log in to a client and run <samp>puppetd &#8211;test</samp> to pull down the new configuration. If sudo was not installed, it should be, and <samp>/etc/sudoers</samp> will be downloaded as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://plathrop.tertiusfamily.net/blog/2007/12/15/managing-sudoers-with-puppet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Started With Puppet</title>
		<link>http://plathrop.tertiusfamily.net/blog/2007/12/13/getting-started-with-puppet/</link>
		<comments>http://plathrop.tertiusfamily.net/blog/2007/12/13/getting-started-with-puppet/#comments</comments>
		<pubDate>Thu, 13 Dec 2007 09:27:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Puppet]]></category>
		<category><![CDATA[automation]]></category>

		<guid isPermaLink="false">http://plathrop.tertiusfamily.net/blog/?p=14</guid>
		<description><![CDATA[In my last post I mentioned Puppet. If you are a systems administrator and you haven&#8217;t taken a look at Puppet, stop reading and go look.
No, really. Open a new tab and head over to the About Puppet page of the Puppet wiki. Because Puppet is one of those tools which will utterly change the [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post I mentioned <a href="http://puppet.reductivelabs.com">Puppet</a>. If you are a systems administrator and you haven&#8217;t taken a look at Puppet, stop reading and go look.</p>
<p>No, really. Open a new tab and head over to the <a href="http://reductivelabs.com/trac/puppet/wiki/AboutPuppet">About Puppet</a> page of the Puppet wiki. Because Puppet is one of those tools which will <em>utterly change the way you work</em>.</p>
<p>Puppet can be described in many ways, but the most accurate (and powerful) way to think about it is as a language for describing systems. In fact, Puppet may end up redefining the term &#8220;systems programming&#8221; completely. Puppet provides the toolkit you need to build the Holy Grail of systems administration: the all-powerful, all-important, but seldom-realized <a href="http://en.wikipedia.org/wiki/CMDB">Configuration Management Database</a>!</p>
<p>Now that you are rolling your eyes and muttering under your breath, thinking you&#8217;ve heard this all before, I&#8217;d like to show you what Puppet can actually do. I think you will be pleasantly surprised&#8230;</p>
<p>In general usage, Puppet is a client/server application. Puppet clients running <samp>puppetd</samp> periodically contact a Puppet server running <samp>puppetmasterd</samp>. Puppet can also be used in stand-alone mode with the <samp>puppet</samp> command-line utility, but we&#8217;ll have to come back to that in a later post. For now, we need to get Puppet installed before we can move on to the good stuff.</p>
<p>I&#8217;m using Puppet to manage a number of Debian Etch servers. Some of these servers are virtualized Xen instances (domUs), the rest are the Xen hosts (dom0s). Lucky for me, Puppet is available as a Debian package. Unfortunately, like many Debian packages, the package is lagging behind the rather rapid release cycle of Puppet. However, the Puppet team has provided excellent instructions on <a href="http://reductivelabs.com/trac/puppet/wiki/DebianUnstablePackages">installing Puppet from the &#8220;Unstable&#8221; release</a> of Debian. These instructions worked perfectly for me and I was able to install Puppet 0.23.2, which is fairly up-to-date.</p>
<p>If you aren&#8217;t using Debian, take a look at the <a href="http://reductivelabs.com/trac/puppet/wiki/InstallationGuide">Installation Guide</a> &#8211; I can&#8217;t vouch for the instructions for other platforms, but the documentation, where it exists, is generally excellent.</p>
<p>With my experience in setting up Puppet, I recommend setting up a dedicated server or virtualized system and calling it <samp>puppet.example.com</samp> (substituting your domain for <samp>example.com</samp>, of course!). There are several reasons for this. First, Puppet clients default to connecting to the host <samp>puppet</samp> in the domain which matches their assigned FQDN. Second, Puppet uses SSL certificates to secure communication between the clients and the server, and the certificates <samp>puppetmasterd</samp> will generate will use a CN corresponding to the system&#8217;s FQDN. This means if you install <samp>puppetmasterd</samp> on <samp>server1.example.com</samp> with an appropriate CNAME in DNS, clients who attempt to connect will get a certificate mismatch error. There is a way around this, but I think it is easier to just set up a new machine if you have the luxury. Last, this system will have an inordinate amount of power over your network, so you want to make sure it is as secure as you can make it &#8211; this suggests a dedicated system. That being said, I went another route and installed Puppet on an existing admin machine.</p>
<p>So, choose a server which will act as your &#8220;Puppetmaster&#8221; and install <samp>puppet</samp> and <samp>puppetmaster</samp> (or whatever the packages are called on your platform). At this point, you won&#8217;t be able to start either Puppet daemon; <samp>puppetmasterd</samp> requires a minimal &#8220;manifest&#8221; before it can function (we&#8217;ll discuss the term &#8220;manifest&#8221; in a moment), and <samp>puppetd</samp> requires a working <samp>puppetmasterd</samp> to talk to!</p>
<p>&#8220;What, exactly, is a manifest?&#8221; I hear you say. I could refer you to the <a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#manifest">Glossary of Terms</a> on the Puppet wiki, but I think a little more explanation is in order. A manifest is nothing more or less than a description, written in the Puppet language, of one or more possibly interconnected and inter-related systems. The Puppet language allows us to fully describe many of the &#8220;nouns&#8221; of systems administration in such a way as to specify the configuration required to create a functioning system.</p>
<p>I have a very specific reason for describing manifests from such a high-level perspective. See, as I mentioned above, Puppet has the potential to change the way systems administration is done; it requires a different perspective to really leverage that potential &#8211; you have to begin thinking in terms of high-level concepts instead of low-level details of command-line arguments and configuration file formats. Yes, these details will (probably) always be <em>part</em> of systems administration (especially while you are still becoming comfortable with Puppet), but the high-level approach gives you the power to step back and deal with systems at a policy level.</p>
<p>Before you can write a manifest, you need to consider a system. By system, I don&#8217;t mean a server, I mean a collection of concepts which encapsulate some functionality on your network. The first system I considered was the SSH <samp>authorized_keys</samp> file. The &#8220;old way&#8221; of doing systems administration usually involves a number of home-grown scripts run over SSH using public-key authentication (so we don&#8217;t have to type the root password 100 times!). Since I like to make small, incremental changes when I move to a new way of doing something, I thought &#8220;Let&#8217;s see if puppet can make it easier to do my normal style of administration.&#8221; I wrote this simple manifest to do that:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">node default <span style="color:#006600; font-weight:bold;">&#123;</span>
  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’:
    owner <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    group <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
    mode <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">644</span>,
    source <span style="color:#006600; font-weight:bold;">=&gt;</span> ‘puppet:<span style="color:#006600; font-weight:bold;">///</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’
  <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></td></tr></table></div>

<p>I put this into <samp>/etc/puppet/manifests/site.pp</samp> (This file is the starting point for puppet, and we&#8217;ll be changing it a lot in later posts). Let&#8217;s work through this file line by line:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">node default <span style="color:#006600; font-weight:bold;">&#123;</span></pre></td></tr></table></div>

<p>tells Puppet that this manifest applies to all nodes (the special node name &#8220;default&#8221; is applied to all client nodes which contact <samp>puppetmasterd</samp> and do not have a specific node defined for their fqdn).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>2
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  file <span style="color:#006600; font-weight:bold;">&#123;</span> ‘<span style="color:#006600; font-weight:bold;">/</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’:</pre></td></tr></table></div>

<p>tells Puppet that we are defining a &#8220;<a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#resource">resource</a>&#8221; of the native type &#8220;<a href="http://reductivelabs.com/trac/puppet/wiki/TypeReference#file">file</a>&#8220;. This resource is named <samp>/root/.ssh/authorized_keys</samp>. The built-in types all do logical things with the name of the resource; in this case, the <samp>path</samp> parameter of the file will be taken from the name. The colon at the end of the line is a bit of syntax.</p>
<p>The next several lines all define &#8220;<a href="http://reductivelabs.com/trac/puppet/wiki/GlossaryOfTerms#parameter">parameters</a>&#8221; of the file type. These parameters are the adjectives of Puppet, they help describe the object which Puppet handles. The first three parameters are fairly self-explanatory:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>3
4
5
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  owner <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
  group <span style="color:#006600; font-weight:bold;">=&gt;</span> root,
  mode <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">644</span>,</pre></td></tr></table></div>

<p>Indicates that this file (<samp>/root/.ssh/authorized_keys</samp>) should be owned by <samp>root</samp>, group ownership should be <samp>root</samp>, and the permissions should be <samp>644</samp>. I took these settings from the existing authorized_keys file on hosts I already manage with SSH and public-key authentication.</p>
<p>The last line of this manifest is where things get a little more interesting.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>6
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  source <span style="color:#006600; font-weight:bold;">=&gt;</span> ‘puppet:<span style="color:#006600; font-weight:bold;">///</span>root<span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">ssh</span><span style="color:#006600; font-weight:bold;">/</span>authorized_keys’</pre></td></tr></table></div>

<p>The <samp>source</samp> parameter tells Puppet where to find this file. This can be a fully-qualified filesystem path or a URI. The documentation is unclear about which URI types are supported &#8211; it says only <samp>puppet://</samp> URIs are supported, but mailing list traffic suggests <samp>http://</samp> is supported as well. In any case, the <samp>puppet://</samp> URI type tells <samp>puppetd</samp> to request the file from the <samp>puppetmasterd</samp> server. The file is copied into the specified location, then ownership and permissions are set.</p>
<p>Suddenly, every Puppet client you configure will have the same <samp>authorized_keys</samp> file for root! This makes those homegrown admin scripts a bit more reliable, because you can count on your SSH key being authorized on every host. (Once you set up Puppet, that is&#8230;)</p>
<p>Let&#8217;s not get ahead of ourselves. How does <samp>puppetmasterd</samp> know which file to give out? On Debian, the Puppet file server is configure in <samp>/etc/puppet/fileserver.conf</samp>. Here&#8217;s one that will work for the manifest above:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">[root]
  path /etc/puppet/files/root
  allow 10.0.0.0/8</pre></td></tr></table></div>

<p>You will need to substitute your own network address in the <samp>allow</samp> statement, of course.</p>
<p>This configuration exports the path <samp>/etc/puppet/files/root</samp> at the URI <samp>puppet:///root</samp>. Simply make a subdirectory <samp>.ssh</samp> and place the master <samp>authorized_keys</samp> file you want distributed into that directory, and you&#8217;re all set to configure your first Puppet client.</p>
<p>When you choose a system to be your first Puppet client, don&#8217;t choose the same system you are using as a &#8220;Puppet Master&#8221;. There are a couple of gotchas that confuse the issue of managing the local machine. They aren&#8217;t complex, but they&#8217;re irritating enough to skip over while you first experiment. If you are using Xen, just provision another VM and install Puppet on it!</p>
<p>If you followed my advice and set up a dedicated system named <samp>puppet.example.com</samp>, once you install Puppet, you can skip straight to the certificate signing. If you didn&#8217;t, you&#8217;ll need one extra step. On Debian, the file <samp>/etc/puppet/puppet.conf</samp> controls certain default options for the various Puppet binaries. Add this to your <samp>puppet.conf</samp> file:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="text" style="font-family:monospace;">[puppetd]
  server=server1.example.com</pre></td></tr></table></div>

<p>Substitute the name of your Puppet master server for <samp>server1.example.com</samp></p>
<p>Next, on the Puppet client, issue the command <samp>puppetd &#8211;test</samp> (You&#8217;ll run this as root). You&#8217;ll get a fairly informative message which indicates that you haven&#8217;t got a certificate configured yet. This is okay. On the Puppet master, issue the command <samp>puppetca &#8211;list</samp>. This command lists the pending certificate requests for Puppet. You should see the FQDN of your puppet client there. I leave it as an excercise to the reader to do due diligence on this signing request, once you feel good about it, sign the certificate on the Puppet master by issuing the command <samp>puppetca &#8211;sign <em>client_fqdn</em></samp>. Back on the client, issue <samp>puppetd &#8211;test</samp> again. You should see some messages describing in detail how puppet is changing your machine. Once this is done, take a look at <samp>/root/.ssh/authorized_keys</samp>. If you aren&#8217;t drooling over the potential of Puppet at this point, I&#8217;m shocked.</p>
<p>Puppet can do a lot more than I&#8217;ve discussed here. This is just a small sample, meant to get you thinking. I&#8217;ll be writing more about my experiences with Puppet, as well as discussing best practices, a maintainable configuration, and more about how Puppet can change your conceptions of systems administration, in future posts.</p>
]]></content:encoded>
			<wfw:commentRss>http://plathrop.tertiusfamily.net/blog/2007/12/13/getting-started-with-puppet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
