# Automating AWS Infrastructure with Terraform

This article is useful for cloud enthusiasts, DevOps engineers, and developers. Let's outline a scenario-based guide to demonstrate how to use Terraform for setting up a basic AWS infrastructure.

---

### **Introduction**

Infrastructure as Code (IaC) is a key practice in modern DevOps that allows teams to manage and provision infrastructure using code. Terraform, an open-source tool developed by HashiCorp, is widely used for this purpose due to its flexibility and support for multiple cloud providers, including AWS. In this guide, I will walk you through a real-world scenario of setting up AWS infrastructure using Terraform.

### **Scenario Overview**

Imagine you are tasked with setting up a new environment on AWS for a web application. The requirements are:

1. **VPC (Virtual Private Cloud)**: To isolate our resources.
    
2. **Subnets**: Public and private subnets to organize resources.
    
3. **EC2 Instances**: To run the web servers.
    
4. **Security Groups**: To control the traffic to and from the EC2 instances.
    
5. **RDS Instance**: For the backend database.
    

### **Set Up AWS Credentials Using the AWS CLI**

The most common way to configure AWS credentials is by using the AWS CLI. Here’s how you can do it:

1. **Install the AWS CLI**: If you haven't already installed it, you can follow the [AWS CLI installation](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) [guide.](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
    
2. [**Configure AWS CL**](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)**I**: Run the follo[wing command to configure](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) the AWS CLI with your credentials:
    
    ```bash
    aws configure
    ```
    
    You will be [prompted to enter your AWS](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) Access Key ID, Secret Access Key, default region name, and default output format. [These credentials will be](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) saved in the `~/.aws/credentials` file on Unix/Linux/macOS or `%USERPROFILE%\.aws\credentials` on Wi[ndows.](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
    

### 2\. **Set AWS Credentials in Environment Variables**

Terraform also supports using environment variables for AWS credentials. You can set them like this:

* **Linux/macOS**:
    
    ```bash
    export AWS_ACCESS_KEY_ID="your_access_key"
    export AWS_SECRET_ACCESS_KEY="your_secret_key"
    export AWS_DEFAULT_REGION="us-east-1"
    ```
    
* [**Window**](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)**s (Command Prompt)**:
    
    ```bash
    set AWS_ACCESS_KEY_ID=your_access_key
    set AWS_SECRET_ACCESS_KEY=your_secret_key
    set AWS_DEFAULT_REGION=us-east-1
    ```
    

Replace `"your_access_key"` and `"your_secret_key"` with your actual AWS access key ID and [secret access key.](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)

### [3\. **Usi**](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)**ng a Shared Credentials File**

If you have multiple AWS profiles set up in a shared credentials file (e.g., `~/.aws/credentials`), yo[u can specify which profil](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)e Terraform should use by adding the `profile` argument to the AWS provider block:

```bash
provider "aws" {
  region  = "us-east-1"
  profile = "your_profile_name"
}
```

Replace `"your_profile_name"` with the name of the profile you want to use.

### **Prerequisites**

* Basic understanding of AWS services (VPC, EC2, RDS, etc.).
    
* Terraform installed.
    
* AWS CLI installed and configured with your credentials.
    
* An AWS [account with permissions](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) to create the necessary resources.
    
* Windows user should install (Git Bash and VS Code) to follow along
    

### **Step 1: Set Up Your Terraform Environment**

First, create a new directory for your Terraform configuration files, by running the following commands. Please note I will be using **Git Bash** and **VS Code** in this project.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725011868101/f7fd0a2b-ac6f-4a9b-8a8b-79ae69784f82.png align="center")

```bash
mkdir terraform-aws-setup
cd terraform-aws-setup
```

### **Step 2: Define Your AWS Provider**

Create a file named `main.tf` to define the AWS provider. This tells Terraform to use AWS as the target for resource provisioning.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725012084737/de27d541-0e04-477f-99bb-791616439a0d.png align="center")

Copy and paste this code below in your main.tf file, don't forget to save.

```bash
# main.tf
provider "aws" {
  region = "us-east-1"
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725012298329/641638f2-cde0-4517-889a-be7c3b380ed0.png align="center")

### **Step 3: Create a VPC**

In the same `main.tf` file, add the configuration to create a VPC.

```bash
# main.tf
resource "aws_vpc" "main_vpc" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main_vpc"
  }
}
```

### **Step 4: Create Subnets**

Next, define public and private subnets within the VPC.

```bash
# main.tf
resource "aws_subnet" "public_subnet" {
  vpc_id                  = aws_vpc.main_vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public_subnet"
  }
}

