PROJECT 6

AWS Infrastructure Provisioning with Terraform

Install the AWS CLI client, configure local administrative credentials, set up HashiCorp Terraform engines, write infrastructure manifests, and launch cloud servers.

Environment
AWS Cloud / Terraform CLI
Difficulty
Advanced
Course Module
Chapters 9–10: AWS & IaC
Deliverables
main.tf & Provisioning Logs
1. System Architecture & Workflow

The system diagram below maps the workflow of provisioning infrastructure as code, showing how local Terraform clients verify configuration schemas, track state files, and coordinate with AWS APIs.

Local Workstation (VM) Terraform CLI Engine main.tf / variables.tf AWS Credentials (AWS Profile) Local State: terraform.tfstate AWS Cloud Platform (Target API) VPC Resource Scope Instance: EC2 Type: t2.micro devops-server Allow SSH/HTTP Bucket: S3 Type: Storage devops-assets-* AWS API Call
2. Part 1: Step-by-Step Action Items & Key Execution Steps
STEP 1

Install and Configure the AWS Command Line Interface

Download the official AWS CLI package, extract files, install dependencies, and configure your API access credentials.

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip
This command downloads the official AWS CLI zip archive and extracts the installation files.
$ sudo ./aws/install && aws configure
This command runs the installer script to install the AWS CLI globally and opens the configuration prompts to set your access keys and region.
$ aws sts get-caller-identity
This command queries AWS to verify your credentials, returning your IAM user details and account ID to confirm access.
STEP 2

Install HashiCorp Terraform Engines

Add HashiCorp's official GPG verification keys, register their package repositories, and install the Terraform CLI tool.

$ wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
This command downloads HashiCorp's GPG keys and imports them, enabling apt to verify the integrity of downloaded packages.
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com/gpg $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
This command adds HashiCorp's stable package repository entry to the system source list, making their software available.
$ sudo apt update && sudo apt install terraform -y && terraform version
This command updates the repository indexes, installs the Terraform CLI engine, and prints the version to verify installation.
STEP 3

Initialize a Local Terraform Project

Create a dedicated folder for your configurations and initialize provider plugins and state files.

$ mkdir -p ~/Projects/terraform-lab && cd ~/Projects/terraform-lab && terraform init
This command creates a project folder, switches your terminal context to it, and initializes the project, downloading the AWS provider plugins.
STEP 4

Validate Syntax Schemas and Run Provisioning Plans

Scan your code files for syntax errors and preview the resources Terraform plans to create.

$ terraform validate
This command scans your configuration files for syntax errors and invalid references, verifying your code before deployment.
$ terraform plan
This command compares your configurations with the active state on AWS, listing the resources Terraform plans to add, modify, or destroy.
STEP 5

Deploy and Tear Down Cloud Resources Automatically

Apply your configurations to provision resources on AWS, and then destroy them to avoid ongoing costs.

$ terraform apply -auto-approve
This command applies your configurations, creating the S3 storage bucket, security groups, and EC2 server on AWS without requiring prompts.
$ terraform destroy -auto-approve
This command terminates and deletes all provisioned resources on AWS, ensuring you don't incur ongoing charges.
3. Automation Architecture

The diagram below traces the infrastructure lifecycle workflow, showing how Terraform plans changes, applies updates, and keeps the state file synchronized.

1. Write Code Define resources in *.tf files main.tf 2. Plan Checks Verify changes against cloud API terraform plan 3. Apply Changes Provision resources automatically terraform apply 4. Sync State Update state files after deployment terraform.tfstate
4. Part 2: Complete Deliverable Assets & Production Templates

To declare and provision your AWS infrastructure, we will write a Terraform configuration file. Below is a step-by-step breakdown of how this configuration is constructed, followed by the final combined script template.

Step-by-Step Script Construction

Step 1

Define Terraform Version Requirements and Provider Source

Setup the terraform settings block to specify tool version ranges and download source paths.

terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
This block locks the required version of Terraform and declares that HashiCorp's official AWS provider plug-in is required to manage resources.
Step 2

Initialize the AWS Provider and Regional Settings

Declare the AWS configuration block mapping regional API endpoints.

provider "aws" { region = "us-east-1" }
This configures the AWS provider to run in the US East (N. Virginia) region, directing all resource requests to this regional datacenter.
Step 3

Create Security Group Firewalls

Declare virtual firewall parameters allowing inbound TCP connections on port 22 and port 80.

resource "aws_security_group" "web_sg" { name = "devops-web-sg" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
This creates a security group resource that opens port 22 (SSH) and port 80 (HTTP) to external traffic, while allowing all outbound traffic.
Step 4

Provision the EC2 Instance and Bootstrap Web Server

Declare server configurations, link firewall rules, and write an automatic startup user-data script.

resource "aws_instance" "web_server" { ami = "ami-0c7217cdde317cfec" instance_type = "t2.micro" vpc_security_group_ids = [aws_security_group.web_sg.id] user_data = <<-EOF #!/bin/bash apt-get update apt-get install -y nginx systemctl start nginx systemctl enable nginx EOF }
This provisions a t2.micro EC2 server instance using Ubuntu Server 22.04 LTS, attaches the security group, and passes a bash script to install and start Nginx automatically when the server boots.
Step 5

Create S3 Storage Buckets

Configure storage instances with dynamic bucket prefixes.

resource "aws_s3_bucket" "assets" { bucket_prefix = "devops-assets-lab-" force_destroy = true }
This creates a private S3 bucket on AWS with a unique prefix, configured to delete all object files automatically when the bucket is destroyed.
Step 6

Declare Outputs to Expose Resource Variables

Declare metrics to output instance IPs and bucket name variables after provisioning.

output "instance_public_ip" { value = aws_instance.web_server.public_ip } output "bucket_name" { value = aws_s3_bucket.assets.id }
This instructs Terraform to output the public IP address of the new EC2 server and the generated S3 bucket name to your terminal once setup finishes.

Combined Complete Configuration File

Save the consolidated blocks above inside your project folder as ~/Projects/terraform-lab/main.tf:

terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = "us-east-1" } resource "aws_security_group" "web_sg" { name = "devops-web-sg" description = "Allow SSH and HTTP inbound traffic" ingress { description = "Allow SSH from anywhere" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { description = "Allow HTTP from anywhere" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "devops-security-group" } } resource "aws_instance" "web_server" { ami = "ami-0c7217cdde317cfec" # Ubuntu Server 22.04 LTS in us-east-1 instance_type = "t2.micro" vpc_security_group_ids = [aws_security_group.web_sg.id] user_data = <<-EOF #!/bin/bash apt-get update apt-get install -y nginx systemctl start nginx systemctl enable nginx EOF tags = { Name = "devops-server" } } resource "aws_s3_bucket" "assets" { bucket_prefix = "devops-assets-lab-" force_destroy = true tags = { Name = "devops-assets-bucket" Environment = "Development" } } output "instance_public_ip" { value = aws_instance.web_server.public_ip description = "Public IP address of the deployed EC2 server instance" } output "bucket_name" { value = aws_s3_bucket.assets.id description = "Name of the generated S3 bucket" }
5. Deliverables Summary

Verify that the following configurations and outputs exist inside your project workspace.

Created Files / Templates

  • /home/devops/Projects/terraform-lab/main.tf - Terraform infrastructure deployment template file.
  • /home/devops/Projects/terraform-lab/terraform.tfstate - Local infrastructure state database file.

Verification Artifacts / Execution Proof

  • Output of aws sts get-caller-identity confirming successful AWS authentication.
  • Output of terraform show displaying S3 and EC2 instance resources.
  • Terminal prints of instance_public_ip values returned by output blocks.
6. Closing Explanation: Why We Did This & What It Accomplishes

Architectural Intent & Operational Impact

Why We Did This

What This Accomplishes