Puppet: System Administration Automated

Puppet Training Schedule
Next Class July 27-29
New York, New York
Discount before July 1st

Frequently Asked Questions

Table of Contents

Contents


General

What is Puppet?

Puppet is an open-source next-generation server automation tool. It is composed of a declarative language for expressing system configuration, a client and server for distributing it, and a library for realizing the configuration.

The primary design goal of Puppet is that it have an expressive enough language backed by a powerful enough library that you can write your own server automation applications in just a few lines of code. With Puppet, you can express the configuration of your entire network in one program capable of realizing the configuration. The fact that Puppet has open source combined with how easily it can be extended means that you can add whatever functionality you think is missing and then contribute it back to the main project if you desire.

For more about the capabilities of Puppet, take a look at the documentation. [back]

Who maintains this FAQ and where can I find an updated version?

This FAQ is maintained by wiki at Reductive Labs. Please send comments, additions, omissions, and errors to:

faq at reductivelabs dot com

The official version of the FAQ is maintained here.

[back]

What license is Puppet released under?

Puppet is open source and is released under the GNU Public License. [back]

Why does Puppet exist?

Luke Kanies, who founded Reductive Labs, has been doing server automation for years, and Puppet is the result of his frustration with existing tools. After significant effort spent trying to enhance cfengine, plus a stint at a commercial server automation vendor, Luke concluded that the only way to get a great automation tool was to develop one.

Puppet is actually the result of years of design and prototyping (called Blink during its prototype phases), but only in 2005 was a commercial company (Reductive Labs) built to be fully dedicated to its creation. If Puppet is not the most powerful and most flexible server automation platform available, then its goals are not being met. [back]

Why does Puppet have its own language?

This actually is a frequently asked question, and people most often ask why I did not choose to use something like XML or YAML as the configuration format; otherwise people ask why I didn't just choose to just use Ruby as the input language.

The input format for Puppet is not XML or YAML because these are data formats developed to be easy for computers to handle. They do not do conditionals (although, yes, they support data structures that could be considered conditionals), but mostly, they're just horrible human interfaces. While some people are comfortable reading and writing them, there's a reason why we use web browsers instead of just reading the HTML directly. Also, using XML or YAML would limit the ability to make sure the interface is declarative -- one process might treat an XML configuration differently from another.

As to just using Ruby as the input format, that unnecessarily ties Puppet to Ruby, which is undesirable, and Ruby provides a bit too much functionality. For more detail, see the thread on the puppet-dev list. [back]

Why is Puppet written in Ruby?

From Luke Kanies, Puppet's author: I was a sysadmin by trade and had mostly developed in perl, but when I tried to write the prototype I had in mind, I couldn't get the class relationships I wanted in perl. I tried Python, because this was around 2003 and Python was the next new thing and everyone was saying how great it is, but I just can't seem to write in Python at all. A friend had said he'd heard Ruby was cool, so I gave it a try, and in four hours I went from never having seen a line of it to having a working prototype. I haven't looked back since then, and haven't regretted the choice.

[back]

How does Puppet compare to cfengine?

Puppet could be said to be the next-generation cfengine. The overall design is heavily influenced by cfengine, but the language is more powerful than cfengine's and the library is more flexible. In addition, Puppet's client and server use standard protocols like XMLRPC and are easy to enhance with new functionality, so they are well-positioned to become the platform for the network applications of the future, while cfengine's client and server rely entirely on cfengine-specific protocols and are quite difficult to enhance.

See How Puppet Compares to Cfengine for more information. [back]

How does Puppet compare to available commercial products?

The primary commercial vendors are BladeLogic and OpsWare. While they both have useful product lines, Puppet surpasses them by re-framing the entire server automation problem -- while the commercial vendors are writing GUI applications for you, Reductive Labs is providing a development platform with all the features of a great language, like library development, code sharing, and the ability to version control your configurations.

Trying to express a complex network configuration entirely through a GUI is an exercise in frustration that no one should suffer, but expressing the abstraction necessary to share those GUI configurations goes beyond frustrating.

Of course, another great difference between Puppet and the commercial products is that Puppet is open sourced under the GNU Public License. You can download the product, try it out, peruse the source, and make whatever modifications you want. You have to have more than 100 servers just to get a demo from the commercial vendors, but Puppet is available for testing by any company that needs to reduce its server administration costs. [back]

Who would find Puppet useful?

Any organization that would like to reduce the cost of maintaining its computers could benefit from using Puppet. However, because the return on investment is linked to multiple factors, like current administrative overhead, diversity among existing computers, and cost of downtime, it can be difficult for organizations to determine whether they should invest in any configuration management tools, much less Puppet. Reductive Labs can always be contacted directly at info at reductivelabs.com to help answer this question.

