It's possible to send your publication's images to a 3rd party service, CDN or database using a custom storage module.

Overview

The storage layer is used to store images from an upload admin UI, from the API, and also when images are included in a zip file uploaded to the importer. Using a custom storage module allows you to change where images are stored without changing Ghost core.

Using a custom storage adapter

By default Ghost stores images on your filesystem. The default location is the Ghost content path in your Ghost folder under content/images, or an alternative custom content path that you have configured.

In order to use a custom storage adapter, your custom configuration file needs to be updated to provide config for your new storage module and set it as active:

storage: {
    active: 'my-module',
    'my-module': {
        key: 'abcdef'
    }
}

The storage block should have 2 items:

  • An active key, which contains the name* of your module
  • A key which reflects the name* of your module, containing any config your module needs

Available custom storage adapters

Creating a custom storage adapter

In order to replace the storage module, use these requirements. You can also take a look at our default local storage implementation.

Location

  1. Create a new folder named storage inside content/adapters
  2. Inside of content/adapters/storage create a file or a folder: content/adapters/storage/my-module.js or content/adapters/storage/my-module - if using a folder, create a file called index.js inside it

Base adapter class inheritance

A custom storage adapter must inherit from your base storage adapter. By default the Base Storage Adapter is installed by Ghost and should be available in your custom adapter.

'use strict';

var BaseAdapter = require('ghost-storage-base');

class MyCustomAdapter extends BaseAdapter{
  constructor() {
    super();
  }
}

module.exports = MyCustomAdapter;

Required methods

Your custom storage adapter must implement five required functions:

  • save - The .save() method stores the image and returns a promise which resolves the path from which the image should be requested in future.
  • exists - Used by the base storage adapter to check whether a file exists or not
  • serve - Ghost calls .serve() as part of its middleware stack, and mounts the returned function as the middleware for serving images
  • delete
  • read
'use strict';

var BaseAdapter = require('ghost-storage-base');

class MyCustomAdapter extends BaseAdapter{
  constructor() {
    super();
  }
  
  exists() {

  }

  save() {

  }

  serve() {
    return function customServe(req, res, next) {
      next();
    }
  }

  delete() {

  }

  read() {

  }
}

module.exports = MyCustomAdapter;

Summary

You have discovered how to use a custom storage module to replace the storage layer which handles images with custom code.

It's good practise to create a public GitHub repository to make your module available for others and you can share your new module in our forum.