Learn Puppet - History, Background & Why You Need Puppet
Episode 1 of 23

Learn Puppet - History, Background & Why You Need Puppet

Tracing how Puppet was born: from the era of manual scripting, CFEngine 1993, the birth of Puppet by Luke Kanies in 2005, to Chef and Ansible. Understanding the problems Puppet solves and its position among other tools.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In the previous episode 0, you prepared the prerequisites and environment — from basic Linux and Ruby skills to installing Puppet Server, PDK, and a test node. This time we'll take a step back from the hands-on work and dive into why Puppet exists. We'll trace the history of configuration management, understand the real problems that gave birth to it, and see Puppet's position among Chef, Ansible, and SaltStack.

Why is understanding this history important? As an engineer, you don't just need to know how to write manifests — you also need to know why Puppet was designed the way it is: why it's pull-based, why it's declarative, and why its ecosystem is so complete. Without this context, you'll struggle to judge when Puppet is the right choice and when it isn't.

The Era Before Configuration Management

Before configuration management existed, managing servers was an exhausting, error-prone job. Imagine managing a hundred web servers: every time there's a new configuration, you have to log into each one, run shell scripts or type manual commands, and then hope nothing was missed. Even shell scripts have major weaknesses:

  • Not idempotent — running the same script twice can produce different states.
  • No reporting — there's no automated way to know whether all servers are in compliance.
  • Drift — one server can diverge from another due to different installation times or different people doing the work.

Out of that frustration came the generation of tools called configuration management.

Evolution of Configuration Management

CFEngine (1993)

CFEngine by Mark Burgess was the first configuration management tool. It introduced the concept that is now an industry standard: describing the desired state and letting the system keep itself converged to that state. CFEngine is very lightweight and efficient, but its configuration language is fairly primitive and its ecosystem is small.

Puppet (2005)

Luke Kanies built Puppet in 2005 to overcome CFEngine's limitations. Puppet brought two major breakthroughs:

  1. A high-level declarative language — Puppet manifests are human-readable and declarative, not just a set of policy rules.
  2. A resource model — Puppet abstracts the system into resource types (package, service, file, user) with well-defined properties.

Puppet also introduced a complete ecosystem: a central server that compiles catalogs, agents running on a schedule, and centralized reporting. This is what made Puppet one of the most dominant tools in its early era.

Chef (2009)

Chef arrived with a different philosophy: code is written in pure Ruby and it follows a client-server model with similar architecture. This "infrastructure as code with a real programming language" approach offers great flexibility, but it has a steeper learning curve because it requires understanding Ruby.

Ansible (2012)

Ansible, by Michael DeHaan, flipped the paradigm: it's push-based and agentless — no agent runs on the nodes, just SSH. This approach is very easy to learn and quick to adopt, which made Ansible popular among those who value simplicity.

Evolution Table

YearToolPioneerModelDistinction
1993CFEngineMark BurgessPull, agentFirst tool; policy-based
2005PuppetLuke KaniesPull, agentDeclarative, resource model, complete ecosystem
2009ChefAdam JacobPull, agentPure Ruby code
2012AnsibleMichael DeHaanPush, agentlessSSH, simple

Model-Driven & Declarative

Puppet is a model-driven system: everything managed is represented as a resource model with properties, not as step-by-step instructions. A Puppet manifest declares how the system should be — for example, nginx installed at a specific version, the service running, and the config file containing specific content.

The Puppet system is also pull-based: every node runs its agent on a schedule (default 30 minutes), the agent fetches a catalog from the server, then applies it. This model differs from Ansible's push approach — an important difference to understand because it affects how you design your Puppet environment.

Example of a declarative manifest
package { 'nginx':
  ensure => installed,
}
 
service { 'nginx':
  ensure => running,
  enable => true,
}

Notice: you don't write "run apt install, then run systemctl start". You declare the end state — Puppet determines the steps and checks whether the state has been reached.

Problems Puppet Solves

Defining and Maintaining Desired State

The core problem Puppet solves: defining the desired state for each server — packages, services, files, users — and keeping it converged. If a person or another process changes a config file, on the next agent run Puppet will restore it to the declared state. This is what idempotency means in the real world.

Large Scale

Manual scripting won't survive thousands of nodes. Puppet is designed for that scale:

  • Scheduled agents on every node run automatically without human intervention.
  • PuppetDB stores facts and reports from all nodes, so you have centralized reporting — you can tell which node failed and which node drifted.
  • Hiera separates data from logic, so the same configuration can be applied to thousands of nodes with different data — for example, per environment across dev, staging, and production.

Complete Ecosystem

Puppet isn't just a single binary — it's an ecosystem:

ComponentFunction
Puppet ServerCompiles catalogs from manifests
Puppet AgentRuns on every node, applies the catalog
PuppetDBCentralized facts and report storage
BoltOrchestration for running on-demand tasks
Puppet EnterpriseConsole, RBAC, compliance on top of Puppet OSS

Puppet vs Other Approaches

AspectPuppetAnsibleChefSaltStack
ModelPull, agentPush, agentlessPull, agentHybrid (master + agentless)
LanguageRuby-like DSLYAML + PythonRubyYAML/Python
Learning curveModerateLowHighModerate
ReportingCentralized PuppetDBAWX/pluginsChef AutomateSalt master
Ideal forStable enterprise infrastructureAd-hoc & fast automationRuby-heavy environmentsLarge & flexible infrastructure

We'll dive deeper into the comparisons in later episodes; for now it's enough to understand where each one stands.

Conclusion

In this episode 1, we traced the journey of configuration management: from the non-idempotent era of manual scripting, the birth of CFEngine in 1993, Puppet by Luke Kanies in 2005, to Chef and Ansible that came later. You also understood Puppet's declarative pull-based model and the big problems it solves — desired state, convergence, scaling to thousands of nodes, and a complete ecosystem.

Key takeaways:

  • Puppet was born from the limitations of manual scripting and CFEngine, bringing a declarative language and a resource model.
  • Puppet is pull-based with a scheduled agent on every node — a fundamental difference from Ansible's push approach.
  • Desired state + idempotency are the heart of Puppet: the system keeps itself always converged.
  • Its ecosystem is complete: Puppet Server, Agent, PuppetDB, Bolt, and Puppet Enterprise.

In the next episode, episode 2, we'll dissect Puppet's core concepts and main architecture — the agent run flow from Facter gathering facts, SSL certificate authentication, catalog compilation on the server, to reporting back to PuppetDB. Grab a coffee, because this is the most fundamental episode for understanding how Puppet works from the inside!