How I'm hosting Hugo on GitHub Pages
⋄ 3 min readThe last time I dabbled in the background for this Hugo-powered site, I was deploying it to a webserver I pay for. Since then, I’ve been looking at how to deploy it to GitHub Pages for free, and to simplify a multiple-workstation-life.
The caveat to GitHub Pages is that, on a free GitHub account, you can only use the feature on public repositories. What I wanted to do was keep my source files and drafts in a private repository, and have the generated static site pushed to the public repository which GitHub Pages would pull from.
This is how I managed it using git submodule
. A word of warning: submodules are complicated. This setup works well for me, a singular person, who updates on one machine. Nonetheless, I hope this post helps someone as a starting point.
Note: If you really do not want it to be a public repository, Netlify allows deploys in private repositories!
Setting up submodules
I have two GitHub repositories:
<username>.github.io
is the public, GitHub pages-enabled repositoryblog
is the private repository holding source files and all drafts
In Hugo, the hugo
command generates the static site in a /public directory by default. So /public has to be move from being a directory in the blog
private repository to its own public repository pointing to <username>.github.io
.
I used Git submodules for this. It’s confusing. So here is what worked for me.
First, I deleted the public folder (rm -rf public
). This is okay because we can generate those files again. Then:
git submodule add git@github.com:<username>/<username>.github.io.git public
git submodule init
The first line checks out the GitHub Page repository and adds it to the blog repository under the directory public.
The second line pulls the code from the repository.
For sanity check, I hugo
to generate files to the public
directory. I cd public
and check git remote -v
and then cd ..
and check git remote -v
to make sure they’re pointing to different repositories.
If, like me, you managed to mess up your submodules, checking what was up in the /.git/modules directory helped me to clean up.
A new deploy script
All right, so now the commands to deploy are a little finicky. I have to generate the site, push the changes to the public repository, then push the source files to the private repository. Not only that, Hugo changes and adds files, it doesn’t delete. So I have to wipe the contents of public without removing its references to Git. Whew.
So I ended up with an executable (chmod +x deploy.sh
) deploy.sh script like this:
rm -rf public/* # Remove all files except dot files
# echo "<domain.tld>" >> public/CNAME # If you use a custom domain
hugo # Generate the static files into /public
cd public
git add .
git commit -m "Rebuilding site"
git push origin master
cd ..
git add .
git commit -m "Updating source and draft content"
git push origin master
Now, once you create your content, you can use ./deploy.sh
and it will generate the new files, and add it to each respective Git repository. It is not quite clean — if you are using multiple machines, you will need to git submodule init
and then git submodule update
to set the remotes correctly.