Host Hugo as GitHub Pages

About half a year ago, I set up a GitHub Actions to deploy Hugo blog to self-hosted VPS. It had been working pretty well so far.

Recently, I reviewed the application running on my VPS and found there’re only a WireGuard proxy and a MTProxy except this blog. Those two proxies hadn’t been used often since we moved to New Zealand, and the VPS provided by Vultr costs us USD$3.5 every month. To save the money, I decide to migrant this Hugo blog to GitHub Pages.

New Workflow

First thing first. A new workflow file .github/workflows/gh-pages.yml is required to build and deploy the generated static blog to GitHub Pages every time I push a commit to the repo. Given the example listed on Hugo Docs, the only thing you might need to change is the branch name used in the workflow, be main or be master, that’s a question.

name: GitHub Pages

    branches: [ master ]

    runs-on: ubuntu-latest

    - uses: yestyle/checkout@v2
        submodules: 'recursive'

    - name: Setup Hugo
      uses: yestyle/actions-hugo@v2

    - name: Build
      run: |
        hugo --minify --quiet

    - name: Deploy
      uses: yestyle/actions-gh-pages@v3
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./public

Settings of the repository

  1. Rename the repository to

The name of my repository used to be lancitou-on-hugo, which will make the published site as (project site). To make it accessible as (user site), I need to rename the repository to Check GitHub Docs if you’re not clear with the types of GitHub Pages sites.

  1. Set the source of the GitHub Pages as gh-pages branch

In the Settings of the repository, go to Pages and select gh-pages as the source of the GitHub Pages branch.

Set the custom domain

After the above steps, my blog should be accessible via, but I want it accessible via as well. That’s the purpose of the custom domain setting.

  1. Custom domain setting of GitHub repository

You might notice there’s a custom domain on the Pages settings mentioned above.

Please don’t use it! After you set a new value in this field, GitHub will push a new CNAME file in the root directory of the gh-pages branch of your repository. But every time you update your blog and push to master or main branch, GitHub will build and deploy the generated static blog in public directory to gh-pages branch, which will remove the CNAME file created before.

Hope my explanation doesn’t confuse you. The solution is create a CNAME file in static directory of Hugo (master or main branch) and your custom domain name should be the only contents inside CNAME. That’s also the guideline on Hugo Docs.

By the way, I highly recommend you enable “Enforce HTTPS” as well. That’s a setting you can use.

  1. CNAME record on DNS provider

In the “Manage DNS Records” page of, add a CNAME record resolving to

Now, if you visit, you will be redirected to Fantastic!

However, because GitHub can only redirect an apex domain to www subdomain, but I’m using blog subdomain, so when you visit or, you’ll get 404 errors. Hope I could find an elegant solution later.

Clear up

  1. Remove old workflow

The workflow setup for self-hosted VPS can be removed.

  1. Backup files on VPS

Any files saved on VPS need to be downloaded and backup, especially the SSH keys in the ~/.ssh directory.

  1. Destroy VPS

Before I murdered the VPS, I took a scan copy of its photo ID:

Then I pulled the trigger. No more VPS running on the cloud!

Have fun!

comments powered by Disqus