resource "aws_subnet" "private_subnet" {
  vpc_id            = aws_vpc.main_vpc.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "us-east-1b"

  tags = {
    Name = "private_subnet"
  }
}
```

### **Step 5: Set Up Security Groups**

Create a security group to allow HTTP and SSH access to the EC2 instances.

```bash
# main.tf
resource "aws_security_group" "web_sg" {
  vpc_id = aws_vpc.main_vpc.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    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 = "web_sg"
  }
}
```

### **Step 6: Launch EC2 Instances**

Define the EC2 instances in the `main.tf` file.

```bash
# web_server
resource "aws_instance" "web_server" {
  ami                    = "ami-0c94855ba95c71c99"  # Replace with your actual AMI ID
  instance_type          = "t2.micro"
  subnet_id              = aws_subnet.public_subnet.id  # Ensure this is a valid subnet ID
  vpc_security_group_ids = [aws_security_group.web_sg.id]  # Use security group IDs

  # Other necessary configurations
  tags = {
    Name = "web_server"
  }
}
```

### **Step 7: Set Up RDS Instance**

Add the configuration to create an RDS instance for the database.

```bash
# web_app_db
resource "aws_db_instance" "web_app_db" {
  allocated_storage    = 20
  engine               = "mysql"
  instance_class       = "db.t3.micro"
  db_name              = "mydb"
  username             = "admin"
  password             = "password"
  parameter_group_name = "default.mysql8.0"
  skip_final_snapshot  = true
  vpc_security_group_ids = [aws_security_group.web_sg.id]
  db_subnet_group_name = aws_db_subnet_group.db_subnet_group.name
}

resource "aws_db_subnet_group" "db_subnet_group" {
  name       = "my-db-subnet-group"
  subnet_ids = [
    aws_subnet.private_subnet.id,  # Subnet in AZ1
    aws_subnet.public_subnet.id   # Subnet in AZ2
  ]

  tags = {
    Name = "db_subnet_group"
  }
}
```

**Save** your main.tf file

### **Step 8: Initialize Terraform**

Run the "terraform init" command to initialize your Terraform workspace. This will download the necessary provider plugins.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725014589986/cd026167-20ee-4010-8033-c2933b6c3bb4.png align="center")

```bash
terraform init
```

### **Step 9: Plan and Apply**

Generate an execution plan with:

```bash
terraform plan
```

**Apply** the changes by running this command, "terraform apply":

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725018137501/1fc409d1-b111-48da-879c-d7faa63a733a.png align="center")

```bash
terraform apply
```

**Confirm** the action, and Terraform will proceed to create your AWS infrastructure as defined.

### **Step 10: Verify the Setup**

After the Terraform script completes, log in to the AWS Management Console and check:

* The VPC and subnets are created.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725019024466/8321e9b5-7e29-44c4-808e-ae69afc77b0f.png align="center")
    
    **Click** the "VPC ID" to see the created subnet, then scroll down to the "Subnet" section.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725019178431/97939023-b91b-45c0-ab5f-08ee6d5631f0.png align="center")
    
* EC2 instance is running with the correct security group settings. Search and select "EC2" in your AWS console.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725018493955/918ae788-1d90-4907-8251-79d037eac2eb.png align="center")
    
    **Click** on the Instance ID as shown above to verify the security group. Scroll down and select the "Security" tab.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725018670680/23700465-2df2-4744-b05f-917a836b7a5a.png align="center")
    
* RDS instance is up and connected to the private subnet. Search and select "RDS" in your AWS console. Click the "DB Instances" link to view details.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725019409052/d40b432c-389b-458d-a92a-74aca412e400.png align="center")
    
    **Click** "DB identifier" to view more details as shown below.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725019581285/7a8e3d53-93c4-4b18-a343-a026ab0568d0.png align="center")
    
    **Scroll down** to "Connectivity & Security" to see the following information:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725019758591/32dea1af-0b99-4442-9706-f8ba6210fcc6.png align="center")
    

### Step 11 : Clean up

Run this command "terraform destroy" and type "yes" when you are prompted to delete all the resources you created with "main.tf"

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725020352555/6c9b841e-4f31-409f-9816-fec713ef8281.png align="center")

You should get a similar message like this:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1725020603586/d8eb9f79-db61-4806-acf0-3523bd7af9a8.png align="center")

### **Final Thought**

Using Terraform to manage AWS infrastructure allows for consistent and repeatable deployments. By following this guide, you have automated the process of creating a VPC, subnets, EC2 instances, security groups, and an RDS instance, all with a few lines of code. This approach reduces the risk of manual errors and enhances collaboration through version-controlled infrastructure definitions.

### **Further Learning**

* Explore Terraform modules to reuse code.
    
* Check out [AWS Best Practices](https://aws.amazon.com/architecture/well-architected/) for designing robust infrastructure.
    
* Try integrating Terraform with CI/CD pipelines for automated deployments.
    

Thanks

:**Valentine Stephen**
