Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Setting Up a VPC on AWS: Cloud Networking Fundamentals

By Kokil Thapa | Last reviewed: September 2026

Setting Up a VPC on AWS: Cloud Networking Fundamentals is the step most teams skip until production traffic exposes a routing mistake or a database sits on a public subnet. A Virtual Private Cloud is your isolated network boundary inside AWS — the place where IP ranges, subnets, gateways, and firewall rules decide what can reach the internet and what stays internal. If you have moved Laravel apps from shared hosting to EC2, as described in our guide on deploying Laravel on AWS EC2 with RDS, the VPC is the foundation beneath every instance, load balancer, and database endpoint. This guide walks through planning, creation, routing, and hardening so your first VPC survives real traffic.

What is an AWS VPC and why does cloud networking start here?

An AWS VPC is a logically isolated section of the AWS cloud where you launch resources with addresses you control. Every EC2 instance, RDS database, Lambda function in a VPC, and internal load balancer lives inside one. Unlike a flat shared hosting network, a VPC gives you routing tables, subnet boundaries, and firewall layers you define.

Think of it as wiring a small data centre inside AWS. You choose the address space. You decide which subnets face the internet and which stay private. You control east-west traffic between tiers. On production Laravel deployments I maintain, the VPC separates web servers, application workers, and database layers before any security group rule is written.

AWS creates a default VPC in each region when you open an account. It works for quick tests. Production workloads should use a custom VPC with deliberate CIDR sizing and multi-AZ layout. Default VPCs use predictable ranges and permissive defaults that do not scale well for compliance or cost control.

AWS VPC Architecture OverviewRegion: ap-south-1 (Mumbai)VPC 10.0.0.0/16AZ-aPublic 10.0.1.0/24Private 10.0.11.0/24AZ-bPublic 10.0.2.0/24Private 10.0.12.0/24InternetGatewayNATGatewaySecurity Groups+ Network ACLs
Setting Up a VPC on AWS: Cloud Networking Fundamentals — region, CIDR block, multi-AZ subnets, and gateway attachments

For context on when cloud networking beats traditional hosting, see our comparison of AWS cloud hosting versus shared hosting in Nepal. VPC design is what makes that migration technically viable rather than just moving files to a bigger server.

How do you plan CIDR blocks and subnets before creating a VPC?

CIDR planning is the decision you cannot easily reverse. Pick a range large enough for growth but small enough to avoid overlapping future VPN or peering connections. The AWS VPC CIDR documentation allows multiple IPv4 CIDR blocks per VPC, but starting with one well-sized block keeps routing simple.

Choose a VPC CIDR size

A /16 block gives 65,536 addresses — enough for most single-application deployments. A /20 gives 4,096 addresses, which suits smaller staging environments or client projects with tight budgets. Avoid ranges that collide with your office LAN, home lab, or another cloud network you may peer later. Common safe choices include 10.0.0.0/16, 10.1.0.0/16, and 172.16.0.0/16.

Split subnets by tier and Availability Zone

Reserve at least two Availability Zones for high availability. Within each zone, create one public subnet and one private subnet. Public subnets get a route to an internet gateway. Private subnets hold databases, cache nodes, and background workers.

A practical /16 layout for a Laravel stack looks like this:

  • 10.0.1.0/24 — public subnet, AZ-a (ALB, bastion, NAT gateway)
  • 10.0.2.0/24 — public subnet, AZ-b (ALB, NAT gateway)
  • 10.0.11.0/24 — private subnet, AZ-a (EC2 app servers)
  • 10.0.12.0/24 — private subnet, AZ-b (EC2 app servers)
  • 10.0.21.0/24 — private subnet, AZ-a (RDS primary)
  • 10.0.22.0/24 — private subnet, AZ-b (RDS standby)

Leave unused /24 blocks for future services like ElastiCache or internal APIs. IP address planning is similar in spirit to subnetting a physical office network — a topic that overlaps with Linux system administration work on bare-metal and VPS setups.

Compare common VPC sizing patterns

PatternCIDRBest forTrade-off
Small staging10.0.0.0/20Dev/test, single AZ acceptableLimited room for growth
Standard production10.0.0.0/16Web app + DB + cache, multi-AZCosts more with NAT per AZ
Multi-app shared VPC10.0.0.0/16 + secondary CIDRSeveral products, shared ops teamBlast radius if misconfigured
Account per environment10.1.0.0/16 prod, 10.2.0.0/16 stagingClean isolation, easier complianceMore accounts to manage

