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 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
aws s3api create-bucket \
--bucket pushpjeetinitm \
--region ap-south-1 \
--create-bucket-configuration LocationConstraint=ap-south-1
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/:
# 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 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
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.
aws s3api put-public-access-block \
--bucket pushpjeetinitm \
--public-access-block-configuration \
BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
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:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::pushpjeetinitm/*"
}
]
}
Then apply it:
aws s3api put-bucket-policy \
--bucket pushpjeetinitm \
--policy file://bucket-policy.json
| Field | Value | Meaning |
|---|---|---|
| Effect | Allow | Grant, rather than deny |
| Principal | * | Anyone, authenticated or not |
| Action | s3:GetObject | Read an object — not list, not write, not delete |
| Resource | arn: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:
Open it in a browser. You should see the home page of this site.
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
# 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 version | Production answer |
|---|---|
| HTTP only — no encryption in transit | CloudFront with a free AWS Certificate Manager certificate |
| The bucket must be public | CloudFront with Origin Access Control; the bucket goes back to private |
| Every request travels to the Mumbai Region | CloudFront caches at hundreds of edge locations worldwide |
| An ugly endpoint URL | Route 53 alias record at your own domain's apex |
| No protection from floods or bad bots | AWS WAF on the distribution, plus Shield Standard for free |
| Manual uploads | A CI pipeline running aws s3 sync on every commit |
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
| Symptom | Likely cause | Fix |
|---|---|---|
| 403 Forbidden | Bucket policy missing, or the Resource ARN has no /* | Re-apply the policy with arn:aws:s3:::bucket/* |
| 403 even with a policy | Block Public Access is still on | Run the put-public-access-block command in step 4 |
| 404 Not Found | Static website hosting not enabled, or the index document name is wrong | Re-run aws s3 website with --index-document index.html |
| BucketAlreadyExists | Bucket names are globally unique | Pick a different name |
| IllegalLocationConstraintException | Missing --create-bucket-configuration outside us-east-1 | Add the LocationConstraint |
| CSS does not load | The css/ folder was not uploaded | Use aws s3 sync, not cp on one file |
| Old content still shows | Browser cache | Hard refresh (Ctrl+Shift+R) |
aws s3 rm s3://pushpjeetinitm/ --recursive
aws s3api delete-bucket --bucket pushpjeetinitm --region ap-south-1