Build a Simple Static Website with S3
Hands-on lab: create an S3 bucket, upload an index.html, enable static website hosting, and make it publicly readable.
All services used in this lesson are covered by the AWS Free Tier.
AWS Services Used
What you are building
Amazon S3 can host a static website from a general purpose bucket. When you enable static website hosting, S3 gives you a Region-specific website endpoint, and you must specify at least an index document.
For a public S3 website, you must make the bucket publicly readable by disabling the relevant Block Public Access setting for the bucket and adding a bucket policy that grants public read access. By default, new buckets and objects do not allow public access.
Before you start
Warning
This lesson is a learning lab. S3 website endpoints support only publicly readable content and do not support HTTPS. AWS recommends CloudFront or Amplify for secure HTTPS hosting in production.
S3 now defaults to Bucket owner enforced object ownership, which disables ACLs. For a basic static website, the simpler path is to keep ACLs disabled and use a bucket policy for public reads.
What you will build
- One S3 bucket
- One
index.htmlfile - Optionally one
error.htmlfile - A public-read bucket policy
- One S3 website endpoint you can open in your browser
Part 1: Create the bucket
Create a general purpose bucket in the Region you want. The Region matters because it determines the S3 website endpoint for the bucket.
A good naming pattern for a learning bucket is something unique like:
yourname-aws-learning-site-12345
Bucket names must be globally unique, so if your first name is taken, add a random suffix.
Part 2: Upload your files
Create a file named index.html with something simple like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My First AWS Site</title>
</head>
<body>
<h1>Hello from S3</h1>
<p>This is my first static website on AWS.</p>
</body>
</html>
Optionally create an error.html file too:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Error</title>
</head>
<body>
<h1>Page not found</h1>
<p>Please go back to the home page.</p>
</body>
</html>
Upload these files to the bucket. In S3, uploaded files become objects.
Part 3: Enable static website hosting
Open the bucket's Properties tab, find Static website hosting, choose Edit, and enable Use this bucket to host a website. Then set:
- Index document:
index.html - Error document:
error.html(optional)
The index document name is case-sensitive and required for website hosting. After saving, S3 shows you the website endpoint at the bottom of the static website hosting section.
Part 4: Make the site publicly readable
This is the step most often missed.
4A) Change bucket public access setting
Go to the Permissions tab and edit Block public access (bucket settings) so the bucket can accept a public-read bucket policy. Block Public Access settings override public policies and permissions, so you must edit this before your bucket policy will work.
4B) Add the bucket policy
Add a bucket policy like this, replacing YOUR_BUCKET_NAME:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForWebsite",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
}
]
}
This grants everyone s3:GetObject permission on all objects in the bucket.
Part 5: Open the website endpoint
Return to Properties and open the website endpoint. If everything is correct, your browser should load index.html.
Tip
If you get 403 Forbidden, the most likely causes are: Block Public Access is still preventing the policy, or the bucket policy does not correctly grant public s3:GetObject.
Important warning
Warning
This lab is good for learning, but it is not the secure production pattern. S3 website endpoints do not support HTTPS. Use CloudFront or Amplify for real public sites.
- S3 website endpoint alone = fine for learning
- CloudFront or Amplify in front = better for real public sites
Verify your work
| Step | Success condition |
|---|---|
| Create bucket | Bucket exists in your chosen Region |
| Upload files | index.html is in the bucket |
| Enable website hosting | Static website hosting is on |
| Set index document | index.html is configured |
| Adjust public access | Bucket can accept public-read policy |
| Add bucket policy | Public s3:GetObject access is granted |
| Test endpoint | Website loads in browser |
Micro-activity 1: Reflection
Think about it
After the lab, reflect: Which Region did you choose? What is your bucket name? What is your website endpoint? Which setting blocked public access before you changed it? Which permission made the site readable in the browser?
Micro-activity 2: Explain the tradeoff
Think about it
Why does this S3 website setup need public read access? Why is CloudFront or Amplify better for a real public site? Consider that S3 website endpoints serve only publicly readable content without HTTPS.
Summary
In this lab, you created a general purpose S3 bucket, uploaded a small website, enabled static website hosting, and made it publicly readable through a bucket policy.
The most important limitation: the S3 website endpoint is public-content-only and does not support HTTPS. That is why AWS recommends CloudFront or Amplify for secure production hosting.