Deploying Ghost on Engine Yard

Over the past few years a few new blog systems have been released which aim to bring simplicity back to blogging. One of these is Ghost, which got a huge amount of attention with it’s amazingly successful Kickstarter campaign in 2013.

If you wanna move your blog to Ghost or wanna start a new one, carry on reading. Follow these steps and you’ll have a Ghost blog running on Engine Yard in a jiffy.

Clone

Before deploy Ghost, we will fork it on GitHub. This way we can add custom themes and deploy hooks. In case you are not familiar with forking a project, go to the Ghost repository and press the Fork button on the top-right of the page. If you don’t have an account yet it’ll lead you through the steps of creating one.

You should end up with a new fork in your account. Next, we clone the repository to our local machine to prepare it for deployment via git clone and create a new branch. We’ll use this for deployment specific changes.

git clone git@github.com:bastilian/Ghost.git
cd Ghost

Ghost recommends you use the stable branch rather than master production.

So, let’s create a branch based on stable:

git checkout stable
git checkout -b 'deploy'

Environment Setup

Now let’s setup the application and environment on Engine Yard.

Go to your Engine Yard dashboard and create a new application. Ghost is a Node.js based, which we’ll select as the Application Language when creating the application. If you have connected your GitHub account to Engine Yard you can search for the Ghost repository in the Git Repository URI field or you can just paste in the URL we used to clone it locally.

After you’ve chosen a name (I named mine “ghost”) and made sure that “stable-v4 2.0” is selected as the Stack and “PostgreSQL 9.3.x” as the Database, press the Create Application button. You’ll be shown the deployment key. You’ll need to add this to GitHub if you’ve made your fork private.

Now, let’s choose to boot this environment with a Single instance. To be able to deploy to an environment that has multiple application instances, we’ll need to add support for S3 to Ghost. I’ll explain this in a later post for those who’d like to be able to scale their blog.

Deployment Setup

While the environment is booting up, let’s add some stuff needed for Ghost to run properly.

First, let’s make sure that the right version of Node.js is used. We accomplish this by adding a before_bundle.rb deploy hook in the deployment directory that contains the following:

# Set the system Node.js to 0.10.28
sudo "emerge -n =net-libs/nodejs-0.10.28"
sudo "eselect nodejs set 0.10.28"
sudo "ln -nfs /opt/nodejs/0.10.28 /opt/nodejs/current"
sudo "npm install -g npm@2.7.0"
sudo "npm install -g grunt-cli"

This will install version 0.10.28 of the Node.js package and make this version the default to be used on your instance. It will also update npm, install Grunt and Bower, which are used to build assets. We will also need another deployment hook to build the assets for Ghost’s admin interface. Let’s do this with this one-liner in deploy/before_symlink.rb:

run "cd #{config.release_path}; bower install; grunt init; grunt prod"

Ghost also requires a configuration file named config.js. We can use this to add sensitive information that we don’t want to add to our repository. This will be put directly onto our instance for us, so it an be be symlinked with each deployment.

For convenience I put the following default configuration into a gist:

var path = require('path'),
    config;

config = {
    production: {
        url: 'http://my-ghost-blog.com',
        mail: {},
        database: {
          client: 'pg',
          connection: {
              host     : process.env.DB_HOST,
              user     : process.env.DB_USER,
              password : process.env.DB_PASSWORD,
              database : 'ghost',
              charset  : 'utf8'
          }
        },

        server: {
            host: '127.0.0.1',
            port: process.env.PORT
        }
    },
};

module.exports = config;

Since I created this as a gist, I can log into my instance and grab it via wget.

To do the same, run ey ssh (make sure you have the engineyard gem installed) in the working directory for your Ghost blog. This will log you into the application master where you can execute the following to put the config file in place:

cd /data/APP_NAME/shared/config
wget http://goo.gl/UZhmRM # shortened for display!

Note: make sure that the database name in the configuration matches your application name.

When config.js is in place we just need to add the symlinking step to our deploy hook. We’ll do this by adding the following to the already existing before_bundle.rb:

sudo "ln -nfs #{config.shared_path}/config/config.js #{config.release_path}/config.js"
sudo "ln -nfs #{config.release_path}/index.js #{config.release_path}/app.js"

The second line is creating a link to index.js named app.js, as Engine Yard is looking for app.js to start rather than index.js.

Deploying

We have every deploy hook required now, and can commit and push our changes to GitHub and deploy it to Engine Yard afterwards.

To do so, run the following:

git add deploy
git commit -m 'add deploy hooks for Ghost to run on Engine Yard'
git push origin deploy

Your code is now on GitHub and you can deploy it by running ey deploy -r deploy from the Ghost directory on your machine.

If everything was successful you can use ey launch to open your blog in the browser. Hopefully, you should see a default Ghost installation. If that is the case you can head to the admin panel by adding /ghost to the URL and you will be presented with a signup screen to create your first user.

Fill out the fields, hit Submit and you’ll be taken right to the dashboard where you can add, edit, publish, unpublish, and delete your posts.

Voilà! Ghost running on Engine Yard.

P.S. Did you try this out? How did you find the process? Was it the first time you deployed to Engine Yard? Let us know what you thought in the comments.

About Sebastian Gräßl

Sebastian Gräßl, also known as bastilian on most social networks, enjoys listening to various kinds of music, either through his headphones or better yet, live. He also works as an Application Support Engineer at Engine Yard.