In this guide, I will show you how to host a static website using AWS in a serverless manner.
The following AWS services will be used:
- Simple Storage Service (S3)
- Route53
- Cloudfront
- Certificate Manager
Angular, Vue, and React apps can be compiled into static files that can be served from an S3 bucket. If you can provide these files, you can host a dynamic website from S3.
You will need an AWS account for this guide.
It is easiest to have a domain in Route53 for this guide. If you do not, then go to your current registrar's DNS settings. Create a CNAME record with host 'www' and the Cloudfront URL as the target. When you request your certificate, make sure to specify your domain as *.yourdomain.com. Then add www and no www variants to your Cloudfront distribution's alternate domain names field.
It is possible to complete these steps with the SDK or by using Cloudformation.
Step 1 - Creating an S3 bucket.
We'll be revisiting our S3 bucket later to adjust bucket policy.
- Visit S3 in the AWS console.
- Click on "Create Bucket" in the top-left corner.
- It is recommended that your S3 bucket name be the same as your domain. (yoursite.com) without the www or http.
- Select your preferred region. This might be the one closest to you.
- Click "Next" and you will see "Configure Options." Leave everything as default.
- Click "Next" and you will see "Set Permissions." Again, leave everything as default.
- Click "Next" and then click "Create Bucket."
- Upload all of the static files and folders for your website.
We cannot proceed further until we create a Cloudfront distribution. Once we do, we can adjust the bucket policy to restrict access to the Cloudfront distribution we create.
Step 2 - Creating a Cloudfront distribution.
This is the resource that Route53 will access your static website from. It will draw the website's files from your S3 bucket.
- Visit Cloudfront in the AWS console.
- Click "Create Distribution" in the top-left corner.
- Under "Web," click "Get Started."
- Click inside the "Origin Domain Name" input, and select your S3 bucket.
- Click inside the "Origin ID" input, and enter your S3 bucket name.
- Next to "Viewer Protocol Policy," select "Redirect HTTP to HTTPs."
- Select which minimum, maximum, and default TTL makes sense for you. In default TTL, enter the number of seconds between each time Cloudfront looks at your S3 bucket, and caches changes you've made to your website. I use 86,400 seconds, or one day.
- Next to "Price Class," select which edge locations you want to support. It is more expensive to use more edge locations.
- You can specify an alternate domain name such as "www.yoursite.com"
- Next to "SSL Certificate," select "Custom SSL Certificate" and then click "Request or Import a Certificate with ACM." This will open the Certificate Manager in a new tab.
Leave the Cloudfront tab open. We will be returning to it shortly.
Step 3 - Requesting an SSL certificate.
You should be in the certificate manager, with the Cloudfront distribution setup in another tab.
Please ensure that your domain is in Route53, and the registrant contact is an email you can access.
- Type in your domain name under "Domain name."
- Click "Next" and the select "Email Validation." This is typically the easiest method.
- Click "Review" and then "Confirm and Request."
- Go to your email and then confirm the request.
- Your certificate should say "Validation status" as "success."
- Copy your certificate ARN.
You have created a valid certificate. AWS Certificate Manager will handle renewals. Close this tab, and switch back to the Cloudfront setup.
Step 4 - Finishing Cloudfront setup.
You are adding the certificate you just created to your in-progress Cloudfront distribution.
- In the field under "Custom SSL Certificate," paste in your ARN.
- Leave the remaining options as default, and select "Create Distribution."
- When your distribution state is "Enabled," select "Origin Access Identity" on the leftmost column.
- Select "Create Origin Access Identity," at the top-left corner.
- Your comment should be the name of your S3 bucket.
- Click "Create" and then copy the ID column for the identity you just created.
- Return to S3.
Next we will upload your static files to S3 and add a bucket policy to allow secure reads from Cloudfront.
Step 5 - Adjusting your bucket policy.
You should be in your S3 bucket again.
- Select the "Permissions" tab on your bucket.
- Select the "Bucket Policy" button.
- Paste the following bucket policy in. You need to change the XXXXXXX to your Origin Access Identity. You also need to change yourdomain.com to the name of your new S3 bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXXX"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::yourdomain.com/*"
}
]
}
- Click "Save" and return to the "Overview" tab.
- Go to Route53.
The last step is to resolve your domain to your Cloudfront distribution.
Step 6 - Resolving your domain to Cloudfront
You should be in Route53. If you haven't created a hosted zone for your domain, here are the steps:
- Click the "Create Hosted Zone" button in the top-left.
- Enter your domain name without www or http.
- Enter the name of your website in the "comment" input.
- Click "Create."
- Click "Create Record Set."
- The name is "www"
- The type is CNAME.
- The value is your domain without the www or http.
- Click "Save Record Set."
- Click "Create Record Set" again.
- The name is blank.
- The type is "A"
- Select "Yes" next to "Alias."
- Next to "Alias Target" select your Cloudfront distribution.
- Select "Create Record Set."
In 1-2 minutes, open a new tab, and see if your domain resolves with and without www to your static website. If it does not, check that you did the steps correctly. If it still does not work, leave a comment below the post.
I couldn't figure out how to end a code block in markdown. I was using dilinger.io to check and the code block escapes when I put a triple backtic. Not here it seems. I've reached out to dev.to on Twitter, and there will hopefully be an answer.
It seems that the syntax has fixed itself. Odd.
I hope this helps whoever was looking for a cheap way to host a secure, serverless, and static website.
Thank you.
Top comments (22)
I think this post missed an important point. So for some people here talking about other solutions or alternatives. Using cloudfront brings you a really great feature that is CDN. Your site is hosted on many locations over the world, this means less latency. The Cloudfront page even says that the amazon prime movies are stored using Cloudfront. So IMHO this provides a great architectural design to your project
It's possible that those alternatives provide global deployments.
I mean yeah. But it is probably not as good as the replication aws cloudfront provides you. In my opinion the reason to go for this approach is just that. Cloudfront charges for that.
Is there a way to do it without hosting the full zone on route53?
Having only a subdomain served through ssl hosted on s3, while the zone is managed by another DNS manager where there are currently several rules already in place.
Does your DNS manager allow you to create CNAME records? Try adding one of those and point it to your Cloudfront URL. Cloudfront has a space for you to pass in alternate domain names. Type the outside domain in that field.
If you try, would you mind letting me know if it worked?
Yup, it worked using the alternate names and a CNAME redirecting. Thanks!
Netlify includes almost all of this and it's free.
A friend of mine uses it. He seems to like it. If a person wants to use Netlify, then they have this option. If a person wants to use AWS, then this guide may prove beneficial.
Hi thanks for this post i intend to use this to learn more about server-less and aws services, how much will it cost deploying a static site using this approach with let say 12000 visitors per month.Thanks
Pennies
The other commenters mentioned other hosting providers that would work. This is how you might do it on AWS.
Interesting that you're hosting 100 websites in one S3 bucket. I think I'd call that an antipattern.
Good article. I would add "Default Root Object: index.html" to CloudFront distribution since you do not use the "Use this bucket to host a website" approach so there is no "Index document" field then.
Yeah I should outline both approaches in the article. Thank you.
Would I need to renew my cert to keep HTTPS working? Maybe it would be worth adding a section for that.
I've used GitHub pages for creating a static site, and they handle the cert renewal.
AWS Certificate Manager handles renewals. I will make a note of that in the post.
I use Github pages for my personal site. I didn't always realize how convenient it was to have the cert renewal. Your reminder may help people who are concerned.
Thank you.
I do this with 3 commands:
firebase init
firebase deploy
and "Add Domain" in the hosting section
There are many excellent hosting solutions for static websites. Firebase is one of them. My guide can help those who wish to host theirs on AWS.
How to use free AWS without credit card?
I've tried, but according to the documentation, you cannot use AWS without a bank card.
If you're a student then AWS Educate may be usable without a card.
EDIT: I now see an option to add a bank to my account. Maybe that could work too.
Yes, that's right. You can go to the origin tab on your distribution. Then you can and select "Yes, update bucket policy."