Cloudflare Pages with Gitlab CI

Cloudflare Pages with Gitlab CI

September 28, 2022
Internet, Providers, CI/CD
Hugo, Cloudflare

This site is one of a couple static sites I’ve been maintaining. I’ve been deploying them locally on filesystem with rsync, then hosting a webserver to present the content. I’ve been using Cloudflare for a couple years for DNS specifically.

Over time they have released a portfolio of interesting products, providing source for many of their implementations. They have also been outspoken in the public about the uncomfortable role they play in censorship. The only major caveat to use of Cloudflare is that they have become a central pathway for packet movement of the Internet. With the CEO stating that Cloudflare is not a front there is still the worry that they are forced to comply with monitoring at scale (e.g. Room 641A).

Cloudflare Pages is a Jamstack platform which works very well for static sites. I’ll cover the two deployment methods

  • Former deployment with rsync to at-least “archive” it out in the open rather than in my git history
  • Current deployment with wrangler/pages

To remark on the hugo build stage, this site is using the hugo-book theme, which needs to be checked out as a submodule prior to being built.

Deploying with rsync to filesystem #

The goal here is to build the hugo site, stash the output as an artifact, then rsync the artifact over to a server via rsync/ssh:

stages:
  - build
  - local

variables:
  GIT_SUBMODULE_STRATEGY: recursive

build:
  stage: build
  image: registry.gitlab.com/pages/hugo/hugo_extended:latest
  script:
    - hugo
  artifacts:
    paths:
      - public
  only:
    - main

local:
  stage: local
  image: alpine:latest
  before_script:
    - apk add --update --no-cache rsync openssh openssh-client-common
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - echo ${DEPLOY_PRIVKEY} | base64 -d > ~/.ssh/id_deploy
    - chmod 600 ~/.ssh/id_deploy
    - ssh-keyscan -p ${DEPLOY_PORT} ${DEPLOY_HOST} >> ~/.ssh/known_hosts
  script:
    - rsync -avzP -e "ssh -p ${DEPLOY_PORT} -i ~/.ssh/id_deploy" --delete public/ ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}
  only:
    - main

I’m restricting the two stages via only because I don’t have a desire with this deployment method to push multiple instances to the server and have multiple site definitions.

Deploying with wrangler to Cloudflare #

The goal here is to build the hugo site, stash the output as an artifact, then use wrangler to deploy to a pages project.

Wrangler doesn’t currently support all the things you’d need to do a deployment from start to finish, specifically I was looking to control the custom domains via wrangler. I’d fiddled with doing this all via the API/Curl but for now it’s been easier to manage the project via the web interface and specify the project via a CI variable.

stages:
  - build
  - cloudflare

variables:
  GIT_SUBMODULE_STRATEGY: recursive

build:
  stage: build
  image: registry.gitlab.com/pages/hugo/hugo_extended:latest
  script:
    - hugo
  artifacts:
    paths:
      - public

cloudflare:
  stage: cloudflare
  image: node:latest
  script:
    - npm install -g wrangler
    - npx wrangler pages publish public/ --project-name=${CLOUDFLARE_PAGES_PROJECT} --branch=${CI_COMMIT_BRANCH}

Notice that I’ve removed the only restriction and am specifying the --branch=${CI_COMMIT_BRANCH}. If you deploy to a branch name other than main you will get a preview deployment which provides a link in the CI output.

The two required CI variables for wrangler are documented here:

  • CLOUDFLARE_ACCOUNT_ID
  • CLOUDFLARE_API_TOKEN

The only major thing I had to consider surmounting was that there is a filesize limit on the deployment which forced me to put my short videos elsewhere for now. s