[With Screenshots] How to Migrate Your Blog Hosting from GitHub Pages to Cloudflare Pages

Why and how to move a Hugo blog from GitHub Pages to Cloudflare Pages. Covers build settings through switching your custom domain, with plenty of screenshots.

Table of Contents

Who This Article Is For

  • People who keep their blog source in a GitHub repository
  • People publishing a Hugo blog or static site on GitHub Pages
  • People torn between GitHub Pages and Cloudflare Pages for hosting their blog
  • People who want to move their blog hosting from GitHub Pages to Cloudflare Pages
  • People (with a custom domain) who want to publish a blog for free
  • People who registered their domain with Cloudflare and manage it with Cloudflare DNS

Architecture diagram before and after migrating from GitHub Pages to Cloudflare Pages

Figure 1: Architecture before and after migrating from GitHub Pages to Cloudflare Pages

Before the migration, GitHub handles source control, building, and publishing all by itself. After the migration, GitHub is limited to private source control, and Cloudflare Pages handles the Hugo build and publishing. The custom domain stays the same, so the URLs your readers use remain unchanged.

The screens, pricing, and plans shown in this article may change. Please check the official documentation as well when you try this yourself.

The screenshots in this article were taken with the Cloudflare dashboard set to Japanese. Button and menu names in the English UI may differ slightly from the labels used here.

Why Move Away from GitHub Pages?

GitHub Pages makes it easy to publish a static site managed on GitHub. It supports custom domains and HTTPS, so it’s perfectly convenient as a place to host a Hugo blog.

However, a blog repository contains more than just posts: Hugo configuration, themes, layouts, build settings, and so on.

And to use GitHub Pages for free, the repository has to be public. If a secret image or something similar ever slipped into the source repository by accident, it would be game over.

So I went looking for a host that would publish pages from a private repository for free. The answer: Cloudflare Pages.

GitHub Pages vs. Cloudflare Pages

ItemGitHub PagesCloudflare Pages
CostFree (GitHub Free)Free
Source controlGitHubGitHub
GitHub integration✓✓
Private repositoriesPublic repositories only on GitHub Free✓
BuildsAutomated with GitHub ActionsAutomated from the dashboard
Build limit on the free planNone (when using Actions)500 per month
Published site sizeUp to 1 GBUp to 20,000 files
Per-file limitAbout 105 MBAbout 26 MB
Custom domain✓ (optional)✓ (optional)

Managing the source on GitHub and building and publishing with GitHub Pages is a simple, easy-to-understand setup. On the other hand, if you want automatic deployments from a private repository, Cloudflare Pages is the better choice. For that reason, I decided to move to Cloudflare Pages, which supports private repositories. Well, to be fair, if something slips into static/ or a page bundle, it gets published even with a private repo…

Before You Migrate

Don’t shut down GitHub Pages first. Publish the site on Cloudflare Pages, check it at the pages.dev URL, and only then switch your custom domain. In this order, even if the build or DNS settings go wrong, you can fix things while your live site keeps running.

Before you start, write down the following:

  • The branch and deployment method you use for GitHub Pages
  • Your Hugo version, build command, and output directory

The steps in this article go in this order: Create the Cloudflare Pages project → Connect the GitHub repository → Configure the Hugo build → Check the site on pages.dev → Set up the custom domain → Clean up the GitHub Pages DNS records and workflow → Make the repository private → Redirect pages.dev to the custom domain

Create the Cloudflare Pages Project

1. Create a New Application from Workers & Pages

In the Cloudflare dashboard, open Workers & Pages and select Create application in the upper right.
Then press the Get started button.

Initial Cloudflare Workers & Pages screen showing the button to create an application

Figure 2: Create an application from Workers & Pages

Screen showing the link to get started with Cloudflare Pages

Figure 3: Get started with Pages

2. Connect Your GitHub Repository

Next, select Import an existing Git repository.

