Open Source Puppet – Quick Start


This post aims to be your quickest guide to get started with Puppet. We’ll be using the open source version of Puppet. An hour of spare time and two Ubuntu machines (physical or virtual doesn’t matter) is all that is needed.

Quick Introduction

Lets say you want to install and run apache server on one of the machines in your lab. On another, you want to create a new user. On a third machine, you want to install MySQL, and allow access to this machine only from the first server. Seems like a lot of manual work isn’t it? The power of Puppet is, you can specify all these tasks in a file, called ‘Puppet manifest’, and then execute it. Everything will be set up for you just as you wanted! Now what makes this ‘I care about the end result, not the process’ approach really powerful is you can ‘apply’ this manifest over and over again to get the same end result. You can easily modify this manifest file, extend it, and manage it under version control, just like you would with a piece of software. Welcome to the world of IT automation ūüôā

Although the syntax of a Puppet manifest is Ruby-ish, no knowledge of Ruby is required at all (I don’t know Ruby).

There is a whole lot of things you can do with Puppet. Here, we’ll just get us started with it. Once you are through this post, you can head over to Puppet Labs’ documents and tutorials, for more on “how”s and “why”s of Puppet.


You just require two Ubuntu machines connected to each other. One will be the Puppet ‘master’ node (the machine which will take care of managing the configuration and state of all the machines in our deployment), the other one ‘slave’ (which unfortunately is the only actual machine in demo deployment ūüôā ).

Here I am using two virtual machines, but you can create one virtual machine and use your host machine as the other one. The hostnames of the master and slave in my setup are puppet-master and puppet-agent.

Make sure both the machines are ping-able from each other — by their IP as well as hostnames (e.g.¬†ping¬†and¬†ping puppet-master). Make sure your /etc/hosts file looks something like this to achieve that:

( and are the IP addresses of externally-visible interfaces of hosts puppet-master and puppet-agent respectively)


r@puppet-master:~$ cat /etc/hosts   localhost   puppet-master  puppet-agent


r@puppet-agent:~$ cat /etc/hosts   localhost   puppet-agent  puppet-master

Getting the hands dirty — Puppet CLI

Install puppetmaster package on the master node

sudo apt-get install puppetmaster

List all the users on the current system:

puppet resource user –list

So basically a ‘user’ is a ‘resource’ in Puppet terminology. Now only list a specific resource.¬†r¬†is the current user in my case.

r@puppet-master:~$ puppet resource user r

