Troubleshooting DigitalOcean Ghost One-Click Install Issues


Image

I've been revamping my site for the past month (more on that in another post), I've decided to try the One-Click install for Ghost. It's supposed to be this utopia where you do a few things and your blog is magically setup. Working in the software industry myself, I didn't expect this. That's just never how it goes. Anyway, I ran into several issues with the DigitalOcean guide or the ghost-cli setup process. I'm not entirely sure where I messed up. It was so frustrating that I decided to make a post and share some insight that might help someone out there.

Use this as an Accompanying Post

I don't want to repeat all the nitty gritty details. It's covered nicely in the original guide. Skim through the Digital Ocean's guide here first. I'll discuss what you need to do differently.


Some vaguely unrelated stock photo to make this post seem more professional. Photo by John Schnobrich / Unsplash

Step 1-3 Just Follow the Original Guide

Step 1-3 in the guide talks about creating the droplet, setting up your domain and logging into the server. Those should all work fine because if it didn't I recommend giving up and trying something else.

Understanding What's Happening

It's good to run through what is happening in this step. With DigitalOcean, you can rent your own server for a few bucks a month and have it automagically install all the software you need. It's great if you want to (almost) truly own your blog and all your content.

Shameless Plug: If you want to try DigitalOcean, you can use my referral link. I can get enough credits to pay for one month of hosting this site. Thanks!

Droplet Setup


Once you've bought a droplet, what's happening is called provisioning. They are setting up a new server for you and it's going through all the automated steps they've defined. Roughly, it's a VM (or maybe a container) with Ubuntu 16.04 on it. They will install MySQL database and default users. You'll get ghost-cli installed along with it's prerequisites. You'll get a non-root user to configure Ghost with.

Domain Setup

Step 2 in the guide involves setting up your domain. It's good to have some high-level idea of how that works. You can read good summary here. To overly simplify it, we need to tell all the browsers how to find the DigitalOcean server you setup just by typing your super cool domain name.

If you do not want to use a subdomain (ie blog.example.com) as in the guide, in the domain setup Choose A record and the hostname is your domain coolwebsite.com. Read more about how to configure that or subdomains like www.coolwebsite.com in the DigitalOcean guide here.

Step 4 Still Follow It

Step 4 involves updating to the latest version of ghost. A good rule of thumb is that THINGS MIGHT BREAK WHEN YOU UPDATE. Software devs have good intentions but there is always a chance that things break. Check your version by running ghost version under /var/www/ghost. If your version is different, there is no guarantees this guide will work.

Version I tried this guide with:

Ghost-CLI version: 1.7.1
Ghost Version: 1.22.3

Step 5 Where Things Get Interesting

Technically, you could skip this step and setup your blog (via Step 6 using your IP address) but might not be a great idea. That would be insecure and is possibly why I screwed up some stuff... Anyway onto setting up your blog!

We'll be running the ghost setup which helps us configure ghost in a few seconds but I recommend checking a few things first.


An image that showed up when I type 'database'. Photo by Tobias Fischer / Unsplash

MySQL Database

One of the steps that the setup will do is to attempt to install and configure the database that ghost will use. There should have already been one setup for us via our One-Click install. We'll check if the database exists and what users were installed. I had issues with my install because the name provided in the guide did not match what was actually installed.

Connect to MySQL and Check Database

First thing we'll do is get the passwords we'll need. Type cat /root/.digitalocean_password (Credits to the commenter from the DigitalOcean article for pointing this out) and it should print out passwords for you. You are now an elite hacker. There should be 2 accounts there. One for root and another for ghost. Keep these somewhere as we'll use it in a sec.

Let's connect to MySQL by typing mysql -u root -p in the terminal. You should be prompted with a password. Type the password for root.

As a master database hacker, let's check out what databases are present.

mysql> show databases;

You see a nice table of the databases present. There should be something that starts with ghost in one of the names. Take note of that name.

Check if Users Exist

Now that we know what database we need, let's check if the users are there. Enter the command below and you'll get a table of all the users in the database.

mysql> select * from mysql.user;

