VPC - An analogy about shared resources
Public subnets and Internet Gateway
Load balancing - one front door, many clerks
<aside> 🚧
This page is currently under construction. Please check back later.
</aside>
<aside> 🧱
Step 2 of 3 — building the week's architecture
In the previous section you built the public subnet in Availability Zone A with hyf-web in it. This section adds the second layer, in the same Availability Zone: a private subnet holding the application server hyf-app, the bastion host you will use to log in to it, and the NAT Gateway that lets it fetch updates without ever being reachable from the internet.
Still missing after this page: the database in a second Availability Zone, and the Security Groups that decide who may talk to whom. That is section 3.
</aside>
In ‣ we made a subnet public by attaching an Internet Gateway and pointing its route table at it. Now we'll build the mirror image: a subnet that cannot be reached from the internet at all, but whose resources can still reach out when they genuinely need to — to download OS updates, pull a Docker image, call an external API — via a NAT Gateway.
This is where the architecture starts to have a shape. Ask yourself why you would bother: your web server is already online and working. The answer is that a web server is the machine most likely to be attacked, because it is the one you deliberately exposed. Everything valuable behind it — your application logic, and later your data — should live somewhere an attacker cannot reach even after breaking into the web tier. "Somewhere they cannot reach" is exactly what a private subnet is.
<aside> 💭
We deliberately put this private subnet in the same Availability Zone as the public one (eu-central-1a). Two reasons: a NAT Gateway lives in one AZ and traffic crossing AZ boundaries is billed, and keeping AZ A self-contained makes the next section's cross-AZ hop (to the database in AZ B) obvious rather than accidental.
</aside>

Same process as before, in the same VPC, but this time we won't give it a route to the internet.
hyf-week4-vpc).hyf-week4-private-subnet-a.eu-central-1a. The -a suffix in the name is there to remind you which AZ it belongs to.10.0.2.0/24.<aside> 💭
You now have two subnets in the same district (AZ) of the same building (VPC): 10.0.1.0/24 facing the street and 10.0.2.0/24 with no door to the outside. Same building, same floor plan — the only thing that will make them behave differently is the route table.
</aside>

If you don't explicitly associate a route table with this subnet, it falls back to the VPC's main route table — and a fresh main route table only contains the local route (traffic to your VPC's own CIDR stays inside the VPC). There is no 0.0.0.0/0 entry pointing at the Internet Gateway, so nothing addressed to the outside world has anywhere to go.
<aside> 💭
That's the entire mechanism behind "private": not a flag you tick, just the absence of a route out. Combined with not assigning a public IP, the instance is unreachable from the internet and, for now, can't reach it either.
</aside>
This instance is the application tier: in the final architecture it is the machine that runs your API, receives requests forwarded by hyf-web, and later queries the database. It never talks to the internet directly.
hyf-app, but this time select the private subnet (hyf-week4-private-subnet-a) in Network settings.hyf-app-sg that allows inbound traffic only from within the VPC — for now, SSH (22) and your app's port (e.g. TCP 3000) from your VPC's CIDR 10.0.0.0/16, not from the whole internet.<aside> 💭
Allowing the whole VPC CIDR is a blunt instrument — it means any machine you ever put in this VPC can knock on this door. In section 3 we replace 10.0.0.0/16 with references to hyf-web-sg (for the API port) and hyf-bastion-sg (for SSH), so only the web server can call the app server and only the bastion can log in to it — whatever their IPs happen to be.
</aside>


Note its private IPv4 address once it's running — there is no public one to note this time.
With no public IP and no route to the internet, you can't ssh into this instance directly from your laptop. The machine is running, and from where you are sitting it may as well not exist.
A bastion (also called a "jump box") is a small EC2 instance that lives in the public subnet, reachable from the internet, whose only job is to be a stepping stone into your private instances. It is the single door into the private tier — which is exactly why it is the one machine you guard properly.
This is what we use for the rest of the week. Every hop stays visible: you can point at the route and the rule that made each one work, and the only new skill it needs is ssh.
t3.micro is plenty) in your public subnet from the previous section. Name it hyf-bastion.hyf-bastion-sg with exactly one inbound rule: SSH (22) from My IP — your own address, never 0.0.0.0/0.Then connect from your laptop, in two hops:
ssh -i key.pem ec2-user@<bastion-public-ip> # hop 1: into the bastion
ssh ec2-user@<app-private-ip> # hop 2: from the bastion, into hyf-app
Or in a single command — -J ("jump") tells SSH to tunnel through the bastion for you:
ssh -i key.pem -J ec2-user@<bastion-public-ip> ec2-user@<app-private-ip>
Use ubuntu@ instead of ec2-user@ if you launched Ubuntu AMIs. The second hop is allowed because hyf-app-sg currently accepts SSH from the whole VPC CIDR, and the bastion is inside it — in section 3 we replace that with a rule naming hyf-bastion-sg specifically.
<aside> 🔑
Prefer -J over copying key.pem onto the bastion. The bastion is the most exposed machine in your VPC; a private key sitting on it is a private key an attacker gets for free the moment they get in. With -J the key never leaves your laptop — the bastion only forwards an encrypted tunnel it cannot read.
</aside>
<aside> ⚠️
Be honest about what a bastion costs you: another machine to patch and monitor, and an SSH port open to the internet somewhere in your VPC. That is why rule 3 is narrowed to your own IP, and why you stop the instance when you are not using it. Home IP addresses change — if SSH suddenly hangs one morning, check that rule before you debug anything else.
</aside>
In production you will often meet AWS Systems Session Manager instead. It opens a shell on an instance from the console or CLI with no public IP, no bastion and no open SSH port at all: an agent on the instance calls outbound to the Systems Manager service, and you meet it there. It needs an IAM role on the instance and a network path to that service.
We stay with the bastion in this course, because the network path is the thing you are here to learn and the bastion keeps it in plain sight. Recognise the name — it is what replaces the bastion the day you stop wanting one.
Say this is an Ubuntu box and you want to run apt update && apt upgrade, or docker pull an image. Both need outbound internet access — which, right now, this instance simply doesn't have: no route out, and no public IP even if it did.
A NAT Gateway solves this. It's a managed, AWS-operated proxy that sits in a public subnet (it needs its own public IP, via an Elastic IP) and forwards outbound traffic from private-subnet resources to the Internet Gateway, translating source addresses so replies find their way back. Unlike an Internet Gateway, it's one-directional: private instances can start connections out through it, but nothing on the internet can use it to start a connection in.
hyf-week4-natgw.
hyf-week4-private-rt-a) associated with your VPC — don't reuse the public one, they need different destinations.0.0.0.0/0, target → your NAT Gateway.

Connect to hyf-app through the bastion (Step 2), then:
sudo apt update (or equivalent) — it should now succeed.curl https://example.com should also succeed.ssh directly to the private instance's IP — it should time out. Outbound works, inbound still doesn't, and the only way in remains the bastion.Public and private subnets are built from the exact same ingredients — a subnet, a route table, and something plugged into that route table — just pointed in different directions:
0.0.0.0/0 to an Internet Gateway. Resources with a public IP are reachable both ways.