Deploying Ghost

Given that this will be a blog mainly focused on the technical side of things, I find it fitting that one of the first posts is how this blog even came to be – from a technical standpoint.

Why Ghost?

While deciding for a blogging platform, the three main choices I found were Medium, WordPress and Ghost. I decided to use Ghost because it has the option of self-hosting, it's very light and its writing UI is very easy to use.

Using Docker

Since most of my infrastructure is hosted on Docker, it seemed obvious to also use it for Ghost. After the first test setup, I ran into a few issues.

The first issue has to do with how Docker works with UFW, my firewall of choice. Docker does not honor UFW and instead ignores them. This may lead to many security issues. The second issue is that the Docker version of Ghost does not support the Ghost-cli needed to properly configure Let's Encrypt.

Thankfully, I was able to solve both of those issues with a quick config change of Caddy. I set the Ghost container to only open a port to localhost, thus solving the Docker vulnerability.

sudo docker run -d \
-v /path/to/local/files:/var/lib/ghost/content \
-p 127.0.0.1:2368:2368 \
-e url=https://blog.skret.net \
--name ghost \
ghost:latest

I then used Caddy's reverse_proxy directive and pointed it from blog.skret.net to localhost:ghost_port. Caddy also features automatic HTTPS encryption, so by using it as the proxy, I was able to solve both security issues.

blog.skret.net {
        reverse_proxy * localhost:2368
}

Setting up mail

To make Ghost fully functional, it needs access to an SMTP server. At first, I used my personal gmail address, but then someone pointed me to MailGun and it's free tier included in the GitHub for students pack. After signing up, the setup was easy and painless.

First of all, I entered the subdomain I want MailGun to use, and then MailGun provided me with all the DNS settings necessary to set it up. I had to add a TXT record, a CNAME record and an NX record. A few minutes after all the records were added, MailGun already confirmed the subdomain was working in proper order.

All I had to do now was to put all the necessary details provided by MailGun into the Docker run command and run it.

sudo docker run -d \
-v /path/to/local/files:/var/lib/ghost/content \
-p 127.0.0.1:2368:2368 \
-e url=https://blog.skret.net \
-e mail__transport="SMTP" \
-e mail__from="Blog <email@example.com>" \
-e mail__options__service="SMTP" \
-e mail__options__auth__user="username" \
-e mail__options__auth__pass="password" \
-e mail__options__host="mail address" \
-e mail__options__port="587" \
--name ghost \
ghost:latest