Ghost Blog on Arch Linux with Systemd-Nspawn

This blog is powered by a piece of Node.js software called "Ghost". Unfortunately the official way of getting a production setup up and running is only really supported on Ubuntu and even then the tool you must use to do this, ghost-cli, requires some globally installed npm packages, requires you to do the setup from a basic user account that will require a lot of sudo privileges instead of properly using the service account it really wants to setup for you, leaves a lot of the files owned by the regular user and requires this to be so for updates to work correctly, and as of writing has a bug where if you do specify a mySQL database, user, and password to use, instead of giving it root credentials to the database so it can do it own setup, it fails to correctly detect if it needs to initialize a fresh database, assumes it then needs to do a migration, and then setup fails due to the migration stage attempting to migrate a blank database. However I already started with an older version of this software, ultimately find it very usable once you get past the setup issues, and manually migrating the pages using the stored post and page HTML in the old database was very easy. I probably could have written a script, but then I'd be too tempted to write it as an official feature to submit. I tried the official migration, which for some reason would have required 2 phases, but it didn't work. Given all this I opted to listen to some advice from the comments on the old Arch Linux AUR package page, since deleted, for ghost and installed it in a systemd nspawn container, hosted MariaDB (mySQL) on the main host, and didn't even have to adjust my nginx proxy. Unfortunately the page that was hosted by the person who suggested this is no longer online and is also now slightly out of date so I will be re-documenting it here. This guide assuming you are already familiar with nginx, or apache, and how to secure your site with HTTPS so I will not be covering that here. It also assumes you already have a working MariaDB instance running on your Arch Linux installation.

Setup

Enable nspawn container startup on boot on your host system.

sudo systemctl enable machines.target

Get the basic system tools installed and do the minimum basic configuration of the new container after the install. As root, or with sudo, run the following.

pacman -S arch-install-scripts
cd /var/lib/machines
mkdir -p ghost
pacstrap -c -d ghost/ base vim bash-completion
machinectl start ghost
machinectl shell ghost
# set the root password
passwd
exit
machinectl stop ghost

Now setup the unit file for the container. If you want to setup more advanced networking change "Private" to yes in the network section. This will create a virtual switch and device for the container to use. The mysql socket directory is being bind mounted inside the container to allow access to the host mysql instance. If you are not using socket connections leave this line out. The bind mounting of the package cache and the host pacman config prevents a lot of wasted time and disk space. The binding of resolve.conf is needed for DNS to work inside the container since it will not go through a network setup stage due to the shared networking with the host.

mkdir -p /etc/systemd/nspawn
cd /etc/systemd/system/nspawn/
cat <<EOF >> ghost.nspawn
[Exec]
PrivateUsers=pick

[Files]
Bind=/var/cache/pacman/
Bind=/etc/pacman.conf
Bind=/run/mysqld/
BindReadOnly=/etc/resolv.conf

[Network]
Private=no
EOF

systemctl enable systemd-nspawn@ghost.service
systemctl start systemd-nspawn@ghost.service

Now we will shell back into the container and install ghost. If there are any other text editors or tools you want installed in the container, do that now.

machinectl shell ghost
useradd --system --user-group ghost
useradd --system --user-group ghostuser
usermod -s /bin/bash ghostuser
mkhomedir_helper ghostuser
pacman -S nodejs-lts-boron npm python2 mariadb-clients sudo
npm install -g ghost-cli sqlite3
echo "ghostuser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
mkdir /opt/ghost
chown ghostuser:ghostuser /opt/ghost
# You must run ghost-cli in you install directory
cd /opt/ghost
su ghostuser
ghost install --no-setup-linux-user --port 2368 --url https://<YOUR DOMAIN> --db mysql --no-start --dir /opt/ghost --no-setup-ssl

Enter you root database user details when prompted by the ghost-cli setup and fill in the other relevant details not already passed to ghost-cli from the command line. Tell ghost to create a new database user for it to use instead of the root credentials. You may still need to configure your mail settings by editing:

/opt/ghost/config.production.json

Ghost-cli should have already created and enabled a systemd service file for your ghost instance. So you should only need to start it.

systemctl start ghost_<YOUR-DOMAIN-NAME>.service

If you do need to create and enable the service file yourself for some reason do the following.

cd /etc/systemd/system/
cat <<EOF >> ghost_<YOUR-DOMAIN-NAME>.service
[Unit]
Description=Ghost systemd service for blog: wdworak-homelinux-com
Documentation=https://docs.ghost.org

[Service]
Type=simple
WorkingDirectory=/opt/ghost
User=ghost
Environment="NODE_ENV=production"
ExecStart=/usr/bin/ghost run
Restart=always

[Install]
WantedBy=multi-user.target
EOF

systemctl enable ghost_<YOUR-DOMAIN-NAME>.service
systemctl start ghost_<YOUR-DOMAIN-NAME>.service

Now go to your new ghost install by navigating to:

https://<YOUR-DOMAIN>/ghost

Configure a user account for you ghost instance and otherwise setup your site. All the other setup should be complete at this point.