May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix


News Unix Configuration Management Tools Recommended Links Chief Software Distribution Configuration Management

I hate cfengine. Puppet is an alternative software configuration manager that can help to centralize and standardize configuration and distribute modifications on your systems. As of 2015 it is reasobaly popular and there are dozens book published about it.

From the point of view of software design Puppet is written in ruby and is a second generation CMS. That might mean that it is a better deal then cfengine:

Such systems only make sense is you have dozens of hundreds similar  systems and can exploit this similarity using Puppet.  For example a large HPC cluster.

Still the approach taken is pretty verbose. This problem with "too much typing" can be solved with automatic tools. Here is an example specification of for a typical sudoer file:

class sudo {

  package { ["sudo","audit-libs"]: ensure => latest }

  file { "/etc/sudoers":
    owner   => root,
    group   => root,
    mode    => 440,
    content => template("sudo/files/sudoers.erb"),
    require => Package["sudo"],

With this level of verbosity automatic generation of such files using, say,  Perl scripts is the only viable solution.

Puppet is also able to collects facts from a managed systems using facter utility

The user and group types

In the absence of central registries such as LDAP, it is useful to be able to manage user accounts on each of your machines. There are providers for all supported platforms; however, the available attributes vary. On Linux, the useradd provider is the most common. It allows the management of all fields in /etc/passwd, such as uid and shell, but also group memberships

group { 
ensure => present, 
gid => 4002, 
user { 
uid => 332456,
gid => 10
home => '/home/bigdata' 
managehome => true, # <- adds -m to useradd 
shell => '/bin/bash', 
groups => [ 'reseachers' ], 

As with all resources, Puppet will not only make sure that the user and group exist, but also fix any divergent properties such as the home directory.

The exec resource type

Puppet is not a specialized scripting engine, but instead a tool that allows you to model part of your system state in a  DSL and is capable of altering your system to meet the defined goal. This is why you declare a user and a group, for example, instead of invoking groupadd and useradd . Puppet also knows that on different platforms, other commands are used for account management and that the arguments can be subtly different on some systems.

There are cases where you only need Puppet to invoke some exotic commands from very few places in your manifest.

For such cases, Puppet provides the exec resource type, which allows the execution of custom commands in lieu of an abstract sync action. For example, it can be used to unpack a tarball in the absence of a proper package:

exec { 
    'tar cjf /opt/packages/homebrewn-3.2.tar.bz2': 
        cwd     => '/opt', 
        path    => '/bin:/usr/bin', 
        creates => '/opt/homebrewn-3.2', 

The creates parameter is important for Puppet to tell whether the command needs running — once the specified path exists, the resource counts as synced. For commands that do not create a telltale file or directory, there are alternative parameters, onlyif and unless, to allow Puppet to query the sync state:

exec { 
    'perl -MCPAN -e "install YAML"': 
        path   => '/bin:/usr/bin', 
        unless => 'cpan -l | grep -qP ^YAML\\b' 

The query command's exit code determines the state. In the case of unless, the exec command runs if the query fails.

Finally, the exec type resources are the second notable case of receivers for events using notify and subscribe:

exec { 
    'apt-get update': 
        path        => '/bin:/usr/bin', 
        subscribe   => 
        refreshonly => true, 

You can even chain multiple exec resources in this fashion so that each invocation triggers the next one. However, this is a bad practice and degrades Puppet to a (rather flawed) scripting engine. The exec resources should be avoided in favor of regular resources whenever possible. Some resource types that are not part of the core are available as plugins from the Puppet Forge. You will learn more about this topic in Chapter 5, Extending Your Puppet Infrastructure with Modules.

Since exec resources can be used to perform virtually any operation, they are sometimes abused to stand in for more proper resource types. This is a typical antipattern in Puppet manifests. It is safer to regard exec resources as the last resort, which are only to be used if all other alternatives have been exhausted.

Let's briefly discuss two more types that are supported out of the box. They allow the management of cron jobs and mounted partitions and shares, respectively, which are frequent requirements in server operation.

The cron resource type

A cron job mainly consists of a command and the recurring time and date at which to run the command. Puppet models the command and each date particle as a property of a resource with the cron type:

cron { 
        ensure      => present, 
        user        => 'root', 
        command     => '/usr/local/bin/clean-files', 
        minute      => '1', 
        hour        => '3', 
        weekday     => [ '2', '6' ], 
        environment => '[email protected]', 

The environment property allows you to specify one or more variable bindings for cron to add to the job.

The mount resource type

Finally, Puppet will manage all aspects about mountable filesystems for you-their basic attributes such as the source device and mount point, the mount options, and the current state. A line from the fstab file translates quite literally to a Puppet manifest:

mount { 
        ensure  => 'mounted', 
        device  => 'gluster01:/data', 
        fstype  => 'glusterfs', 
        options => 'defaults,_netdev', 
        dump    => 0, 
        pass    => 0, 

For this resource, Puppet will make sure that the filesystem is indeed mounted after the run. Ensuring the unmounted state is also possible, of course, but Puppet can also just make sure the entry is present in the fstab file, or absent from the system altogether.

Built-in language

The whole paradigm is different from that of scripting languages. Whereas Ruby or Perl are imperative languages, which are based around statements that will be evaluated in a strict order, the Puppet language (DSL) is declarative: the manifest declares a set of resources that are expected to have certain properties. So the manifest for /etc/sudoer file above ensures that the file /etc/sudoers is installed from templates and after the installation has specified properties (ownership and permissions)

Variable assignment works just like in most scripting languages. Any variable name is always prefixed with the $ sign:

$proxy_server = '' 
$mc_package = "https://${epel}/pkg/mc.rpm" 

Like in Perl, Puppet performs variable value substitution in strings that are in double quotes, but no interpolation at all in single-quoted strings.

Variables are useful to make your manifest more concise and comprehensible. They help you with the overall goal of keeping your source code free from redundancy. An important distinction from variables in imperative programming and scripting languages is the immutability of variables in Puppet manifests. Once a value has been assigned, it cannot be overwritten.

Under specific circumstances, it is possible to amend values through concatenation. You might encounter statements such as for $variable += 'value'. This should be used with care, or avoided altogether.

Variable types

There are three main variable types: strings, arrays, and hashes. Puppet 4 introduced a richer type system. The three variable types work much like their respective counterparts in Perl:

$a_string = 'This is a string value' 
$an_array = [ 'This', 'forms', 'an', 'array' ] 
$a_hash   = { 
    'subject'   => 'Hashes', 
    'predicate' => 'are written', 
    'object'    => 'like this', 
    'note'      => 'not actual grammar!', 
    'also note' => [ 'nesting is', 
                     { 'allowed' => 'of course' } ], 

Accessing the values is equally simple. Note that the hash syntax is similar to that of Ruby, not Perl's:

$x = $a_string 
$y = $an_array[1] 
$z = $a_hash['object'] 

Strings can obviously be used as resource attribute values, but it's worth noting that a resource title can also be a variable reference:

package { 
        ensure => 'installed' 

It's intuitively clear what a string value means in this context. But you can also pass arrays here to declare a whole set of resources in one statement. The following manifest manages three packages, making sure that they are all installed:

$packages = [ 'apache2', 
              'libapache2-mod-passenger', ] 
package { 
        ensure => 'installed' 

Control structures

The most common control element is the if/else block. It is quite similar to its equivalent in many programming languages:

if 'mail_lda' in $needed_services { 
    service { 'dovecot': enable => true } 
} else { 
    service { 'dovecot': enable => false } 

The Puppet has a case statement, which is reminiscent of its counterpart in other languages as well:

case $role { 
    'imap_server': { 
        package { 'dovecot': ensure => 'installed' } 
        service { 'dovecot': ensure => 'running' } 
    /_webserver$/: { 
        service { [ 'apache', 'ssh' ]: ensure => 'running' } 
    default: { 
        service { 'ssh': ensure => running } 

A variation of the case statement is the selector. It's an expression, not a statement, and can be used in a fashion similar to the ternary if/else operator found in C-like languages:

package { 
    'dovecot': ensure => $role ? { 
        'imap_server' => 'installed', 
        /desktop$/    => 'purged', 
        default       => 'removed', 

Regular expersssions

language used by Pupper is close to Perl, which simply its learning (after all Rubi is derivative of perl). Puppet supports standard Ruby regular expressions, as defined at . The regex operator works with a string on the left, and the regular expression on the right of the ~ operator.

$version_of_mc_istalled =~ /5.8.1/ #  
$version_of_r_installed !~ /3.21/ #  

Resources and properties

Each of the manifests you wrote in the previous section declared one respective resource. Resources are the elementary building blocks of manifests. Each has a type (in this case, notify and service, respectively) and a name or title (Hello, world! and puppet). Each resource is unique to a manifest and can be referenced by the combination of its type and name, such as Service["puppet"]. Finally, a resource also comprises a list of zero or more attributes. An attribute is a key-value pair such as "enable => false".

Attribute names cannot be chosen arbitrarily. Each resource type supports a specific set of attributes. Certain parameters are available for all resource types, and some names are just very common, such as ensure. The service type supports the ensure property, which represents the status of the managed process. Its enabled property, on the other hand, relates to the system boot configuration (with respect to the service in question).

Note that I have used the terms attribute, property, and parameter in a seemingly interchangeable fashion. Don't be deceived-there are important distinctions. Property and parameter are the two different kinds of attributes that Puppet uses. You have already seen two properties in action. Let's look at a parameter:

service { 
        ensure   => 'stopped', 
        enable   => false, 
        provider => 'upstart', 

The provider parameter tells Puppet that it needs to interact with the upstart subsystem to control its background service, as opposed to systemd or init. If you don't specify this parameter, Puppet makes a well-educated guess. There is quite a multitude of supported facilities to manage services on a system. You will learn more about providers and their automatic choosing later.

The difference between parameters and properties is that the parameter merely indicates how Puppet should manage the resource, not what a desired state is. Puppet will only take action on property values. In this example, these are ensure => 'stopped' and enable => false. For each such property, it will perform the following tasks:

A property is considered to be in sync when the system entity that is managed by the given resource (in this case, the upstart service configuration for Puppet) is in the state that is described by the property value in the manifest. In this example, the ensure property will be in sync only if the puppet service is not running. The enable property is in sync if upstart is not configured to launch Puppet at system start.

As a mnemonic concerning parameters versus properties, just remember that properties can be out of sync, whereas parameters cannot.

Interpreting the output of the puppet apply command

As you have already witnessed, the output presented by Puppet is rather verbose. As you get more experienced with the tool, you will quickly learn to spot the crucial pieces of information. Let's first look at the informational messages though. Apply the service.pp manifest once more:

Puppet took no particular action. You only get two timings-one from the compiling phase of the manifest and the other from the catalog application phase. The catalog is a comprehensive representation of a compiled manifest. Puppet bases all its efforts concerning the evaluation and syncing of resources on the content of its current catalog.

Now, to quickly force Puppet to show you some more interesting output, pass it a one-line manifest directly from the shell. Regular users of Ruby or Perl will recognize the call syntax:


I prefer double quotes in manifests that get passed as command-line arguments, because on the shell, the manifest should be enclosed in single quotes as a whole, if at least for convenience.

You instructed Puppet to perform yet another change upon the Puppet service. The output reflects the exact change that is performed. Let's analyze this log message:

Dry-testing your manifest

Another useful command-line switch for puppet apply is the --noop option. It instructs Puppet to refrain from taking any action on unsynced resources. Instead, you only get log output that indicates what will change without the switch. This is useful to determine whether a manifest would possibly break anything on your system:

Note that the output format is the same as before, with a (noop) marker trailing the notice about the sync action. This log can be considered a preview of what will happen when the manifest is applied.

As shown throughout all previous examples, you declare a resource using the resource type lowercase and enclose the definition in curly brackets.

package { 'puppet':
ensure => present,
Once the resource has been given a unique title, it is possible to refer to that resource by name. This is called a Resource Reference. In this chapter we're going to refer to specific resources quite often, so let's describe how to do it. To create a resource reference, uppercase the first letter of the resource type and enclose the title in square brackets. For example, when referring to the package resource created above, you'd use Package['puppet']. Here an example which builds a service to run the puppet agent installed above.
service { 'puppet':
ensure => running,
enabled => true,
require => Package['puppet'],

So remember: create a resource with the lowercase type, and refer to an existing resource with an uppercase first letter.

Ordering Resources

In many situations some resources must be applied before others. For example, you cannot start a service until after you install the package which contains the application. Here we will show you the before and require metaparameters you can use to ensure the package is installed before the service is started.

package { 'puppet':
ensure => present,
before => Service['puppet'],

service { 'puppet':
ensure => running,
enable => true,
require => Package['puppet'],

The before and require metaparameters are redundant in this case. Either one would work by itself. Use the one which fits your manifest and is easiest to read. Belt and suspenders people like myself often use both when possible.

Triggering Refresh Events

The before and require metaparameters ensure that dependencies are processed before resources that require them. However, these parameters do not link or provide data to the other resource.

The notify and subscribe metaparameters operate in a similar manner, but will also send a refresh event to the dependent resource if the dependency is changed. The dependent resource will take a resource-specific action. For example, a service would restart after the configuration file has been changed.

Let's modify our previous policy to upgrade the Puppet package whenever a newer version is available.

package { 'puppet':
ensure => latest,
notify => Service['puppet'],

service { 'puppet':
ensure => running,
enable => true,
subscribe => Package['puppet'],

In this case, if a newer version of Puppet is available then the puppet package will be upgraded. Any time the Puppet package is installed or upgraded, the puppet service will be restarted.

As before, the notify and subscribe metaparameters are redundant. Either one would send the refresh event without the other. Belt and suspenders people like myself do both.

The refresh event means something special to Exec resources. If an Exec resource is created with the attribute refreshonly set to true, then the Exec resource will not run unless it receives a refresh event. In the following example, we will update the facts.yaml file for MCollective only after Puppet has been upgraded.

Dependencies: Chaining Resources with Arrows

You can also order and related resources using Chaining Arrows. You put the required resource on the left, and the dependent resource on the right, linked together with ->. For example, to install puppet before starting the service you could express it like so.
Package['puppet'] -> Service['puppet']

You can use ~> to also send a refresh event, like notify does. For example, this will restart the Puppet service after the Puppet package is upgraded.
Package['puppet'] ~> Service['puppet']

The chaining arrow syntax is harder to read than the metaparameters, and should be avoided when possible. In particular, right to left relationships are harder to read and explicitly against the Puppet Style Guide.
# Don't do this. Order it left -> right instead.
Service['puppet'] <~ Package['puppet']

Processing with Collectors

A collector is a grouping of many resources together. You can use Collectors to affect many resources at once.

A Collector is declared by the capitalized type followed by <|, an optional attribute comparison, and |>. Let's examine some collectors.
User <||> # every User
User <| groups == 'wheel' |> # Users in the wheel group declared in a manifest
Package <||> # every Package
Package <| tag == 'packages' |> # Packages tagged with 'packages' tag in a manifest
Service <||> # every Service
Service <| enabled == true |> # Services set to start at boot time in a manifest

# Search expressions may be grouped with parenthesis and combined
Service <| ( ensure == running ) or ( enabled == true ) |> # Services running OR set to start at boot time
Service <| ( ensure == running ) and ( title != 'puppet' ) |> # Services other than Puppet set to be running

Top Visited
Past week
Past month


Old News ;-)

[Aug 03, 2010] Puppet vs Chef BHUGA WOOGA!

I spent a while going over recipes, and comparing them to Puppet. For example, here's some code to manage sudo for Chef. The Chef code was written by Chef's authors; the Puppet code was written by myself. The Chef code is spread across 3 files.
# recipes/default.rb:
package "sudo" do
  action :upgrade
template "/etc/sudoers" do
  source "sudoers.erb"
  mode 0440
  owner "root"
  group "root"
    :sudoers_groups => node[:authorization][:sudo][:groups], 
    :sudoers_users => node[:authorization][:sudo][:users]
# attributes.rb:
authorization unless attribute?("authorization")
authorization[:sudo] = unless authorization.has_key?(:sudo)
unless authorization[:sudo].has_key?(:groups)
  authorization[:sudo][:groups] = 
unless authorization[:sudo].has_key?(:users)
  authorization[:sudo][:users] =
# metadata.rb:
maintainer        "Opscode, Inc."
maintainer_email  "[email protected]"
license           "Apache 2.0"
description       "Installs and configures sudo"
version           "0.7"
attribute "authorization",
  :display_name => "Authorization",
  :description => "Hash of Authorization attributes",
  :type => "hash"
attribute "authorization/sudoers",
  :display_name => "Authorization Sudoers",
  :description => "Hash of Authorization/Sudoers attributes",
  :type => "hash"
attribute "authorization/sudoers/users",
  :display_name => "Sudo Users",
  :description => "Users who are allowed sudo ALL",
  :type => "array",
  :default => ""
attribute "authorization/sudoers/groups",
  :display_name => "Sudo Groups",
  :description => "Groups who are allowed sudo ALL",
  :type => "array",
  :default => ""

Here's more or less the same thing for Puppet:

class sudo {

  package { ["sudo","audit-libs"]: ensure => latest }

  file { "/etc/sudoers":
    owner   => root,
    group   => root,
    mode    => 440,
    content => template("sudo/files/sudoers.erb"),
    require => Package["sudo"],

Both Chef and Puppet then take this information and output it through an ERB template, which is an exercise for the reader, since it's basically the same for both.

There's a few things worth noting here. First of all, Puppet has zero metadata available. If you want to set sudo-able groups, you need to know those variable names ahead of time and set them to what you want. Both your template and whatever code sets your sudo-able groups must magically 'just know' this information. Since the Puppet DSL is not even Ruby, you have *zero* ability to perform any kind of metadata analysis on these attributes in order to make code more generic.

Chef gives you complete metadata about the variables it's using. This is powerful and indeed critical in my imagined use domains for Chef (keep reading). That metadata comes at a cost of a lot of boilerplate code, though. Chef comes with some rake tasks to generate some scaffolding. I'm always uncomfortable with scaffolding like this; I think this kind of code generation is a bad way to do metaprogramming.

Chef spreads this information across 3 files, named a particular way. Puppet has a similar scheme of magically named files, but it's basically just a folder structure, a file called init.pp, and templates/source files. For a fairly simple task, Chef requires you to know a folder structure and 3 file names, and which data goes in which files. This is congruent with the Ruby world's (perhaps specifically the rails/merb world's?) general practice of 'convention not configuration'. This is in addition to all of the 'you just have to know' parts of the Chef system which are taken from Merb, such as where models and controllers live, though you would not need to edit those save for pretty advanced cases.

Lastly, Chef provides you with an actual data structure that is fed to the sudoers template. Puppet simply uses available dynamically-scoped variables in its template files. This is *awful*, and a big loss for puppet. I administrate Zimbra servers, for example, which require extra content in sudoers. I cannot add this to the zimbra module unless the zimbra module were to be the one including the sudo module. There are solutions to this, of course, but this is a really, really simple use case and we're already shaving yaks. Chef's method is undeniably superior.

All 3 of these are part of the same core difference between the two: Puppet is an application, and Chef is a part of one.

Chef is a library to be used in a combined system of resource management in which the application itself is aware of the hardware it's using. This allows certain kinds of applications to exist on certain kinds of platforms (particularly EC2) that simply couldn't before--an application using this system can declare a database just as well as it can declare an integer. That's fundamentally powerful, awesome, amazing.

Puppet is an application which has an enormous built-in library of control methods for systems. The puppet package manager, for example, supports multiple kinds of *nix, Solaris, HPUX, and so forth. Chef cookbooks can certainly be written to do this, but I imagine by the time you supported everything puppet does I don't think Chef would get a smiley-face sticker for being tiny and pure with extra ruby sauce. Puppet's not a fundamental change, it's just a really nice workhorse.

I picked puppet for the project I'm working on now. It made sense for a lot of reasons. Probably first and foremost, there are 3 other sysadmins working with me, some split between this project and others. None of us are ruby programmers. We don't write rake tasks like we configure Apache, we don't want to explain to new hires the difference between a symbol or a variable, or where the default Merb configuration files, or 100 other ruby-isms. Meanwhile, most puppet config, silly folder structure aside, is not any harder to configure than something like Nagios. I think it would be a mistake for an IT shop with a lot of existing systems running various old-fashioned stateful applications like databases or LDAP to suddenly declare that sysadmins need to be Merb programmers.

Puppet's much deeper out-of-the-box support for a lot of systems provides the kind of right-now real improvements that a lot of IT shops and random contractors desperately need. System administration is depressingly rarely about being elegant or 'the best' and much more frequently about being repeatable and reliable. It's just the nature of the business--if the systems ran themselves, there would be no administrators.

Having a bunch of non-programmers become not just programmers but programmers specializing in a tiny subset of the ruby world is a lot of yaks to shave for an organization. This is not some abstract jab at my colleagues: I am most certainly not a Merb programmer, and even if I were, I have too many database copies to make, SQL queries to run, mysterious performance problems to diagnose and deployments to make to give this kind of development the attention it requires. How many system administrators do you know that use the kind of TDD that Merb can provide for their bash scripts? What would make one think that's going to happen with Chef?

The other big reason I picked Puppet is that it's got a sizable mailing list, a friendly and frequently used google group for help, and remains in active development after a couple of years. I don't think Reductive Labs is going away, and if it did, there have been a lot of contributors to the code base over those 2 years.

It's worth noting, though, that the Chef guys come with an impressive set of resumes. It seems to be somehow tied in with Engine Yard (several presentations about Chef include Ezra Zygmuntowicz as a speaker). I worry, though, that they are working the typical valley business model, namely to explode about a year after launch. Chef was released about 8 months before I write this. The organization I am installing Puppet for does not have the Ruby talent base required to ensure that they can fix bugs as required in the long term if Opscode goes away, or if they get hired on to Engine Yard and they make Chef into the kind of competitive differentiation secret it could be.

Chef currently manages the EC2 version of Engine Yard, and that's just the kind of thing I cannot imagine using puppet for: interact with a giant ruby application to manage itself. If you have a lot of systems joining and leaving the resource pool as required, Chef's ability to add nodes dynamically is going to save you. The ability to define resources programmatically is very powerful--one could easily imagine reducing the number of web server threads if a system's CPU use goes over a certain threshold, for example. I would not try that in puppet! But note that this is an application built from scratch to expect such a command and control system to exist. If you're just managing a bunch of LAMP stacks and samba servers, this is more power than you need. One of the Opscode founders has some slides that talk about this kind of model.

And Chef is powerful for that model, sure, but is that even the model you want for your applications? Applications should not have to worry about the hardware they use. Making an application's own hardware use visible to itself encourages programmers to spend time thinking about issues they should be trying their hardest to ignore. A better model is App Engine's, where the system just scales forever without developer intervention. Even Azure's service configuration schema model is better, in which different application roles (web, proxy, etc) are described as resources and given a dynamic instance count, and transparently scalable data stores are available. The number of 'nodes' in the system is never an issue for either model.

Chef is what you'd use to build that auto-scaling backend. Engine Yard uses it for, well, Engine Yard--scalable rails hosting, transparently sold as a service to folks who can then just blissfully program in rails and never think about Chef. Very few organizations are making that infrastructure, and most of them that are are shaving really big yaks and need to stop and use one of the available clouds.

Meanwhile, a very many organizations are running 6 kinds of *nix to maintain tens of older applications built on the POSIX or LAMP paradigms, or hosting virtual machines running applications made who knows when. For these organizations, Puppet is probably the easiest thing that could work, and thus probably the best option.

I'm sure there are sysadmins out there who think I'm completely wrong, and that you just can't beat the elegance Chef provides. There are a lot of people better than me out there, and I'm sure they have a point. But in my experience, bad system administration happens when sysadmins try and do everything for themselves. For a given situation in system administration, it's highly unlikely a sysadmin can do a better job than an available tool. Puppet's sizable default library is what most organizations need, not the ability to write their own.

And all of the above aside, one thing is clear: there is little excuse for an organization with 3 or more *nix servers not to be using Puppet, Chef, cfengine, or *something*. I would argue that about 80% of the virtualization push is dodging some of the core questions of system administration, making systems movable to new resources indefinitely rather than making their configuration repeatable, but that's a topic for another post. Especially since nobody got this far on this one anyway.

Adam Jacob

Hi John! Thanks for being passionate about my favorite space - configuration management. You do great work, and I know your intent wasn't necessarily to sow discord - but I wanted to take a moment to comment on a few of your points that I think are either wrong or missing some important context.

1) Large installed base

Chef has somewhere in the neighborhood of ~1500 working installations. It's true that our early adopters are primarily large web players like Wikia, Fotopedia, and 37signals. We also have a growing number of people integrating Chef directly into their service offering - it's not just Engine Yard, it's RightScale and others.

2) Large developer base

According to Ohloh, 39 developers have contributed to Puppet in the last 12 months, and 71 over the projects entire history.

Chef has been open source for a year. We just had our 100th CLA (contributor license agreement, meaning they can contribute code). Over the course of the year, 52 different people have contributed to Chef, including significant functionality (for the record, 5 of them work for Opscode.) We're incredibly proud of the community of developers who have joined the project in the last year, and the huge amount of quality code they produce.

3) Dedicated Configuration Language

To each their own, man. :) My preference for writing configuration management in a 3GL was born out of frustration with doing the higher order systems integration tasks. By definition, internal DSLs aren't meant to do that - when they start being broadly applicable, they loose the benefits they gained from domain specificity. For me, the benefit of being able to leverage the full power of a 3GL dramatically outweigh the learning curve, and I think a side-by-side comparison of the two languages shows just how close you can get to never having to leave the comfort of your DSL most of the time.

4) Robust Architecture

Chef is built to scale horizontally like a web application. It's a service oriented architecture, built around REST and HTTP. Like cfengine, it pushes work to the edges, rather then centralizing it. There are large (multi-thousand node) chef deployments, and larger ones coming. Chef scales just fine.

5) Documentation

It's true, we've been focused pretty intently on refining Chef in tandem with our earlier adopters, and that focus has had an impact on the clarity of our documentation. Rest assured, we're working on it.

6) Language/Framework Neutral

I'm not sure where this comes from, other than we've had great adoption in the Ruby community. People deploy and manage every imaginable software stack with Chef - Java, Perl, Ruby, PHP - it's all being managed with Chef.

7) Multi-Platform

It's true that, at release a year ago, Chef didn't support many platforms. Since then, we've been growing that support steadily - all the platforms you list run Chef just fine, with the exception of AIX. We have native packages for Red Hat (community maintained by the always awesome Matthew Kent!) and Ubuntu that ship regularly at every release. As for the Chef Server only running on Ubuntu - that's just not true.

8) Doesn't re-invent the wheel

Again, to each their own. I think Chef's deterministic ordering, ease of integration, wider range of actions, directly re-usable cookbooks, and lots of other things make it quite innovative. I'm pleased to explain it to you over beer, on my dime. :)

9) Dependency Management

While I understand how you can think this would be true, it isn't. Chef does have dependency management, and a more robust notification system then Puppet. Each resource is declarative and idempotent. Within a recipe, resources are executed in the order they are written - meaning the way you write it is the way it runs. This is frequently the way puppet manifests are written as well. The difference being, there is no need to declare resource-level dependency relationships.

With Chef, you focus on recipe-level dependencies. "Apache should be working before I install Tomcat". You can ensure that another recipe has been applied at any point, giving you great flexibility, along with a high degree of encapsulation.

One added benefit of the way Chef works is that the system behaves the exact same way, every time, given the same set of inputs. This greatly eases debugging of ordering issues, and results in a system that is, in my opinion, significantly easier to reason about at scale (thousands of resources under management).

10. Big Mindshare

There is a bit of survivor bias happening here. I meet people every day who are starting with, or switching to, Chef. You don't, because, well - you don't use Chef.

* Conclusion

Thanks for taking the time to write about Puppet and Chef - I know your heart is in the right place. Next time, come talk to us - we're pretty accessible guys, and I would be happy to provide feedback and education about how Chef works. I won't even try and convince you to switch. :)

Best regards,

[Aug 03, 2010] Puppet versus Chef 10 reasons why Puppet wins Bitfield Consulting

Puppet, Chef, cfengine, and Bcfg2 are all players in the configuration management space. If you're looking for Linux automation solutions, or server configuration management tools, the two technologies you're most likely to come across are Puppet and Opscode Chef. They are broadly similar in architecture and solve the same kinds of problems. Puppet, from Reductive Labs, has been around longer, and has a large user base. Chef, from Opscode, has learned some of the lessons from Puppet's development, and has a high-profile client: EngineYard.

You have an important choice to make: which system should you invest in? When you build an automated infrastructure, you will likely be working with it for some years. Once your infrastructure is already built, it's expensive to change technologies: Puppet and Chef deployments are often large-scale, sometimes covering thousands of servers.

Chef vs. Puppet is an ongoing debate, but here are 10 advantages I believe Puppet has over Chef today.

1. Larger installed base

Put simply, almost everyone is using Puppet rather than Chef. While Chef's web site lists only a handful of companies using it, Puppet's has over 80 organisations including Google, Red Hat, Siemens, lots of big businesses worldwide, and several major universities including Stanford and Harvard Law School.

This means Puppet is here to stay, and makes Puppet an easier sell. When people hear it's the same technology Google use, they figure it works. Chef deployments don't have that advantage (yet). Devops and sysadmins often look to their colleagues and counterparts in other companies for social proof.

2. Larger developer base

Puppet is so widely used that lots of people develop for it. Puppet has many contributors to its core source code, but it has also spawned a variety of support systems and third-party add-ons specifically for Puppet, including Foreman. Popular tools create their own ecosystems.

Chef's developer base is growing fast, but has some way to go to catch up to Puppet - and its developers are necessarily less experienced at working on it, as it is a much younger project.

3. Choice of configuration languages

The language which Puppet uses to configure servers is designed specifically for the task: it is a domain language optimised for the task of describing and linking resources such as users and files.

Chef uses an extension of the Ruby language. Ruby is a good general-purpose programming language, but it is not designed for configuration management - and learning Ruby is a lot harder than learning Puppet's language.

Some people think that Chef's lack of a special-purpose language is an advantage. "You get the power of Ruby for free," they argue. Unfortunately, there are many things about Ruby which aren't so intuitive, especially for beginners, and there is a large and complex syntax that has to be mastered.

There is experimental support in Puppet for writing your manifests in a domain language embedded in Ruby just like Chef's. So perhaps it would be better to say that Puppet gives you the choice of using either its special-purpose language, or the general-purpose power of Ruby. I tend to agree with Chris Siebenmann that the problem with using general-purpose languages for configuration is that they sacrifice clarity for power, and it's not a good trade.

4. Longer commercial track record

Puppet has been in commercial use for many years, and has been continually refined and improved. It has been deployed into very large infrastructures (5,000+ machines) and the performance and scalability lessons learned from these projects have fed back into Puppet's development.

Chef is still at an early stage of development. It's not mature enough for enterprise deployment, in my view. It does not yet support as many operating systems as Puppet, so it may not even be an option in your environment. Chef deployments do exist on multiple platforms, though, so check availability for your OS.

5. Better documentation

Puppet has a large user-maintained wiki with hundreds of pages of documentation and comprehensive references for both the language and its resource types. In addition, it's actively discussed on several mailing lists and has a very popular IRC channel, so whatever your Puppet problem, it's easy to find the answer. (If you're getting started with Puppet, you might like to check out my Puppet tutorial here.)

Chef's developers have understandably concentrated on getting it working, rather than writing extensive documentation. While there are Chef tutorials, they're a little sketchy. There are bits and pieces scattered around, but it's hard to find the piece of information you need.

6. Wider range of use cases

You can use both Chef and Puppet as a deployment tool. The Chef documentation seems largely aimed at users deploying Ruby on Rails applications, particularly in cloud environments - EngineYard is its main user and that's what they do, and most of the tutorials have a similar focus. Chef's not limited to Rails, but it's fair to say it's a major use case.

In contrast, Puppet is not associated with any particular language or web framework. Its users manage Rails apps, but also PHP applications, Python and Django, Mac desktops, or AIX mainframes running Oracle.

To make it clear, this is not a technical advantage of Puppet, but rather that its community, documentation and usage have a broader base. Whatever you're trying to manage with Puppet, you're likely to find that someone else has done the same and can help you.

7. More platform support

Puppet supports multiple platforms. Whether it's running on OS X or on Solaris, Puppet knows the right package manager to use and the right commands to create resources. The Puppet server can run on any platform which supports Ruby, and it can run on relatively old and out-of-date OS and Ruby versions (an important consideration in many enterprise environments, which tend to be conservative about upgrading software).

Chef supports fewer platforms than Puppet, largely because it depends on recent versions of both Ruby and CouchDB. As with Puppet, though, the list of supported platforms is growing all the time. Puppet and Chef can both deploy all domains of your infrastructure, provided it's on the supported list.

8. Doesn't reinvent the wheel

Chef was strongly inspired by Puppet. It largely duplicates functionality which already existed in Puppet - but it doesn't yet have all the capabilities of Puppet. If you're already using Puppet, Chef doesn't really offer anything new which would make it worth switching.

Of course, Puppet itself reinvented a lot of functionality which was present in earlier generations of config management software, such as cfengine. What goes around comes around.

9. Explicit dependency management

Some resources depend on other resources - things need to be done in a certain order for them to work. Chef is like a shell script: things are done in the order they're written, and that's all. But since there's no way to explicitly say that one resource depends on another, the ordering of your resources in the code may be critical or it may not - there's no way for a reader to tell by looking at the recipe. Consequently, refactoring and moving code around can be dangerous - just changing the order of resources in a text file may stop things from working.

In Puppet, dependencies are always explicit, and you can reorder your resources freely in the code without affecting the order of application. A resource in Puppet can 'listen' for changes to things it depends on: if the Apache config changes, that can automatically trigger an Apache restart. Conversely, resources can 'notify' other resources that may be interested in them. (Chef can do this too, but you're not required to make these relationships explicit - and in my mind that's a bad thing, though some people disagree. Andrew Clay Shafer has written thoughtfully on this distinction: Puppet, Chef, Dependencies and Worldviews).

Chef fans counter that its behaviour is deterministic: the same changes will be applied in the same order, every time. Steve Traugott and Lance Brown argue for the importance of this property in a paper called Why Order Matters: Turing Equivalence in Automated Systems Administration.

10. Bigger mindshare

Though not a technical consideration, this is probably the most important. When you say 'configuration management' to most people (at least people who know what you're talking about), the usual answer is 'Puppet'. Puppet owns this space. I know there is a large and helpful community I can call on for help, and even books published on Puppet. Puppet is so widely adopted that virtually every problem you could encounter has already been found and solved by someone.


Currently 'Chef vs. Puppet' is a rather unfair comparison. Many of the perceived disadvantages of Chef that I've mentioned above are largely due to the fact that Chef is very new. Technically, Puppet and Chef have similar capabilities, but Puppet has first mover advantage and has colonised most corners of the configuration management world. One day Chef may catch up, but my recommendation today is to go with Puppet.

Selected Comments

Julian Simpson:

Culture is an important reason as to why people gravitate to one tool or another. Chef will draw in Ruby developers because it's not declarative, and because it's easy.

My experience is that most developers don't do declarative systems. Everyday languages are imperative, and when you're a developer looking to get something deployed quickly, you're most likely to pick the tool that suits your world view.

Systems Administrators tend to use more declarative tools (make, etc.)

Developers and Systems Administrators also have a divergent set of incentives. Developers are generally rewarded for delivering systems quickly, and SA's are rewarded for stability. IMHO, Chef is a tool to roll out something quickly, and Puppet is the one to manage the full lifecycle. That's why I think Chef makes a good fit for cloud deployment because Vm instances have a short lifespan.

I think it's still anybody's game. The opportunity for Chef is that the developer community could build out an ecosystem very quickly.


It seems to me that both system have quite a bit of support out there and it really comes down to what you as the sysadmin/developer prefer.

I would also agree with ripienaar's tweet about disagreeing with point 6. Configuration management systems are not really intended for deploying software but for making sure that systems conform to a certain policy ie. webserver policy etc.

Nick Anderson:

I'm a SA and have worked closely with developers for years. It never ceased to amaze me how differently we think. It does boil down to priorities, culture, and incentives as Julian mentioned. I have not used Chef but I saw quite the stir the last time I mentioned puppet Puppet Works Hard To Make Sure Nodes Are In Compliance.

I have used puppet both as a deployment tool and a configuration management tool. It really can do both just fine as a deployment is essentially a configuration change. But I have found it easier to use a tool like fabric when I need to perform "actions" on a group of machines, especially when those actions are many and very possibly one time. I have found it a bit daunting if you put too much into your configuration management tool as over time it becomes a lot to sift through, and when its time to remove a configuration you have to leave that part of the configuration there (the part that removes whatever it was).

Maybe I haven't looked around enough but I really want to see a puppet reporting tool. I know bcfg2 has a decent one. I want to be able to know the current stats of my nodes, who is in compliance, who isn't, when I last spoke with what node, last time nodex changed and what changed.

John Arundel:

It is hard to be objective - probably impossible. I'm sure I haven't been.

My background is that I've used Puppet for commercial sysadmin work for several years (basically since it came out), and it currently manages many infrastructures for many of my clients (I'm a freelancer). The biggest deployment I've worked on is probably 25-30 servers, and a comparable number of desktops. Maybe 6,000 lines of manifest code (not counting templates).

When Chef was first announced, I set aside time to build a Chef server and try it out, with a view to adopting it if it was superior to Puppet. I found it quite hard going (admittedly that was early days for Chef), and I didn't find sufficient advantages for Chef to migrate any of my clients to it. If a client asked for Chef specifically, I'd be quite happy to use it, but so far no-one has.

So based on what I know, I use Puppet and that's what I recommend to others. I'm very interested in hearing from anyone who knows different.


Readers, do you homework too and stop reading articles with the title 'versus', the hallmark of propaganda. If you must read on, some specific points, with disclosure that I'm a Chef early adopter with previous Puppet exposure.

#1, #2, #5, #7, #10: puppet is more mature than Chef

All software starts with a small install base, fewer adherents, etc. That doesn't make it more suitable for your specific environment or taste in software development (configuration management is development too). The answer here is to try both systems yourself and compare them - something the author of this article seems to not have done yet. It's not just about the code, it's about the software used to deploy it, the way it authenticates, etc. These things should also influence your decision.

#9: Dependency management

"Chef has no support for specifying dependencies (ordering resources). Chef is like a shell script: things are done in the order they're written, and that's all."

Chef's default behavior is to process resources in the order you write them. It has other dependency features just like Puppet does - see below.

"A resource in Puppet can 'listen' for changes to things it depends on: if the Apache config changes, that can automatically trigger an Apache restart. Conversely, resources can 'notify' other resources that may be interested in them."

This has been possible in Chef for a long time. See this real world example: - See the 'notifies' attribute in the Meta section.

#3 Dedicated configuration language

"Ruby is a good general-purpose programming language, but it is not designed for configuration management - and learning Ruby is a lot harder than learning Puppet's language."

Sysadmins who can code can learn Ruby quickly, and there are plenty of resources on how to write Ruby. While most of the time you can stick to the Chef style of Ruby, you have access to the power of a mature programming language for free. If you think this language is easier, show why that would be the case for someone who already knows at least one programming language.

I see nothing inherent in Puppet's language that makes it better suited to configuration management. If you think there is, show some examples.

#6: Language/framework neutral

Straight up bullshit here. There is nothing in Chef specific to Ruby on Rails. All chef deployments I know of (including our own) are used for deploying entire stacks of software totally unrelated to Ruby or Rails, just like Puppet.

Conclusion: In the next installment, show more code examples and tell us why Chef didn't work for you where Puppet did. Try both software packages the day before you write the article, not 6 months before. Assume your readers write code and already know that adopting less mature software is more risky.


I'd agree with almost everything above, this strikes me as mostly self promoting b/s written with the express intend on driving traffic to a blog. Especially given the spammy nature of its promotion.

As an aside, and I wouldn't want to distract from the fantasy here with actual facts, but Puppet is getting native Ruby base DSL some time soon and so will please both sides of that particular fence.

[Aug 03, 2010] Introduction to Puppet Streamlined System Configuration

Puppet packages should be available for most major distros already. Just search for puppet using your package manager of choice. For example, on Ubuntu 10.04 you'd want puppet and puppet-common for the managed systems, and puppetmaster for the central server (if you have multiple systems). You might also want the vim-puppet package if you'll be writing Puppet manifests in Vim, or puppet-el if you want to write manifests in GNU Emacs.

When you're working with Puppet, you're working with resources. Users, packages, files, services, etc. A resource describes something on your system. You can find the standard types on the language resource guide on Puppet Labs' site. Some resources are standard across all OSes (like files) others are OS-dependent (like zfs and zone, which are Solaris-only).

For single systems, you'll usually use puppet to execute a manifest. Remember, a manifest is a file containing a set of resources and instructions on how that resource should be configured or manipulated.

Puppet also has a shell that you can use to execute Puppet commands and configure a local system. The Resource Abstraction Layer Shell (ralsh) can list resources, and operate on resources. Here's a simple example to verify whether a user exists on the system using ralsh:

ralsh user norm

If norm doesn't exist as a user account on the system yet, you'll see this:

user { 'norm':
    ensure => 'absent'

This is Puppet providing the current system configuration, as expressed in the Puppet language. This is how you'd write a manifest to remove the user norm from a system. What if we want to add norm as a user with ralsh? Easy:

ralsh user norm

Ridiculously easy, isn't it? That will create norm with some sane defaults. Here's the manifest that ralsh executes:

user { 'norm':
    uid => '1001',
    ensure => 'present',
    gid => '1001',
    home => '/home/norm',
    shell => '/bin/sh'

You'd write that up as a manifest and run it using puppet on your local system. What if we want to make norm's shell bash instead of sh? Let's look at that as a manifest:

user { 'norm':
    uid => '1001',
    ensure => 'present',
    gid => '1001',
    home => '/home/norm',
    shell => '/bin/sh'

Copy that to a file, like norm.pp, and change the shell line to shell => '/bin/sh'. Then run puppet norm.pp. Puppet will check the user, and make the changes necessary so that the user conforms to the manifest.

So how is this easier than running the commands to create a new user on your system? On a single system, it's not. What if you need to create the user on 20 systems, though? Much, much easier. And this would work on Linux, Mac OS X, FreeBSD, and more.

This has been a pretty quick overview of how Puppet works on a single system. In the next tutorial, we'll look at configuring Puppet to manage multiple systems and how to make changes across different distros

Selected Comments

Paul Ivanov:

mudfly, the beauty of Puppet is that you build and manage system configurations, as Joe described, which can then be realized by any machine running the puppet client (be it real or virtual).

Once you define the different configurations, you don't have to have a copy of the huge VM images for each. In the most minimal extreme, you just need one VM that has a puppet client, and now you can transform it into any of your configurations by changing e.g. its hostname or the configuration provided by the puppetmaster.

It's also a lot more elegant to version control your configurations, since they are just small text files, not the gigabytes of libraries and binaries which might even be identical from one VM image to the next.

I tried to explain some of this in the comments section here , that while virtual machines help you contain different configurations, keeping track of the changes/differences between virtual machines becomes and increasingly difficult proposition.

The Puppet way is to work on the configuration, instead of directly on the images - and have the images conform to the configuration by running the puppet client. There are legitimate reasons to keep around multiple images (it's faster to get up and running, disk space is cheap, etc), but if you're using puppet, making changes to the images in "lock-step" as well as keeping track of the resources in each image becomes a lot less painful.

[Aug 03, 2010] Puppet: configuration management made easy by Sam Varghese

April 28, 2009 | iTWire

UNIX system administrators normally use Perl, Python or shell scripts for their scripting needs; Puppet is written in Ruby but one doesn't need to learn Ruby to use it. "You don't need to learn Ruby to use Puppet. It's all under the covers. If you want to extend Puppet - it's quite easily extensible - then yes, you're going to have to pick up some Ruby along the way," Turnbull clarifies.

"Our primary desire is to make it easier for sys admins to do things without every script. Luke's very fond of saying SSH always isn't the solution. And he's quite right, because my big problem with this is that I've worked in a number of different organisations where I've done exactly that - I've written Perl or Python scripts or bash scripts, and numerous things, and every single organisation almost certainly one starts from scratch.

"I have a collection of Perl and bash scripts to manage a whole lot of environments - well-maintained, well documented. Sometimes I can't take them with me because of the organisation's IP. Puppet's an attempt to get rid of that whole model. Instead of every shop having to start from scratch and writing your provisioning script, or your management script, or your user management process, or setting the root password on all of your hosts, you can do it through Puppet. It's one language, it's all described the same way.

"There are a lot of systems administrators who don't do a lot of scripting, particularly people who manage small- to medium-sized businesses. You may be the systems administrator but you're also the accountant or operations manager. And you're not an IT expert - you just want a simple way of saying, 'well, all my boxes should be up-to-date. All of my boxes need user Bob, because I'm user Bob, and I need to assign all the boxes and they need to have the same password'.

"Puppet is designed to be a low level of entry for your average systems administrator. Other from the domain specific language, they don't need to learn a new one, and the DSL's very simple. It contains some programmatic concepts, like if else statements and case statements and things like that, but broadly speaking, it's quite simple."

Turnbull says Puppet is fine for remote environments but the speed at which things get done will, as always, depend on the available bandwidth. "A lot of ISPs use Puppet. There's nothing wrong with having the master just sitting in Melbourne and connecting clients. We're not depending on how many hops you have between you and your host. There'll be some performance issues. Puppet has an ability to serve files out to hosts. If you're copying large amounts of files you can have a performance hit there. There's also a lot of people who create a model of a centralised puppet master and child masters, some kind of a distributed hierarchy."

Running Puppet Master under Apache and Passenger – CentOS 6.4

I have been running my puppetmaster using the embedded WEBrick server for a while. I decided it was time to migrate to something a little more robust – namely Apache and Passenger. I loosely followed the documentation available on the Puppet site, although that covers Passenger 3.0.x and I'm using 4.0.x, and the supplied Apache configuration does not work. There were also a few other changes I had to make along the way to suit my configuration requirements. My puppetmaster is running CentOS 6.4.

Related posts:
  1. Adding Puppet DB to a CentOS 6.4-based puppetmaster
  2. Implementing Git Dynamic Workflows with Puppet
  3. Apache httpd: How to Use htpasswd to Password Protect Areas of your Site
  4. Puppet Module: apache2: VirtualHost templates
  5. Puppet Module: security::tcpwrappers with Hiera

Recommended Links



Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy


War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes


Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law


Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D

Copyright © 1996-2021 by Softpanorama Society. was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site


The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: March 12, 2019