Teaching Puppet Configuration Management in The National Library of Finland

Packing up after the course on Friday evening. Photo courtesy of Emma.


I’m very happy to get a change to talk about Puppet in the National Library of Finland. Working with experienced professionals makes an interesting day. I have used their Finto ontology to create one of the largest free Finnish-English dictonaries and enjoyed many services they provide.
Course feedback was very good, 4.4 out of 5. One participant named this as the best course this person had ever participated. Thank you!


These are some notes and scribbles mentioned in the training. This is not a tutorial on Puppet, just some snippets listed to avoid writing them down manually.

REDACTED
This page does not contain all of the
course, due to practical reasons and
confidentiality.
For example, missing are
- Theory on Configuration Management Systems
- Architectural and practical questions related to National Library network
- Security questions related to National Library
I still hope that the practical, hands-on commands below are useful.

Key Features of Modern Configuration Management Systems

Idempotent
Infrastructure as Code
Single Source of Truth

Interactive Puppet for Testing and Training

$ sudo apt-get update
$ sudo apt-get -y install puppet
$ puppet --version

Help and Documentation

Commands print information specific to your version and system. On the web, check the version.
Sudo is usually required with Puppet. Not just for permissions – also the environment will be different.

$ sudo puppet resource file /etc/passwd
file { '/etc/passwd':
 ensure  => 'file',
 content => '{md5}9d892087544105fee8bec3d1d3ad033c',
 # ...
}
$ puppet describe file|less

Most important resources: package-file-service, user, exec

$ sudo puppet resource file /tmp/foo ensure=file
$ sudo puppet resource file /etc/passwd
$ sudo puppet resource file /root/terowashere ensure=file
$ sudo puppet resource file /root/terowashere ensure=file content="Moi vaan"
$ sudoedit /root/terowashere
$ sudo puppet resource package apache2
$ sudo puppet resource package bash
$ puppet describe package|less
$ sudo puppet resource package apache2 ensure=installed
$ curl localhost
$ curl localhost -s|grep title
$ sudo puppet resource service apache2 ensure=stopped
$ sudo puppet resource service apache2 ensure=running enable=true
$ sudo puppet resource user vagrant
$ sudo puppet resource user terote01 ensure=present managehome=true
$ sudo puppet resource user terote01 ensure=absent managehome=true
$ sudo puppet resource exec
$ puppet describe exec|less
$ sudo puppet resource exec 'touch /tmp/ajettu' path='/usr/bin/:' creates="/tmp/ajettu"

Modules

When you create stuff with Puppet, you create modules. One thing fully configured == one module. For example, apache module to install the package with apt , configure it and restart the daemon.

$ cat /etc/puppet/modules/hellotero/manifests/init.pp
class hellotero {
 file {"/tmp/hellotero":
 content=>"Tero was here\n",
 }
}
$ sudo puppet apply -e 'class {hellotero:}'
Notice: Compiled catalog for vagrant.vm in environment production in 0.11 seconds
Notice: /Stage[main]/Hellotero/File[/tmp/hellotero]/ensure: defined content as '{md5}00e10248f6827939f378f0c4c1f0c511'
Notice: Finished catalog run in 0.02 seconds
$ cat /tmp/hellotero
Tero was here

It’s idempotent: the following runs do nothing, as the system has already reached the target state.

$ sudo puppet apply -e 'class {hellotero:}'
$ sudo puppet apply -e 'class {hellotero:}'

Package-File-Service for Apache

Can you improve the module by adding the missing requires?
Notice the weird syntax inside template(“apache/teroexamplecom.conf”): module/filename. It’s not a path. It does not contain the word “template”.
Two files, some directories:

$ find /etc/puppet/modules/apache/
/etc/puppet/modules/apache/
/etc/puppet/modules/apache/manifests
/etc/puppet/modules/apache/manifests/init.pp
/etc/puppet/modules/apache/templates
/etc/puppet/modules/apache/templates/teroexamplecom.conf

/etc/puppet/modules/apache/manifests/init.pp

class apache {
 package {"apache2":
 ensure => "installed",
 }
 file {"/var/www/html/index.html":
 content=>"Welcome\n",
 }
 file {"/etc/apache2/sites-available/teroexamplecom.conf":
 content=>template("apache/teroexamplecom.conf"),
 notify=>Service["apache2"],
 }
 file {"/etc/apache2/sites-enabled/teroexamplecom.conf":
 ensure=>"symlink",
 target=>"../sites-available/teroexamplecom.conf",
 notify=>Service["apache2"],
 }
 file {"/etc/apache2/sites-enabled/000-default.conf":
 ensure=>'absent',
 notify=>Service["apache2"],
 }
 service {"apache2":
 ensure=>"running",
 enable=>"true",
 require=>Package["apache2"],
 }
}

/etc/puppet/modules/apache/templates/teroexamplecom.conf

<VirtualHost *:80>
 ServerName tero.example.com
 ServerAlias www.tero.example.com
 DocumentRoot /home/vagrant/public_html/
 <Directory /home/vagrant/public_html>
 Require all granted
 </Directory>
</VirtualHost>

Testing

$ sudo puppet apply -e 'class {apache:}'

If you create the file mentioned in the new virtual host definition, you can test it.

