Installing Ghost using Nginx / Phusion Passenger on Ubuntu

This guide assumes you're using Ubuntu LTS version 14.04 (Trusty Thar). At the time of writing (October, 29th 2014), the latest version of Ubuntu is 14.10, however there are no Nginx / Passenger packages available.

Update: June 20th 2016

The normal version of Passenger works just fine these days. Updated again to reflect that.


Update: March 13th 2015

Passenger 5 was just released, which is great, but is not backwards compatible with Passenger 4, which this guide originally assumed you would be using.

If you have already installed following this guide, you need to change the followling line in passenger.lst




Before you install any updates to passenger or your blog will be frustratingly broken.

This guide has been updated to reflect these changes.

Install node

Since Ghost needs nodejs to run, we need to have that installed and running first. Assuming you're running as a user with access to sudo, you should run the following:

$  sudo apt-get update
$  sudo apt-get install nodejs nodejs-legacy npm

That's it! Node should be all set up and ready for you to use now.

We need to install the nodejs-legacy package in order for Passenger to be able to find the correct binary to use. You can, however skip this package and configure the node path manually for your host, following the instructions in the Nginx Passenger Manual.

Install Passenger

This part is mostly just straight out of the Nginx Passenger Manual. We're going to add Phusion's apt repository and get it all set up.

$  sudo apt-get install apt-transport-https ca-certificates
$  touch passenger.list
$  echo 'deb trusty main' > passenger.list
$  sudo mv passenger.list /etc/apt/sources.list.d/passenger.list
$  sudo apt-key adv --keyserver --recv-keys 561F9B9CAC40B2F7
$  sudo chown root: /etc/apt/sources.list.d/passenger.list
$  sudo chmod 600 /etc/apt/sources.list.d/passenger.list
$  sudo apt-get update

Phew! Now that's out the way, we need to install the packages.

$  sudo apt-get install nginx-extras passenger

You now need to open up /etc/nginx/nginx.conf in your favourite editor, find passenger_root and passenger_ruby and make sure you uncomment them.

Finally, restart the service, done!

$  sudo service nginx restart  

Installing Ghost

We need to do one or two wee things before we get Ghost installed. This part is a matter of personal preference, with regards to how you set up your server.

Essentially, you need to have a place to install ghost that confirms to Passenger's application guidelines.

I always put my webapps into /var/www/apps and the configuration for them into /var/www/conf, and access them as a unprivileged user, so I'll be assuming that in the following examples. You should replace the parts specific for your setup where required.

$  cd /var/www/apps
$  mkdir blog
$  cd blog
$  mkdir log public tmp
$  touch app.js

Now we need to actually install Ghost. We'll deal with app.js later, along with the directories we've created when we deal with the Passenger setup.

$  sudo apt-get install unzip
$  wget 
$  unzip -d ghost
$  cd ghost
$  sudo sudo npm install --production 

Configuring Ghost is the next step. To get you started quickly, I'll just give you the bare-minimum to get going, but you'll need to have a close look at the configuration file to set other options, like your mail server.

$  cp config.example.js config.js

Now, open up the file in your favourite editor. Find url: '', and replace it with the correct URL for your blog. Once you save it, you're done with the configuration for now.

Prepare the static assets paths

We want to make sure nginx serves the static assets for the blog. To do this, we need to symlink the shared assets for all of Ghost and the theme-specific assets into the public folder.

Again, I'll be using my /var/www/apps convention, so you need to make sure you use the correct path for you. Also, this assumes you are using the default Casper theme. If you are using another one, you should update the symlink.

$  cd /var/www/apps/blog/public
$  ln -s /var/www/apps/blog/ghost/content/themes/casper/assets assets
$  ln -s /var/www/apps/blog/ghost/core/shared shared

Write a minimal app.js

The app.js file is what Passenger runs to boot your node application (in this case, Ghost). It needs to know where the files for Ghost are and which application to serve.

Open in up in your favourite editor and, assuming you used the same paths as me, you'll want something that looks like the following:


Pretty simple, huh? We're almost done too.

Lastly, configure nginx for your blog

The last part is to tell nginx about Ghost so that it can serve it. Assuming you're using the same paths as me, you'll want to create in /var/www/conf using your favourite editor.

You'll want to create something like:

server {  
  root /var/www/apps/blog/public;
  passenger_enabled on;
  passenger_set_cgi_param NODE_ENV production;

It's really important to have passenger_enabled on; and passenger_set_cgi_param NODE_ENV production; as they make sure Passenger is running and is set up in the production environment.

Now, you just need to sudo service nginx restart and you should be good to go.


You should make sure you set your mail: {}, settings in config.js are pointing to a real mail server.