It might be a little bit hard to read so expand your terminal to your entire screen or learn better SQL to see the row you want. There should be User column. One of the rows should be root, the user you are using and another should be called something like ghost.

If all went well, we've confirmed that the database exists and the users exists. You also have this noted down. We're ready to start the setup process. If it didn't, maybe try Medium instead.

Also, type exit to exit if you're still inside MySQL.

Ghost Setup Process

A displayed content of a toolkit displayed showing tools like hammer, axe, box cutter, iron and flashlight
None of these things will be used to make your blog. Photo by Todd Quackenbush / Unsplash

Let's teleport into our ghost install directory by typing cd /var/www/ghost. Run the command below to start the process. Remember you must be using ghost-mgr and not root. This will not work under root. (You can switch user by typing sudo -i -u ghost-mgr).

[email protected]:/var/www/ghost$ ghost setup

Type your blog URL on the first prompt. This has to match exactly what you setup in the DNS records in step 2.

Output
? Enter your blog URL: http://mysupercooldomain.pizza

Now it'll ask you for your MySQL hostname and username. Type localhost for the host. For the username, look at your notes from when we checked the database. type that in.

? Enter your MySQL hostname: localhost
? Enter your MySQL username: <the user you found in the database>

Next, they'll ask for the password for that user and the database name. You've noted this down from the last step so go and put that in.

? Enter your MySQL password (skip to keep current password): [hidden]
? Enter your Ghost database name: <the database name you found earlier>

After that, it'll do a bunch of things and you'll see checkmarks like below.

✔ Configuring Ghost
...
✔ Setting up "ghost" system user

It'll now ask you if you want to setup the MySQL user. We already have that so respectfully decline.

Do you wish to set up "ghost" mysql user? n 

NGINX Web Server

Now, it asks yet another question. This time Nginx. WTF is this Nginx? It's a web server which means when someone is requesting your website, Nginx figures out where your blog is installed and returns all the content from your blog back to the user so they can read your wonderful blog post.

That seems important, so let's hit Y.

? Do you wish to set up Nginx? (Y/n)Y

It's important to note that it will create all the configuration you need. It will dump important information like the stuff below. Note it down just in case anything goes wrong. If you attempt to go through ghost setup again because something failed later, it will skip displaying this information as it's already configured (I wish I noticed that earlier).

Output
✔ Creating nginx config file at /var/www/ghost/system/files/<supercoolblog>.conf
Running sudo command: ln -sf /var/www/ghost/system/files/<supercoolblog>.conf /etc/nginx/sites-available/<supercoolblog>.conf
Running sudo command: ln -sf /etc/nginx/sites-available/<supercoolblog>.conf /etc/nginx/sites-enabled/<supercoolblog>.conf
Running sudo command: nginx -s reload
✔ Setting up Nginx

What are all these things?

In a quick summary, the conf files above tells Nginx what should it do if it receives a request from yoursupercoolblog.com. From my memory, the configuration looks something like below.

server {
    listen 80;
    server_name my-super-cool-blog.com;
    
    location / {
        proxy_pass http://127.0.0.1:{GHOST_PORT};
        ...(some other configuration)
   }
}

Port 80 is the HTTP port. Our server is listening to that and your domain name. Once we detect someone is trying to access it via the browser (or http), Nginx goes to the location part. The location part is the directory of ghost application. Note that ghost by default uses port 2368.

The Rest of Step 5

Now, follow the rest of the DigitalOcean guide.

Step 6 Make or Break

Type http://your-super-mega-cool-domain.com/ghost then try https://your-super-mega-cool-domain.com/ghost. Now try www.your-super-mega-cool-domain.com/ghost. Did it work? If it did then you're all good. Go forth and blog.

If it didn't, below are further troubleshooting things you can do.

Further Troubleshooting

A focused man working on a sticker-covered laptop in a coffee shop
What you probably look like if you reached this far in the blog post. Photo by Tim Gouw / Unsplash

Check out some of the issues below. I've copied some suggestions from the comments section of DigitalOcean article as they are pretty useful. Credits goes to all the people who shared those valuable tips.

