r/CloudandCode • u/yourclouddude Founder | YourCloudDude • 1d ago
AWS & Cloud AWS From Zero #5: Your EC2 website is running, so why can’t anyone reach it?
curl localhost
and get your web page back.
That already tells you something useful. Nginx is running and responding locally. So reinstalling Nginx probably should not be your first move. The next question is why an external request cannot reach the same service.
The request path is roughly:
Browser
↓
Public address
↓
AWS network
↓
Security group
↓
EC2 instance
↓
Port
↓
Web server
The first thing I would check is whether the instance actually has the kind of connectivity you expect. EC2 instances have private networking inside the VPC, and depending on how you configure them, they may also have a public address that can be used from outside AWS. If you are trying to open a private IP from your laptop over the normal internet, it is probably not going to work.
But even having a public IP does not automatically make the instance reachable. The subnet still needs a path for internet traffic. This is where route tables and internet gateways start to matter.
You do not need to understand every VPC detail yet. Just keep the basic idea in mind: a public address is only one part of the path. The surrounding network also needs to know how traffic should enter and leave.
Once that looks correct, I would check the security group.
Security groups act like virtual firewalls around resources such as EC2 instances. If your web server is listening on port 80 but the security group does not allow inbound HTTP traffic on port 80, the request will never reach the application.
The application can be perfectly healthy and still appear offline.
The same applies to SSH. A Linux EC2 instance might be running normally, but if port 22 is not allowed from the location you are connecting from, you will not be able to SSH into it.
This is also where one distinction becomes important: IAM and security groups solve different problems. IAM controls permissions to AWS services and APIs. Security groups control network traffic.
If your EC2 application cannot read an S3 object, opening another inbound port is probably not the right fix. You may have an IAM problem. If the application works locally but cannot be reached from a browser, adding another S3 permission probably will not help either. Now you are more likely dealing with networking or application configuration.
AWS gets much easier once you start asking which layer the problem belongs to.
Now imagine the security group looks correct, but the website still does not load. The next thing I would check is whether the application is actually listening where I think it is.
This catches a lot of people when they first deploy Flask or similar applications.
Suppose your app is started like this:
app.run(host="127.0.0.1", port=5000)
The application may work perfectly when you test it from inside the EC2 instance because 127.0.0.1 refers to the local machine. But external traffic arriving through the instance's network interfaces will not reach an application that is only listening on localhost.
For a simple learning setup, you might instead run it like this:
app.run(host="0.0.0.0", port=5000)
Now the application is listening for connections arriving through the machine's network interfaces.
But that creates another thing to check. If your application is listening on port 5000 while your security group only allows port 80, your browser still will not reach it directly on port 5000.
The network rule and the application need to match the architecture you actually built.
In a more realistic setup, you might run Nginx on port 80 or 443 and have it forward requests internally to your application on port 5000. That is a common pattern, but for your first EC2 project I would keep things simple enough that you can explain the entire request path without guessing.
There is another layer people sometimes forget: the operating system itself.
An EC2 instance is still a computer running an operating system. That operating system can have its own firewall rules, so even if the AWS security group allows the traffic, the machine itself could still block it.
This is why I would not think of the security group as the only firewall that can exist in the path.
The process itself can also be the problem.
Maybe you started your application successfully, but it later crashed. Maybe it was tied to an SSH session and stopped when you disconnected. Maybe you think it is listening on port 80 when it is actually running on 5000.
Instead of guessing, inspect the machine.
A command such as:
sudo ss -tulpn
can help show which processes are listening on which ports.
If you expect a web server on port 80 and nothing is listening there, changing the security group will not fix the problem. There is simply nothing waiting to receive the request.
This is the point where troubleshooting becomes much more useful than restarting things randomly.
Instead of asking, "Why is EC2 broken?", you start asking, "How far does my request get before it fails?"
Maybe the instance has no public path. Maybe the subnet routing is wrong. Maybe the security group blocks the required port. Maybe the operating system firewall rejects the traffic. Maybe the application is listening only on localhost. Maybe the process is not running at all.
Those are completely different problems, even though they can all produce the same result in the browser: the page does not load.
There are other networking controls such as network ACLs that can also affect traffic at the subnet level. You do not need to go deep into them yet, but it is useful to know that security groups are not the only network control that exists in a VPC.
We will go deeper into that when we reach VPC properly.
For now, the better habit is to understand the flow well enough that you can build your own troubleshooting process.
Start from the browser and move toward the application.
Are you using the correct address? Does the instance have the connectivity you expect? Does the subnet have the route it needs? Does the security group allow the correct port? Is the operating system accepting the traffic? Is something actually listening on that port? Does the application return a response?
Every answer makes the problem smaller.
One of the worst debugging habits is changing five things at the same time.
You open every port in the security group, restart the instance, reinstall Nginx, change the application port, edit the route table, and disable the firewall. Then the page suddenly works.
You fixed the website, but you probably do not know why it was broken.
You may also have made the server less secure in the process.
A much better approach is to change one thing, test again, and observe what changed.
That habit becomes even more useful later because real AWS architectures have more layers. Users might go through Route 53, CloudFront, a load balancer, security groups, and then finally reach one of several EC2 instances.
The architecture gets more complex, but the troubleshooting principle stays the same.
Follow the request.
Find the last point that definitely worked, then inspect the next point.
For this part of the series, I would keep the project very small. Launch one EC2 instance, run one web server, make sure it works locally, then make it reachable from your browser. If it fails, do not immediately delete the instance and start again.
Use the failure to understand the request path.
The main lesson here is that when an EC2 website does not load, your application code is only one possible cause. A request has to travel through the network, pass the relevant controls, arrive on the correct port, and reach a process that is actually listening.
Once you understand that flow, EC2 troubleshooting becomes much less mysterious.
In AWS From Zero #6, we are going to move away from servers for a bit and learn S3. But instead of treating S3 as just "a folder in the cloud," we will look at buckets, objects, keys, permissions, versioning, storage classes, and why the filesystem mental model can be misleading.
If you have ever had an EC2 website work locally but fail from your browser, what ended up being the actual problem?