I have spent ages trying to find a good blogging platform.  Wordpress is good but has too many security vulnerabilities, which makes it a chore to manage. Static blogging engines such as Jekyll, Hugo are great but I ended up spending more time on the build process than writing.  

I wanted a blogging platform that was simple to manage, easy to use and had a gui editor so I could write and deploy a new post from anywhere. I have seen a few recommendations for Ghost and whilst they do an excellent managed version, I chose the self-hosted option as I already had a server available.  

Step 1 - Preparation

This post assumes you have an Ubuntu 18.04 setup and ready to go.  My previous post has a walkthrough on a minimal server setup.  It is IMPORTANT that you run this process as a standard user (NOT ROOT)

The Ghost documentation has an excellent guide on how to install and configure Ghost here.  However, I am going to make a couple of changes to that walkthrough.

If you follow this guide through, we will end up installing the following

  • Nginx
  • MySQL
  • Node & NPM
  • Ghost

Whilst Ubuntu 18.04 has nginx in the repos, it is the 1.14.x branch and doesn't have support for TLS1.3.  As such, I prefer to add a PPA to get the up-to-date Nginx build compiled for HTTP/2 & TLS1.3.  To do this, run these commands in order:

sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/nginx-mainline 
sudo apt update
sudo apt install nginx

you can now test Nginx is installed & running with systemctl and the output will look like this.

systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: en
   Active: active (running) since Thu 2019-05-02 11:16:20 CEST; 23h ago
     Docs: man:nginx(8)
 Main PID: 2332 (nginx)
    Tasks: 9 (limit: 4915)
   CGroup: /system.slice/nginx.service
           ├─ 2332 nginx: master process /usr/sbin/nginx -g daemon on; master_pr
           ├─27083 nginx: worker process
           ├─27084 nginx: worker process
           ├─27085 nginx: worker process
           ├─27086 nginx: worker process
           ├─27087 nginx: worker process
           ├─27088 nginx: worker process
           ├─27089 nginx: worker process
           └─27090 nginx: worker process

Now we can install MySQL (Database Server) using

sudo apt-get install mysql-server

We will need to configure MySQL so the Ghost install can connect later on.

# Connect to the mysql database
sudo mysql

# Now update the root user to have a password
# Replace 'password' with your password, but keep the quote marks!
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

# exit MySQL

Now we need to install Node.  Ghost is really picky about which version of Node to use so we will use the recommended LTS version.  

# Add the NodeSource APT repository for Node 10
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash

# Install Node.js
sudo apt-get install -y nodejs

Finally we can install Ghost

sudo npm install [email protected] -g

Step 2 - Install Ghost

Now the server is correctly setup we can go ahead and configure Ghost. The CLI has a lot of flags and options to allow you to have fine grain control over the process but for our purposes the standard install will work.

Note: Installing Ghost in the /root or home/<user> directories results in a broken setup. Always use a custom directory with properly configured permissions.

Create the website directory

First we need to create a directory where the blog will live and set the correct permissions.

# My folder is named thatopsguy, you can use whatever you want
sudo mkdir -p /var/www/thatopsguy

# Replace <user> with the name of your user
sudo chown <user>:<user> /var/www/thatopsguy

# Set the correct permissions
sudo chmod 775 /var/www/thatopsguy

# Then navigate into it
cd /var/www/thatopsguy

Run the install process

Now we can run the Ghost install cmd.  

ghost install

Install questions

During the  install, the process will ask a number of questions to configure your site.

Blog URL

Enter the exact URL your blog will use including the protocol for HTTP or HTTPS. If you use HTTPS, Ghost-CLI will offer to set up SSL for you later on.

MySQL hostname

This determines where your MySQL database can be accessed from. When MySQL is installed on the same server, use localhost as it is on the same server

MySQL username / password

If you already have an existing MySQL database enter the the username. Otherwise, enter root. Then supply the password for your user.

Ghost database name

Enter the name of your database. It will be automatically set up for you, unless you're using a non-root MySQL user/pass. In that case the database must already exist and have the correct permissions.

If you provided your root MySQL user, Ghost-CLI can create a custom  MySQL user that can only access/edit your new Ghost database and nothing else.  

This means add a conf file to /etc/nginx/sites-enabled automatically. This will allow your site to be live immediately without you having to change anything else. Setting up NGINX manually is possible, but you will need to know what you're doing.

If you used https when setting theBlog URL, Ghost-CLI can automatically set up SSL for you using Let's Encrypt. Alternatively you do this later by running ghost setup ssl at any time.  This process will ask you for your email (required by Lets-Encrypt).  It will then use the Lets_Encrypt tools to generate a new SSL cert and set up the renewal process.

systemd is the recommended process manager tool to keep Ghost running smoothly. We recommend choosing yes but it’s possible to set up your own process management.

Start Ghost?

Choosing yes runs Ghost, and makes your site work.

Once Ghost is started, A message pops up with the link to the blog.  Go there and register yourself as the first user. Happy Days, your blog is up and running.