summaryrefslogtreecommitdiff
path: root/content/posts/2020/2020-01-08-running-cgit-on-gentoo.md
blob: 085da26fadc73446c984750e07df0f398d9f18d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
---
title: Running cgit on Gentoo
date: 2020-01-08
tags:
- git
- cgit
- Gentoo
---

[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.

```txt
emerge dev-python/pygments www-apps/cgit www-servers/nginx www-servers/uwsgi
```

## 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.

```txt
# 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
```

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.

```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
```

#### 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.

```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"
```

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.

```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
```

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`.

```txt
cd /etc/conf.d
ln -s uwsgi uwsgi.cgit
```

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.

```txt
rc-service uwsgi.cgit start
rc-service uwsgi.cgit service

# Start this after boot
rc-update add uwsgi.cgit
```

### 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.

```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;
}
```

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://git.tyil.nl/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.