After a long hiatus from publishing updates on my blog, I tried to publish a new page only to realize that my prior automated solution broke. Instead of fixing and maintaining something that was overly complex, and in light of my POSSE / self-hosted philosophy, I looked around for other version control approaches.
So if I’m going to rethink the approach, what are the essential requirements?
After a few days of reading up on Game of Trees (gotd), I decided to give it a try. I love the idea of self-hosting my VCS and using a permissions-limited approach to keeping my remote web host updated. True to the ideals of the OpenBSD project, got/gotd serves as a security- and simplicity-focused replacement for the core features offered by the git protocol without all of the cruft. It’s explicit in its mission to do the parts of git that are relevant for the OpenBSD developers, but for my simple use cases it can stand in as a roughly standardized VCS that gains all the security benefits of a restricted architecture.
In a typical workflow case, I could bang out a quick blog-as-markdown on my laptop, commit it to my gotd server, and then my web server could pick up changes, process them, and publish them. While I haven’t figured out “notify” just yet or post-commit hooks, simply having the web server check-in with the gotd repo on a cron is working just fine for now.
In order to get familiar with got / gotd, I primarily used the architecture concept presentation to EuroBSDcon 2019 and the later development update given at FOSDEM 2023 as well as the excellent man pages on their site.
I really liked that the server was permission restricted by pledge (which is used in the OpenBSD ecosystem to restrict syscalls, typically segregating eg. network access from file writing) & unveil (which restricts the files that a running process can see, and which permissions they have to eg. read or write), and that with a simple git-compliant shell helper, I could even enable an anonymous user restricted to that gotsh wrapper and potentially publish read-only code repos eventually.
I’d like to be able to build off of this simple exercise, so the idea of getting to a place where my gotd / gotwebd could be public-facing is appealing. Having the site deployment tools, Sigma rules, or other code content available for publication would be a great way to grow from here!
This approach would have 3 main parts:
The web host could have a pinhole firewall rule that allows only it to connect back to gotd to mirror the web site’s repository. On a cron, it would check for updates to the web site repo, fetch them, and update the files. It would also run the static site generator script to deploy those changes to the site.
The publishing client could use git (for simple commands that are mutually supported by git and got) to write, add, commit, and push markdown via a read/write user and SSH key on the gotd server.
In the middle, gotd would host the website repo allowing the web server user (read-only) or the author (read-write) accounts to interact with the repo.
I run a simple cron on my web server that does the following:
One of the things that I quickly stumbled with was… git. I’m not a strong git user, even though it’s part of my daily work. I have tried a number of methods to learn git more thoroughly, but it’s still a work in progress. Julia Evans’ zines, including How Git Works and Oh Shit, Git! have both been hugely helpful for me to absorb the mental model and get myself out of trouble. But I still have regular friction, particularly when I need to do something that isn’t part of my regular flow.
In particular, I found that lots of things that I’ve gotten as habits from the git CLI or the large, centralized web UIs or day-job deployment workflows, are not 1-for-1 in got/gotd. This is fine, it’s not intended that got would be a git replacement. But it meant that lots of “hey, this is clearly in the repo but the site is not pulling and deploying it” debugging ensued.
Specifically?
I started with a simple “everything happens on the ‘main’ branch” to avoid having to sort out branches from the outset. But one of the things (abstracted?) by git is that the repo blobs and the files themselves are actually distinct. In got, this means that you have a cloned repo (see git-repository(5) and got-worktree(5)) that you have to manage.
I also learned that since the web server isn’t intending to deploy / manage code locally (the web server got client user only has read-only access as an extra layer of security), I want to clone –mirror the repository into a “worktree” directory and do work there. The repo and worktree are not in a unified directory under got.
So once the worktree is cloned as a mirror, the cron script will be doing a ‘got fetch’ and ‘got update’ to ensure that we have the latest files and are tracking the latest commit from main.
I’m sure things will get a little more complicated over time, and I’m not entirely certain that this is in fact the ‘correct’ approach, but it is functional and seems to have survived initial testing.
From here, I’m going to back off my cron to something regular like 15-60 minutes, and try to commit (pun intended) more markdown.
But one of the things that I noticed was that the original host for my current shell-based static site generator is offline. I’m going to continue to use the open code, but I will perhaps need to consider writing a maintainable replacement. Even if I don’t, I do think there are some things that I’d like to be able to do on my site that my current SSG doesn’t solve for. I’m imagining still using a static generator to publish plain HTML, but I might use something like tags in the markdown to make dynamic category pages for topics and use them to populate navigation links. It might mean something like an intermediate data structure (csv? read by sqlite?) that would let me link a single static page that fits two topics at a predictable URL, but also have topical indexes that focus on just posts tagged for that topic. Still noddling on this one…
I’m sure there’s more. For now, I’m enjoying that this post was as simple as:
vi move-to-gotd.md
git add .
git commit -m ‘update draft’
git push -u origin main
Published elsewhere: Mastodon