Ghost on Debian with Nginx as a reverse proxy

I finally came around to trying out Ghost and I’m loving it. So much that I switched my old Jekyll website over to Ghost. I used a small Ruby script to convert my Markdown files to a JSON file that Ghost can use to import my posts. Here’s a quick tutorial how to install NodeJS and Ghost and use Nginx as a reverse proxy.

Install dependencies

We’ll need NPM and unzip to extract Ghost and prepare it’s dependencies.

apt-get install unzip npm

After all that’s done we can install NodeJS. Nodesource provides an excellent Debian repository for NodeJS packages. Add it to your sources.list or create a new file in /etc/apt/sources.list.d/.

deb wheezy main
deb-src wheezy main

We can now install NodeJS

apt-get install nodejs

You should be able to execute nodejs and run a few commands.

	> .help
	.break  Sometimes you get stuck, this gets you out
	.clear  Alias for .break
	.exit   Exit the repl
	.help   Show repl options
	.load   Load JS from a file into the REPL session
	.save   Save all evaluated commands in this REPL session to a file

Install Ghost

We will create a user for Ghost to run as and download the latest version.

adduser ghost
su - ghost

Prepare Ghost dependencies:

npm install --production

Don’t forget to change the blog address:

vim config.js

Install Forever

You should use Forever in order to automatically restart Ghost on changes or when it crashes.

As root:

npm install -g forever

Now we can start Ghost with it’s own user:

NODE_ENV=production forever start index.js

To stop the Forever process that’s keeping Ghost online you can list all processes and kill the ID.

forever list
forever stop <ID>

Nginx reverse proxy

server {
    listen         80;
    server_name <your-blog-address>;
    root /home/ghost/;
    index index.php;

    if ($http_host != "<your-blog-address>") {
         rewrite ^ http://<your-blog-address>$request_uri permanent;

    location / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;

    location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
        access_log off;
        expires 30d;
        add_header Pragma public;
        add_header Cache-Control "public, mustrevalidate, proxy-revalidate";

    location = /robots.txt { access_log off; log_not_found off; }
    location = /favicon.ico { access_log off; log_not_found off; }

    location ~ /\.ht {
            deny all;

Test the configuration and reload Nginx

nginx -t && nginx -s reload

Your Ghost blog should now be online at http://<your-blog-address>.

Start Ghost with Forever on boot

It’s a bit of a hack but I’ve put the following in rc.local in order to let Forever run Ghost on boot:

su ghost -c 'cd /home/ghost/; NODE_ENV=production forever start index.js'