Skip to main content

Command Palette

Search for a command to run...

Terraform Module that defines a VPC with public/private subnets across multiple AZs with Internet Gateways

Updated
10 min read

Terraform AWS VPC Module

SRE Learning Platform

Overview

This Terraform module creates an Amazon Virtual Private Cloud (VPC) with both public and private subnets, route tables, Network ACLs (NACLs), and NAT Gateways. It provides an extensible and customizable setup for scalable networking in AWS.

Features

  • Creation of a VPC with specified CIDR blocks, tags, and NACL settings.

  • Dynamic creation of public and private subnets with automatic retrieval of their IDs.

  • Subnet creation with the ability to assign them to specific Availability Zones (AZ) or AZ IDs.

  • Independent tagging for each subnet, allowing for individual resource labeling.

  • Flexible network management: ability to add new subnets or remove existing ones without impacting other subnets.

  • Support for three NAT Gateway scenarios (by default, AZ NAT Gateway is used):

    • AZ: One NAT Gateway is created for each AZ specified in private subnets.

    • SINGLE: One NAT Gateway is created for the entire VPC.

    • SUBNET: One NAT Gateway per subnet.

    • NONE: No NAT Gateway is created for the subnet, and no routes for 0.0.0.0/0 are configured.

    • Each subnet can be configured with any NAT Gateway type, and all types can coexist within a single VPC.

  • Custom DHCP options to fine-tune network configurations.

  • Output of all created resources, including subnet IDs grouped by type, AZ, and AZ ID.

Table Of Contents

Quick Start

provider "aws" {
  region = "eu-north-1"
}


module "vpc" {
  source = "ViktorUJ/vpc/aws"
  tags_default = {
    "Owner"       = "DevOps Team"
    "Terraform"   = "true"
    "cost_center" = "1111"
  }
  vpc = {
    name          = "test-vpc"
    cidr          = "10.10.0.0/16"
  }

  subnets = {
    public = {
      "pub1" = {
        name   = "public-subnet-1"
        cidr   = "10.10.1.0/24"
        az     = "eu-north-1c"
      }
      "pub2" = {
        name   = "public-subnet-2"
        cidr   = "10.10.2.0/24"
        az     = "eu-north-1a"
    }

    }
    private = {

     "private1" = {
       name        = "private-subnet-1"
       cidr        = "10.10.11.0/24"
       az          = "eu-north-1a"
       tags        = { "cost_center" = "1234" }

     }
     "private2" = {
       name        = "private-subnet-2"
       cidr        = "10.10.12.0/24"
       az          = "eu-north-1c"
       tags        = { "cost_center" = "5678" }
     }
    }
  }
}

output "vpc_id" {
  value = module.vpc.vpc_raw.id
}

output "vpc_cidr_block" {
  value = module.vpc.vpc_raw.cidr_block
}


output "private_subnets_by_type" {
  value = module.vpc.private_subnets_by_type
}
output "public_subnets_by_type" {
  value = module.vpc.public_subnets_by_type
}

Input Variables

VPC

VariableTypeRequiredDefaultDescription
vpc.namestringYesN/AThe name of the VPC.
vpc.cidrstringYesN/AThe CIDR block for the VPC.
vpc.secondary_cidr_blockslist(string)No[]Additional CIDR blocks to associate with the VPC.
vpc.tagsmap(string)No{}Tags to assign to the VPC.
vpc.instance_tenancystringNodefaultInstance tenancy option for instances in the VPC. Options: default, dedicated.
vpc.enable_dns_supportboolNotrueEnable DNS support in the VPC.
vpc.enable_dns_hostnamesboolNofalseEnable DNS hostnames in the VPC.
vpc.nacl_defaultmap(object)No{}Default NACL rules for the VPC.
vpc.dhcp_optionsobjectNo{}DHCP options set for the VPC.

Subnets

Public Subnets

