The why
I personally not a fan of having a let’s say blog site completely public. Reason being is that there is always some posts work in progress that should not be published yet.
Github does not allow to host pages of a private repository without having pro account. To overcome this, one can setup a private repository for the site source and a public one just for hosting.
1GitHub Pages is available in public repositories with GitHub Free,2and in public and private repositories with GitHub Pro,3GitHub Team, GitHub Enterprise Cloud, and GitHub Enterprise Server
This post is about one of the many workarounds that allows to have a public, hosted version of a private repository without pro account.
Assumptions
Let’s assume that there are two github repos:
- public - the
gh-pages
branch will be hosted by github - private - contains all final and draft source for the blog
For the sake of simplicity - in this exercise - the private repo will have a simple index.html
in it’s src
folder.
In a real site, files in /public
most likely will be generated by a framework, let it be Gatsby, Jekyll etc.
During this exercise we’ll use a simple cp to copy files from src
to public
.
Private repository
This is the repo where all the work is done.
Folder structure
1project2│ .gitignore3└───src4 index.html5 CNAME
index.html
1<!DOCTYPE html>2<html>3 <body>45 <h1>My awesome blog page</h1>67 <p>My first paragraph.</p>89 </body>10</html>
CNAME
1mydomain.com
CNAME
is required by github to link custom domain to repository. In the public repo, it must be sitting in the root folder, along with index.html
.gitignore
1public
Files in public
folder are generated, therefore should be ignored in private repository. Run echo 'public' >> .gitignore
to generate it.
Linking public repository
Add a new remote to private repository. We’ll call it public
.
1git remote add public https://github.com/<github-handle>/<remote-repo-name>.git
Run the commands below to create a gh-pages
branch in public repo. This needs to be done once.
1git checkout --orphan gh-pages2git reset --hard3git commit --allow-empty -m "Init gh-pages branch"4git remote -v5git push public gh-pages6git checkout master
Public repository
This is the repo that will be hosted github.
Do not edit files in this repository directly. Files in this repo’s gh-pages branch will be coming from the private repository.
Enabling hosting
Go to repo settings. Link will be https://github.com/\<gh-user>/\<repo name>/settings
Setting up Apex domain
Github has a detailed walkthrough to setup a domain.
However, here I just cut to the case and do the absolute minimum config necessary.
In order to point domain name to gh-pages, we need to configure an A record - some dns providers calls it ALIAS or ANAMAE - on the registars website that points to below ip addresses:
- 185.199.108.153
- 185.199.109.153
- 185.199.110.153
- 185.199.111.153
Note: everything will work fine using only one A record. The rest 3 are just redundancy, hence I’ll configure only one below.
Godaddy
Login to godaddy then go to domains.
Select the desired domain
Click on manage button. On the next page scroll down and click to Manage DNS
link. It’ll bring up DNS management page
Click on ADD button on the bottom of the widget and fill out form as below
Note: Optionally repeate it 4 times to add all 4 ip addresses.
Once it’s done, added A records show up on domain settings.
Hallelujahh, public repo is done. From this point onward, whatever files sit in the public repo’s gh-pages branch will be available on mydomain.com.
Check if apex domain propagated
According to my experience, the above changes apply almost immediatelly. However propagating A records might take a while.
To double check if records went live, run the below dig command.
1$ dig +noall +answer mydomain.com2mydomain.com. 3600 IN A 185.199.108.153
Note that the returning IP address is 185.199.108.153
, the one configured during above steps.
Dig may return more records, depending how many A records have been configured.
Publishing files
Recapping what we have so far
- a private repo with
index.html
andCNAME
files sitting in/public
folder - a public repo configured to host files in
gh-pages
branch under mydomain.com
Now what needs to be done is copying files from private repo /public
to public repo gh-pages
branch. Let’s call it deploy.
Go to private repo root folder. Branch is irrevelant.
1# cleanup2rm -rf public3mkdir public4git worktree prune5# cleanup worktree6rm -rf .git/worktrees/public/7# checkout public remote repo gh-pages branch into public folder8git worktree add -B gh-pages public public/gh-pages9# cleanup - everythign will be re-generated10rm -rf public/*11# copy files from src to public. In a rela project this would be `jekyll build` or `gatsby build` etc12cp src/* public/13cd public14git add --all15git commit -m "Added this and that"16git push public gh-pages
👏👏👏Congratulations.
src/index.html
sitting in a private repository is now hosted on github under mydomain.com.
Hence this post is long enough already, I’ll script the above up in a following post.
Thank you for reading.