For teams evaluating cloud platforms before committing to VPC design, our AWS vs Azure vs Google Cloud comparison for 2026 covers regional presence and pricing context relevant to Nepal-based deployments.

How do you create and configure an AWS VPC step by step?

You can create a VPC through the AWS Console, the AWS CLI, or infrastructure-as-code tools. For repeatable production setups, prefer AWS CloudFormation for infrastructure as code or Terraform. Manual console clicks are fine for learning. They become a liability when you rebuild staging every month.

Step 1: Create the VPC

aws ec2 create-vpc \
  --cidr-block 10.0.0.0/16 \
  --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=prod-app-vpc}]' \
  --region ap-south-1

Enable DNS hostnames and DNS resolution on the VPC. Laravel apps, RDS endpoints, and internal service discovery depend on DNS inside the VPC. Without it, private hostnames fail to resolve and health checks break silently.

aws ec2 modify-vpc-attribute \
  --vpc-id vpc-0abc123def456789 \
  --enable-dns-hostnames '{"Value": true}'

aws ec2 modify-vpc-attribute \
  --vpc-id vpc-0abc123def456789 \
  --enable-dns-support '{"Value": true}'

Step 2: Create subnets in two Availability Zones

aws ec2 create-subnet \
  --vpc-id vpc-0abc123def456789 \
  --cidr-block 10.0.1.0/24 \
  --availability-zone ap-south-1a \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-az-a}]'

aws ec2 create-subnet \
  --vpc-id vpc-0abc123def456789 \
  --cidr-block 10.0.11.0/24 \
  --availability-zone ap-south-1a \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-app-az-a}]'

Repeat for AZ-b with 10.0.2.0/24 and 10.0.12.0/24. Map public IP assignment at launch only on public subnets. Private subnets should never auto-assign public IPs.

Step 3: Attach an internet gateway

aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=prod-igw}]'

aws ec2 attach-internet-gateway \
  --internet-gateway-id igw-0abc123 \
  --vpc-id vpc-0abc123def456789

The internet gateway is a horizontally scaled AWS component. You do not manage its capacity. You only attach it and reference it in route tables.

Three-Tier Subnet LayoutPublic TierALB · Bastion · NAT GatewayPrivate App TierEC2 · Laravel · Queue WorkersPrivate Data TierRDS · Redis · No Public RouteTraffic flows down; databases never receive inbound internet routes
Production VPC subnet tiers — public edge, private application layer, and isolated data layer

Step 4: Create and associate route tables

Route tables define where packets go. A public route table needs a 0.0.0.0/0 route pointing to the internet gateway. Private route tables send default outbound traffic to a NAT gateway sitting in a public subnet.

aws ec2 create-route-table \
  --vpc-id vpc-0abc123def456789 \
  --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=public-rt}]'

aws ec2 create-route \
  --route-table-id rtb-public001 \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id igw-0abc123

aws ec2 associate-route-table \
  --route-table-id rtb-public001 \
  --subnet-id subnet-public-az-a

Each subnet associates with exactly one route table. If you skip association, AWS uses the main route table, which often lacks the routes you expect. That mistake causes instances to launch without internet access or with too much exposure.

How do route tables, internet gateways, and NAT gateways work together?

Understanding traffic direction prevents the most common VPC outages. Inbound user traffic hits a public-facing load balancer in a public subnet. The load balancer forwards to private EC2 instances. Those instances reach the internet for package updates and external APIs through a NAT gateway — not through a public IP on the instance itself.

NAT gateways bill per hour and per gigabyte processed. A single NAT in one AZ saves roughly Rs 4,000–6,000/month (~USD 30–45) compared to one per zone. The trade-off is an AZ failure takes outbound connectivity with it. For production, I run one NAT per AZ on client projects where uptime matters more than marginal savings. Our AWS cost optimization tactics guide covers NAT placement decisions in more detail.

VPC Traffic Flow PathsUsersInternetGatewayPublic ALBSubnetPrivate EC2SubnetInbound path (HTTPS)Private EC2SubnetNAT GatewayPublic SubnetInternetExternalAPIsOutbound path (updates, webhooks)Private instances have no public IPNAT provides outbound-only internet access
Inbound traffic via internet gateway and ALB; outbound private traffic via NAT gateway — core AWS VPC routing pattern

