So many options…

When thinking about hosting a new blog in 2020 I immediately faced numerous options on how to do it.

These are only a couple of the more obvious choices:

None of those seems to be a perfect fit for my needs. Going with Wordpress would mean to dig into PHP (again); something I have briefly touched back in 2007 and wasn’t looking forward to spend more time with. In addition using a self-hosted variant would have the same challenges as setting up a custom server (see below). If using a managed Wordpress service instead, you will be restricted by the features offered from the provider. The same is true when using a blog service such as Write.as, which might offer additional, pre-selected features if you are willing to pay (more).

Static hosting seems to be the new trending topic and looks like being a perfect fit for a blog. Still GitHub Pages, which is based on Jekyll and uses the Ruby language (also not part of my programming language portfolio), as well as GitLab Pages, which at least offers more choices for the static site generator to be used, might rather be a better fit for (OSS) project-specific documentation Web sites than for a (single) user blog. I briefly thought about the Amazon S3 option as this would allow me to also enhance my blog with dynamic content by introducing additional AWS cloud features (such as serverless functions) if needed, but the initial setup including a custom domain with Amazon Route53 looks rather complex and restricts myself to Amazon services. In addition you need to find an automated way to build your static site and publish it to the S3 bucket as new posts are ready to be released. And as I don’t have the time to spend a lot of effort into setting up and managing infrastructure, the Amazon S3 and the custom server option, the latter would also mean taking care about OS and runtime updates, were out of the game.

This initial brainstorming gave me some input on the features I would expect from my blogging platform of choice though:

  • use some sort of a static side generator, which allows me to write my posts in markdown
  • still I need a way to automatically build and deploy the artifacts from the static site generator as soon as a new article gets published
  • a bit of flexibility in regards to the features offered; if not build into the static side generator directly, some kind of serverless function execution would be welcomed (it will get additional bonus points if it supports a language I’m interested in or familiar with)
  • less burden on setting up and managing the infrastructure required to host the static site (as well as the serverless functions if any)

Luckily I eventually found a fitting hosting platform. I was looking for some conference or meetup recordings about the Rust programming language when I stumbled upon this talk from Steve Klabnik, who is one of the core contributors to the Rust language and an author of the Rust Programming Book, a couple of weeks ago…

After watching this talk it was clear to me that the answer to my hosting platform of choice will be CloudFlare Workers.

Once upon a time… there was a CDN

Initially a Content Delivery Network such as CloudFlare CDN has been established to bring static Web site content and multimedia assets such as images and videos closer to the end users with the objective to reduce network latency. To achieve this target CDN providers have build up a large-scale network around the globe. If you take a look at the datacenter map from CloudFlare you will see that it has servers in more than 95 countries, which even goes beyond the reach you will get when using one of the current Top 3 cloud providers Amazon Web Services, Microsoft Azure and Google Cloud.

CloudFlare Data Centers
Source: https://developers.cloudflare.com/workers/about/how-it-works/

Recently those providers are looking for ways to enable customers to also host dynamic content within their networks. As such the two major CDN providers have been working on some kind of serverless platform: Fastly has announced a “computing at the edge” feature based on WASM named Terrarium, and CloudFlare launched Workers as an alternative to containers in 2018.

CloudFlare’s platform is based on V8 isolates, which are part of the same V8 engine that is used in Chromium-based Web browsers as well as Node.js. In that context an isolate represents a sandboxed and isolated runtime environment that can execute code. In the beginning this was limited to run JavaScript only, but the integration of a WASM runtime opened it up for any kind of language that can target WASM such as Rust, C/C++, or even Cobol.

Beside being able to host custom code CloudFlare also offers Worker Sites since last year, which is build ontop of the current serverless runtime and a distributed distributed database named Workers KV. The latter is used to store the assets of a static side generator as we will see shortly.

Blogging for Nerds in 2020

Based on my decision to go with CloudFlare Workers and Worker Sites for hosting my blog I just had to select a static side generator and workflow that suited my writing and publishing requirements.

The tutorials for CloudFlare Sites have guidelines on how to get started, and also mention some of the commonly used static side generators - on a funny side note they even give an advise on how to host a static Wordpress site… 😄. I searched for something more Rustacean (aka build on Rust), and found Zola, which I promptly installed on my Pinebook Pro to set up my new blog.

The sources of my blog are hosted on SourceHut, which is a free and open source alternative to GitHub and GitLab. It also offers build jobs that get executed as soon as a commit is pushed to a Git repository. The steps necessary to build and publish my blog are stated in a build.yml in the Git repository and are straigthforward:

image: archlinux
packages:
  - nodejs
  - npm
  - zola-bin
sources:
  - https://git.sr.ht/~appelgriebsch/...
secrets:
  - <git repo access key>
  - <cloudflare workers api key>
tasks:
  - setup: |
      cd website
      npm install @cloudflare/wrangler
  - build: |
      cd website
      zola build
      npx wrangler publish

First it has to install a couple of prerequisites:

  1. Node.js (used by the CloudFlare Wrangler CLI)
  2. Zola (used to compile my blog pages)

After synchronising the Git repository it changes into the blog source directory and installs the CloudFlare Wrangler CLI. After that it builds the static Web site content from the markdown files into a local public/ directory, and last-but-not-least calls the publish command on the Wrangler CLI. The latter is using a custom configuration file to figure out what has to be pushed to the Worker Sites:

name = "my-blog"
type = "webpack"
# settings from the CloudFlare dashboard
account_id = "<cloudflare account id>"
zone_id = "<cloudflare zone id for my custom domain>"
# don't forget the wildcard at the end
route = "www.appelgriebsch.org/*"
# only publish on custom domain name
workers_dev = false

[site]
# static content from the public/ subdirectory has to be published
bucket = "public/"
# publish as a Workers Site
entry-point = "workers-site"

The status of your CloudFlare Workers can be checked at the CloudFlare Dashboard, which also gives you some performance metrics for each Worker:

CloudFlare Workers Performance Dashboard

As mentioned before the Worker Sites store all the static assets of the blog in the Workers KV database:

CloudFlare KV Database for Blog

When investigating the index.js file that starts the CloudFlare Worker I can already grab some of the internal hosting details:

// import utility functions for the KV database interaction
import {
  getAssetFromKV,
  mapRequestToAsset,
} from "@cloudflare/kv-asset-handler";

// this event is triggered as soon as a request comes in
addEventListener("fetch", (event) => {
  try {
    event.respondWith(handleEvent(event));
  } catch (e) {
    event.respondWith(new Response("Internal Error", { status: 500 }));
  }
});

// async/await !!!
async function handleEvent(event) {
  // extract the requested URL
  const url = new URL(event.request.url);
  let options = {};

  try {
    // fetch the blob from the KV database and return it
    return await getAssetFromKV(event, options);
  } catch (e) {
    try {
      // in case of an error check for a custom 404.html
      let notFoundResponse = await getAssetFromKV(event, {
        mapRequestToAsset: (req) =>
          new Request(`${new URL(req.url).origin}/404.html`, req),
      });
      return new Response(notFoundResponse.body, {
        ...notFoundResponse,
        status: 404,
      });
    } catch (e) {}
  }
}

That’s all for today. I hope you have enjoyed my ride on how to host a blog in 2020 if you’re a Nerd like me. For sure I will do some more hacking against the CloudFlare Workers serverless platform especially in regards to Web APIs and GraphQL endpoints, which I want to be written in Rust. So I will give another look at it, which is more from the hacking perspective, in a future blog post.

Please stay tuned!