static site generator for git repos
629 KiB | 60 commits
git clone https://khoe.thac.loan/khoe
khoe (Vietnamese, verb): to show something off
It's a static site generator for your git repos - think stagit, but git clone
-able. If you ever wanted to share your plain git repos without the security headaches of hosting a dynamic web service, you may like khoe.
We use zig master, which is 0.16.0-dev.393+dd4be26f5 at the time of writing:
# khoe is hosted on khoe
git clone https://khoe.thac.loan/khoe
cd khoe
zig build -Doptimize=ReleaseSafe
Runtime dependencies (khoe shells out to these commands at runtime):
Assuming all of your repos (both normal and bare repos work fine) reside in /srv/git/repos
, run:
# replace 2nd arg with the domain you'll host your site on
khoe /srv/git/repos http://localhost:8000
Khoe will create 2 things inside this dir:
index.html
: the home page_
(underscore): the directory that stores the rest of the generated htmlThis repos
dir is now serveable as a static website. For a quick preview, try python3 -m http.server -b localhost -d /srv/git/repos
. People can git clone
repos from this site too.
Please make sure there's nothing sensitive in your repos dir before exposing it to the unwashed public. Git hooks, config, etc. are the usual suspects.
You can now either serve the dir as-is using caddy/nginx/etc., or rsync it to a remote server, or serve it on s3 if you like burning your (employer's) money, or even, get this, make it a git repo itself to host on GitHub Pages for free! I'm not saying you should, but you could. Static web hosting is cheap, often free even. The world's your oyster.
Simplest way is to setup a global post-update hook like this:
flock /tmp/khoe khoe .. https://your.site
Using flock ensures that only 1 instance of the script could be running at a time, avoiding race conditions when multiple people could be pushing.
Nothing is cached. Every page is regenerated every time, except for those in /objects/. Computers are fast though so performance hasn't been a problem for me. If it is for you, let me know and we can optimize it.
Worse still, every repo is regenerated every time. This one I'll fix... sometime. Khoe should allow choosing a specific repo to regenerate so that it can run efficiently as a post-update git hook. See Roadmap.
Outdated pages, if not overwritten, are left as-is. Since git itself is an append-only paradigm, deletion is rarely necessary. Security-wise, if you've accidentally pushed a secret on a public repo, you must consider it compromised forever and perform appropriate credential rotation and whatnot. Deleting the offending pages means nothing in this context. If it bothers you still, feel free to write a script to delete-before-generate, or generate-and-swap if you have lots of nines to maintain - you do you.
See How to interact with a bare git repo. I generally agree with his preferences.
Copyright © 2025 tri@thac.loan
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program (agpl-3.0.txt). If not, see https://www.gnu.org/licenses/.