Menu

JAM Stack with Zola and Cloudflare

rust icon

JAM Stack with Zola and Cloudflare


July 31st, 2020

What is Zola?

Zola is a static site generator, similar to Jekyll and Gatsby, built entirely in Rust.

Being built in Rust has some advantages. Zola is crazy fast and is a single binary with no dependencies. It's pretty similar to other static site generators, though, and if you're not a Rust developer interested in extending Zola at all, then the performance difference may not be enough justification for you to choose Zola over something like Jekyll.

While my examples in this post will showcase Zola, this process will work almost the same with any static site generator that you wish to use.

What are Cloudflare Worker Sites?

Cloudflare Worker Sites allow you deploy your static site directly to Cloudflare's CDN.

This is a big part of JAM Stack: moving from content generated dynamically on a server request to statically generated content delivered directly from a CDN. This removes the need to manage and maintain web servers.

Cloudflare Worker Sites are built on Cloudflare's "Workers product" and allow you to delivery your static site directly from the Cloudflare CDN.

Cloudflare Workers Sites are also pretty affordable at $5/month.

The process is incredible simple. In fact, I was able to get my site up and running in about an hour (including researching and reading documentation). To help with this, Cloudflare provides a nifty CLI tool (built using Rust!) called Wrangler.

Wrangler

Wrangler is a super fast CLI for Cloudflare Workers built in Rust. With Wrangler, you can initialize a site, configure it and publish. You can also preview and test your changes before publishing.

You can find the GitHub repo for Wrangler here. The full documentation can be found here.

I'll go over how to use Wrangler both locally and as a part of your CI/CD process in a moment.

Creating a Zola Site

Creating a site in Zola, while pretty simple, is a bit out of the scope of this post. However, Zola does provide a getting started guide that you can follow to get a site setup in minutes.

If you're familiar with something like Jekyll or Gatsby, this will all be pretty familiar for you.

Setting up Cloudflare Workers

Once you have a static site generated, you'll need to setup a Cloudflare Workers plan. Unfortunately, the free plan won't work for Worker Sites. You'll need the Unlimited plan, which is $5/month.

Once you've setup the plan, you'll just want to make note of your Account Id. You'll need this in a moment when you configure you're Workers site. Details on finding that here.

You'll also need to generate an API Token that Wrangler can use. You can do this from here: https://dash.cloudflare.com/profile/api-tokens. You'll want to use the Edit Workers template. Take note of this token as you won't be able to see it again later.

Configuring your Worker Site

Installing Wrangler

You can install Wrangler using NPM or Cargo: https://developers.cloudflare.com/workers/tooling/wrangler/install/.

Note: If you decide to use Cargo, it will take several minutes since cargo will compile the Wrangler binary for you.

Initialize the site

With Wrangler installed, you can run the following command from inside your site directory:

wrangler init

This will generated a wrangler.toml file and a workers-site directory.

Configure the site

Open the wrangler.toml file, and edit the account_id field with the account ID you noted earlier.

Also, set the bucket field under the [site] category to public. That might look something like this:

[site]
bucket = "./public"
entry-point = "workers-site"

If you're using a generator other than Zola, you'll need to use the output directory for that generator. Here's a few examples:

  • Hugo: public
  • Gatsby: public
  • Jekyll: _site
  • Eleventy: _site

Then you can run

wrangler config --api-key <YOUR_API_KEY>

Replace <YOUR_API_KEY> with the Cloudflare API key that you just generated.

A final, optional step would be to configure a production environment. By default, Wrangler will publish to a dev worker site. This will use your free http://<your-subdomain>.workers.dev subdomain.

If you want to use a custom, personal domain, you'll need to set that up in Cloudflare if you haven't already, and then get the Zone ID for that domain. Since the files will all be served up from Cloudflare and you won't be using any kind of web server, you can just create a dummy DNS record with a value of 1.2.3.4. More details here: https://developers.cloudflare.com/workers/quickstart#publish-to-your-domain.

Once you have you're zone id, you can add a production environment to your workers.toml:

[env.production]
zone_id = "your_zone_id"
route = "example.com/*"

The route should be your personal domain.

Publish your site

Publishing with Wrangler

Now that you're all configured, you can easily publish you're site with the following command:

wrangler publish

This will publish to your dev workers site and allow you to test before you publish to your production zone.

When you're ready to publish to your production environment, you can use the --env argument:

wrangler publish --env production

Now, at this point you're technically done. However, you'll have to run wrangler publish anytime you make any changes.

We can automate this really easily, though, by creating a CI/CD workflow using Github Actions.

Setting up CI/CD using Github Actions

We can create a completely automated CI/CD pipeline in just a few minutes using Github Actions. If you're not familiar with Github actions, I highly recommend checking them out. I'll go over a simple workflow that will build your site and publish to Cloudflare with just a little bit of yaml and all for free.

Action Secrets

First, a little configuration is needed. Just like when running locally, Wrangler needs you Cloudflare API token. You definitely don't want to put that in source control or anywhere else public. So, we'll make use of Github Secrets.

Secrets allow you to store sensitive information and pass to your actions in a safe way. These are encrypted and never exposed at any point.

Creating them are easy. Just go ton your github repository and then select Settings > Secrets > Add Secret. Full documentation can be read here.

Give it descriptive name, like CF_API_TOKEN.

Create Workflow

Now we can create our workflow.

In your site directory, create a folder called .github. Inside of that folder, create another folder called workflows.

Github will automatically discover the workflows in this folder and run them.

Now inside of .github/workflows, create a yaml file. You can name anything. For example, deploy.yml. Github does care about the naming.

Add the following to the contents:

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - uses: actions/checkout@master
      - name: Install and Run Zola Build
        run: |
          sudo snap install --edge zola
          zola build
      - name: Publish to Cloudflare
        uses: cloudflare/wrangler-action@1.2.0
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          environment: 'production'

This workflow tells Github that we want any push to the master branch to trigger this deployment. Pull requests will not trigger this deployment at all, neither will pushes to any other branch.

Next, we're telling Github that we want to run all of this inside an small ubuntu image with the latest version. We then take the following actions:

  • Checkout the master branch
  • Install Zola using snap and then run zola build to generate our site in the public folder.
  • Download and install Wrangler
  • Publish to the production environment using our Cloudflare API token (the secret we created earlier... CF_API_TOKEN).

That's it! Now any changes that you push to the master branch will automatically build and deploy to Cloudflare.

Now would probably be a good time to ensure that you have branch protection rules on the master branch. This is only available for Pro, Team and Enterprise users, though. So, if you're using a free account, you'll just have to be a little more careful about the master branch.

© 2023 Stefan Perales

Built with by peralysis