VPC endpoints as a NAT alternative

When private instances only call AWS services like S3 or SSM, add gateway or interface VPC endpoints. Traffic stays on the AWS network. You skip NAT data processing charges for those calls. Interface endpoints cost hourly per AZ but often pay back quickly on busy workloads.

Peering and hybrid connections

VPC peering links two VPCs at the network layer. Transit Gateway scales better when you connect many VPCs or on-premises networks through VPN or Direct Connect. If you run workloads across AWS and GCP, read our guide on AWS to GCP networking and VPN setup before choosing overlapping CIDR ranges.

What security controls should you apply to a new VPC?

A VPC without security groups is an empty fence. Security groups are stateful firewalls attached to ENIs — the network interfaces on EC2, RDS, and load balancers. Network ACLs add a stateless subnet-level filter. Use both, but rely on security groups for daily access control.

Security group baseline for a web application

  1. ALB security group — allow inbound 443 from 0.0.0.0/0; allow outbound to app security group on port 80 or 443.
  2. App security group — allow inbound from ALB security group only; allow outbound to RDS and Redis security groups.
  3. RDS security group — allow inbound 3306 or 5432 from app security group only; no outbound internet rules needed.
  4. Bastion security group — allow inbound SSH from your office IP or VPN CIDR; restrict tightly and disable when not needed.

Reference the official AWS security groups documentation for rule syntax and referencing by group ID rather than CIDR where possible.

Generate strong credentials for bastion and admin access with a secure password generator and store secrets in AWS Secrets Manager. Never hard-code keys in user-data scripts or CloudFormation templates committed to Git.

Network ACL hardening

Default NACLs allow all traffic. Custom NACLs can deny specific ports at the subnet boundary. They evaluate rules in order with lowest number first. Because NACLs are stateless, return traffic needs explicit allow rules. Most teams keep NACLs permissive and enforce policy through security groups unless compliance requires subnet-level blocks.

VPC Security Layer ComparisonSecurity GroupsStateful firewallAttached to ENIAllow rules onlyReturn traffic autoPrimary daily controlUse for app tiersNetwork ACLsStateless filterSubnet boundaryAllow and deny rulesOrdered evaluationCompliance extraUse when requiredDefence in depth: NACL at subnet edge, security group at instance
Security groups versus network ACLs — stateful instance-level control versus stateless subnet filtering in AWS VPC

Flow logs and monitoring

Enable VPC Flow Logs on the VPC or individual subnets. Send them to CloudWatch Logs or S3 for traffic analysis. Flow logs do not capture every packet detail, but they show accepted and rejected connections. That data helps debug security group misconfigurations faster than guessing from application error logs.

For booking platforms like Adventure Third Pole Trek, VPC isolation keeps payment callbacks and supplier CRM data off shared network paths. The same pattern applies to legal-tech portals where document uploads must stay on private subnets with encrypted storage.

How do you validate and automate VPC setup for production?

After creation, run a short validation checklist before launching production instances. Confirm DNS resolution works inside private subnets. Confirm private instances reach the internet through NAT for Composer and system updates. Confirm RDS is unreachable from the public internet with a port scan from outside the VPC.

Production validation checklist

  • Subnets span at least two Availability Zones for the tiers that need HA.
  • Private subnets have no route to the internet gateway — only to NAT or endpoints.
  • Security groups reference other groups, not 0.0.0.0/0, for internal traffic.
  • Default security group has no permissive inbound rules attached to production ENIs.
  • CloudFormation or Terraform state tracks every resource for repeatable rebuilds.
  • Backup and DR plans account for VPC region failure — see cloud backup and disaster recovery strategy.

Automate provisioning with scripts or IaC from day one. The Amazon VPC User Guide is the authoritative reference when CLI flags change between API versions. Pair manual learning with Boto3 automation once the network layout stabilizes.

When migrating from cPanel or shared hosting, VPC design is often the first unfamiliar step. Our article on migrating from shared hosting to the cloud covers the broader sequence — DNS cutover, SSL, and database migration — that assumes a working VPC underneath.

For multi-account or multi-cloud growth, read multi-cloud architecture: a practical guide before peering production VPCs across providers. Overlapping CIDR blocks discovered after launch force painful renumbering.

