Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Cloudfront as CDN for Heroku Site with Custom Domain

Recently, I bought a domain from AWS Route 53 (brianpatrickhummel.com) to host a personal portfolio. The portfolio site is up and running, using an S3 bucket and Cloudfront as a CDN. On the portfolio site, visitors are able to preview some apps that I built, which launch in-site using iframe elements, and I noticed that my Heroku-deployed apps take 10-20 seconds to load, since those sites have very few visitors on average and have no CDN service.

Therefore, I began researching using AWS Cloudfront as a CDN. I began with one Heroku app, adding a custom domain which is now configured as such:

Domain Name: burger.brianpatrickhummel.com
DNS Target: burger.brianpatrickhummel.com.herokudns.com

The last step is to "configure your app’s DNS provider to point to the Heroku-supplied DNS Target." Between this step and properly configuring a Cloudfront distribution, I have run myself into a spiral of confusion. I'm uncertain as to of where I make certain DNS/CNAME changes, in Cloudfront, Route 53 or both.

There isn't much online documention specifically related to these three technologies (Heroku, Cloudfront, Route 53) and I've spent much time bouncing between these three articles, to no avail:

Heroku - Using Amazon CloudFront CDN

Configuring Amazon Route 53 DNS for Your Heroku App

I'm confident that the necessary changes are simple in nature and would greatly appreciate any insight from those who might have experience with this particular configuration.

---UPDATE---

I have one last question, now that I have all of my Heroku apps successfully routing through Cloudfront, I have realized that all of the apps which have components that generate POST HTTP requests receive 403 - forbidden errors. Does this have anything to do with the relative URL in the respective AJAX calls:

$(document).on("click", ".saveButton", function () {
  var thisId = $(this).attr("id");
  $.ajax({
    method: "POST",
    url: "/save/" + thisId
  }).done(function () {} 

I see the following in the Cloudfront documentation:

CloudFront always caches responses to GET and HEAD requests. You can also configure CloudFront to cache responses to OPTIONS requests. CloudFront does not cache responses to requests that use the other methods.

Is this more of a problem with handling the responses from the server of the Heroku app than it is an issue with successfully sending the request?

-- UPDATE 2 --
I'm thinking that this has to do with HTTP/HTTPS based on this statement in the Cloudfront Documentation:

CloudFront doesn't redirect DELETE, OPTIONS, PATCH, POST, or PUT requests from HTTP to HTTPS. If you configure a cache behavior to redirect to HTTPS, CloudFront responds to HTTP DELETE, OPTIONS, PATCH, POST, or PUT requests for that cache behavior with HTTP status code 403 (Forbidden).

Heroku states:

If you are wanting to serve Cloudfront assets using SSL you can simply use HTTPS on the distribution domain given to you by Amazon. Note, whilst you can create CNAME’s for this purpose, serving Cloudfront assets over your CNAME and SSL has an attached cost.

In AWS Cloudfront Distribution Cache Behaviour settings, you can choose for the Viewer Protocol Policy from three options:

If you want CloudFront to allow viewers to access your web content using either HTTP or HTTPS, specify HTTP and HTTPS. If you want CloudFront to redirect all HTTP requests to HTTPS, specify Redirect HTTP to HTTPS. If you want CloudFront to require HTTPS, specify HTTPS Only.

The Cloudfront doc goes on to note:

Redirect HTTP to HTTPS Viewers can use both protocols, but HTTP requests are automatically redirected to HTTPS requests. CloudFront returns HTTP status code 301 (Moved Permanently) along with the new HTTPS URL. The viewer then resubmits the request to CloudFront using the HTTPS URL.

When a viewer makes an HTTP request that is redirected to an HTTPS request, CloudFront charges for both requests. For the HTTP request, the charge is only for the request and for the headers that CloudFront returns to the viewer. For the HTTPS request, the charge is for the request, and for the headers and the object returned by your origin.

HTTPS Only Viewers can access your content only if they're using HTTPS. If a viewer sends an HTTP request instead of an HTTPS request, CloudFront returns HTTP status code 403 (Forbidden) and does not return the object.

Good grief, I had no idea how complicated it would be to host a personal website!

like image 781
Brian Patrick Hummel Avatar asked Sep 08 '17 16:09

Brian Patrick Hummel


People also ask

Does heroku support CDN?

The Edge CDN supports applications written in any Heroku-supported language and is managed via the Edge dashboard.

What is http CloudFront net?

Cloudfront.net is an online service referred to as a content delivery network, or CDN, that many companies use to speed up or accelerate the delivery of content such as video, API (Application Program Interface), and overall website loading speed, which is crucial in keeping a visitor engaged on any website.


2 Answers

Domain Name: burger.brianpatrickhummel.com

You will point this to CloudFront, in Route 53... but before you can do that, you need to create a new CloudFront distribution and configure that hostname as an Alternate Domain Name for the distribution.

DNS Target: burger.brianpatrickhummel.com.herokudns.com

Configure this as the Origin Domain Name when creating the distribution CloudFront.

In the Cache Behavior settings, whitelist the Host header so that Heroku will understand which site the request is for.

like image 70
Michael - sqlbot Avatar answered Oct 19 '22 06:10

Michael - sqlbot


Here are the steps I would do,

Since you are already on Route 53,

Get a free SSL from ACM

Confirm your SSL verification to the domain email address. Make sure it looks green as below,

ACM Confirmation

Assign it to CloudFront Endpoint with the SSL and CNAME as well

You will also see a cname will be automatically created in Route53 for this SSL endpoint.

If you ping burger.brianpatrickhummel.com, it should respond from the clound front.

Cloudfront SSL

Now setup Origins in Cloudfront to point it to your endpoint with all the cache settings needed. If you don't need cache settings, you can set them all to 0, so cloudfront will not cache any data.

In your Cloudront Pattern make sure you have * at the end so it matches all the url pattern to forward it to your endpoint.

If your endpoint need to be secured, you can pass in additional headers from Cloudfront and make sure the request is orignating from cloudfront, rather than any public endpoint.

like image 1
Kannaiyan Avatar answered Oct 19 '22 06:10

Kannaiyan