⚙️ 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 focusConfig managementAutomation / OrchestrationInfrastructure provisioning
LanguagePuppet DSLYAMLHCL
ApproachDeclarativeProcedural + idempotentDeclarative
Push / PullPullPushPush (via API)
Agent neededYesNoNo
State fileCatalog (server)None (stateless)Yes (.tfstate)
Cloud resourcesLimitedYes (modules)Excellent
Learning curveHighLowMedium

🎯 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:

  1. Terraform provisions the VM on AWS/Azure/GCP
  2. Ansible bootstraps the OS, installs base packages, deploys the app
  3. 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