This tutorial will show you how to set up a blog using Cloudflare and Ghost. Cloudflare will improve performance and security by acting as a caching reverse-proxy.

What is Cloudflare?

Cloudflare is a service that acts as a middleman between a website and its end users. End users connect to Cloudflare servers, which retrieve content from the website's origin. Cloudflare can act as a firewall and allow/deny requests based on conditions, such as location. Lastly, Cloudflare can often improve performance by directly serving cached content to users without contacting the origin server.

How to use Cloudflare

Cloudflare has a free plan that provides DDoS protection and up to 3 page rules.

Register your account, and then add your first site.

Next, you need to log in to your domain registrar and set the domain to use Cloudflare servers.

Once the DNS has propagated, create the certificate/key for the origin server. This can be accessed in the crypto section. This certificate/key is used to secure the link between the origin server and cloudflare. Make sure you save this.

Next, we configure the cloudflare servers to provide a certificate to the origin server. Enable authenticated origin pulls

Next, in the DNS section, add the new IP address of the origin server

Protecting the admin interface

To improve the security of the blog, the admin interface will only be accessible from a specific autonomous system (only from your ISP networks, in other words). You can find your ISP AS number at Click firewall, and then add rule. The rule will block traffic if the path contains /ghost/ and the AS num does not equal 20473 (my isp)

Attempts to access the admin interface from other networks, will be blocked and logged, displaying the following message to clients

Configuring the origin server

I've made an installation script that will automate the whole process of configuring the origin server; all you need to do is add your key and certificate

The script does the following things:

1. Installs docker and docker compose

2. Installs and configures socat to serve the blog over TLS, checking the client provides a valid certificate; this means only cloudflare servers can access the origin server

3.  Configures a production Ghost environment with a separate MySQL database container using docker compose.

#! /bin/bash

mkdir /root/socat-ghost
# Put your certficate here
cat > /root/socat-ghost/origin-cert.pem << EOF

# Put your key here
cat > /root/socat-ghost/origin-key.pem << EOF

# Download origin ca
curl -fSsL --output /root/socat-ghost/origin-ca.pem

# Install and enable socat 
apt-get update
apt-get -y install socat 

# Socat systemd unit
cat > /etc/systemd/system/socat.service << EOF
ExecStart=/usr/bin/socat openssl-listen:443,su=nobody,certificate=/root/socat-ghost/origin-cert.pem,key=/root/socat-ghost/origin-key.pem,cafile=/root/socat-ghost/origin-ca.pem,verify=1,fork tcp-connect:
systemctl daemon-reload
systemctl enable socat.service 
systemctl start socat.service 

# Install and enable docker 
curl -fsSL | sh -
systemctl enable containerd.service docker.service
systemctl start docker.service

# Install docker-compose
curl -L "$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# Start ghost docker compose environment
mkdir /root/docker-ghost && cd /root/docker-ghost

# Docker-compose yml
cat > docker-compose.yml << EOF
version: "2"
    image: ghost
      - ghostdata:/var/lib/ghost/content
      - "2368:2368"
      - url=
      - database__client=mysql
      - database__connection__host=db
      - database__connection__user=ghostdb
      - database__connection__password=secret
      - database__connection__database=ghostdb
      - VIRTUAL_PORT=2368
      - db
    restart: unless-stopped
    image: mariadb
      - ghostdb:/var/lib/mysql
      - MYSQL_ROOT_PASSWORD=supersecret
      - MYSQL_DATABASE=ghostdb
      - MYSQL_USER=ghostdb
      - MYSQL_PASSWORD=secret
    restart: unless-stopped

# Start docker compose
/usr/local/bin/docker-compose up -d
systemctl start socat.service