DEV Community

Cover image for i touched AWS and stuff didn't break (mostly)
Ansh Dhanani
Ansh Dhanani

Posted on

i touched AWS and stuff didn't break (mostly)

so. i finally sat down and actually did AWS. not just watched tutorials, not just read docs actually clicked buttons, broke things, fixed them, and now i have opinions.

this is a writeup of everything i learned practically in this last 1 week, in the order i learned it, with zero fluff. if you're someone who learns by doing and wants a no-nonsense walkthrough of core AWS concepts you're in the right place.

let's go.


spinning up my first EC2 instance

EC2 is basically "rent a computer from Amazon and it runs 24/7 somewhere in a data center." that's the whole thing. everything else is just configuration.

i launched a t3.micro in ap-south-1 (Mumbai) free tier, which is perfect for learning. named it my web server because i'm creative like that.

what actually matters when launching: the AMI (think: OS), the instance type (think: hardware specs), and your key pair (SSH access). everything else can be changed later. don't overthink it.

once it's running, you get a public IPv4. EC2 Instance Connect lets you SSH directly from the browser which is actually very clean for beginners. no terminal setup needed.

one thing that tripped me up the instance showed "Running" but that doesn't mean your application is running. the VM is up, your code is not. different things.


deploying a "website" (lol)

my first deployed website on AWS was literally this:

Hi, i am Ansh. and this is my first AWS based self deployed website. WOHOOOO!!! let's gooo!!!
Enter fullscreen mode Exit fullscreen mode

one line of HTML. serving it with nginx. accessible on port 80 over HTTP. it's terrible and i loved it.

hitting that raw IP in the browser and seeing that text load that was a real moment. first cloud-deployed thing i've ever built. it's plain text and i don't care, it counts.

the actual commands to get nginx running:

# update, install, start
sudo apt-get update -y
sudo apt-get install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

# drop your HTML here
sudo nano /var/www/html/index.html
Enter fullscreen mode Exit fullscreen mode

a live server

that's literally it. the web server is now live. the hard part was not the code it was getting the networking right, which brings us to...


security groups - what even is a port?

security groups are basically firewall rules for your EC2 instance. when i first tried hitting my instance's IP in the browser, nothing loaded. timeout. because i hadn't opened port 80 (HTTP).

i set up a security group called ssh-http-web-secgrp with two inbound rules:

1. SSH on port 22 so i can connect to the instance via terminal. source: 0.0.0.0/0 (anywhere) for learning, should be your IP in prod.

2. HTTP on port 80 so the world can access the web server. source: the load balancer's security group, not the open internet. that is how security is built. we only allow what is needed, in this case the security group of the load balancer which is named LB-SG.

actually important thing: security groups are stateful. if you allow inbound on port 80, the response traffic goes out automatically. you don't need a matching outbound rule. this confused me for a bit.

security groups incoming ports


launch templates + auto scaling groups (aka AWS spawning servers for me automatically)

this was the point where AWS stopped feeling like "just a Linux VM in the cloud" and started feeling like actual cloud engineering.

after setting up the load balancer, i wanted the infrastructure to react automatically when traffic increased. not manually launching EC2 instances every time the CPU cried for help.

so i created a Launch Template and connected it to an Auto Scaling Group (ASG).

the mental model finally clicked:

  • Launch Template = blueprint for creating EC2 instances
  • Auto Scaling Group = service that decides when to create or terminate them

the template stored everything:

  • Ubuntu AMI
  • t3.micro
  • security groups
  • key pair
  • nginx setup
  • networking config

basically a reusable recipe for servers.

instead of manually configuring instances forever, AWS can now just clone new ones automatically whenever needed.

my ASG config looked like this:

minimum instances: 1
desired instances: 1
maximum instances: 3
Enter fullscreen mode Exit fullscreen mode

which basically means:

  • always keep at least 1 server alive
  • normally run 1
  • but if traffic spikes, scale up to 3

and honestly, this is where cloud finally became interesting.


the architecture looked like this

internet
    ↓
Application Load Balancer
    ↓
Auto Scaling Group
   ↙          ↘
web-1        web-2
ap-south-1c ap-south-1a
Enter fullscreen mode Exit fullscreen mode

traffic comes into the ALB.

the ALB distributes requests across healthy EC2 instances.

CloudWatch monitors metrics like CPU usage.

if usage crosses a threshold, the ASG launches another instance automatically using the Launch Template.

very simple idea conceptually. insanely powerful in practice.


making AWS panic on purpose

then came the fun part.

i SSH'd into web-1 and intentionally tortured the CPU using the stress tool:

sudo apt-get install stress -y

stress --cpu 2 --timeout 600 &
stress --cpu 1 --timeout 600 &
stress --cpu 2 --timeout 60
Enter fullscreen mode Exit fullscreen mode

my scaling policy was configured around:

if CPU > 40%
→ launch another instance
Enter fullscreen mode Exit fullscreen mode

and then i just watched the dashboards.


watching auto scaling happen live

Load Balancer Monitoring

the load balancer monitoring started showing request spikes and activity increasing as the stress test ran.


EC2 Monitoring Graphs

CPU utilization climbed hard from basically idle.

