Project — Static Website Hosting on AWS using S3+CloudFront — Walkthrough
Hi everyone! We often study something and then get lost in how to test it out practically and this is one of the things that I struggled…
Project — Static Website Hosting on AWS using S3+CloudFront — Walkthrough
Hi everyone! We often study something and then get lost in how to test it out practically and this is one of the things that I struggled with as well. So I decided to make some projects and in turn, document it to help others like me to overcome this issue.
Roadmap:

The first project that I chose to make is hence a very simple but interesting one — Making a static resume website, hosted on AWS. We’ll be using S3 bucket so that we can store the website files, and will be using CloudFront to serve it fast globally. CloudFront also helps us with providing HTTPS, which is a website standard and also allows us to keep the website safe and be available for viewing easily, as the unsecured website can be prone to getting blocked by the employer, and that’s the last thing we want for our resume :)
Creating AWS Account:
I’m assuming everyone got an AWS account but if not, go ahead and make one and sign up for a free tier account. When we first sign up, we are logged in as the Root User, who is the ultimate master to the digital kingdom. It got unrestricted access to the entire account and have the power to delete anything and everything. On top of it, it also holds the access to billing and account closure and every other aspect of AWS. If its credentials are leaked, then the entire control of the cloud infrastructure will become vulnerable to malicious activities. So, the solution? Implementing security principle of least privilege, that’s the user/program/cloud service should only have the absolute minimum permissions necessary to complete its specific job. So, we create an IAM User and give administrator access to that user. Further we lock Root account with MFA and use it for absolute necessities.
Creating IAM User:
Head over to IAM and IAM Users and create a User.

In Step02, create a group with ‘administratorAccess’ and assign it to the user. We have a user now.

Optional: Not needed for this particular project. Head over to this user and under access key 1 — >create access key. Download this .csv for CLI use case.

AWS Console:
-
Log out of your root and log in back with your AWS IAM User.
-
Creating the files locally: On desktop create a file called index.html with an HTML code of your choice/of your resume.
-
Create an S3 Bucket: Go back to AWS Console and choose the region from the top right, like, us-east-1.
Head over to ‘create bucket’ and name it my-aws-resume-yourname. Uncheck ‘Block all public access’, check acknowledgement box and create.

- Upload the files: Click on the newly created bucket and ‘upload’. ‘Add’ the index.html file into the bucket.

- Enable Static Website Hosting: Open the Bucket, head over to the Properties tab and scroll all the way down to ‘Edit’ it in order to enable it. Under ‘Index Document’ and ‘Error Document’, type index.html and save the changes. Remember the ‘Bucket website endpoint’ shown at the bottom of the snapshot. This is the URL we will use to open our resume.

Note: Index Document is used to assign a default document where the S3 bucket’s URL will point to. So instead of typing example.com/index.html, we can simply type example.com to access the index.html file. Error Document is the page that we can assign when something goes wrong with the website. By default AWS shows an XML error, but we can upload another file named for example like error.html and point that for the Error Document.
- Open the bucket policy under ‘Permission’ and edit it to give permission to make the contents of the S3 public to the entire internet, because without it, only the authenticated account owner aka you, can open it, no one else without AWS login credentials or an IAM permissions can open it to see the content inside the S3.

What the permission mean — Anyone () can read (getObject) any file (/) from the bucket we made(arn:aws:s3:::my-aws-resume-pulkit). Copy the URL as we’ll need to connect the CloudFront with it.
Note: arn is just a unique identifier that AWS uses to identify any resource. Now we can open the ‘Bucket website endpoint’ that was mentioned under properties.
Note: Difference between Uncheck ‘Block all public access’ (in step3) and bucket policy (in step 6): While the ‘Block all Public Access’ is a main gate, the Bucket Policy is the individual doors of the rooms inside. When we uncheck ‘Block all public access’, it simply says, “Fine, I’m letting the main door open; you may use the room policies to handle the opening of various individual rooms.” So in short, unchecking the ‘Block all public access’ doesn't make anything public, bucket policy is where the actual grant permissions are specified. If we check the ‘block all public access’, then AWS completely ignores the bucket policies.
- Setting the CloudFront: Open CloudFront in a new window and ‘Create distribution’ Name your CloudFront and head over to step2 ‘Specify origin’ where you select Amazon S3 and Origin Path will be the URL, but we’ll remove http://

