Self hosting a Ghost Blog on Debian

A guide to installing Ghost blog on Debian 6 (squeeze) and reverse proxying behind Apache HTTP Server.

Why Ghost?

If you have ever published a blog you will be familiar with the popular services available to you such as WordPress, Blogger, Tumblr, SquareSpace, Typepad and many more. Much has been written about these platforms so I will not cover old ground but suffice to say that when deciding which blogging software to use these were the main candidates I looked at. My checklist of features was simple and short, boiling down to the platform being:

  • Easy to host myself
  • Preferably Free
  • Simple and intuitive to edit content within

Not a particularly pressing list yet none of the services ticked all the boxes. WordPress cannot be classed as easy to host yourself by any stretch of the imagination, Blogger and Tumblr can't be hosted on your own kit and SquareSpace and Typepad do not offer free versions. So I guess I'd have to compromise....

Well no, there is a new kid on the block and from my first impressions it could make a very big mark in the blogosphere. Ghost has just become available to the public after a beta phase open to the backers of its very successful Kickstarter funding campaign and I can tell you it ticked all my boxes and is well worth a try.

As you will see from the remainder of this post Ghost is very simple to install, run and maintain, it’s free and uses Markdown in a simple split screen editor for content creation - perfect. Ghost doesn't just pass my checklist; its strength is how it puts the content to the forefront without the bells and whistles that feel like a distraction when using some other platforms.

Installing Ghost

I will now go through the steps I went through to install and get Ghost running on Debian 6 (squeeze).

1. Get node and NPM

Debian squeeze does not have a dpkg package available for Ghost yet so you will need to download node and build from source.

Get build dependencies for Debian

Firstly you will need to ensure you have all the tools available on your Debian machine to build the node source:

> su
  password: ************
> apt-get update
> apt-get upgrade
> apt-get install curl build-essential

You should now have a system capable of building node from source so lets get the source from the github repository.

Get node.js from Github and build

node.js source is available from GitHub so go ahead and clone the repository:

> cd /tmp
> git clone https://github.com/joyent/node.git

You can now determine the latest node.js distribution is available usig the git tag command and checkout the version you wish to build. At the time of writing the latest tag is v0.11.7 but I chose to install version v0.10.9 due to several issues when trying to build the latest on Debian Squeeze:

> cd node/
> git tag
> git checkout v0.10.9

Build the source, which will take some time, after which you can check the versions of node and npm installed:

> ./configure && make && make install
> node -v
> npm -v

Tidy up /tmp:

> rm -r /tmp/node

2. Get and install Ghost

Now we are ready to install Ghost!

Setup the directory structure

The first task is to create the directory structure you are going to host your Ghost install(s) on. As host my company website on Apache I decided to run Ghost behind a Apache Reverse Proxy, therefore I'm using a directory structure familiar to Apache users - /var/www/ghost/[your site name]/. Commands below (still as the root user):

> cd /var/www
> mkdir ghost
> cd ghost/
> mkdir [your site name]
> cd [your site name]/
> mkdir htdocs
> mkdir logs

Create a ghost user to run Ghost

It is best to run Ghost as its own users so lets create the ghost user which is done on Debian by running the addUser command. addUser will walk you through the steps of creating the user including setting a password and by default will create a home directory and group for the user (still running as root):

> addUser ghost

After creating the ghost user set the file permissions of the files under your ghost directory (/var/www/ghost) to be owned by ghost:ghost:

> chown -R ghost:ghost /var/www/ghost/

Get Ghost

Now we can get the latest version of Ghost and place it in our company blog directory under /var/www/ghost/blog.apericore/htdocs. The latest version of Ghost (currently version 0.3.3) can be found on the ghost.org site:

> su ghost
> cd /var/www/ghost/blog.apericore/htdocs
> wget https://en.ghost.org/zip/ghost-0.3.3.zip
> unzip ghost-0.3.3.zip
> rm ghost-0.3.3.zip

Install Ghost using npm install (as root):

> su
> password: ***********
> cd /var/www/ghost/blog.apericore/htdocs
> npm install --production

This process will run a little while before completing the install of Ghost. If you receive an error around SQLite (as I did) you may need to install it from source and rerun the Ghost install as shown below (still as the root user):

> npm install sqlite3 --build-from-source
> npm install --production

You now have a ghost install, update the config.js file to name your blog correctly and update the port if you wish. Now you can start it up:

> su ghost
> vi config.js # update blog address and port if you wish
> npm start --production

By default Ghost will now be running on port 2368 and you can check it by launching http://yoursite:2368.

3. Running Ghost behind Apache as a reverse proxy

As I host my company website on Apache I'm running Ghost behind it via reverse proxy. Here is how I set that up.

Block the Ghost port from the outside world via iptables

Add the following 2 rules to your iptables configuration:

> iptables -A INPUT -p tcp -s localhost --dport 2368 -j ACCEPT
> iptables -A INPUT -p tcp --dport 2368 -j DROP

Alternatively you can edit the iptables rules in /etc and import them using iptables-restore (as root):

> cd /etc
> vi iptables.up.rules 
> iptables-restore < iptables.up.rules

Ensure your updates have been made by running:

> iptables -L

Configure the reverse proxy in Apache

Firstly you will need to ensure that you have the required Apache modules enabled to allow configuration of the proxy:

> su
> *********
> a2enmod proxy proxy_http
> /etc/inid.d/apache2 restart

Now create the virtual host under /etc/apache2/sites-available:

> cd /etc/apache2/sites-available
> vi blog.apericore

The contents of the virtual host file are:

<VirtualHost *:80>
    ServerAdmin admin@apericore.com
    ServerName blog.apericore.com
    ServerAlias blog.apericore.org
    DocumentRoot /var/www/ghost/blog.apericore/htdocs/

    # LogFiles
    ErrorLog /var/www/ghost/blog.apericore/logs/error.log
    CustomLog /var/www/ghost/blog.apericore/logs/access.log combined

    ProxyRequests Off
    ProxyPass / http://127.0.0.1:2368/
    ProxyPassReverse / http://127.0.0.1:2368/
    ProxyPreserveHost On
    <Proxy *>
        Order deny,allow
        Allow from 127.0.0.1
    </Proxy>

</VirtualHost>

Apache will now pass any request to blog.apericore.com or blog.apericore.org to the local Ghost blog install running on port 2368.

Restart or reload Apache to let the settings take affect:

> /etc/init.d/apache2 restart

4. Configure your Ghost blog to run as a daemon

You have a number of options to run Ghost as a daemon process on Debian such as creating your own init.d scripts, installing supervisor or using the Forever node package. I decided to go with Forever:

> su
> **********
> npm install -g forever

Now you can start your Ghost instance under the control of Forever (remember to start it as the ghost user we created earlier):

> su ghost
> cd /var/www/ghost/blog.apericore/htdocs/
> NODE_ENV=production forever start index.js

Conclusion

A ghost blog instance is now running on my Debian server and can be accessed via http://blog.apericore.com after a relatively painless installation process.

You can now set up your blog admin user id by routing to http://blog.apericore.com/ghost/signup and entering the email and password required. In my next post I'll detail how you can run ghost over https.

Get blogging.