Load assets from your own domain with Storyblok and nginx

How to add a custom asset domain to a Storyblok website without additional cloud services, using a regular web server.

Load assets from your own domain with Storyblok and nginx

Storyblok is an easy to understand and to work with CMS. It comes with a Digital Asset Management, and a powerful Image Optimisation API. For daily use on your website, there is only one small problem with this: the domain for the assets points to a.storyblok.com. Not everyone is happy with that, you might want to load assets from your own domain.

Why

There are a bunch of tutorials on how to set up your own asset domain with Amazon CloudFront or Azure or Google Cloud - but there is a much easier way. Especially when you don’t want to add into Infrastructure or you are not a customer of any of those services this alternative can be quite interesting.

The setup

Chances are, when you operate a website, you have a web server running*. My personal preference is nginx, but that is to everyone for themselves to decide. As I know nginx better than the alternatives, I will give a quick example on how to achieve this.

The way you do it is that you set up a reverse proxy, as such:

proxy_cache_path /var/www/asset_cache levels=1:2 keys_zone=asset-cache:500m inactive=60m;

server {
        listen   443 ssl http2;

        server_name assets.mydomain.tld;
        root /var/www/html;

        # adapt this to your SSL config
        ssl_certificate /etc/letsencrypt/assets.mydomain.tld/fullchain.cer;
        ssl_certificate_key /etc/letsencrypt/assets.mydomain.tld/assets.mydomain.tld.key;
        ssl_protocols TLSv1.3;

        location / {
                proxy_ssl_server_name on;
                proxy_cache asset-cache;
                proxy_pass https://a.storyblok.com;
                proxy_pass_request_headers on;
                add_header X-Cache-Status $upstream_cache_status;
        }
}

And that’s it.

In your front end, add a helper to rewrite the asset URL such as this

function transformImageSrc(src) {
   const url = new URL(src);
   if (url.hostname === "a.storyblok.com") {
       url.hostname = "assets.mydomain.tld";
   }
   return url.href;
}

(From the Storyblok Documentation)

Congratulations, you’ve just set up your own asset domain – but using this setup we can even dial it one bit further. What if we you want to load images from a folder like “/assets/”? The answer is: the setup needs to change only slightly:

proxy_cache_path /var/www/asset_cache levels=1:2 keys_zone=asset-cache:500m inactive=60m;

server {
        listen   443 ssl http2;

        server_name www.mydomain.tld;
        root /var/www/html;

        # all your normal webserver configuration

        location /assets {
                proxy_ssl_server_name on;
                proxy_cache asset-cache;
                proxy_pass https://a.storyblok.com;
                proxy_pass_request_headers on;
                add_header X-Cache-Status $upstream_cache_status;
        }
}

And in the frontend change your helper to

function transformImageSrc(src) {
   const url = new URL(src);
   if (url.hostname === "a.storyblok.com") {
       url.hostname = "www.mydomain.tld/assets";
   }
   return url.href;
}

Tada.

You might want to play around a little with different parameters and settings, the documentation for nginx reverse proxy can be found here: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/

Other web servers

Other web servers also allow you to set up reverse proxies. I haven't tested it, so your mileage may vary.

If you have anything to add or correct - reach out on Mastodon (@gurkendoktor@mastodon.cloud)


* If don’t have one because you run your site on e.g Netlify, there might still be a way to set up a proxy. For Netlify, this is described here: https://docs.netlify.com/routing/redirects/rewrites-proxies/