Generally, however, an organization should be using server automation if any of the following are true:

  • It has high server administration costs
  • It pays a high price for downtime, either because of contracts or opportunity cost
  • It has many servers that are essentially either identical or nearly identical
  • Flexibility and agility in server configuration are essential

[back]

Can Puppet manage workstations?

Yes, Puppet can manage any type of machine. We have found that most organizations are more concerned with server management than workstation management, and frankly, the term 'server' is slightly more aesthetically appealing than 'computer', but Puppet would be ideal for organizations with a large number of workstations. [back]

Does Puppet run on Windows?

The short answer is 'not yet'. It will eventually, but Reductive Labs does not yet have the development bandwidth to make this work. [back]

What size organizations should use Puppet?

There is no minimum or maximum organization size that can benefit from Puppet, but there are sizes that are more likely to benefit. Organizations with fewer than 10-20 servers are unlikely to consider maintaining those servers to be a real problem, and thus they can avoid investment in tools even though those tools could likely provide savings.

There is no real upper limit to who could benefit from using Puppet. Obviously as the server count increases the investment must increase somewhat, but with Puppet that increase is not linear. [back]

My servers are all unique; can Puppet still help?

All servers are at least somewhat unique -- with different host names and different IP addresses -- but very few servers are entirely unique, since nearly every one runs a relatively standard operating system. Servers are also often very similar to other servers within a single organization -- all Solaris servers might have similar security settings, or all web servers might have roughly equivalent configurations -- even if they're very different from servers in other organizations. Finally, servers are often needlessly unique, in that they have been built and managed manually with no attempt at retaining appropriate consistency.

Puppet can help both on the side of consistency and uniqueness. Puppet can be used to express the consistency that should exist, even if that consistency spans arbitrary sets of servers based on any type of data like operating system, data centre, or physical location. Puppet can also be used to handle uniqueness, either by allowing special provision of what makes a given host unique or through specifying exceptions to otherwise standard classes. [back]

Where can I get Puppet?

You can always find the latest release in the download directory. Currently, puppet is being tracked on Freshmeat, and RubyForge. [back]

When is the Next Release?

There are regular feature and release updates on the Mailing List, and you can always find the latest release in the download directory. [back]

Who is Reductive Labs?

Reductive Labs is a small, private company focused on re-framing the server automation problem. Our primary focus is Puppet, but Reductive Labs also provides automation consulting, training, and custom development. For more information email info at reductivelabs.com.

The Projects page lists our active projects. [back]

How do I contribute?

Firstly, join one or both of the Mailing Lists. There is currently a development list , and a user discussion list as well. You can also join the IRC channel #puppet on irc.freenode.net, where Puppet's developers will be hanging out most days (and nights).

If you are interested in helping with Puppet's development you can read about how it is developed and how to submit patches and fixes on the Development Lifecycle wiki page.

The most valuable contribution you can make, though, is to use Puppet and submit your feedback, either directly on IRC or through the mailing list, or by reporting to the bug database. We're always looking for great ideas to incorporate into Puppet. [back]


Installation

How Do I Install Puppet?

The Installation Guide documents the fastest way to start using Puppet. [back]

What's The Minimum Version of Ruby?

Puppet is supported on all versions of Ruby from 1.8.2 on up. It will sometimes work on 1.8.1, but it's not supported on that release.


Upgrading

Should I upgrade the client or server first?

When upgrading to a new version of Puppet, always upgrade the server first. Old clients can point at a new server but you may have problems when pointing a new client at an old server. [back]

How should I upgrade Puppet & Facter?

The best way to install and to upgrade Puppet and Facter is via your operating system's package management system. This is easier than installing them from source. If you do install them from source make sure you remove old versions including all application and library files (excepting configuration in /etc/puppet obviously) entirely before upgrading. [back]


Configuration

What is a Manifest?

Because the word script implies a procedural one-step-after-another program, the word does not apply well to Puppet programs. Thus, we use the word manifest to describe declarative Puppet programs. Speaking of applying, Puppet applies a manifest to a server or a network, rather than executing it. [back]

How Do I Write Manifests?

The best way is to download Puppet and just start writing. There are multiple sets of examples, including the examples used in unit testing and publicly available modules, and the reference will obviously be useful. [back]

What characters are permitted in a class name?

Alphanumeric and hyphen '-', nothing else. If you intend on using qualified variables, don't use hyphen. [back]

How Do I Run Manifests?

Once you have Puppet installed according the the Installation Guide, just run the puppet executable against your example:

puppet -v example.pp

[back]

How do I document my manifests?

Using some simple documentation syntax (which you can see on the PuppetManifestDocumentation Wiki page) and the puppetdoc command you can generate automated documentation in RDoc or HTML for your manifests and modules.

[back]

How do I manage passwords on Red Hat Enterprise Linux & Fedora Core?

