How to Build AWS VPC using Terraform – Step by Step

How to Build AWS VPC using Terraform – Step by Step

In this guide, we will see how to create AWS VPC in any AWS region with just one line command terraform apply and you will have AWS VPC ready

git clone https://github.com/Muhammad-Usama-1/aws-vpc-with-terraform

Before starting out we would have only four files when you would clone the repo

from which one file terraform.tfvars would be empty and we are required to add our AWS credentials access_key secret_key to this file for creating any resource in the AWS account.

copy the Access key, and secret key and paste them to

terraform.tfvars file

access_key=some-random-valu-from-aws
secret_key=some-secret-from-aws

Now run

terraform init

now go to the variable.tf file in which we will need to modify the region CIDR for VPC and network for subnets and Project name

This block is setting region, availability zone for that regionavailability_zones ,

but what if we want to change the region we need to change region name ,availability zone

you need to change the region name and run terraform refresh and it will print available zones for that region to replace the availability_zones from new values

in this example, I am changing to ap-south-1

variable.tf file

#ADjust project name
variable "project" {
  # Change this with your Project name
  default     =  "project-name"
  type        = string
}
#ADjust region name
variable "region" {
  default     =  "ap-south-1"
  type        = string
}

data "aws_availability_zones" "example" {
   state = "available"
}
output "availability_zones" {
  value = data.aws_availability_zones.example.names
}
#ADjust region azs
variable "availability_zones" {
  default     =[
  "ap-south-1a",
  "ap-south-1b",
  "ap-south-1c",
]
  type        = list  
  description = "List of availability zones"
}
variable "vpc_cidr" {
  # CIDR for your new VPC , 10.0.0.0/16 means you can not change first 10.0 (16 bits) when creating subnetwork(subnet, private or piblci)
  default     = "10.0.0.0/16"
  type        = string
}

variable "public_subnet_cidr_blocks" {
  # Change this if change vpc_cidr

  default     = ["10.0.0.0/24", "10.0.2.0/24"], now run 
  type        = list
  description = "List of public subnet CIDR blocks"
}
variable "private_subnet_cidr_blocks" {

  # Change this if change vpc_cidr
  default     = ["10.0.100.0/24", "10.0.101.0/24"]
  type        = list
  description = "List of private subnet CIDR blocks"
}




variable "access_key" {
  description = "AWS Access Key ID"
  type        = string
}
variable "secret_key" {

description = "AWS Secret Access Key"
  type        = string
}

provider.tf file

provider "aws" {
  region = var.region
  access_key = var.access_key
  secret_key = var.secret_key
}

terraform.tfvars file

access_key =
secret_key =

vpc.tf file

# VPC
resource "aws_vpc" "default" {
  cidr_block = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name = "${var.project}-vpc",

  }
}

# Creating Public subnets
resource "aws_subnet" "public" {
  count = length(var.public_subnet_cidr_blocks)
  vpc_id                  = aws_vpc.default.id
  cidr_block              = var.public_subnet_cidr_blocks[count.index]
  availability_zone       = var.availability_zones[count.index]
  map_public_ip_on_launch = true

   tags = {
    # Name = "${var.project}-pub-subnet-${substr(var.availability_zones[count.index], 8, 2)}",   
    Name = "${var.project}-pub-subnet-${var.availability_zones[count.index]}"

  }
}
# Creating Private subnets
resource "aws_subnet" "private" {
  count = length(var.private_subnet_cidr_blocks)
  vpc_id            = aws_vpc.default.id
  cidr_block        = var.private_subnet_cidr_blocks[count.index]
  availability_zone = var.availability_zones[count.index]
    tags = {
    # Name = "${var.project}-priv-subnet-${substr(var.availability_zones[count.index], 8, 2)}",   
    Name = "${var.project}-priv-subnet-${var.availability_zones[count.index]}"

  }
}

# Creating internet gateway for accesing to internet
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.default.id
  tags =  {
   Name = "${var.project}-igw"

  }
}
# create route table with a record to internet incase of 0.0.0.0
resource "aws_route_table" "public-rt" {
 vpc_id = aws_vpc.default.id

 route {
   cidr_block = "0.0.0.0/0"
   gateway_id = aws_internet_gateway.igw.id
 }

 tags = {
   Name = "${var.project}-public-rt"
 }
}


resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "default" {
  depends_on = [aws_internet_gateway.igw]
  allocation_id = aws_eip.nat.id
  # Launching aws nat gateway in public subnet
  subnet_id     = aws_subnet.public[1].id
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.default.id
   tags = {
  #  Name = "nat-gateway-rt"
   Name = "${var.project}-nat-gateway-rt"

 }
}
resource "aws_route" "private" {
  route_table_id         = aws_route_table.private.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.default.id
}

resource "aws_route_table_association" "private" {
  count = length(var.private_subnet_cidr_blocks)
  subnet_id      = aws_subnet.private[count.index].id
  route_table_id = aws_route_table.private.id
}
resource "aws_route_table_association" "public" {
  count = length(var.public_subnet_cidr_blocks)
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public-rt.id
}

now we have adjusted the region and project name, run the terraform apply to create a VPC

terraform apply

write yes when it prompts, it will create the new VPC in your AWS account

It has created a whole new VPC in just 2 minutes

if we want to create another subnet in the available zone add CIDR for that in the below block

after making changes just run terraform apply again it will make changes

Clean up

Terraform provides a command used to tear down and remove infrastructure resources provisioned using Terraform.

terraform destroy

it will ask for yes to destroy, enter yes

Destroyed infra in a mint

Did you find this article valuable?

Support Muhammad Usama by becoming a sponsor. Any amount is appreciated!