Use the Rails Asset Pipeline with Google Cloud CDN

Google Cloud, Rails,

Setting up a Google Cloud CDN is challenging, because it requires you to fully immerse yourself in the vast vocabulary of Google Cloud. The goal of this article is to help get your Rails assets hosted on Google Cloud CDN. Along the way, I will try to contextualize why each step is necessary. At the end of this article, not only will you have your Rails assets hosted on Google Cloud CDN, but you’ll also understand a bunch of new Google Cloud terminology.

Prerequisites

  • A Google Cloud account and access to the Google Cloud Console.
  • A hosted Rails app (e.g. Heroku, App Engine).
  • Access to the DNS for your app’s domain (www.your-app.com), because we will eventually create a custom subdomain for your assets (assets.your-app.com).

Introduction to CDNs

A CDN (Content Delivery Network) is a geographically distributed network of servers whose sole purpose is to place content physically closer to end users. For a Rails app, that content consists of scripts, stylesheets and media.

The closer your assets are to end users, the faster they will be able to download them. And this is because computer networks are slower than you might think. To illustrate my point, I’ve included an excerpt from Latency Numbers Every Programmer Should Know below.

OperationTotal
Round trip within same data center0.5 ms
Read 1 MB sequentially from SSD1 ms
Disk seek10 ms
Read 1 MB sequentially from disk20 ms
Send packet CA ➔ Netherlands ➔ CA150 ms

Introduction to Google Cloud CDN

I think it’s key to understand the entire system from a macroscopic level and how your asset request will flow through the system. Once you understand how an asset request flows through the system, setting up each individual service will be much easier because you’ll understand how it fits into the system as a whole.

Take a moment to study the graph below, which describes how an asset request will flow through our CDN.

Now that you understand how an asset request flows through the CDN, we will begin by setting up each service from the bottom-up.

You might be wondering why we’re doing this in reverse. The reason is because I want you to spend as little time in the Google Cloud Console as possible. I brute-forced this process from the top-down many times, and through trial and error I discovered that it’s faster, and it takes fewer steps in the UI to set up each service from the bottom-up.

Step 1. Create a Network Endpoint Group

A Network Endpoint Group is a Google Cloud abstraction that is placed between a Load Balancer and the backend servers. A Network Endpoint Group is what allows us to bring our Rails app into the Google Cloud ecosystem and expose our Rails app to the Load Balancer that we’ll set up in the next section

This abstraction allows Google Cloud to route traffic from a Load Balancer to 3 different types of backend servers: traditional backend servers, Serverless servers and containerized services running on a VM.

But for Rails apps only 2 are relevant, and they are:

  1. Internet Network Endpoint Group (e.g Rails app on Heroku)
  2. Serverless Network Endpoint Group (e.g. Rails app on Google Cloud App Engine)

I will be focusing on how to setup a Network Endpoint Group for an externally hosted Rails app (e.g. Heroku). I have omitted instructions for Serverless Rails apps because support is currently in beta. If your Rails app is hosted on Google Cloud, you will need to follow these instructions.

  1. Using the search bar at the top of the screen, search for “network endpoint groups” and click on Network endpoint groups.
  1. Create an Internet Network Endpoint Group.
    1. Network endpoint group type: Network endpoint group (Internet)
    2. Default port: 443
    3. New network endpoint
      1. Add through: Fully qualified domain name and port
      2. Fully qualified domain name: www.your-app.com
      3. Port type: Custom
      4. Port number: 443

Step 2. Create a Load Balancer

A typical Load Balancer sits in front of your backend servers, and its main job is to evenly distribute requests to the backend servers without overloading any single server.

A Google Load Balancer provides similar functionality and much more, including the ability to turn your Load Balancer into a CDN with the click of a button.

  1. Using the search bar at the top of the screen, search for “load balancing” and click on Load balancing.
  1. Create a Load Balancer.
    1. HTTP(S)
    2. Internet facing
    3. Backend configuration
      1. Create a backend service
        • Backend type: Internet network endpoint group
        • Protocol: HTTPS
        • Select your Internet network endpoint group from the previous section.
        • Enable Cloud CDN
        • Open advanced configuration and add a custom request header.
          • Host: www.your-app.com
    4. Frontend configuration
      1. Protocol: HTTPS
      2. IP address: Create IP address
      3. Create an SSL Certificate for your asset subdomain.
        • Domain: assets.your-app.com
      4. SSL policy: Compatible
        • This is important to change. By default, Google Cloud uses a custom SSL policy which doesn’t work with non-Google Cloud backends such as Heroku.
  1. Write down the static frontend IP address so you can create an A record in your DNS settings. This record will map your asset subdomain to your Google Cloud Load Balancer.

  2. Wait for the SSL certificate for your asset subdomain to be provisioned. A green check mark will appear once it has been successfully provisioned.

Step 3. Create a DNS A Record

DNS is how domain names are resolved into IP addresses. This step will connect your asset subdomain to the IP address of your Google Cloud Load Balancer. We will create an A record which is specifically made for mapping domain names to IP addresses.

  1. Visit your DNS host and find the advanced settings.

  2. Create an A record to map your asset subdomain (assets.your-app.com) to your Google Cloud CDN frontend IP, which you previously wrote down.

    1. Host: assets
    2. IP address: frontend configuration IP
  1. Wait for the A record to propagate across the internet to other DNS servers.

Step 4. Test Your Google Cloud CDN

Before you can test, you must wait for your SSL certificate to be provisioned, and your DNS A record to be propagated. Once these 2 tasks have been completed, you can begin testing.

You can test your Google Cloud CDN by using your asset subdomain to access a public asset on your app. For example, if your public asset is located at www.your-app.com/style.css, then replace the subdomain (www) with your asset subdomain (assets), and your public asset should also be available at assets.your-app/style.css.

Step 5. Update Your Rails Config

Once your assets are available through your asset subdomain, you will need to update your Rails app configuration. To set your asset host in Rails, open config/environments/production.rb and set config.action_controller.asset_host.

1# config/environments/production.rb
2Application.configure do
3  config.action_controller.asset_host = 'assets.your-app.com'
4end

For more details on how to setup a CDN with Ruby on Rails click here.

Conclusion

Congratulations, you’re all done! At this point you should have your Rails assets fully hosted on Google Cloud CDN.

If you found anything that was unclear or outdated please let me know, and I will update this post.

Thank you to Marín Alcaraz and Michael Geraci for editing.