Provision a two-tier web stack on AWS with Terraform, then configure it with Ansible - fully reproducible, no console clicks. The config is parameterized, validated in CI, and driven by a simple Makefile.
┌─────────────────────── AWS ───────────────────────┐
│ security group: HTTP :80 (world) │
SSH │ SSH :22 (allowed_ssh_cidr only) │
:22 ──┼──▶ ┌───────────────┐ ┌───────────────┐ │
HTTP │ │ EC2: <p>-nginx│ │ EC2:<p>-php_fpm│ │
:80 ──┼──▶ │ web tier │ │ app tier │ │
│ └───────────────┘ └───────────────┘ │
│ both from one for_each definition │
└────────────────────────────────────────────────────┘
Terraform provisions ─▶ outputs public IPs ─▶ Ansible installs NGINX / PHP-FPM
| File | Purpose |
|---|---|
versions.tf |
Terraform & provider version pins |
variables.tf |
Region, AMI, instance type, key path, allowed_ssh_cidr |
main.tf |
Key pair, security group, and both EC2 tiers via for_each |
outputs.tf |
Public IPs + a ready-to-paste Ansible inventory |
setup.yml |
Ansible: install & enable NGINX / PHP-FPM |
.github/workflows/terraform.yml |
CI: fmt -check + validate on every push |
Makefile |
make fmt / validate / plan / apply / configure / destroy |
make validate # fmt + init + validate (also runs in CI)
terraform apply # provision (prompts for confirmation)
terraform output ansible_inventory_hint > inventory.ini # grab the IPs
make configure # ansible-playbook -i inventory.ini setup.ymlPrereqs: an AWS account (aws configure), Terraform ≥ 1.3, Ansible, and an SSH key at ~/.ssh/id_rsa.pub.
- No credentials or state are committed -
credentials,*.tfstate,inventory.iniare git-ignored. allowed_ssh_cidrdefaults to0.0.0.0/0for demo convenience - set it to your IP for real use.- All resources are tagged (
Project,ManagedBy,Role) for cost tracking and cleanup.
Released under the MIT License.