# AWS IaC scaffold: Terraform / OpenTofu read-only smoke + Ansible (SSM) template

Published with the blog post *[AWS IaC: Terraform vs OpenTofu vs Ansible (2026 decision guide)](https://www.factualminds.com/blog/aws-terraform-opentofu-ansible-iac-decision-guide/)*. Browse this tree at [`www.factualminds.com/examples/aws-iac-decision-demo/`](https://www.factualminds.com/examples/aws-iac-decision-demo/README.md).

It intentionally **creates zero billable AWS resources** in the Terraform root: only provider wiring plus **`data`** lookups so you validate credentials and provider pins without risking drift in a sandbox.

## Prerequisites

- AWS credentials with **`sts:GetCallerIdentity`** (and IAM read APIs if you uncomment optional data sources later).
- **Terraform >= 1.5** **or** **OpenTofu >= 1.8** (`tofu` substitutes 1:1 for `terraform` in commands below).

## Smoke test (Terraform or OpenTofu)

```bash
cd terraform
terraform init -backend=false -input=false   # or: tofu init -backend=false -input=false
terraform plan -input=false -no-color       # expect: Plan: 0 to add, 0 to change, 0 to destroy
```

You should see **`No changes`** if your AWS caller identity resolves.

## Ansible (Systems Manager wiring)

Collections (install once per controller):

```bash
ansible-galaxy collection install -r ansible/requirements.yml
```

Configure inventory for **SSM** targets (recommended on AWS instead of bastion SSH for private subnets). Copy `ansible/inventory/group_vars/target_aws_ec2.yml.example` to `group_vars/target_aws_ec2.yml` (when using dynamic inventories) or adapt inline.

```bash
cd ansible
ANSIBLE_PYTHON_INTERPRETER=auto ansible-playbook -i inventory/static.example.yml \
  playbooks/ping-ssm-compatible.yml --check
```

`--check` performs a dry-run of module argument validation suitable for laptops without live targets.

## Decision tree (summary)

| Layer                     | Typical tool                                   |
| ------------------------- | ---------------------------------------------- |
| VPC, subnets, SGs, IAM    | Terraform or OpenTofu (+ remote state S3+Dynamo) |
| OS packages / app rollout | Ansible (SSM Session Manager plugin or SSH)    |
| Vendor / license stance   | HashiCorp **BSL Terraform** vs **MPL OpenTufu**|

## Disclaimer

Infrastructure patterns here are deliberately minimal templates—not production blueprints.
