Table of Contents
Introduction
Terraform and Ansible are the two most popular infrastructure automation tools — and they’re even better together. Terraform provisions your cloud infrastructure (VMs, networks, databases), while Ansible configures what’s running on them (packages, services, applications). This guide shows you how to integrate both for end-to-end automation.
If you’re new to Ansible, check out Ansible Pilot for 500+ tutorials and hands-on guides.
The Architecture
┌─────────────────────────────────────────────┐
│ Your CI/CD Pipeline │
├─────────────────┬───────────────────────────┤
│ Terraform │ Ansible │
│ (Provision) │ (Configure) │
├─────────────────┼───────────────────────────┤
│ • Create VPC │ • Install packages │
│ • Launch EC2 │ • Configure nginx │
│ • Setup RDS │ • Deploy application │
│ • Create ALB │ • Setup monitoring │
│ • DNS records │ • Security hardening │
└─────────────────┴───────────────────────────┘
Step 1: Terraform Provisions Infrastructure
# main.tf
resource "aws_instance" "web" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
key_name = aws_key_pair.deployer.key_name
vpc_security_group_ids = [aws_security_group.web.id]
subnet_id = aws_subnet.public[count.index].id
tags = {
Name = "web-${count.index + 1}"
Role = "webserver"
Environment = var.environment
}
}
# Output IPs for Ansible
output "web_server_ips" {
value = aws_instance.web[*].public_ip
}
output "web_server_private_ips" {
value = aws_instance.web[*].private_ip
}
Step 2: Generate Ansible Inventory from Terraform
# Generate Ansible inventory dynamically
resource "local_file" "ansible_inventory" {
content = templatefile("inventory.tpl", {
web_servers = aws_instance.web[*]
db_endpoint = aws_db_instance.main.endpoint
})
filename = "../ansible/inventory/hosts"
}
# inventory.tpl
[webservers]
%{ for server in web_servers ~}
${server.tags.Name} ansible_host=${server.public_ip} ansible_user=ubuntu
%{ endfor ~}
[all:vars]
db_endpoint=${db_endpoint}
environment=${var.environment}
Step 3: Ansible Configures the Servers
# playbook.yml
---
- hosts: webservers
become: true
roles:
- common
- nginx
- app-deploy
- monitoring
- hosts: webservers
tasks:
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: restart nginx
- name: Deploy application
git:
repo: "https://github.com/company/webapp.git"
dest: /var/www/app
version: "{{ app_version }}"
notify: restart app
Step 4: CI/CD Pipeline Integration
# .gitlab-ci.yml
stages:
- provision
- configure
- test
provision:
stage: provision
script:
- cd terraform/
- terraform init
- terraform apply -auto-approve
- terraform output -json > ../ansible/tf_outputs.json
configure:
stage: configure
script:
- cd ansible/
- ansible-playbook -i inventory/hosts playbook.yml
dependencies:
- provision
Best Practices
- Use Terraform for cloud resources — anything with an API (AWS, Azure, GCP)
- Use Ansible for OS-level configuration — packages, files, services
- Share data via outputs/variables — Terraform outputs → Ansible variables
- Use dynamic inventory — ansible-inventory plugins for cloud providers
- Separate repos or directories — keep Terraform and Ansible code organized
- Test both independently — terraform validate + ansible-lint
Learning Resources
Terraform: Terraform Pilot Course — complete Terraform training
Ansible: Ansible Pilot — 500+ Ansible tutorials
Both: Ansible for VMware — integrating Ansible with infrastructure
Hands-on: Copy Paste Learn — interactive code examples
Conclusion
Terraform + Ansible is the gold standard for full-stack infrastructure automation. Terraform handles the “what exists” question, Ansible handles the “how it’s configured” question. Together, they give you complete control over your infrastructure from creation to configuration. Check out our Terraform course and Ansible Pilot to master both tools.

