Why we built our blog on Ghost?

Disclaimer: This is not a scary post!

The first thing that we did after revamping our web presence (find it here), is to look for a blogging platform to share our Insights with. We started with Jekyll, explored Middleman and decided to go with Ghost. Our love for open-source and new platforms led us to it.

Ghost is an open-source, lightweight publishing platform that just simply works. Moreover, it uses NodeJS, Ember.js and Handlebars under the hood that makes it incredibly faster than other platforms.

In this step-by-step tutorial I will describe what we did to get the blog up and running. We hope you find it useful. This was tested on a VPS instance w/ 2GB RAM that runs Ubuntu 16.04. Without further ado, let's get started.

Ghost installation and configuration

Download the latest version from the Github Repo of Ghost.

> curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip

Check your NodeJS version installed on the server and make sure its supported by Ghost. The list of supported versions can be found here. In case, you don't have supported NodeJS version, install it using npm and confirm the version by typing node -v in the terminal.

Unzip the downloaded package into your document root.
Ghost suggests you to use /var/www. We've chosen /var/www/html instead.

> sudo unzip -uo ghost.zip -d /var/www/html/ghost

In case, it complains that unzip isn't recognised, run sudo apt-get install unzip and try unzipping again. Once done, you can see ghost directory in the chosen document root.

Switch to the Ghost directory cd /var/www/html/ghost and install Ghost dependencies. Make sure you add --production to install only those dependencies that are required to run the blog. If not specified, it will default to development which installs a lot of modules that are required only if you want to contribute to Ghost development (which is also great if you are up for it).

To install dependencies, run

sudo npm install --production  

This will take some time as Ghost tries to install Node modules that are required. Make sure you have a decent internet connection and your firewall isn't blocking.

Once the installation is completed, its time to set up Ghost. Ghost's configuration file config.js is located in the root of your Ghost directory. If its not there already, run sudo cp config.example.js config.js and open the file for editing.

Locate the section for production (or for the environment of your interest) and change the url and mail directives. Here is a sample production section from config.js that uses SQLite3 as database and Mailgun to trigger emails. Before you wonder, you can use any email service provider of your choice. Look for the documentation here.

production: {  
        url: 'http://sub.domain.tld',
        mail: {
            transport: 'SMTP',
            options: {
              service: 'Mailgun',
              auth: {
                user: 'creds from Mailgun account',
                pass: 'creds from Mailgun account '
        database: {
            client: 'sqlite3',
            connection: {
                filename: path.join(__dirname, '/content/data/ghost.db')
            debug: false
       server: {
            host: '', //
            port: '2368'

Save the file after modifications and exit the editor. Its time to start Ghost and experience the awesomeness!

sudo npm start --production  
Nginx configuration

The above command starts Ghost in production environment on port 2368. Now, lets configure Nginx to proxy requests to Ghost. If you don't have Nginx already, install it and make sure it listens on port 80/443. You might have to stop Apache service if its already running on port 80/443. To get the list of ports in use, type sudo lsof -i -P -n | grep LISTEN.

Create a new file / edit an existing file in /etc/nginx/sites-available and add a server block. In case a new file is created, make sure you symlink the file from sites-enabled directory. Here is a sample server block that you can use.

server {  
    listen 80;
    listen [::]:80;
    server_name sub.domain.tld;

    location / {
        proxy_set_header Host $host;
        proxy_buffering off;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Save the file after modifications and exit the editor. This will allow connections on port 80 to connect through to the port that Ghost is running on. Test Nginx configuration for any syntax errors using sudo nginx -t. Reload the configuration file using sudo nginx -s reload. Restart Nginx using sudo service nginx restart.

Lets create a separate user account to run Ghost, mainly to improve security, and make the user as owner of Ghost directory.

> sudo adduser --shell /bin/bash --gecos 'Ghost application' ghost
> sudo chown -R ghost:ghost /var/www/html/ghost/

# Log in as the ghost user and try to run Ghost
> su - ghost
> cd /var/www/html/ghost
> npm start --production

If you've survived till here, you can access your Ghost blog using http://sub.domain.tld. That leaves us with one last step - to run Ghost as a background service so that it restarts when system restarts. We will use init script to achieve that. Type the command below to get a woking init script.

> sudo curl https://raw.githubusercontent.com/TryGhost/Ghost-Config/master/init.d/ghost -o /etc/init.d/ghost

Open the file and change GHOST_ROOT to match your Ghost directory. DAEMON must match the output of which node. Change the execution permission for init script by typing

> sudo chmod 755 /etc/init.d/ghost

Now you are good to control Ghost as a service using sudo service ghost restart. To start Ghost at system start, type

> sudo update-rc.d ghost defaults
> sudo update-rc.d ghost enable

That's it!
Restart Ghost server and Enjoy blogging! :)

What's Next?

Now that your blog is up and running, here are few things that you might want to do next.

  • Access content interface of Ghost using http://sub.domain.tld/ghost. Complete the signup process and login.
  • Invite team members to manage the content and users of your publishing platform.
  • Play around with the settings to configure Ghost platform.
  • Change the default theme of Ghost with that of your choice.
  • Add comment thread (eg: Disqus) and web analytics (eg: Google Analytics) scripts to your blog posts.

Please share this post, in case you liked it.

Ghost Node JS Publishing Open-source Tech

Sandeep Guduru

10 years of designing developing and maintaining solutions that solve business problems. "Ship it out fast and keep on improving" is what i follow.

Hyderabad, India

Subscribe to Gleecus Insights

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!