Peter Reid
Peter Reid

My ramblings about developer tooling, the Cloud, JavaScript, DevOps, programming and technology.

Peter Reid
Author

Software Engineering student, full stack JavaScript developer, developer tooling nerd and all round geek - not necessarily in that order.

Subscribe


Fill in the form below get the latest posts from Peter Reid straight to your inbox!

Share


Peter Reid

Setting up a CDN with AWS S3 and CloudFront

Peter ReidPeter Reid

In this tutorial I'll walk you through setting up your own CDN with Amazon Web Services (AWS) S3 and CloudFront.

In this modern era of web development where 'pagespeed' can be critical factor in your SEO and vital for retaining user's attention many sites will require the use of a Content Distribution Network (CDN) to host their static assets. In this tutorial I'll walk you through setting up your own CDN with Amazon Web Services (AWS) S3 and CloudFront.

Pre-requisites

For this tutorial you will require an AWS account with access to create S3 buckets and CloudFront distributions. As of time of writing the resources used in this tutorial are available for free for new customers for 12 months through the AWS free tier.

Create an S3 bucket

In order to set up our CDN we will need somewhere to upload and store our files to, on AWS this is S3. Head over to the S3 console and click 'Create Bucket'. A dialog will appear as below.

S3 Create Bucket Dialog

For Bucket Name you should enter a descriptive name with no spaces so you can identify this bucket in your console, it is worth noting that this is the domain name that will appear if you link directly to your bucket e.g https://s3-eu-west-1.amazonaws.com/peters-demo-cdn-bucket/, this name must also be unique across the whole of AWS. For this tutorial I am going to use peters-cdn-bucket, take a note of the name you use as this will be required in later steps.

For Region you should select the region that you want to be the 'canonical source' for your CDN, this is also the region you will be uploading the files too, so for optimal upload speed you should probably select the region geographically closest to you - so I will choose EU (Ireland).

Now click 'Next'. You will be presented with the following screen.

S3 Create Bucket Dialog Step 2

On this screen you can set various additional options such as tracking versions of files in case you want to revert to a previous version, logging requests to AWS CloudWatch and tagging this bucket so you can show it in reports in your billing dashboard along with other resources of a similar nature. For this tutorial we won't need any of these so just click 'Next'. You will now be presented with the following screen.

S3 Create Bucket Dialog Step 3

You can use this screen to modify access permissions for your bucket, under the 'manager users' section you could add other IAM users from your account that you want to be able to access this bucket. We are not going to modify the public permissions, as we will be giving public access through CloudFront and we will do this later with an IAM policy. Click 'Next'. You will be presented with the following screen.

S3 Create Bucket Dialog Step 4

Review your settings and edit them if you spot an error, then click 'Create Bucket'.

Adding files to your bucket

Now that you have a bucket set up, let's get to adding some files to serve to it. For this example I'm going to use a .jpg file testImg.jpg. Click your bucket name in the console

S3 Bucket list

You should be presented with the following screen showing the 'getting started' dialog.

S3 Bucket list

To upload a file you can do any of the following:

Upload your file using any of the above.

File upload dialog

Once your uploads are completed click 'Next'.

On the 'Set permissions' tab we do not need to choose anything for this tutorial, so click 'Next' to proceed to the 'Set properties' tab.

File upload properties dialog

In the 'Set properties' tab that is illustrated above, scroll down until you see the 'Metadata' heading as shown in the picture. Click the dropdown that reads Select a header... and choose Cache-Control which should be the first option in the dropdown. Now enter a Header Value of max-age=2592000 and click 'Save'. This value of 2592000 tells user's browsers to retain the resource in their cache for a maximum of 2592000 seconds (or 30 days) after initially requesting the resource. Your dialog should now look like so.

File upload properties dialog

Click 'Next' to progress to the 'Review' screen, review your changes and click 'Upload'. You should now see your file inside your directory.

If you need to edit the metadata of an object in your bucket after initial upload, you can click the name of the file in your bucket console, select the 'properties' and click on the 'Metadata' box to modify the values.

Getting an SSL Certificate for our CDN domain

Next up: we want to head over to the AWS Certificate Manager console for US-East-1 (North Virginia - this is where certificates for CloudFront distributions must be placed, no other region is valid). It is worth noting that all certificates acquired from Certificate Manager are free.

