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 bgp.he.net. 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 -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- EOF # # Put your key here # cat > /root/socat-ghost/origin-key.pem << EOF -----BEGIN PRIVATE KEY----- -----END PRIVATE KEY----- EOF # # Download origin ca # curl -fSsL https://support.cloudflare.com/hc/en-us/article_attachments/201243967/origin-pull-ca.pem --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 [Unit] After=network.target [Service] Type=simple Restart=always 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:0.0.0.0:2368 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable socat.service systemctl start socat.service # # Install and enable docker # curl -fsSL https://get.docker.com | sh - systemctl enable containerd.service docker.service systemctl start docker.service # # Install docker-compose # curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(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" services: ghost: image: ghost volumes: - ghostdata:/var/lib/ghost/content ports: - "2368:2368" environment: - url=http://test.etherarp.net - database__client=mysql - database__connection__host=db - database__connection__user=ghostdb - database__connection__password=secret - database__connection__database=ghostdb - VIRTUAL_HOST=test.etherarp.net,www.test.etherarp.net - VIRTUAL_PORT=2368 depends_on: - db restart: unless-stopped db: image: mariadb volumes: - ghostdb:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=supersecret - MYSQL_DATABASE=ghostdb - MYSQL_USER=ghostdb - MYSQL_PASSWORD=secret restart: unless-stopped volumes: ghostdb: ghostdata: EOF # # Start docker compose # /usr/local/bin/docker-compose up -d systemctl start socat.service