VariableTypeRequiredDefaultDescription
subnets.publicmap(object)NoN/APublic subnets
subnets.public.namestringYesN/AName of the public subnet.
subnets.public.cidrstringYesN/AThe CIDR block for the public subnet.
subnets.public.azstringYesN/AAvailability Zone or Availability Zone ID for the public subnet.
subnets.public.tagsmap(string)No{}Tags to assign to the public subnet.
subnets.public.typestringNo"public"A custom type label for the public subnet (e.g., web, app).
subnets.public.assign_ipv6_address_on_creationboolNofalseAssign IPv6 addresses on creation.
subnets.public.customer_owned_ipv4_poolstringNo""ID of the customer-owned IPv4 address pool to use for the subnet.
subnets.public.enable_dns64boolNofalseEnable DNS64 for NAT64 in the public subnet.
subnets.public.enable_resource_name_dns_aaaa_record_on_launchboolNofalseEnable DNS AAAA records for resources in the public subnet.
subnets.public.enable_resource_name_dns_a_record_on_launchboolNofalseEnable DNS A records for resources in the public subnet.
subnets.public.ipv6_cidr_blockstringNo""The IPv6 CIDR block for the public subnet.
subnets.public.ipv6_nativeboolNofalseEnable native IPv6 addressing.
subnets.public.map_customer_owned_ip_on_launchboolNofalseMap customer-owned IP addresses on launch.
subnets.public.map_public_ip_on_launchboolNotrueMap public IP addresses on launch.
subnets.public.outpost_arnstringNo""ARN of the Outpost for the public subnet.
subnets.public.private_dns_hostname_type_on_launchstringNoip-nameThe type of DNS hostnames to assign on launch. ip-name or resource-name .
subnets.public.naclmap(object)No{}Network ACL (NACL) configuration for the public subnet.
subnets.public.nacl.egressstringNoN/AEgress rule for NACL (allow or deny).
subnets.public.nacl.rule_numberstringNoN/ARule number for the NACL entry.
subnets.public.nacl.rule_actionstringNoN/ARule action for the NACL entry (allow or deny).
subnets.public.nacl.from_portstringNo""From port for NACL rule (if applicable).
subnets.public.nacl.to_portstringNo""To port for NACL rule (if applicable).
subnets.public.nacl.icmp_codestringNo""ICMP code for NACL rule (if applicable).
subnets.public.nacl.icmp_typestringNo""ICMP type for NACL rule (if applicable).
subnets.public.nacl.protocolstringYesN/AProtocol for the NACL rule (e.g., TCP, UDP, ICMP, or -1 for all).
subnets.public.nacl.cidr_blockstringNo""CIDR block for the NACL rule (if applicable).
subnets.public.nacl.ipv6_cidr_blockstringNo""IPv6 CIDR block for the NACL rule (if applicable).

Private Subnets

VariableTypeRequiredDefaultDescription
subnets.privatemap(object)NoN/APrivate subnets.
subnets.private.namestringYesN/AName of the private subnet.
subnets.private.cidrstringYesN/AThe CIDR block for the private subnet.
subnets.private.azstringYesN/AAvailability Zone or Availability Zone ID for the private subnet.
subnets.private.tagsmap(string)No{}Tags to assign to the private subnet.
subnets.private.typestringNo"private"A custom type label for the private subnet (e.g., app, db).
subnets.private.nat_gatewaystringNo"AZ"NAT Gateway configuration: AZ, SINGLE, SUBNET, DEFAULT, or NONE.
subnets.private.assign_ipv6_address_on_creationboolNofalseAssign IPv6 addresses on creation.
subnets.private.customer_owned_ipv4_poolstringNo""ID of the customer-owned IPv4 address pool to use for the subnet.
subnets.private.enable_dns64boolNofalseEnable DNS64 for NAT64 in the private subnet.
subnets.private.enable_resource_name_dns_aaaa_record_on_launchboolNofalseEnable DNS AAAA records for resources in the private subnet.
subnets.private.enable_resource_name_dns_a_record_on_launchboolNofalseEnable DNS A records for resources in the private subnet.
subnets.private.ipv6_cidr_blockstringNo""The IPv6 CIDR block for the private subnet.
subnets.private.ipv6_nativeboolNofalseEnable native IPv6 addressing.
subnets.private.map_customer_owned_ip_on_launchboolNofalseMap customer-owned IP addresses on launch.
subnets.private.map_public_ip_on_launchboolNotrueMap public IP addresses on launch.
subnets.private.outpost_arnstringNo""ARN of the Outpost for the private subnet.
subnets.private.private_dns_hostname_type_on_launchstringNo"ip-name"The type of DNS hostnames to assign on launch for the private subnet. ip-name or resource-name
subnets.private.naclmap(object)No{}Network ACL (NACL) configuration for the private subnet.
subnets.private.nacl.egressstringYesN/AEgress rule for NACL (allow or deny).
subnets.private.nacl.rule_numberstringYesN/ARule number for the NACL entry.
subnets.private.nacl.rule_actionstringYesN/ARule action for the NACL entry (allow or deny).
subnets.private.nacl.from_portstringNo""From port for NACL rule (if applicable).
subnets.private.nacl.to_portstringNo""To port for NACL rule (if applicable).
subnets.private.nacl.icmp_codestringNo""ICMP code for NACL rule (if applicable).
subnets.private.nacl.icmp_typestringNo""ICMP type for NACL rule (if applicable).
subnets.private.nacl.protocolstringYesN/AProtocol for the NACL rule (e.g., TCP, UDP, ICMP, or -1 for all protocols).
subnets.private.nacl.cidr_blockstringNo""CIDR block for the NACL rule (if applicable).
subnets.private.nacl.ipv6_cidr_blockstringNo""IPv6 CIDR block for the NACL rule (if applicable).

Other

VariableTypeRequiredDefaultDescription
tags_defaultmap(string)No{}(Optional) Default tags to assign across all resources created by the module.

Output

VariableTypeDescription
tags_defaultmap(string)Default tags assigned to all resources.
subnets_varmap(object)The input subnets object for testing.
vpc_varobjectThe input VPC object.
vpc_rawmap(object)The AWS VPC resource.
az_mappingmap(object)Mapping of Availability Zones (AZ) to their corresponding IDs.
normalized_public_subnets_allmap(object)Normalized list of all public subnets.
subnets_public_rawmap(object)The AWS public subnets resource.
public_subnets_by_typemap(object)Public subnets grouped by type.
public_subnets_by_azmap(object)Public subnets grouped by Availability Zone.
public_subnets_by_az_idmap(object)Public subnets grouped by Availability Zone ID.
normalized_private_subnets_allmap(object)Normalized list of all private subnets.
subnets_private_rawmap(object)The AWS private subnets resource.
private_subnets_by_typemap(object)Private subnets grouped by type.
private_subnets_by_azmap(object)Private subnets grouped by Availability Zone.
private_subnets_by_az_idmap(object)Private subnets grouped by Availability Zone ID.
nacl_default_rules_rawmap(object)Default NACL rules.
public_nacl_rawmap(object)Public Network ACL resource.
public_nacl_rules_rawmap(object)Rules for the public Network ACL.
private_nacl_rawmap(object)Private Network ACL resource.
private_nacl_rules_rawmap(object)Rules for the private Network ACL.
nat_gateway_single_rawmap(object)The NAT gateway for the entire VPC.
nat_gateway_subnet_rawmap(object)The NAT gateway for each subnet.
nat_gateway_az_rawmap(object)The NAT gateway for each Availability Zone.
route_table_private_rawmap(object)Private route table.
route_table_public_rawmap(object)Public route table.

Examples

You can find additional examples in the examples directory:

ExampleDescription
simpleA basic VPC setup with public and private subnets.
customExample showcasing custom configurations in the VPC ,Subnets , NACL, etc .
nacl_defaultDemonstrates default Network ACL (NACL) configurations.
nacl_subnetConfiguring Network ACLs for individual subnets.
nat_gateway_azNAT Gateway setup with one NAT Gateway per Availability Zone (AZ).
nat_gateway_singleUsing a single NAT Gateway for the entire VPC.
nat_gateway_subnetSetting up one NAT Gateway per subnet.
output_private_subnet_by_typeOutputting private subnets grouped by type.

Contribution

If you want to be part of the project development team, get in touch with us. We are always happy to welcome new members to our development team

If you want to say thank you or/and support the active development of module :

  • Star the terraform-aws-vpc on Github

  • Feel free to write articles about the project on dev.to, medium, hackernoon or on your personal blog and share your experiences.

License and Usage Agreement

More from this blog

SRE Tribe

413 posts