--- title: Running cgit on Gentoo layout: post tags: git cgit Gentoo social: mastodon: https://soc.fglt.nl/notice/9rG9O32VTSYnlL451U description: > Recently, I've setup cgit on my desktop, running Gentoo. This post covers the installation and configuration I've undertaken to get it running as desired. --- [cgit](https://git.zx2c4.com/cgit/about/), a web interface for git repositories, allows you to easily share your projects' source code over a web interface. It's running on my desktop right now, so you can [see for yourself](https://home.tyil.nl/git) what it looks like. On [Gentoo](https://www.gentoo.org/), the ebuild for this software can be found as `www-apps/cgit`. However, after installation, a number of configuration steps should be performed to make it accessible on `$HOSTNAME/git`, and index your repositories. This post will guide you through the steps I took. ## Filesystem layout In my setup, my (bare) git repositories reside in `$HOME/.local/git`. But, some of the repositories should not be public, such as the [`pass`](https://www.passwordstore.org/) store. So, a different directory for cgit to look in exists, at `$HOME/.local/srv/cgit`. This directory contains symlinks to the actual repositories I want publicly available. ## Installing the required software For this to work, there is more than just cgit to install. There are a number of ways to set this up, but I chose for Nginx as web server, and `uwsgi` as the handler for the fastcgi requests. {% highlight sh %} emerge dev-python/pygments www-apps/cgit www-servers/nginx www-servers/uwsgi {% endhighlight %} ## Configuring all elements After installation, each of these packages needs to be configured. ### cgit The configuration file for cgit resides in `/etc/cgitrc`. After removing all the comments, the contents of my `/etc/cgitrc` can be found below. {% highlight text %} # Fixes for running cgit in a subdirectory css=/git/cgit.css logo=/git/cgit.png virtual-root=/git remove-suffix=1 # Customization root-desc=All public repos from tyil enable-index-owner=0 cache-size=1000 snapshots=tar.gz tar.bz2 clone-prefix=https://home.tyil.nl/git robots=index, follow readme=master:README.md readme=master:README.pod6 # Add filters before repos (or filters won't work) about-filter=/usr/lib64/cgit/filters/about-formatting.sh source-filter=/usr/lib64/cgit/filters/syntax-highlighting.py # Scan paths for repos scan-path=/home/tyil/.local/srv/cgit {% endhighlight %} You should probably update the values of `root-desc`, `clone-prefix` and `scan-path`. The first describes the small line of text at the top of the web interface. `clone-prefix` is the prefix URL used for `git clone` URLs. The `scan-path` is the directory `cgit` will look for repositories in. Additionally, the `readme=master:README.pod6` only positively affects your setup if you also use my [Raku](https://raku.org/) customizations, outlined in the next section. For more information on the available settings and their impact, consult `man cgitrc`. #### Raku customizations Since I love working with Raku, I made some changes and a couple modules to get `README.pod6` files rendered on the *about* tab on projects. You should ensure the `cgit` user can run `raku` and has the [`Pod::To::Anything`](https://home.tyil.nl/git/raku/Pod::To::Anything/) and [`Pod::To::HTML::Section`](https://home.tyil.nl/git/raku/Pod::To::HTML::Section/) modules installed (including any dependencies). How to achieve this depends on how you installed Raku. Feel free to send me an email if you need help on this part! Once this works, however, the remaining step is quite simple. The `about-filter` configuration item in `/etc/cgitrc` points to a small shell script that invokes the required program to convert a document to HTML. In my case, this file is at `/usr/lib64/cgit/filters/about-formatting.sh`. Open up this file in your favorite `$EDITOR` and add another entry to the `case` for [Pod6](https://docs.raku.org/language/pod) to call Raku. {% highlight sh %} case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in *.markdown|*.mdown|*.md|*.mkd) exec ./md2html; ;; *.pod6) exec raku --doc=HTML::Section; ;; *.rst) exec ./rst2html; ;; *.[1-9]) exec ./man2html; ;; *.htm|*.html) exec cat; ;; *.txt|*) exec ./txt2html; ;; esac {% endhighlight %} #### Highlighting style The `syntax-highlighting.py` filter carries the responsibility to get your code highlighted. This uses the Python library [pygments](https://pygments.org/), which comes with a number of styles. cgit uses *Pastie* by default. To change this, open the Python script, and look for the `HtmlFormatter`, which contains a `style='Pastie'` bit. You can change `Pastie` for any other style name. These styles are available in my version (2.4.2): - default - emacs - friendly - colorful - autumn - murphy - manni - monokai - perldoc - pastie - borland - trac - native - fruity - bw - vim - vs - tango - rrt - xcode - igor - paraiso-light - paraiso-dark - lovelace - algol - algol_nu - arduino - rainbow_dash - abap - solarized-dark - solarized-light - sas - stata - stata-light - stata-dark For those interested, I use the `emacs` theme. ### uwsgi Next up, `uwsgi`. This needs configuration, which on Gentoo exists in `/etc/conf.d/uwsgi`. However, this file itself shouldn't be altered. Instead, make a copy of it, and call it `/etc/conf.d/uwsgi.cgit`. The standard file exists solely as a base template. For brevity, I left out all the comments in the contents below. {% highlight sh %} UWSGI_SOCKET= UWSGI_THREADS=0 UWSGI_PROGRAM= UWSGI_XML_CONFIG= UWSGI_PROCESSES=1 UWSGI_LOG_FILE= UWSGI_CHROOT= UWSGI_DIR=/home/tyil UWSGI_PIDPATH_MODE=0750 UWSGI_USER= UWSGI_GROUP= UWSGI_EMPEROR_PATH= UWSGI_EMPEROR_PIDPATH_MODE=0770 UWSGI_EMPEROR_GROUP= UWSGI_EXTRA_OPTIONS="--ini /etc/uwsgi.d/cgit.ini" {% endhighlight %} That covers the service configuration file. When things don't work the way you expect, specify a path in `UWSGI_LOG_FILE` to see its logs. Additionally, you may want to alter the value of `UWSGI_DIR`. This specifies the working directory from which the process starts. Now comes the application configuration, which will be read from `/etc/uwsgi.d/cgit.ini`, according to `UWSGI_EXTRA_OPTIONS`. Create that file with the following contents. {% highlight ini %} [uwsgi] master = true plugins = cgi socket = 127.0.0.1:1234 uid = cgit gid = cgit procname-master = uwsgi cgit processes = 1 threads = 2 cgi = /usr/share/webapps/cgit/1.2.1/hostroot/cgi-bin/cgit.cgi {% endhighlight %} Note that the `cgi` value contains the version number of `www-apps/cgit`. You may need to come back after an upgrade and update it accordingly. As last step for `uwsgi` configuration, a service script, to manage it with `rc-service`. These scripts all exist in `/etc/conf.d`, and the package installed a script called `uwsgi` in there. Just like with the `conf.d` variant, its just a template. This time, however, don't make a copy of it, but a symlink. It does not need to be edited, but the name must be the same as the `conf.d` entry name. That would be `uwsgi.cgit`. {% highlight sh %} cd /etc/conf.d ln -s uwsgi uwsgi.cgit {% endhighlight %} Now you can start the service with `rc-service uwsgi.cgit start`. If a consequent `status` notes the state as *Started*, you're all good. If the state says *Crashed*, you should go back and double-check all configuration files. When those are correct and you can't figure out why, feel free to reach out to me via email. {% highlight sh %} rc-service uwsgi.cgit start rc-service uwsgi.cgit service # Start this after boot rc-update add uwsgi.cgit {% endhighlight %} ### nginx The final element to make it accessible, the web server, `nginx`. How you organize the configuration files here is largely up to you. Explaining how to set up nginx from scratch is beyond the scope of this post. Assuming you know how to configure this, add the following `location` blocks to the `server` definition for the vhost you want to make `cgit` available on. {% highlight nginx %} location "/git" { alias /usr/share/webapps/cgit/1.2.1/htdocs; try_files $uri @cgit; } location @cgit { include uwsgi_params; gzip off; uwsgi_modifier1 9; uwsgi_pass 127.0.0.1:1234; fastcgi_split_path_info ^(/git/?)(.+)$; uwsgi_param PATH_INFO $fastcgi_path_info; } {% endhighlight %} Once saved, you can reload `nginx`, and the `$HOSTNAME/git` endpoint can be reached, and should display an cgit page, detailing there are no repositories. That can be easily solved by making some available in `$HOME/.local/srv/cgit`, through the power of symlinks. ## Symlinking the repositories Go nuts with making symlinks to the various repositories you have gathered over the years. You don't need to use bare repositories, `cgit` will also handle regular repositories that you actively work in. As with the `nginx` configuration, explaining how to make symlinks is out of scope. In dire situations, consult `man ln`. ### `git-mkbare` While making the symlinks is easy, I found that it sheepishly boring to do. I go to `$HOME/.local/git`, make a directory, `cd` to it, and create a bare repository. Then off to `$HOME/.local/srv/cgit` to make a symlink back to the newly created bare repository. I think you can see this will get tedious very quickly. So, to combat this, I made a small shell script to do all of that for me. I called it `git-mkbare`, and put it somewhere in my `$PATH`. This allows me to call it as `git mkbare repo-name`. It will ask for a small description as well, so I that can also be skipped as a manual task. This script may be of use to you if you want to more quickly start a new project. You can find this script [in my dotfiles repository](https://home.tyil.nl/git/dotfiles/tree/.local/bin/git-mkbare). ## Wrapping up Now you should have cgit available from your site, allowing you to share the sources of all your projects easily with the world. No need to make use of a (proprietary) third-party service! If you have questions or comments on my setup, or the post in general, please contact me through email or irc.