AWS Builder Center

What I Learned Setting Up My First VPC and EC2 Instance

A beginner's lessons on VPC networking, and the checklist I now use when an instance won't connect.

Introduction

When I set up my first custom VPC and launched an EC2 instance inside it, I assumed it would take ten minutes. Instead, I spent hours staring at a "Connection timed out" error while my instance sat there, running and unreachable.
This article walks through what I built, the mistakes I made, and the checklist that now saves me time. If you're new to AWS networking, I hope it saves you the same pain.

What I Built

The setup was simple on paper:
  • A custom VPC with the CIDR block 10.0.0.0/16
  • One public subnet (10.0.1.0/24)
  • An internet gateway
  • A route table for the subnet
  • An EC2 instance (Amazon Linux, t2.micro) that I wanted to reach over SSH
Simple, but every one of these pieces has to be connected correctly. Miss one link and nothing works.

Lesson 1: Creating an Internet Gateway Is Not Enough

My first mistake was thinking that creating an internet gateway made my subnet public. It doesn't. Two more steps are needed:
  1. Attach the internet gateway to the VPC.
  2. Add a route in the subnet's route table that sends 0.0.0.0/0 to the internet gateway.
A subnet is only "public" because its route table has a route to an internet gateway. Without that route, the subnet is private, no matter what you named it.

Lesson 2: A Public Subnet Still Needs a Public IP

Even with the route in place, my instance was unreachable. The reason: it had no public IPv4 address. Instances need one (or an Elastic IP) to be reached from the internet.
You can fix this by enabling auto-assign public IPv4 address on the subnet, or by turning it on in the network settings when you launch the instance.

Lesson 3: Security Groups and NACLs Behave Differently

I knew I needed to allow SSH, so I added an inbound rule for port 22 to my security group. But I didn't understand how it differed from a network ACL.
Security GroupNetwork ACL
Applies toInstance (network interface)Subnet
StateStateful: return traffic is automatically allowedStateless: you must allow traffic in both directions
RulesAllow rules onlyAllow and deny rules
The default NACL allows all traffic, so I was fine. But when I later created a custom NACL, I forgot the outbound rule for ephemeral ports (1024-65535), and connections broke again. Because NACLs are stateless, return traffic needs its own rule.

Lesson 4: Plan Your CIDR Blocks Early

I picked 10.0.0.0/16 without much thought. It worked, but it taught me that CIDR ranges are hard to change later. A few tips:
  • Leave room to grow. A /16 VPC gives you plenty of space to split into /24 subnets.
  • Avoid overlapping ranges if you might peer VPCs or connect to an on-premises network later.
  • Use separate subnets for different tiers, such as public, private, and database.

Lesson 5: Don't Open SSH to the Whole World

In my rush, I set the SSH rule source to 0.0.0.0/0. That means anyone on the internet can attempt to connect. Instead:
  • Restrict port 22 to your own IP (x.x.x.x/32).
  • Better still, use AWS Systems Manager Session Manager, which lets you connect without opening any inbound ports at all.

Lesson 6: Private Subnets Need a NAT Gateway for Outbound Access

When I added a private subnet for a second instance, it couldn't download updates. Private subnets have no route to the internet gateway, so they need a NAT gateway (placed in a public subnet) for outbound-only access.
One warning: NAT gateways are billed hourly plus data processing. If you're experimenting, delete them when you're done so they don't quietly add to your bill.

My Troubleshooting Checklist

Now, whenever an instance is unreachable, I check these in order:
  1. Public IP: Does the instance have a public IPv4 address or Elastic IP?
  2. Internet gateway: Is it attached to the VPC?
  3. Route table: Does the subnet's route table send 0.0.0.0/0 to the internet gateway?
  4. Security group: Does it allow the port and source IP I'm connecting from?
  5. Network ACL: Does it allow traffic in both directions?
  6. Instance state: Is the instance actually running, and is the service listening on that port?
If you're still stuck, the VPC Reachability Analyzer can trace a path between two resources and point out where traffic is blocked.

Key Takeaways

  • A subnet is public only if its route table points to an internet gateway.
  • A public subnet doesn't help without a public IP on the instance.
  • Security groups are stateful; NACLs are stateless. Check both.
  • Plan your CIDR ranges before building, not after.
  • Restrict SSH access, or skip SSH entirely with Session Manager.
  • Clean up NAT gateways and unused resources to avoid surprise costs.
Most VPC problems come down to routing and permissions. Once you understand how the route table, gateway, and security group fit together, the rest falls into place.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article