Since gitorious' shutdown I decided it was time to start hosting my
own git repositories for my own little projects (although the company
which took over gitorious has a Free software offering it seems that
their hosted offering is based on the proprietary version, and in any
case
once bitten, twice shy and all that).
After a bit of investigation I settled on using
gitolite and
gitweb. I did consider
(and even had a vague preference for)
cgit but it wasn't available in Wheezy
(even backports, and the backport looked tricky) and I haven't
upgraded my VPS yet. I may reconsider cgit this once I switch to
Jessie.
The only wrinkle was that my VPS is shared with a friend and I didn't
want to completely take over the
gitolite and
gitweb namespaces in
case he ever wanted to setup
git.hisdomain.com, so I needed
something which was at least somewhat compatible with
vhosting.
gitolite doesn't appear to support such things out of the
box but I found an
interesting/useful
post
from Julius Plenz which included sufficient inspiration that I thought
I knew what to do.
After a bit of trial and error here is what I ended up with:
Install gitolite
The
gitolite website has
plenty of documentation on configuring gitolite. But since
gitolite is
in Debian its even more trivial than even the quick install makes out.
I decided to use the newer
gitolite3 package from
wheezy-backports instead of the
gitolite (v2) package
from Wheezy. I already had backports enabled so this was just:
# apt-get install gitolite3/wheezy-backports
I accepted the defaults and gave it the public half of the ssh key
which I had created to be used as the
gitolite admin key.
By default this added a user
gitolite3 with a home directory of
/var/lib/gitolite3. Since they username forms part of the URL used
to access the repositories I want it to include the 3, so I edited
/etc/passwd,
/etc/groups,
/etc/shadow and
/etc/gshadow to say
just
gitolite but leaving the home directory as
gitolite3.
Now I could clone the
gitolite-admin repo and begin to configure
things.
Add my user
This was simple as dropping the public half into the
gitolite-admin
repo as
keydir/ijc.pub, then
git add,
commit and
push.
Setup vhosting
Between
the gitolite
docs and
Julius'
blog
post
I had a pretty good idea what I wanted to do here.
I wasn't too worried about making the vhost transparent from the
developer's (ssh:// URL) point of view, just from the
gitweb and
git clone side. So I decided to adapt things to use a simple
$VHOST/$REPO.git schema.
I created
/var/lib/gitolite3/local/lib/Gitolite/Triggers/VHost.pm
containing:
package Gitolite::Triggers::VHost;
use strict;
use warnings;
use File::Slurp qw(read_file write_file);
sub post_compile
my %vhost = ();
my @projlist = read_file("$ENV HOME /projects.list");
for my $proj (sort @projlist)
$proj =~ m,^([^/\.]*\.[^/]*)/(.*)$, or next;
my ($host, $repo) = ($1,$2);
$vhost $host //= [];
push @ $vhost $host => $repo;
for my $v (keys %vhost)
write_file("$ENV HOME /projects.$v.list",
atomic => 1 , join("\n",@ $vhost $v ));
1;
I then edited
/var/lib/gitolite3/.gitolite.rc and ensured it
contained:
LOCAL_CODE => "$ENV HOME /local",
POST_COMPILE => [ 'VHost::post_compile', ],
(The first I had to uncomment, the second to add).
All this trigger does is take the global
projects.list, in which
gitolite will list any repo which is configured to be accessible via
gitweb, and split it into several vhost specific lists.
Create first repository
Now that the basics were in place I could create my first repository
(for hosting
qcontrol).
In the
gitolite-admin repository I edited
conf/gitolite.conf and added:
repo hellion.org.uk/qcontrol
RW+ = ijc
After adding, committing and pushing I now have
"/var/lib/gitolite3/projects.list" containing:
hellion.org.uk/qcontrol.git
testing.git
(the
testing.git repository is configured by default) and
/var/lib/gitolite3/projects.hellion.org.uk.list containing just:
qcontrol.git
For cloning the URL is:
gitolite@$ VPSNAME :hellion.org.uk/qcontrol.git
which is rather verbose (
$ VPSNAME is quote long in my case too),
so to simplify things I added to my
.ssh/config:
Host gitolite
Hostname $ VPSNAME
User gitolite
IdentityFile ~/.ssh/id_rsa_gitolite
so I can instead use:
gitolite:hellion.org.uk/qcontrol.git
which is a bit less of a mouthful and almost readable.
Configure gitweb (http:// URL browsing)
Following the
documentation's
advice I edited
/var/lib/gitolite3/.gitolite.rc to set:
UMASK => 0027,
and then:
$ chmod -R g+rX /var/lib/gitolite3/repositories/*
Which arranges that members of the
gitolite group can read anything
under
/var/lib/gitolite3/repositories/*.
Then:
# adduser www-data gitolite
This adds the user
www-data to the
gitolite group so it can take
advantage of those relaxed permissions. I'm not super happy about this
but since gitweb runs as
www-data:www-data this seems to be the
recommended way of doing things. I'm consoling myself with the fact
that I don't plan on hosting anything sensitive... I also arranged
things such that members of the groups can only list the contents of
directories from the vhost directory down by setting
g=x not
g=rx
on higher level directories. Potentially sensitive files do not have group
permissions at all either.
Next I created
/etc/apache2/gitolite-gitweb.conf:
die unless $ENV GIT_PROJECT_ROOT ;
$ENV GIT_PROJECT_ROOT =~ m,^.*/([^/]+)$,;
our $gitolite_vhost = $1;
our $projectroot = $ENV GIT_PROJECT_ROOT ;
our $projects_list = "/var/lib/gitolite3/projects.$ gitolite_vhost .list";
our @git_base_url_list = ("http://git.$ gitolite_vhost ");
This extracts the vhost name from
$ GIT_PROJECT_ROOT (it must be
the last element) and uses it to select the appropriate vhost specific
projects.list.
Then I added a new vhost to my apache2 configuration:
<VirtualHost 212.110.190.137:80 [2001:41c8:1:628a::89]:80>
ServerName git.hellion.org.uk
SetEnv GIT_PROJECT_ROOT /var/lib/gitolite3/repositories/hellion.org.uk
SetEnv GITWEB_CONFIG /etc/apache2/gitolite-gitweb.conf
Alias /static /usr/share/gitweb/static
ScriptAlias / /usr/share/gitweb/gitweb.cgi/
</VirtualHost>
This configures
git.hellion.org.uk (don't forget to update DNS too)
and sets the appropriate environment variables to find the custom
gitolite-gitweb.conf and the project root.
Next I edited
/var/lib/gitolite3/.gitolite.rc again to set:
GIT_CONFIG_KEYS => 'gitweb\.(owner description category)',
Now I can edit the repo configuration to be:
repo hellion.org.uk/qcontrol
owner = Ian Campbell
desc = qcontrol
RW+ = ijc
R = gitweb
That
R permission for the
gitweb pseudo-user causes the repo to be
listed in the global
projects.list and the trigger which we've added
causes it to be listed in
projects.hellion.org.uk.list, which is
where our custom
gitolite-gitweb.conf will look.
Setting
GIT_CONFIG_KEYS allows those options (
owner and
desc are
syntactic sugar for two of them) to be set here and propagated to the
actual repo.
Configure git-http-backend (http:// URL cloning)
After all that this was pretty simple. I just added this to my vhost
before the
ScriptAlias / /usr/share/gitweb/gitweb.cgi/ line:
ScriptAliasMatch \
"(?x)^/(.*/(HEAD \
info/refs \
objects/(info/[^/]+ \
[0-9a-f] 2 /[0-9a-f] 38 \
pack/pack-[0-9a-f] 40 \.(pack idx)) \
git-(upload receive)-pack))$" \
/usr/lib/git-core/git-http-backend/$1
This (which I stole straight from the
git-http-backend(1) manpage
causes anything which
git-http-backend should deal with to be sent
there and everything else to be sent to
gitweb.
Having done that access is enabled by editing the repo configuration
one last time to be:
repo hellion.org.uk/qcontrol
owner = Ian Campbell
desc = qcontrol
RW+ = ijc
R = gitweb daemon
Adding
R permissions for
daemon causes
gitolite to drop a stamp
file in the repository which tells
git-http-backend that it should
export it.
Configure git daemon (git:// URL cloning)
I actually didn't bother with this,
git http-backend supports the
smart HTTP mode which
should be as efficient as the git
protocol. Given
that I couldn't see any reason to run another network facing daemon on
my VPS.
FWIW it looks like vhosting could have been achieved by using the
--interpolated-path option.
Conclusion
There's quite a few moving parts, but they all seems to fit together
quite nicely. In the end apart from adding
www-data to the
gitolite group I'm pretty happy with how things ended up.