network traffic increased too because requests were flowing through the ALB into the instances.

and then suddenly another EC2 instance appeared automatically.

i did not press "Launch Instance."

AWS launched it for me.


Stress Testing Terminal

this tiny terminal command triggered the whole scaling workflow:

high CPU load
    ↓
CloudWatch detects >40%
    ↓
Auto Scaling policy triggers
    ↓
Launch Template used
    ↓
new EC2 instance created
    ↓
Load Balancer adds healthy target
Enter fullscreen mode Exit fullscreen mode

that feedback loop is the foundation of scalable cloud systems.


the thing that changed how i think about servers

before this, my brain thought scaling meant:

"buy a bigger machine"

AWS teaches the opposite mindset.

instead of:

1 huge server
Enter fullscreen mode Exit fullscreen mode

you do:

many smaller servers
Enter fullscreen mode Exit fullscreen mode

horizontal scaling.

because smaller machines are replaceable.

if one dies? the ASG launches another.

if traffic spikes? launch more.

if traffic drops? terminate extras and save money.

that's why load balancers matter so much. users don't connect directly to servers anymore. they connect to the ALB, and the ALB decides where traffic goes.

instances become disposable infrastructure.

and that is a VERY different way of thinking compared to traditional hosting.


honestly the coolest part

the craziest thing is this entire setup was built using just:

  • EC2
  • CloudWatch
  • Load Balancer
  • Launch Template
  • Auto Scaling Group

no Kubernetes.

no Docker orchestration.

no Terraform.

just core AWS services working together.

and suddenly the infrastructure can:

  • scale itself
  • distribute traffic
  • recover automatically
  • survive instance failures

that's the first moment AWS actually felt like "the cloud" to me instead of just "Ubuntu running somewhere else."


IAM - learning what "not authorized" feels like

IAM (Identity and Access Management) is AWS's permission system. users, roles, policies. this one bit me directly.

i was poking around with a second AWS account and tried to view EC2 instances in eu-north-1 (Stockholm). got this:

You are not authorized to perform this operation.
User: arn:aws:iam::590128028909:user/Ansh-2 is not authorized
to perform: ec2:DescribeInstances because no identity-based
policy allows the ec2:DescribeInstances action
Enter fullscreen mode Exit fullscreen mode

makes total sense in hindsight. the user had no IAM policies attached. by default in AWS you get nothing. zero permissions. you have to explicitly grant everything.

this is the opposite of how most beginners think about it. they expect "allow everything by default, block what's dangerous." AWS does "block everything by default, allow what you need." way more secure.

the IAM mental model:

  • root account = god mode. don't use it for daily stuff.
  • IAM user = a specific identity with attached policies.
  • policy = JSON document saying "this action on this resource is allowed/denied."
  • role = like a user but assumed temporarily (e.g., an EC2 instance acting as a user to access S3).

the ARN (Amazon Resource Name) in that error message is how AWS identifies every resource uniquely. arn:aws:iam::590128028909:user/Ansh-2 = account ID + service + resource.

you'll see ARNs everywhere.


S3 - storing stuff in the cloud like a normal person

S3 (Simple Storage Service) is object storage. not a file system, not a database just a bucket that holds objects (files). infinitely scalable, stupidly cheap, and the backbone of half the internet.

i created a bucket called first-s3-bucket-by-ansh in ap-south-1 and uploaded one image:

maykl-dzhekson-michael-jackson.jpg · 62.2 KB · Standard storage class
Enter fullscreen mode Exit fullscreen mode

(yes that's how it was spelled. yes i kept it.)

first attempt to access it via the public URL, got this:

<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
</Error>
Enter fullscreen mode Exit fullscreen mode

because S3 buckets are private by default. again, AWS defaults to locked down.

to make an object publicly accessible you need to:

  1. Disable "Block Public Access" at the bucket level.
  2. Add a bucket policy that allows s3:GetObject for Principal: "*" on the objects.
  3. or just hit "Make public" on the individual object. faster for learning, wrong for production.

after sorting that out, the image loaded. michael jackson silhouette on a black background, served from my S3 bucket and accessible from anywhere in the world.

the URL structure is:

https://[bucket-name].s3.[region].amazonaws.com/[object-key]
Enter fullscreen mode Exit fullscreen mode

mj background

S3 is everywhere: static website hosting, ML model weights, application logs, database backups, CDN origin... you'll use S3 in basically every AWS architecture. understand it early.


tldr / what i actually learned

not just "what buttons to click" the mental models that stuck:

  • AWS defaults to deny. no permissions, no access. you build up from zero.
  • Availability zones are not optional. run across at least two if anything needs to stay up.
  • Security groups are stateful firewalls. inbound rules are enough for most setups.
  • Load balancers + auto scaling = resilience. don't make your instance bigger, make more of them.
  • IAM is the foundation. understanding ARNs, policies, and roles unlocks everything else.
  • S3 is not just file storage. it's an architecture primitive.

what's next: RDS for a proper database, CloudFront for CDN, and Route 53 for a real domain instead of raw IP addresses.

also i need to terminate these instances before my free tier runs out.

- Ansh Dhanani

Top comments (0)