Homework 08 — Terraform Basics + Remote State
Lesson 08 · Cloud Infrastructure & DevOps · Three tasks
These three tasks extend the Terraform module from the lab. Each one introduces a real-world pattern you will use again in Module 4 and beyond. Start with the lab’s VM running and state already in S3 before attempting any task.
Task 1 — Add a Cloudflare DNS A record via Terraform
After the lab’s terraform apply, you manually pointed a DNS A record at the Elastic IP. Replace that manual step with code.
- Add the
cloudflare/cloudflareprovider (version~> 4.0) torequired_providersinversions.tf. - Add a
provider "cloudflare" {}block that reads its API token from theCLOUDFLARE_API_TOKENenvironment variable (no inline token). - Add a
data "cloudflare_zone"source that looks up your zone by name (e.g.example.com), controlled by a newvar.cf_zonevariable. - Add a
cloudflare_recordresource that creates an A record forvar.domainpointing ataws_eip.vm.public_ipwith a 60-second TTL. - Run
terraform init && terraform applyto wire the full provision-and-route pipeline in one command.
✓ Self-check: terraform apply from a cold baseline creates the VM, EIP, and DNS record in one run. dig +short urls.example.com returns the EIP within 60 seconds of apply completing. curl -fsS https://urls.example.com/healthz returns {"status":"ok"}.
Task 2 — Tighten SSH to your IP only
The lab’s security group opens port 22 to 0.0.0.0/0. This is a significant attack surface: any host on the internet can attempt SSH authentication. Narrow it to your current public IP.
- Add the
hashicorp/httpprovider (version~> 3.0) torequired_providers. - Add a
data "http" "myip"data source that fetcheshttps://ipv4.icanhazip.com. - Add a
variable "ssh_admin_cidr"with an empty string default. - Add a
localthat usestrimspace(data.http.myip.response_body)/32whenvar.ssh_admin_cidris empty, and the variable value otherwise. - Replace the
0.0.0.0/0in the SSH ingress rule withlocal.effective_admin_cidr. - Run
terraform init && terraform apply. - Document your findings in a new file
cloud-devops/sample-app/terraform/SECURITY.mdchecked into your fork.
✓ Self-check: nmap -p 22 <public_ip> from a different network shows “filtered”; from your home network (or any IP in ssh_admin_cidr) shows “open”. SECURITY.md explains what was changed and why.
Task 3 — Two environments via workspaces
Terraform workspaces let you maintain multiple independent state slots from the same .tf files — useful for dev and prod instances of the same service.
- Modify the
tagsmap onaws_instance.vmto includeName = "url-shortener-${terraform.workspace}"andEnv = terraform.workspace. - Create a
devworkspace and apply with the defaultt3.micro:terraform workspace new dev terraform apply - Create a
prodworkspace and apply witht3.small:terraform workspace new prod terraform apply -var instance_type=t3.small - Confirm both instances exist simultaneously. Then tear both down:
terraform workspace select dev && terraform destroy terraform workspace select prod && terraform destroy
✓ Self-check: terraform workspace list shows dev, prod, and default. The AWS console shows two running instances tagged url-shortener-dev and url-shortener-prod with different instance types. The S3 bucket contains state at env:/dev/prod/terraform.tfstate and env:/prod/prod/terraform.tfstate.