Core Principle

Ansible is an agentless configuration management tool that runs ordered tasks against target machines over SSH (or WinRM). Each task invokes a module that is expected to be individually idempotent (“ensure this package is installed,” not “install this package”). There is no global state file and no whole-system diff: Ansible only touches what you tell it to touch.

Why This Matters

Agentless + SSH means Ansible works on day zero against any Unix box that already accepts SSH. There is nothing to bootstrap on the target, which is a major operational advantage when you inherit existing fleets, lab equipment, or bare-metal servers that you don’t control end-to-end.

The lack of a state file is both the freedom and the limitation. Freedom: no state corruption, no locking, no secrets-in-state, no concept of “drift” because nothing claims to be authoritative. Limitation: no whole-system view, no automatic deletion of things you removed from the playbook, no reliable preview of “what would this run change.”

Evidence/Examples

  • Bootstrap workflows: provision a VM with Terraform, then hand off to Ansible to install packages, write config files, start services. Classic two-tool pattern.
  • Fleet operations: rolling restart 200 web servers, rotate a credential across a cluster, apply a kernel patch. The procedural model fits “do this everywhere, in this order.”
  • App-level state via modules: community.postgresql.postgresql_query, community.grafana.grafana_dashboard, community.general.keycloak_realm. Same target as Terraform providers, different execution model.
  • --check mode offers a dry run, but quality varies module by module, unlike Terraform’s first-class plan.

Implications

  • Pick Ansible when the work is genuinely procedural, when you don’t want a state file, or when Ansible is already running your machines and adding Terraform is overhead.
  • Pick Ansible when you only want to add without policing the rest of the system. If “delete things I removed from the file” is the wrong semantic for your use case, the absence of a state file is a feature.
  • The idempotency contract lives in module quality. Custom command: and shell: tasks break it instantly because they always report “changed.” Prefer real modules.
  • Largely supplanted by NixOS-style declarative system config when you control the machine end-to-end and can build a system closure instead of mutating one in place.

Questions

  • At what fleet size does the lack of a state file become painful enough to migrate to a stateful tool?
  • Is there a clean pattern for combining Ansible (bootstrap) with a GitOps reconciler (steady state) without ownership ambiguity?
  • How much of the Ansible ecosystem survives the long-term shift toward immutable infrastructure (build a new image, replace the host)?