January 17, 2021

How to build a website from scratch under the AWS free tier (Part I : Front)

I used to love to pick up any CMS to launch and host a website.

As a growth hacker, its a valuable resource that allows you to test different ideas, landing pages etc.

With experience, I realized that Wordpress was not customizable enough anymore for me. Moreover it started to get on the expensive side and I felt like I didn’t get what I wanted for what I was paying.

That’s how this story came about, I needed a quick and easy solution to host potential tech product, where I can manage front and back end on a suite of services I am familiar with.

This two part tutorial will show you how to build (or transfer) your website from scratch on AWS in a few steps, making it faster, safer and cheaper.

This first part is going to focus on how to host and distribute the front end of our website. I will use my website 5€ pour rien as an example. (Literally means 5 euros for nothing and yes it’s dumb)

In this part, we are going to be using:

Prerequisites

Host your website files on S3

  1. If you already have a hand on your website files, you’re all good. Otherwise, you can start a new site from scratch yourself or with a template from HTML5UP.

2. Once you’re there, login to your AWS console, and get to s3 to create two buckets, named your-domain.com and www.your-domain.com.
We’ll modify the permissions later, so you can use the default options so far :

Image for post
The S3 interface, i already created the buckets

Image for post
The two created buckets

3. Then upload your files to the www.your-domain.com bucket.

4. Change the options and permissions of your buckets :

Image for post
{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Sid": "PublicReadGetObject",
           "Effect": "Allow",
           "Principal": "*",
           "Action": "s3:GetObject",
           "Resource": "arn:aws:s3:::www.your-domain.com/*"
       },
       {
           "Sid": "PublicReadForGetBucketObjects",
           "Effect": "Allow",
           "Principal": "*",
           "Action": "s3:GetObject",
           "Resource": "arn:aws:s3:::www.your-domain.com/*"
       }
   ]
}
Image for post

5. Congrats ! You should already be able to see your site live on the endpoint indicated on the s3 prompt. The only problem is that the url is problably not optimal. To change that we are going to change the DNS settings of our domain name.

6. Do this step only if you don’t care about : 1) Your site being secured, 2) Your site not being optimally fast. Go to your domain name manager and add an A (alias) record with a name of www and the value being the endpoint of your S3 hosted www.your-domain.com website.

If you’re on Route 53, click on Hosted Zones on the navigation menu, click on your domain, click on Create Record Set.

As name type www before your domain name, select A — IPv4 address, tick Yes on Alias and select your bucket.

You’re done !

Image for post

Secured distribution with Cloudfront

  1. Head on over to Amazon’s certificate manager and make sure you’re on the US-EAST region, because it’s Amazon’s global region. To change the region, check the upper right corner of the navigation menu.
    You can then create a global certificate for free by clicking on Request a certificate.
Image for post

2. Add your domain names to the certificate (don’t forget the root domain)

Image for post

3. If you have email setup for your domain, go for the email validation, you’ll receive a link confirmation to click to confirm and validate your certificate.
Otherwise, select DNS validation and edit your DNS zone accordingly. This method unfortunately takes time (a bit less if you’re on route 53) so you’ll have to wait until your DNS settings are propagated to get the certificate.

Image for post

Since my domain was bought on Route 53, I could create a record in the Certificate Manager

Image for post

4. Get your www bucket endpoint that should look like www.your-domain.com.s3-website.your-region.amazonaws.com.

We’re going to create a new Cloudfront distributions to distribute and encrypt the content on both our endpoints.

Click on Create distribution and Get Started on the web portion of the next screen.

On that screen here are the only things you have to do:

Image for post
Image for post
Image for post

Image for post
Our Cloudfront distribution

5. There’s only one thing missing now, and that’s to actually use our distributions with our domain name. To do so, we’re going to once again look for our domain name manager.
In my case, it’s super easy:

Image for post
Associating the root domain to its cloudfront distribution

If you don’t use Route 53, the idea is the same, create an A record with a name of @ (itself) and a value of your-domain.com’s Cloudfront distribution domain name (d2xxxxxxx.cloudfront.net) you created.

Repeat with an A record for www.your-domain.com and its Cloudfront distribution domain name.

6. You’re done ! All you have to do is to wait for the distributions to be deployed and for the DNS changes to be propagated.

What’s next ?

If you already have a backend running, you can just enjoy cheap rates and speed as is.

If you don’t, stay tuned for part 2 where I explain how to build a super lightweight and scalable back end with AWS Lambdas !

Bonus : Make live changes on your website instantly

You can change the default options of the Cloudfront caching, but I wouldn’t recommend it since it’s part of what makes the distribution so fast. The alternative is to use Cloudfront invalidations to refresh your website.
You get up to 2000 free invalidations per month so you can use them quite a bit although it’s much better to do your biggest changes locally.

To do so, click on one of your distributions and go on the Invalidations tab:

Image for post

Click on Create Invalidation and type /* to invalidate all of your files

Image for post

Wait a bit, and you’re all done ! All your changes are live !

Get my posts in your inbox

I promise I'll never send any spam your way

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.