An Amazon Virtual Private Cloud is the network boundary in which many AWS resources run. Beginners often create an EC2 instance in the default VPC and make it publicly reachable without understanding the route table, gateway, subnet or security group that made the connection possible. This AWS VPC project builds those concepts deliberately by placing an Nginx web server in a public subnet and a MySQL database server in a private subnet.
The project demonstrates a simple two-tier architecture. Internet users can reach only the web tier. The database has no direct public route and accepts MySQL traffic only from the web server security group. The design is still a learning lab, but it creates a strong foundation for understanding cloud networking, application isolation and secure service-to-service communication.
What will you build?
The example plan uses the following network:
- VPC CIDR:
10.0.0.0/16 - Public subnet:
10.0.1.0/24 - Private subnet:
10.0.2.0/24 - Internet gateway attached to the VPC
- Public route table with
0.0.0.0/0routed to the internet gateway - Private route table without a direct internet-gateway route
- Ubuntu EC2 instance with Nginx in the public subnet
- Ubuntu EC2 instance with MySQL in the private subnet
- Separate security groups for the web tier and database tier
- Optional NAT gateway for controlled outbound IPv4 access from the private subnet
Choose CIDR ranges that do not overlap with networks you may later connect. The values above are easy to understand for a standalone lab, but real organizations plan address space across accounts, Regions, offices and connected networks.
Public and private subnets explained simply
A subnet becomes public or private mainly because of its routing. A public subnet has a route that sends internet-bound traffic to an internet gateway. A resource in that subnet also needs suitable addressing and security rules before it can communicate with the internet.
A private subnet does not have a direct route to the internet gateway. If an instance in the private subnet requires outbound IPv4 internet access for updates, it can route that traffic through a NAT gateway placed in a public subnet. The NAT design allows connections initiated from the private side while preventing unsolicited inbound internet connections through that path.
A NAT gateway is not automatically free and can create hourly and data-processing charges. For a lab, check current pricing and delete resources after use. Also consider VPC endpoints for supported AWS services when they meet the workload need and reduce unnecessary NAT traffic.
Step 1: Create the custom VPC
- Open the VPC console in the chosen AWS Region.
- Create a VPC with the IPv4 CIDR
10.0.0.0/16. - Enable DNS support and DNS hostnames when the workload requires them.
- Add useful tags such as project, environment and owner.
- Record the VPC ID before creating dependent resources.
A custom VPC makes the network decisions visible. Tags help identify resources during troubleshooting, cost review and cleanup. Use consistent names such as aws-learning-vpc, web-public-subnet and db-private-subnet.
Step 2: Create public and private subnets
Create the public subnet with 10.0.1.0/24 and the private subnet with 10.0.2.0/24. For the first lab, they may be in the same Availability Zone so that the flow is easy to observe. A production high-availability design normally uses resources across at least two Availability Zones and avoids a single point of failure.
Configure public IPv4 assignment deliberately. The public web instance needs an appropriate public address if it will be reached directly from the internet. The private database instance should not receive a public IP address.
Step 3: Attach an internet gateway
Create an internet gateway and attach it to the VPC. Creating the gateway alone does not make a subnet public. The public subnet’s route table must send the default IPv4 route to that gateway, and the instance still needs compatible addressing and security controls.
This separation is important in interviews. The route table decides where traffic goes, while the security group decides which traffic is permitted for associated resources. Both must be correct for connectivity to work.
Step 4: Configure route tables
Create a public route table, add 0.0.0.0/0 with the internet gateway as the target and explicitly associate it with the public subnet. Create a private route table and associate it with the private subnet. Do not add a direct default route from the private subnet to the internet gateway.
Every route table includes a local route that enables communication within the VPC CIDR. That local route allows the web server to reach the database using private addresses when security controls permit the connection.
Step 5: Create security groups
Web security group
Allow HTTP on port 80 from the intended audience. For a public demonstration, that may be all IPv4 addresses, but production applications often use an Application Load Balancer and accept web traffic only from the load balancer security group. Restrict SSH on port 22 to a trusted administrator IP if SSH is needed.
Database security group
Allow TCP port 3306 with the web security group as the source. Do not use 0.0.0.0/0 for MySQL. Referencing the web security group expresses the relationship between application tiers without depending on a changing public address.
Security groups are stateful. Response traffic for an allowed connection is automatically permitted. Network ACLs operate at the subnet level and are stateless, but the default network ACL is sufficient for this first lab unless the learning objective specifically includes custom subnet-level filtering.
Step 6: Launch the Nginx web instance
Launch an Ubuntu EC2 instance in the public subnet, attach the web security group and assign the required public addressing. Connect through the approved method, update package information, install Nginx and verify that the service is active.
Open the public address in a browser. If it does not load, troubleshoot from the outside inward: confirm instance state and addressing, security-group inbound rules, public route-table association, internet-gateway attachment, operating-system firewall and Nginx status.
Step 7: Launch the private MySQL instance
Launch a second Ubuntu EC2 instance in the private subnet without a public IP address. Attach the database security group. Because the server is private, choose a controlled management method. Options include Systems Manager Session Manager when its prerequisites are configured, or a tightly controlled path through an administrative host. Avoid turning the database into a public server simply to make setup easier.
Install MySQL through an approved path. If the private instance needs internet access for package installation, add a NAT gateway in the public subnet, allocate its required public address and point the private route table’s default IPv4 route to it. Delete the NAT gateway after a temporary lab if it is no longer required.
Step 8: Configure MySQL for private application access
Create a dedicated database and application user instead of using the database root account from the web server. Grant only the permissions the application requires. Store the password in an approved secrets solution rather than placing it directly in a public repository, user-data script or container image.
MySQL must listen on the appropriate private interface for a remote web server to connect. Change this carefully and verify that the security group still restricts port 3306 to the web tier. Restart the service after configuration changes and inspect logs if it fails.
Step 9: Test web-to-database connectivity
From the web instance, test name resolution or private IP reachability as appropriate, then attempt a MySQL connection using the dedicated application user. A successful connection proves that the local VPC route and security-group relationship work.
Do not use ping as the only test. ICMP may be blocked even when TCP port 3306 is correctly allowed. Test the protocol and port that the application actually needs. If the connection fails, check the database service, listening address, database user host permissions, database security group, subnet route tables and network ACLs.
Add NAT only when the private tier needs outbound access
A public NAT gateway is created in a public subnet and uses a public address. The private subnet route table points internet-bound IPv4 traffic to the NAT gateway. The NAT gateway’s public subnet must route to the internet gateway. This arrangement lets the private instance initiate outbound connections while not accepting unsolicited inbound internet connections through the NAT gateway.
For production resilience using zonal NAT gateways, organizations commonly design a NAT path per Availability Zone so one zone does not depend on a NAT gateway in another. AWS networking capabilities evolve, so review current AWS VPC documentation and pricing when designing a real production environment.
Improve the lab toward production architecture
The direct public EC2 design is easy to learn but has limitations. A production-oriented web architecture can place an Application Load Balancer in public subnets and application instances in private subnets across multiple Availability Zones. A managed database such as Amazon RDS can replace a self-managed MySQL instance when its operational model suits the application.
Add Auto Scaling, HTTPS certificates, DNS, backups, monitoring, patch management, secrets management and infrastructure as code. Apply least privilege to IAM roles, encrypt data where required and document recovery objectives. Each improvement should address a specific risk or operating requirement.
Monitor the two-tier environment
Collect EC2 metrics and logs, create alarms for conditions that need action and send notifications to the responsible team. Use the AWS EC2 monitoring project with CloudWatch, SNS and Lambda to add server-health visibility. If the application is delivered frequently, the AWS CI/CD pipeline project with GitHub, Jenkins, Docker and EC2 shows how to automate tested deployments.
Common VPC mistakes
- Internet gateway created but no connectivity: confirm attachment, route-table association, public address and security rules.
- Database receives a public IP: stop and correct the launch settings; the database tier should remain private for this architecture.
- MySQL open to the world: replace the broad rule with a source referencing the web security group.
- Private server cannot update packages: add a controlled outbound path such as NAT when required, or use supported private service access.
- NAT gateway placed in a private subnet: a public NAT gateway needs the correct public-subnet route to the internet gateway.
- Wrong route table associated: inspect explicit subnet associations instead of relying on names.
- Overlapping CIDR ranges: plan address space before connecting VPCs or on-premises networks.
- Unexpected cost: review NAT, public IPv4, data transfer and running compute charges, then clean up the lab.
Project cleanup checklist
Terminate lab EC2 instances when they are no longer needed. Delete unused volumes and snapshots only after confirming that no data must be retained. Remove NAT gateways and release associated public addresses. Delete unused security groups, route tables, subnets and the VPC in dependency order. Review billing and Cost Explorer after cleanup because some charges may appear after a delay.
How to explain the VPC project in an interview
Begin with the security requirement: the web application needed internet access, but the database should not be publicly reachable. Describe the VPC CIDR, the two subnet CIDRs, the internet gateway, route-table associations and separate security groups. Explain that the database rule accepts port 3306 only from the web security group.
Then explain outbound access from the private subnet and why a NAT gateway may be used. Mention cost and high-availability tradeoffs. Finish with your connectivity tests, one problem you solved and how you would improve the design with a load balancer, multiple Availability Zones, private application servers, RDS, monitoring and infrastructure as code.
Learning path for AWS beginners
This lab is useful for cloud support learners, network students, Linux administrators, developers and DevOps beginners. It turns abstract terms such as subnet, route table and gateway into a visible traffic path. Learners who want trainer-led practice with EC2, S3, IAM, VPC, RDS, Lambda, CloudWatch and cloud projects can explore AWS training in Vizag at Softenant Technologies.
Frequently asked questions
Is a subnet public because auto-assign public IP is enabled?
No. Public addressing helps an instance communicate, but the subnet’s route table must include a route to an internet gateway for it to be a public subnet in this design.
Can an internet gateway be attached directly to the private subnet?
An internet gateway attaches to the VPC, not to an individual subnet. Route-table configuration determines which subnet sends internet-bound traffic to it.
Why reference a security group instead of an IP address?
Security-group referencing represents the application-tier relationship and continues to work when instances are replaced within the permitted group. It also avoids opening the database port broadly.
Does a private subnet always require a NAT gateway?
No. Add outbound internet access only when the workload requires it. Some workloads can use VPC endpoints, internal repositories or other controlled paths. Choose the design based on service needs, security and cost.
Should MySQL run on EC2 or Amazon RDS?
Running MySQL on EC2 is useful for learning operating-system and database administration. RDS is a managed database service that can reduce several operational tasks. The correct choice depends on control, features, availability, cost and team responsibilities.
Conclusion
This AWS VPC project teaches the network logic behind a secure two-tier application. A public subnet provides the controlled entry point, a private subnet isolates the database, route tables determine traffic paths, and security groups enforce workload relationships. When you can build, test, troubleshoot and explain this architecture, you have moved beyond memorizing AWS service definitions toward practical cloud design.