On the home page of the Certificate Manager console, click Request a Certificate.

In the Domain Name field enter the domain name on which you want to host your custom CDN for example mycdn.reidweb.com.

Certificate Manager dialog

If you have any further domains to add, add them now. It is worth noting that you can only have one certificate associated with a CloudFront distribution - so if you have multiple domains you'll have to include them all on the same certificate. Once you are done click Review and Request.

Verify your details are correct and click Confirm and Request. On the next screen verify the contact details that AWS has determined for that domain - you should see your email address listed - head over to your email inbox and click the verification link in the email followed by I approve on the web-page that opens.

Click continue to go back to the Certificate Manager console home page, you should see the certificate you requested listed.

Setting up a CloudFront Distribution

We now have our file(s) uploaded to AWS S3 we simply could setup 'static website hosting' to access them directly over HTTP(S), however we want to set up our resources to be distributed from AWS' CDN offering 'CloudFront' so they are distributed to a series of 'edge locations' around the globe for fast-access from anywhere so that user's browsers in Asia don't have to make a request to your bucket in Europe to get your resources.

Head over to the CloudFront console and click 'Create Distributon' at the top of the screen. You will be presented with a screen asking you to choose between 'Web' or 'RTMP', in this case we are distributing resources such as images, css and javascript for use on webpages, so choose 'Get Started' for 'Web'.

On the 'Create Distribution' screen you will want to set the options as follows:

Origin settings

It's increasingly standard practice to not permit standard non-secure HTTP connections, so let's set Viewer Protocol Policy as Redirect HTTP to HTTPS. For Compress Objects automatically choose Yes. The remaining Default Cache Behavior Settings can be left on their defaults.

For 'Distribution Settings', you can choose your pricing class. Then set the Domain Name to the custom domain name you selected earlier for your certificate e.g. mycdn.reidweb.com. For the SSL Certificate option choose Custom SSL Certificate and select your SSL certificate from earlier from the dropdown. Leave the rest of the options at their default values

Origin settings

Click Create Distribution.

Now to play the waiting game, your CloudFront distribution will take 20-40 mins in my experience to propagate settings out across the AWS edge location network. Furthermore, any changes you ever make to the distribution settings will have to be 're-deployed' which can take time.

Now we need to grant our distribution permission to read the files from our S3 bucket. Click your Distribution ID, then click 'Origins', select the default origin. For Restrict Bucket Access choose Yes, choose Create a New Identity. For Grant Read Permissions on Bucket choose Yes, Updated Bucket Policy. Then choose 'Yes, Edit' to save your choices.

Setting up the domain

Now that we have our objects/resources in place in S3, our certificate provisioned, and our CloudFront distribution deployed, we need to set up our domain name to point at our CloudFront distribution.

In the CloudFront console, click on your distribution ID. Copy the value of the Domain Name value into your clipboard.

Now go over to your domain control panel (in my case AWS Route 53) and add a new CNAME record with the name of your domain from earlier e.g. mycdn.reidweb.com, and a value of your Domain Name value from your CloudFront distribution - leaving the TTL on it's default value should be sufficient. Save this change and wait for it to propagate out.

Testing it out

Head over to your S3 bucket from earlier and view the name of the resource you uploaded e.g. testImg.jpg, copy this name and append it onto the end of your custom CDN domain in URL form e.g. https://mycdn.reidweb.com/testImg.jpg; take this URL and visit in your browser. If the image loads up you now have a working CDN with edge location distribution and caching, browser caching, and compression enabled - allowing your users to have optimal load times regardless of geo-location.

Your Next Steps

You can upload more objects to the 'directory structure' of your AWS bucket, and treat them as you would file paths of a conventional server. Enable object versioning if you find you are uploading new versions of files frequently, as this will clear the cache at edge locations of your file, so the new version is distributed. Alternatively use 'invalidation requests' in the CloudFront console to force the edge locations to clear their cache of one of your resources.

My Next Steps

I'll hopefully soon be checking out AWS CloudFormation, and should be able to simplify this entire guide down into 3-4 CloudFormation templates!

Peter Reid
Author

Peter Reid

Software Engineering student, full stack JavaScript developer, developer tooling nerd and all round geek - not necessarily in that order.

Comments