AWS CLI VPC Commands: Create a VPC, Subnets and Route Tables
We build a full VPC from the terminal: VPC, public and private subnets, internet gateway, route tables, security groups and a NAT gateway. Then we tear it down.
What you'll learn in this chapter
- Create a VPC and subnets
- Attach an internet gateway and routes
- Security groups and NACL basics
- NAT gateway for private subnets
- Describe and delete in order
1. The big picture: a network by commands
Why do we need this?
A housing society has one gate (internet gateway), roads (route tables), wings (subnets) and guards at each flat door (security groups).
What is it?
All VPC commands are inside aws ec2: create-vpc, create-subnet, create-internet-gateway, create-route-table, create-route, create-nat-gateway.
How to do it (step by step)
2. Create the VPC and subnets
Why do we need this?
A VPC is your private network. Subnets split it by zone and by public/private.
What is it?
The VPC gets a CIDR like 10.0.0.0/16. Each subnet takes a smaller CIDR in one Availability Zone.
How to do it (step by step)
- Create the VPC.
VPC=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications "ResourceType=vpc,Tags=[{Key=Name,Value=cli-vpc}]" --query Vpc.VpcId --output text)
echo $VPC
Expected output:
vpc-0a1b2c3d4e5f60718
- Turn on DNS hostnames.
aws ec2 modify-vpc-attribute --vpc-id $VPC --enable-dns-hostnames
Expected output:
(no output means success)
- Public subnet in ap-south-1a.
PUB=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.0.1.0/24 --availability-zone ap-south-1a --query Subnet.SubnetId --output text)
aws ec2 modify-subnet-attribute --subnet-id $PUB --map-public-ip-on-launch
Expected output:
subnet-0pub...
- Private subnet in ap-south-1b.
PRI=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.0.2.0/24 --availability-zone ap-south-1b --query Subnet.SubnetId --output text)
Expected output:
(no output means success)
- Verify.
aws ec2 describe-subnets --filters Name=vpc-id,Values=$VPC --query "Subnets[].[SubnetId,CidrBlock,AvailabilityZone,MapPublicIpOnLaunch]" --output table
Expected output:
| subnet-0pub... | 10.0.1.0/24 | ap-south-1a | True |
| subnet-0pri... | 10.0.2.0/24 | ap-south-1b | False |
3. Internet gateway and public route
Why do we need this?
Without a gateway and a route, nothing in the VPC can reach the internet.
What is it?
A subnet is public only when its route table sends 0.0.0.0/0 to an internet gateway.
How to do it (step by step)
- Create and attach the IGW.
IGW=$(aws ec2 create-internet-gateway --query InternetGateway.InternetGatewayId --output text)
aws ec2 attach-internet-gateway --vpc-id $VPC --internet-gateway-id $IGW
Expected output:
igw-0abc...
- Public route table.
RT=$(aws ec2 create-route-table --vpc-id $VPC --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $RT --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW
aws ec2 associate-route-table --route-table-id $RT --subnet-id $PUB
Expected output:
{ "Return": true }
{ "AssociationId": "rtbassoc-0abc..." }
- Verify routes.
aws ec2 describe-route-tables --route-table-ids $RT --query "RouteTables[0].Routes[].[DestinationCidrBlock,GatewayId]" --output text
Expected output:
10.0.0.0/16 local
0.0.0.0/0 igw-0abc...
4. Security groups and NACLs
Why do we need this?
Guards decide who may knock on each server.
What is it?
Security groups are stateful and attach to instances. NACLs are stateless and attach to subnets.
How to do it (step by step)
- Web SG allowing HTTP.
WSG=$(aws ec2 create-security-group --vpc-id $VPC --group-name cli-web --description web --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $WSG --protocol tcp --port 80 --cidr 0.0.0.0/0
Expected output:
(no output means success)
- DB SG allowing 3306 only from the web SG.
DSG=$(aws ec2 create-security-group --vpc-id $VPC --group-name cli-db --description db --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $DSG --protocol tcp --port 3306 --source-group $WSG
Expected output:
(no output means success)
- See the default NACL.
aws ec2 describe-network-acls --filters Name=vpc-id,Values=$VPC --query "NetworkAcls[0].Entries[].[RuleNumber,Egress,RuleAction]" --output text
Expected output:
100 False allow
32767 False deny
100 True allow
32767 True deny
5. NAT gateway for the private subnet
Why do we need this?
Private servers need updates from the internet but must not be reachable from it.
What is it?
A NAT gateway sits in the public subnet with an Elastic IP. The private route table sends 0.0.0.0/0 to it. It costs money per hour.
How to do it (step by step)
- Create NAT.
EIP=$(aws ec2 allocate-address --query AllocationId --output text)
NAT=$(aws ec2 create-nat-gateway --subnet-id $PUB --allocation-id $EIP --query NatGateway.NatGatewayId --output text)
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT && echo nat-ready
Expected output:
nat-ready
- Private route.
PRT=$(aws ec2 create-route-table --vpc-id $VPC --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $PRT --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT
aws ec2 associate-route-table --route-table-id $PRT --subnet-id $PRI
Expected output:
{ "Return": true }
- Verify.
aws ec2 describe-nat-gateways --nat-gateway-ids $NAT --query "NatGateways[0].State" --output text
Expected output:
available
6. Same action in Python, Node.js, Java, Go, .NET and PHP
Why do we need this?
Scripts start in the CLI. Apps call the same API through an SDK. Knowing both helps you move a tested command into real code.
What is it?
Each CLI command maps to one API call. For example aws ec2 create-vpc --cidr-block 10.0.0.0/16 maps to the CreateVpc API.
How to do it (step by step)
Same action (CreateVpc) from code. Every SDK reads the same profile, region and credentials as the CLI.
| Stack | Code |
|---|---|
| Python (boto3) | boto3.client("ec2").create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"] |
| Node.js (v3) | await ec2.send(new CreateVpcCommand({CidrBlock:"10.0.0.0/16"})); |
| Java (v2) | ec2.createVpc(r -> r.cidrBlock("10.0.0.0/16")).vpc().vpcId(); |
| Go (v2) | c.CreateVpc(ctx, &ec2.CreateVpcInput{CidrBlock: aws.String("10.0.0.0/16")}) |
| .NET | await ec2.CreateVpcAsync(new CreateVpcRequest{CidrBlock="10.0.0.0/16"}); |
| PHP | $ec2->createVpc(["CidrBlock"=>"10.0.0.0/16"]); |
7. Clean up so nothing keeps costing
Why do we need this?
Lab resources left running cost money and can be a security risk.
What is it?
Delete in reverse order: children first, then parents.
How to do it (step by step)
- NAT first, then EIP.
aws ec2 delete-nat-gateway --nat-gateway-id $NAT
aws ec2 wait nat-gateway-deleted --nat-gateway-ids $NAT
aws ec2 release-address --allocation-id $EIP
Expected output:
(no output means success)
- Security groups.
aws ec2 delete-security-group --group-id $DSG
aws ec2 delete-security-group --group-id $WSG
Expected output:
(no output means success)
- Route tables (disassociate first).
for A in $(aws ec2 describe-route-tables --route-table-ids $RT $PRT --query "RouteTables[].Associations[].RouteTableAssociationId" --output text); do aws ec2 disassociate-route-table --association-id $A; done
aws ec2 delete-route-table --route-table-id $RT
aws ec2 delete-route-table --route-table-id $PRT
Expected output:
(no output means success)
- IGW, subnets, VPC.
aws ec2 detach-internet-gateway --vpc-id $VPC --internet-gateway-id $IGW
aws ec2 delete-internet-gateway --internet-gateway-id $IGW
aws ec2 delete-subnet --subnet-id $PUB
aws ec2 delete-subnet --subnet-id $PRI
aws ec2 delete-vpc --vpc-id $VPC
Expected output:
(no output means success)
- Verify.
aws ec2 describe-vpcs --vpc-ids $VPC
Expected output:
An error occurred (InvalidVpcID.NotFound) ...
Ravindra Bagale's Tip
If delete-vpc fails with DependencyViolation, list network interfaces in the VPC. Something (NAT, endpoint, Lambda) still uses it.
8. Interview questions and answers
Q. What makes a subnet public?
A route of 0.0.0.0/0 to an internet gateway in its route table.
Q. Where does a NAT gateway live?
In a public subnet, with an Elastic IP.
Q. SG vs NACL?
SG is stateful at the instance. NACL is stateless at the subnet with numbered rules.
Q. How do you allow DB traffic only from web servers?
--source-group with the web security group ID.
Q. Why does delete-vpc fail?
Dependencies remain: ENIs, NAT, IGW, subnets or SGs.
Try at home
- Build the VPC, launch an instance in the public subnet and curl it.
- Write the cleanup as one bash script and run it.
In short
- create-vpc, create-subnet.
- IGW + 0.0.0.0/0 route = public.
- SG by instance, NACL by subnet.
- NAT for private egress.
- Delete in reverse order.
Practice Tasks
Pune Fintech Labs is a finance business in Pune. Rohan Kulkarni looks after its IT and cloud work. They count money in INR and run their AWS resources in the ap-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.
0 / 12
Easy How many addresses in a /16?
Why: Picking a VPC size needs this count.
What to do: Pune Fintech Labs plans the VPC 10.42.0.0/16. How many IP addresses does it hold in total?
- Write down the numbers the task gives you.
- Work it out step by step on paper.
- Type only the final answer in the box.
- Click Check answer.
Easy Create a VPC
Why: A VPC is your own private network in AWS. Everything else lives inside it.
What to do: Create a VPC with the CIDR block 10.8.0.0/16.
- Read the task and decide which AWS service it is about.
- Write aws, then the service name, then the operation (the action word).
- Add each needed flag (--name) followed by its value from the task.
- Flags can be in any order. Click Check answer.
Easy Create an internet gateway
Why: Without an internet gateway, nothing in the VPC can reach the internet.
What to do: Create a new internet gateway.
- Read the task and decide which AWS service it is about.
- Write aws, then the service name, then the operation (the action word).
- Add each needed flag (--name) followed by its value from the task.
- Flags can be in any order. Click Check answer.
Medium Create a subnet in one AZ
Why: Subnets split the VPC range and each one lives in exactly one AZ.
What to do: In vpc-042045ff53deadbee, create subnet 10.8.1.0/24 in ap-south-1a.
- Read the task and decide which AWS service it is about.
- Write aws, then the service name, then the operation (the action word).
- Add each needed flag (--name) followed by its value from the task.
- Flags can be in any order. Click Check answer.
Medium Find the VPC router address
Why: AWS reserves base+1 for the router.
What to do: Which address does AWS reserve for the VPC router in subnet 10.42.4.0/24?
- Write down the numbers the task gives you.
- Work it out step by step on paper.
- Type only the final answer in the box.
- Click Check answer.
Medium Usable IPs in an AWS /24 subnet
Why: AWS keeps 5 addresses in every subnet.
What to do: How many addresses can Pune Fintech Labs use for servers in subnet 10.42.1.0/24 on AWS?
- Write down the numbers the task gives you.
- Work it out step by step on paper.
- Type only the final answer in the box.
- Click Check answer.
Medium Add the internet route
Why: A subnet is "public" only when its route table sends 0.0.0.0/0 to an internet gateway.
What to do: In route table rtb-00542045cc53bb22, send all internet traffic (0.0.0.0/0) to igw-0542045cc53aa11.
- Read the task and decide which AWS service it is about.
- Write aws, then the service name, then the operation (the action word).
- Add each needed flag (--name) followed by its value from the task.
- Flags can be in any order. Click Check answer.
Medium Link a subnet to a route table
Why: Until you associate it, a subnet uses the main route table.
What to do: Associate subnet subnet-00542045cc53bb1 with route table rtb-00542045cc53bb22.
- Read the task and decide which AWS service it is about.
- Write aws, then the service name, then the operation (the action word).
- Add each needed flag (--name) followed by its value from the task.
- Flags can be in any order. Click Check answer.
Medium Attach the internet gateway
Why: A gateway does nothing until it is attached to a VPC.
What to do: Attach igw-0542045cc53aa11 to vpc-042045ff53deadbee.
- Read the task and decide which AWS service it is about.
- Write aws, then the service name, then the operation (the action word).
- Add each needed flag (--name) followed by its value from the task.
- Flags can be in any order. Click Check answer.
Medium First usable IP for a server
Why: The first 4 addresses are reserved by AWS.
What to do: What is the first IP address a server can get in 10.42.20.0/24 on AWS?
- Write down the numbers the task gives you.
- Work it out step by step on paper.
- Type only the final answer in the box.
- Click Check answer.
Hard Pick the smallest prefix
Why: Right-sizing saves address space.
What to do: A subnet must hold 100 servers on AWS. What is the largest prefix number (smallest subnet) that fits? Answer like /25.
- Write down the numbers the task gives you.
- Work it out step by step on paper.
- Type only the final answer in the box.
- Click Check answer.
Hard Split a /24 into two
Why: Public and private subnets often split one block.
What to do: Split 10.42.8.0/24 into two equal subnets. Write both CIDRs separated by a comma.
- Write down the numbers the task gives you.
- Work it out step by step on paper.
- Type only the final answer in the box.
- Click Check answer.
Revision, comparison and interview cards
Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.




More cards: Ravi Sir's Cards.