Enhancing Ghost.js with Cloudant on IBM codename: BlueMix

Share this post:

As a followup to my last post for deploying Ghost.js on IBM codename:BlueMix, I would like to share a follow-up technique which utilizes a Cloudant CouchDB instance as a persistent image datastore.


Why would I want to do that?

My earlier post generated a healthy amount of comments and inquiry for overcoming the ephemeral nature of file storage that exists in most Platform As a Service technologies, which includes Cloud Foundry and BlueMix. Briefly, BlueMix applications are typically given an ephemeral file system and isolated from read/write access to any persistent disk. The Cloud Foundry community recommends that applications avoid writing to the local file system. [Reference] Some reasons for this include:

  • Local file system storage is short-lived. When apps crash, stop or are restarted, resources can be reclaimed by the platform.
  • Instances of the same app do not share a local file system. Each app runs in its own container. If you scale up instances, both instances will not have access to the same file system.

This creates an interesting quandry. Ghost.js rocks! BlueMix can rapidly deploy, host and scale up a Ghost.js instance, which is awesome! But, BlueMix uses an ephemeral file storage and most bloggers will not tolerate being constrained to using images defined by URI only nor being constantly hassled with having to go upload local image files to some other place. [As an interesting aside: Ghost.js provides a configuration option named filestorage to eliminate the local file upload scenario entirely and be more compatible with PaaS environments]

Enter Cloudant. Let’s exploit BlueMix’s composeable service model to quickly attach a Cloudant CouchDB instance to our deployed Ghost.js app. A couple of BlueMix UI clicks and a quick Cloudant account create should be the elixir to our ills 🙂 I considered MongoDB’s GridFS capability as well, but settled on Cloudant because of its stellar dashboard management and responsive performance as a proven commercial solution. After 5 mins of clicking – well, that also includes one quick email and an instant message, the next chore was to empower Ghost.js to leverage this storage resource. I copied the localfilesystem module and created a new one called cloudant.js. I dutifully tweaked the save and exists functions to interact with Cloudant using the simple, but solid, Nano Node.js package. This resulted in a user experience where I can upload local files into my BlueMix Ghost.js deployment, while having Ghost.js be smart enough to subsequently go and create a representative Cloudant document and attachment which it will then exploit as a linked image resource. Sweet! Ghost.js now always uses URI defined image sources and the user experience remains intact for uploading local files without additional end-user hassle.

