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.

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.
- Apache: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
- Caddy: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy
- Traefik: https://community.traefik.io/t/traefik-as-reverse-proxy-server-to-external-web-server/15619/2
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/