Terraform and Ansible are two of the most popular infrastructure automation tools in the DevOps ecosystem, but they solve fundamentally different problems. Choosing the right tool - or understanding how to use them together - can dramatically improve your infrastructure management workflow.
This comprehensive comparison covers architecture, syntax, use cases, and real-world scenarios to help you make the right choice for your projects in 2026.
The Fundamental Difference
| Aspect | Terraform | Ansible |
|---|---|---|
| Primary Purpose | Infrastructure provisioning | Configuration management |
| Approach | Declarative ("what") | Procedural/Declarative hybrid |
| Language | HCL (HashiCorp Config Language) | YAML |
| State | Maintains state file | Stateless (agentless) |
| Agent | No agent needed | No agent needed (SSH) |
| Best At | Creating cloud resources | Configuring servers |
Terraform: Infrastructure as Code
Terraform excels at provisioning infrastructure - creating VMs, networks, load balancers, databases, DNS records, and other cloud resources. You describe the desired end state, and Terraform figures out how to get there.
Example: Provision a Web Server on AWS
# main.tf - Terraform configuration
provider "aws" {
region = "eu-central-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = { Name = "production-vpc" }
}
resource "aws_subnet" "web" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
tags = { Name = "web-subnet" }
}
resource "aws_security_group" "web" {
name = "web-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
subnet_id = aws_subnet.web.id
security_groups = [aws_security_group.web.id]
tags = { Name = "web-server-01" }
}
Terraform Workflow
# Initialize (download providers)
terraform init
# Preview changes
terraform plan
# Apply changes (create/modify infrastructure)
terraform apply
# Destroy all resources
terraform destroy
# Import existing resources into state
terraform import aws_instance.web i-1234567890abcdef0
# Show current state
terraform state list
terraform state show aws_instance.web
Ansible: Configuration Management
Ansible excels at configuring servers - installing software, managing config files, deploying applications, and ensuring servers are in the correct state. It connects via SSH and executes tasks in order.
Example: Configure a Web Server
# playbook.yml - Ansible playbook
---
- name: Configure web server
hosts: webservers
become: yes
vars:
app_user: www-data
app_directory: /var/www/myapp
tasks:
- name: Update package cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install required packages
apt:
name:
- nginx
- postgresql-client
- python3
- python3-pip
- git
state: present
- name: Create application directory
file:
path: "{{ app_directory }}"
state: directory
owner: "{{ app_user }}"
mode: '0755'
- name: Copy nginx configuration
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/myapp
notify: Restart nginx
- name: Enable nginx site
file:
src: /etc/nginx/sites-available/myapp
dest: /etc/nginx/sites-enabled/myapp
state: link
notify: Restart nginx
- name: Deploy application code
git:
repo: https://github.com/company/myapp.git
dest: "{{ app_directory }}"
version: main
notify: Restart application
- name: Ensure nginx is running
service:
name: nginx
state: started
enabled: yes
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted
- name: Restart application
service:
name: myapp
state: restarted
Ansible Workflow
# Run a playbook
ansible-playbook -i inventory playbook.yml
# Run with specific hosts
ansible-playbook -i inventory playbook.yml --limit webservers
# Dry run (check mode)
ansible-playbook -i inventory playbook.yml --check
# Run ad-hoc commands
ansible webservers -m ping
ansible webservers -a "uptime"
ansible webservers -m apt -a "name=nginx state=latest" --become
# Encrypt secrets
ansible-vault encrypt secrets.yml
ansible-vault decrypt secrets.yml
When to Use Each Tool
Use Terraform When:
- Creating cloud infrastructure (VMs, networks, databases, DNS)
- Managing multi-cloud environments (AWS + GCP + Azure)
- You need to track infrastructure state and detect drift
- You want to preview changes before applying them
- You need to destroy and recreate entire environments
Use Ansible When:
- Installing and configuring software on existing servers
- Deploying application code
- Managing configuration files across many servers
- Running one-off operational tasks
- You need a simple tool with minimal learning curve
Use Both Together (Recommended for Production):
# 1. Terraform creates the infrastructure
terraform apply
# Creates: VPC, subnets, security groups, EC2 instances, RDS database
# 2. Terraform outputs feed into Ansible inventory
terraform output -json > terraform_output.json
# 3. Ansible configures the servers
ansible-playbook -i dynamic_inventory.py site.yml
# Configures: Nginx, app deployment, SSL, monitoring agents
Decision Matrix
| Task | Best Tool | Why |
|---|---|---|
| Create AWS VPC + subnets | Terraform | Infrastructure provisioning |
| Install Nginx on 50 servers | Ansible | Configuration management |
| Provision Kubernetes cluster | Terraform | Cloud resource creation |
| Deploy application update | Ansible | App deployment |
| Manage DNS records | Terraform | API-driven resources |
| Rotate SSH keys | Ansible | Server configuration |
| Create database instance | Terraform | Cloud service provisioning |
| Configure database users | Ansible | Software configuration |
Recommended Reading
Master DevOps and infrastructure automation:
Download our Terraform vs Ansible Cheat Sheet for a printable comparison with key commands and decision flowchart.