Skip to content

vpc module

Aleksej Komnenovic edited this page Jun 30, 2026 · 3 revisions

VPC Module

Creates a VPC with private subnets. The public-subnet resources (public subnets, internet gateway, NAT gateway, EIP) are optional. With them off, the module builds a fully private VPC with no public-subnet resources.

Files

File Purpose
main.tf VPC, subnets, NAT, IGW, route tables
endpoints.tf VPC endpoints for S3, ECR, Logs, SM, STS
variables.tf Input variables
outputs.tf Module outputs

Resources Created

Core Networking (main.tf)

Resource Count Purpose
aws_vpc 1 VPC with DNS hostnames + support enabled
aws_internet_gateway 0 or 1 Created only when public subnets exist
aws_subnet.public 0 or 1 per AZ Created when an internet-facing ALB needs them, or to host a NAT gateway
aws_subnet.private 1 per AZ Private subnets (cidrsubnet(cidr, 8, index + 128))
aws_eip.nat 0, 1 or N None when nat_gateway_mode = none
aws_nat_gateway 0, 1 or N None when nat_gateway_mode = none
aws_route_table.public 0 or 1 Created with public subnets
aws_route_table.private 1 or N Always created. Routes 0.0.0.0/0 to NAT when one exists

Subnet CIDR Calculation

With default CIDR 10.0.0.0/16:

  • Public subnets: 10.0.0.0/24, 10.0.1.0/24, 10.0.2.0/24...
  • Private subnets: 10.0.128.0/24, 10.0.129.0/24, 10.0.130.0/24...

NAT Gateway Modes

Mode NAT Gateways Private Route Tables Public Subnets Use Case
single 1 1 shared Yes (hosts the NAT) Dev/staging
ha 1 per AZ 1 per AZ Yes (hosts the NATs) Production
none 0 1 shared No Private VPC, egress via VPC endpoints

In ha mode, each private subnet routes through its own AZ's NAT gateway for resilience.

none creates no NAT gateway and no EIP. Public subnets are then created only if an internet-facing ALB needs them. With every ALB internal, the VPC has no public-subnet resources. The tasks reach AWS through VPC endpoints, which the module turns on automatically in this mode.

These endpoints reach AWS only. A workload that calls the public internet, such as BRMS validating its license at portal.gorules.io, needs real egress and cannot run in this VPC. The none mode suits an agent-only deployment.

VPC Endpoints (endpoints.tf)

Created when enable_vpc_endpoints = true, and automatically when nat_gateway_mode = none (then they are the only path to AWS). They cut NAT cost and keep traffic on the Amazon network.

Endpoint Type Purpose
S3 Gateway S3 access without NAT (used by Storage Module)
ECR API Interface Pull container images (used by ECS Module)
ECR DKR Interface Docker layer downloads
CloudWatch Logs Interface Log shipping
Secrets Manager Interface Secret retrieval (used by Secrets Management)
STS Interface IAM temporary credentials

All interface endpoints share one security group that allows HTTPS (443) from the VPC CIDR. The base set is ecr.api, ecr.dkr, logs, secretsmanager, sts. Add more with additional_vpc_endpoints. The root module injects kms automatically when BRMS uses the aws-kms secrets provider, and bedrock-runtime when BRMS AI uses Amazon Bedrock (amazon-bedrock). It merges these into the list it passes to the VPC module as additional_interface_endpoints. The VPC module does not add them itself.

How Other Modules Use This

  • ECS Module: ALBs in public subnets, or private subnets when alb_internal = true. Tasks always run in private subnets.
  • Database Module: Aurora cluster in private subnets via aws_db_subnet_group
  • Security Architecture: SGs reference VPC ID for network isolation

Key Variables

vpc = {
  create               = true          # false → use existing VPC
  cidr                 = "10.0.0.0/16"
  availability_zones   = []            # auto-selects first 2 AZs
  nat_gateway_mode     = "single"      # "single", "ha", or "none"
  enable_vpc_endpoints = false         # forced on when nat_gateway_mode = "none"
  additional_vpc_endpoints = []        # extra interface endpoints, e.g. ["ssmmessages"]
  # For existing VPC:
  id                   = null
  private_subnet_ids   = []
  public_subnet_ids    = []            # optional when every ALB is internal
}

Outputs

  • vpc_id, vpc_cidr_block
  • private_subnet_ids, public_subnet_ids + CIDRs (public lists are empty in a private VPC)
  • nat_gateway_ids, nat_gateway_public_ips (empty when nat_gateway_mode = none)
  • public_route_table_id (null with no public subnets), private_route_table_ids
  • vpc_endpoint_s3_id, vpc_endpoint_interface_ids, vpc_endpoints_security_group_id
  • internet_gateway_id (null when the VPC has no public subnets)

Clone this wiki locally