Manage puppet agents, master/passenger, multiple developers, and host multiple agent sites




8,899 latest version

2.9 quality score

Version information

  • 0.2.4 (latest)
  • 0.2.3
  • 0.2.2
  • 0.2.1
  • 0.2.0
  • 0.1.1
  • 0.1.0
  • 0.0.2
  • 0.0.1
released Jan 30th 2014

Start using this module


foolean/puppet — version 0.2.4 Jan 30th 2014


This module handles the management of puppet agents as well as the puppetmaster. Puppetmaster invocations have the option of running the standard webrick (the default) or passenger. Multiple environ- ments are created to provide for a three-tiered development archit- ecture. These environments create 'production', 'development', and individual 'developer' areas. This module also provides for the management of additional environments for the purposes of providing puppet services to multiple sites (see CAVEAT below).


node myagent { class { 'puppet': mode => 'agent', } }

accomplishes the same thing done for 'myagent' above

node myotheragent { class { 'puppet': } }

Agent with different tidying requirements

node smallagent { class { 'puppet': tidy_age => '4w', } }

node mymaster { class { 'puppet': mode => 'master', clients => [ 'host1', 'host2', etc ], modules => [ 'foolean-ssh' ], } }

A puppetmaster with different tidying requirements (5yrs)

node mylongtermmaster { class { 'puppet': mode => 'master', clients => [ 'host1', 'host2', etc ], tidy_age => '260w', modules => [ 'foolean-ssh' ], } }

A puppetmaster running passenger

node myothermaster { class { 'puppet': mode => 'passenger', workers => 5, clients => [ 'host1', 'host2', etc ], developers => [ 'user1', 'user2', etc ], modules => [ 'foolean-ssh' ], } }

A puppetmaster running passenger and multiple sites

node mysitemaster { class { 'puppet': mode => 'passenger', workers => 5, clients => [ 'host1', 'host2', etc ], developers => [ 'user1', 'user2', etc ], modules => [ 'foolean-ssh' ], sites => { 'site1' => { 'clients' => [ 'host1', 'host2', etc ], 'developers' => [ 'user1', 'user2', etc ], }, 'site2' => { 'clients' => [ 'host1', 'host2', etc ], 'developers' => [ 'user1', 'user2', etc ], }, }, } }



Puppet allows for the execution of arbitrary ruby code on the puppetmaster. This can be accomplished in manifest files by using the inline_template function or in template files themselves. The arbitrary code will execute in the context of the puppet daemon, typically uid:puppet, gid:puppet. While it limits the scope of readable and writable files over the entire file system it does also mean that any file puppet can read so can anyone with the rights to upload manifests and templates. Because of this "feature" there is no way to ensure privacy between sites.

Manifest Example:

# Grab the puppet.conf file (extra vars to ease 80-char wrapping)
$config_file = "${settings::confdir}/${settings::config_file_name}"
$foo = inline_template( "<%= %x{ cat ${config_file} } %>" ) 
notify { 'show-foo': message => $foo }

Template Example
        hostname -f;
        id ;
        echo "#"
        echo "# uid=puppet and writable"
        find / -type f -user puppet -perm -u=w  -ls
        echo "#"
        echo "# gid=puppet and writable"
        find / -type f -group puppet -perm -g=w  -ls
        echo "#"
        echo "# world writable"
        find / -type f -perm -o=w -ls
        echo "#"
        echo "# facter information"

About this module

Q. Shouldn't the Apache2 controls be in an Apache module instead of here?

This is an experiment to see if it is posisble to have this class be indepedent of any other classes. Ordinarily functionality such as the Apache2 controls would be handled by an Apache module so that enhancements will be carried through to all classes who utilize it. The a2ensite, a2dissite, and a2enmod defines are innocuous enough that their structure should not need to change. It is also the hopes of this module that it will not conflict with other Apache modules. In the future, a Foolean Apache module will be created. This module may depend on the Apache module only if conflicts can not be avoided. In the end, this is all an attempt to publish useful modules without having to foist additional modules upon the adopter.


This module requires puppet version 2.7 or greater.

For CentOS and RedHat this can be found on the RepoForge site as the EPEL site is still publishing v2.6.18

Note: Even as of SLES 11-SP3, Novell SUSE is still using v2.6.18.

Supported Operating Systems

Primary development is done on Debian and then validated against other operating systems. The current list of supported operating systems is:

