From 3ac79530c2add55fde6e5acd53b670ee3821d90d Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Sun, 4 Jun 2017 13:50:36 +0200 Subject: post: Self-hosted git setup --- content/post/self-hosted-git.md | 147 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 content/post/self-hosted-git.md (limited to 'content') diff --git a/content/post/self-hosted-git.md b/content/post/self-hosted-git.md new file mode 100644 index 0000000..c73d255 --- /dev/null +++ b/content/post/self-hosted-git.md @@ -0,0 +1,147 @@ ++++ +Description = "I describe my git server setup (using cgit and gitolite), and what it allows" +Tags = ["development","git"] +date = "2017-06-04T12:33:02+02:00" +title = "A simple, powerful self-hosted git setup" ++++ + +I had been using [gogs][] for about a year. It worked reasonably +well, as it focuses on being a lightweight self-hosted GitHub +replacement. However, that wasn't really what I wanted. I just +wanted to host my own projects, I didn't need things like issues, pull +requests or wikis. + +I recently switched to [gitolite][] and [cgit][], as they were even +lighter on resources, don't require another login and work without +an external database. Gitolite is unusual in its configuration: it +creates a git repository with its configuration file. I will describe +how I use them, rather than how to set them up, as they both have +enough documentation on that. + +My gitolite configuration file looks like this: + +``` +repo gitolite-admin + RW+ = alan + +repo dotfiles + C = alan + RW+ = alan + R = READERS + option hook.post-update = github-mirror + +repo [a-z].* + C = alan + RW+ = CREATOR + RW = WRITERS + R = READERS +``` + +The first block just allows me to work with the configuration +repository, as the initial setup only enables one specific public SSH +key, whereas I have three keys that I configure gitolite with. + +The second configures my dotfiles specifically. Naturally, I should +be the only person with read/write access. The `R = READERS` line +allows remote configuration of read permissions via `ssh $DOMAIN +perms` (explained further below). The last line runs a mirror script +(just `git push --mirror…`) so that +my [dotfiles repository on GitHub][dotfiles-github] is updated when I +push to my private version. + +## Wild (or magic) repositories + +The third block is where things get interesting. gitolite has a +feature called [wildrepos][], which allows configuring a set of +repositories at once, using a regular expression to match the +repository name. + +The really nice thing here is that the repository need not exist +before applying the configuration. Therefore, the line `C = alan` +means that I can create a remote repository automatically by cloning a +repository URL that doesn't already exist. +I can clone and create a new repo simultaneously like so: + +{{< highlight shell-session >}} +cd ~/projects +git clone alanpearce.eu:some-new-repository +{{< /highlight >}} + +But with [ghq][], which I [blogged about before][using-ghq], I don't +have to concern myself with where to put the repository: + +{{< highlight shell-session >}} +$ ghq get alanpearce.eu:some-new-repository + clone ssh://alanpearce.eu/some-new-repository -> /Volumes/Code/projects/alanpearce.eu/some-new-repository + git clone ssh://alanpearce.eu/some-new-repository /Volumes/Code/projects/alanpearce.eu/some-new-repository +Cloning into '/Volumes/Code/projects/alanpearce.eu/some-new-repository'... +Initialized empty Git repository in /var/lib/gitolite/repositories/some-new-repository.git/ +warning: You appear to have cloned an empty repository. +{{< /highlight >}} + +The nice URLs come from this piece of my SSH configuration: + +``` +Host alanpearce.eu + HostName git.alanpearce.eu + User gitolite +``` + +## Configuring wild repositories + +This repository would be private by default, but I can change that by an +SSH command. Here's how I would do it: + +{{< highlight shell-session >}} +$ ssh alanpearce.eu perms some-new-repository + READERS gitweb +$ ssh alanpearce.eu perms some-new-repository + READERS daemon +{{< /highlight >}} + +The first command makes it visible in cgit, whilst the second makes it +clonable via `git://` url. I can make a repository +publically-clonable, but invisible on cgit by only allowing the `daemon` +user and not `gitweb`, if I wanted. + +I can also add or change the description of a repository shown on cgit like +so: + +{{< highlight shell-session >}} +$ ssh alanpearce.eu desc some-new-repository 'A new repository' +{{< /highlight >}} + +All the remote commands exposed by gitolite are described in the +`help` command + +{{< highlight shell-session >}} +$ ssh alanpearce.eu help +hello alan, this is gitolite@oak running gitolite3 (unknown) on git 2.12.2 + +list of remote commands available: + + D + desc + help + info + motd + perms + writable + +{{< /highlight >}} + +## Conclusion + +I much prefer creating repositories in this way. It's much simpler +and allows me to get on with working on the repositories rather than +going through a multi-step process in a web browser. + +With cgit and gitolite, I have a minimal setup, that does exactly what +I want, without consuming many system resources with daemons. + +[gogs]:https://gogs.io/ "Go Git Service" +[gitolite]:http://gitolite.com/gitolite/ +[cgit]:https://git.zx2c4.com/cgit/ +[NixOS]:http://nixos.org +[dotfiles-github]:https://github.com/alanpearce/dotfiles +[wildrepos]:http://gitolite.com/gitolite/wild/ +[ghq]:https://github.com/motemen/ghq +[using-ghq]:{{< relref "post/repository-management-with-ghq.md" >}} "Repository management with ghq" -- cgit 1.4.1