Validate JSON policies and config snippets with a JSON formatter before applying them in CI pipelines. Small syntax errors in CloudFormation templates can delete routes or open security groups during stack updates.

Teams without in-house cloud skills often pair VPC setup with domain registration and hosting services or broader web development support so DNS, SSL, and application deployment stay aligned with network design.

Key Takeaways

  • Plan your CIDR block and subnet layout before creating resources — renumbering a live VPC is painful and risky.
  • Use public subnets only for load balancers, NAT gateways, and bastion hosts; keep databases and app servers in private subnets.
  • Associate every subnet with an explicit route table — the main route table catches mistakes silently.
  • Security groups are your primary firewall; reference group IDs instead of open CIDR ranges for internal traffic.
  • Run one NAT gateway per AZ in production for fault tolerance; use VPC endpoints to cut NAT data charges for AWS API calls.
  • Automate VPC creation with CloudFormation or Terraform and enable flow logs before go-live.

People Also Ask

What is the difference between a public and private subnet in AWS?

A public subnet has a route table entry pointing 0.0.0.0/0 to an internet gateway, so resources with public IPs can receive inbound traffic from the internet. A private subnet lacks that direct route and typically sends outbound traffic through a NAT gateway instead.

How many IP addresses does a /16 VPC provide?

A /16 CIDR block provides 65,536 IPv4 addresses in theory. AWS reserves five addresses per subnet, and you lose additional space to AWS-managed services. In practice, a /16 supports large multi-tier applications with room for future subnets across many Availability Zones.

Do I need a NAT gateway if my instances are in private subnets?

Yes, if those instances must reach the internet for software updates, external APIs, or webhook delivery. Without a NAT gateway or VPC endpoints, private instances cannot initiate outbound connections beyond the VPC. Inbound user traffic still arrives through a load balancer in a public subnet.

Can I change the CIDR block of an existing VPC?

You can add secondary IPv4 CIDR blocks to an existing VPC, but you cannot shrink or replace the primary CIDR. If your initial range is too small or overlaps with a peer network, create a new VPC and migrate resources rather than patching around the limitation.

Build your AWS network with intent

Setting Up a VPC on AWS: Cloud Networking Fundamentals is not a one-time console exercise. It is the contract your applications inherit for routing, isolation, and exposure. Plan CIDR space with room to grow, split tiers across Availability Zones, route traffic deliberately through gateways, and enforce access at the security group layer. That foundation supports everything from a single Laravel API to a multi-service platform deployed with GitLab CI and Deployer on EC2.

If you want help designing a VPC for a production migration or a new product launch, contact us to discuss architecture, cost, and deployment. You can also explore related work on the portfolio page or read more on the blog about cloud infrastructure and application hosting.

Frequently Asked Questions

An AWS VPC is a logically isolated section of the AWS cloud where you launch resources with IP addresses you control.

Every EC2 instance, RDS database, Lambda function in a VPC, and internal load balancer lives inside one VPC. Unlike flat shared hosting, a VPC gives you routing tables, subnet boundaries, and firewall layers you define. On production Laravel deployments I maintain, the VPC separates web servers, application workers, and database layers before any security group rule is written. AWS creates a default VPC in each region for quick tests, but production workloads need deliberate network design so routing mistakes do not expose databases or break outbound updates.

Use a custom VPC for production workloads needing deliberate CIDR sizing, multi-AZ layout, compliance, and cost control—not AWS's predictable default ranges.

CIDR planning is hard to reverse later. Pick a range large enough for growth but small enough to avoid overlapping future VPN or peering connections. A /16 block gives 65,536 addresses for most single-application deployments; a /20 gives 4,096 for smaller staging. Avoid ranges that collide with office LAN, home lab, or peered clouds. Common safe choices include 10.0.0.0/16, 10.1.0.0/16, and 172.16.0.0/16. Reserve at least two Availability Zones, with one public and one private subnet per zone for high availability.

A practical /16 layout splits tiers across two Availability Zones. Public subnets like 10.0.1.0/24 and 10.0.2.0/24 hold the ALB, bastion, and NAT gateways. Private subnets 10.0.11.0/24 and 10.0.12.0/24 run EC2 app servers. Private subnets 10.0.21.0/24 and 10.0.22.0/24 hold RDS primary and standby. Leave unused /24 blocks for future ElastiCache or internal APIs. Public subnets get routes to an internet gateway; private subnets hold databases, cache nodes, and background workers with no auto-assigned public IPs at launch.