$ curl localhost
See you at TeroKarvinen.co

Can you write a similar module to configure sshd to an alternate port?

Tricks

Short prompt

$ export PS1="\W\$ "

Parametrized Classes, Variables and Templates

vagrant@vagrant:~$ cat notes2.txt
vagrant@vagrant:/etc/puppet/modules/paramet$ cat manifests/init.pp
class paramet($port=80) {
 notice("Port is ${port}.")
 file {"/tmp/hello.txt":
 content => template("paramet/hello.txt.erb")
 }
}
vagrant@vagrant:/etc/puppet/modules/paramet$ cat templates/hello.txt.erb
Hello Tero
The port is <%= @port %>
This system is <%= @lsbdistdescription %>
vagrant@vagrant:/etc/puppet/modules/paramet$ sudo puppet apply -e 'class {paramet: port=>73}'
Notice: Scope(Class[Paramet]): Port is 73.
Notice: Compiled catalog for vagrant.vm in environment production in 0.13 seconds
Notice: Finished catalog run in 0.08 seconds
vagrant@vagrant:/etc/puppet/modules/paramet$ cat /tmp/hello.txt
Hello Tero
The port is 73
This system is Ubuntu 16.04.3 LTS

Site Manifests

$ cat /etc/puppet/manifests/site.pp
class {paramet: port=>73}
class {apache:}
class {hellotero:}
$ sudo puppet apply /etc/puppet/manifests/site.pp
Notice: Scope(Class[Paramet]): Port is 73.
Notice: Compiled catalog for vagrant.vm in environment production in 0.68 seconds
Notice: /Stage[main]/Hellotero/File[/tmp/hellotero]/ensure: defined content as '{md5}00e10248f6827939f378f0c4c1f0c511'
Notice: /Stage[main]/Paramet/File[/tmp/hello.txt]/ensure: defined content as '{md5}53524a1710272973551edb515715a8fd'
Notice: Finished catalog run in 0.06 seconds

Master and Slave

$ sudo apt-get -y install puppetmaster
$ sudo puppet agent --enable
$ sudo puppet agent --test
$ sudo puppet agent --test --debug --verbose
$ sudoedit /etc/hosts   # test only, 127.0.0.1 puppet

For Master and Slave on different computers

$ sudoedit /etc/puppet/puppet.conf

Add DNS names under [master] heading

dns_alt_names = puppet, master.local, puppet.terokarvinen.com

For slave

$ sudoedit /etc/puppet/puppet.conf
[agent]
server = tmaster.example.com

Fixing Cert Problems

Master is the most valuable computer in the network it protects. That’s why Puppet errs on the side of not working when certs don’t match or validate.

$ sudo service puppetmaster stop
$ sudo rm -r /var/lib/puppet/ssl
$ sudo service puppet stop
$ sudo rm -r /var/lib/puppet/ssl

Conditional Statements

Make your module work on one platform first. Add conditional logic in the beginning.

class apache {
 if $operatingsystem == "Ubuntu" {
   $webserver = "apache2"
 } else {
   $webserver = "httpd"
 }
 notice("webserver is ${webserver}")
 ####
 package {"apache2":
 name => "${webserver}",
   ensure => "installed",
 }
 # ...
}

Git Version Control

With Git, use only what you need, and what everyone on you team can use.
Basic use

$ git init
$ nano README
$ git add . && git commit

Helful commands

$ git log
$ git status

Network use

$ git clone https://github.com/hattupuu/earplotter.git
$ cd earplotter/
$ git add . && git commit; git pull && git push

Pull first. Always pull before push.

Read More

Tag Puppet on TeroKarvinen.com

Puppet CookBook Yes, it’s a cookbook, but you’ll probably hit these “challenges” when you start applying Puppet to real cases.
Awaseroot A finished project by my students.
Arctic CCM My students just started the project, there will be new content weekly.
Puppet Reading List Including how US GOV and Wikipedia use Puppet.

PuppetMaster on Ubuntu 12.04 (It’s similar in modern distro versions)

An Interesting System

Heat pump UI. Screenshot copyright Osma Suominen.

Cottage IoT control and measurement still works – five years after installation. System designed and built by Osma Suominen, a participant in the course.

Adminstrivia

This article will be updated as more notes are being scribbled.

Posted in Uncategorized | Tagged , , , , , , , | 3 Comments

3 Responses to Teaching Puppet Configuration Management in The National Library of Finland

  1. anonymous hero says:

    Testaan pupettia mahdollisesti raspien konffimiseen.

  2. Päivi says:

    Opin hyvin puppetin perusteet ja sain riittävät eväät siihen, että pystyn itseänäisesti jatkamaan puppettiin tutustumista. Kurssi oli minulle erittäin hyödyllinen.
    Kurssilla opittuja asioita on tarkoitus käyttää palvelinylläpidon tehostamiseen. Suosittelisin kurssia ystäville ja kollegoilleni.

  3. Emma says:

    Did I learn something?
    – Yes, I know understand Puppet. 🙂
    Is it usefull for me?
    – Yes.
    How do I plan to use my skills after the course?
    – At least to administrate our servers.
    How could the course be improved?
    – No idea. 🙂
    Would I recommend this course to my friends or collegues?
    – Yes, absolutely!