AWS Builder Center

Host a Static Website on AWS with S3 and CloudFront

Beginner guide to hosting a static site on a private S3 bucket with CloudFront, HTTPS, and Origin Access Control in about 15 minutes.

## Why this setup?
Hosting a static site (HTML, CSS, JS) on S3 is cheap and simple. Adding CloudFront gives you HTTPS, global caching, and lets you keep the bucket **private**. In this guide, you'll build it from scratch in the AWS Console.
**You'll need:** an AWS account and a simple `index.html` file.
## Step 1: Create an S3 bucket
1. Open **S3** → **Create bucket**.
2. Choose a globally unique name, e.g. `my-static-site-demo-123`.
3. Keep **Block all public access** turned **on**.
4. Click **Create bucket**.
## Step 2: Upload your website
1. Open the bucket → **Upload**.
2. Add `index.html` (and any CSS, JS, or images).
3. Click **Upload**.
## Step 3: Create a CloudFront distribution
1. Open **CloudFront** → **Create distribution**.
2. For **Origin domain**, select your S3 bucket.
3. Under **Origin access**, choose **Origin access control (OAC)** and create a new one.
4. Set **Default root object** to `index.html`.
5. Under viewer protocol policy, choose **Redirect HTTP to HTTPS**.
6. Click **Create distribution**.
## Step 4: Allow CloudFront to read the bucket
After creating the distribution, CloudFront shows a banner with a **bucket policy**. Click **Copy policy**, then go to your bucket → **Permissions** → **Bucket policy**, paste it, and save.
This allows only your CloudFront distribution to read the files. The bucket stays private.
## Step 5: Test it
Wait a few minutes until the distribution status shows **Deployed**. Then open the **Distribution domain name** (like `d1234abcd.cloudfront.net`) in your browser. Your site should load over HTTPS.
## Updating your site
Upload the new files to S3. If you still see the old version, create a **cache invalidation** in CloudFront with the path `/*`.
## Cost
For small sites, costs are typically just a few cents per month, and both services have free tier allowances. Check the AWS pricing pages for current details.
## Troubleshooting
- **403 Access Denied:** check that the bucket policy is applied and the default root object is set.
- **Old content showing:** create an invalidation.
- **Blank page:** confirm the file is named `index.html` (case-sensitive).
## Conclusion
You now have a private S3 bucket served globally over HTTPS through CloudFront. Next, try adding a custom domain with Route 53 and a free certificate from AWS Certificate Manager.
Have questions or ran into issues? Drop a comment below!
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article