If this has piqued your interest, give it a try. You’ll love the results. Here’s how …

  1. Download the latest
  2. Unzip the download (e.g. unzip and change to the base directory (e.g. ghost-0.6.4)
  3. Clone a copy of this git repository and copy the content within the files folder into the root of your ghost installation directory. You will replace two (2) new files (package.json and core/server/storage/index.js), delete one (1) file (npm-shrinkwrap.json), add four (4) new files (config.js, manifest.yml, manifest.cfg and core/server/storage/cloudant.js) and modify one (1) file (core/server/api/upload.js) to the default Ghost.js installation to enable its use.
  4. Open the core/server/api/upload.js and edit line #44
    from:  return Promise.promisify(fs.unlink)(filepath);<br />to: return Promise.promisify(function(){return true});

    Reason: While the local files are temporarily stored on the local filesystem, our new CloudantFileStore actually tells Ghost a url that is an HTTP URL which we’ve generated on-the-fly via a binary attachment into Cloudant. Unlinking is unnecessary and these tmp files will be destroyed during app future app re-staging/restart as a victim of the ephemeral storage paradigm.

  5. Update the name, host and services entries within the manifest.yml to match your deployment environment. The service entries for both the MySQL and Cloudant Service instance names are totally up to you.
  6. Using the BlueMix Web UI, login to BlueMix, and create two (2) back-end database service instances (MySQL and Cloudant) that matches your manifest.yml entries.
    IMPORTANT: When creating the Cloudant Service Instance, the url field should be in the format of <your_cloudant_username> . Your database can be named anything and your username/password will be whatever was used when setting up your Cloudant account. Be sure to alter your image store database permissions so that reader access is granted to everyone. This is easily done by clicking on the DB within the Cloudant dashboard, then clicking on the Docs dropdown button and choosing permissions. Click the Reader checkbox for the Everybody Else category. A database will automatically be located or created with the format <app_name>-ghost-images for use by Ghost.js during application startup. Permissions are automatically set for Everyone on the database to have read access.
  7. Navigate to the root of the Ghost.js installation directory. Using the cloud foundry v6 cli, login to BlueMix and deploy Ghost.js.
    #Step 0: cf login -a 
    <b>$ cf login -a</b>
    # Step 1: CF_STAGING_TIMEOUT=4 CF_STARTUP_TIMEOUT=4 cf push -s cflinuxfs2
    # CF_STAGING_TIME : Max wait time for app instance startup, in minutes
    # CF_STARTUP_TIMEOUT : Max wait time for app instance startup, in minutes
    # -s : Establishes the stack to use as Trusty Ubuntu 14.04<br /># ENV variables are suggested to accommodate longer staging and startup times.
    <b>$ CF_STAGING_TIMEOUT=4 CF_STARTUP_TIMEOUT=4 cf push -s cflinuxfs2</b>
  8. If all goes well, you should have a running Ghost.js blogging platform. Browse and setup your user. Then visit: <your_app_name> .


There are two (2) ways to embed an image and there are at least two places where images are used within Ghost.js.

  1. Place #1: Settings. You can click on the upload image buttons for a blog cover and blog logo. You will see a little chain-link icon in the bottom left. That toggles the UI from being a file upload to a direct url link to the image. Feel free to give both ways a try, but the Cloudant tweak affects only the local file upload flow. After uploading an image and saving, you can verify if the tweak is working by using the browsers “inspect element” context menu. This should show an image that has a source using a cloudant url pointing to your account. In theory, this should never go away if the account remains in good standing and you never delete the database or document.
  2. Place #2: Content. You can embed an image using the markdown syntax ![alt text](url to image). If you simply type ![an inspiring image of earth] … you will see a familiar image uploader dialog in the preview that can be clicked. Same options hold true, direct web url or local file upload. Same technique to verify if its using Cloudant.

Running Example can be seen @

Cool. Happy Blogging!

Add Comment

Leave a Reply

Your email address will not be published.Required fields are marked *

John W. Williams

My name is John and I am a user experience here at IBM. I actually work on the newer reporting solutions working their way through Rational right now…anyhow, I am in need of a fresh online portfolio and I have been wanting to try Ghost. I would also like to get everything up and running on Bluemix, if at all possible. I found you cool example and explanation of how you got it up and running and it looks like a feasible solution.

Unfortunately, I am not a dev per se and the whole Bluemix/web application deployment via cloud services thing is something I am just getting my head wrapped around…and this experiment with Bluemix strikes me as an ideal means to get my iron hot.

That said, everything seems rather clear to me. I have successfully deployed simple “Hey World” apps on BlueMix in the past. My issue here concerns some confusion over Cloudant and which account to use. I have a unique Cloudant account (the most basic, free version). I cannot figure out how to use this unique account to create my Cloudant service when using BlueMix…am I missing something or do you recommend I simply use the account that is auto-generated when I attempt to create a new service instance using Bluemix.

Also, are there any plans to make an auto deploy version of Ghost (similar to that found on OpenShift) for Bluemix? This would strike me as a awesome move in the “coolness” direction as Ghost seems to have quite a bit of momentum as a simple, fast blogging platform and many hosts seem to be struggling to get up to speed, for various reasons.

Any help would be appreciated…


    John W. Williams

    It may help if I clarify that I cannot find any means–when creating my Cloudant service–to change the URI to match myCloudantusernamecloudantcom. The app field, which I presume is the URI field you mention, is not editable.



Hi John,
While I wrote the article to leverage the built-in generated Cloudant account provided by the Bluemix service, there is no hard requirement to point to that. Take a look at: . These lines within the cloudant.js file (and used with Step 3) are what define the url to use with Cloudant. I’m dynamically reading the environment variable to grab the Bluemix service details … but you could comment/delete these lines and provide your own details in the form of a JSON string. Something like:

cloudantCreds = {
      "url": "",
      "database": "ghostimages",
      "username": "yourcloudantuser",
      "password": "yourcloudantpassword"

Hope this helps. Eager to hear how it goes.



I was playing around with this again today and I cannot get my app deployed. Here is what I see. Everything looks fine except the app will not start once the push has completed.

[quote]>cf push
Using manifest file C:UsersIBM_ADMINDocumentsGitHubjohnyux.mybluemix.netma

Updating app johnyux in org / space dev as

Using route
Uploading johnyux…
Uploading app files from: C:UsersIBM_ADMINDocumentsGitHubjohnyux.mybluemix.
Uploading 818K, 220 files
Binding service ClearDB MySQL Database-di to app johnyux in org
m / space dev as
Binding service Cloudant NoSQL DB-8c to app johnyux in org / s
pace dev as

Stopping app johnyux in org / space dev as
Starting app johnyux in org / space dev as
Server error, status code: 500, error code: 0, message:



    Hi John,
    Checkout my comment here. Specifically, I discovered a bug in my approach for using the manifest.yml as a config data source. I suspect that your app_url isn’t being populated correctly which causes a startup failure and an error during startup of a missing manifest.yml file relevant lines of code. Try

    cf logs appname --recent

    to see the errors. To resolve this … you can either hardcode your appurl info into the defined config.js variable OR create a copy of your manifest.yml (e.g. manifest.yml.cfg) and then modify to reflect this new file name.

    If you’re curious about why this happens: I think that CloudFoundry includes the manifest.yml file as an “ignoreable” file during pushes since in theory it is only supposed to be used to tell CF how to deploy and not tell the app how to run. It was a flaw in my thinking to use it.



I feared for long hours setting this up, but amazingly it took about 15 minutes.. thank you for that

Just one comment i had to remove ‘https://’ + from line 144 in your cloudant.js file .. as the service was already prepending this, so uploading images gave me http://
after removing this http:// is nicely worked



    @Guy – Awesome! Glad that it worked smoothly and more importantly – quickly. I’ve updated the git repo files to remove the prefixed ‘https://’ string for the benefit of others. Appreciate the feedback.



Awesome Sanjay. I will try this out using the new info and process you have documented. I gave up on my original exploration as I got sidetracked and slammed with work-related things.


[…] projects onto Bluemix. In past posts, I’ve shared how to deploy Drupal, WordPress, Ghost.js and Piwik. I’ve now turned my focus to Eve, a Python-based open source web REST API framework […]



Hi Sanjay,

Great job! I got my first blue mix up and running! But I got some erros;
Error: Cannot find module ‘intl’
Error: Cannot find module ‘intl-messageformat’
So added this 2 lines;
“intl”: “1.0.0”,
“intl-messageformat”: “1.1.0”,
to package.json file. Now it works!





    Hi Juan,
    Awesome! Glad you were able to get it deployed with minimal trouble. Thanks for the heads up. I’ve located the package.json commit that caused this here ( . In general, this will be an ongoing challenge to our repo since we’re maintaining a fork of the TryGhost project’s package.json. Feel free to send us a PR on our repo for updates to the package.json which include your mentioned changes and I’ll merge it in. Otherwise, I’ll try to make the tweak later this week. Thanks again for the feedback 🙂

More How-tos Stories

Build and deploy a MEAN stack application on IBM Cloud

MEAN is a collection of JavaScript-based technologies — MongoDB, Express.js, AngularJS, and Node.js — used to develop web applications. From the client and server sides to databases, MEAN is a full-stack development toolkit. This tutorial walks you through the creation of a web application using the popular MEAN stack. It is composed of a Mongo DB, Express web framework, Angular front-end framework and a Node.js runtime.

Continue reading

A hybrid Cordova mobile app with Push and Analytics in minutes

As promised while introducing "Tutorials to get your mobile development up and running", we are continuing our efforts to add more mobile solution tutorials. After quickly scaffolding a native iOS-Swift and Android mobile app with Push and Analytics, it's time to bring in the hybrid mobile app development flavor to the game with Cordova - Apache Cordova is an open-source mobile development framework. It allows you to use standard web technologies - HTML5, CSS3, and JavaScript for cross-platform development.

Continue reading

Use your own branded UI for user sign-in with App ID

With IBM Cloud App ID’s Cloud Directory feature, you can create a user registry, and add sign-up and email/password sign-in to your mobile or web app. Cloud Directory comes with a pre-built sign-in widget that you can use, or if you prefer to use your own branding, you can replace it with your own custom UI. This blog will show you how to use Cloud Directory APIs and add your own custom sign-in screen to an Android application. You can find the Android Cloud Land App on GitHub.

Continue reading