Ghost and USB RAID-1 on Raspberry Pi
Once you have installed Ghost on your Raspberry Pi, the last thing you want is for the system to crash and for you to lose all your hard work! A smart person always makes a backup of their system on a regular basis, but what about adding some redundancy via a RAID-1 set up too?
Backup your system
Before you do anything to your own Raspberry Pi hosted Ghost blog, you should always backup before you attempt something new. That way, should something go wrong, you can restore and be back up-and-running in no time.
There are various methods to backing up your Pi's SD card, but as there are countless guides online we won't cover those, you can take a look at this instead.
You should also export your Ghost configuration via the labs section from within the Ghost admin panel to create an export of your posts.
RAID on Raspberry Pi
RAID stands for "Redundant Array of Independent Disks" and there are various types, including:
RAID-0
In short, RAID-0 combines your disks into one giant volume. So imagine you have 2 USB flash drives each with a capacity of 32GB. In a RAID-O configuration, the new RAID-0 configuration will provide you with a storage size of 64GB (2 x 32GB). However, this does not provide any form of data redundancy, and if one disk fails, the whole RAID array fails.
RAID-1
This provides you with some data redundancy. In the same scenario above where we have 2 USB flash drives each with a capacity of 32GB, a RAID-1 configuration will give you 32GB of storage, but will mirror the data across both drives. Should one disk fail, then you can replace it without any data loss.
For this guide, we will be using a RAID-1 configuration as we want to provide data redundancy, not a combined larger storage volume.
RAID-2, 3, 4, 5 and 6 etc
There are many more RAID configurations, but the majority of them are not suited to life on a Raspberry Pi due to the performance constraints the Pi has. There are many online resources where you can learn more about RAID configurations, as well as this excellent guide written by Alex Ellis that covers all you need to know in order to create a hardened NAS drive using a Raspberry Pi and a RAID-1 configuration.
Select your storage
In our setup, we're using 2 USB flash drives with a capacity of 16GB per drive. We could have used larger, but for hosting and running a Ghost blog on a Raspberry Pi, 16GB is plenty of space. You could use USB 3.0 flash drives, but as the Pi only supports 2.0, there is no specific requirement although more USB drives come as 3.0 as standard nowadays.
Install the RAID controller
We found a very comprehensive guide on getting RAID up-and-running on your Raspberry Pi, which was extremely helpful and covered everything along the way, but in this guide we'll show you the key points you'll need to do the same.
First, let's ensure our Raspberry Pi is up-to-date by updating Raspbian:
boo@ghost-pi ~ $ sudo apt-get update && sudo apt-get dist-upgrade -y
Depending on when you last updated your Pi, this could take a while.
Next we'll install the RAID controller - mdadm:
boo@ghost-pi ~ $ sudo apt-get install mdadm -y
During the installation process for mdadm
, you may be asked to configure the tool. If so, just select all
and continue to finish this.
It's now time to create the RAID-1 volume, but first let's prepare our USB drives:
boo@ghost-pi ~ $ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 1 14.3G 0 disk
└─sda1 8:1 1 14.3G 0 part
sdb 8:16 1 14.3G 0 disk
└─sdb1 8:17 1 14.3G 0 part
mmcblk0 179:0 0 14.9G 0 disk
├─mmcblk0p1 179:1 0 43.2M 0 part /boot
└─mmcblk0p2 179:2 0 14.8G 0 part /
The above command will list all the disks connected to your Raspberry Pi - in our case, you can see the two USB drives as sda
and sdb
. Before creating the RAID-1 volume, we'll need to format the USB drives accordingly:
boo@ghost-pi ~ $ sudo fdisk /dev/sda
This will launch fdisk
where you'll see the following:
Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help):
As a shortcut, we can run the following commands in order:
o
n
p
enter
enter
enter
w
The above will create a new DOS disk label (o
); create a new partition (n
) that is a primary partition (p
); select the default partition number (enter
); default first sector (enter
); default last sector (enter
) and then will write the changes to disk (w
).
You should then repeat the above but for /dev/sdb
- i.e.:
boo@ghost-pi ~ $ sudo fdisk /dev/sdb
Now you should have 2 formatted USB drives ready for the RAID-1 array.
Creating the RAID-1 array
We'll now use mdadm
to create the RAID-1 array:
boo@ghost-pi ~ $ sudo mdadm --create /dev/md0 --level=mirror --raid-devices=2 /dev/sda1 /dev/sdb1
Notice that we used /dev/sda1
and /dev/sdb1
, which refers to the partitions we created earlier. If yours are different, you'll need to change the command above accordingly.
Next we will create a folder on our Raspberry Pi, which will become the mount point for the new RAID-1 array:
boo@ghost-pi ~ $ sudo mkdir -p /mnt/raid1
And then we'll format the new RAID-1 array as EXT4:
boo@ghost-pi ~ $ sudo mkfs.ext4 /dev/md0
Before mounting it with:
boo@ghost-pi ~ $ sudo mount /dev/md0 /mnt/raid1/
In order for the array to be mounted automatically on boot, we just need to tweak a few things:
boo@ghost-pi ~ $ echo "/dev/md0 /mnt/raid1/ ext4 defaults,noatime 0 1" | sudo tee -a /etc/fstab
boo@ghost-pi ~ $ sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
We can now check that our RAID-1 array is accessible by looking in the directory:
boo@ghost-pi ~ $ cd /mnt/raid1
boo@ghost-pi ~ $ ls
lost+found
The directory will only contain lost+found
at the moment, which is just what we want.
Moving your NGINX configuration
Now that we have created our RAID-1 array and set the Raspberry Pi to auto-mount it on boot, we need to tweak a few more settings to complete our setup.
The next step is to move our NGINX configuration, which by default is usually /var/www/html
, as this is located on our Raspberry Pi's SD card instead of our new RAID-1 setup across our 2 USB flash drives.
To achieve this, we need to make a few changes. I followed a helpful guide on DigitalOcean, which is based on Ubuntu 16.04, but works just the same on Raspbian Stretch. Below are the key points summarised:
Move NGINX to USB RAID-1 array
To be sure we move the correct files, we just need to check the output of:
boo@ghost-pi ~ $ grep "root" -R /etc/nginx/sites-enabled
This command utilises grep
to check for the term root
in the /etc/nginx/sites-enabled
file. The output should be similar, if not identical to this:
/etc/nginx/sites-enabled/default: root /var/www/html;
/etc/nginx/sites-enabled/default: # deny access to .htaccess files, if Apache's document root
/etc/nginx/sites-enabled/default:# root /var/www/example.com;
Now, let's make a directory on our new RAID-1 array to hold the files:
boo@ghost-pi ~ $ sudo mkdir -p /mnt/raid1/nginx
Then we'll use rsync
to copy the files to the new location:
boo@ghost-pi ~ $ sudo rsync -av /var/www/html /mnt/raid1/nginx
This shouldn't take long. Once done, we now need to update our NGINX configuration to look for the files in the correct location:
boo@ghost-pi ~ $ sudo nano /etc/nginx/sites-enabled/default
And then look for the line that begins with root
(TIP: use CTRL+W
to search and then look for root
that way). Then change the location to:
# include snippets/snakeoil.conf;
root /mnt/raid1/nginx/html;
Exit (CTRL+X
) and save (Y
) the changes, then check your NGINX configuration is correct by running:
boo@ghost-pi ~ $ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
If your output looks like the above, then it is working just fine. Now we just need to restart NGINX then remove the old files:
boo@ghost-pi ~ $ sudo systemctl restart nginx
boo@ghost-pi ~ $ sudo rm -Rf /var/www/html
The final step is to install our Ghost blog on the new RAID-1 array!
Install Ghost on RAID-1 on Raspberry Pi
The final steps to installing Ghost on your Raspberry Pi whilst utilising RAID-1 for data redundancy is to follow an almost-identical process to installing Ghost on a Raspberry Pi normally.
The only major exception is the location, and a few manual steps at the end to ensure the Ghost blog starts on boot.
First, create the Ghost install directory on our RAID-1 array:
boo@ghost-pi ~ $ sudo mkdir -p /mnt/raid1/nginx/ghost
boo@ghost-pi ~ $ sudo chown [user]:[user] /mnt/raid1/nginx/ghost
boo@ghost-pi ~ $ cd /mnt/raid1/nginx/ghost
You will need to replace the [user]:[user]
part with your current user, for example pi:pi
.
Now, install Ghost using the command line:
boo@ghost-pi ~ $ ghost install
And then follow the same steps as before, except do not choose to start Ghost at the end because we need to tweak the systemd
file first.
Fix the systemd file issues
When Ghost installs normally, it creates a soft symlink in /lib/systemd/system
for the Ghost service file, which is usually found within your Ghost install directory within /system/files
and begins with ghost_nameofyourblog.service
. However, as highlighted in the issue I logged with Ghost on their GitHub page, the file is not loaded when the RAID-1 array is loaded at boot, unless it is physically created, rather than linked to. Thankfully, there is an easy fix:
boo@ghost-pi ~ $ sudo rm /lib/systemd/system/ghost_nameofyourblog.service
This will delete the soft symlink created by the Ghost installation from the systemd folder. Next, we'll copy the file there permanently:
boo@ghost-pi ~ $ sudo cp /mnt/raid1/nginx/ghost/system/files/ghost_nameofyourblog.service /lib/systemd/system/
Obviously if you installed your Ghost blog in a different location, you will need to update that in the command.
You can then test it out by finally running:
boo@ghost-pi ~ $ cd /mnt/raid1/nginx/ghost
boo@ghost-pi ~ $ ghost start
If all goes well, the Ghost blog should start, and should do some automatically if / when you reboot your Raspberry Pi!
Updating Ghost in the future
As this alters the way Ghost CLI tool works, updating Ghost can cause the systemd
workaround to revert to "normal" on each update. However, re-doing the fix above will resolve this, until Ghost supports the copying of the ghost_nameofyourghostblog.service
fix.
If you found this guide, as well as any other guides on Ghost Pi helpful, then if you wanted to buy Ghost Pi a coffee to show your support, then that would be greatly appreciated! As this site does not use any form of adverts, all the costs for running and maintaining the blog are done voluntarily so any extra would be fantastic!