Recently, I have started moving my non-critical websites to GitHub pages. I am documenting the process in one place for future me.
Objectives
- I should be able to edit the website by committing to a git repository.
- We can also modify the blog using the web IDE if needed.
- The system must generate the website after every push and deploy it to GitHub pages.
- I want to use my own custom domain.
Requirements
- You have a custom domain. Mine are registered with Namecheap.
- You either have a generated website or you can use a static website generator like Hugo.
- You have a GitHub account.
GitHub Project Sites
If you have a GitHub account (either user or organization) you can have a
website using GitHub pages at your-account.github.io
. These are called user or
organization sites.
Each project in an account can have its own website. These are called Project
sites. They are available under your-account.github.io/repository-name
.
We are going to leverage these project sites and deploy each project with a custom domain.
For more info please see https://docs.github.com/en/github/working-with-github-pages/about-github-pages#types-of-github-pages-sites.
The Process
I am going to write this as concise as I can.
Step 1: Change the DNS Records
You need to change the DNS records of your custom domain. This change is very quick if your existing DNS is handled by Namecheap (e.g., a new domain) but it took 24 hours for my AWS hosted websites.
If your domain has any existing DNS records, you need to delete them. This also includes the default records pointing to the Namecheap parking page for new domains.
One of my domains was hosted out of an S3 bucket so I had pointed the DNS
records to Amazon. In NameCheap, I had to switch the DNS back to Namecheap BasicDNS
under Nameservers
in the Domain
tab. This Namecheap KB article
shows how:
After switching, switch to the Advanced DNS
tab and create five records.
- Four
A records
with host@
and the following values:185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153
CNAME
record with hostwww
and valueyour-account.github.io.
.- Note the extra dot in the end. This is needed for project sites.
Reference: https://deanattali.com/blog/multiple-github-pages-domains/
Namecheap has a guide for using user or organization GitHub pages. The process is the same as above except the value of the CNAME record:
Step 2: Creating a Deploy Workflow
The workflow is pretty straightforward and based on this Hugo docs page:
begbounty.com is a simple single page Hugo website. But it works for more complex deployments.
You can see the workflow here:
The peaceiris-actions-hugo
action builds the Hugo website. If your website
does not need the extended version, be sure to remove the extended: true
field.
peaceiris/actions-gh-pages
grabs the generated files from the public
directory and stores them in the gh-pages
branch.
There is no need to setup the secrets.GITHUB_TOKEN
token manually.
Note: I did not have this issue but the first deployment run might encounter some issues and you have to do re-run it.
Step 3: Push a Commit
We need to get the workflow to create the gh-pages
branch. This is where you
can troubleshoot the site build. Clone the resulting branch locally to see how
the site looks like and fix any issues.
Step 4: Repository Settings
Now, we need to setup the repository.
- Go to the repository's
Settings
on GitHub. - Select
Pages
from the sidebar. - Under
Source
select thegh-pages
branch. - Under
Custom domain
enter your domain. E.g.,begbounty.com
.- This will create a file in the root of the repository named
CNAME
with value ofbegbounty.com
. This is useless for a Hugo website but I chose to keep it. - For Hugo websites, you should create it in
static/CNAME
. If you follow the instructions on the Hugo documentation page linked above, you already it.
- This will create a file in the root of the repository named
- Enable
Enforce HTTPS
. This will generate a certificate byLet's Encrypt
. This is usually done in 15 minutes.
For more information please see this page on GitHub docs:
Now, you should be good to go. Fingers crossed.
A More Complex Workflow
For a more complex workflow for parsiya.io (my clone) see this:
This website is a bit special. The contents are in https://github.com/parsiya/Parsia-Clone but the actual Hugo theme is in a different repository at https://github.com/parsiya/parsiya.io.
I wanted to have the contents in a separate place without the theme. The
workflow checks out the parsiya.io
repository first and then checks out
parsia-clone
under the content
directory.
While the theme has the content directory as a submodule, just populating the submodule means I am looking an older commit so the new content are not pulled. Hence, this in the workflow:
- name: Checkout parsiya.io
uses: actions/checkout@v2
with:
repository: 'parsiya/parsiya.io' # Get parsiya.io the parent repo
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 1 # Fetch all history for .GitInfo and .Lastmod
- name: Checkout parsia-clone # Otherwise the outdated commit will be pulled
uses: actions/checkout@v2
with:
repository: 'parsiya/parsia-clone'
path: 'content'
There appears to be some ways to make a submodule pull to get the latest commit. I searched around the internet and realized a second checkout is not going to be end of the world and is much simpler to accomplish.