Note: We don’t use the ‘Browse S3’ option because it will open the REST endpoint which bypasses the static website hosting config.
In Step3, ‘Enable Security’ section, in order to 100% be sure to keep the project free, we’ll check on the ‘Do not enable security protections’. Go on and finish creating the distribution.
- Open the distribution and ‘Edit’ the ‘Origin’ Under Protocol, check ‘HTTP only’. Save.

Note: We selected HTTP only because CloudFront and S3 are both AWS services and so CloudFront can use the AWS internal network to talk to S3 over HTTP and then serve the users over HTTPS. Data Flow Chart — Summary: User access CloudFront — HTTPS hence encrypted, Public Internet CloudFront access S3 — HTTP, AWS internal Network hence safe
- Wait for redeployment and use the ‘Distribution domain name’ to access the website. Now even if you access the domain with HTTP instead of HTTPS, it’ll redirects to HTTPS.
Your Static Website is up and running
Things that can be improved:
-
Route 53: Having a domain like https://d1otb157b3ly2p.cloudfront.net isn't professional and won’t leave a good impression on the employers and recruiters. Mapping it to a real domain could help a lot.
-
Setting a TTL(Time to Live): For our project since it has to deal with Resume which doesn’t change often, having a default TTL will suffice, but it is a good habit to setting up a proper cache TTL values to tell CloudFront how long it needs to hold the file(s) before checking S3 Again.
-
Cache Invalidation: Since we are using CloudFront, if we make any changes to index.html, they can take some time to be cached again at CloudFront. A simple cache invalidation while deployment can help to purge this cache.
-
S3 Cross Region Replication: S3 automatically replicates data in multiple AZs within a region (us-east-1). but in order to make our data absolute region failure proof, it’ll be good that we can replicate out S3 to a different geographical region like eu-west-2.
-
Automatic Deployments: Right now, if I make changes to my resume 10 different times, I’ll have to reupload my resume 10 different times. We can rather use platform like GitHub to push and deploy our index.html file whenever we make a change on our system.
-
Origin Access Control (OAC): Currently S3 bucket is public. While CloudFront fetches files from S3 using AWS internal network, S3 website’s endpoint URL has a predictable patter — bucket-name.s3-website-region.amazonaws.com and is usually publicly available which can result in bypassing CloudFront and hitting on S3 directly. So the solution is to implement OAC, that’s make the bucket private and give IAM permission to CloudFront. Any direct hit on S3 will now result in an error.
Lastly, cleaning the Resources:
AWS gives USD 200 credits and some of the things we do are indeed free, but still, cleaning the resources is important to avoid accidental usage fee.
- Head over to S3 and empty the bucket first.
- Now delete the bucket.
- Go to CloudFront and select the distribution we created and hit ‘disable’
- Wait few minutes for the ‘last modified’ tab to change from deploying to the current date.
- Select the distribution and hit ‘delete’.
I really hope this project proved helpful to you, it surely has helped me in demystified how these core AWS services interact :)
Many Thanks!
메타데이터
- post_id
- c84dfcbcf6d9
- slug
- project-static-website-hosting-on-aws-using-s3-cloudfront-walkthrough-c84dfcbcf6d9
- url
- https://medium.com/@jainpulkit07/project-static-website-hosting-on-aws-using-s3-cloudfront-walkthrough-c84dfcbcf6d9
- canonical_url
- https://medium.com/@jainpulkit07/project-static-website-hosting-on-aws-using-s3-cloudfront-walkthrough-c84dfcbcf6d9
- author_url
- https://medium.com/@jainpulkit07
- status
- ok
- fetched_at
- 2026-06-28 10:39:35