Setup cgit with nginx on Arch Linux
I recently had to setup cgit
with nginx
on Arch Linux for https://siosm.fr/git and it took me quite some time as I was not familiar with cgi
, fcgi
, fcgiwrap
, spawn-fcgi
and had no idea how they worked together.
2012-11-11 update: Add systemd support
Moreover, most of the howtos I found on the internet where using custom init scripts or perl scripts which didn’t feel really right and maintainable. On Arch Linux we won’t even have to compile anything from source as all the required packages are available in the repositories:
I chose to copy cgit.css
and cgit.png
to an other folder (/srv/cgit
) to be able to easily edit them but you can keep the default location (found using pacman -Ql cgit
).
So how do we setup cgit
with nginx
? nginx
seems to only support the FastCGI protocol so we’ll need something to make the link between cgit
and nginx
as cgit
is a “cgi for git”. Here comes fcgiwrap
, which will “serve CGI applications over FastCGI”. Reading the manpages, you may notice this line:
The recommended way to deploy fcgiwrap is to run it under a process manager that takes care of opening the socket.
and this one:
Most probably you will want to launch fcgiwrap by spawn-fcgi using a configuration like this: …
So let’s have a look at spawn-fcgi
. It’s a daemon that will take care of setup for our fcgi
applications. As we’re now using systemd, here is a sample fcgiwrap.service
systemd service unit file which can be copied in /etc/systemd/system
:
1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Simple server for running CGI applications over FastCGI
After=syslog.target network.target
[Service]
Type=forking
Restart=on-abort
PIDFile=/var/run/fcgiwrap.pid
ExecStart=/usr/bin/spawn-fcgi -s /var/run/fcgiwrap.sock -P /var/run/fcgiwrap.pid -u http -g http -M 700 -- /usr/sbin/fcgiwrap
ExecStop=/usr/bin/kill -15 $MAINPID
[Install]
WantedBy=multi-user.target
This config uses a local unix socket, restricts user
and group
to http
and will handle FastCGI requests from nginx
.
I then configured nginx
with this extract from /etc/nginx/conf/nginx.conf
:
You will then have to tell systemd to reload unit files and to restart nginx
and fcgiwrap
:
I’m also using gitolite
and the git-daemon
to manage access to my repositories. The configuration for gitolite
is clearly detailed on the gitolite wiki, but the git-daemon
is not securly configured by default as it is running as root
.
Thanks to systemd, we can easily use socket-based daemon activation here. Thus I copied the git-daemon@.service
file (not git-daemon.service
) to /etc/systemd/system
and modified it to increase security:
1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=Git Daemon Instance
[Service]
User=nobody
Group=git
# The '-' is to ignore non-zero exit statuses
ExecStart=-/usr/lib/git-core/git-daemon --inetd --base-path=/srv/git /srv/git
StandardInput=socket
StandardOutput=inherit
StandardError=journal
We can now enable the git-daemon
socket with systemd
and it will spawn git-dameon
instances for us:
So what’s the lesson learned this time? RTFM. I clearly did not read the manuals carefully enough and wasted a lot of time. The only thing that wasn’t in the manuals was the rewrite rule for the nginx
configuration.
Old config when using initscripts
/etc/conf.d/fcgiwrap
:
1
2
3
4
5
6
7
8
9
10
11
SPAWNER='/usr/bin/spawn-fcgi'
FCGI_SOCKET='/var/run/fcgiwrap.sock'
FCGI_USER='http'
FCGI_GROUP='http'
FCGI_EXTRA_OPTIONS='-M 700'
FCGI_PROGRAM='/usr/sbin/fcgiwrap'
ALLOWED_ENV="PATH"
SPAWNER_ARGS="-u $FCGI_USER -g $FCGI_GROUP -s $FCGI_SOCKET $FCGI_EXTRA_OPTIONS -- /usr/sbin/fcgiwrap"
/etc/conf.d/git-daemon.conf
:
1
2
3
4
5
6
7
8
9
10
# path to git repositories served
GIT_REPO="/srv/git/"
# user and group
GIT_USER="nobody"
GIT_GROUP="git"
# see `man git-daemon` for all available options
# $GIT_REPO will be present twice in most configs
GIT_DAEMON_ARGS="--detach --syslog --verbose --base-path=$GIT_REPO --user=$GIT_USER --group=$GIT_GROUP $GIT_REPO"
Comments
You can also contact me directly if you have feedback.