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.
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.
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
Now click 'Next'. You will be presented with the following screen.
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.
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.
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
You should be presented with the following screen showing the 'getting started' dialog.
To upload a file you can do any of the following:
- Click 'Upload file' and select your file(s) using the file select dialog of your OS.
- Click 'Upload file' and drag the files onto the dialog.
- Drag a file into the bucket area
Upload your file using any of the above.
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.
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.
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.
Domain Name field enter the domain name on which you want to host your custom CDN for example
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.
On the 'Create Distribution' screen you will want to set the options as follows:
- Origin Domain Name start typing the name of your bucket (e.g.
peters-cdn-bucket) and you should get an autofill option such as
- Origin Path to the directory within your bucket you want to make all paths relative to, if you uploaded your files straight to the root of your bucket just set this to
- Origin ID can usually be set to the value it defaulted to (your bucket name prefaced with
- Origin Custom Headers can be left blank for this use-case.
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
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
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!