In the previous article (Terraform recipe – Managing AWS VPC – Creating Public Subnet), we’ve used Terraform to create a VPC, Internet Gateway, and Route Table to form Public Subnet. If you missed it, we strongly encourage you to read it first. This article continues Terraform article series and covers the management of NAT-ed and Fully Isolated Private Subnets.
Table of contents
But if you’re looking only for code snippets, please, feel free to use the VPC declaration from the next section. It already contains everything you need to move forward.
You may find a complete example of the project in our GitHub repo.
VPC with the public subnet
Here’s a complete example from the previous article:
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = {
Name = "My VPC"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.0.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "Public Subnet"
}
}
resource "aws_internet_gateway" "my_vpc_igw" {
vpc_id = aws_vpc.my_vpc.id
tags = {
Name = "My VPC - Internet Gateway"
}
}
resource "aws_route_table" "my_vpc_us_east_1a_public" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.my_vpc_igw.id
}
tags = {
Name = "Public Subnet Route Table."
}
}
resource "aws_route_table_association" "my_vpc_us_east_1a_public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.my_vpc_us_east_1a_public.id
}
resource "aws_security_group" "allow_ssh" {
name = "allow_ssh_sg"
description = "Allow SSH inbound connections"
vpc_id = aws_vpc.my_vpc.id
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 = "allow_ssh_sg"
}
}
resource "aws_instance" "my_instance" {
ami = "ami-0ac019f4fcb7cb7e6"
instance_type = "t2.micro"
key_name = "Lenovo T410"
vpc_security_group_ids = [ aws_security_group.allow_ssh.id ]
subnet_id = aws_subnet.public.id
associate_public_ip_address = true
tags = {
Name = "My Instance"
}
}
NAT-ed Private Subnet
Instances launched in this subnet will be able to communicate with any services within VPC and go to the Internet using the special AWS service NAT Gateway.
AWS recommends using this type of network if you’re running, for example, a public-facing web application, and you don’t want to make your back-end servers publicly accessible. A typical example is a multi-tier website, with web servers in a public subnet and database servers in a private subnet. You can set up security and routing so that the web servers can communicate with the database servers.
Here’s how the infrastructure looks like:

To extend our VPC with this NAT-ed Private network, we need to create the following resources:
- VPC NAT Gateway.
- Subnet.
- Route Table with the route to VPC NAT Gateway.
- Association between Route Table and Subnet.
Let’s begin from Subnet, by declaring additional aws_subnet resource:
resource "aws_subnet" "nated" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "NAT-ed Subnet"
}
}
Now let’s create NAT Gateway in a public subnet by declaring aws_nat_gateway and aws_eip.
You can not launch NAT Gateway without Elastic IP address associated with it, that’s why aws_eip required:
resource "aws_eip" "nat_gw_eip" {
vpc = true
}
resource "aws_nat_gateway" "gw" {
allocation_id = aws_eip.nat_gw_eip.id
subnet_id = aws_subnet.public.id
}
Now we need to create Main Route Table by declaring additional already known for you resources aws_route_table and associate it with our NAT-ed Subnet (aws_route_table_association):
resource "aws_route_table" "my_vpc_us_east_1a_nated" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.gw.id
}
tags = {
Name = "Main Route Table for NAT-ed subnet"
}
}
resource "aws_route_table_association" "my_vpc_us_east_1a_nated" {
subnet_id = aws_subnet.nated.id
route_table_id = aws_route_table.my_vpc_us_east_1a_nated.id
}
Now we’re ready to create private servers in our Private NAT-ed Subnet and they will have access to the Internet, but will not be visible from the Internet.
I guess you may do it using the instructions from the previous article.
Fully Isolated Private Subnet
Instances launched in this subnet will be able to communicate with instances within VPC, but will not be able to go to the Internet.
This type of network is commonly used when you need to connect your organization network to the AWS cloud and want more strict control of network boundaries. Or, you do not want to give some of your servers access to the Internet.
Here’s how the infrastructure looks like:

To implement a fully isolated Private Subnet we need to create the following resources:
- Subnet.
- Route Table.
- Association between Route Table and Subnet.
Let’s start from Subnet:
resource "aws_subnet" "private" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "Isolated Private Subnet"
}
}
Next, we need to create an additional Route Table with no routes declaration and associate it with our private
Subnet:
resource "aws_route_table" "my_vpc_us_east_1a_private" {
vpc_id = aws_vpc.my_vpc.id
tags = {
Name = "Local Route Table for Isolated Private Subnet"
}
}
resource "aws_route_table_association" "my_vpc_us_east_1a_private" {
subnet_id = aws_subnet.private.id
route_table_id = aws_route_table.my_vpc_us_east_1a_private.id
}
Summary
In this article, you’ve learned how to create different types of AWS Private Subnets in your environment and the differences between them.
We hope, this article has been helpful for you! If so, please, help us to spread it to the world!
Stay tuned!
Related articles
- Terraform – Managing AWS VPC – Creating Public Subnet
- AWS CloudFormation. Managing VPC
- CloudFormation Tutorial – How To Automate EC2 Instance In 5 Mins [Example]
- Top 10 SSH Features You MUST Know To Be More Productive
- Terraform – Managing Auto Scaling Groups & Load Balancers
- How to use CodePipeline CICD pipeline to test Terraform
- Automating Access To Multi-Region VPC Endpoints using Terraform
How useful was this post?
Click on a star to rate it!
We are sorry that this post was not useful for you!
Let us improve this post!
Tell us how we can improve this post?
I’m a passionate Cloud Infrastructure Architect with more than 15 years of experience in IT.
Any of my posts represent my personal experience and opinion about the topic.