How to deploy Ghost v1.x on Heroku for free

Bergé Greg
Smooth Code
Published in
4 min readAug 28, 2017

Ghost is a very popular blog platform that supports Markdown. It is very powerful and easy to use. This article will give you the keys to deploy it quickly and for free on Heroku.

The Ghost blog platform logo.

1. Create a new application on Heroku

The first step is signing up for Heroku. If you are familiar with Heroku, just go to the next step, else you can follow this quick start guide.

2. Downloading Ghost

As I am writing this article, the last version of Ghost is v1.7.1.

$ unzip ~/Downloads/Ghost-1.7.1.zip -d ~/projects/my-blog
$ cd ~/projects/my-blog

3. Create a Heroku application

Since Heroku deployment is based on git, we have to create a git repository to host Ghost source code.

To initialize a new git repository, use these commands in your project directory:

$ git init
$ git add -A
$ git commit -m 'Initialize repository'

Next we will set-up the application using heroku-cli. If you do not have heroku-cli installed on your machine, follow this guide: https://devcenter.heroku.com/articles/heroku-cli.

First we create an application, replace “my-blog” by the name of your blog.

$ heroku create my-blogCreating ⬢ my-blog... done
https://my-blog.herokuapp.com/ | https://git.heroku.com/my-blog.git

We can now deploy our blog on Heroku.

$ git push heroku masterReleased v13
https://my-blog.herokuapp.com/ deployed to Heroku

Even if the deployment was successful, your blog is not functional yet. A major element is still missing: the database.

4. Install mySQL

Ghost database is mySQL, to make it work on Heroku, you have to choose a mySQL provider. I am not an expert but ClearDB sounds like a good choice. Let’s add the mySQL add-on to our application:

$ heroku addons:create cleardb:igniteCreating cleardb:ignite on ⬢ my-blog... free
Created cleardb-aerodynamic-72322 as CLEARDB_DATABASE_URL
Use heroku addons:docs cleardb to view documentation

The add-on is now installed but it is still not used by our Ghost application. We must set up database credentials using heroku config:

First, get credentials of your database:

$ heroku config:get CLEARDB_DATABASE_URLmysql://b74638b58e8fff:dc944939@us-cdbr-iron-east-05.cleardb.net/heroku_6a6045b8e83395b?reconnect=true

You should get something like that, the format of the url is : “mysql://user:password@host/database?reconnect=true”

Second, using heroku config:set, configure each part of the url:

$ heroku config:set \
database__connection__user=b74638b58e8fff \
database__connection__password=dc944939 \
database__connection__host=us-cdbr-iron-east-05.cleardb.net \
database__connection__database=heroku_6a6045b8e83395b
Setting database__connection__user, database__connection__password, database__connection__host, database__connection__database and restarting ⬢ my-blog... done, v4
database__connection__database: heroku_6a6045b8e83395b
database__connection__host: us-cdbr-iron-east-05.cleardb.net
database__connection__password: dc944939
database__connection__user: b74638b58e8fff

Unfortunately the free tier of ClearDB does not allow us a lot of connections. We can set the connections to 2 max, enough for a small website:

$ heroku config:set database__pool__max=2

You database connection is now configured, but database is still empty. We must initialize it using heroku run.

$ heroku run "knex-migrator init"Running knex-migrator init on ⬢ my-blog... up, run.3926 (Free)
[2017-08-28 13:47:59] INFO Creating table: posts
[2017-08-28 13:47:59] INFO Creating table: users
[2017-08-28 13:47:59] INFO Creating table: roles
[2017-08-28 13:47:59] INFO Creating table: roles_users
[2017-08-28 13:47:59] INFO Creating table: permissions
[2017-08-28 13:47:59] INFO Creating table: permissions_users
[2017-08-28 13:47:59] INFO Creating table: permissions_roles
[2017-08-28 13:47:59] INFO Creating table: permissions_apps
[2017-08-28 13:48:00] INFO Creating table: settings
[2017-08-28 13:48:00] INFO Creating table: tags
[2017-08-28 13:48:00] INFO Creating table: posts_tags
[2017-08-28 13:48:00] INFO Creating table: apps
[2017-08-28 13:48:00] INFO Creating table: app_settings
[2017-08-28 13:48:00] INFO Creating table: app_fields
[2017-08-28 13:48:00] INFO Creating table: clients
[2017-08-28 13:48:00] INFO Creating table: client_trusted_domains
[2017-08-28 13:48:00] INFO Creating table: accesstokens
[2017-08-28 13:48:00] INFO Creating table: refreshtokens
[2017-08-28 13:48:00] INFO Creating table: subscribers
[2017-08-28 13:48:00] INFO Creating table: invites
[2017-08-28 13:48:01] INFO Creating table: brute
[2017-08-28 13:48:01] INFO Model: Post
[2017-08-28 13:48:01] INFO Model: Tag
[2017-08-28 13:48:01] INFO Model: Client
[2017-08-28 13:48:02] INFO Model: Role
[2017-08-28 13:48:02] INFO Model: Permission
[2017-08-28 13:48:03] INFO Model: User
[2017-08-28 13:48:03] INFO Relation: Role to Permission
[2017-08-28 13:48:04] INFO Relation: Post to Tag
[2017-08-28 13:48:04] INFO Relation: User to Role
[2017-08-28 13:48:04] INFO Finished database init!

If you see “Finished database init!” it is good. Do not panic if command is not responding. Just terminate it manually (control + C).

5. Configure server

We have to change the host binding, the default is “127.0.0.1” but using Heroku we have to set it to “0.0.0.0”.

$ heroku config:set server__host=0.0.0.0

We can also set up our blog url:

$ heroku config:set url=https://my-blog.herokuapp.com

On Heroku, the web application port is dynamic and provided in “PORT” environment variable by Heroku.

In Ghost, we have to set up the application port using “server__port” environment variable.

To make an alias between “PORT” and “server__port” we create a “.profile” at the root of our application.

$ echo "export server__port=\$PORT npm start" > .profile
$ git add .profile
$ git commit -m 'Add .profile'
$ git push heroku master

Your blog is now ready, enjoy!

--

--