---
title: "Run Ansible Playbook From Terraform: Provision and Configure EC2 in AWS | CloudGuys Blog"
description: "Automate AWS Bastion Host provisioning with Terraform and Ansible - deploy an EC2 bastion host and configure it with Docker and Docker Compose in a single workflow to eliminate manual setup and streamline infrastructure automation."
url: "https://cloudguys.io/blog/run-ansible-playbook-from-terraform-provision-and-configure-ec2-in-aws"
language: "en"
image: "https://cloudguys.io/_astro/cover.C4pilpCy.png"
published: "2026-05-03T00:00:00.000Z"
modified: "2026-05-13T00:00:00.000Z"
---

ENGINEERING NOTES / DEVOPS, IAC

# Run Ansible Playbook From Terraform: Provision and Configure EC2 in AWS

Combine Terraform and Ansible to fully automate AWS Bastion Host deployment. This project provisions EC2 infrastructure and configures it with Docker/Compose v2 in one single, repeatable IaC workflow.

Sabbir Ahmed · · · May 3, 2026 · · · 3 min

![Run Ansible Playbook From Terraform: Provision and Configure EC2 in AWS](https://cloudguys.io/_astro/cover.C4pilpCy_ZncBDP.webp)

Often we have to provision EC2 instances as bastion hosts and then \\ we run ansible playbooks or init scripts to install packages or configure the system. But if we run terraform and ansible in one go that would save time as we as reduce toil.

In this article, we are going to learn how to achieve this goal. We will set up a bastion host and install docker and docker-compose v2 automagically!

### Terminal Time

Clone the repository, and edit the files at

[https://github.com/by-sabbir/terraform-ansible-ec2](https://github.com/by-sabbir/terraform-ansible-ec2)

* * *

-   `modules/ec2/variables.tf`
-   `modules/sshkey/variables.tf`
-   `./variables.tf`

Change the variables with your VPC ID, Public Subnet, Private, and Public key. This process can also be automated if deploy from scratch or use an external `terraform data resource.`But that is out of the scope of this article. Now run the following commands:

```plaintext
terraform plan
```

This will show the provisioning plan and/or show if the infra code has any error.

Assuming the previous command executed successfully, let’s provision the infrastructure —

```plaintext
terraform apply --auto-approve
```

After successful completion, you’ll get something similar to this,

Press enter or click to view image in full size

![](https://cloudguys.io/_astro/img-1.DtnqvGJB_ZarWnY.webp)

Awesome! Now you should be able to ssh into the server via the private key specified at `modules/ec2/variables.tf`

### Getting a Closer Look

—

**Project Structure**

I decided to go with `moduler` or `module-based` approach for this project. This enables us to reuse our IaC. Also, you can start a terraform `monorepo` for all your infrastructure resources in production with this pattern.

```plaintext
.
├── ansible
├── modules
│   ├── ec2
│   └── sshkey
└── main.tf
```

`ansible` folder contains an installation script and the `playbook.` Our main focus is the `modules` folder. This holds all the resources for your infrastructure. We can use `outputs` of any resource to provision other resources, we can independently update/delete any component for the infrastructure from and within this folder. I just love this IaC structure.

Now, the rest is easy. Let’s dissect the following terraform code line 79–126 from `modules/ec2/main.tf`,

We declared the `connection`method for the EC2 as SSH, so we provided the block with a private key, personally, I would take `ed25519` for the public key cryptography anyday and everyday. This will be used by the `file` and `remote-exec`provisioner. Let’s take a look at the `ansible/install.sh` file —

This is a pretty simple script, we are updating the package cache of the newly created VM and then installing ansible. Finally, we run the ansible playbook. The ansible playbook contains the necessary steps to install docker and the compose plugin.

> *Note: I did not manage state and locking. If you use it for production please use remote state and locking mechanisms of your choice.*

### Cleaning Up

```plaintext
terraform destroy
```

That’s it! Improvements/ideas will be highly appreciated.

Happy Architecting…

#Terraform · #Ansible · #AWS · #bastion host · #EC2 · #automation · #infrastructure as code · #Docker · #Docker Compose · #provisioning · #configuration management · #DevOps · #IaC · #AWS networking · #remote exec

A FRESH PERSPECTIVE ON YOUR CLOUD

## Great engineering starts  
with a good conversation.

Let’s talk about what’s working, what’s slowing you down, and what comes next.

[Talk to an engineer ↗](mailto:hello@agrohi.com?subject=CloudGuys%20assessment%20enquiry)

## Structured data

```json
[
  {
    "@context": "https://schema.org",
    "@type": "Organization",
    "@id": "https://cloudguys.io/#organization",
    "name": "CloudGuys",
    "url": "https://cloudguys.io/",
    "logo": {
      "@type": "ImageObject",
      "url": "https://cloudguys.io/assets/logo.png",
      "width": 512,
      "height": 512
    },
    "image": "https://cloudguys.io/assets/og-image.png",
    "description": "Security assessments, cloud architecture reviews, and practical remediation across AWS, Google Cloud, Azure, Kubernetes, and infrastructure as code.",
    "email": "hello@agrohi.com",
    "slogan": "Know your risks. Build a stronger cloud.",
    "areaServed": "Worldwide",
    "knowsAbout": [
      "DevOps",
      "Kubernetes",
      "Terraform",
      "Cloud migration",
      "Cloud cost optimization",
      "GitOps",
      "Site reliability engineering",
      "Kubernetes dashboard",
      "AI SRE",
      "Kubernetes troubleshooting",
      "AWS",
      "Google Cloud",
      "Azure"
    ],
    "contactPoint": {
      "@type": "ContactPoint",
      "contactType": "sales",
      "email": "hello@agrohi.com",
      "availableLanguage": [
        "English"
      ],
      "areaServed": "Worldwide"
    },
    "sameAs": [
      "https://www.linkedin.com/company/agrohitech",
      "https://berth.agrohi.com"
    ],
    "owns": {
      "@type": "SoftwareApplication",
      "@id": "https://berth.agrohi.com/#software",
      "name": "Berth",
      "applicationCategory": "DeveloperApplication",
      "operatingSystem": "Kubernetes",
      "url": "https://berth.agrohi.com",
      "description": "Berth is a self-hosted Kubernetes dashboard with a read-only AI SRE: endpoint health, capacity planning, guided app exposure, and evidence-based troubleshooting, run in your own cluster."
    }
  },
  {
    "@context": "https://schema.org",
    "@type": "WebSite",
    "@id": "https://cloudguys.io/#website",
    "url": "https://cloudguys.io/",
    "name": "CloudGuys",
    "description": "Security and cloud consultancy helping organizations assess risks, improve architecture, and verify remediation.",
    "publisher": {
      "@id": "https://cloudguys.io/#organization"
    },
    "inLanguage": "en"
  },
  {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "@id": "https://cloudguys.io/blog/run-ansible-playbook-from-terraform-provision-and-configure-ec2-in-aws#article",
    "headline": "Run Ansible Playbook From Terraform: Provision and Configure EC2 in AWS",
    "description": "Automate AWS Bastion Host provisioning with Terraform and Ansible - deploy an EC2 bastion host and configure it with Docker and Docker Compose in a single workflow to eliminate manual setup and streamline infrastructure automation.",
    "image": "https://cloudguys.io/_astro/cover.C4pilpCy.png",
    "datePublished": "2026-05-03T00:00:00.000Z",
    "dateModified": "2026-05-13T00:00:00.000Z",
    "author": {
      "@type": "Organization",
      "name": "Sabbir Ahmed",
      "url": "https://cloudguys.io/"
    },
    "publisher": {
      "@id": "https://cloudguys.io/#organization"
    },
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://cloudguys.io/blog/run-ansible-playbook-from-terraform-provision-and-configure-ec2-in-aws"
    },
    "articleSection": "DevOps, IaC",
    "keywords": "Terraform, Ansible, AWS, bastion host, EC2, automation, infrastructure as code, Docker, Docker Compose, provisioning, configuration management, DevOps, IaC, AWS networking, remote exec",
    "inLanguage": "en"
  },
  {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": [
      {
        "@type": "ListItem",
        "position": 1,
        "name": "Home",
        "item": "https://cloudguys.io/"
      },
      {
        "@type": "ListItem",
        "position": 2,
        "name": "Blog",
        "item": "https://cloudguys.io/blog"
      },
      {
        "@type": "ListItem",
        "position": 3,
        "name": "Run Ansible Playbook From Terraform: Provision and Configure EC2 in AWS",
        "item": "https://cloudguys.io/blog/run-ansible-playbook-from-terraform-provision-and-configure-ec2-in-aws"
      }
    ]
  }
]
```