Screen showing the button to import an existing Git repository

Figure 4: Import an existing Git repository

Sign in to your GitHub account, select the target repository, and press Begin setup.
When authorizing on GitHub, granting the Cloudflare Workers & Pages GitHub App access to only this blog’s repository makes things easier to manage.

Screen for selecting the GitHub account and repository and starting setup

Figure 5: Select the GitHub repository

Hugo Build Settings

3. Enter the Hugo Build Settings

For a typical Hugo site, the settings are as follows.

SettingValue
Production branchmain (match the branch you currently publish from)
Framework presetHugo
Build commandhugo --gc --minify
Build output directorypublic

For this site, I set the build command to hugo --gc --minify as shown in the screenshot. --gc cleans up cache files that are no longer needed, and --minify compresses the generated HTML, CSS, and JavaScript. The output directory is public. See also Cloudflare’s Hugo guide.

Screen for configuring the Hugo build settings and HUGO_VERSION in Cloudflare Pages

Figure 6: Hugo build settings

If you want to pin the Hugo version you use, add HUGO_VERSION to the project’s environment variables. If the versions differ between your local machine and CI, themes or Markdown may render differently, so setting it is a safe bet if you value reproducibility. Note that production and preview environments have separate environment variable settings. If you also use preview deployments, make sure HUGO_VERSION is set for the Preview environment as well (check under the project’s settings), and add it there if it’s missing.

First Deployment and Verification

4. Check the Site on pages.dev

When you choose to deploy, Cloudflare Pages fetches the repository, runs Hugo, and serves public/. When it finishes, you’ll see the screen below and get a URL in the form https://<project>.pages.dev.

Once the deployment success screen appears, open the issued pages.dev URL and check the site. Don’t switch the custom domain yet.

Cloudflare Pages deployment success screen

Figure 7: First deployment complete

Before switching to my custom domain, I confirmed the site displayed correctly at this URL.

Switch Your Custom Domain to Cloudflare Pages

5. Add Your Custom Domain

If everything looks fine on pages.dev, add your custom domain from the Pages project’s Custom domains.

On the project screen, open the Custom domains tab. Then select Set up a custom domain.

Custom domains tab of the Cloudflare Pages project

Figure 8: Open the Custom domains tab

Screen showing the button to set up a custom domain

Figure 9: Start setting up the custom domain

Enter your registered domain and select Continue.

Screen for entering a custom domain in Cloudflare Pages

Figure 10: Enter your custom domain

If your DNS is managed by Cloudflare, review the DNS record shown and select Activate domain.

Screen for reviewing the DNS record proposed by Cloudflare Pages

Figure 11: Review the DNS record and activate the domain

If your domain’s DNS is managed by Cloudflare, follow the prompts to set up the DNS record for Pages.

Right after setup, the status shows Initializing. Wait until DNS and certificate processing finish. The screen says it can take up to 48 hours to take effect, but in my case, after waiting about a minute and reloading the page, the status changed to Active. Once SSL is enabled, you’re done.

Screen showing the Cloudflare Pages custom domain initializing

Figure 12: Custom domain initializing

Screen showing the Cloudflare Pages custom domain active

Figure 13: Custom domain setup complete

Once the switch is complete, your site should probably be showing up at https://your-domain/.

Clean Up the Old GitHub Pages Setup

After confirming that the site displays correctly on your custom domain via Cloudflare Pages, tidy up the old GitHub Pages settings. If you stop GitHub Pages or delete DNS records first, the site may become temporarily unreachable, so do this only after confirming the site is live on Cloudflare.

Delete Old DNS Records

In your DNS dashboard, check for any leftover records pointing to GitHub Pages. These are especially easy to miss:

  • A records pointing to GitHub Pages IP addresses such as 185.199.108.153
  • CNAME records pointing to <username>.github.io
  • GitHub Pages A/CNAME records left on subdomains such as www

