Introduction
Puppet is a mature configuration management tool that uses a declarative language to define the desired state of your infrastructure. Unlike Ansible (agentless push), Puppet uses a master-agent architecture where agents periodically pull and apply configuration from the Puppet server (every 30 minutes by default).
Puppet Architecture
TEXT
Puppet Server (master)
|
|-- puppet agent (node1) -- pulls catalog every 30 min
|-- puppet agent (node2)
|-- puppet agent (node3)Key concepts:
- Catalog: Compiled set of resources to apply to a node
- Resource: A thing to manage (file, package, service, user)
- Module: Reusable collection of manifests, templates, files
- Hiera: Hierarchical data lookup for separating data from code
Installing Puppet Server
BASH
# Ubuntu 22.04 — Puppet 8
wget https://apt.puppet.com/puppet8-release-jammy.deb
dpkg -i puppet8-release-jammy.deb
apt update
apt install puppetserver
# Configure memory (default 2GB — reduce for small servers)
# /etc/default/puppetserver
JAVA_ARGS="-Xms512m -Xmx512m"
systemctl enable puppetserver && systemctl start puppetserverInstalling Puppet Agent
BASH
# On each managed node
wget https://apt.puppet.com/puppet8-release-jammy.deb
dpkg -i puppet8-release-jammy.deb
apt update && apt install puppet-agent
# Configure server address
echo "[main]
server = puppet.company.com" >> /etc/puppetlabs/puppet/puppet.conf
systemctl enable puppet && systemctl start puppetSigning Agent Certificates
BASH
# On puppet server — list pending certificate requests
puppetserver ca list
# Sign a specific agent
puppetserver ca sign --certname server01.company.com
# Sign all pending requests (careful in production!)
puppetserver ca sign --all
# Test agent connection
puppet agent --test # Run on agentWriting Puppet Manifests
PUPPET
# /etc/puppetlabs/code/environments/production/manifests/site.pp
node 'webserver01.company.com' {
# Install nginx
package { 'nginx':
ensure => installed,
}
# Manage nginx config
file { '/etc/nginx/nginx.conf':
ensure => file,
content => template('nginx/nginx.conf.erb'),
owner => 'root',
group => 'root',
mode => '0644',
require => Package['nginx'],
notify => Service['nginx'],
}
# Ensure service is running
service { 'nginx':
ensure => running,
enable => true,
require => Package['nginx'],
}
}Creating Puppet Modules
BASH
# Generate module structure
puppet module generate company-nginx
# Creates:
# nginx/
# manifests/
# init.pp
# templates/
# files/
# metadata.jsonPUPPET
# modules/profiles/manifests/webserver.pp
class profiles::webserver {
$packages = ['nginx', 'php8.1-fpm']
package { $packages:
ensure => installed,
}
service { 'nginx':
ensure => running,
enable => true,
require => Package['nginx'],
}
}Hiera — Separating Data from Code
YAML
# /etc/puppetlabs/code/environments/production/hiera.yaml
version: 5
hierarchy:
- name: "Per-node data"
path: "nodes/%{trusted.certname}.yaml"
- name: "Common data"
path: "common.yaml"
defaults:
datadir: data
# data/common.yaml
profiles::webserver::max_connections: 1024
# data/nodes/webserver01.company.com.yaml
profiles::webserver::max_connections: 2048Running Puppet
BASH
# Manual run on agent (immediate, don't wait 30 min)
puppet agent --test
# Dry run — show what would change
puppet agent --test --noop
# Force run from server for all nodes
puppet kick --all # deprecated
# Better: use Bolt or Orchestrator
# Check last run report
puppet agent --test --summarizeSummary
- Puppet excels at managing large fleets with consistent configuration
- Use modules to organize code; Hiera to separate data
- Agent checks in every 30 minutes automatically — no push needed
- The noop flag lets you preview changes safely before applying
- Puppet Forge has pre-built modules for common software (nginx, mysql, etc.)
