How to set up Ghost correctly on Ubuntu...
with nginx proxying, correct permissions, and running forever

First off, let me start by saying that Ghost is very simple software, with a ton of hype around it.

After 2 years of development and a foundation around it, with paid hosting plans, Ghost still...

  • doesn't let you install themes via the UI
  • has no plugin architecture
  • can't queue/schedule posts
  • doesn't make it intuitive to upload images
  • can't self-update
  • doesn't have galleries, custom post types, and the many other features that Wordpress does.

On the other hand, there's enormous enthusiasm around Ghost, so let's wait and see.

Installing Ghost on Ubuntu properly

The official guides for installing Ghost on Ubuntu neglect to mention that the recommended configuration is to have nginx proxy Ghost. Other guides just don't work.

This guide will teach you how to

  • set up Ghost to serve your blog at a specific path, e.g.
  • use nginx with Ghost (the recommended setup)
  • run Ghost forever even after you reboot (let alone log out)

So let's get started. This assumes an Ubuntu blank installation. If you're still logged in as root, you can omit the sudo in front of every command.

# May get failures to find package repos without this
sudo apt-get update

# Enable the add-apt-repository command
sudo aptitude install -y python-software-properties

# Add Node.js repository
curl -sL | sudo bash -

# Add nginx repository
sudo add-apt-repository ppa:nginx/stable -y

# Latest stable git
sudo add-apt-repository ppa:git-core/ppa -y

sudo apt-get update
sudo apt-get upgrade -y
sudo aptitude install -y zip wget git-core mc nodejs nginx lynx
sudo npm install -g pm2

# Create `ghost` user
sudo adduser --shell /bin/bash --gecos 'Ghost application' ghost
sudo passwd ghost  # pick a password for your ghost user

sudo mkdir -p /var/www/ghost
cd /var/www/ghost
sudo chown -R ghost:ghost /var/www/ghost/

# log in as `ghost`:

su - ghost
unzip -d ghost
npm install --production
echo "export NODE_ENV=production" >> ~/.profile  # we'll use this later with pm2
npm start --production

We've launched Ghost. Verify in another shell that Ghost works: lynx http://localhost:2368. If that works, Ctrl+C the process, then run pm2 to prepare Ghost for running forever:

pm2 kill
pm2 start index.js --name ghost
pm2 dump

nginx proxying for Ghost

Now let's hook up nginx. Logout from the ghost user, then run sudo mcedit /etc/nginx/sites-enabled/default and after the location / block, add:

location /blog {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header HOST $http_host;


Save, then run sudo service nginx configtest && sudo service nginx restart.

Serving at the /blog path

Simply edit the Ghost configuration: sudo mcedit /var/www/ghost/config.js, and change the production -> url field to match your site, e.g. to

Running Ghost forever

We'll use pm2 (a much more capable tool than forever):

sudo pm2 startup <ubuntu|centos|amason> -u ghost

That's it. Test by running sudo reboot, then after a minute or so, navigating to

Extra tips

Adding themes

Adding themes is very simple:

  1. Make sure you're logged in as ghost
  2. Find your theme in the Marketplace
  3. If it's a free theme, you'll end up at its GitHub page
    1. Copy the HTTPS URL of the theme (the one in the URL bar will work)
    2. cd /var/www/ghost/content/themes
    3. git clone <
    4. pm2 restart ghost
  4. If you don't load the theme from somewhere else, just make sure to unpack it in /var/www/ghost/content/themes.
My tags:
Popular tags: