How to Setup a Blog with Ghost

Create a user for the blog to run under

$ adduser --shell /bin/bash --gecos 'Blog' blog

Deploy the blog to its own folder under /var/www

$ cd
$ wget https://ghost.org/zip/ghost-latest.zip
$ unzip -q ghost-latest.zip -d blog/ && rm ghost-latest.zip
$ mv blog/ /var/www/ && cd /var/www/ && chown -R blog:blog blog/
$ mv blog/config.example.js blog/config.js

Edit the /var/www/blog/config.js file to correctly set up the various options for the blog, including:

  • config.production.url to set the URL for the blog service, for example http://example.com.
  • config.production.mail to set up mail support for the blog, using a mail service such as Mandrill or Sendgrid.
  • config.production.database to set up the database for the blog; any database supported by the Knex library is supported, most commonly SQLite3, and MySQL.
  • config.production.server.port to set the port on which the Ghost application will listen for HTTP requests; this might be necessary in case you are running multiple Ghost applications on your server.

NB: The following commands assume that node v0.10.x is already installed on the system.

$ npm install --production
$ npm start --production

You should see something like the following the first time you start the Ghost application.

> ghost@0.8.0 start /var/www/blog
> node index

Migrations: Database initialisation required for version 005
Migrations: Creating tables...
Migrations: Creating table: posts
Migrations: Creating table: users
Migrations: Creating table: roles
Migrations: Creating table: roles_users
Migrations: Creating table: permissions
Migrations: Creating table: permissions_users
Migrations: Creating table: permissions_roles
Migrations: Creating table: permissions_apps
Migrations: Creating table: settings
Migrations: Creating table: tags
Migrations: Creating table: posts_tags
Migrations: Creating table: apps
Migrations: Creating table: app_settings
Migrations: Creating table: app_fields
Migrations: Creating table: clients
Migrations: Creating table: client_trusted_domains
Migrations: Creating table: accesstokens
Migrations: Creating table: refreshtokens
Migrations: Creating table: subscribers
Migrations: Running fixture populations
Migrations: Creating owner
Migrations: Ensuring default settings
Ghost is running in production...
Your blog is now available on http://example.com
Ctrl+C to shut down

On subsequent runs, you should see something like:

> ghost@0.8.0 start /var/www/blog
> node index

Migrations: Up-to-date at version 005
Ghost is running in production...
Your blog is now available on http://example.com
Ctrl+C to shut down

If you see that, you can press Ctrl+C to shut down the Ghost application.

Use the which command to note down the full path of the npm executable, e.g., /usr/local/n/bin/npm. We will need this when creating the start up scripts.

If you're running on Ubuntu, you have either upstart or systemd as the init system. Ubuntu made the switch over from upstart to systemd with version 15.04.

Please use this Q&A on Stack Exchange to ascertain which init system is in use in your machine, in case you don't already know.

Create the startup script for the blog using systemd

$ nano /etc/systemd/system/blog.service

Copy the following contents into the file.

[Unit]
Description=My Awesome Blog
After=network.target

[Service]
Type=simple
PIDFile=/var/www/blog/blog.pid
WorkingDirectory=/var/www/blog/
User=blog
Group=blog
ExecStart=/usr/bin/npm start --production
StandardOutput=syslog
StandardError=syslog
Restart=always
SyslogIdentifier=blog
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

After the file has been created, issue the following command to allow the blog to start automatically upon system restart.

$ systemctl enable blog.service

The following command will actually start the blog service.

$ systemctl start blog.service

Other useful verbs for the systemctl command include stop, restart, and status.

In case there are issues with the blog service starting up correctly, the following command can help ascertain what's going on and aid in troubleshooting:

$ journalctl -xe

At this point, hopefully, the blog is up and running, being served at http://localhost:2367.

The next step is to configure nginx to serve it via an IP name.

Create the startup script for the blog using upstart

$ nano /etc/init/blog.conf

Copy the following contents into the file.

description "Blog"
author "Umar Farooq Khawaja"

start on (started networking)

respawn
respawn limit 10 5

script
    su -c "cd /var/www/blog && /usr/local/n/bin/npm start --production" -s /bin/sh blog
end script

The Ghost application can be started and stopped by standard upstart commands.

$ service blog start
$ service blog stop
$ service blog status

The final piece of this puzzle is to make our blog available to the public for browsing.

Install and configure nginx

Installation is as simple as issuing the following command on Ubuntu:

$ apt-get install nginx --yes

Configuration involves creating the configuration file for the blog, e.g., for a blog hosted at example.com, create the configuration file /etc/nginx/sites-available/example.com.conf and add the following contents to it:

server {
	listen 80;

	server_name example.com;

	location / {
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_set_header X-NginX-Proxy true;

		proxy_pass http://127.0.0.1:2367/;
		proxy_redirect off;

		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}
}

And then enable this site in nginx:

$ ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf
$ systemctl restart nginx.service

The End

At this point, your blog should be available at http://example.com.