giuseppe-trisciuoglio/aws-cloudformation-vpc
Provides AWS CloudFormation patterns for VPC foundations, including subnets, route tables, internet and NAT gateways, endpoints, and reusable outputs. Use when creating a new network baseline, segmenting public and private workloads, or preparing CloudFormation networking stacks for application deployments.
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill aws-cloudformation-vpc
Build a VPC foundation with CloudFormation that stays readable, reusable, and safe to evolve. Provides a clear subnet and routing model with predictable connectivity for public and private workloads, plus outputs that downstream stacks can consume without duplicating network logic.
Use the references/ files for larger templates and extended service combinations.
Before writing resources, define:
This prevents route-table sprawl and painful subnet replacement later.
Create the stack in this order:
Keep each layer easy to inspect in the template and avoid mixing unrelated application resources into the same stack.
Useful parameters include:
Do not parameterize every route or tag unless it meaningfully changes between environments.
Typical outputs:
Stable outputs make application stacks easier to compose and migrate.
Run these commands to validate the template and verify routing:
# Validate CloudFormation template syntax
aws cloudformation validate-template --template-body file://vpc.yaml
# Review change set before applying
aws cloudformation create-change-set \
--stack-name my-vpc \
--template-body file://vpc.yaml \
--change-set-type CREATE
# Verify route table associations
aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=<vpc-id>"
# Check subnet to route table mappings
aws ec2 describe-route-tables \
--filters "Name=association.subnet-id,Values=<subnet-id>"
# Verify internet gateway attachment
aws ec2 describe-internet-gateways \
--filters "Name=attachment.vpc-id,Values=<vpc-id>"
This template creates a VPC with public and private subnets, internet gateway, NAT gateway, and properly configured route tables.
AWSTemplateFormatVersion: "2010-09-09"
Description: "Two-tier VPC with public and private subnets"
Resources:
# VPC
MainVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-main"
# Internet Gateway
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-igw"
# Attach IGW to VPC
GatewayToInternet:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MainVpc
InternetGatewayId: !Ref InternetGateway
# Public Subnet (AZ 1)
PublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MainVpc
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs ""]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-public-a"
# Private Subnet (AZ 1)
PrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MainVpc
CidrBlock: 10.0.11.0/24
AvailabilityZone: !Select [0, !GetAZs ""]
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-private-a"
# Elastic IP for NAT Gateway
NatEip:
Type: AWS::EC2::EIP
DependsOn: GatewayToInternet
Properties:
Domain: vpc
# NAT Gateway
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
SubnetId: !Ref PublicSubnetA
AllocationId: !GetAtt NatEip.AllocationId
# Public Route Table
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MainVpc
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-public-rt"
# Default route to IGW
PublicDefaultRoute:
Type: AWS::EC2::Route
DependsOn: GatewayToInternet
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
# Associate public subnet
PublicSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetA
RouteTableId: !Ref PublicRouteTable
# Private Route Table
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MainVpc
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-private-rt"
# Default route via NAT Gateway
PrivateDefaultRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
# Associate private subnet
PrivateSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnetA
RouteTableId: !Ref PrivateRouteTable
Outputs:
VpcId:
Description: VPC ID
Value: !Ref MainVpc
Export:
Name: !Sub "${AWS::StackName}-VpcId"
PublicSubnetA:
Description: Public subnet AZ1
Value: !Ref PublicSubnetA
Export:
Name: !Sub "${AWS::StackName}-PublicSubnetA"
PrivateSubnetA:
Description: Private subnet AZ1
Value: !Ref PrivateSubnetA
Export:
Name: !Sub "${AWS::StackName}-PrivateSubnetA"
PublicRouteTableId:
Description: Public route table ID
Value: !Ref PublicRouteTable
Export:
Name: !Sub "${AWS::StackName}-PublicRouteTableId"
PrivateRouteTableId:
Description: Private route table ID
Value: !Ref PrivateRouteTable
Export:
Name: !Sub "${AWS::StackName}-PrivateRouteTableId"
Resources:
# S3 VPC Endpoint
S3Endpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref MainVpc
ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
RouteTableIds:
- !Ref PrivateRouteTable
VpcEndpointType: Gateway
references/examples.mdreferences/examples.mdreferences/reference.mdTake giuseppe-trisciuoglio/aws-cloudformation-vpc from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.