Installing Multiple Ghost Blogs Behind NGINX on Ubuntu 12.04

Ghost LogoLooking to set up a blog with Ghost? While it still has a few rough edges and missing features at the time of this writing, as it’s essentially in beta at this point (hence the “0.3” versioning), it definitely shows promise as a blogging platform.

If you’re reading this, you’re probably aware that you can’t just FTP Ghost to a dinky shared host and expect it to run like your average PHP script. Ghost is a Node.js application, which works differently, and has yet to be adopted by services that generally cater to newbies. You’re going to need a VPS and command line access. I’m also going to assume a rudimentary knowledge of Linux commands. (You can pick up the basics pretty easily at if need be.)

This tutorial aims to walk you through the process of installing one ore more instances of Ghost behind the NGINX server. NGINX is a fast and lightweight web server that, when configured in this manner, acts as a proxy, forwarding requests to the correct Ghost blog.


I’m a big fan of DigitalOcean. I’ve been hosting my various web sites with them since this June, and their service has been of excellent quality. In addition to their rock-bottom price, their virtual machines have performed well and their staff has been competent and helpful. (You can find my review of DigitalOcean here.)

$5/month will get you a “Droplet” with 512MB of RAM, 20GB of storage on a solid state drive and plenty of data transfer. (It’s a soft cap with reasonable overages. You’re very, very unlikely to ever reach it, though. Unless you’re a popular podcaster or something, in which case you should be looking into a CDN…)

The figure that’s the most important is the RAM. Just like with the computer you’re using to read this, active applications reside in the system’s memory, and the amount they use varies depending on what the app is doing. Ghost, in my informal tests, doesn’t seem to be too memory-intense. So a 512MB Droplet could probably host a few Ghost blogs at once, depending on their popularity and how the system is configured.

There are plenty of options for a VPS, though. If you’re not too keen on DigitalOcean, Linode, Rackspace, Amazon EC2 and RamNode are popular. If you want to give DigitalOcean a try, you can sign up with the promo code DIVEIN5 to get a $5 credit. You can also pay by the hour if you just want to fire up a VM for a few hours to experiment before making a decision.

Initial Setup

Once you’ve got your VPS, it’s time to start setting things up. For simplicity, I will assume you are running Ubuntu 12.04. You can follow along with any Linux distribution on any hosting provider, but some commands may be a little different.

First, if you haven’t already, use SSH to log in to your VM as root, using the password your host gave you. Take this opportunity to change your password to something different, and reasonably strong, for security. Just run the passwd command and follow the on-screen instructions.

Now let the system update its package index by running the following command:

apt-get update

While you’re at it, install the unzip tool so you can unpack the Ghost archive later on.

apt-get install unzip

Installing Node.js

Now we need to install Node.js, the JavaScript platform that Ghost is built on. Ubuntu’s pre-made package probably isn’t new enough to run Ghost, so we’ll have to compile it ourselves.

First, install the Linux build tools through Ubuntu’s package manager. This will install the necessary compilers, as well as the make tool.

apt-get install build-essential

Now you need to change to your home folder, make a new directory to contain the source, and download Node.js.

mkdir src
cd src

If you run ls, you should see the archive in the src directory. If the file was successfully downloaded, you can unpack the archive and change to the resulting directory.

tar -zxvf node-v0.10.21.tar.gz
cd node-v0.10.21

Ready to compile? After you run the next two commands, be prepared to wait 5-10 minutes while the system works its magic and converts raw source code into an executable binary.


Once the messages stop scrolling by and the command prompt returns, you just need to run the installer.

make install

Congratulations, you’ve successfully compiled and installed a program from source! To verify that everything worked properly, run node -v. It should output the Node.js version, which in this case is v0.10.21. (Or a greater version if there is a newer one out by the time you read this.)

Ghost Installation

The next step is to install a copy of Ghost for each of your blogs. First, let’s make a place for them to reside in.

mkdir /var/ghost
cd /var/ghost

If you intend to use an FTP client to make it easier to upload themes or such, /var/ghost is the place where your blogs’ files will be found. So it’s a good path to remember. (On a related note, the SSH process also doubles as a secure FTP server. If your FTP client supports SFTP, you can connect to the domain/IP and log in with a valid username and password.)

To add a copy of Ghost, just follow these steps:

mkdir myghostblog
cd myghostblog
npm install --production

What you’re doing is:

  1. Creating a folder for the blog
  2. Changing to that folder
  3. Downloading Ghost
  4. Unzipping Ghost
  5. Removing the .zip file
  6. Installing Ghost

Before we can actually start Ghost up, there is some essential configuration that needs to be adjusted.

Copy the example configuration file to a new config.js file with cp config.example.js config.js. Open the config.js file in the nano text editor with nano config.js. Use the arrow keys to scroll down to where the “production” environment starts in the config. It looks something like this:

