Installing Puppet on Mac OS X
Puppet
Puppet is an open source (with enterprise version and support available) client/server tool from Puppet Labs to facilitate the configuration and management of computer systems.
Written in ruby and available on many platforms, it offers a DSL that allows the "programming" of operational tasks across many machines.
The DSL covers abstracting the computer resources in a extensible way, and providing structure like class, modules and graphs that a configuration language can manipulate.
The server is called puppet master. It controls a puppet agent installed on client machines that are to be managed. In addition of master and agent, there are puppet apply for stand alone use and puppet resource for accessing the Puppet resource abstraction layer.
Its extensibility makes it future proof and there are providers (implements a resource abstraction in Puppet) for many platforms like Virtual box VMs and Amazon EC2.
The communication between clients and server is secured using SSL certificates.
This post is mainly for me so I can remember how I did install Puppet on Mac OS X and to allow me to repeat it on many mac systems.
The install basically boils down to running a script I put on Gist (assuming you want to install Puppet 2.7.11 with Facter 1.6.6 on a startup disk called Macintosh HD):
bash -s 1.6.6 2.7.11 /Volumes/Macintosh\ HD < <(curl -s https://raw.github.com/gist/1895594/install_puppet_mac.sh)
The remainder of the post describes the gory details. I'll keep this post updated as I learn more about the idiosyncrasies of Puppet on Mac.
Deployment environment
I've tested these instructions on Mac OS X Lion (10.7.3) and Mac OS X Snow Leopard (10.6.8).
Downloading necessary files
For Mac OS X, there is a .pkg available for Facter and Puppet downlable from Puppet Lab web site:
http://downloads.puppetlabs.com/mac/
There are several versions available on that site.
For the purpose of this post, we will consider version 1.6.6 and 2.7.11 for Facter and Puppet respectively.
Puppet depends on Facter, so you need both. These are Mac OS X package on the site above.
There is another blog post [1] describing a way to install Puppet from source but the source links didn't work for me when I tried.
Installation steps
Unpack the dmg
hdiutil attach facter-1.6.6.dmg
hdiutil attach puppet-2.7.11.dmg
Install the pkg
sudo installer -package /Volumes/facter-1.6.6/facter-1.6.6.pkg -target /Volumes/Macintosh\ HD
sudo installer -package /Volumes/puppet-2.7.11/puppet-2.7.11.pkg -target /Volumes/Macintosh\ HD
Create the puppet group and user
In other systems, the packaging may include the creation of the necessary puppet user and group.
The packages for Mac OS X don't do that. Although it's possible to create these when starting the puppet master with the --mkusers options, I prefer create then before hand during installation.
max_gid=$(dscl . -list /Groups gid | awk '{print $2}' | sort -ug | tail -1)
new_gid=$((max_gid+1))
dscl . create /Groups/puppet
dscl . create /Groups/puppet gid $new_gid
max_uid=$(dscl . -list /Users UniqueID | awk '{print $2}' | sort -ug | tail -1)
new_uid=$((max_uid+1))
dscl . create /Users/puppet
dscl . create /Users/puppet UniqueID $new_uid
dscl . -create /Users/puppet PrimaryGroupID $new_gid
Create directories
mkdir -p /var/lib/puppet
mkdir -p /etc/puppet/manifests
mkdir -p /etc/puppet/ssl
Change permission on directories
chown -R puppet:puppet /var/lib/puppet
chown -R puppet:puppet /etc/puppet
Create puppet.conf
There are several sections, each relevant only to different puppet subcommands except for [main] which is global.
If puppet is running on a client ensure the server property is set to the machine running puppet master instead of local hostname as here.
echo "[main]
pluginsync = false
server = `hostname`
[master]
vardir = /var/lib/puppet
libdir = $vardir/lib
ssldir = /etc/puppet/ssl
certname = `hostname`
[agent]vardir = /var/lib/puppetlibdir = $vardir/libssldir = /etc/puppet/sslcertname = `hostname`
" > /etc/puppet/puppet.conf
Putting it all together
As I needed to install Puppet on more than one mac, I've made a script, inspired by trevmex's tutorial [1], with all the steps together:
bash -s 1.6.6 2.7.11 /Volumes/Macintosh\ HD < <(curl -s https://raw.github.com/gist/1895594/install_puppet_mac.sh)
(Some of the steps uses sudo, so login password will be asked)
In the example above I've passed the version of Facter, the version of Puppet and my system disk as parameter to the script.
Create a hello world puppet class
Create the file /etc/puppet/manifests/site.pp with the following content:
import "nodes"
Create the file /etc/puppet/manifests/nodes.pp with the following content:
node default {
notify {"Hello World":;}
}
Run the example:
puppet apply /etc/puppet/manifests/site.pp
you should see something like:
notice: Hello world
notice: /Stage[main]//Node[default]/Notify[Hello world]/message: defined 'message' as 'Hello world'
notice: Finished catalog run in 0.02 seconds
Setting up puppet in client/server mode
Testing on the same computer
Run the puppet master
sudo puppet master --verbose --no-daemonize
You should see something like:
notice: Starting Puppet master version 2.7.11
Run the puppet agent in a separate shell by typing:
sudo puppet agent --test --server=`hostname`
You should see something like:
info: Caching catalog for wall-e.home
info: Applying configuration version '1330800282'
notice: Hello world
notice: /Stage[main]//Node[default]/Notify[Hello world]/message: defined 'message' as 'Hello world'
info: Creating state file /var/lib/puppet/state/state.yaml
notice: Finished catalog run in 0.02 seconds
Between computers (or virtual machines)
install Puppet using the shell script above.
If you run the agent as above, you'll get this error:
Exiting; no certificate found and waitforcert is disabled
on the server, ensure puppet master is running, then
on the client machine, ensure puppet.conf has the server property set to the hostname of the server (or use --server in the command below) and do:
sudo puppet agent –waitforcert 60 –test --debug --no-daemonize
then on the server, on the a different shell than the on running puppet master, do:
<span class="kw2">sudo</span> puppetca <span class="re5">--sign</span> <hostname of the client machine>
until the command above is run on the server, the client will output the following message:
notice: Did not receive certificate
Then when the command to issue a certificate is run on the server, the server will output:
notice: Signed certificate request for <client host name>
notice: Removing file Puppet::SSL::CertificateRequest mc-s056627.home at '/etc/puppet/ssl/ca/requests/<client hostname>.pem'
and the client will output:
info: Caching certificate for <client hostname>
Revoking a client's privilege to connect to the Puppet master
the client certificate's name is the lowercase hostname
To revoke a client's certificate and thus deny it's connection attempts, it's a two steps process.
First on the server, revoke the certificates:
sudo puppetca --revoke <client host name>
Then on the client, remove the certificates:
sudo rm -rf /etc/puppet/ssl
In some circumstances, you will need to use the following command to completely remove the client certificate from the master:
sudo puppet cert clean <client hostname>
Gotchas
Ruby errors:
If you encounter one of the following errors:
/usr/bin/puppet:3:in `require': no such file to load -- puppet/util/command_line (LoadError) from /usr/bin/puppet:3/usr/sbin/puppetd:3:in `require': no such file to load -- puppet/application/agent (LoadError) from /usr/sbin/puppetd:3
it's probably because you've got rvm installed.
You can make the problem go away by using system ruby:
rvm use system
I'm not happy about that solution, but I haven't find a better way so far.
Error about plugins when running the puppet agent:
If you see this error in the agent log:
info: Retrieving plugin
err: /File[/var/lib/puppet/lib]: Could not evaluate: Could not retrieve information from environment production source(s) puppet://wall-e.home/plugins
The puppet master log would correspondingly display this:
info: Could not find filesystem info for file 'plugins' in environment production
info: Could not find file_metadata for 'plugins'
ensure you've set pluginsync to false in the puppet.conf: pluginsync = false
Certificates errors:
so far, I solved them by deleting the /etc/puppet/ssl directory on client and master
What if problems occur
-
use --debug and --verbose options to puppet commands
-
use --configprint to dump the value of a config property. E.g: puppet apply --configprint modulepath
-
use the notify keyword in your classes to print custom debug information
-
check the documentation
Links
[1] http://trevmex.com/post/850520511/bootstrapping-puppet-on-mac-os-x
Language guide: http://docs.puppetlabs.com/guides/language_guide.html
Modules and classes: http://docs.puppetlabs.com/learning/modules1.html
Core Types Cheat sheet: http://docs.puppetlabs.com/puppet_core_types_cheatsheet.pdf