Deploying Ghost on Openshift

Index

  • Introduction
    • Ghost
    • Openshift
  • Let's do it
    • Install with Openshift Hub
    • Install as a node module
  • Use your own domain
  • Security
  • Conclusion

Introduction

Ghost

Ghost is just a blogging platform, as they claimed officially. Their design philosophy is similar to Medium. Only the minimum essential features is provided to allow bloggers to focus on the content. Unlike most other blogging platforms, the backend of Ghost is powered by Node.js.

Openshift

Openshift is a cloud application platform hosted by Red Hat. It supports most popular programming platforms and databases, including Node.js and MongoDB. The free plan offers three small basic gears which can be used to create up to three web applications.

Let's do it

Ghost supports a few ways to deploy the application on Openshift. We will go through the two of them in this article.

  1. Install with Openshift Hub
  2. Install as a node module

Method 1 is magical. Installation is done in just a few clicks. If you are interested in the details, follow me when we work on Method 2.

1. Install with Openshift Hub

This is the easiest way to install Ghost. Only some basic technical knowledge is needed and is suitable for beginners.

Step 1

Find the newest version of Ghost on Openshift Hub.

Step 2

Deploy Ghost by clicking Deploy.

Step 3

Give the application a name. When choosing the database, pick the one which you are more familiar with. It is just the same for Ghost. But it shall make a difference if you add custom plugins.

Step 4

Create Application and wait for a...few...seconds......or...minutes...

Step 5

Yeah! Your blog is live. Visit it at <app>-<domain>.rhcloud.com. Don't forget to set it up at <app>-<domain>.rhcloud.com/ghost. Enjoy :)

Note:
If you want to customize or configure the blog (e.g. theme, custom URL, etc), you have to clone the git repository from Openshift. Remember to git commit and git push the changes after configuration. Openshift will handle the rest for you.

2. Install as a node module

It works like a charm installing Ghost with Openshift Hub. We will install without any installer this time to see what happens behind the scene. Basic knowledge of Git and Node.js will help you understand better.

Prerequisite
Step 1

Click Add Application on the application page of Openshift.

Step 2

Choose the Node.js cartridge. On the create application page, you need to complete the public URL. Other fields can be left as default. Click Create Application to continue.

Step 3

Add a database cartridge on the Application Overview page. Picking MySQL or PostgreSQL depends on which you think is more handy.

Step 4

Initialize an empty project with Git locally.

$ mkdir <your-desired-location> && cd <your-desired-location>
$ git init
$ git remote add origin <your-openshift-application-repo>

The <your-openshift-application-repo> could be found on the Application Overview page.

Step 5

Create a .gitignore and commit it. I usually use this for my node projects.

$ git add .gitignore
$ git commit -m 'Initial commit'
Step 6

Initialize a node project.

$ npm init
$ npm install ghost --save

The above commands will generate a package.json like this:

{
  "name": "MyGhostBlog",
  "version": "0.0.1",
  "description": "Have fun!",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Tim Wong",
  "license": "ISC",
  "dependencies": {
    "ghost": "^0.5.10"
  }
}
Step 7

Copy the themes from Ghost.

$ mkdir content && mkdir content/themes
$ cp -R node_modules/ghost/content/themes content/themes
Step 8

Create a config.js from Ghost's example.

$ cp node_modules/ghost/config.example.js config.js
Step 9

Configure the production environment in config.js as follow.

...
    production: {
        url: 'http://' + process.env.OPENSHIFT_APP_DNS,
        mail: {},
        database: {
            client: 'pg',
            connection: {
                host     : process.env.OPENSHIFT_POSTGRESQL_DB_HOST,
                port     : process.env.OPENSHIFT_POSTGRESQL_DB_PORT,
                user     : process.env.OPENSHIFT_POSTGRESQL_DB_USERNAME,
                password : process.env.OPENSHIFT_POSTGRESQL_DB_PASSWORD,
                database : process.env.OPENSHIFT_APP_NAME,
                charset  : 'utf8'
            }
        },
        server: {
            host: process.env.OPENSHIFT_NODEJS_IP,
            port: process.env.OPENSHIFT_NODEJS_PORT
        },
        paths: {
            contentPath: path.join(__dirname, '/content/')
        }
        ...
    }
...

The database setting above is for PostgreSQL. Replace database as below if you use MySQL.

    database: {
        client: 'mysql',
        connection: {
            host     : process.env.OPENSHIFT_MYSQL_DB_HOST,
            port     : process.env.OPENSHIFT_MYSQL_DB_PORT,
            user     : process.env.OPENSHIFT_MYSQL_DB_USERNAME,
            password : process.env.OPENSHIFT_MYSQL_DB_PASSWORD,
            database : process.env.OPENSHIFT_APP_NAME,
            charset  : 'utf8'
        }
    }