As described in the TypeReference you need the Shadow Password Library, this is provided by the ruby-shadow package. The ruby-shadow library is available natively for fc6 (and higher) and should build on the RHEL and CentOS variants that match.

[back]

How do I use Puppet's graphing support?

Puppet has graphing support capable of creating graph files of your Puppet client configurations. The graphs are created by and on the client, so you must enable graphing on the client. This will create files in dot format in the client's graphdir; these files are text files and need to be interpreted by another application to get turned into images. The easiest way to do this is to use OmniGraffle, since it automatically converts them to attractive graphs, but it only runs on OS X. You can also install graphviz, which comes with the dot application, which you can use to turn the text files into images:

dot -Tpng /var/puppet/state/graphs/resources.dot -o /tmp/configuration.png

[back]

How do all of these variables, like $operatingsystem, get set?

The variables are all set by Facter. You can get a full listing of the available variables and their values by running facter by itself in a shell.:

# facter

[back]

Can I access environmental variables with Facter?

Not directly no but Facter has a special types of facts that can be set from environment variables. Any environment variable with a prefix of FACTER will be taken by Facter and converted into a fact, for example:

$ FACTER_FOO="bar"
$ export FACTER_FOO
$ facter | grep 'foo'
  foo => bar

The value of the FACTER_FOO environmental variable would now be available in your Puppet manifests as $foo with a value of 'bar'.

[back]


Techniques

How Can I Manage Whole Directories of Files Without Explicitly Listing the Files?

The file type has a parameter recurse which can be used to synchronize the contents of a target directory recursively with a chosen source. In the example below, the entire /etc/httpd/conf.d directory is synchronized recursively with the copy on the server:

file { "/etc/httpd/conf.d":
  source => "puppet://server/vol/mnt1/adm/httpd/conf.d",
  recurse => "true"
}

[back]

I Want To Manage A Directory and Purge Its Contents

Many people try to do something like this:

file { "/etc/nagios/conf.d":
  owner   => nagios,
  group   => nagios,
  purge   => true,
  recurse => true,
  force   => true,
}

It seems what most people expect to happen here is create the named directory, set the owner and group, then purge any files or directories that are not managed by puppet underneath that. But this is not the behaviour puppet will display. In fact the purge will silently fail.

The workaround is to define a source for the directory that doesn't exist.

file { "/etc/nagios/conf.d":
   owner   => nagios,
   group   => nagios,
   purge   => true,
   recurse => true,
   force   => true,
   source  => "puppet:///nagios/emtpy",
}

The fileserver context (here 'nagios') must exist and be created by the fileserver and an empty directory must also exist, and puppet will purge the files as expected.

[back]

How Do I Run a Command Whenever A File Changes?

The answer is to use an exec resource with refreshonly set to true, such as in this case of telling bind to reload its configuration when it changes:

file { "/etc/bind": source => "/dist/apps/bind" }

exec { "/usr/bin/ndc reload":
  subscribe => File["/etc/bind"],
  refreshonly => true
}

The exec has to subscribe to the file so it gets notified of changes.

[back]

How Can I Ensure a Group Exists Before Creating a User?

In the example given below, we'd like to create a user called tim who we want to put in the fearme group. By using the require parameter, we can create a dependency between the user tim and the group fearme. The result is that user tim will not be created until puppet is certain that the fearme group exists.

group { "fearme":
        ensure => present,
        gid => 1000
}
user { "tim":
        ensure => present,
        gid => "fearme",
        groups => ["adm", "staff", "root"],
        membership => minimum,
        shell => "/bin/bash",
        require => Group["fearme"]
}

Note that Puppet will set this relationship up for you automatically, so you should not normally need to do this.

[back]

How Can I Require Multiple Resources Simultaneously?

In the example given below, we're again adding the user tim (just as we did earlier in this document), but in addition to requiring tim's primary group, fearme, we're also requiring another group, fearmenot. Any reasonable number of resources can be required in this way.

user { "tim":
        ensure => present,
        gid => "fearme",
        groups => ["adm", "staff", "root", "fearmenot"],
        membership => minimum,
        shell => "/bin/bash",
        require => [ Group["fearme"],
                            Group["fearmenot"]
                          ]
        }

[back]

Can I use complex comparisons in if statements and variables?

In Puppet version 0.24.6 onwards you can use complex expressions in if statements and variable assignments. You can see examples of how to do this in the Language Tutorial.

In versions prior to 0.24.6 Puppet does not support complex conditionals: if can only test for the existence of a variable, and case can only switch on a defined string.

However, a workaround is possible by using the generate() function to call out to Ruby or Perl to perform the comparison, eg:

if generate('/usr/bin/env', 'ruby', '-e', 'puts :true if eval ARGV[0]', "'$operatingsystem' =~ /redhat/") {
     # do stuff
}

