What you'll build
S3 Bucket
Your storage container — holds the files that make up your website
Static Hosting
S3's built-in feature that turns a bucket into a website
Bucket Policy
JSON rules that allow the world to read your files (read-only)
CloudFront
AWS's global CDN — serves your site fast from 400+ edge locations
Public URL
A shareable link to your portfolio you can put on your CV today
Portfolio Site
A simple HTML page showcasing you — your name, skills, and CV link
Architecture
Before you start — what you need
Get everything ready before touching AWS
Read this first
This is your first AWS lab. The goal is one thing: get your portfolio live on the internet today. We'll teach the concepts as you go. Don't worry about understanding every detail on the first pass — the live session and the second lab will reinforce everything.
By the end of this lab you'll have a public URL you can share. That alone puts you ahead of 90% of people who say they're "learning the cloud" but have never deployed anything.
-
1AWS Account with Free Tier active Sign up at aws.amazon.com/free if you haven't already. Card required, but everything in this lab is FREE under the 12-month free tier.
-
2Set your AWS Region Click the region name top-right of the AWS console. Choose one and stick with it for the whole bootcamp.
-
3A simple HTML file (or two) You don't need to be a designer. We'll provide a template HTML file you can use. If you already have a portfolio HTML/CSS, even better — bring that.
-
4A text editor VS Code, Sublime, Notepad++ — anything that lets you save .html files. Even Notepad works.
Day-one habit: go to Billing → Budgets → Create budget → Zero-spend budget. Set it for $1. AWS will email you the moment any service starts charging. This habit will save you from horror stories.
✅ Ready to go when:
Prepare your portfolio files
Create a simple HTML page about yourself
Why we start here
S3 doesn't care what's in the file — it'll host any HTML you give it. So our first job is to have a file ready. Use the template below if you don't have your own. You can always upgrade the design later.
-
1Create a new folder on your computer Call it
portfolio. This is where all your site files will live. -
2Open your text editor and create a file called
index.htmlThe filename matters — S3's static hosting looks for "index.html" by default. -
3Paste this template into index.html Replace the placeholders with your own info — name, role, skills, etc.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Your Name — Portfolio</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 720px;
margin: 60px auto; padding: 0 20px; color: #1a1a1a;
line-height: 1.6; }
h1 { font-size: 42px; margin-bottom: 4px; }
.role { color: #00B4D8; font-weight: 600; margin-bottom: 30px; }
.skill { background: #E8F4FD; color: #1565C0; padding: 4px 10px;
border-radius: 14px; font-size: 13px; margin-right: 6px; }
a { color: #1565C0; }
</style>
</head>
<body>
<h1>Your Name</h1>
<p class="role">Aspiring Cloud Engineer · Accra, Ghana</p>
<h2>About</h2>
<p>I'm learning AWS through the cloudwithshad bootcamp.
This site is hosted on S3 + CloudFront — built in week 1.</p>
<h2>Skills</h2>
<p>
<span class="skill">AWS</span>
<span class="skill">S3</span>
<span class="skill">EC2</span>
<span class="skill">Linux</span>
</p>
<h2>Contact</h2>
<p>Email: <a href="mailto:you@example.com">you@example.com</a><br>
LinkedIn: <a href="https://linkedin.com/in/your-handle">your-handle</a></p>
</body>
</html>
If you have time, also drop these into your portfolio folder:
- cv.pdf — your CV. We'll link to it.
- profile.jpg — a photo of you. Add
<img src="profile.jpg" width="160">in your HTML. - error.html — a "page not found" page (any HTML). S3 will use it for 404s.
✅ Check before moving on:
Create your S3 bucket
This is where your portfolio files will live
What is an S3 bucket?
A bucket is a container for files in S3. Think of it like a folder in the cloud — but with global reach. Each file (S3 calls them "objects") lives inside a bucket and gets its own URL. Bucket names are globally unique across all of AWS, so you'll need a creative name.
-
1Navigate to the S3 service
-
2Click "Create bucket" Big orange button, top-right of the buckets page.
By default, AWS blocks public access to S3 buckets — this is a GOOD default that prevents accidental data leaks. But for a public website, we need the world to read our files. We're explicitly opting in to public access. The acknowledgement box AWS shows is exactly the kind of safety prompt you want to see.
Important: only do this for buckets you intend to be public (websites, public images). NEVER for private data.
Bucket names are globally unique across all AWS accounts on Earth. "portfolio" is taken. "my-bucket" is taken. "cloudwithshad-portfolio" might be taken too. Adding your-name in there makes it almost certainly available — and easier to find later.
-
3Click "Create bucket" at the bottom If the name is taken, AWS will tell you. Try a different one.
✅ What you should see
- Green success banner: "Successfully created bucket"
- Your bucket name appears in the list of buckets
- Region matches what you selected
- Access shows "Objects can be public"
Memorise: S3 bucket names are globally unique. They're DNS-compatible (no spaces, no underscores, lowercase only). They're tied to a region but the name is global. Bucket names appear in URLs.
✅ Check before moving on:
Upload your files
Put your portfolio into the bucket
-
1Click on your bucket name This opens the bucket. You'll see an empty "Objects" tab.
-
2Click "Upload" Either click the orange Upload button OR drag your files into the page.
-
3Add your files Click "Add files" and select your
index.html(and any others — cv.pdf, profile.jpg, etc.). -
4Leave all permissions/properties as default We'll set the public access via a bucket policy in Step 5 — that's cleaner than per-file permissions.
-
5Click "Upload" at the bottom Wait for the green "Upload succeeded" message.
✅ What you should see
- "Upload succeeded" green banner
- Files listed in the Objects tab of your bucket
- Each file shows a size, type, and last modified date
✅ Check before moving on:
Enable static website hosting
Turn the bucket into a website
What "static hosting" actually does
By default, S3 is just a file store — each file has its own URL but they're not "linked together" as a website. Enabling static hosting tells S3: "this bucket is a website. When someone visits the bucket's root URL, serve them index.html. If a page is missing, show error.html."
-
1Go to Properties tab Inside your bucket, click the Properties tab at the top.
-
2Scroll all the way to the bottom Find "Static website hosting" at the very bottom of Properties.
-
3Click "Edit"
-
4Click "Save changes"
-
5Copy the website endpoint URL After saving, scroll back down to the same section. You'll see "Bucket website endpoint" — copy that URL. It looks like:
http://your-bucket.s3-website-us-east-1.amazonaws.com -
6Open the URL in a new tab You should see... wait for it...
You'll get a 403 Forbidden right now — that's NORMAL and EXPECTED. The bucket allows public access in theory, but we haven't told it WHICH files to share with the public yet. That's the next step.
✅ Check before moving on:
Make your files public with a bucket policy
The JSON that grants the world read-only access
What is a bucket policy?
A bucket policy is a JSON document that tells AWS who can do what to the files in your bucket. It's part of IAM (Identity and Access Management) — one of the 4 services we covered in the lecture today.
We'll write a policy that says: "Everyone in the world can READ files from this bucket — but they can't write, delete, or list anything." That's exactly what a public website needs.
-
1Go to Permissions tab Still inside your bucket, click the Permissions tab at the top.
-
2Find "Bucket policy" section Scroll down → click Edit next to "Bucket policy".
-
3Paste this policy — REPLACE the bucket name Change
YOUR-BUCKET-NAMEto your actual bucket name (twice in the policy).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
}
]
}
- Effect: Allow — we're granting permission
- Principal: * — to everyone (the asterisk means anonymous public)
- Action: s3:GetObject — only the action of reading a file. Not deleting, not listing, not modifying.
- Resource: arn:aws:s3:::your-bucket/* — applies to every file inside the bucket (the /* means "all objects")
This is the same JSON-with-Effect/Principal/Action/Resource pattern used everywhere in AWS IAM. Learn it once — use it forever.
-
4Click "Save changes" If you get a syntax error, you probably forgot to replace YOUR-BUCKET-NAME. AWS will tell you what's wrong.
-
5Refresh your S3 website URL in the browser Now visit your bucket website endpoint again — the one from Step 4.
✅ What you should see
- Your portfolio page is LIVE on the public internet 🎉
- Your name, role, skills — all rendered as a real website
- The URL bar shows your S3 bucket website endpoint
Bucket policies vs ACLs vs IAM policies — all three control S3 access. Bucket policies are the modern, recommended approach for bucket-wide rules. Memorise: Effect, Principal, Action, Resource.
✅ Check before moving on:
Add CloudFront CDN for global speed
Serve your site from 400+ edge locations worldwide
Why we add CloudFront
Right now your site lives in ONE region (e.g. Virginia). A visitor from Tokyo has to fetch every file from Virginia — slow. CloudFront is AWS's Content Delivery Network (CDN): it caches your site at 400+ edge locations globally, so visitors get served from the closest one.
Bonus: CloudFront also gives you HTTPS for free, hides your S3 URL from visitors, and makes the site faster everywhere — including West Africa.
-
1Navigate to CloudFront
-
2Click "Create distribution"
You'll see an option for OAC (Origin Access Control). That's the more secure pattern — it makes CloudFront the ONLY way to access your bucket, and re-locks the bucket to private. We're using the simpler "Public" path for this lab — we'll cover OAC in Week 3.
Without it, visiting your-distribution.cloudfront.net/ (with no file specified) will return an error. Setting it to "index.html" makes CloudFront serve your homepage when someone hits the root URL — exactly like a normal website.
-
3Click "Create distribution" CloudFront takes 5–10 minutes to deploy globally. Status will show "Deploying" then change to "Enabled".
-
4Copy your CloudFront domain Once status = Enabled, copy the Distribution domain name — looks like
d1234abc.cloudfront.net -
5Open it in a NEW browser tab (not refreshed S3 tab) You should see your portfolio — but now served via HTTPS, from a CloudFront edge location near you.
✅ What you should see
- URL starts with https:// (not http)
- The CloudFront domain in the address bar (d-something.cloudfront.net)
- Your portfolio loads — possibly faster than the S3 URL
- Browser shows a lock icon (HTTPS = secure)
✅ Check before moving on:
Test, share, and update
Make sure it really works — and learn how to push updates
-
1Test on your phone Open your CloudFront URL on your phone (not on your laptop's WiFi network — use mobile data to really test). It should load and look correct.
-
2Share it with a friend Send the link to a friend on a different continent if you can. Ask them: "is it fast?" — that's CloudFront working.
-
3Update your portfolio (the workflow) Edit your local index.html → upload the new version to S3 (replaces the old) → wait ~1 minute → refresh CloudFront. Your changes appear.
If you update index.html and the new version doesn't show up after refresh, CloudFront might still be serving the old cached copy. To force a refresh:
- Quick fix: open in incognito mode (bypasses your local cache)
- Proper fix: CloudFront → Distribution → Invalidations tab → Create invalidation → path
/*(this clears the CDN cache)
You've now used 3 of the most important AWS services: S3 (storage), IAM via bucket policies (permissions), and CloudFront (global delivery). This same architecture pattern hosts millions of real-world websites — yours is technically the same setup as the marketing pages of major SaaS companies. That's not nothing.
✅ Final check:
Most students keep the site running — it's basically free under free tier and looks great on a CV. But if you want to delete everything, follow these steps in order.
CloudFront takes 5–15 minutes to disable before it can be deleted.
You can't delete a bucket that contains files.
S3 charges ~$0.023 per GB stored per month. Your portfolio is probably under 5 MB = effectively $0. CloudFront's free tier covers up to 1 TB/month outbound. For a portfolio site with normal traffic, this is permanently free. Keep it. Show it off.
What's next — Lab 2
Launch EC2
Spin up a real Linux server you can SSH into from your laptop
SSH Access
Connect to your server with a key pair — like a real engineer
Deploy a Web App
Install Nginx, host a dynamic page on YOUR server