diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/blog/2026-09-05-cgit/cgit.md | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/blog/2026-09-05-cgit/cgit.md b/src/blog/2026-09-05-cgit/cgit.md new file mode 100644 index 0000000..53c00bd --- /dev/null +++ b/src/blog/2026-09-05-cgit/cgit.md | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | # From stagit to cgit | ||
| 2 | |||
| 3 | When I first set up this website back in 2022, I also started self-hosting | ||
| 4 | my git repositories. To make them accessible via web I used | ||
| 5 | [stagit](https://codemadness.org/stagit.html), and I wrote about this | ||
| 6 | in [an old blog post](..//2022-11-23-git-host/). In short, I used a custom | ||
| 7 | post-receive [git | ||
| 8 | hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that used | ||
| 9 | stagit to generate the HTML pages for [my git | ||
| 10 | website](https://stagit.tronto.net). | ||
| 11 | |||
| 12 | This script ran every time I pushed some changes to a repository. | ||
| 13 | After calling stagit, the script would also modify the generated | ||
| 14 | pages to add a custom Download button at the top, which was not | ||
| 15 | efficient. For my largest repositories, this took around | ||
| 16 | a couple of minutes for every `git push`. Moreover, having all the file | ||
| 17 | contents both in the git folder and in the HTML pages wasted some | ||
| 18 | space on my small VM. | ||
| 19 | |||
| 20 | So I looked for alternatives, and I found | ||
| 21 | [cgit](https://git.zx2c4.com/cgit/about/), which works quite differently | ||
| 22 | from stagit. I gave it a try, and I am quite happy with the result! If | ||
| 23 | you want to check it out, go to [git.tronto.net](https://git.tronto.net). | ||
| 24 | A frozen version of the old stagit-generated pages is still available at | ||
| 25 | [stagit.tronto.net](https://stagit.tronto.net). | ||
| 26 | |||
| 27 | ## Static pages versus CGI | ||
| 28 | |||
| 29 | Instead of generating pages to be served by a | ||
| 30 | [web server](https://en.wikipedia.org/wiki/Web_server), cgit is | ||
| 31 | based on [CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface). | ||
| 32 | To put it simply, cgit is a program that continuously runs on a server, | ||
| 33 | generating on the fly each page a visitor requests. | ||
| 34 | |||
| 35 | There is an obvious trade-off between disk space and CPU usage here: | ||
| 36 | on the one hand we don't need to store all the HTML pages that are | ||
| 37 | essentially a duplicate of what can already be found in the git | ||
| 38 | repository's folder; on the other hand, computing the page on the | ||
| 39 | go takes some work for the server's CPU. However, cgit can also | ||
| 40 | cache the most recently viewed pages, so it does not have to re-compute | ||
| 41 | the most requested ones all that often. | ||
| 42 | |||
| 43 | Of course, another cost is the more complex setup, as we are now dealing with | ||
| 44 | a full-blown web application instead of plain and simple static HTML files. | ||
| 45 | We'll get into some of the problems that this causes in the next section. | ||
| 46 | |||
| 47 | ## OpenBSD and cgit | ||
| 48 | |||
| 49 | As you may know, the [VM](https://en.wikipedia.org/wiki/Virtual_machine) | ||
| 50 | that hosts this website has historically been running on | ||
| 51 | [OpenBSD](https://openbsd.org) (spoiler: this is no longer the case). | ||
| 52 | When it comes to hosting cgit, or any CGI application, this comes with | ||
| 53 | some pros and some cons. | ||
| 54 | |||
| 55 | First off, the pros: OpenBSD's base system already has a web server | ||
| 56 | ([httpd](https://man.openbsd.org/httpd.8)) and a FastCGI server | ||
| 57 | ([slowcgi](https://man.openbsd.org/slowcgi.8)) that are capable of | ||
| 58 | running cgit. So no external program is strictly needed other than | ||
| 59 | cgit itself - see [this short | ||
| 60 | tutorial](https://codemadness.org/openbsd-httpd-and-cgit.html) for | ||
| 61 | details. | ||
| 62 | |||
| 63 | But there are some points of friction that arise from one of httpd's | ||
| 64 | most-loved security features: the fact that it works in a | ||
| 65 | [chroot](https://en.wikipedia.org/wiki/Chroot) environment, by default | ||
| 66 | rooted at `/var/www`. This means that httpd cannot see any file outside | ||
| 67 | of `/var/www`. So any file that cgit needs, including all the git | ||
| 68 | repositories that one wants to show, must be inside `/var/www`. | ||
| 69 | |||
| 70 | And while it is not much effort to put them there, I have been | ||
| 71 | managing my repositories via a dedicated `git` user, keeping them in | ||
| 72 | `/home/git`. So I would have to either change this user's home directory | ||
| 73 | to something in `/var/www`, or change the relative path of each repository. | ||
| 74 | Either way, it wouldn't be as nice as my current setup. | ||
| 75 | |||
| 76 | But the repositories are not all cgit may want to know about. For example, | ||
| 77 | one can *filter* README files through a Markdown parser, such as | ||
| 78 | [lowdown](https://kristaps.bsd.lv/lowdown/), to display more nicely on the | ||
| 79 | web - see [this README](https://git.tronto.net/nissy-core/about/) for an | ||
| 80 | example. The parser, too, must live within httpd's chroot. Same for any | ||
| 81 | [dynamic library](https://en.wikipedia.org/wiki/Dynamic_library) it | ||
| 82 | depends on. To make this work, I ended up creating `usr/bin` and `usr/lib` | ||
| 83 | folders inside `/var/www` and manually copied some executables and libraries | ||
| 84 | there - not the cleanest solution. | ||
| 85 | |||
| 86 | Alternatively, one may configure httpd to chroot at `/`, making things | ||
| 87 | more practical but loosing the security benefits. But at this point, | ||
| 88 | I decided I wanted to try out a different stack - new VPS provider, new | ||
| 89 | OS, new web server. This is something I had been thinking about for | ||
| 90 | about a year at this point, and I'll talk about the reasons in the | ||
| 91 | next post. | ||
| 92 | |||
| 93 | But if you plan to host cgit on OpenBSD, do not be discouraged! | ||
| 94 | Everything can be set up with just a little manual work. | ||
| 95 | |||
| 96 | ## My cgit configuration | ||
| 97 | |||
| 98 | My new cgit instance is hosted on an [Alpine Linux](https://alpinelinux.org) | ||
| 99 | VM and it is running via [Lighttpd](https://www.lighttpd.net). | ||
| 100 | For the basic setup, I followed [this wiki | ||
| 101 | page](https://wiki.alpinelinux.org/wiki/Cgit) (note that lighttpd has a | ||
| 102 | `mod_cgi` module that replaces fcgiwrap entirely). Not much | ||
| 103 | to say here, just a little fiddling with lighttpd's configuration. | ||
| 104 | |||
| 105 | As for customization, my configuration files are available in my | ||
| 106 | [cgit-config](https://git.tronto.net/cgit-config) repository. The | ||
| 107 | main configuration file, | ||
| 108 | [cgitrc](https://git.tronto.net/cgit-config/tree/cgitrc), is | ||
| 109 | well-commented, and won't require further explanation. | ||
| 110 | |||
| 111 | There are a bunch of other files too, such as the custom | ||
| 112 | [about-filter.sh](https://git.tronto.net/cgit-config/tree/custom/about-filter.sh) | ||
| 113 | which, is used to display README files more nicely. As for the custom | ||
| 114 | [css](https://git.tronto.net/cgit-config/tree/custom/cgit.css), the | ||
| 115 | main feature is making the website a little more comfortable to | ||
| 116 | browse on mobile; I shamelessly copied this part from [another cgit | ||
| 117 | user](https://git.matejamaric.com/responsive-cgit-css). | ||
| 118 | |||
| 119 | ## Pros and con(cern)s | ||
| 120 | |||
| 121 | So far, cgit seems to run pretty fast on my new VM with a single CPU | ||
| 122 | core and 1GB of RAM. It also looks pretty cool, even though I liked | ||
| 123 | stagit's simplicity. | ||
| 124 | |||
| 125 | Unfortunately, the nice download button that I added to each of my | ||
| 126 | repositories is now gone. cgit allows downloading tarballs of a repo, | ||
| 127 | but only from tags, not for the current state of the master branch. | ||
| 128 | Overall, stagit's simplicity also allowed for great deal of customizability. | ||
| 129 | |||
| 130 | I am also a bit concerned about AI | ||
| 131 | [crawlers](https://en.wikipedia.org/wiki/Web_crawler). I have heard horror | ||
| 132 | stories of people having to make their repositories private because of | ||
| 133 | bots scanning their pages to feed the slop machine overloading their servers. | ||
| 134 | However, I hope cgit being quite small compared to a | ||
| 135 | [forge](https://en.wikipedia.org/wiki/Forge_(software)) such as | ||
| 136 | [GitLab](https://en.wikipedia.org/wiki/GitLab) or | ||
| 137 | [Gitea](https://en.wikipedia.org/wiki/Gitea) will help my server | ||
| 138 | sustain the extra effort - if any bot is interested in my code at all. | ||
| 139 | |||
| 140 | In conclusion, stagit served me well for a while, and I think | ||
| 141 | cgit is better suited to my needs now. | ||
