I recently blogged about how I moved my website from being a custom Ruby on Rails blog hosted in AWS to Ghost(Pro) fronted by Cloudflare.
Switching over to Ghost(Pro) was a fairly slick process until I got an email from Keybase informing me that I’d broken my websites Proof:
Keybase is a key directory that offers end-to-end chat encryption as well as identity proofs that allow you to prove a link between your online identities (Websites, Twitter, GitHub, etc) and your encryption key.
I had setup my website to host a Keybase proof (text file) that proved as a cryptographic link between my website and my encryption key.
Cloudflare Workers to the Rescue!
When I planned to migrate to Ghost(Pro) and Cloudflare, I’d completely forgotten about Keybase and the proof that the site was hosting.
The challenge I faced is that Ghost is a blogging platform, and doesn’t have provisions for hosting text files or doing anything outside of being a great blogging platform.
I can use a Cloudflare Worker to intercept the request made by Keybase for the proof file and respond with the proof instead of sending the request on to Ghost. The Keybase proof is a text file that sits in the
Let's take a look at how we can write some code for a Cloudflare Worker and version control it in git.
npm i @cloudflare/wrangler -g
We need to configure Wrangler with an API token from the Cloudflare Dashboard:
Cloudflare provides a number of templates for creating an API token with refined permissions:
Pick Edit Cloudflare Workers. As this is my personal account I was comfortable creating an API token that has access to all Account Resources and all Zone Resources, so I set these both to include all accounts and include all zones under the respective Account Resources and Zone Resources sections.
From your terminal window run
wrangler config and provide your API token that you've just created.
Now we can create our new project:
$ wrangler generate cloudflare-worker-security Installing cargo-generate... Creating project called `cloudflare-worker-security`... Done! New project created /home/james/projects/cloudflare-worker-security You will need to update the following fields in the created wrangler.toml file before continuing: You can find your account_id and zone_id in the right sidebar of the zone overview tab at https://dash.cloudflare.com - account_id
A Keybase proof is a textfile that's generated from Keybase and that you host as a specific URL such as
/.well-known/keybase.txt. Whilst doing this I also wanted to setup a security.txt that provides anyone wanted to report a security vulnerability with clear instructions of how to contact the person responsible for security of the website.
In short, our worker just needs to serve up some text files in response to specific requests.
The Keybase proof is fairly big, and I don't want to try and embed the contents of the textfiles within the code, I'd rather reference the text files.
raw-loader is a webpack module that allows strings to be loaded from text files.
Wrangler knows how to handle our code based on the
wrangler.toml file in our project. We will need to alter this to setup our project to use webpack, and to ensure that the worker serves traffic from the correct route:
We now need to create the
webpack.config.js file so that webpack will load the
txt files using
Now that we're able to load in text files we can implement the logic for our worker:
We could now publish this with
wrangler publish if we wanted to publish this from our own machine.
It's worth noting that in the
wrangler.toml file we did not configure an
account_id or a
zone_id. I did this deliberately as I wanted to share my code online in a fairly easy to re-use fashion.
You can go back and populate those values in the
toml file, or you can pass the values in using environment variables:
$ CF_ACCOUNT_ID=xyz CF_ZONE_ID=abc wrangler publish
Being able to set these values via environment variables will be important when we attempt to automate the deployment of our worker.
Deploying with GitHub Actions
Last summer GitHub announced that they'd be launching a new set of functionality called GitHub Actions. It's aimed at automating workflows, from typical CI/CD tasks, through to automation around issues and pull requests.
Needless to say, I'd been looking forwards to playing with it:
When I wrote about moving my website from a custom Rails app to Ghost, the intention was to spend less time maintaining my website and more time working on projects and writing them up. With that in mind I wanted to make sure that updating the security.txt or Keybase proof is just a change to the text file and a
git push – this is where GitHub Actions comes in.
GitHub Action workflows are defined as yaml files in .
github/workflows of a given repository.
One of the great things about the GitHub Actions ecosystem is that anyone can write and publish an action that can be re-used by anyone. The folks over at Cloudflare have written a wrangler-action that we can leverage!
This workflow is designed to run a master branch push. When a change is pushed to master, Actions will run a series of steps on an Ubuntu image under a job called "Deploy":
- Checkout the git repository
- Run the
apiTokenas an argument and setting
The values for the API Token, Account ID and Zone ID are read from the Secrets in your GitHub repository settings. This allows you to have public repositories that can use Actions without exposing secrets to the general public:
I can now push my code to GitHub and let GitHub Actions take care of publishing the code to my Cloudflare account:
A few minutes after doing this I got an email from Keybase confirming that the proof was now working again:
I've also made the code for this publicly available in my cloudflare-worker-security repo on GitHub.