VPC: your own network in the cloud
Before you launch a server, it needs somewhere to live: a network with addresses, a way in from the internet (or deliberately none), and a firewall. In AWS that's a VPC (Virtual Private Cloud). It's the same networking you learned on Linux: CIDR blocks, routes, a default gateway and firewall rules. The difference is that you build it with API calls instead of cables.
You will learn
- VPCs, CIDR blocks and subnets, and why a subnet lives in one AZ
- What makes a subnet public: an internet gateway plus a route table
- Security groups (stateful, per instance) vs network ACLs (stateless, per subnet)
- Building a small VPC from the CLI, with shell variables holding the IDs
The pieces
VPC cht-vpc 10.0.0.0/16 ─────────────────────────────────────────── us-east-1
│
├── Internet gateway (igw-…) ◀──── the internet
│
├── Route table "public-rt": 10.0.0.0/16 → local 0.0.0.0/0 → igw-…
│ │
│ └── Subnet public-a 10.0.1.0/24 us-east-1a ← web servers get public IPs
│
└── Main route table: 10.0.0.0/16 → local (no way out)
└── Subnet private-b 10.0.2.0/24 us-east-1b ← databases: no internet route
| Piece | What it does | Linux cousin |
|---|---|---|
| VPC | A private network in one region, with an address range like 10.0.0.0/16 (65,536 addresses) | your home LAN |
| Subnet | A slice of the VPC's range, in one availability zone. /24 = 256 addresses, of which AWS keeps 5 | one network segment |
| Internet gateway | The VPC's door to the internet. Free, and does nothing until a route points at it | your router's WAN port |
| Route table | Rules for where packets go, attached to subnets | ip route |
| Security group | A firewall around each instance: allow rules only. Stateful: replies to allowed traffic go out on their own | firewalld / ufw on every server |
| Network ACL | A firewall on the subnet edge, with numbered allow and deny rules. Stateless: you must allow replies too. Most people leave the default (allow all) | a router ACL |
A subnet is public only because its route table sends 0.0.0.0/0 to an internet gateway. There's no "public" checkbox. Private subnets have no such route, so nothing there can be reached from the internet, even if it has a public IP.
AWS makes one (172.31.0.0/16) with a public subnet in each AZ, so beginners can launch servers straight away. It's fine for experiments. For real work you build your own, so you know exactly what's public.
Planning the addresses
Pick a private range (10.x, 172.16–31.x or 192.168.x) that won't clash with your office or other VPCs you might connect later. A common plan: a /16 for the VPC, and a /24 per subnet, numbered so you can tell them apart: 10.0.1.0/24 public in AZ a, 10.0.2.0/24 in AZ b, and so on. Subnets can't overlap, and they must fit inside the VPC's range. AWS will refuse if they don't.
Building it from the CLI
Each create command prints JSON with a new ID in it. Catch the ID in a shell variable with --query … --output text, and the next command can use it:
VPC=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=cht-vpc}]' \
--query Vpc.VpcId --output text)
echo $VPC # vpc-0e64304f81f7eef46
SUBA=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a --query Subnet.SubnetId --output text)
IGW=$(aws ec2 create-internet-gateway --query InternetGateway.InternetGatewayId --output text)
aws ec2 attach-internet-gateway --internet-gateway-id $IGW --vpc-id $VPC
RTB=$(aws ec2 create-route-table --vpc-id $VPC --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $RTB --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW
aws ec2 associate-route-table --route-table-id $RTB --subnet-id $SUBA
aws ec2 modify-subnet-attribute --subnet-id $SUBA --map-public-ip-on-launch # new servers here get a public IP
Tags are labels (Key=Name,Value=cht-vpc). The Name tag is what the web console shows, and tags like Project=cht let you find (and clean up) everything that belongs together.
Security groups
SG=$(aws ec2 create-security-group --group-name web-sg --description "Web servers" \
--vpc-id $VPC --query GroupId --output text)
curl checkip.amazonaws.com # your public IP, e.g. 203.0.113.77
aws ec2 authorize-security-group-ingress --group-id $SG --protocol tcp --port 22 --cidr 203.0.113.77/32
aws ec2 authorize-security-group-ingress --group-id $SG --protocol tcp --port 80 --cidr 0.0.0.0/0
SSH only from your address (/32 = exactly one IP), the website from anywhere (0.0.0.0/0). A security group can also allow traffic from another security group (--source-group), which is how you'll let a load balancer talk to web servers in the load balancer lesson.
0.0.0.0/0
Bots try passwords on every public SSH port within minutes of it appearing. Allow your own IP only, or skip SSH completely and use AWS Systems Manager Session Manager.
Just like on Linux: a security group that doesn't allow a port drops the packets, so you see a timeout. If the packet gets through but nothing listens there, you get connection refused. Timeout = check the network (security group, route table). Refused = check the server.
One piece this lesson leaves out: a NAT gateway lets servers in private subnets reach out to the internet (for updates) without being reachable. It's handy but costs about $32 a month plus data, even when idle. Beginners often forget one and get a surprise bill.
Practice: build a VPC 🧱
An empty account (just the default VPC). Build the network from the diagram: a VPC, a public and a private subnet, an internet gateway, a route table and a security group. The next lesson launches a server into a network like this one.
Quick check
1. What makes a subnet "public"?
✓ Public means "has a route to the internet gateway". The map-public-ip setting only decides whether new servers get a public address.
2. curl to your server's port 80 hangs and then times out. What do you check first?
✓ Timeouts mean packets were dropped on the way. "Connection refused" would point at the server itself.
3. Why does each subnet live in exactly one availability zone?
✓ One subnet per AZ, and you spread your servers over several.