Deploying a Ghost blog using Capistrano

I absolutely love Capistrano, I use it almost every day, so when I had to choose a deploy tool for this blog, the choice was obvious.
Luckily, someone had already made a gem that greatly helps with the deploy of a node.js application, so I didn't have to figure out everything on my own.


For this tutorial there are three prerequisites:

  1. The files of your Ghost blog already are under version control, I will use git but feel free to use something else as long as it's supported by Capistrano.

  2. You have ssh access and sudo privileges to the machine where you will be deploying your blog.

  3. You have Ruby, RubyGems and Bundler installed on your local machine (if you don't, there's plenty of tutorials around the web, just use Google).

The juicy part

Ok, let's begin!

First, you will need to create a Gemfile with the following content:

source ''
gem 'capistrano', '~> 2.15.5'
gem 'capistrano-node-deploy', '~> 1.2.11'
gem 'capistrano_rsync_with_remote_cache', '~> 2.4.0'
gem 'capistrano-shared_file', '~> 0.1.3'

Then, from your local machine's terminal, run:

user@local-machine:~$ bundler install (you may need sudo privileges depending on your RubyGems setup)

Now that you have Capistrano along with some other very useful gem installed, you need to tell Capistrano how it should deploy your project. To do that, you need to create a Capfile in the root directory of your project containing the following:

require "capistrano/node-deploy"
require "capistrano/shared_file"

set :application, "blog"
set :user, "remote-user"
set :deploy_to, "/remote/path/to/ghost"

set :node_user, "remote-user"
set :node_env, "production"

set :scm, :git
set :repository,  ""
set :deploy_via, :rsync_with_remote_cache

role :app, ""

set :shared_files,    ["config.js"]
set :shared_children, ["content/data", "content/images"]

set :keep_releases, 5

namespace :deploy do
  task :mkdir_shared do
    run "cd #{shared_path} && mkdir -p data images files"

after "deploy:create_symlink", "deploy:mkdir_shared"

Adjust the above configuration to match your specific settings and needs and then you will be able launch the first deploy of your blog by running this simple command from your terminal:

user@local-machine:~$ cap deploy

Capistrano using the above configuration will:

  1. Fetch the latest files from the branch master from the git repository and copy them to a hidden folder under your project's root (.rsync_cache).

  2. Rsync the files from the newly created .rsync_cache folder to your remote server using the user remote-user (it will also create the standard Capistrano folder structure in the process).

  3. Create the symlinks for config.js and the data and images directories making them point to the shared folder under /remote/path/to/ghost. This is needed to retain the config, the db (if you are using SQLite) and the uploaded images between deploys that would otherwise be completely overwritten every time you deploy a new version of your blog.

  4. Create an upstart script under /etc/init/ that will be used to start/stop the node application.

  5. Start the node application using the upstart script just created.

Since this is the first time you deploy your blog, you will need to manually copy your config.js and your ghost.db file on the remote machine under the shared folder; to do that, you can use scp like this:

user@local-machine:~$ scp config.js [email protected]:/remote/path/to/ghost/shared/files

user@local-machine:~$ scp content/data/ghost.db [email protected]:/remote/path/to/ghost/shared/data

If you are using a SQLite database make sure to modify your production config.js to match the new location of the config file (the shared folder). Here's how:

database: {
    client: 'sqlite3',
    connection: {
        filename: path.join(__dirname, '/../data/ghost.db')
    debug: false

Rolling back

One of the main advantages of using Capistrano to deploy an application is that you can roll back a deploy that breaks something in production with the same ease of deploying a new version:

user@local-machine:~$ cap deploy:rollback

The number of previous versions that you can rollback to depends on the set :keep_releases, 5 setting in your Capfile (in this case you will be able to issue the rollback command up to 4 times).

Wrapping up

You should now have a solid deploy process that lets you focus on coding instead of making you worry about breaking something in production at every manual deploy. Enjoy!