Nginx Failing to Route to Ghost

Issue: I can view my ghost blog via http://your_digital_ocean_server_ip but not http://your-super-mega-cool-domain.com

Try This: There might be 2 things at play here. One, the domain name is not properly configured or Nginx is failing to route to ghost. If it's the former, check out this guide which goes to the topic in more detail. Let's investigate the latter.

Check logs if there are attempts to view your blog.

We can check the Nginx access logs and you'll be able to see if there were requests to your blog. Type sudo cat /var/log/nginx/access.log; and you should get a bunch of text. If you're unfamiliar with log files, they'll have a timestamp, the request (in this case a GET is an attempt to get something from your site like a blog post) and an HTTP code.

If you attempt to access your blog again at this point and open the log again, you should see a new request. If you are seeing the number 500 something in the logs, it's an HTTP error code saying we can't serve the request.

Check if Nginx configuration is correct.

Remember that Nginx information that we saved in Step 5? We'll to access those files. Dump the contents of that file using cat command.

Let's go to the address cd /var/www/ghost/system/files. Now type cat then the name of the configuration file. It should be something like yoursupercoolwebsite.com.conf. Here's a sample below.

[email protected]:/var/www/ghost/system/files$ cat supercoolwebsite.com.conf 

server {
    listen [http port number];
    listen [::]:[http port number];

    server_name [your domain name];
    root [ghost nginx location];

    location / {
        [some configuration]
        proxy_pass http://[localhost or 127.0.0.1]:[some port number];
    
    ...[some other things]
}

If you can't find the file or don't remember it, type ls in the /var/www/ghost/system/files directory to see all the conf files available then cat those out.

Now, check if the http port number is correct (it should be 80). Then check if the domain matches the domain you setup. Check if the ghost-nginx location exists. Finally check if the proxy_pass is correct. It should be localhost or 127.0.0.1. Because we didn't customize ghost, the port number is probably the default one which is 2368.

If any of those are incorrect, you can modify them using your favorite terminal editor. Example sudo nano supercoolwebsite.com.conf will open up an editor. Edit the file to whatever it needs to be then save.

After you've made the changes, you'll need to restart Nginx. Restart or reload shoud do the trick.

sudo service nginx restart

Try checking if your site is now accessible.

Database Migration Failed

Issue: During the ghost setup process you see something like below and now you're sad and just want to quit. You consider that maybe your blog can fit in 180 characters chunks and consider using Twitter.

✖ Running database migrations
A ProcessError occurred.

Message: The database migration in Ghost encountered an error.
Help: https://docs.ghost.org/v1/docs/troubleshooting#section-general-update-error

Try This: There's a few troubleshooting tips we can do.

  • Check if the database exists
  • Check if the ghost user exists
  • Check if the password is correct
  • Check that there was a setup database
  • Attempt to connect to the database with ghost user/password

I've covered them in Step 5 section above. Try those things.

My Site Can't Be Access via www.

Issue: http://yourcoolwebsite.com works but http://www.yourcoolwebsite.com doesn't.

Try this: www is a subdomain of your domain. There's two things to check. First, check if the CNAME is setup correctly. Read more about that here. Second, check if the Nginx config has www.

To do that, first open up the appropriate conf file. I mentioned it the Check if Nginx configuration is correct section. Once you have that open, as user santhoshveer mentions in his comment in the original guide

Find this line server_name example.com; Replace it with server_name example.com www.example.com;
...
After all set up restart ghost and Nginx
ghost restart
sudo service nginx restart
~Original comment here

Failed Migration TypeError: task.execute is not a function

Issue: Users slifty and jezper mentioned having an error that had something like below in the error message.

NAME: MigrationScript
MESSAGE: task.execute is not a function

level:normal

Error occurred while executing the following migration: 1-custom-template-post.js
MigrationScript: task.execute is not a function

Try This: User wtflux recommends updating ghost-cli.

Conclusion

I hope you managed to setup you blog. If not, there is always Medium, Blogger or Wordpress. You could also try static site generators like Hugo or GatsbyJs with Netlify.