Ghost Blog

Setup Ghost Blog In FreeBSD Jail

Matching Blog Post

Create new jail to install Ghost Blog into:

$ doas bastille create ghost 13.0-RELEASE

Create database user for the Ghost Blog

bsh ➜  doas bastille console database

Log into the database server

mysql -u root -p
Enter password: **********

Create database user

[(none)]> create user 'ghost'@'' identified by '**********************';

Create the database

[(none)]> create database ghostdb;

Grant all privileges on the database to the user

[(none)]> grant all on `ghostdb`.* to 'ghost'@'';

Make it so the user can log in over jails network

[(none)]> alter user 'ghost'@'' identified with mysql_native_password;

After the above step I always have to enter the password for the user again. It’s been decades since I worked as DBA, so maybe I’m just doing things out of step here.

[(none)]> alter user 'ghost'@'' identified by '**********************';

Flush privileges and exit

[(none)]> flush privileges;
[(none)]> quit

Log into Ghost jail and install and configure Ghost. Note initially I tried latest npm-node package, but kept backing down the version until I found a version that worked which is npm-node14. Doas is just for my convenience and not required if you prefer to su - instead. And of course I need to the MySQL client to connect to the database in the database jail.

doas bastille console ghost
# pkg update
# pkg upgrade
# pkg install doas npm npm-node14 openssl curl mysql80-client

Create ghost user

# adduser

Create startup script so the Ghost Blog will start on reboot.

# vi /usr/local/etc/rc.d/ghost

Example of script below


# PROVIDE: ghost
# REQUIRE: mysql
# KEYWORD: shutdown

. /etc/rc.subr


load_rc_config ghost



    su ghost -c "/usr/local/bin/ghost start -d /usr/local/www/"
    su ghost -c "/usr/local/bin/ghost stop -d /usr/local/www/"


    su ghost -c "/usr/local/bin/ghost status -d /usr/local/www/"

run_rc_command "$1"

Make the script executable.

# chmod +x /usr/local/etc/rc.d/ghost

Create directory for the blog to be installed into and run from.

# mkdir -p /usr/local/www/

Make user ghost own the directory

# chown -R ghost:ghost /usr/local/www/

Install ghost command line tools

# npm install ghost-cli@latest -g

change to ghost user and install ghost

# su - ghost
$ cd /usr/local/www/
$ ghost install

During the install you will get errors about unsupported system, since everyone who writes software nowadays assumes we have all been assimilated into the Linux collective.

The configuration file built from the answers provided by the install will look like the file below.

$ cat config.production.json
  "url": "",
  "server": {
    "port": 2368,
    "host": ""
  "database": {
    "client": "mysql",
    "connection": {
      "host": "",
      "user": "ghost",
      "password": "***************************",
      "database": "ghostdb"
  "mail": {
    "transport": "Direct"
  "logging": {
    "transports": [
  "process": "local",
  "paths": {
    "contentPath": "/usr/local/www/"

You can start ghost from the install directory with $ ghost start or by using the rc script created earlier with $ doas service ghost start I had already setup a DNS zone file as shown earlier for Creating Vultr Instance for the Ghost Blog’s domain of So we just need to add that domain to the caddy server jail configuration

bsh ➜  doas bastille console caddy
# vi /usr/local/etc/caddy/Caddyfile

And add {
        log {
                output file /var/log/caddy/
                format json

Then restart caddy with # service caddy restart You will not want to wast time and create your user and secure that account because until you do anyone can do so. I used to create firewall rules and allow only access from my workstation or rather ISP account. But that triples the amount of time. So I just make sure as soon as I restart caddy I’m setting up the owner account at I used to then go in and configure the server to host dark only themes, open external links in new windows/tabs and remove the Ghost branding by modifying the /usr/local/www/ file, but with version 3 you can configure the server to default to dark mode at Settings --> design --> site wide --> Color scheme and for simplicity I now just use code injection. To remove the Ghost Branding I inject the following code in the footer

  /* The footer links to ghost keep coming back */
  .site-footer a[href^=""] { display: none; }

And to ensure external links open in new tabs/windows I inject the following code also in the footer

  const anchors = document.querySelectorAll('a');

  for (x = 0, l = anchors.length; x < l; x++) {
    const regex = new RegExp('/' + + '/');
    if (!regex.test(anchors[x].href)) {
      anchors[x].setAttribute('target', '_blank');
      anchors[x].setAttribute('rel', 'noopener');

That’s it now all that remains is to begin blogging, which is the most difficult part me.