Suggested Approach for "Remote" Images?

For performance/storage reasons, I want to store and host page images on a different server than Kirby is running on. (In my case, Kirby will be hosted on Google App Engine, but images will live a Google Cloud Storage bucket.)

Does anyone have recommendations on the most “Kirby”-like way to handle images like this. I actually need Kirby/PHP to do little work, because Google Cloud Storage (GCS) handles image/thumbnail resizing itself.

Obviously, when I use images, I could just link to the image URL manually, but I would like to be able to use Kirby methods like ->images() as if the images were stored directly in the filesystem.

I would still like to be able to have metadata files stored in Kirby, but they essentially would refer to “remote” images.

Is there a way to have metadata files that actually refer to remote images and convince Kirby that these images “exist”?

The image URLs from GCS will be served from a Google-owned domain and the URL will be not resemble a traditional filename (it’s either a hash of something or random).

I haven’t done this before, but I think the images will have to “live” in your kirby content folder anyway.

For performance reasons, you can plug in your installation into a CDN or something. There is already a plugin for that: https://github.com/getkirby-plugins/cdn-plugin.

Kirby objects are tied to their storage as actual files in the system. You wouldn’t be able to use Kirby’s API to access these files, or their meta data. In fact, adding meta data files that don’t belong to an actual file name would break the system (because Kirby would probably try to use such a file as the content file).

I think you would have a hard time adding files to your content anyway, because you could neither drag and drop them into your content nor would you be able to select them. You’d be limited to adding absolute URLs into your content files.

Are you stuck with Googles cloud bucket? I would suggest switching to Cloudinary, because a quick look at the website suggests they do support meta data and other information.

With the CDN plugin and creating some custom kirby tags to manipulate the images, I think you can get what you want.

I think you can also store metadata for object in Google cloud storage, that shouldn’t be a problem. And of course you can write a plugin that lets you access this data and all information related to an object in those buckets. But you still wouldn’t be able to use something like $page->images() unless you overwrite these methods in page models that return a list of URLs instead. Still, that wouldn’t give you the information stored in an image object in the Kirby file system.

I guess I should have clarified … I meant that the same result could be achieved except the images, metadata etc are stored on cloudinary, so you would need to use their API to spit the images out rather then Kirbies helpers. As @texnixe says, this would mean writing a plugin or kirby tags to fetch and manipulate the data.

@jimbobrjames Yes, but I don’t understand the advantage of Cloudinary over GCS, they also have an API that you can use to access the objects and their meta data etc.

Oh, it was just that the API looked much more powerful & flexible to me, from the examples in the docs. It was built specifically for images, where as i think GCS is more general storage.

:slight_smile:

Anyway, no matter what sort of external storage you use, you will be facing the same challenges and would have to write a plugin to manage these in Kirby. There is no way to write meta data files for non existing (as in not in the file system) images.

The easiest way is to store your images in the page/site object and then use a CDN to serve your images as already suggested by @bvdputte, even though it means that you need storage space and performance right on the web server.

Thanks for the all the advice. I think I’ll go with just uploading the image assets directly to the Kirby server. My initial hesitation were a few reasons:

  • I wanted my /content/ folder to be under version control, but didn’t want to bloat the Git repo with image assets.
  • The “free” storage space for all Google App Engine instances is 1GB (collectively), which is more than enough for us to start with, but I worry we’ll hit his eventually. (In comparison, Google Cloud Storage includes 5GB.)
  • Updating Google App Engine sometimes requires uploading all files from scratch (this is rare, as GAE is usually smart enough to only upload the differences) but I wanted to avoid issues where I’m re-uploading all image attachments.

However, the usefulness of having assets show up normally in the panel outweighs these concerns. The cost of surplus storage is negligible for the convenience.

In terms of CDN, we’d be using Cloudflare, so I think we should okay. (If I stick with Google Cloud Storage, it’d be multi-regional storage and could not be CDN’d by Cloudflare.)

Yep, definitely (and some more characters).

But, I just realized one annoying issue: I won’t be able to take advantage of GCS’s live-resizing and I cannot use Kirby’s resizing in production. Google App Engine prohibits write-access to the filesystem.

How can you use the Panel then?

We would only use the Panel on a staging server (not on GAE). When we push to GAE, it’d essentially be a read-only snapshot of what staging had.

Then I guess you have two options:

You can ignore *.jpg or *.png etc in git if you want…

Definitely, but that doesn’t make sense if you push a snapshot from staging to production?

Why would it bloat the repo anyway? How many images are we talking about? I have a few sites that total anything up to 500mb due to lots of images. Git and Kirby handles it just fine.

If the individual files are large (several megabytes or more), an option is Git LFS. I’ve not used it personally, but it was built for this very problem.

Side question:

How did you set up your yaml for GAE? I want to use it as well, but how can I get it to work with dynamic content such as /projects/porjects-ID. Right everything except for the index is broken. Not even /projects works. Example:

runtime: php55
api_version: 1

handlers:

# Static files
- url: /dist/
  static_dir: dist
- url: /assets/
  static_dir: assets
- url: /img/
  static_dir: img
- url: /js/
  static_dir: js
- url: /vendor/
  static_dir: vendor
- url: /content/
  static_dir: content

# Everything else to PHP
- url: /
  script: index.php
- url: /about.php
  script: about.php
- url: /careers.php
  script: careers.php
- url: /projects
  script: projects
- url: /blog
  script: blog