How to Host a Static Website on Amazon S3 (Step by Step)
To host a static website on Amazon S3, create a bucket, upload index.html (and error.html), turn on Static website hosting in the bucket's Properties, turn off Block Public Access for that bucket only, and add a bucket policy that allows s3:GetObject for everyone. The site is then live at the bucket website endpoint, for example http://BUCKET.s3-website.ap-south-1.amazonaws.com. The S3 website endpoint is HTTP only; for HTTPS and a custom domain, put CloudFront in front.
Come on, friends! We hosted a website on EC2 with Nginx – the server, updates, security group, all on our own head. Today, a different trick: a website without a server. If you have HTML, CSS and images, create a bucket on Amazon S3, put the files in, and the site is live. Today we put my small shayari site on S3. Pay attention: this is the only bucket we make public on purpose.
चला मित्रांनो! आपण EC2 वर Nginx ने वेबसाइट होस्ट केली – सर्व्हर, अपडेट्स, सिक्युरिटी ग्रुप, सगळं आपल्या डोक्यावर. आज एक वेगळा जुगाड: सर्व्हर शिवाय वेबसाइट. HTML, CSS आणि इमेजेस असतील तर Amazon S3 वर एक बकेट बनवा, फाइल्स टाका, आणि साइट लाइव्ह. आज आपण माझ्या शायरीची छोटी साइट S3 वर टाकूया. लक्ष द्या, हा एकच बकेट असा आहे जो आपण जाणून-बुजून पब्लिक करतो.
चलो दोस्तों! हमने EC2 पर Nginx से वेबसाइट होस्ट की – सर्वर, अपडेट्स, सिक्योरिटी ग्रुप, सब अपने सिर पर. आज एक अलग जुगाड़: बिना सर्वर के वेबसाइट. HTML, CSS और इमेजेस हों तो Amazon S3 पर एक बकेट बनाओ, फ़ाइलें डालो, और साइट लाइव. आज हम मेरी शायरी की छोटी साइट S3 पर डालेंगे. ध्यान दो, यही एक बकेट है जिसे हम जान-बूझकर पब्लिक करते हैं.
Quick answer
With the AWS CLI configured (the console steps are below):
BUCKET=tujanena-shayari-site-2026 # globally unique, lowercase
aws s3 mb s3://$BUCKET --region ap-south-1
aws s3 sync ./site s3://$BUCKET/ # index.html, error.html, css/, img/
aws s3 website s3://$BUCKET/ --index-document index.html --error-document error.html
aws s3api put-public-access-block --bucket $BUCKET --public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=false,RestrictPublicBuckets=false
aws s3api put-bucket-policy --bucket $BUCKET --policy file://policy.json # public read, Step 5
# open http://tujanena-shayari-site-2026.s3-website.ap-south-1.amazonaws.com
What do I need before hosting a site on S3?
- An AWS account and an IAM user (not root) — see How to Create an IAM User with MFA.
- A static site: HTML, CSS, JavaScript and images. S3 cannot run PHP, WordPress or a database; for that use EC2 (Host a Static Website on EC2 with Nginx is the server version of this guide).
- An
index.html, and ideally anerror.htmlfor wrong links.
How does an S3 website answer a browser?
The browser asks the S3 website endpoint for a page. Block Public Access is off for this bucket only, the bucket policy allows s3:GetObject, so S3 returns index.html over HTTP. No server to manage.
ब्राउझर S3 website endpoint कडे पेज मागतो. Block Public Access फक्त या बकेट साठी बंद आहे, bucket policy s3:GetObject ला परवानगी देते, म्हणून S3 HTTP वर index.html परत पाठवतो. सांभाळायला कोणताही सर्व्हर नाही.
ब्राउज़र S3 website endpoint से पेज माँगता है. Block Public Access सिर्फ़ इस बकेट के लिए बंद है, bucket policy s3:GetObject की इजाज़त देती है, इसलिए S3 HTTP पर index.html वापस भेजता है. सँभालने के लिए कोई सर्वर नहीं.
How do I host a static website on Amazon S3?
Step 1 — Prepare the files
For practice, make a tiny two-page site on your laptop:
mkdir site && cd site
cat > index.html <<'HTML'
<!DOCTYPE html>
<html lang="mr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Shayari</title></head>
<body style="font-family:sans-serif;text-align:center;padding-top:60px">
<h1>आजची शायरी</h1><p>Hosted on Amazon S3 – no server!</p>
</body></html>
HTML
echo '<h1>404 – page not found</h1><a href="/">Home</a>' > error.html
cd ..
Keep <meta charset="utf-8"> in every page so Marathi and Hindi text shows correctly.
Step 2 — Create the bucket
S3 → Create bucket → General purpose → a bucket name such as tujanena-shayari-site-2026. Bucket names are global across all AWS accounts, lowercase, 3–63 characters, no spaces or underscores. Choose your region (for example Asia Pacific (Mumbai) ap-south-1). Keep Object Ownership: ACLs disabled.
Step 3 — Allow public policies for this bucket only
In Block Public Access settings for this bucket, untick Block all public access and tick the acknowledgement. Then Create bucket. If the bucket already exists: Permissions → Block public access (bucket settings) → Edit.
Leave the account-level Block Public Access and all your other buckets untouched.
Ravindra Bagale's Tip
Many students accidentally upload the .git folder, .env or backup.zip into the website bucket too – and those become public as well! Upload with aws s3 sync ./site s3://bucket/ --exclude ".git/*" --exclude "*.env" --exclude "*.zip", and afterwards check once with aws s3 ls s3://bucket --recursive exactly what has become public. This bucket holds only the website, nothing else.
Ravindra Bagale's Tip – मराठी
वेबसाइट बकेट मध्ये खूप स्टुडंट्स चुकून .git फोल्डर, .env किंवा backup.zip पण अपलोड करतात – आणि ते पण पब्लिक होतात! अपलोड करायला aws s3 sync ./site s3://bucket/ --exclude ".git/*" --exclude "*.env" --exclude "*.zip" वापरा, आणि नंतर aws s3 ls s3://bucket --recursive ने एकदा नक्की बघा काय काय पब्लिक झालं आहे. या बकेट मध्ये फक्त वेबसाइट, दुसरं काहीही नाही.
Ravindra Bagale's Tip – हिंदी
वेबसाइट बकेट में बहुत स्टूडेंट्स ग़लती से .git फ़ोल्डर, .env या backup.zip भी अपलोड कर देते हैं – और वे भी पब्लिक हो जाते हैं! अपलोड के लिए aws s3 sync ./site s3://bucket/ --exclude ".git/*" --exclude "*.env" --exclude "*.zip" इस्तेमाल करो, और बाद में aws s3 ls s3://bucket --recursive से एक बार ज़रूर देखो क्या-क्या पब्लिक हुआ है. इस बकेट में सिर्फ़ वेबसाइट, और कुछ नहीं.
Step 4 — Upload the files
Open the bucket → Upload → Add files (index.html, error.html) and Add folder (css/, img/ if you have them) → Upload. index.html must sit at the root of the bucket, not inside a site/ folder.
Step 5 — Add the public read bucket policy
Permissions → Bucket policy → Edit, paste this (change the bucket name) and Save changes:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicReadWebsite",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::tujanena-shayari-site-2026/*"
}]
}
Only s3:GetObject — never s3:ListBucket or s3:PutObject for "Principal": "*". The /* at the end of Resource means "every object in the bucket".
Step 6 — Turn on static website hosting
Properties → scroll to Static website hosting → Edit → Enable → Host a static website → Index document index.html, Error document error.html → Save changes. The same section now shows the Bucket website endpoint:
http://tujanena-shayari-site-2026.s3-website.ap-south-1.amazonaws.com
Open it on your phone — your site is live, with no server to patch. 🎉 Try a wrong path such as /abc to see error.html.
Step 7 — Update the site later
aws s3 sync ./site s3://tujanena-shayari-site-2026/ --delete --exclude ".git/*"
--delete removes files from the bucket that you deleted locally. Browsers may cache old files for a short time; refresh with Ctrl+F5.
Ravindra Bagale's Tip
Pay attention: when you open a file in the bucket you see an object URL like https://bucket.s3.ap-south-1.amazonaws.com/index.html – that is not the website endpoint. The website endpoint contains the word s3-website, and it works only on http://. The browser adds https:// and students say the site doesn't work. Got it? If you need HTTPS, use CloudFront.
Ravindra Bagale's Tip – मराठी
लक्ष द्या: बकेट मध्ये फाइल उघडली तर https://bucket.s3.ap-south-1.amazonaws.com/index.html असा object URL दिसतो – हा website endpoint नाही. Website endpoint मध्ये s3-website शब्द असतो, आणि तो फक्त http:// वर चालतो. ब्राउझर https:// लावतो आणि स्टुडंट्स म्हणतात साइट चालत नाही. समजलं का? HTTPS पाहिजे तर CloudFront.
Ravindra Bagale's Tip – हिंदी
ध्यान दो: बकेट में फ़ाइल खोली तो https://bucket.s3.ap-south-1.amazonaws.com/index.html जैसा object URL दिखता है – यह website endpoint नहीं है. Website endpoint में s3-website शब्द होता है, और वह सिर्फ़ http:// पर चलता है. ब्राउज़र https:// लगा देता है और स्टूडेंट्स कहते हैं साइट नहीं चल रही. समझ आया? HTTPS चाहिए तो CloudFront.
Step 8 — HTTPS and your own domain (next step)
For a real site, create a CloudFront distribution with the bucket as origin and Origin Access Control (OAC), so only CloudFront can read the bucket and Block Public Access can stay on. Add a free certificate from AWS Certificate Manager (in us-east-1 for CloudFront) and point www.yourdomain.com to CloudFront with a CNAME record.
| Option | HTTPS | Bucket public? | Use for |
|---|---|---|---|
| S3 website endpoint (this guide) | No | Yes, read only | Learning, quick demos |
| CloudFront + OAC | Yes, custom domain | No | Real production static sites |
| Nginx on EC2 | Yes, with Certbot | Not applicable | When you also need server-side code |
How do I fix common S3 website errors?
Ghabru naka 😅 — these are the usual ones:
| Symptom | Likely cause | Fix |
|---|---|---|
| 403 Forbidden (Access Denied) | No bucket policy, Block Public Access still on, or Resource without /* |
Step 3 and Step 5; check the bucket name in the ARN |
Access denied when saving the policy |
Block Public Access still blocks public policies | Untick it for this bucket (Step 3), then save the policy again |
404 Not Found / NoSuchKey |
index.html not at the root, or wrong name (Index.html) |
Move it to the root; names are case-sensitive |
| Page downloads instead of opening | Wrong Content-Type from a manual upload |
Upload again with the console or aws s3 sync (sets text/html) |
Site does not open with https:// |
The website endpoint is HTTP only | Use http://, or CloudFront for HTTPS |
BucketAlreadyExists |
The name is taken in another account | Pick another unique name |
| Marathi text shows as strange symbols | Missing charset | Add <meta charset="utf-8"> to the page and upload again |
Learn it properly
This guide is the short path. The free Cyber Security course explains S3 security in depth, with labs:
Samajla ka? Got it? Bucket, upload, Block Public Access off for this bucket only, the GetObject policy, and static website hosting on – a website without a server is ready. Next, let's learn CloudFront for HTTPS and a domain.
समजलं का? बकेट, अपलोड, Block Public Access फक्त या बकेट साठी बंद, GetObject पॉलिसी, आणि static website hosting ऑन – सर्व्हर शिवाय वेबसाइट तयार. आता HTTPS आणि डोमेन साठी पुढे CloudFront शिकूया.
समझ आया? बकेट, अपलोड, Block Public Access सिर्फ़ इस बकेट के लिए बंद, GetObject पॉलिसी, और static website hosting ऑन – बिना सर्वर की वेबसाइट तैयार. अब HTTPS और डोमेन के लिए आगे CloudFront सीखेंगे.
Frequently asked questions
How do I host a static website on S3?
Create a bucket, upload index.html, enable Static website hosting in the bucket properties, turn off Block Public Access for that bucket, and add a bucket policy that allows s3:GetObject for everyone.
Why do I get 403 Forbidden on my S3 website?
The bucket policy is missing or wrong, Block Public Access is still on, or index.html is not at the bucket root. The policy Resource must end with /*.
Does S3 static website hosting support HTTPS?
No. The S3 website endpoint is HTTP only. For HTTPS and your own domain, put Amazon CloudFront in front of the bucket.
Can S3 host a PHP or WordPress website?
No. S3 serves only static files (HTML, CSS, JavaScript, images). For PHP, WordPress or a database, use EC2 or another compute service.
Is it safe to make an S3 bucket public?
Only for a bucket that holds nothing but the public website files, and only with s3:GetObject. Never allow s3:ListBucket or s3:PutObject to everyone, and keep Block Public Access on for every other bucket.
Should I host a static site on S3 or on EC2 with Nginx?
S3 needs no server, no patching and scales by itself, so it is ideal for simple sites. EC2 with Nginx teaches Linux and web server skills and can later run server-side code.