I lived on GitHub Pages for static hosting for a long time. For example, this blog been hosted as https://mprokopov.github.io for years, just with the custom domain https://prokopov.me
But last week I finally moved everything to CloudFlare Pages and quite happy about it!
The major driver for the change was a hassle of management github-pages. It’s either your have to keep everything in a separate branch, with the name like github-pages
, or have to use completly different repository.
I chose the latter, and for a long time kept using two repositories, one with Hugo sources, second with rendered HTML. It was a bit painful to manage two git repositories in the same working tree, hugo build
renders the website to the public
folder. In addition, the repository with HTML should be public.
Another option for static hosting is AWS S3, but the problem, it’s very inefficient without having AWS CloudFront in front of S3, slow and costly. Adding AWS CloudFront adds to burden of infra management.
One more option is a Google Firebase Hosting, that includes free hosting. It’s nice, but the downside, setting up authentication for gcloud is a hassle.
Last week I decided to check what’s going on with CloudFlare, and it turns out they have a very generous offer on CloudFront Pages. Setting up GitHub Actions was as easy as adding this snippet
- name: Deploy to CloudFlare
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: <account-id>
command: pages deploy . --project-name=<project-name>
workingDirectory: public
And it works like a charm!
As the follow-up, Cloudflare Pages support even better integration with GitHub via GitHub App and allows to have a dedicated previews, which is for content with approval workflows is a very nice addition!
Nice part about infrastructure as a code, now it’s repeatable! I can add a new hosting just by adding a new terragrunt module in no time.
Example of terraform module. Also, DNS entry should be changed to CloudFlare provided CNAME for the website.
resource "cloudflare_pages_project" "main" {
name = var.project_name
account_id = var.account_id
production_branch = var.production_branch
}
resource "cloudflare_pages_domain" "main" {
account_id = var.account_id
project_name = var.project_name
domain = var.domain
depends_on = [
cloudflare_pages_project.main
]
}
It was a good decision!