Amazon Virtual Private Cloud using Terraform

Amazon Virtual Private Cloud using Terraform

When you create any resources in AWS, by default it will be accessible to the Internet. Anyone with internet access can see the resources and interact with them. How do we secure the resources? How do we authorize only certain entities to interact with those resources? The answer to the question is using Amazon Virtual Private Cloud. In this, we will define our own virtual network and then deploy the resources into it. It is like having our own data center, but with all the utilities and goodies from AWS.

In this blog post, we will do the following below items:

  • Create a VPC
  • Create Subnets
  • Create an Internet Gateway
  • Create Route Tables
  • Create Routes in RouteTable
  • Connect Route Table to Subnets
  • Create a Security Group

Create a VPC

When you create an AWS account, you will get the default VPC in your account. We can create a custom VPC by using Terraform resource aws_vpc. The required attribute is cidr_block. It is the short form of Classless Inter-Domain Routing block. It provides the required number of IP addresses to the users. It also has a number after '/' which indicates, the number of bits for the network ID. In cidr_block, each number is of 8bits. so, in the example, there are a total of 8 * 4 = 32 bits and 16 is the number of bits that represent network ID. So, first 16 bits that is, 10.0 is fixed and from the remaining 16 bits, we will be able to create 2 ^ 16 unique IP addresses.

resource "aws_vpc" "vpc-learning" {
  cidr_block = ""
  tags = {
    "Name" = "vpc-learning"

Create Subnets

If we have a large network, then it becomes complex to manage the network. So, it is logical divided into Subnets. There are two types of Subnets. One is a private subnet that is not exposed to the outside world and another is a public subnet that is exposed to the internet.

We can create a Subnet by using Terraform resource aws_subnet. The required attribute is cidr_block and VPC, in which the subnet needs to be created. Here the cidr_block will have fixed the first 16 bits as defined by the VPC which we created earlier. Here 24 bits represent network ID. So, we have only 8 bits, which can be changed. So, we will be able to create 2 ^ 8 unique IP addresses. The map_public_ip_on_launch indicates that the public IP address will be assigned to the instances within the subnet.

resource "aws_subnet" "vpc-learning-public-subnet-1" {
  cidr_block = ""
  vpc_id =
  map_public_ip_on_launch = true
  availability_zone = "ap-south-1a"

Create an Internet Gateway

As the public IP address are assigned earlier, we can allow the instances to be accessible through the internet. we can use the aws_internet_gateway terraform resource and we need to point to the vpc as shown below.

resource "aws_internet_gateway" "vpc-learning-internet-gateway" {
  vpc_id =

Create Route Tables

We can create Route Tables using the aws_route_table resource with terraform.

resource "aws_route_table" "vpc-learning-public-route-table" {
  vpc_id =

Create Routes in RouteTable

We need to create a Routes in the RouteTable which was created earlier. We can use aws_route resource using terraform. Also, we make sure that these routes will be access through the internet. So, we need to provide the internet gateway using the attribute gateway_id as shown below.

resource "aws_route" "vpc-learning-public-route" {
  route_table_id =
  destination_cidr_block = ""
  gateway_id =

Connect Route Table to Subnets

Once the route tables are created, we need to associate the route table to the Subnets which were created earlier. We can use aws_route_table_association resource of terraform.

resource "aws_route_table_association" "vpc-learning-public-route-table-association" {
  route_table_id =
  subnet_id =

Create a Security Group

We need to define the security group to control the incoming and outgoing network calls. we can use the aws_security_group resource in terraform. We need to give the incoming and outgoing network call by using terraform attributes ingress and outgress respectively. Below, we are only allowing incoming from SSH i.e from 22 port and from HTTP i.e. 80 port, and the outgoing to unrestricted.

resource "aws_security_group" "vpc-learning-security-group" {
  name = "vpc-learning-default-security-group"
  vpc_id =
  ingress {
    from_port = 22
    protocol = "tcp"
    to_port = 22
    cidr_blocks = [var.ingress_egress_cidr_blocks]
  ingress {
    from_port = 80
    protocol = "tcp"
    to_port = 80
    cidr_blocks = [var.ingress_egress_cidr_blocks]

  egress {
    from_port = 0
    protocol = "-1"
    to_port = 0
    cidr_blocks = [var.ingress_egress_cidr_blocks]

Deploy using Terraform

Let us initiate the directory with terraform by issuing a command terraform init.

Once done, issue a command terraform plan -out plan-out where it will display what all resources will be provisioned and put the plan in the file named plan-out.


Now, we can apply the actual resource by using the command terraform apply "plan-out"

Verify the resources in AWS Console.

  • VPC


  • Subnets


  • Internet Gateway


  • Route Table showing association with subnets.


  • Security Groups showing Inbound and outbound




In this blog post, we have looked into the working of virtual private cloud in your AWS. We have looked into creating VPC and Subnets. Also, we have exposed the endpoints using the internet gateway and created a route table with subnet association. We also looked into how the security group helps us with the traffic to the network.

GitHub Repo:

Did you find this article valuable?

Support Rahul Lokurte by becoming a sponsor. Any amount is appreciated!