Home › Labs & Reference › S3 Static Website

🖥️ Lab · Host this website on Amazon S3

The full AWS CLI sequence that puts these pages on the internet — create the bucket, upload the files, enable static website hosting, open public access and apply a bucket policy.

AWS CLIAmazon S3 ap-south-1 (Mumbai)~20 minutes

Before you start

You need an AWS account, the AWS CLI installed, and credentials configured. The bucket name must be globally unique across all of AWS, so replace pushpjeetinitm with your own name throughout — for example yourname-aws-project.

aws --version          # confirm the CLI is installed
aws configure          # access key, secret key, region, output format
aws sts get-caller-identity    # confirm who you are authenticating as
The Region matters

The S3 website endpoint contains the Region. This lab uses ap-south-1 (Mumbai). AWS documents the endpoint format as http://bucket-name.s3-website.Region.amazonaws.com.

1 · Create the S3 bucket

Terminal
aws s3api create-bucket \
    --bucket pushpjeetinitm \
    --region ap-south-1 \
    --create-bucket-configuration LocationConstraint=ap-south-1
Why LocationConstraint?

Every Region except us-east-1 requires it. If you omit it outside us-east-1 the call fails with IllegalLocationConstraintException.

2 · Upload the website

From the folder containing index.html, css/ and js/:

Terminal
# upload one file
aws s3 cp index.html s3://pushpjeetinitm/

# or upload the whole site, including the css and js folders
aws s3 sync . s3://pushpjeetinitm/ --exclude ".*" --exclude "*/.*"

# check what is there
aws s3 ls s3://pushpjeetinitm/ --recursive --human-readable
sync is the command you will actually use

sync uploads only what has changed, so redeploying after an edit takes a second. It is also what a CI/CD pipeline would run.

3 · Enable static website hosting

Terminal
aws s3 website s3://pushpjeetinitm/ \
    --index-document index.html \
    --error-document index.html

The index document is served when someone requests the bucket root. Setting the error document as well means a mistyped URL lands on your home page rather than an XML error.

4 · Allow public access

This is the important part. By default S3 blocks all public access — a deliberately safe default. For the traditional website endpoint the content must be publicly readable.

Terminal
aws s3api put-public-access-block \
    --bucket pushpjeetinitm \
    --public-access-block-configuration \
    BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
Understand what you are doing here

You are deliberately making every object in this bucket readable by anyone on the internet. That is correct for a public website and wrong for anything else. Never put anything private in this bucket. AWS explicitly warns that disabling Block Public Access exposes the bucket's contents publicly — and a misconfigured bucket is one of the most common real-world data breaches.

5 · Add a bucket policy

Create a file called bucket-policy.json:

bucket-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::pushpjeetinitm/*"
        }
    ]
}

Then apply it:

Terminal
aws s3api put-bucket-policy \
    --bucket pushpjeetinitm \
    --policy file://bucket-policy.json
Read the policy line by line — this is Module 5 in practice
FieldValueMeaning
EffectAllowGrant, rather than deny
Principal*Anyone, authenticated or not
Actions3:GetObjectRead an object — not list, not write, not delete
Resourcearn:aws:s3:::bucket/*Every object inside the bucket. Note the /* — without it the policy covers the bucket itself, not its contents, and nothing will load.

6 · Your website URL

With Region ap-south-1 and bucket pushpjeetinitm, the endpoint is:

http://pushpjeetinitm.s3-website.ap-south-1.amazonaws.com/

Open it in a browser. You should see the home page of this site.

Note the http, not https

The traditional S3 website endpoint is HTTP only. Browsers will show "Not secure". AWS recommends CloudFront when you need HTTPS — which is exactly what the next section covers.

The whole sequence in one block

Copy, change the bucket name, run
# 1. Create the bucket
aws s3api create-bucket \
    --bucket pushpjeetinitm \
    --region ap-south-1 \
    --create-bucket-configuration LocationConstraint=ap-south-1

# 2. Upload the website
aws s3 sync . s3://pushpjeetinitm/

# 3. Enable website hosting
aws s3 website s3://pushpjeetinitm/ --index-document index.html

# 4. Disable public access blocking
aws s3api put-public-access-block \
    --bucket pushpjeetinitm \
    --public-access-block-configuration \
    BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false

# 5. Apply the public-read bucket policy
aws s3api put-bucket-policy \
    --bucket pushpjeetinitm \
    --policy file://bucket-policy.json

# 6. Open it
echo http://pushpjeetinitm.s3-website.ap-south-1.amazonaws.com/index.html

Making it production-ready

This is the part worth talking about in your project presentation. The lab version works; it is not how you would run a real site.

Problem with the lab versionProduction answer
HTTP only — no encryption in transitCloudFront with a free AWS Certificate Manager certificate
The bucket must be publicCloudFront with Origin Access Control; the bucket goes back to private
Every request travels to the Mumbai RegionCloudFront caches at hundreds of edge locations worldwide
An ugly endpoint URLRoute 53 alias record at your own domain's apex
No protection from floods or bad botsAWS WAF on the distribution, plus Shield Standard for free
Manual uploadsA CI pipeline running aws s3 sync on every commit
Browser ─https─▶ Route 53 ─▶ CloudFront + ACM + WAF ─▶ S3 (PRIVATE, via OAC)

After this lab works, the natural next exercise is exactly that: S3 → CloudFront → HTTPS → Route 53, turning a basic S3 website into a production-style architecture.

Troubleshooting

SymptomLikely causeFix
403 ForbiddenBucket policy missing, or the Resource ARN has no /*Re-apply the policy with arn:aws:s3:::bucket/*
403 even with a policyBlock Public Access is still onRun the put-public-access-block command in step 4
404 Not FoundStatic website hosting not enabled, or the index document name is wrongRe-run aws s3 website with --index-document index.html
BucketAlreadyExistsBucket names are globally uniquePick a different name
IllegalLocationConstraintExceptionMissing --create-bucket-configuration outside us-east-1Add the LocationConstraint
CSS does not loadThe css/ folder was not uploadedUse aws s3 sync, not cp on one file
Old content still showsBrowser cacheHard refresh (Ctrl+Shift+R)
Clean-up when you are finished
aws s3 rm s3://pushpjeetinitm/ --recursive
aws s3api delete-bucket --bucket pushpjeetinitm --region ap-south-1