|  OS      | Bootstrap | Puppet | Puppetmaster | Passenger |
| CentOS   |    yes    |  yes   |     yes      |    Yes    |
| Debian   |    yes    |  yes   |     yes      |    Yes    |
| Fedora   |    yes    |  yes   |     yes      |    Yes    |
| OpenSUSE |    yes    |  yes   |     yes      |    Yes    |
| RedHat   |    yes    |  yes   |     yes      |    Yes    |
| Ubuntu   |    yes    |  yes   |     yes      |    Yes    |


  • General: Puppet doesn't seem to be able to both stop puppetmaster and start Apache in the same run. Just manually start Apache after the first puppet run when switching to passenger. This should get fixed in a future release.

  • OpenSUSE: OpenSUSE requires that the modules be added to the APACHE_MODULES variable in /etc/sysconfig/apache2.

    The following modules are required for Puppet's Passenger:

    • headers
    • lbmethod_byrequests
    • passenger
    • proxy
    • proxy_balancer
    • proxy_http
    • slotmem_shm
    • socache_shmcb
    • version
  • RedHat: There are a number of packages that are required to run passenger that are not in the EPEL or RepoForge repositories. They are however, in the RedHat subscription repository. If you are experimenting with the RedHat operating system and do not have a subscription, you can install the missing packages from a CentOS repository.

    The missing packages are:

    • rubygems
    • ruby-docs
    • ruby-rdoc
    • ruby-irb
    • rubygem-rake


The passenger configuration created by this module does not function properly under SELinux at this time. This can be fixed by dropping back to permissive mode and running audit2allow after a client runs against the server. SELinux support will be addressed in a future release.

Directory Structure

To facilitate host multiple sites, this module creates and relies on the following directory structure.

`-- default
    |-- development
    |   |-- manifests
    |   |   `-- site.pp
    |   |-- modules
    |   |   |-- puppet
    |   |   `-- [ other modules ]
    |   `-- private
    |       `-- [ fqdn ]
    |-- developers
    |   `-- [ developer ]
    |       |-- manifests
    |       |   `-- site.pp
    |       |-- modules
    |       |   |-- puppet
    |       |   `-- [ other modules ]
    |       `-- private
    |           `-- [ fqdn ]
    `-- production
        |-- manifests
        |   `-- site.pp
        |-- modules
        |   |-- puppet
        |   `-- [ other modules ]
        |-- private
            `-- [ fqdn ]

File and Directory Permissions

Puppet, by default, will attempt to manage the permissions and ownership of the various files within the $vardir structure. In doing so a number of the objects will end up with world readable permissions and ownership other than the puppet user or group. In order to allow this module to manage the permissions and ownership the 'manage_internal_file_permissions' options is set to 'false' in the main configuration block of puppet.conf.

This module will then to remove all 'world' permissions and set ownership to the puppet user and puppet group as there is really no reason for any other users to access the puppet files. The premis is that only an administrator (e.g. someone with root) should be running puppet on a system. Likewise only an administrator or someone in the puppet group should be looking at any of the puppet files.

Even with all of this there are still a couple of areas where puppet itself still tries to enforce ownership.

Prerun and Postrun commands

This module uses a cron.d like format to handle prerun and postrun commands. Scripts should be placed in either $confdir/pre-run.d or $confdir/post-run.d. The 'rundir' script will execute any executable script found in the respective directory. This enables modules to add pre and post run processing much in the same manner that cron.d is handled. Script precedence can be achieved by adding numerical prefixes such as pre-run.d/00_etckeeper.

Example: prerun_command = /etc/puppet/rundir pre postrun_command = /etc/puppet/rundir post

NOTE: The 'rundir' script utilizes the PUPPET_NOOP variable, which is set by the facter script isnoop.rb to skip the running of the prerun and postrun scripts when running with --noop turned on.

CAUTION: This will run any executable script found in the pre and post run directories. It is for this reason that only root should be allowed to write into them. Allowing the puppet user to write into these directories will allow anyone with the ability to add recipees to the system to run arbitrary code on the agents. Like cron.d these will, more often than not, get run as root so care should be taken regarding the content that gets added.


Creating the package (tarball) that can be installed using puppet's module function is simple. Run the following command while in the top of the module directory (e.g. /usr/src/puppet-puppet).

puppet module build .

The resulting tarball will be named foolean-puppet-$VER.tar.gz and can be found in the "pkg" directory within the source tree.

PuppetForge Installation

Foolean Puppet is on PuppetLab's PuppetForge making installation as simple as:

puppet module install foolean/puppet

Manual Installation

When we're installing from a tarball the installation and upgrade process is the same. You'll need to set --modulepath if f you're installing the module in a path other than the location defined in puppet.conf.

puppet module install         \
    --force                   \
    --ignore-dependencies     \
    --module-path $MODULEPATH \


When going for complete deterministic installations we will quickly find ourselves in chicken/egg territory. We use puppet to ensure determinism in our systems but how do we get puppet onto a new puppetmaster when an existing puppetmaster doesn't exist? That is the purpose of the "bootstrap.pp" file. The first time the operating system comes up after install the following steps can be run to bootstrap the puppetmaster.

# install puppet
apt-get install puppet

# retrieve the bootstrap.pp file
wget https://raw.github.com/foolean/puppet-puppet/master/manifests/master/bootstrap.pp

# run the bootstrap process (add --noop if you want to review first)
puppet apply --detailed-exitcodes --verbose ./bootstrap.pp

# run puppet again to configure the system as a puppetmaster
puppet agent --test

To Do

  • Add SELinux support


Copyright (c) 2013 Foolean.org

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at


Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.