DEV Community

Cover image for How to Build AWS VPC Using Terraform
Gias Uddin
Gias Uddin

Posted on

How to Build AWS VPC Using Terraform

Creating a Virtual Private Cloud (VPC) in AWS is an essential part of deploying resources in a secure and isolated network. In this guide, we’ll create a VPC with Terraform, including subnets, route tables, an Internet Gateway, and a NAT Gateway, all in a single configuration file.

Prerequisites

  1. AWS Account: You’ll need an AWS account with permissions to create network resources.
  2. Terraform: Install Terraform if it’s not already on your machine.
  3. Text Editor: Use any text editor or IDE for writing the configuration file.

Step 1: Set Up the Project Directory

Create a new directory to hold the Terraform files.

mkdir aws-vpc-terraform
cd aws-vpc-terraform
Enter fullscreen mode Exit fullscreen mode

In this directory, create a file called main.tf to store the configuration.

Step 2: Define the VPC Configuration in main.tf

Open main.tf in your editor and add the configuration step-by-step.

Provider Configuration

Specify the AWS provider and the region you want to work in.

# main.tf

provider "aws" {
  region = "us-east-1"  # Specify your preferred region
}
Enter fullscreen mode Exit fullscreen mode

VPC Resource

Define the VPC resource with a custom CIDR block and enable DNS support.

# Define the VPC
resource "aws_vpc" "main_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "my-vpc"
  }
}
Enter fullscreen mode Exit fullscreen mode

Public and Private Subnets

Create a public subnet and a private subnet within the VPC. These will each have unique CIDR blocks.

# Public Subnet
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 = "my-public-subnet"
  }
}

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

  tags = {
    Name = "my-private-subnet"
  }
}
Enter fullscreen mode Exit fullscreen mode

Internet Gateway and Public Route Table

An Internet Gateway allows the public subnet to connect to the internet. We’ll also create a public route table that routes traffic from the public subnet to the Internet Gateway.

# Internet Gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main_vpc.id

  tags = {
    Name = "my-igw"
  }
}

# Public Route Table
resource "aws_route_table" "public_route_table" {
  vpc_id = aws_vpc.main_vpc.id

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

  tags = {
    Name = "my-public-route-table"
  }
}

# Associate Public Route Table with Public Subnet
resource "aws_route_table_association" "public_assoc" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_route_table.id
}
Enter fullscreen mode Exit fullscreen mode

This configuration:

  • Creates an Internet Gateway attached to the VPC.
  • Sets up a public route table that allows the public subnet to access the internet.

NAT Gateway and Private Route Table

To allow the private subnet to access the internet without being publicly accessible, we’ll add a NAT Gateway and a private route table.

# NAT Gateway
resource "aws_eip" "nat_eip" {
  vpc = true
}

resource "aws_nat_gateway" "nat_gw" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = aws_subnet.public_subnet.id

  tags = {
    Name = "my-nat-gw"
  }
}

# Private Route Table
resource "aws_route_table" "private_route_table" {
  vpc_id = aws_vpc.main_vpc.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat_gw.id
  }

  tags = {
    Name = "my-private-route-table"
  }
}

# Associate Private Route Table with Private Subnet
resource "aws_route_table_association" "private_assoc" {
  subnet_id      = aws_subnet.private_subnet.id
  route_table_id = aws_route_table.private_route_table.id
}
Enter fullscreen mode Exit fullscreen mode

In this configuration:

  • We allocate an Elastic IP (EIP) to the NAT Gateway.
  • The NAT Gateway is deployed in the public subnet, providing internet access to the private subnet.
  • A private route table is created, and any outbound traffic from the private subnet is routed to the NAT Gateway.

Step 3: Initialize and Apply the Terraform Configuration

  1. Initialize Terraform: Run terraform init in your project directory. This command initializes your project and downloads any required provider plugins.

    terraform init
    
  2. Apply the Configuration: Run terraform apply to create the VPC and all associated resources. Terraform will prompt you to confirm by typing yes.

    terraform apply
    
  3. Verify the Outputs: Terraform will display the resources it created, including IDs for the VPC, subnets, route tables, and gateways. You can also check the AWS Console under VPC Dashboard to verify.

Full main.tf Configuration

Here’s the complete code for main.tf:

# main.tf

provider "aws" {
  region = "us-east-1"
}

resource "aws_vpc" "main_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "my-vpc"
  }
}

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 = "my-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-1a"

  tags = {
    Name = "my-private-subnet"
  }
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main_vpc.id

  tags = {
    Name = "my-igw"
  }
}

resource "aws_route_table" "public_route_table" {
  vpc_id = aws_vpc.main_vpc.id

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

  tags = {
    Name = "my-public-route-table"
  }
}

resource "aws_route_table_association" "public_assoc" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_route_table.id
}

resource "aws_eip" "nat_eip" {
  vpc = true
}

resource "aws_nat_gateway" "nat_gw" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = aws_subnet.public_subnet.id

  tags = {
    Name = "my-nat-gw"
  }
}

resource "aws_route_table" "private_route_table" {
  vpc_id = aws_vpc.main_vpc.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat_gw.id
  }

  tags = {
    Name = "my-private-route-table"
  }
}

resource "aws_route_table_association" "private_assoc" {
  subnet_id      = aws_subnet.private_subnet.id
  route_table_id = aws_route_table.private_route_table.id
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

You’ve now created a fully functional AWS VPC with a public and private subnet using Terraform, all in one file. This approach is simple and quick for building basic network setups on AWS. Once you’re comfortable with this, you can explore modularization to scale your infrastructure with reusable components.

Cleanup

To avoid any charges, you can delete the resources by running:

terraform destroy
Enter fullscreen mode Exit fullscreen mode

Type yes to confirm when prompted. This will clean up all resources created

With this setup, you’ve taken a big step in mastering infrastructure as code and AWS network management using Terraform.

Top comments (0)