Close

Configuration Management on Raspberry Pi with Puppet

Puppet is an open-source configuration management tool that helps automate the deployment and management of files and applications on target hosts. A puppet master contains the definition of the desired configurations in files called manifests or modules. Agents can query the master in order to know which configuration changes to apply.

Screen Shot 2016-06-02 at 19.16.55

puppet labs logo from Puppet Keynote by Luke Kanies

In this post, I will cover the installation of the puppet master and puppet agent, along with a simple example manifest. I intend to fully puppetize my project, delivering a set of manifests and modules, making it possible to recreate it with minimal effort.

Let’s get puppetizing!

Preparation

For this guide, I am using a Raspberry Pi 3 running the latest version of Jessie.

After connecting via SSH (via ethernet or wifi), the file system was expanded using “raspi-config”:

Screen Shot 2016-05-29 at 14.29.35

Using the same application, the hostname was changed to “puppet”:

Screen Shot 2016-05-29 at 14.29.58 Screen Shot 2016-05-29 at 14.30.07

Finally, the software has been fully updated:

pi@puppet:~ $ sudo apt-get update && sudo apt-get upgrade -y

With that taken care of, we can proceed to the actual installation.

Puppet Master

The puppet master holds the definition of every node by means of reusable modules. A node is then defined by a specific combination of modules, in order to obtain a specific role.

Screen Shot 2016-06-02 at 19.14.57

Lifecycle of a Puppet Run from Puppet Keynote by Luke Kanies

Installation & Configuration

Installing puppet master is straightforward and can be done using the following command:

pi@puppet:~ $ sudo apt-get install puppetmaster-passenger
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
apache2 apache2-bin apache2-data apache2-utils augeas-lenses facter hiera libapache2-mod-passenger libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaugeas0 libev4 libjsoncpp0 liblua5.1-0 libpci3 pciutils puppet-common puppetmaster-common
ruby-activemodel ruby-activerecord ruby-activerecord-deprecated-finders ruby-activesupport ruby-arel ruby-atomic ruby-augeas ruby-blankslate ruby-builder ruby-hiera ruby-i18n ruby-json ruby-minitest ruby-passenger ruby-rack ruby-rgen ruby-safe-yaml ruby-selinux
ruby-shadow ruby-thread-safe ruby-tzinfo ssl-cert virt-what
Suggested packages:
apache2-doc apache2-suexec-pristine apache2-suexec-custom augeas-doc mcollective-common augeas-tools ruby-rrd librrd-ruby puppet-el ruby-ldap ruby-stomp stompserver vim-puppet ruby-builder-doc rails ruby-passenger-doc openssl-blacklist
The following NEW packages will be installed:
apache2 apache2-bin apache2-data apache2-utils augeas-lenses facter hiera libapache2-mod-passenger libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaugeas0 libev4 libjsoncpp0 liblua5.1-0 libpci3 pciutils puppet-common puppetmaster-common
puppetmaster-passenger ruby-activemodel ruby-activerecord ruby-activerecord-deprecated-finders ruby-activesupport ruby-arel ruby-atomic ruby-augeas ruby-blankslate ruby-builder ruby-hiera ruby-i18n ruby-json ruby-minitest ruby-passenger ruby-rack ruby-rgen
ruby-safe-yaml ruby-selinux ruby-shadow ruby-thread-safe ruby-tzinfo ssl-cert virt-what
0 upgraded, 44 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,905 kB of archives.
After this operation, 23.8 MB of additional disk space will be used.
Do you want to continue? [Y/n]

It will install the necessary dependencies.

Once installed, you should be able to query puppet to verify the installed certificates:

pi@puppet:~ $ sudo puppet cert --list --all
+ "puppet.home" (SHA256) 03:2D:C0:4A:33:FC:C7:A0:3B:45:A0:41:DC:B6:B4:97:3B:B3:32:39:67:3B:F5:69:17:C4:B9:46:50:EE:D7:99 (alt names: "DNS:puppet", "DNS:puppet.home")

When new agents will attempt to perform a puppet run, a certificate will be generated on the master. Only when it is signed by the master, will the agent be able to successfully perform the puppet run.

To start or stop the puppet master, simply call the apache2 service:

pi@puppet:~ $ sudo service apache2 status|start|stop|restart

Manifests & Modules

In puppet, manifests describe the configuration actions to be performed. This can be as simple as ensuring a certain file with specific content is present (or absent), but also more advanced like automatically installing and configuring a certain application.

To test the installation of the puppet master, a simple manifest can be used.

pi@puppet:~ $ sudo nano /etc/puppet/manifests/site.pp
file { '/tmp/testfile':
ensure   => present,
mode     => '0444',
content  => 'test content',
}

