Introduction
Ansible and Terraform are the two most popular Infrastructure as Code tools — but they solve different problems. Ansible excels at configuration management and orchestration (what happens on your servers), while Terraform excels at infrastructure provisioning (creating the servers themselves). Understanding when to use each — and how to combine them — is key to effective DevOps.
Quick Comparison
| Feature | Ansible | Terraform |
|---|---|---|
| Primary purpose | Configuration management, orchestration | Infrastructure provisioning |
| Language | YAML (playbooks) | HCL (HashiCorp Configuration Language) |
| Approach | Procedural + Declarative | Declarative |
| State management | Stateless | Stateful (terraform.tfstate) |
| Agent | Agentless (SSH/WinRM) | Agentless (API calls) |
| Execution | Push-based | Plan → Apply |
| Strength | Software config, app deployment | Cloud resource lifecycle |
| Idempotent | Yes (module-dependent) | Yes (by design) |
| Rollback | Manual (run previous playbook) | terraform destroy or previous state |
| Ecosystem | 85+ collections, 30K+ modules | 3,000+ providers |
| License | GPL v3 (fully open source) | BSL 1.1 (OpenTofu fork is open source) |
What Ansible Does Best
Configuration Management
# Ansible: Configure a web server
- name: Configure nginx
hosts: web_servers
become: true
tasks:
- name: Install nginx
ansible.builtin.dnf:
name: nginx
state: present
- name: Deploy config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Start nginx
ansible.builtin.systemd:
name: nginx
state: started
enabled: true
handlers:
- name: restart nginx
ansible.builtin.systemd:
name: nginx
state: restarted
Application Deployment
- name: Deploy application
hosts: app_servers
serial: 2 # Rolling deployment
tasks:
- name: Pull latest code
ansible.builtin.git:
repo: https://github.com/org/app.git
dest: /opt/app
version: "v2.3.1"
notify: restart app
- name: Install dependencies
ansible.builtin.pip:
requirements: /opt/app/requirements.txt
virtualenv: /opt/app/venv
Orchestration and Multi-Step Workflows
- name: Database migration
hosts: db_primary
tasks:
- name: Run migrations
ansible.builtin.command:
cmd: /opt/app/venv/bin/python manage.py migrate
chdir: /opt/app
- name: Deploy application
hosts: app_servers
serial: 1
tasks:
- name: Deploy and restart
ansible.builtin.include_role:
name: app_deploy
What Terraform Does Best
Infrastructure Provisioning
# Terraform: Create cloud infrastructure
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_instance" "web" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
subnet_id = aws_subnet.web.id
tags = {
Name = "web-${count.index}"
}
}
resource "aws_lb" "web" {
name = "web-lb"
load_balancer_type = "application"
subnets = aws_subnet.web[*].id
}
State Management
Terraform tracks the current state of all resources:
# See what exists
terraform state list
# Plan changes (dry run)
terraform plan
# Apply changes
terraform apply
# Destroy everything
terraform destroy
Multi-Cloud Support
# AWS
provider "aws" {
region = "us-east-1"
}
# Azure
provider "azurerm" {
features {}
}
# GCP
provider "google" {
project = "my-project"
region = "us-central1"
}
Key Differences Explained
State: Stateless vs Stateful
Ansible is stateless — it checks current state on each run and makes changes as needed. No external state file to manage or corrupt.
Terraform maintains a state file (terraform.tfstate) that maps your config to real resources. This enables:
- Knowing what exists vs what should exist
- Detecting drift
- Planning changes before applying
- Clean destruction of resources
Trade-off: Terraform's state gives powerful lifecycle management but requires state file storage, locking, and backup.
Execution: Push vs Plan/Apply
Ansible: You run ansible-playbook and it executes immediately, task by task, in order.
Terraform: Two-phase workflow:
terraform plan— shows what will change (dry run)terraform apply— executes the changes
Mutable vs Immutable
Ansible typically mutates existing servers — installs packages, edits configs, restarts services.
Terraform encourages immutable infrastructure — instead of updating a server, you replace it with a new one built from a fresh image.
Using Ansible + Terraform Together
The most powerful approach: Terraform provisions, Ansible configures.
┌──────────────┐ ┌──────────────┐
│ Terraform │────▶│ Ansible │
│ │ │ │
│ Create VMs │ │ Install apps │
│ Create LBs │ │ Configure │
│ Create DBs │ │ Deploy code │
│ Create VPCs │ │ Orchestrate │
└──────────────┘ └──────────────┘
Terraform Creates, Ansible Configures
# Terraform creates the servers
resource "aws_instance" "web" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
# ...
# Generate Ansible inventory
provisioner "local-exec" {
command = "echo '${self.public_ip}' >> ../ansible/inventory.txt"
}
}
# Ansible configures them
- name: Configure new servers
hosts: all
become: true
roles:
- base_config
- nginx
- app_deploy
Dynamic Inventory
Ansible can automatically discover Terraform-created resources:
# AWS dynamic inventory
ansible-playbook -i aws_ec2.yml site.yml
Decision Matrix
| Scenario | Use |
|---|---|
| Create VMs, networks, databases | Terraform |
| Install and configure software | Ansible |
| Manage cloud resources lifecycle | Terraform |
| Deploy application code | Ansible |
| Rolling updates across servers | Ansible |
| Multi-cloud resource management | Terraform |
| Ad-hoc server administration | Ansible |
| Manage Kubernetes resources | Either (both have good support) |
| CI/CD pipeline automation | Ansible |
| Destroy and recreate infrastructure | Terraform |
Related Articles
- Ansible Best Practices Guide
- Ansible-Core Guide
- Ansible Roles Explained
- What is Ansible AWX?
- Ansible for Windows
Conclusion
Ansible and Terraform are complementary, not competing. Use Terraform for provisioning infrastructure (VMs, networks, cloud services) with state-tracked lifecycle management. Use Ansible for configuring what runs on that infrastructure (software, configs, deployments) with agentless, push-based automation. Together, they provide complete Infrastructure as Code — Terraform builds the house, Ansible furnishes it.
Related
For a production-focused walkthrough, see Luca Berton's guide on migrating from Terraform to Ansible.