After confirming that the Cloudflare Pages record is working correctly, delete only the unneeded GitHub Pages records. Compare each record’s target one by one so you don’t delete the Cloudflare Pages record.

Delete the GitHub Actions Pages Workflow

If you built and published with GitHub Actions for GitHub Pages, the Pages workflow in .github/workflows/ is no longer needed. If you leave it and make the repository private, a failing workflow will run on every push and eat into your Actions quota.

Delete and commit only the workflow you’ve confirmed is for Pages. Be careful not to delete other CI workflows by mistake.

git rm .github/workflows/<github-pages-workflow>.yml
git commit -m "Remove GitHub Pages workflow"
git push

Make the Repository Private

6. Make the GitHub Repository Private

Once you’ve confirmed the site displays correctly on your custom domain, change the repository’s Visibility to Private in the GitHub repository settings.

Fellow Free-plan users probably can’t use GitHub Pages with a private repository anyway, but check that GitHub Pages is turned OFF just in case.

After the change, actually edit something small, such as a post, push it, and confirm that a new build runs in the Cloudflare Pages deployment list. To avoid accidentally adding secrets or unrelated files, check your changes with git status first.

git status
# Add only the files you edited
git add content/blog/<edited-post>/index.md
git commit -m "Verify Cloudflare Pages deployment"
git push

If the new deployment succeeds on Cloudflare Pages and your edit appears on the site, automatic deployment after going private is working correctly.

Redirect pages.dev to Your Custom Domain

7. Redirect pages.dev Traffic to Your Custom Domain

On Cloudflare Pages, the site is still reachable at <project-name>.pages.dev even after you set up a custom domain. To keep search engines and readers from using multiple URLs, redirecting pages.dev traffic to your custom domain is just sexier, right?

Here, I’ll use Cloudflare’s Bulk Redirects to set up a redirect from document-6eg.pages.dev to https://mitz17.com as an example. Replace these with your own project name and domain. Please take care not to redirect your site to mitz17.com. (Not that I’d mind.)

7-1. Create a Bulk Redirect List

On your Cloudflare account screen, open Bulk Redirects (under the delivery and performance section of the sidebar). Select Create in the upper right.

Cloudflare Bulk Redirects screen showing the Create button

Figure 14: Create a bulk redirect list

Enter a list name. Here I used pages_dev_redirect. Any name that’s easy to manage is fine. After entering it, select Next.

Screen for entering the Cloudflare bulk redirect list name

Figure 15: Name the redirect list

7-2. Register the Redirect from pages.dev to Your Custom Domain

Open Or, manually add URL redirects and enter the following. Replace the source and target URLs to match your own environment.

ItemValue
Source URLdocument-6eg.pages.dev
Target URLhttps://mitz17.com
Status301 - Permanent Redirect

As in the screenshot, check Include subdomains if you also want subdomains to be redirected. Feel free to check any of the other options as well.
After entering everything, select Next.

Screen for adding a 301 redirect from pages.dev to the custom domain

Figure 16: Register the redirect target

7-3. Enable the Redirect Rule

Creating the list alone doesn’t make the redirect work. On the completion screen, select Proceed to redirect rules and link the list you created to a rule.

Screen for proceeding to the Cloudflare redirect rule settings

Figure 17: Proceed to the redirect rule settings

Enter a rule name and select the pages_dev_redirect list you just created as the redirect list. Finally, select Save and Deploy.

Screen for saving and deploying a bulk redirect rule in Cloudflare

Figure 18: Deploy the redirect rule

After setting it up, visit https://document-6eg.pages.dev and confirm that it 301-redirects to https://mitz17.com. Your browser cache may interfere, so checking in a private window or with curl -I is the most reliable way.

Closing

I sincerely hope this improves your QOBL (Quality of Blog Life).

Share this article

X (Twitter) Bluesky
Built with Hugo
Theme Stack designed by Jimmy