Ghost is a new blogging platform launched 14 October 2013. It's funded by kickstarter and runs completely on node.js. Today i will show you how to setup Ghost with Phusion Passenger on Nginx. Passenger makes it easy to manage your ruby, python and node.js applications, it has a nice list of features which are listed here.


To make this all work you need the following things. Each of them has their own installation guide which is pretty easy to follow.

A Linux server####

This has been tested to work on Debian 7 Wheezy 64bits. But should work on a lot of other distributions too. In the setup guides there are specific instructions for each distro.


On Debian it's advised to compile from source and build your own package. That means you will be getting the latest node.js. When installing node it will also install the Node Package Manager, so you don't have to install this separately. To install check the Node installation instructions for your specific distro.

Phusion Passenger + Nginx####

Since passenger integrates with nginx it has it's own nginx package which contains nginx 1.4.3 stable + passenger module. The installation instructions can be found here


Many distro's have the directory for the web at /var/www/. However since web applications can be made in a many programming languages today, we will make a directory just for node applications in /var/node/ with a directory /var/node/blog. In there we make the passenger directory structure together with a directory to place the actual ghost files in. This is the resulting directory structure:

/var/node/blog/app.js (empty file for now)

Make sure to set the right permissions on all four. By default on many distro's you can use www-data user and group, but you can set any other user and group if you like. Running as root is not recommended for security reasons. Passenger will automatically check the owner of app.js and launch a new process as this user.

To change ownership:

chown www-data:www-data app.js
chown -R www-data:www-data public
chown -R www-data:www-data tmp
chown -R www-data:www-data ghost


The Nginx main configuration is fairly simple just uncomment passenger_root and passenger_ruby. If you are on debian create a new file in /etc/nginx/sites-enabled with any name but i suggest If you don't like separate files per virtual host you can also put everything in nginx.conf. The last bit of the configuration is to make a server block looking like this:

server {
        root /var/node/blog/public;
        passenger_enabled on;

Now make a symlink to active the configuration

cd /etc/nginx/sites-enabled
ln -s ../sites-available/ .

Setting environment variables

Here is an example of setting environment variables. This one shows you how to set the NODE_ENV variable which you have to set to production in case your have an older passenger version (for sure that would be 4.0.21)

server {
        passenger_set_cgi_param NODE_ENV production;

Or globally in your nginx config

env NODE_ENV=production;

Making Ghost passenger compatible###

UPDATE 11-12-2013:
Since passenger version 4.0.25 a fixed directory/files layout is no longer required

Ghost does not make use of the Passenger directory structure and it's advantages. Especially the public directory has a special purpose since it serves files directly from nginx instead of passing them to node. Also ghost will start with index.js but Passenger launches your app with app.js.


Let's make this compatible first. Edit your app.js and type:

require('./ghost/index.js'); // this starts ghost
process.chdir('./ghost'); // set the working directory to ghost

If you don't change the working directory ghost will have problems resolving relative paths correctly and loading your config.js

public directory####

Ghost seems to load public files from two directories. The ghost/core/server/shared directory and the ghost/content/themes/casper/assets directory of your theme. To serve them directly make symlinks from your public folder:

ln -s /var/node/blog/ghost/core/shared .
ln -s /var/node/blog/ghost/content/themes/casper/assets ./assets

You will have to remake these symlinks when you switch theme. Unfortunately there is no native Passenger integration yet. This could be scripted of course but I'm not too familiar with node.js.


You now should have your Ghost running on a very fast nginx server. Future installation of any ruby, python or node.js apps should be easy to manage and be secure along with your blog.

To check out the status of your running apps you can use passenger-memory-status.