Setting up cGit on OpenBSD

By Biswakalyan Bhuyan4 minutes read

Introduction

cGit is a lightweight web interface for Git repositories, written in C. It’s fast, minimal, and makes browsing Git repos a breeze. cGit is licensed under GPLv2, and you can learn more about it on its official GitHub page.

In this tutorial, I’ll walk you through setting up cGit on OpenBSD, focusing on getting Lua support and custom filters working. So, let’s dive in!

Prerequisites

Before we start, make sure your OpenBSD server is up and running. Here’s what we’ll need:

You’ll need root access, and your system should be up to date. For reference, I’m using OpenBSD 7.5, so some configurations might have changed by the time you’re reading this. If you run into issues, feel free to email me at biswa@surgot.in.

My Story: The Challenges I Faced

Setting up cGit can be straightforward if all you need is a simple interface to show your Git repos. But I wanted more. I wanted Lua support and dark theme filters, so I compiled cGit myself. The default package in OpenBSD wasn’t cutting it for me—it felt too plain and limiting, especially because it didn’t support filters. Filters are crucial for customizing how your repositories are displayed.

The Troubleshooting Process

I spent nights poring over documentation for cGit, uWSGI, and httpd. I also had to rewrite parts of the luaossl library for LibreSSL support, faced issues with the build process, and tweaked various configurations. In the end, everything worked smoothly, and I even wrote my own Python filters, which I’ll share later in this tutorial.

Let’s Begin

I’m hosting my OpenBSD server on Hetzner, but since Hetzner doesn’t officially support OpenBSD VMs, I had to mount an ISO manually. I kept my installation minimal, excluding games and the X server.

Step 1: Install Git

First, install Git on your OpenBSD system:

doas pkg_add git

Step 2: Clone the cGit Repository

Next, clone the cGit repository from the jd/zx2c4-deployment branch:

git clone --branch jd/zx2c4-deployment https://git.zx2c4.com/cgit/

After cloning, initialize the Git submodule and pull the latest updates:

git submodule init
git submodule update

Step 3: Configure and Compile cGit

Navigate to the cGit directory and locate the config.mk file, which is crucial for compiling the project. Use gmake to build cGit with LuaJIT support:

gmake LUA_PKGCONFIG=luajit CFLAGS="-I/usr/local/include/luajit-2.0" install

This will take a bit of time, so grab a coffee while it compiles!

Step 4: Directory Setup

Once compiled, you’ll find the relevant files under /var/www/uwsgi/cgit/. Your cgitrc configuration file will be located in /var/www/uwsgi/cgit/cgitrc—note this path as it’s important for later.

Feel free to check out my personal cgitrc config.

Step 5: Set up uWSGI

Clone the uWSGI repository:

git clone https://github.com/unbit/uwsgi /var/www/uwsgi/daemon

After cloning, you’ll need Python 3 to compile uWSGI:

doas pkg_add python

In my case, I used Python 3.11.10. Once installed, build uWSGI:

python3 uwsgiconfig.py --build core

Then, compile the CGI plugin for uWSGI:

python3 uwsgiconfig.py --plugin plugins/cgi core

Step 6: Configure uWSGI

Create a cgit.ini file for uWSGI under /var/www/uwsgi/cgit.ini with the following content:

[uwsgi]
fastcgi-socket = /var/www/run/cgit.socket 
fastcgi-modifier1 = 9
plugin-dir = /var/www/uwsgi/daemon
plugins = cgi

cgi = /var/www/uwsgi/cgi/cgit.cgi
need-app = false
gid = www
uid = www

This config tells uWSGI to use FastCGI to communicate with httpd. It also ensures that cGit runs in a chrooted environment with the necessary plugins.

Test your uWSGI setup by running:

./uwsgi --ini /var/www/uwsgi/cgit.ini

If you run into permission issues, fix them with:

doas chown -R www:daemon /var/www

Step 7: Configure httpd

Now, configure httpd to serve cGit. Here’s a sample config for a TLS-enabled site:

server "git.example.com" {
    listen on * tls port 443
    root "/uwsgi/cgit/cgi/cgit.cgi"
    fastcgi socket "/run/cgit.socket"
    tls {
        certificate "/etc/ssl/git.example.com.fullchain.pem"
        key "/etc/ssl/private/git.example.com.key"
    }
    location "/cgit.*" {
        root "/cgit"
        no fastcgi
    }
    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2
    }
}

Restart httpd with:

doas rcctl -f restart httpd

Finally, run the uWSGI command again to verify everything works.

Step 8: Set up rc.d

To make sure uWSGI starts automatically after a reboot, create an rc.d script at /etc/rc.d/cgit:

#!/bin/ksh 

name="cgit"
daemon="/var/www/uwsgi/daemon/uwsgi"
daemon_flag="/var/www/uwsgi/cgit.ini &"
daemon_execdir="/var/www/uwsgi"

. /etc/rc.d/rc.subr

rc_cmd $1

Enable and start the service:

doas rcctl enable cgit
doas rcctl start cgit

Filters

To enable filters, you’ll need specific Lua and Python libraries (check each filter’s documentation for requirements). I encountered issues with luaossl, but I added LibreSSL support in my repo. You can download and install it with make install.

Some Lua plugins weren’t working on my setup, so I rewrote a few in Python. You can find all my custom filters on my Git server.