You could see that we use process.env.* to define all the configuration. It is actually the environment variables defined when Node starts. Here is a reference to Openshift pre-defined environment variables.

Step 10

Set up index.js, which should share the same name for main of package.json.

var path = require('path');
var ghost = require('ghost');

ghost({
    config: path.join(__dirname, 'config.js')
}).then(function(ghostServer) {
    ghostServer.start();
});

It configures the ghost server with config.js and launches the blog.

Step 11

The blog has been setup completely upon this stage. We could save the changes now.

$ git add --all
$ git commit -m 'Ghost Setup'

However, the blog is not deployed properly if you push the changes to Openshift at this moment. Two more steps is required to configure the environment on Openshift.

  1. Setup an environment variable to tell Node that we are using the production configuration.
  2. Setup symbolic links to Openshift's persistent data folder. Otherwise, some data will be lost once you make a new deployment.
Step 12

Setup NODE_ENV to specify we are production.
We need to create pre_start_nodejs and pre_restart_nodejs action hooks in the .openshift/action_hooks folder. They will export NODE_ENV=production for us whenever the blog is (re)started.
The chmod command is to ensure the hooks are executable.

$ mkdir .openshift
$ mkdir .openshift/action_hooks
$ touch .openshift/action_hooks/pre_start_nodejs
$ touch .openshift/action_hooks/pre_restart_nodejs
$ chmod +x .openshift/action_hooks/pre_start_nodejs
$ chmod +x .openshift/action_hooks/pre_restart_nodejs

The content for both hooks should be:

#!/bin/bash
echo "Exporting Node Environment (production)"
export NODE_ENV=production
Step 13

Next, we need to link up the content folder with Openshift's persistent data folder.

$ touch .openshift/action_hooks/deploy
$ chmod +x .openshift/action_hooks/deploy

The content should be:

#!/bin/bash 
if [ ! -d "$OPENSHIFT_DATA_DIR/content/data" ]; then
  echo "Creating persistent Ghost data directory on Openshift"
  mkdir -p $OPENSHIFT_DATA_DIR/content/data
fi
if [ ! -d "$OPENSHIFT_DATA_DIR/content/images" ]; then
  echo "Creating persistent Ghost images directory on Openshift"
  mkdir -p $OPENSHIFT_DATA_DIR/content/images
fi
echo "Symlinking the persistent Ghost data directory on Openshift"
rm -rf $OPENSHIFT_REPO_DIR/content/data
ln -sf $OPENSHIFT_DATA_DIR/content/data $OPENSHIFT_REPO_DIR/content/data
echo "Symlinking the persistent Ghost images directory on Openshift"
rm -rf $OPENSHIFT_REPO_DIR/content/images
ln -sf $OPENSHIFT_DATA_DIR/content/images $OPENSHIFT_REPO_DIR/content/images
Step 14

Save the action hooks.

$ git add --all
$ git commit -m 'Openshift Configuration'
Step 15

We can deploy our app onto Openshift finally!

$ git push -f

The -f is required because we are overwriting the sample Node project provided by Openshift. Deployment will be done when the master branch is pushed to Openshift. They will install all the dependency for us automatically.

Step 16

Done! Visit your blog at <app>-<domain>.rhcloud.com. Don't forget to set it up at <app>-<domain>.rhcloud.com/ghost. Phew :o

Let me know if you have problems with any of the steps. It's sooo complicated.

Use your own domain

Step 1

You can follow the instruction here to specify a custom domain for your Ghost on Openshift.

Step 2

Open config.js, replace the url of production with your custom URL (http(s)://your-domain.com)

Step 3

git commit and git push the changes to Openshift.

Security

You can always access your blog with the default Openshift URL over the https protocol. However, you cannot set up the secure protocol for your own domain because Openshift Online's free plan does not support custom SSL certificate.

Fortunately, it should be safe enough to secure the connection only when you login the admin panel. You can give http://myblog.com to friends while managing the blog at https://myblog.rhcloud.com/ghost.

Ghost supports redirecting the admin panel to secure login natively, by simply adding the following two settings into config.js.

urlSSL: 'https://' + process.env.OPENSHIFT_APP_DNS    // `https://myblog.rhcloud.com`
forceAdminSSL: true    // redirect the admin panel to use the secure URL

Conclusion

I love Ghost because of its simplicity. What is sacrificed on the other hand is the flexibility for customization. You shall find it hard to add some fancy features for now. Hopefully, plugins (apps) are supported very soon. Just try out different platforms and find the best writing environment for you. Cheers!

Read also...

  1. How to upgrade self-installed Ghost
  2. Installing the OpenShift Client Tools