yumh

writing about things, sometimes.

cgit & gitolite

Written by Omar Polo on 22 April 2020.

I've just finished to configure gitolite and cgit to manage some git repos of mine (and friends), so I'm posting here the setup before forgetting the details.

The final result is a git server with both a web view, HTTP clone and ssh for you and your users.

It requires more work than, say, gitea or gitlab, and has a few moving parts. Nevertheless, it's a modular solution (you can replace cgit with gitweb for instance) and it does not have obnoxious web guis to manage things. The whole gitolite config is itself a git repository, so you can use the tools you're familiar with (a bit of ssh, git and your preferred $EDITOR) to build and maintain your own git server.

gitolite

Install gitolite, it's easy, just follow the installation guide. I've done that on a new user called "git". This will create two repos in ~git/repositories: gitolite-admin and testing. With the default configuration testing will be read-write for all users (in the gitolite sense).

You should import your own ssh public key. Try to clone the “gitolite-admin” repo with:

git clone git@your.own.host:gitolite-admin

to test the setup and, eventually, add more users and repos.

cgit

I'm using nginx plus fcgiwrap on a FreeBSD system, but other options are available. (For instance, if you're using OpenBSD than you have httpd and slowcgi already in base.)

For reference, my configuration file is /usr/local/etc/cgit-op.conf and contains:

css=/mine.css
logo=/logo.png

head-include=/usr/local/lib/cgit/theme/head.html

enable-http-clone=1
enable-index-links=1
remove-suffix=1
enable-commit-graph=1
enable-log-filecount=1
enable-git-config=1

source-filter=/usr/local/lib/cgit/filters/syntax-high.py
about-filter=/usr/local/lib/cgit/filters/about-formatting.sh

virtual-root=/
enable-index-links=1
enable-index-owner=0
snapshots=tar.gz tar.bz2
root-title=Stuff
root-desc=some git repos of mine
local-time=1

# path to the root about file
#root-readme=/usr/local/lib/cgit/theme/about.html

# search for these files in the root fo the default branch
readme=:README.md
readme=:readme.md
readme=:README.mkd
readme=:readme.mkd
readme=:README.rst
readme=:readme.rst
readme=:README.html
readme=:readme.html
readme=:README.htm
readme=:readme.htm
readme=:README.txt
readme=:readme.txt
readme=:README
readme=:readme
readme=:INSTALL.md
readme=:install.md
readme=:INSTALL.mkd
readme=:install.mkd
readme=:INSTALL.rst
readme=:install.rst
readme=:INSTALL.html
readme=:install.html
readme=:INSTALL.htm
readme=:install.htm
readme=:INSTALL.txt
readme=:install.txt
readme=:INSTALL
readme=:install

scan-path=/home/git/repositories

The important bits of all of these are only:

enable-git-config=1

and

scan-path=/home/git/repositories

The first let us configure per-repo cgit options via the standard git config file, while the second lets cgit discovers the repos by searching in that path.

If you're curious, I used ‘head-include’ to add some meta tags and modified the default CSS to render the pages *decently* on mobile screens. More work is needed.

Note about permissions

You are probably running cgit with the www user and gitolite with the git user, so you have a permission problem. While you can do fancy stuff with mount_nullfs, ‘mount --bind’ and whatnot or by changing the default path for the repositories, I didn't want to.

I'm still not sure if this is the best way to handle things, but I made fcgiwrap use the `git` user with

fcgiwrap_user="git"

in `/etc/rc.conf` plus a manual `chown(8)` on the socket. Now cgit and gitolite are run by the same user. Problem solved.

hide some repositories!

This was the basic setup to have cgit display the repositories managed by gitolite, as well as having both public HTTP and authenticated ssh clone. Pretty neat.

But, you have no way (still) to hide some repositories. For instance, the ‘gitolite-admin’ repository is public readable (not writable). It may be fine for you, but I wanted a way to have *private* repositories, while still having the repos managed by gitolite.

If you set ‘enable-git-config’ in cgit configuration file, now you can control some cgit per-repo options via `~git/repositories/$REPO/config`. You can create a section that looks like this:

[cgit]
	ignore = 1

to make cgit ignore that repo. Check the documentation of cgit for the list of parameters you can set.

But it's tedious and needs manual work per-repo. That's something that needs to be automatized.

Fortunately, gitolite lets us set git configurations via the gitolite.conf file. You first need to set ‘GIT_CONFIG_KEYS’ to ‘.*’` in ~git/.gitolite.rc. (‘.*’ is the broader, probably ‘cgit.*’ is enough, haven't tested tho).

Now, in your `gitolite.conf` you can

repo gitolite-admin
    config cgit.ignore=1

and BOOM, it's hidden and unreachable via cgit (both via web and http clone).

But (there are too many “but” in this section, hu?) we can do even better:

@hiddenrepos = gitolite-admin
@hiddenrepos = private-stuff
@hiddenrepos = next-gen-revolutionary-stuff

repo @hiddenrepos
    config cgit.ignore=1

to bulk-hide repositories.

Neat.