This manifest will ensure the file “testfile” is present in the “/tmp” folder, with read permission containing the text “test content”. If the file doesn’t exist, or the permissions or content are not as expected, puppet will correct it accordingly.

This example showcases a standalone manifest. Manifests can be combined with files and templates into a module. The purpose of the module is to complete a set of related actions, such as installing an application and configuring it for example.

Let’s install the agent and test out this manifest.

Puppet Agent

Puppet agent’s role is to retrieve the local machine’s configuration by contacting the Puppet Master, retrieve the configuration and apply it.

For this purpose, I used a second Raspberry Pi. I used the same preparation steps, except I gave it a different hostname: “piiot1”.

Installation

Installing and activating the agent is as easy as installing the master:

pi@piiot1:~ $ sudo apt-get install puppet

Once the agent is installed, an initial “puppet run” is required to generate the certificate on the master:

pi@piiot1:~ $ sudo puppet agent -t
Info: Creating a new SSL key for piiot1.home
Info: csr_attributes file loading from /etc/puppet/csr_attributes.yaml
Info: Creating a new SSL certificate request for piiot1.home
Info: Certificate Request fingerprint (SHA256): D2:C5:40:64:A0:B9:C2:90:A0:19:EE:BF:24:3F:87:95:3E:33:38:26:48:07:1B:6B:A7:BD:10:73:D3:F7:75:F7
Exiting; no certificate found and waitforcert is disabled

On the puppet master, it is possible to list the certificates. The certificate for node “piiot1” is not signed yet, preventing the actual execution of the manifest.

pi@puppet:~ $ sudo puppet cert --list --all
"piiot1.home" (SHA256) D2:C5:40:64:A0:B9:C2:90:A0:19:EE:BF:24:3F:87:95:3E:33:38:26:48:07:1B:6B:A7:BD:10:73:D3:F7:75:F7
+ "puppet.home" (SHA256) 03:2D:C0:4A:33:FC:C7:A0:3B:45:A0:41:DC:B6:B4:97:3B:B3:32:39:67:3B:F5:69:17:C4:B9:46:50:EE:D7:99 (alt names: "DNS:puppet", "DNS:puppet.home")

On the same master, the certificate can be signed, as the node is known to be part of our setup.

pi@puppet:~ $ sudo puppet cert sign piiot1.home
Notice: Signed certificate request for piiot1.home
Notice: Removing file Puppet::SSL::CertificateRequest piiot1.home at '/var/lib/puppet/ssl/ca/requests/piiot1.home.pem'

A “+” sign is added in front of the certificate, indicating it is signed.

pi@puppet:~ $ sudo puppet cert --list --all
+ "piiot1.home" (SHA256) 23:44:D3:B6:70:68:77:F9:9E:A7:EB:72:09:E9:F1:67:FA:24:53:47:99:BB:D9:2F:74:A1:CC:3E:50:76:55:01
+ "puppet.home" (SHA256) 03:2D:C0:4A:33:FC:C7:A0:3B:45:A0:41:DC:B6:B4:97:3B:B3:32:39:67:3B:F5:69:17:C4:B9:46:50:EE:D7:99 (alt names: "DNS:puppet", "DNS:puppet.home")

With the certificate signed, it is now possible to perform a puppet run and execute the actions defined in the manifest.

Puppet Run

Repeating the same command to perform the puppet run, now results in the execution of the manifest defined on the master:

pi@piiot1:~ $ sudo puppet agent -t
Info: Caching certificate for piiot1.home
Info: Caching certificate_revocation_list for ca
Info: Caching certificate for piiot1.home
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for piiot1.home
Info: Applying configuration version '1464532909'
Notice: /Stage[main]/Main/File[/tmp/testfile]/ensure: created
Notice: Finished catalog run in 0.10 seconds

The test file has been created, has the required permissions and content:

pi@piiot1:~ $ ls -l /tmp/testfile
-r--r--r-- 1 root root 12 May 29 16:41 /tmp/testfile
pi@piiot1:~ $ cat /tmp/testfile
test content

Conclusion

Success! Puppet master and agent have successfully been deployed. We can now continue by defining more elaborate manifests and modules which will help us simplify future deployments.

It may be hard to grasp or see the advantages of setting up puppet based on this example, but instead of deploying a simple file, imagine this “puppet run” installing and configuring a set applications. Sounds rather neat, right? That’s what you can expect for in a future post!

© Frederick Vandenbosch, 2014-2021. Unauthorised use and/or duplication of this material without express and written permission from this blog’s author and owner is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to Frederick Vandenbosch with appropriate and specific direction to the original content.