Create the VPC with your chosen CIDR block, then enable DNS hostnames and DNS resolution—Laravel apps, RDS endpoints, and internal health checks depend on this. Create public and private subnets in at least two Availability Zones. Attach an internet gateway to the VPC. Create route tables: public tables need a 0.0.0.0/0 route to the internet gateway; private tables send default outbound traffic to a NAT gateway in a public subnet. Associate every subnet with an explicit route table. For repeatable production setups, prefer AWS CloudFormation or Terraform over manual console clicks.

Each subnet associates with exactly one route table. If you skip association, AWS uses the main route table, which often lacks the routes you expect. That mistake causes instances to launch without internet access or with too much exposure. A public route table needs a 0.0.0.0/0 route pointing to the internet gateway. Private route tables send default outbound traffic to a NAT gateway sitting in a public subnet. I have seen production outages traced to a subnet left on the main table after a rushed console setup.

Inbound user traffic hits a public-facing load balancer in a public subnet via the internet gateway. The load balancer forwards to private EC2 instances. Those instances reach the internet for package updates and external APIs through a NAT gateway—not through a public IP on the instance itself. The internet gateway is a horizontally scaled AWS component you attach and reference in route tables; you do not manage its capacity. Private subnets should have no route to the internet gateway, only to NAT or VPC endpoints.

NAT gateways bill per hour and per gigabyte processed. One NAT in one AZ saves roughly Rs 4,000–6,000/month (~USD 30–45) versus one per zone.

A single NAT in one AZ saves roughly Rs 4,000–6,000/month (~USD 30–45) compared to one per zone, but an AZ failure takes outbound connectivity with it. For production, I run one NAT per AZ on client projects where uptime matters more than marginal savings. When private instances only call AWS services like S3 or SSM, add gateway or interface VPC endpoints so traffic stays on the AWS network and you skip NAT data processing charges for those calls.

Security groups are stateful firewalls attached to ENIs on EC2, RDS, and load balancers—use them for daily access control. Network ACLs add a stateless subnet-level filter; because they are stateless, return traffic needs explicit allow rules. Default NACLs allow all traffic. Most teams keep NACLs permissive and enforce policy through security groups unless compliance requires subnet-level blocks. A VPC without security groups is an empty fence; both layers matter, but security groups carry most production policy.

ALB security group: allow inbound 443 from 0.0.0.0/0; allow outbound to the app security group on port 80 or 443. App security group: allow inbound from the ALB security group only; allow outbound to RDS and Redis security groups. RDS security group: allow inbound 3306 or 5432 from the app security group only. Bastion security group: allow inbound SSH from your office IP or VPN CIDR, restrict tightly, and disable when not needed. Reference security groups by group ID rather than CIDR for internal traffic where possible.

Confirm DNS resolution works inside private subnets. Confirm private instances reach the internet through NAT for Composer and system updates. Confirm RDS is unreachable from the public internet with a port scan from outside the VPC. Check subnets span at least two Availability Zones for tiers needing HA. Verify private subnets have no route to the internet gateway. Ensure security groups reference other groups, not 0.0.0.0/0, for internal traffic, and the default security group has no permissive inbound rules on production ENIs. Track every resource in CloudFormation or Terraform state.

Enable VPC Flow Logs on the VPC or individual subnets and send them to CloudWatch Logs or S3 for traffic analysis. Flow logs do not capture every packet detail, but they show accepted and rejected connections. That data helps debug security group misconfigurations faster than guessing from application error logs. For booking platforms and legal-tech portals where payment callbacks and document uploads must stay on private subnets, flow logs add visibility when access rules drift after deploys or manual console changes.

Manual console clicks are fine for learning but become a liability when you rebuild staging every month. For repeatable production setups, prefer AWS CloudFormation or Terraform from day one. Pair manual learning with Boto3 automation once the network layout stabilizes. The Amazon VPC User Guide is the authoritative reference when CLI flags change. Small syntax errors in CloudFormation templates can delete routes or open security groups during stack updates, so validate JSON policies and config snippets before applying them in CI pipelines.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: