Prerequisite is to have Puppet installed and running, both on the Puppet master server and on the Puppet clients.
See my IT Knowledge Base article on How To Install Puppet Server and Clients
NOTE: a good source of practical Puppet tips and commands can be found at www.puppetcookbook.com/
Another tip: you can run your Puppet code through a quick syntax check at: https://validate.puppet.com/
Some basic Puppet concepts
Resources
Puppet code is composed mainly of resource declarations which describe the desired state of the system. This can specify such aspects as that a particular user or file should exist, or that a specific software package should be installed.
Resource declarations are formatted thus:
resource_type { ‘resource_name’
attribute => value
…
}
For example, we may specify the following user resource declaration:
user { ‘smith’:
ensure => present,
uid => ‘1000’,
gid => ‘1000’,
shell => ‘/bin/bash’,
home => ‘/home/smith’
}
To list all default Puppet resource types:
puppet resource –types
root@gemini:/opt/puppetlabs/bin# puppet resource –types
augeas
cron
exec
file
filebucket
group
host
mount
notify
package
resources
schedule
scheduled_task
selboolean
selmodule
service
ssh_authorized_key
sshkey
stage
tidy
user
whit
yumrepo
zfs
zone
zpool
root@gemini:/opt/puppetlabs/bin#
Manifests
Puppet programs are known as manifests. Manifests are composed of puppet code and are saved as files with the .pp filename extension.
The default main manifest in Puppet is located at /etc/puppetlabs/code/environments/production/manifests/site.pp (for older versions of Puppet at /etc/puppet/manifests/site.pp.)
Classes
Puppet classes are code blocks which can be called in code from elsewhere.
Classes allows you re-use Puppet code and make it easier to read manifests.
Class Definition
A class definition contains the code that composes a class.
Defining a class makes the class available for use in manifests.
The format for a class definition is:
class example_class {
…
code
…
}
This defines a class with the name “example_class”.
Class Declaration
A class declaration occurs when a class is referenced in a manifest. There are two types of class declaration: normal and resource-like.
Puppet evaluates the code within the class.
A normal class declaration occurs when the “include” keyword is referenced in Puppet code, for example:
include example_class
This instructs Puppet to evaluate the code in example_class.
A resource-like class declaration occurs when a class is declared like a resource, thus:
class { ‘example_class’: }
“resource-like” class declarations allow you to specify class parameters. These override the default values of class attributes.
Modules
A Puppet module is a collection of manifests and data (which includes such items as facts, files, and templates). These have a specific directory structure.
Modules are used for organizing Puppet code, since they allow you to split up your Puppet code into manageable individual manifests. Modules are the preferred method for organizing Puppet manifests.
To add a module to Puppet, save it in the /etc/puppetlabs/code/modules directory.
Manifests are defaultwise located under /etc/puppetlabs/code/environments/production/manifests
root@gemini:/etc/puppetlabs/code/environments/production# ll
total 28
drwxr-xr-x 5 root root 4096 Jul 20 15:08 ./
drwxr-xr-x 3 root root 4096 Jul 20 15:08 ../
drwxr-xr-x 2 root root 4096 Jun 14 09:16 data/
-rw-r–r– 1 root root 865 Jun 14 09:16 environment.conf
-rw-r–r– 1 root root 518 Jun 14 09:16 hiera.yaml
drwxr-xr-x 2 root root 4096 Jun 14 09:16 manifests/
drwxr-xr-x 2 root root 4096 Jun 14 09:16 modules/
root@gemini:/etc/puppetlabs/code/environments/production#
By default, the main manifest for an environment is set to <ENVIRONMENTS DIRECTORY>/<ENVIRONMENT>/manifests
For example /etc/puppetlabs/code/environments/production/manifests as above.
You can configure the manifest on a per-environment basis or you can configure a default for all environments.
To determine its main manifest, an environment uses the manifest setting in environment.conf. This can be an absolute path or a path relative to the environment’s main directory.
If the environment.conf manifest setting is absent, then it references the value of the default_manifest setting found in the puppet.conf file. The default_manifest setting defaults to ./manifests.
NOTE: The current puppet environment location is now /etc/puppetlabs. This replaces the older location /etc/puppet which is still found in older Puppet documentation and may be in use on older versions of Puppet.
Resource declarations
Resource declarations are deployed in manifests. Some basic essential resource declarations include:
exec: for executing commands, such as apt-get
package: for installing packages via apt
service: to ensure that a service is running
file: to ensure certain files are present
Writing a Puppet manifest
The following is a simple basic example of a configuration manifest.
This will ensure the package hello is available on a puppet client node (puppetclient_intelvpn)
Open a default manifest with the name /etc/puppetlabs/code/environments/production/manifests/site.pp file on the master server and add the following configuration:
nano /etc/puppetlabs/code/environments/production/manifests/site.pp
package { “hello”:
ensure => “installed”
}
Our agent on client node puppetclient_intelvpn is set by default to retrieve the puppet master configuration every 30 minutes.
If we do not wish to wait for this time period, we can trigger the configuration request manually:
Package hello is currently unavailable on the client. Trigger new configuration request manually with puppet agent –test
First set a symlink for puppet in order to avoid having to enter the full path to puppet for each command:
root@len:~# ln -s /opt/puppetlabs/puppet/bin/puppet /usr/local/sbin/puppet
then do:
root@len:~# puppet agent –test
Info: Using configured environment ‘production’
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for puppetclient_lenvpn
Info: Applying configuration version ‘1626883804’
Notice: /Stage[main]/Main/Package[hello]/ensure: created
Notice: Applied catalog in 18.89 seconds
root@len:~#
From the above output we can see that new configuration was applied and that the package “hello” has now been made available by Puppet on the client machine:
root@len:~# hello
Hello, world!
root@len:~#
A module to keep ubuntu systems updated:
Sourced from the official puppet forge site at https://forge.puppet.com/
from https://forge.puppet.com/modules/puppet/unattended_upgrades
root@gemini:~# puppet module install puppet-unattended_upgrades –version 5.1.0
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules …
Notice: Downloading from https://forgeapi.puppet.com …
Notice: Installing — do not interrupt …
/etc/puppetlabs/code/environments/production/modules
└─┬ puppet-unattended_upgrades (v5.1.0)
├─┬ puppetlabs-apt (v7.7.1)
│ └── puppetlabs-translate (v2.2.0)
└── puppetlabs-stdlib (v6.6.0)
root@gemini:~#
then on the clients do:
root@len:~# puppet agent –test
Info: Using configured environment ‘production’
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for puppetclient_lenvpn
Info: Applying configuration version ‘1626886951’
Notice: Applied catalog in 1.97 seconds
root@len:~#
then add following to /etc/puppetlabs/code/environments/production/manifests/site.pp
root@gemini:~# nano /etc/puppetlabs/code/environments/production/manifests/site.pp
node ‘puppetclient_lenvpn’ {
include unattended_upgrades
}
node ‘puppetclient_asusvpn’ {
include unattended_upgrades
}
node ‘puppetclient_intelvpn’ {
include unattended_upgrades
}
then run puppet agent –test
on each client:
eg on puppetclient_lenvpn:
then run puppet agent –test
on puppetclient_lenvpn:
root@len:/etc/apt# puppet agent –test
Info: Using configured environment ‘production’
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for puppetclient_lenvpn
Info: Applying configuration version ‘1626888562’
Notice: /Stage[main]/Apt/File[preferences]/ensure: created
Info: /Stage[main]/Apt/File[preferences]: Scheduling refresh of Class[Apt::Update]
Notice: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]/content:
— /etc/apt/apt.conf.d/15update-stamp 2013-07-12 19:07:51.000000000 +0200
+++ /tmp/puppet-file20210721-829078-1iei017 2021-07-21 19:29:35.053955262 +0200
@@ -1 +1,2 @@
+// This file is managed by Puppet. DO NOT EDIT.
APT::Update::Post-Invoke-Success {“touch /var/lib/apt/periodic/update-success-stamp 2>/dev/null || true”;};
Notice: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]/content: content changed ‘{sha256}174cdb519fd06372847e23c20db869b2ff4b593252c0d2a6274d770eae2d92c9’ to ‘{sha256}2e6eb1f5f20262bfc6b7dfb26a302f00b4ab5fee803abd9e07ad8378cce067d5’
Info: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]: Scheduling refresh of Class[Apt::Update]
Info: Class[Apt::Update]: Scheduling refresh of Exec[apt_update]
Notice: /Stage[main]/Apt::Update/Exec[apt_update]: Triggered ‘refresh’ from 1 event
Notice: /Stage[main]/Unattended_upgrades/Apt::Conf[unattended-upgrades]/Apt::Setting[conf-unattended-upgrades]/File[/etc/apt/apt.conf.d/50unattended-upgrades]/content:
— /etc/apt/apt.conf.d/50unattended-upgrades 2020-04-14 00:37:21.000000000 +0200
+++ /tmp/puppet-file20210721-829078-px7grn 2021-07-21 19:29:56.030091041 +0200
@@ -1,3 +1,4 @@
+// This file is managed by Puppet. DO NOT EDIT.
// Automatically upgrade packages from these (origin:archive) pairs
//
// Note that in Ubuntu security updates may pull in new dependencies
@@ -6,126 +7,49 @@
Unattended-Upgrade::Allowed-Origins {
“${distro_id}:${distro_codename}”;
“${distro_id}:${distro_codename}-security”;
– // Extended Security Maintenance; doesn’t necessarily exist for
– // every release and this system may not have it installed, but if
– // available, the policy for updates is such that unattended-upgrades
– // should also install from here by default.
– “${distro_id}ESMApps:${distro_codename}-apps-security”;
– “${distro_id}ESM:${distro_codename}-infra-security”;
-// “${distro_id}:${distro_codename}-updates”;
-// “${distro_id}:${distro_codename}-proposed”;
-// “${distro_id}:${distro_codename}-backports”;
};
-// Python regular expressions, matching packages to exclude from upgrading
+// List of packages to not update (regexp are supported)
Unattended-Upgrade::Package-Blacklist {
– // The following matches all packages starting with linux-
-// “linux-“;
–
– // Use $ to explicitely define the end of a package name. Without
– // the $, “libc6” would match all of them.
-// “libc6$”;
-// “libc6-dev$”;
-// “libc6-i686$”;
–
– // Special characters need escaping
-// “libstdc\+\+6$”;
–
– // The following matches packages like xen-system-amd64, xen-utils-4.1,
– // xenstore-utils and libxenstore3.0
-// “(lib)?xen(store)?”;
–
– // For more information about Python regular expressions, see
– // https://docs.python.org/3/howto/regex.html
};
-// This option controls whether the development release of Ubuntu will be
-// upgraded automatically. Valid values are “true”, “false”, and “auto”.
-Unattended-Upgrade::DevRelease “auto”;
+// List of days in the week that updates should be applied.
+// The days can be specified as localized abbreviated or full names.
+// Or as integers where “0” is Sunday, “1” is Monday etc.
+// Require Unattended-upgrades version >=0.91 to work, else it is ignored
+Unattended-Upgrade::Update-Days {
+};
// This option allows you to control if on a unclean dpkg exit
-// unattended-upgrades will automatically run
+// unattended-upgrades will automatically run
// dpkg –force-confold –configure -a
// The default is true, to ensure updates keep getting installed
-//Unattended-Upgrade::AutoFixInterruptedDpkg “true”;
+Unattended-Upgrade::AutoFixInterruptedDpkg “true”;
// Split the upgrade into the smallest possible chunks so that
// they can be interrupted with SIGTERM. This makes the upgrade
// a bit slower but it has the benefit that shutdown while a upgrade
// is running is possible (with a small delay)
-//Unattended-Upgrade::MinimalSteps “true”;
+Unattended-Upgrade::MinimalSteps “true”;
-// Install all updates when the machine is shutting down
-// instead of doing it in the background while the machine is running.
-// This will (obviously) make shutdown slower.
-// Unattended-upgrades increases logind’s InhibitDelayMaxSec to 30s.
-// This allows more time for unattended-upgrades to shut down gracefully
-// or even install a few packages in InstallOnShutdown mode, but is still a
-// big step back from the 30 minutes allowed for InstallOnShutdown previously.
-// Users enabling InstallOnShutdown mode are advised to increase
-// InhibitDelayMaxSec even further, possibly to 30 minutes.
-//Unattended-Upgrade::InstallOnShutdown “false”;
–
-// Send email to this address for problems or packages upgrades
-// If empty or unset then no email is sent, make sure that you
-// have a working mail setup on your system. A package that provides
-// ‘mailx’ must be installed. E.g. “user@example.com”
-//Unattended-Upgrade::Mail “”;
–
-// Set this value to one of:
-// “always”, “only-on-error” or “on-change”
-// If this is not set, then any legacy MailOnlyOnError (boolean) value
-// is used to chose between “only-on-error” and “on-change”
-//Unattended-Upgrade::MailReport “on-change”;
–
-// Remove unused automatically installed kernel-related packages
-// (kernel images, kernel headers and kernel version locked tools).
-//Unattended-Upgrade::Remove-Unused-Kernel-Packages “true”;
+// Install all unattended-upgrades when the machine is shuting down
+// instead of doing it in the background while the machine is running
+// This will (obviously) make shutdown slower
+Unattended-Upgrade::InstallOnShutdown “false”;
-// Do automatic removal of newly unused dependencies after the upgrade
-//Unattended-Upgrade::Remove-New-Unused-Dependencies “true”;
-// Do automatic removal of unused packages after the upgrade
+
+
+// Do automatic removal of new unused dependencies after the upgrade
// (equivalent to apt-get autoremove)
-//Unattended-Upgrade::Remove-Unused-Dependencies “false”;
+Unattended-Upgrade::Remove-Unused-Dependencies “true”;
-// Automatically reboot *WITHOUT CONFIRMATION* if
-// the file /var/run/reboot-required is found after the upgrade
-//Unattended-Upgrade::Automatic-Reboot “false”;
–
-// Automatically reboot even if there are users currently logged in
-// when Unattended-Upgrade::Automatic-Reboot is set to true
-//Unattended-Upgrade::Automatic-Reboot-WithUsers “true”;
+// Automatically reboot *WITHOUT CONFIRMATION*
+// if the file /var/run/reboot-required is found after the upgrade
+Unattended-Upgrade::Automatic-Reboot “false”;
// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: “now”
-//Unattended-Upgrade::Automatic-Reboot-Time “02:00”;
–
-// Use apt bandwidth limit feature, this example limits the download
-// speed to 70kb/sec
-//Acquire::http::Dl-Limit “70”;
–
-// Enable logging to syslog. Default is False
-// Unattended-Upgrade::SyslogEnable “false”;
–
-// Specify syslog facility. Default is daemon
-// Unattended-Upgrade::SyslogFacility “daemon”;
–
-// Download and install upgrades only on AC power
-// (i.e. skip or gracefully stop updates on battery)
-// Unattended-Upgrade::OnlyOnACPower “true”;
–
-// Download and install upgrades only on non-metered connection
-// (i.e. skip or gracefully stop updates on a metered connection)
-// Unattended-Upgrade::Skip-Updates-On-Metered-Connections “true”;
–
-// Verbose logging
-// Unattended-Upgrade::Verbose “false”;
–
-// Print debugging information both in unattended-upgrades and
-// in unattended-upgrade-shutdown
-// Unattended-Upgrade::Debug “false”;
+Unattended-Upgrade::Automatic-Reboot-Time “now”;
-// Allow package downgrade if Pin-Priority exceeds 1000
-// Unattended-Upgrade::Allow-downgrade “false”;
Notice: /Stage[main]/Unattended_upgrades/Apt::Conf[unattended-upgrades]/Apt::Setting[conf-unattended-upgrades]/File[/etc/apt/apt.conf.d/50unattended-upgrades]/content: content changed ‘{sha256}84fb166f00cc1a0dab73075e6fc9cdbc265ef47dc6d0fe9bdfb054c76cf94947’ to ‘{sha256}06e08c106ff275615b3211d9079c389de4c0dc141d76596acf04197977e00360’
Notice: /Stage[main]/Unattended_upgrades/Apt::Conf[periodic]/Apt::Setting[conf-periodic]/File[/etc/apt/apt.conf.d/10periodic]/content:
— /etc/apt/apt.conf.d/10periodic 2013-07-12 19:07:51.000000000 +0200
+++ /tmp/puppet-file20210721-829078-1t795c6 2021-07-21 19:29:56.082091378 +0200
@@ -1,3 +1,49 @@
+// This file is managed by Puppet. DO NOT EDIT.
+APT::Periodic::Enable “1”;
+# – Enable the update/upgrade script (0=disable)
+#
+APT::Periodic::BackupArchiveInterval “0”;
+# – Backup after n-days if archive contents changed.(0=disable)
+#
+APT::Periodic::BackupLevel “3”;
+# – Backup level.(0=disable), 1 is invalid.
+#
+APT::Periodic::MaxAge “0”;
+# – Set maximum allowed age of a cache package file. If a cache
+# package file is older it is deleted (0=disable)
+#
+APT::Periodic::MinAge “2”;
+# – Set minimum age of a package file. If a file is younger it
+# will not be deleted (0=disable). Usefull to prevent races
+# and to keep backups of the packages for emergency.
+#
+APT::Periodic::MaxSize “0”;
+# – Set maximum size of the cache in MB (0=disable). If the cache
+# is bigger, cached package files are deleted until the size
+# requirement is met (the biggest packages will be deleted
+# first).
+#
APT::Periodic::Update-Package-Lists “1”;
+# – Do “apt-get update” automatically every n-days (0=disable)
+#
APT::Periodic::Download-Upgradeable-Packages “0”;
+# – Do “apt-get upgrade –download-only” every n-days (0=disable)
+#
+APT::Periodic::Download-Upgradeable-Packages-Debdelta “1”;
+# – Use debdelta-upgrade to download updates if available (0=disable)
+#
+APT::Periodic::Unattended-Upgrade “1”;
+# – Run the “unattended-upgrade” security upgrade script
+# every n-days (0=disabled)
+# Requires the package “unattended-upgrades” and will write
+# a log in /var/log/unattended-upgrades
+#
APT::Periodic::AutocleanInterval “0”;
+# – Do “apt-get autoclean” every n-days (0=disable)
+#
+APT::Periodic::Verbose “0”;
+# – Send report mail to root
+# 0: no report (or null string)
+# 1: progress report (actually any string)
+# 2: + command outputs (remove -qq, remove 2>/dev/null, add -d)
+# 3: + trace on
Notice: /Stage[main]/Unattended_upgrades/Apt::Conf[periodic]/Apt::Setting[conf-periodic]/File[/etc/apt/apt.conf.d/10periodic]/content: content changed ‘{sha256}82d9ce0d3f5d2c66945d8a1267445e9955409d1ef3cb9934107adccb46bf5f6a’ to ‘{sha256}2219f593d53546c3025c126a2afb1e799dcb073bb51a2d8cd2648070bbbf8d5f’
Notice: /Stage[main]/Unattended_upgrades/Apt::Conf[auto-upgrades]/Apt::Setting[conf-auto-upgrades]/File[/etc/apt/apt.conf.d/20auto-upgrades]/ensure: removed
Notice: /Stage[main]/Unattended_upgrades/Apt::Conf[options]/Apt::Setting[conf-options]/File[/etc/apt/apt.conf.d/10options]/ensure: defined content as ‘{sha256}fbee4ce1e047bf061a71232f5a0f6e373beec970e5afa52ae5bae984cb7d6f61’
Notice: Applied catalog in 22.72 seconds
root@len:/etc/apt#
To instruct Puppet to ensure a systemd service is running
In this example we want to make sure the sshd server service is active:
first of all, we set the following in the site.pp:
root@gemini:~# nano /etc/puppetlabs/code/environments/production/manifests/site.pp
node default {
# include module_name
# include ssh
service {‘ssh’:
ensure => running,
enable => true,
hasstatus => true,
hasrestart => true,
}
}
then install a relevant puppet module for ssh.
We obtain this from the official forge puppet repository site https://forge.puppet.com/modules
We are going to use the module from ghoneycutt, available from https://forge.puppet.com/modules/ghoneycutt/ssh
So on our puppet master server we do:
puppet module install ghoneycutt-ssh –version 3.62.0
(the command can be found on the URL page above)
this will download and install the ssh puppet module directly onto our server.
Then, on the clients we can do the following:
Note: to test that the manifest does actually start ssh if it is not running we have first stopped ssh on the client.
As can be seen in the output result, puppet has started ssh on the client successfully:
root@asus:~# puppet agent –test
Info: Using configured environment ‘production’
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for puppetclient_asusvpn
Info: Applying configuration version ‘1626892938’
Notice: /Stage[main]/Main/Node[default]/Service[ssh]/ensure: ensure changed ‘stopped’ to ‘running’ (corrective)
Info: /Stage[main]/Main/Node[default]/Service[ssh]: Unscheduling refresh on Service[ssh]
Notice: Applied catalog in 0.38 seconds
root@asus:~#
root@asus:~#
root@asus:~# systemctl status ssh
● ssh.service – OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-07-21 20:42:19 CEST; 8min ago
Docs: man:sshd(8)
man:sshd_config(5)
Process: 2757294 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
Main PID: 2757295 (sshd)
Tasks: 1 (limit: 21459)
Memory: 4.3M
CGroup: /system.slice/ssh.service
└─2757295 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups