A bit over a week ago my friend Sam restarted his blog with a post about How [he] built this site. I’d been planning to write my own version of that post in the future, however I decided to do so sooner since our approaches have noticeable differences.
I’m using Hugo as a static site generator for the content so that rebuilding the
blog is as easy as deleting the public/
folder then recreating it using the
hugo
command. I’m not going to go into the full details of my blogging
workflow at this time beyond saying I write the posts in Emacs Org-Mode and use
ox-hugo to generate the appropriate markdown files for the posts themselves. My
Techdocs site uses the exact same process just with a different theme that is
better designed to handle documentation.
Hosting Hugo
Hugo can publish to GitHub pages which means all you need is a domain name, and even that can be skipped if you don’t mind using the GitHub branded URL. In my case I have a handful of low cost VPSes that are part of my Homelab environment and already have one running Caddy as the reverse proxy1 for all my exposed services, which makes it perfect for hosting my site.
A small addition to my Caddyfile and I had an easy way to host my sites. The missing portions relate to my exposed homelab services and so are omitted since they are not relevant.
/etc/caddy/Caddyfile
1# [...] other configuration omitted for brevity
2# static sites
3docs.leechpepin.com,
4blog.leechpepin.com {
5 root * /var/www/{host}
6 file_server
7}
Publishing to a private server
Publishing is almost as simple, even though not quite what I want as a long term solution, I have a pre-commit hook2 set up to run pre-push that handles the rsync push to the VPS. A typical workflow might be to use GitHub CI (or the equivalent with your git repository site of choice) to publish the site once the commit reaches the repository. In my case this would require adding appropriate credentials to the CI systeml to allow it to connect to the VPS whereas using a pre-push hook leverages my existing SSH credentials to establish that connection. It also handles all the usual pre-commit linting and validation I want so that my repo stays in a consistent state. All it took was installing the hooks (including pre-push requires explicitly specifying all the desired hook types)
1pre-commit install -t pre-commit -t pre-push
.pre-commit-config.yaml
1repos:
2- repo: https://github.com/pre-commit/pre-commit-hooks
3 rev: v4.4.0
4 hooks:
5 - id: trailing-whitespace
6 - id: end-of-file-fixer
7 - id: check-yaml
8 - id: check-added-large-files
9
10- repo: local
11 hooks:
12 - id: hugo-syntax-check
13 name: Hugo syntax check
14 entry: hugo --logLevel warning --renderToMemory
15 language: system
16 pass_filenames: false
17 types: [file]
18 files: '\.(md|html|toml|yaml)$'
19 stages: [pre-commit]
20 - id: hugo-publish
21 name: Publish Hugo
22 entry: bash -c "hugo && rsync -rlz --delete public/ jlpgreencloud:/var/www/blog.leechpepin.com"
23 language: system
24 pass_filenames: false
25 stages: [pre-push]
With this once a post is in a ready-to-publish state it gets built and uploaded to my blog the next time I push it to a repository.
How my Techdocs differ
As I had mentioned, the majority of the workflow for my Techdocs site is identical to how my blog is handled. The main differences are outlined below:
- The
hugo-publish
pre-commit hook points to/var/www/docs.leechpepin.com
for thersync
task. - Instead of being treated as posts, the pages are stored in a
docs/
directory and have a nested structure to leverage the Leaf and Branch bundling functionality to create a structured layout. - Comment and Sharing functionality is not added since my intent is for it to be a set of reference documents.
-
A reverse proxy is a webserver that handles incoming requests by forwarding them to the appropriate server, application or static content. ↩︎
-
A
pre-commit
git hook runs before a git commit is made to validate the content being committed. Apre-push
hook runs before the push is performed either for further validation or, as in this case, to do extra tasks using the system doing the pushing. ↩︎