Install Ghost with Caddy on Ubuntu
Tags: ubuntu, node
Published: 2019-12-14 05:08:23

## TL; DR

1. Get a server with Ubuntu up and running
2. Set up a non-root user and add it to superuser group
3. Install MySQL and Node.js
4. Install Ghost-CLI and start
5. Install Caddy as a service and write a simple Caddyfile
6. Get everything up and running!

## Foreword (Feel-Free-to-Ignore-My-Nonsense™️)

This article is about how I built **this** blog with Ghost, an open-source blog platform based on Node.js. I used to use WordPress and static website generators like Hexo and Jekyll for my blog. But they turned out either too heavy or too light. Ghost seems like a perfect balance between them. It's open source; it's elegant out-of-the-box. Zero configuration is required; yet it's configurable from top to bottom. 

The Ghost project is actually very well-documented – it has a decent [official installation guide](https://ghost.org/docs/install/ubuntu) on Ubuntu with Nginx. But as you can see from the title of this article, I am going to ship it together with my favorite web server – Caddy! It's a lightweight, easy to configure yet powerful web server. To someone like me, who hate to write or read either Nginx `conf` files or Apache `.htaccess` files, Caddy is like an oasis in the desert of tedious web server configurations. 

The web technologies are changing rapidly, especially for open source projects like Ghost and Caddy. From my observation, I would say neither Ghost nor Caddy are going to be backward compatible, which means the newer version of the software may not work as expected in older environment. So I **recommend** that you should always check if this tutorial is outdated or deprecated before moving on. You can go to their official website by clicking their names in the next section. Also,  if you are running the application in production, use a fixed version, preferably with LTS (*Long-term support*).

## Environments and Softwares

- [Ubuntu 18.04.3 LTS](https://ubuntu.com/download/server)
- [Node.js v10.17.0 LTS](https://nodejs.org/en/about/releases/) (This is the highest version Ghost support as of Dec. 2019)
- [Caddy 1](https://caddyserver.com/v1/) (**NOT** Caddy 2, which is still in **beta** as of Dec. 2019)
- MySQL 5.7 (It's gonna consume **A LOT** of memory! Use a lower version if you're running on a server with <1GB RAM.

Let get started! 👨‍💻👩‍💻

## Step 1: Get a server

Get a server with Ubuntu up and running! Almost every cloud hosting company will provide Ubuntu 18.04 LTS image as of now.

## Step 2: Set up a non-root superuser

```bash
# connect with root credentials to the server
ssh root@<server_ip> -p <ssh_port> # Default port: 22
    
# create a new user
adduser <username>
    
# add that user to superuser group
usermod -aG sudo <username>
    
# login as the new user
su <username>
```
## Step 3: Install MySQL and set up

```bash
sudo apt update
sudo apt upgrade
    
# install MySQL
sudo apt install mysql-server
    
# Set up MySQL password, it's required on Ubuntu 18.04!
sudo mysql
    
# Replace 'password' with your password, but keep the quote marks!
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
    
# Then exit MySQL
quit
```

## Step 4: Install Node.js

### Method 1: Use apt / apt-get

```bash
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash
sudo apt-get install -y nodejs
```

### Method 2: Use nvm (Node Version Manager)

to facilitate switching between Node.js versions

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash
```

The script clones the nvm repository to `~/.nvm`, and adds the source lines from the snippet below to your profile (`~/.bash_profile`, `~/.zshrc`, `~/.profile`, or `~/.bashrc`):

```bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
```

Install Node.js v10.17.0

```bash
# source profile
source ~/.bash_profile	# change to your profile
    
# check if nvm is properly installed
command -v nvm	# output will be `nvm` if it is
    
nvm install v10.17.0
```

## Step 4: Install Ghost-CLI

### Method 1: Use npm

```bash
sudo npm install ghost-cli@latest -g
```

### Method 2: Use yarn

```bash
# install yarn if you don't have it
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update && sudo apt install yarn
    
sudo yarn global add ghost-cli@latest
```

## Step 5: Get Ghost up and running

```bash
    sudo mkdir -p /var/www/ghost
    sudo chown <username>:<username> /var/www/ghost
    sudo chmod 775 /var/www/ghost
    cd /var/www/ghost
    ghost install
```

### Install questions

During install, the CLI will ask a number of questions to configure your site. They will probably throw an error or two about you don't have Nginx installed. Just ignore that.

#### Blog URL

Enter the exact URL your publication will be available at and include the protocol for HTTP or HTTPS. For example, `https://example.com`.

#### MySQL hostname

This determines where your MySQL database can be accessed from. When MySQL is installed on the same server, use `localhost` (press Enter to use the default value). If MySQL is installed on another server, enter the name manually.

#### MySQL username / password

If you already have an existing MySQL database enter the the username. Otherwise, enter `root`. Then supply the password for your user.

#### Ghost database name

Enter the name of your database. It will be automatically set up for you, unless you're using a **non**-root MySQL user/pass. In that case the database must already exist and have the correct permissions.

#### Set up a ghost MySQL user? (Recommended)

If you provided your root MySQL user, Ghost-CLI can create a custom MySQL user that can only access/edit your new Ghost database and nothing else.

#### Set up systemd? (Recommended)

`systemd` is the recommended process manager tool to keep Ghost running smoothly. We recommend choosing `yes` but it’s possible to set up your own process management.

#### Start Ghost?

Choosing `yes` runs Ghost on default port `2368`.

## Step 6: Get Caddy up and running

Caddy has an awesome collection of plugins. You can go to [Download Caddy](https://caddyserver.com/v1/download) page. First, select the correct platform; then add a bunch of plugins that you're interested. After that, don't click `Download`. Copy the link in the `Direct link to download` section. Head back to ssh in terminal.

![](https://blog.alex0.dev/content/images/2019/12/Screenshot_2019-12-13_03-17-32.png)

```bash
mkdir -p ~/Downloads
cd ~/Downloads
    
# download caddy binary, the link may differ if you added plugins
curl https://caddyserver.com/download/linux/amd64?license=personal&telemetry=off --output caddy
sudo cp ./caddy /usr/local/bin
sudo chown root:root /usr/local/bin/caddy
sudo chmod 755 /usr/local/bin/caddy
    
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy
    
sudo mkdir /etc/caddy
sudo chown -R root:root /etc/caddy
sudo mkdir /etc/ssl/caddy
sudo chown -R root:<username> /etc/ssl/caddy
sudo chmod 770 /etc/ssl/caddy
```

### Run Caddy as a service

```bash
wget https://raw.githubusercontent.com/caddyserver/caddy/master/dist/init/linux-systemd/caddy.service
sudo cp caddy.service /etc/systemd/system/
sudo chown root:root /etc/systemd/system/caddy.service
sudo chmod 644 /etc/systemd/system/caddy.service
sudo systemctl daemon-reload
sudo systemctl start caddy.service
sudo systemctl enable caddy.service
```

### Create `Caddyfile`

```bash
sudo touch /etc/caddy/Caddyfile
sudo chown root:root /etc/caddy/Caddyfile
sudo chmod 644 /etc/caddy/Caddyfile
    
sudo vi /etc/caddy/Caddyfile	# edit Caddyfile with your preferred editor, here I use vi
```

We're gonna set up a simple reverse proxy to Ghost's port (2368). Here are 2 sample `Caddyfile`s respectively for Auto SSL enabled and disabled. 

```bash
# auto ssl
example.com, www.example.com {
    proxy / 127.0.0.1:2368
    tls admin@example.com
}
    
# no auto ssl
http://example.com, http://www.example.com {
    proxy / 127.0.0.1:2368
}
```

If you want Auto SSL issued by Let's Encrypt, you should put your email after the `tls` directive on the 3rd line; otherwise, use the second part of this `Caddyfile`. (For me, I was using Cloudflare flexible Auto SSL mode, so I just built a reverse proxy based on HTTP protocol only here)

### Fire it up 🔥

```bash
sudo systemctl start caddy.service
```

## References

- [https://ghost.org/docs/install/ubuntu](https://ghost.org/docs/install/ubuntu/#overview)
- [https://github.com/caddyserver/caddy/tree/master/dist/init/linux-systemd](https://github.com/caddyserver/caddy/tree/master/dist/init/linux-systemd)
- [https://github.com/nvm-sh/nvm](https://github.com/nvm-sh/nvm)