The Perl equivalent is:

if generate('/usr/bin/env', 'perl', '-e', 'print("true") if (eval shift)', "'$operatingsystem' =~ /redhat/") {
     # do stuff
}

Note that the generate() function is executed on the Puppet master at manifest compilation, so cannot be used client-side. Also note the quoting around the final option - this is to ensure that $operatingsystem variable is interpolated by the parser and passed to the Ruby or Perl interpreter as a string.

[back]

Can I output Facter facts in YAML?

Facter supports output of facts in YAML as well as to standard out. You need to run:

# facter --yaml

To get this output, which you can redirect to a file for further processing.

[back]

Troubleshooting

Why hasn't my new node configuration been noticed?

If you're using separate node definition files and import them into site.pp with an import *.node (for example) you'll find that new files added won't get noticed until you restart puppetmasterd. This is due to the fact globs aren't evaluated on each run, but only when the 'parent' file is re-read.

To make sure your new file is actually read, simply 'touch' the site.pp (or importing file) and the glob will be re-evaluated.

[back]

Why don't my certificates show as waiting to be signed on my server when I do a "puppetca --list"?

puppetca must be run as root. If you are not root then rerun the command with sudo:

sudo puppetca --list

[back]

I keep getting "certificates were not trusted". What's wrong?

Firstly, if you're re-installing a machine, you probably haven't cleared the previous certificate for that machine. Run "puppetca --clean <fqdn>" on the Puppetmaster to clear the certificates, and remove the entire SSL directory of the client machine (/etc/puppet/ssl) to correct the problem.

Assuming that you're not re-installing, by far the most common cause of SSL problems is that the clock on the client machine is set incorrectly, which confuses SSL because the "validFrom" date in the certificate is in the future.

You can figure the problem out by manually verifying the certificate with openssl:

sudo openssl verify -CAfile /etc/puppet/ssl/certs/ca.pem /etc/puppet/ssl/certs/myhostname.domain.com.pem

This can also happen if you've followed the Using Mongrel recipe to alleviate file download problems. If your set-up is such that the host name differs from the name in the Puppet server certificate, or there is any other SSL certificate negotiation problem, the SSL handshake between client and server will fail. In this case, either alleviate the SSL handshake problems (debug using cURL), or revert to the original Webrick installation.

[back]

I'm getting IPv6 errors; what's wrong?

This can apparently happen if Ruby is not compiled with IPv6 support; see the mail thread for more details. The only known solution is to make sure you're running a version of Ruby compiled with IPv6 support. [back]

I'm getting tlsv1 alert unknown ca errors; what's wrong?

This problem is caused by puppetmasterd not being able to read its ca certificate. This problem might occur up to 0.18.4 but has been fixed in 0.19.0. You can probably fix it for versions before 0.19.0 by changing the group ownership of the /etc/puppet/ssl directory to the puppet group, but puppetd may change the group back. Having puppetmasterd start as the root user should fix the problem permanently until you can upgrade. [back]

Why does Puppet keep trying to start a running service?

The ideal way to check for a service is to use the hasstatus parameter, which calls the init script with the status parameter. This should report back to Puppet whether the service is running or stopped.

In some broken scripts, however, the status output will be correct ("Ok" or "not running"), but the exit code of the script will be incorrect. Most commonly, the script will always blindly return 0, no matter what the actual service state is. Puppet only uses the exit code, so interprets this as "the service is stopped".

There are two workarounds, and one fix. If you must deal with the scripts broken behavior as is, you can modify your resource to either use the pattern parameter to look for a particular process name, or the status parameter to use a custom script to check for the service status.

The fix is to rewrite the init script to use the proper exit codes. When rewriting them, or submitting bug reports to vendors or upstream, be sure to reference the LSB Init Script Actions standard. This should carry more weight by pointing out an official, published standard they're failing to meet, rather than trying to explain how their bug is causing problems in Puppet. [back]

I'm using the Nagios types but the puppetrun on the server running Nagios is starting to take ages

If you are exporting Nagios objects, they will need to be collected on your Nagios server to be added to the nagios service configuration file. Let's say you are exporting some hundreds of nagios_service objects, the corresponding nagios_service.cfg file will be quite large. On every puppetrun however, for each and every nagios_service defined, puppet will have to seek through that file to see if anything has changed. This is incredibly time consuming.

You'll have better results using the "target" option for the nagios_service type. Eg.

nagios_service { "check_ssh_$fqdn":
     ensure => present,
     check_command => "check_ssh",
     use => "generic-service",
     host_name => $fqdn,
     service_description => "SSH",
     target => "/etc/nagios/nagios_service.d/check_ssh_$fqdn"
}

This will dramatically improve your puppetrun performance, as puppet only has to look in the directory for the file it needs and seek through a file with only one service definition in it.

[back]