user { ‘r’:

ensure¬† => ‘present’,

comment => ‘r,,,’,

gid¬†¬†¬†¬† => ‘1000’,

groups¬† => [‘adm’, ‘cdrom’, ‘sudo’, ‘dip’, ‘plugdev’, ‘lpadmin’, ‘sambashare’],

home¬†¬†¬† => ‘/home/r’,

shell¬†¬† => ‘/bin/bash’,

uid¬†¬†¬†¬† => ‘1000’,


Notice the syntax. Resource ‘r’ is of type ‘user’, with ‘ensure’, ‘comment’, etc as keys/attributes, and ‘present’, ‘r,,,’ as values for those attributes.

You can change the value using the Puppet CLI

r@puppet-master:~$ sudo puppet resource user r comment=’some text missing’

notice: /User[r]/comment: comment changed ‘r,,,’ to ‘some text missing’

user { ‘r’:

ensure¬† => ‘present’,

comment => ‘some text missing’,


Create a new user with specified key-value pairs

r@puppet-master:~$ sudo puppet resource user katie ensure=present shell=/bin/bash

notice: /User[katie]/ensure: created

user { ‘katie’:

ensure => ‘present’,

shell¬† => ‘/bin/bash’,


r@puppet-master:~$ sudo puppet resource user katie

user { ‘katie’:

ensure¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† => ‘present’,

gid¬†¬†¬†¬† ¬†¬†¬†¬†¬†¬†¬†¬†¬†=> ‘1001’,

home¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† => ‘/home/katie’,

password¬†¬†¬†¬†¬†¬†¬†¬† => ‘!’,

password_max_age => ‘99999’,

password_min_age => ‘0’,

shell¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† => ‘/bin/bash’,

uid¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† => ‘1001’,


Remove the newly created user, but this time, let’s put this information into a file¬†katie_remove.pp¬†and ask Puppet to ‘apply’ this file and thus removing the user ‘katie’.

r@puppet-master:~$ cat katie_remove.pp

user {‘katie’:

ensure => absent,


Apply this Puppet manifest

r@puppet-master:~$ sudo puppet apply katie_absent.pp

warning: Could not retrieve fact fqdn

notice: /Stage[main]//User[katie]/ensure: removed

notice: Finished catalog run in 0.47 seconds

Puppet’s description of user ‘katie’:

r@puppet-master:~$ sudo puppet resource user katie

user { ‘katie’:

ensure => ‘absent’,


is now same as that of a non-existent user.

r@puppet-master:~$ sudo puppet resource user absent-user

user { ‘absent-user’:

ensure => ‘absent’,


That is, the user ‘katie’ is now deleted. You can see that the ‘ensure’ attribute can be used to make sure a user (or in general, any ‘resource’, is present, or absent).

Note: Ignore the warning which is printed while applying a manifest from a file. Or if you are bothered by it popping up all the time, in the /etc/hosts file, change   puppet-master

to puppet-master

where you can choose a domain name of your own choice in place of

Puppet modules

Note:¬†puppet module¬†doesn’t work on Precise (Ubuntu 12.04). You need to install ruby, and gems, etc. Too much of a hassle. So I’ll just post commands here which work for a higher version of Ubuntu.

Install standard library:

sudo puppet module install puppetlabs/stdlib

View all the installed modules

r@puppet-master:~$ sudo puppet module list


‚Ēú‚ĒÄ‚ĒÄ puppetlabs-mysql (v2.2.1)

‚Ēú‚ĒÄ‚ĒÄ puppetlabs-ntp (v3.0.2)

‚ĒĒ‚ĒÄ‚ĒÄ puppetlabs-stdlib (v4.1.0)

/usr/share/puppet/modules (no modules installed)

All the modules, and all other information in the system goes in /etc/puppet directory.

Note: Modules installed via sudo will be visible when you perform puppet module list with sudo only. Same for non-sudo use.

Puppet in master-client configuration

Everything we did so far concerned with a single machine. Let’s now introduce another machine — Puppet agent.

Note that you need to set FQDNs for both the machines. See the step above, where we suppressed a warning.

First, we’ll need to install¬†puppet¬†package (the agent) on the agent node.

sudo apt-get install puppet

By default, the Puppet agent service will not be running.

r@puppet-agent:~$ sudo service puppet status

* agent is not running

Before starting it, change START=no to START=yes in /etc/default/puppet file, to start the agent service by default when the system starts/reboots.

sudo sed -i s/START=no/START=yes/g /etc/default/puppet

And add these two lines at the end of /etc/puppet/puppet.conf to allow the agent to discover the master by its FQDN.


server = puppet-master

Now start the Puppet agent service

r@puppet-agent:~$ sudo service puppet start

* Starting puppet agent                                   [ OK ]

I also make sure that clocks of both the machines are synchronized by running¬†ntpdate¬†on both master and slave. I am not sure if this is required, but doesn’t do any harm. sudo ntpdate

Now the master needs to sign the certs by agent.

Execute this command on agent node.

sudo puppet agent –test –waitforcert 60

Now hop over to the master node, and retrieve the list of certs waiting to be signed

r@puppet-master:~$ sudo puppet cert –list

“” (EB:0F:E4:14:6F:B2:7E:85:7E:21:26:C4:78:80:58:E1)

Sign the cert

r@puppet-master:~$ sudo puppet cert sign

notice: Signed certificate request for

notice: Removing file Puppet::SSL::CertificateRequest at ‘/var/lib/puppet/ssl/ca/requests/’

Now we are ready to go. Let’s create a file (‘Puppet manifest’) on master where we write that: 1. We want apache package to be installed. 2. Once we ensure that the package is installed, we want to start the apache service. We’ll name the file¬†site.pp, which is the ‘main’ configuration file for Puppet. We’ll put it into¬†/etc/puppet/manifests¬†directory. Note how we can specify a dependency between resources.

package { ‘apache2’:

ensure => installed


service { ‘apache2’:

ensure => true,

enable => true,

require => Package[‘apache2’]


Puppet works on ‘push’ model, meaning configurations are pulled by agents at periodic intervals. I think the default periodic interval is 30 minutes. Alternatively, you can pull from agent at your own will, any time. Let’s do that now. Execute this command on the agent:

r@puppet-agent:~$ sudo puppet agent –test

info: Caching catalog for

info: Applying configuration version ‘1397343482’

notice: /Stage[main]//Package[apache2]/ensure: ensure changed ‘purged’ to ‘present’

notice: Finished catalog run in 6.30 seconds

And you can see the apache server running!

r@puppet-agent:~$ sudo service apache2 status

Apache2 is running (pid 5874).

Ta! Da!

Please comment if you have any ideas to make this post easier for the newbies to understand.



This is just a quick start guide. There are excellent resources and docs at¬† I have their beginner’s¬†PDF¬†saved in my DropBox. Around 80 pages long, it covers almost every aspect of basic Puppet. The only problem with this guide is it is (I think deliberately) made to work only with the Enterprise Puppet version, but you can always refer back to this post to know how to set the open source version ūüôā

If you mess up the cert signing process, here is a quick and dirty way to get it resolved. On master:

sudo puppet cert clean

On both master and slave: sudo rm -r /var/lib/puppet/ssl sudo service puppet restart

Thats all the Puppet set up has been done easily, Thanks for reading !!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s