Cloudflare Pages Migration Notes
Ever since I started the journey with static websites , I have always loved using the Jekyll or Hugo + GitLab Pages combo. A few examples include:
- this site
- Ubucon Europe Portugal - a static website for Ubucon Europe back in 2019;
- adistancia.ansol.org - a static website listing open source software for schools and teachers to use during COVID-19 and lockdown times.
- More private ones, granted.
The main reason I enjoy it is things work right out of the box, after the initial point & click instructions and it is effortless.
However, one major downside led me to rethink the approach and try a new product (to me, as it is not necessarily
new): Cloudflare Pages. Cloudflare Pages is a JAMstack platform, where you can deploy
your static websites (or add functionality using Functions, which resembles a lot AWS Lambda’s) and has one big features
that matter to me: Redirects. With redirects, I can finally take down the ugly default link GitLab (and
GitHub) Pages set for your domain: <repo>.gitlab.io
or <repo>.github.io
.
This post is about some notes on this migration to Cloudflare Pages, as my approach gives more control over the pipelines that deploy resources and uses other tools to upload files, instead of integrating Cloudflare with your VCS of choice.
Local Testing
The product’s main selling point is that you simply integrate your Cloudflare account with your Git platform (GitHub or
GitLab) and you can automatically start deploying sites after things get merged in the “production branch”. I personally
wanted to stay in control of all my pipelines, so I essentially re-did my repositories’ pipelines in GitLab to account
for this new approach. In a later chapter, I’ll cover what those stages look like.
In a nutshell, after building you site and generating all the static files it needs, you can use wrangler
to deploy your site into your pages. First, however, create the application in the UI so you know where to deploy. Go
to “Workers & Pages” > “Create application” and proceed from there. Beware the project name will automatically be granted
a subdomain in *.pages.dev
, which is pretty much like <repo>.gitlab/hub.io
. This was quick to do, after configuring
wrangler, you can simply run
wrangler pages publish <OUTPUT_DIRECTORY> --branch=<default branch>
and your website will be published to Cloudflare
Pages. However, this raises some problems.
CSS Broken Paths
In my Hugo config, I am setting a baseUrl
which suffixes all resources with this path. After the steps from above, the
website was essentially broken and everything was misplaced - another thing I noticed is that I have not changed the DNS
Records setup from GitLab (you essentially add GitLab’s nameservers on Cloudflare and a CNAME to GitLab) - so I went to
my account’s DNS Records setup, removed all setup related to GitLab, then connected my Cloudflare Pages project with my
own custom domain and site. It automatically creates a CNAME
record for you (your custom domain pointing to
Cloudflare’s infrastructure), with DNSSEC
and a few other cool features. But this does not resolve the ugly paths -
that was thanks to Bulk Redirects
, which are, essentially, redirect rules that get applied to all accounts1.
I did one to redirect all requests to Cloudflare’s provided *.pages.dev
domain to gsilvapt.me
- and voilá, my assets
were back!
GitLab CI Changes
As mentioned, I wanted to stay in control of my pipelines after this migration. Moving to point & click solutions was not appealing. With the following two stages, you can basically repeat what I described in the Local Testing and deploy your changes to your Pages site very quickly:
1build:
2 stage: build
3 script: hugo
4 artifacts:
5 name: build
6 paths:
7 - public/
8 expire_in: 1 day
9
10deploy:
11 image: node:latest
12 stage: deploy
13 dependencies:
14 - build
15 script:
16 - npm install -g wrangler
17 - wrangler pages deploy public --project-name=gsilvapt-me --branch=main
18 rules:
19 - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
The first stage, build
, will have to build the static assets for the site. Using the artifacts
](https://docs.gitlab.com/ee/ci/jobs/job_artifacts.html)
functionality from GitLab, you can cache results without having to constantly building. It’s not that big of a site and
it’s not that hours matter on the free tier, but hey… Optimization matters to me, okay? :)
The deploy stage uses node
-based image to install wrangler
and call the commands to deploy the project. You are
probably wondering how auth is performed at this point and that is a good question. Wrangler supports environment
variables for things like the account ID, zone ID and API token, which are all the keys you need to authenticate with
the services. Thus, go to your repositories variable settings and add the following variables:
CF_ZONE_ID
- so it knows which zone ID to deploy changes.CLOUDFLARE_ACCOUNT_ID
- same, but for the account.CLOUDFLARE_API_TOKEN
- this is a user-generated token for this purpose only. I used one of the templates for workers, with specific permissions to read/write with Workers and Pages.
A cool thing about GitLab Pipelines is that you can specify the rules in which the stage is added to the pipeline. For
now, by default, I am only deploying to production resources that get merged into the default branch (main
). However,
Cloudflare Pages support different environments to publish changes, so it would be nice to use the merge request pipeline
to deploy the resources in staging first, so I can view the changes, and only when merged things get deployed to
production (which is something as simple as dynamically adding --branch=main
when I want to publish to production).
On the other hand, it might be total overkill, considering this is a personal site and there’s no reason to complicate
that much.
Thank you for reading and hope this quick post helps you bootstrap your next Hugo + Cloudflare Pages site, without using their integration on GitHub/GitLab.