Using Digital Ocean Spaces and KeyCDN within Statamic

Nat Hobson
5 min readAug 2, 2018

--

If your website is going to be handling quite a few assets and if you have any kind of global reach, it’s definitely worth considering outsourcing the storage and delivery of your assets. Or, perhaps we can make it simple enough that you should just do it anyway 😎

Spaces are Digital Ocean’s own object storage offering backed by an API which is 100% compatible with Amazon S3s API.

So why bother using Space over S3? After all, Statamic comes with a baked in S3 driver. The big selling point for our agency, who are looking after a number of websites, is that they are fixed in price. For $5/month you get 250GB storage and 1TB of transfer. That’s as complicated as it gets. You only pay extra if you go over that. Trying to figure out what your S3 bill will look like will make your head explode and that makes it a hard sell for clients and a pain for us to bill.

OK, so how about KeyCDN? In my experience, KeyCDN are great at rolling out the latest and greatest new technologies – HTTP/2, brotli compression, Let’s Encrypt etc. I wont run down their full feature list but I will say that it’s a pretty fully-featured service, it’s simple to set up and it is very competitively priced. You can also trial the service for 30 days for free.

Get up and running with Spaces

Once you’re signed up and logged in with Digital Ocean, create a new Space. Currently you can select New York, Amsterdam or Singapore. Don’t worry about the limited selection as we’ll actually be serving the images via KeyCDN who have 33 locations. Make sure you add a name, location and select Restrict File Listing. You can then go ahead and create the Space.

Now you’ll need to generate an access key:

  1. From the left-hand menu in the Digital Ocean dashboard, navigate to API
  2. Under Spaces access keys, click the Generate New Key button.

The last step is to create a new asset container within Statamic and wire it up to the Space we just created. Thankfully, this is extremely easy as the Spaces API directly matches the S3 API, so we can reuse Statamic’s S3 implementation. The only gotcha is that we will have to create the container manually with a yaml file rather than through the control panel, otherwise we can’t input the correct Spaces endpoint. Within your Statamic project, create a new yaml file within site/content/assets. The contents of this file should look like:

title: Whatever you like
driver: s3
key: your Space key
secret: your Space secret
bucket: your Space name
region: your Space region
endpoint: your Space endpoint

A completed config might look like this:

title: Global assets
driver: s3
key: xxxxxx
secret: xxxxxx
bucket: statamic-assets
region: ams3
endpoint: ams3.digitaloceanspaces.com

You can also add path: a/sub/directory if you would like to limit the container to a specific folder within your Space.

Go and give that a test, it should just work. You should be able to see any assets added within Statamic pop up with your Space immediately. You can navigate into your Space within the Digital Ocean dashboard to view the contents.

Going global

Assets shouldn’t be served directly from object storage such as S3 or Spaces. Whilst these services are great for resilient storage, they are not tuned for performance and your assets will only be served from a single location. A CDN on the other-hand, is geared specifically for performance and global delivery.

First, sign up/in to KeyCDN. Within the dashboard, navigate to Zones then click Add Zone. We’re going to create a pull zone. This will “suck in” the assets from Spaces automatically, without any need for us to push any assets into the CDN.

  1. Add the zone name
  2. Make sure you have the zone type set to pull, although this is the default
  3. Leave the advanced features for now.
  4. Under the origin URL, add in your Space URL, such as https://your-space.ams3.digitaloceanspaces.com and click Save.
  5. It’ll take a few minutes to configure itself.

Once you’ve got Status active for the pull zone, go ahead and test your assets are available. Copy a URL for one of your assets in Statamic, which should look something like:

your-space.ams3.digitaloceanspace.com/your-image.jpg

Swap out everything before the filename and extension for the KeyCDN Zone URL. This should now look something like:

your-zone-cbbe.kxcdn.com/your-image.jpg

This should load up exactly the same image. You can open Chrome’s Network tab and check the headers:

Headers sent with our image

You should see the cache status, an expires header, the canonical link to the original image and also the edge location you were served the image from, which in my case is uklo (London, UK). Perfect 🌎

Serving images via a CDN in Statamic

At this point, we have our images mirrored on a CDN but Statamic will still be serving the images directly from Spaces. I’m sure there’s several ways to address this but here’s what I’ve arrived at.

Firstly, let’s create an environment variable which contains our CDN zone URL. Open up your .env file within the root of your Statamic project and create a new variable such as CDN with your zone URL.

APP_ENV=dev
CDN="http://your-zone-cbbe.kxcdn.com"

I feel like this is a pretty neat solution, as if our CDN URL was to change, we can simply replace it here and the change would roll out site-wide. We can also choose not to serve from a CDN in a given environment.

So how can we use this? Let’s say that we have an asset field called image.

{{ assets:image }}
<img src="{{ env:CDN }}/{{ path }}">
{{ /assets:image }}

Now if you inspect the image, you should see you’re being served the image over the CDN zone we set up 🎉

Bonus points

There are two further enhancements we can easily make to improve this set up. First up, we probably don’t want to serve our assets from an ugly URL that has nothing to do with your domain. KeyCDN lets us set up Zonealiases to solve exactly this problem. You’ll need to set up a CNAME record with your DNS provider. For example, you may want to set up a CNAME such as:

cdn.yourdomain.com 120 IN CNAME <yourzonename>-cbbe.kxcdn.com

Once the record is in place:

  1. Navigate to Zonealiases within the KeyCDN dashboard and click Add Zonealias
  2. Add your alias, such as cdn.yourdomain.comand select the zone we made earlier
  3. You’ll need to wait a a short while for this to take effect, around 3–5 minutes in my experience
  4. Once you see your images appear under cdn.your-domain.com/your-imnage.jpg you’re good to go

The final piece of the puzzle is to serve everything via https, which you will likely be doing for the rest of your site. Thankfully, KeyCDN has you covered and offers Let’s Encrypt certificates zones.

  1. Navigate to your zone and click Manage and then Edit
  2. Check Show Advanced Features
  3. Scroll down to SSL and select letsencrypt
  4. You’ll probably also want to set Force SSL to enabled
  5. Save the changes then navigate back over to Zonealiases
  6. Click edit on your zonealias, don’t change anything, then click Save. This will reconfigure your alias to be served over https
  7. Give it another 3–5 minutes to do its thing then try hitting one of your images again.

Bingo 🔥

--

--