Installing Ghost and Nginx on Ubuntu 16.04

By Jon Leopard on 17 Jan, 2017

Here’s a guide on installing Ghost on a Ubuntu 16.04 LTS VPS.


  • A cloud provider such as Digital Ocean or AWS
  • Node (NVM)
  • PM2 or Forever (to keep it running background).

Before starting, make sure you are operating as a non-root user with sudo privileges.

NVM (Node Version Manager) is a neat tool for installing and managing multiple versions of node.

Lets first grab some handy tools, NVM will need them.

$ sudo apt-get install build-essential libssl-dev

Now we can use NVM’s install script using cURL. If you don’t have cURL installed, do so now:

$ sudo apt-get install curl
$ curl -o- | bash

I encountered a small issue with this script:

=> Profile not found. Tried (as defined in $PROFILE), ~/.bashrc, ~/.bash_profile, ~/.zshrc, and ~/.profile.
=> Create one of them and run this script again
=> Create it (touch ) and run this script again

So I checked if I had this file:

$ cat ~/.profile

Turns out one didn’t exist, so I ran:

$ touch ~/.profile

I then re-ran the script and then everything went fine. After its finished, open a new shell and reconnect to your server. Type "nvm" and you should see the CLI now.

Ghost tells us which versions of Node it’s happy with, you can view that list here:

I’ll be installing node v4.4.7

$ nvm install 4.4.7

Now check that node and npm are installed correctly:

$ node -v
$ npm -v

So, now we can get to installing ghost!

$ sudo mkdir -p /var/www/
$ cd /var/www/
$ sudo wget

Now lets unzip that file into a directory called ghost:

$ sudo apt-get install unzip
$ sudo unzip -d ghost
$ cd ghost/

Now run npm to install:

$ sudo npm install --production

We now need to go in the config file and change some settings. config.js likely doesn’t exist yet in the directory, so lets go ahead and make one using the default variables found in config.example.js

$ sudo cp config.example.js config.js

Update the URL value to represent your domain name. If you are using mailgun, you can configure that in this file as well.

var path = require('path'),
config = {
    // ### Production
    // When running Ghost in the wild, use the   production environment
    // Configure your URL and mail settings here
    production: {
        url: '',
        mail: {
            // Your mail settings
        database: {
            client: 'sqlite3',
            connection: {
                filename: path.join(__dirname, '/content/data/ghost.db')
            debug: false
        server: {
            // Host to be passed to node's `net.Server#listen()`
            host: '',
            // Port to be passed to node's `net.Server#listen()`, for iisnode s$
            port: '2368'

Save the file and exit. While still in the /var/www/ghost directory, start Ghost with the following command:

$ sudo npm start --production

You should now be able to access your blog using port 2368 Now push ctrl + c to shut it down. We are now going to install nginx.

$ sudo apt-get install nginx

CD into the directoy and remove the default file:

$ cd /etc/nginx/
$ sudo rm sites-enabled/default

Create a new file in /etc/nginx/sites-available/ and call it ghost. Then open with nano:

$ sudo touch /etc/nginx/sites-available/ghost
$ sudo nano /etc/nginx/sites-available/ghost

Now copy and paste this snippet. Replace your_domain.tld with the value of your sites domain name.

server {
    listen 80;
    server_name your_domain.tld;
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;

symlink the configuration in sites-enabled:

$ sudo ln -s /etc/nginx/sites-available/ghost /etc/nginx/sites-enabled/ghost

grant privileges:

$ sudo chown -R ghost:ghost /var/www/ghost/

Now cd into the directory and start ghost again:

$ cd /var/www/ghost
$ npm start --production

Now lets set up and configure PM2

$ npm install pm2@latest -g

We should install completion while we are at it:

$ pm2 completion install

I came into an error here, PM2 said it couldn’t find my .bashrc file. I looked in my root directory for one, and it didn’t exist. So I created a fresh one like so:

$ nano .bashrc

Save and exit, then: /bin/cp /etc/skel/.bashrc ~/

Run this after:

$ source ~/.bashrc

CD back into your ghost directory and:

$ pm2 completion install
$ NODE_ENV=production pm2 start index.js --name "ghost"
$ pm2 save

Logrotation would be nice to have, lets add it:

$ pm2 install pm2-logrotate
$ pm2 set pm2-logrotate:retain 7
$ pm2 save
$ pm2 list

Almost there, lets make sure that PM2 starts up on reboot:

$ pm2 startup

PM2 will return a message like this one: You have to run this command as root. Execute the following command:

sudo su -c "env PATH=$PATH:/home/ghost/.nvm/versions/node/v4.4.7/bin pm2 startup linux -u ghost --hp /home/ghost"

Eventually I’d like to migrate to a more robust DB such as Postgre SQL. More on that another time.