⚙️ Configuration as Code
Puppet · Ansible · Terraform
— What's the difference and when to use what? —
Finistère Dev Meetup · 2026
📋 Agenda
01
What is Configuration as Code?
02
The IaC landscape
03
Puppet — Declare your state
04
Ansible — Automate everything
05
Terraform — Provision infrastructure
06
Comparison & when to use what
🤔 What is Configuration as Code?
Managing infrastructure and system configuration through machine-readable files stored in version control — just like application code.
- ✅ Reproducible — same result every time
- ✅ Versionable — Git history, pull requests, rollbacks
- ✅ Auditable — who changed what, and when
- ✅ Scalable — apply to 1 or 10 000 servers identically
- ✅ Collaborative — code review, CI/CD pipelines
🌍 The IaC Landscape
Three main problem spaces:
🐾 Configuration
Management
- Install / configure software
- Enforce desired state on servers
- Puppet, Chef, Salt
⚡ Orchestration &
Automation
- Run tasks across many hosts
- Deploy apps, pipelines
- Ansible, Fabric
🏗️ Infrastructure
Provisioning
- Create VMs, networks, DNS…
- Cloud-agnostic
- Terraform, Pulumi, OpenTofu
🐾 Puppet Configuration Management
- Born: 2005 — one of the oldest IaC tools
- Language: Puppet DSL (Ruby-based) or YAML (Hiera)
- Model: Pull — agents poll a central Puppet Server every 30 min
- Approach: Declarative — you describe the desired state
- Agent required: Yes (puppet-agent on each node)
💡 Great for large fleets where continuous compliance and drift detection matter.
🐾 Puppet — Example
# manifests/webserver.pp
class webserver {
package { 'nginx':
ensure => installed,
}
file { '/etc/nginx/nginx.conf':
ensure => file,
content => template('webserver/nginx.conf.erb'),
notify => Service['nginx'],
}
service { 'nginx':
ensure => running,
enable => true,
}
}
🔁 Run again → idempotent: only changes what diverged from the desired state
⚡ Ansible Automation & Orchestration
- Born: 2012, acquired by Red Hat in 2015
- Language: YAML (Playbooks)
- Model: Push — the control node connects via SSH
- Approach: Procedural (tasks run in order) with idempotent modules
- Agent required: No — agentless, just Python + SSH
💡 Great for ad-hoc tasks, app deployments, and quick automation without setup overhead.
⚡ Ansible — Example
# playbook/webserver.yml
- name: Configure web server
hosts: webservers
become: true
tasks:
- name: Install nginx
ansible.builtin.package:
name: nginx
state: present
- name: Copy nginx config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx
- name: Ensure nginx is running
ansible.builtin.service:
name: nginx
state: started
enabled: true
handlers:
- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
🏗️ Terraform Infrastructure Provisioning
- Born: 2014 by HashiCorp (open-source fork: OpenTofu)
- Language: HCL (HashiCorp Configuration Language)
- Model: Plan → Apply — preview changes before applying
- Approach: Declarative — describe your infrastructure graph
- Agent required: No — uses provider APIs (AWS, GCP, Azure, etc.)
💡 Great for creating and managing cloud resources — VMs, networks, DNS, databases…
🏗️ Terraform — Example
# main.tf
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" { region = "eu-west-3" }
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = { Name = "meetup-webserver" }
}
output "public_ip" {
value = aws_instance.web.public_ip
}
🗺️ terraform plan shows a diff · terraform apply creates resources · terraform destroy removes them
📊 Comparison at a Glance
|
🐾 Puppet |
⚡ Ansible |
🏗️ Terraform |
| Primary focus | Config management | Automation / Orchestration | Infrastructure provisioning |
| Language | Puppet DSL | YAML | HCL |
| Approach | Declarative | Procedural + idempotent | Declarative |
| Push / Pull | Pull | Push | Push (via API) |
| Agent needed | Yes | No | No |
| State file | Catalog (server) | None (stateless) | Yes (.tfstate) |
| Cloud resources | Limited | Yes (modules) | Excellent |
| Learning curve | High | Low | Medium |
🎯 When to Use What?
🐾 Use Puppet when…
- Large fleet (100s–1000s of servers)
- Continuous compliance / drift detection
- Enterprise, strict governance
- Long-running servers (pets)
⚡ Use Ansible when…
- Agentless is a must
- Quick automation or one-off tasks
- App deployment & pipelines
- Already using Red Hat / AWX
🏗️ Use Terraform when…
- Creating cloud infrastructure
- Multi-cloud or hybrid environments
- Preview changes before applying
- Immutable infra (cattle, not pets)
🤝 They Work Together!
These tools are complementary, not mutually exclusive.
A common real-world stack:
- Terraform provisions the VM on AWS/Azure/GCP
- Ansible bootstraps the OS, installs base packages, deploys the app
- Puppet continuously enforces compliance and manages config drift
→ Right tool for the right layer of the stack
💡 Key Takeaways
- Configuration as Code → reproducible, auditable, scalable infrastructure
- Puppet — continuous compliance on large server fleets (pull, agent)
- Ansible — agentless automation & orchestration (push, YAML)
- Terraform — cloud infrastructure provisioning (plan/apply, HCL)
- They complement each other — choose based on the layer of your stack
🙋 Questions?
Thank you!
Slides made with Reveal.js
Finistère Dev Meetup · 2026