TerraformPilot

DevOps

Using Terraform and Ansible Together for Full Stack Automation

Learn how to combine Terraform for infrastructure provisioning with Ansible for configuration management. A complete guide to full-stack automation using.

LLuca Berton1 min read

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

#
  1. Use Terraform for cloud resources — anything with an API (AWS, Azure, GCP)
  2. Use Ansible for OS-level configuration — packages, files, services
  3. Share data via outputs/variables — Terraform outputs → Ansible variables
  4. Use dynamic inventory — ansible-inventory plugins for cloud providers
  5. Separate repos or directories — keep Terraform and Ansible code organized
  6. Test both independently — terraform validate + ansible-lint

Learning Resources

#

Conclusion

#

Related: How to install Terraform on macOS — our most popular installation guide.

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.

#Terraform#Infrastructure as Code#DevOps#Cloud Computing#Automation

Share this article