Configuration Management#

The first big automation wave (mid-2000s onward). Replace manual sysadmin work on each server with declarative recipes describing the desired state. Run an agent on each box (or push from a controller); the agent makes reality match the recipe.

The pets era’s response to “we have too many servers to manage by hand”. Outclassed by containers + immutable infrastructure for greenfield work, but still ubiquitous in long-lived environments.

The Big Four#

The configuration-management tools that defined the mid-2000s. CFEngine started the wave; Puppet brought declarative DSLs at scale; Chef put recipes in Ruby; Ansible swept the operator side with agentless YAML and SSH. Each is still in production somewhere in 2026.

Tool

Year Mental Model

CFEngine

1993 The original. Promise theory; declarative.

Puppet

2005 Declarative DSL; agent-based; central master.

Chef

2009 Recipes in Ruby; imperative-feeling but converges.

Ansible

2012 YAML playbooks; agentless via SSH; push-based.

Latecomers and adjacent tools:

  • SaltStack, ZeroMQ pub-sub; fast at fleet scale.

  • Rudder, compliance-focused frontend to CFEngine.

  • BCfg2, LCFG, Bash + ssh-loops, many shops just had scripts.

Push vs. Pull#

  • Push (Ansible), a controller initiates; runs over SSH; no agent on the target. Easy to start; harder to scale.

  • Pull (Puppet, Chef, CFEngine), agent on each host phones home for the latest config; runs locally. Better at scale; needs agent lifecycle management.

Both models persist in 2026.

A Tiny Ansible Playbook#

- hosts: web
  become: true
  tasks:
    - name: install nginx
      apt:
        name: nginx
        state: latest
        update_cache: true

    - name: deploy site config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/site
        owner: root
        group: root
        mode: '0644'
      notify: reload nginx

    - name: ensure nginx is running
      service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: reload nginx
      service:
        name: nginx
        state: reloaded

Declarative vs. Imperative (Sort Of)#

These tools claim to be declarative, but the reality is mixed:

  • The high-level intent is declarative, “package X is installed”, “service Y is running”.

  • The way you express it is imperative, ordered tasks, with register / when / loop / failed_when clauses doing the imperative work.

  • Idempotency is the goal, not the guarantee, bad task design can break it.

True declarative tools (Terraform, Kubernetes) compute the diff between current and desired state and apply it. Config management runs through tasks one at a time and hopes the result is the desired state.

What Config Management Solved#

The wins that justified the tool category. Reproducibility across a fleet, drift detection from periodic runs, documentation embodied in code, self-configuring fresh servers, and a clear inventory of what’s running where – each was a real pain point in the pre-CM era.

  • Reproducibility, a new server matches its peers because the same playbook ran.

  • Drift detection, periodic runs report what changed.

  • Documentation as code, the playbook is the documentation.

  • Onboarding, a fresh server boots, joins the fleet, configures itself.

  • Inventory, knowing what’s running on which hosts.

What Config Management Didn’t Solve#

The gaps that left room for the next tool wave. CM didn’t provision the server; drift between runs left reality wrong for hours; the impedance with cloud resource provisioning was real; and at hyperscale, declarative scheduling replaced the model entirely.

  • Provisioning, you still need a server to configure. (Hence Terraform later.)

  • Drift between runs, if someone SSHs in and changes something, the next run fixes it, but reality may be wrong for hours.

  • Config + infra in one tool, impedance mismatch with cloud resource provisioning.

  • Scaling beyond ~thousands of pets, pull-mode helps, but at Google / Meta scale, declarative scheduling (Borg → Kubernetes) replaced this entirely.

The Modern Position#

  • Containers + immutable images, you don’t configure a running server; you replace it with a new image. Config management’s job at the application layer is gone.

  • Cloud-init, handles the small set of bootstrap actions on a fresh VM (SSH keys, network config). Often enough on its own.

  • Ansible at the host fleet edge, still common for things that must happen on actual hosts: kernel modules, SELinux profiles, OS patching, on-prem switch configuration.

  • In hybrid environments, where some servers are pets (DBs, appliances), config management still earns its keep.

You’ll meet Ansible in nearly every infrastructure team in 2026; it just owns a smaller piece of the pie than it did in 2014.

When to Reach For It#

The shapes of work where CM still earns its keep. OS-level setup that has to run on real hosts, ad-hoc fleet commands, network-device configuration, Kubernetes-on-bare-metal bootstrap, and compliance hardening (CIS, STIGs) all play to CM strengths the container model can’t reach.

  • OS-level setup that has to happen on physical or VM hosts.

  • One-off tasks across a fleet, ad-hoc Ansible commands are unrivalled.

  • Network device configuration (Cisco, Juniper), Ansible modules cover most.

  • Bootstrap of a Kubernetes cluster on bare metal (kubeadm + Ansible).

  • Compliance / hardening, DISA STIGs, CIS benchmarks; mature Ansible roles exist.

When to Skip It#

  • Application packaging, use a container.

  • Cloud resource provisioning, use Terraform / Pulumi / CloudFormation.

  • Desired-state Kubernetes config, use Helm / Kustomize + GitOps.

  • Greenfield container workloads, the playbook is a Dockerfile + a YAML manifest, not Ansible.

See Also#