captainarkdotnet/content/post/2017-11-19-installing-ghost.md

302 lines
10 KiB
Markdown

---
title: "Installing Ghost"
date: 2017-11-19T00:00:00+01:00
draft: false
share: false
---
I haven't published an article on here for over a year and a half... While this was mostly due to a lack of motivation, another reason was that I didn't enjoy the blogging system I was using.
As lightweight as [Pelican](https://blog.getpelican.com/) is, I found it cumbersome to use on a regular basis. Every time I wanted to publish or update an article, I had to :
- edit local markdown files ;
- regenerate the website files ;
- start a webserver locally to proofread the article ;
- commit and push the files to my git repo ;
- pull the files on the webserver.
I hadn't had a look at the CMS landscape for a while, and I started searching for one with a web editor that supports markdown. I also wanted to avoid anything that runs on PHP if possible.
I quickly discovered [Ghost](https://ghost.org/), and decided to give it a shot. I was convinced by it within a few hours and I decided to migrate this blog.
So, to celebrate my move to Ghost, I figured I'd write an article on how I've installed it on my server.
All commands in this article have to be run as the `root` user on a Debian server.
# Installing nodejs
Unlike most CMS (Wordpress, for example), Ghost is not files that you have to upload to a webserver, but a daemon that runs on [nodejs](https://nodejs.org/en/).
Here's the official recommended way of installing the current LTS version of nodejs on Debian :
```bash
curl -sL https://deb.nodesource.com/setup_8.x | bash -
apt-get install -y nodejs
```
If, like me, you don't want to run a bash script downloaded from the internet on your server, here are the commands you have to run to install it manually.
Since the nodejs repo uses https, we'll first need to install the required package to use those :
```bash
apt install apt-transport-https
```
We'll then have to add the nodejs repository public key to the system :
```bash
curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
```
Now we have to add the nodejs repository to our sourcelist :
```bash
echo 'deb https://deb.nodesource.com/node_8.x stretch main' > /etc/apt/sources.list.d/nodesource.list
```
We can now install nodejs
```bash
apt update
apt install nodejs
```
# System configuration
Before installing Ghost, some system configuration is required.
First, let's create a new `ghost` system user that'll be used to run the Ghost daemon :
```bash
useradd -s /bin/false -r -d /opt/ghost -m ghost
```
Ghost needs an empty folder for the automated installation script to work. For that purpose, let's create a subfolder in the `ghost` user home folder :
```bash
sudo -Hu ghost mkdir /opt/ghost/app
```
# Database
Ghost requires a MySQL/MariaDB database to store its data (technically, you could use a SQLite database, but please don't).
I personnally have all my databases stored on a single LXC container running MariaDB. However, if you need to, you can install MariaDB locally this way :
```bash
apt install mariadb-server mariadb-common
```
We now have to declare a `ghost` user and database in the MariaDB shell :
```mysql
create database ghost;
create user `ghost`@`%` identified by 'password';
grant all privileges on ghost.* to 'ghost'@`%`;
```
You can change the `%` to `localhost` in the `create user` command if you've installed MariaDB locally. Please also remember to change `'password'` by an actual password.
Once that's done, we're ready to install Ghost !
# Installing Ghost
## Ghost CLI
To install Ghost, we first have to install the Ghost CLI :
```bash
npm i -g ghost-cli
```
The Ghost CLI is a tool that lets you install, upgrade and manage your Ghost installation easily. Its usage is thoroughly documented on the official website [here](https://docs.ghost.org/v1/docs/ghost-cli).
## Installing Ghost
Let's install Ghost :
```bash
cd /opt/ghost/app
sudo -Hu ghost ghost install --no-setup-nginx --no-setup-systemd --no-setup-linux-user --no-setup-mysql
```
The command will ask you for the following information :
- the URL of your website ;
- the hostname or IP of the server that's hosting your MariaDB installation ;
- the username to use to connect to the database (`ghost`) ;
- the password you've configured for the database user ;
- the database name (`ghost`).
Once the script has finished running, you've successfully installed Ghost ! However, the daemon won't start since we haven't configured systemd yet.
Since it contains a password, let's fix the permissions on our installation's configuration file to make sure it's not world-readable :
```bash
chmod 600 /opt/ghost/app/config.production.json
```
As you can see from the `ghost install` command, it can install and configure pretty much all of its dependencies on its own. However, since I'm a [_sysadmin_](https://xkcd.com/705/), that's not how I roll.
## Systemd configuration
As I wrote earlier, Ghost runs as a daemon. For us to be able to start it, we now need to declare a systemd unit file :
Let's create the file :
```bash
vim /etc/systemd/system/ghost.service
```
And add the following content to it :
```text
[Unit]
Description=Ghost systemd service
Documentation=https://docs.ghost.org
[Service]
Type=simple
WorkingDirectory=/opt/ghost/app
User=ghost
Group=ghost
Environment="NODE_ENV=production"
ExecStart=/usr/bin/ghost run
[Install]
WantedBy=multi-user.target
```
We can now reload systemd an start Ghost :
```
systemctl daemon-reload
systemctl start ghost.service
```
The daemon should now be running :
```
pgrep -alf ghost
14184 ghost run
```
# Nginx
With its default configuration, Ghost runs as a webserver on localhost, on a non-standard HTTP port (TCP 2368). For your website to be publicly browseable, you'll need to configure a webserver as a reverse-proxy in front of your Ghost installation. We'll use nginx for that purpose.
If you already have nginx running on a different server from your Ghost installation, you can use it for that purpose. For it to work, you'll need to edit the server host IP in Ghost's `config.production.json` configuration file with your Ghost server public IP and to restart Ghost. If you do so, make sure to limit direct access to your Ghost installation to the IP of your reverse-proxy by using iptables.
If you need to, you can install nginx locally this way :
```bash
apt install nginx
```
I won't go into details on how to configure and secure a nginx installation here as it is beyond the scope of this article.
Here is my nginx configuration for this website :
```
location / {
proxy_pass http://127.0.0.1:2368;
include proxy.conf;
add_header Front-End-Https on;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Authorization "";
proxy_set_header Accept-Encoding "";
proxy_redirect off;
}
location /ghost/ {
proxy_pass http://127.0.0.1:2368/ghost/;
allow 192.0.2.100;
deny all;
include proxy.conf;
add_header Front-End-Https on;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Accept-Encoding "";
proxy_redirect off;
}
```
As you can see, I've declared two location blocks :
- `/` is publicly visible by anyone ;
- `/ghost` (Ghost's administation interface) is only accessible from 192.0.2.100 (my public IP address).
I'd rather have left Ghost's administation interface accessible from anywhere. However, since there is currently no way to replace `/ghost` by another subfolder and two-factor authentification is not available, I've decided against it.
# Monit
As I mentionned in previous articles, I have monit running on all of my servers to make sure that my services are running and to restart them should they crash.
I've created a configuration file for Ghost :
```bash
vim /etc/monit/conf.d/ghost
```
With the following content :
```text
check process ghost
matching "ghost run"
start program = "/bin/systemctl start ghost"
stop program = "/bin/systemctl stop ghost"
if changed pid then alert
if changed ppid then alert
```
Let's reload monit :
```bash
monit reload
```
Ghost should now appear in your `monit summary`.
# Logging
Ghost writes its logs through `syslog`. If you don't want those messages to end up in `/var/log/syslog`, you'll have to configure your `syslog` daemon. For me, that's `syslog-ng`.
## Syslog-ng
Let's create a dedicated folder for the Ghost daemon's log files :
```bash
mkdir /var/log/ghost
chown root:adm /var/log/ghost
```
Then, we need to create a configuration file :
```bash
vim /etc/syslog-ng/conf.d/ghost.conf
```
And add the following content to it :
```
filter f_ghost { program ("ghost"); };
destination d_ghost { file (/var/log/ghost/ghost.log); };
log { source(s_src); filter (f_ghost); destination (d_ghost); flags(final); };
```
We can now reload `syslog-ng` :
```
service syslog-ng reload
```
Once that's done, Ghost should start logging in `/var/log/ghost/ghost.log`. Accessing a page on your site will create a new log entry, so that'll be enough to make sure it's working properly.
## Logrotate
As always with logs, let's configure logrotate to make sure we don't end up with huge files.
Let's create a new logrotate configuration file :
```bash
vim /etc/logrotate.d/ghost
```
And add the following content to it :
```text
/var/log/ghost/ghost.log {
rotate 8
weekly
notifempty
missingok
create 640 root adm
compress
copytruncate
}
```
There's no need to reload anything here. This new configuration file will be read by logrotate automatically next time its cron runs.
# Conclusion
This blog uses a previous version of Ghost's default theme, [Casper](https://github.com/TryGhost/Casper).
I've modified it a bit, and I really enjoy how it looks now ! You can get the theme with my modifications from my [GitHub](https://github.com/captainark/Casper) ! Credits to [this article](http://www.brycematheson.io/fixing-ghosts-default-casper-theme/) for some of the changes, and thanks [@Aguay](https://mastodon.fun/@aguay) for the help !
You've also probably noticed that I now use a private installation of [NodeBB](https://nodebb.org/) for the comments section. I'll probably write an article on how I've installed and implemented it in my Ghost installation in the near future. In the meantime, please feel free to make use of it !