production: {
    url: '',
    mail: {},
    database: {
        client: 'sqlite3',
        connection: {
            filename: path.join(__dirname, '/content/data/ghost.db')
        debug: false
    server: {
        host: '',
        port: '2368'

There are three things you need to change:

  1. The url field. Replace with
  2. The port field in the server block may need to be changed, depending on whether this is the first blog you’re setting up or not.

To save the file, press control+o and, then control+x to exit.

Web browsers, by default, connect to HTTP port 80 when requesting a web page. The way we’re setting this up, NGINX will listen on port 80, waiting for requests, and forward them to the ports your Ghost blogs are listening on. So Blog A can listen on port 2368 and Blog B can listen on port 2369. NGINX will listen on port 80, figure out which domain name belongs to which blog, and route the requests to the appropriate port.

Repeat the relevant steps in this section to set up additional blogs. You can wait until after you’ve finished setting up the first, if you want.


We need to make it easy to start and stop the Ghost processes, and ensure that they come back online automatically if the server is restarted. On Ubuntu, it’s super simple with a system known as Upstart.

First, create a new Upstart configuration file called ghost.conf.

cd /etc/init
nano ghost.conf

Now fill it with the following Upstart script, replacing myghostblog with the directory you created for your blog:

start on startup

    cd /var/ghost/myghostblog
    npm start --production
end script

If you have multiple Ghost blogs set up, you would do something like this:

start on startup

    cd /var/ghost/myghostblog
    npm start --production
    cd /var/ghost/myotherghostblog
    npm start --production
end script

NGINX Installation

apt-get install nginx

That was easy, wasn’t it?

NGINX Configuration

NGINX keeps its site configuration files in two directories within /etc/nginx:

  • sites-available — Each site gets its own configuration file in here
  • sites-enabled — This directory contains symbolic links pointing to the files in sites-available.

Let’s create a new site configuration for myghostblog.

cd /etc/nginx/sites-available
nano myghostblog

A simple configuration that does nothing but pass traffic addressed to to the Ghost blog listening on port 2368 looks like this:

server {

    location / {

Of course, NGINX is a powerful and flexible piece of software that is capable of a lot more. This is just one of many things you can use it for.

As before, save the file by pressing control+o and quit nano with control+x. Next, move back up one directory level to /etc/nginx and create a symbolic link in sites-enabled, pointing to the file in sites-available.

cd ../
ln -s sites-available/myghostblog sites-enabled/myghostblog

Fire it Up

Now that you have everything configured, you can start (or stop) the processes with the service command.

service ghost start
service nginx start

You can replace start with stop to exit ghost or nginx if you have reason to do so, or restart if you need to reload one after making some sort of change. (e.g. editing Ghost’s config.js file requires that Ghost be restarted.) NGINX can reload its config files without doing a full restart of the process with service nginx reload, which takes less time and is useful when making edits.

If all went well, you should be able to open your Ghost blog in a browser.

Managing Memory

How much memory is Ghost using, you may wonder. And if you aren’t, you probably should. The enemy of performance on web servers is swapping, which is where the system runs out of available RAM and starts copying things back and forth to the hard disk, causing major slowdowns. This is frequently referred to as “thrashing.” Even a fast solid state drive is orders of magnitude slower than RAM.

There are some useful tools for monitoring available RAM and inspecting active processes. The most commonly used ones are free, top, and ps.

The free command shows the system’s memory totals. If you run it with the m flag (free -m) to show the values in human-readable megabytes instead of plain bytes, you should see something like this:

root@DeepSpaceNine:~$ free -m
             total       used       free     shared    buffers     cached
Mem:           369        129        239          0         11         51
-/+ buffers/cache:         67        302
Swap:          767          0        767

The most important line is the one labeled -/+ buffers/cache. Modern operating systems don’t waste memory. If nothing else is making use of it, the OS will make use of it until the space is needed. The -/+ line shows the usage sans caches. In this example, there are 302MB of free memory with only 67 being in use. There is also nothing in swap, which is exactly what you want to see.

The top command shows a live-updated table of currently running processes, and statistics for them. By default, it’s sorted by CPU activity, but you can sort by memory usage by pressing shift+M.

The top command

Pressing control+C exits top.

Need to see a list of all running processes? Run ps aux. Be prepared for a huge list, as it will be full of system processes.


I hope this guide helps you get started with Ghost. I realize it is a bit technical, something the upcoming hosted service and DigitalOcean’s one-click Ghost image should help obviate, but hey, it’s new. It was harder to get up an running with WordPress back in 2003, too.

  • Michael Sheils

    Should the default file still be in /etc/nginx/sites-available? Because when I start both ghost & nginx and point my browser to my domain all I get is the welcome to nginx landing page.

    • Michael Sheils

      Found the issue, had to change the ip address in the config.js from to

  • Hospity

    Awesome Ideas. Thanks for sharing.. Great

  • Madhuri Agarwal

    Hii matt, as i am looking for the same to installing multiple ghost blogs behind NGINX on Ubuntu and here the perfect ans..! thanks Gold Tips