Part 5: Adding CloudFront
Tags: aws, cloud, serverless, database
Published: 2021-01-17 23:19:11

<p>In this post we will add a CloudFront distribution to our project. &nbsp;Amazon CloudFront is AWS's Content Delivery Network (CDN). &nbsp;Other popular CDNs that you may have heard of are Cloudflare, Fastly, and Akamai. &nbsp;A CDN has servers distributed around the world for the purpose of caching content closer to its end users. &nbsp;By caching content closer to the end users, the resources load faster and less traffic has to be served by your origin (the term used to refer to the source of the content).</p><p>This post picks up where we left off in <a target='_blank' href='https://www.jonholman.com/ComputelessBlog/part-4-adding-category-landing-and-home-page'>Part 4: Adding the category and home landing pages</a>. &nbsp;If you did not go through that post, you can get the project files we will be using as our starting point <a target='_blank' href='https://github.com/JonHolman/ComputelessBlog/tree/part-4-adding-category-landing-and-home-page'>here</a>.</p><p>The first thing we will do is add an additional item to the resources section of our template.yaml file. &nbsp;This new item in the template.yaml file will create our CloudFront Distribution when we apply our updated CloudFormation template (via sam deploy).</p>{% gist https://gist.github.com/JonHolman/392a1a6b1a381af187212b2aab7a13fe.js %}<p>Then we will add an additional item to the output section of our template.yaml file. &nbsp;This new output will provide us with the URL to our CloudFront distribution.</p>{% gist https://gist.github.com/JonHolman/6d3bcfb9ea45b83b633abab383b9ffa5.js %}As a part of the CloudFront distribution that we added, we specified that the OriginPath is /Prod. &nbsp;That tells CloudFront to use that base path for all items being requested from origin. &nbsp;So, now with that added, we should remove /Prod from the hyperlinks in our page.yaml file. &nbsp;We can just do a global replace to remove /Prod from our page.yaml file, it should be there 5 times.</p><p>Now let's run sam deploy so that these CloudFormation updates will be deployed.</p><p>When sam deploy completes, you will see our new output being returned for the CloudFrontDistribution's URL which will be something like <a target='_blank' href='https://d2mubg31z2zmzn.cloudfront.net/'>https://d2mubg31z2zmzn.cloudfront.net/</a></p><p>I can imagine a possibility that someone would like their blog to have a more memorable URL than <a target='_blank' href='https://d2mubg31z2zmzn.cloudfront.net/.'>https://d2mubg31z2zmzn.cloudfront.net/.</a> &nbsp;So, in this next section we will add a custom domain for our CloudFront distribution.</p><p>First, you will need a domain name and the ability to add a DNS record to that domain. &nbsp;For this the AWS answer is Route 53, but like I have said in previous posts, I am a very cost conscious person. &nbsp;With that in mind, I cannot get myself to pay 50 cents a month for a hosted zone when every other registrar I have used provides that service for free. &nbsp;Yes, even though AWS took liberties with the DNS standard and added their own record type (ALIAS). &nbsp;I still don't think it is worth 50 cents a month.</p><p>To add a custom domain to our blog, via CloudFront, we will first add parameters and conditions to our CloudFormation template. &nbsp;There will be two parameters, one for the DNS alias we want to use and the second for the Amazon Resource Names (ARN) for your certificate stored in AWS Certificate Manager. &nbsp;We are adding these as parameters, so we do not have to hard code these values in the CloudFormation template. &nbsp;The conditions are being added, so that if anyone wants to follow along and they do not have a domain name they want to use (or maybe they are happy with a URL like <a target='_blank' href='https://d2mubg31z2zmzn.cloudfront.net/),'>https://d2mubg31z2zmzn.cloudfront.net/),</a> they can just leave these new parameters blank and CloudFormation will apply just like it did before we added them. &nbsp;To add those parameters and conditions add the following to your template.yaml file. &nbsp;I like to add these right above the Mappings sections.</p>{% gist https://gist.github.com/JonHolman/113f5d669cd4b288bea9a0cfe366b935.js %}<p>Next we will add logic to our CloudFront resource in template.yaml to add the alias and certificate properties when the condition we defined above is met. &nbsp;To do that add these lines to the bottom of the <code>AWS::CloudFront::Distribution</code> resource.</p>{% gist https://gist.github.com/JonHolman/2bb5897d1176810797147aaf4d41ba60.js %}<p>And last, we will add another output to our CloudFormation template. &nbsp;This output will give us the information we need to create our CNAME DNS record to point it to our CloudFront Distribution. &nbsp;To add that just add the following to the outputs section of your template.yaml file.</p>{% gist https://gist.github.com/JonHolman/2ab29856eb8871e745a7b7493140d1d8.js %}<p>That is everything we need to add to our project files. &nbsp;If you will be using a custom domain, we need a certificate in AWS Certificate Manager (ACM) before we are ready to apply our updated CloudFormation. &nbsp;We will be using a public certificate, so it is free. &nbsp;Since generating a certificate is not usually something you want to do often, and I commonly create/destroy CloudFormation stacks while keeping the certificate, I do it outside of the CloudFormation. &nbsp;This is one of the rare things that I feel is ok to do through the AWS console. &nbsp;To create a certificate in AWS Certificate Manger follow these steps.</p><ol><li>Open your web browser and log into the AWS console.</li><li>Search for Certificate Manager and open it.</li><li>Click request a certificate.</li><li>Keep request a public certificate selected and press request a certificate.</li><li>For domain name enter the domain name that you will be using for your blog (I commonly create a wildcard certificate by entering *.domainname.tld, like *.jonholman.com) and press next. &nbsp;Note that it would be helpful to have the wildcard (*) certificate as we will be using the same certificate later when we create our admin page.</li><li>Now for validation method you can pick whichever option you prefer, either way you need to validate 'that you own or control the domains for which you are requesting the certificate' and press next.</li><li>On the next page you can add any AWS tags to your certificate, if you would like, and press review.</li><li>Then review your selections and press confirm and request.</li><li>The next screen will give you information about how your validation is being processed, press continue.</li><li>Now follow the instructed steps to complete validation of your request.</li><li>Soon after you complete validation, you can refresh the AWS Certificate Manager console and see that your certificate has updated from pending validation to issued.</li><li>Expand your new certificate and copy the ARN value, so that you can provide it to our next step as the value to that parameter.</li></ol><p>Now that we have added those items and generated our certificate (if necessary), let's deploy these changes by running sam deploy --guided. &nbsp;Note that we need to run sam deploy with the guided option this time to allow us to add values for the two new parameters that we added. &nbsp;If you will not be adding a custom domain name just press enter for each of those values when prompted.</p><p>Our project directory at the end of this post is available <a target='_blank' href='https://github.com/JonHolman/ComputelessBlog/tree/part-5-adding-cloudfront'>here</a>.</p><p>Thanks for reading. &nbsp;If you have any feedback or questions, please leave a comment or message me on Twitter/LinkedIn (links on the right side bar).</p><p>In the next post, we will move our static assets to an S3 Bucket so that our web pages do not rely on resources from other web sites. &nbsp;We will then add that s3 bucket as another origin on this same CloudFront distribution.</p>