Git9 is a simple, clean implementation of git for Plan 9.
Every commit on it has been made using git9, but the hosting has always been on Github. This was done for two reasons: First, the server side of the protocol hadn't been implemented at the time, making hosting a git server difficult. Second, github is by far the most popular git server, so making sure that every commit was tested against it seemed like a good idea, especially since there are a number of github bugs I've run into. (More on that in another post)
That changes today: Git9 is running on git/serve, hosted on 9front. It's been towed within the environment.
I'll keep mirroring to github for the foreseeable future, because people keep promising that using github will bring in contributors -- and because it doesn't hurt to keep testing against github. Also, breaking links annoys people.
It lives here now: https://orib.dev/git/git9/HEAD/info.html
Why run this over other hosting providers?
Pride, mostly. I implemented a git client and a git server. Why the hell shouldn't it be self hosting?
If you're not in my position, I don't recommend it. It needs a weird operating system, has very few features, and isn't battle hardened. It's probably fine for up to medium scale projects with a few million lines of code and a few tens of thousands of commits, but I expect that fresh clones will be slow for linux-scale projects or larger.
If you're looking for a familiar option, use sr.ht, github.com, or similar. If you want self hosting, there are options like gittea, smithy, or cgit.
If you want to ignore my advice and use this anyways, I'm finding it to be a simple, lightweight, and easy to customize hosting platform, and I'm happy help with any rough spots in either the documentation or code.
Git9 supports the git:// protocol, over a various number of transports, with varying levels of authentication and security.
For Unix users on upstream git, the only supported protocol is the
unencrypted git://
. While technically you can push over
the git protocol, this is disabled on my instance for good reason.
For read only access on Plan 9 clients, I also serve up the
git://
protocol over ssl: You can use it by cloning
using the gits://
transport. At some point I'll look
at submitting a patch upstream, since it seems like a no-brainer
to allow encrypted git.
Finally, for authenticated access, I use the hjgit://
protocol, which does a key exchange using Plan 9 authentication, then
uses the exchanged secret to set up a TLS connection. On my server,
only
dp9ik
is supported.
There's also a web view, hosted at https://orib.dev/git/repos.html, for exploring the code without cloning.
My instance of git9 is hosted using 9front, with a small number of additional utilities: cinap's tcp80 is used for the webserver, and execfs is used to provide dynamically generated static paths
The services are started using
aux/listen. Aux/listen is similar to inetd: If a file exists in the
service directory, then it's run when someone tries to connect. So, for
example, if /rc/bin/service/tcp443
exists, then when someone
connects to tcp port 443, that program gets executed.
The following config files live in the service directory:
tcp9418 runs the unencrypted git://
server.
Every time you connect to git, a new instance of git/serve
is started, responds to your request, and exits. The -w
flag is
omitted, so git/serve
invocations on this port are read only.
#!/bin/rc exec git/serve -r/usr/git
tcp9419 runs the gits://
server. The invocation
of git/serve
is the same as for git://
, however
it's wrapped up in tlssrv
,
so the fd passed to git/serve
is for an encrypted connection.
#!/bin/rc exec tlssrv -c/sys/lib/tcp80/fullchain.pem /bin/git/serve -r/usr/git
tcp17021 runs the hjgit
server. By now, this
will look familiar. The -a
flag to tlssrv
tells it to use plan9 auth to establish a shared secret for the TLS
tunnel, and the -w
flag to git/serve
tells
it to allow writing to repositories.
#!/bin/rc exec tlssrv -a /bin/git/serve -wr/usr/git
Finally, tcp443 runs the web server. It follows the pattern,
but before starting, it mounts execfs
to provide the virtual
files for browsing repositories.
#!/bin/rc execfs -m /usr/web/git /sys/lib/tcp80/gitrules rfork n exec tlssrv -c/sys/lib/tcp80/fullchain.pem /bin/tcp80
execfs provides a virtual file system, where file paths map to the output of commands. Every line of the rules file contains two fields: A regex pattern to match the path, and a program invocation to use to provide those file contents. The rules used are below:
/repos.html /bin/gitls /usr/git list /([^'/]+)/info.html /bin/gitls /usr/git info '\1' HEAD /([^'/]+)/([^'/]+)/info.html /bin/gitls /usr/git info '\1' '\2' /([^'/]+)/([^'/]+)/snap.tar.gz /bin/gitls /usr/git tar '\1' '\2' /([^'/]+)/([^'/]+)/(([^']+)/)?f.html /bin/gitls /usr/git view '\1' '\2' '\4'
The gitls script is used to actually render the repository contents into html.
It's a short rc
script,
which lives here:
https://orib.dev/git/git9/HEAD/extra/gitls/f.html. This script sandboxes
itself, and then generates a web view.
It runs in one of four modes: tar, list, info, and view.
The list view generates a list of all repsoitories containing
.git/webpublish
.
The tar mode generates a snap.tar.gz of the repository.
It exists largely to bootstrap git9 on systems that don't already have it.
The info view shows the current commit, the list of files at the top
level, and the contents of .git/README
, or the readme in the
repository. Finally, the view mode shows the contents of a file or directory.
In addition to self hosting, I've also set up a site to host other people's git repositories. Doing this is part of my evil plan to get other people to find bugs in my code.
Shithub is live, at shithub.us