summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorAlan Pearce2017-06-04 13:50:36 +0200
committerAlan Pearce2017-06-04 13:50:36 +0200
commit3ac79530c2add55fde6e5acd53b670ee3821d90d (patch)
tree700db6e48c3904910eed07a49c97f07b9bcd0d91 /content
parent0254c947f04abacdb932d21f7fca5ad0113bc5f3 (diff)
downloadwebsite-3ac79530c2add55fde6e5acd53b670ee3821d90d.tar.xz
website-3ac79530c2add55fde6e5acd53b670ee3821d90d.zip
post: Self-hosted git setup
Diffstat (limited to 'content')
-rw-r--r--content/post/self-hosted-git.md147
1 files changed, 147 insertions, 0 deletions
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 @@
1+++
2Description = "I describe my git server setup (using cgit and gitolite), and what it allows"
3Tags = ["development","git"]
4date = "2017-06-04T12:33:02+02:00"
5title = "A simple, powerful self-hosted git setup"
6+++
7
8I had been using [gogs][] for about a year. It worked reasonably
9well, as it focuses on being a lightweight self-hosted GitHub
10replacement. However, that wasn't really what I wanted. I just
11wanted to host my own projects, I didn't need things like issues, pull
12requests or wikis.
13
14I recently switched to [gitolite][] and [cgit][], as they were even
15lighter on resources, don't require another login and work without
16an external database. Gitolite is unusual in its configuration: it
17creates a git repository with its configuration file. I will describe
18how I use them, rather than how to set them up, as they both have
19enough documentation on that.
20
21My gitolite configuration file looks like this:
22
23```
24repo gitolite-admin
25 RW+ = alan
26
27repo dotfiles
28 C = alan
29 RW+ = alan
30 R = READERS
31 option hook.post-update = github-mirror
32
33repo [a-z].*
34 C = alan
35 RW+ = CREATOR
36 RW = WRITERS
37 R = READERS
38```
39
40The first block just allows me to work with the configuration
41repository, as the initial setup only enables one specific public SSH
42key, whereas I have three keys that I configure gitolite with.
43
44The second configures my dotfiles specifically. Naturally, I should
45be the only person with read/write access. The `R = READERS` line
46allows remote configuration of read permissions via `ssh $DOMAIN
47perms` (explained further below). The last line runs a mirror script
48(just `git push --mirror…`) so that
49my [dotfiles repository on GitHub][dotfiles-github] is updated when I
50push to my private version.
51
52## Wild (or magic) repositories
53
54The third block is where things get interesting. gitolite has a
55feature called [wildrepos][], which allows configuring a set of
56repositories at once, using a regular expression to match the
57repository name.
58
59The really nice thing here is that the repository need not exist
60before applying the configuration. Therefore, the line `C = alan`
61means that I can create a remote repository automatically by cloning a
62repository URL that doesn't already exist.
63I can clone and create a new repo simultaneously like so:
64
65{{< highlight shell-session >}}
66cd ~/projects
67git clone alanpearce.eu:some-new-repository
68{{< /highlight >}}
69
70But with [ghq][], which I [blogged about before][using-ghq], I don't
71have to concern myself with where to put the repository:
72
73{{< highlight shell-session >}}
74$ ghq get alanpearce.eu:some-new-repository
75 clone ssh://alanpearce.eu/some-new-repository -> /Volumes/Code/projects/alanpearce.eu/some-new-repository
76 git clone ssh://alanpearce.eu/some-new-repository /Volumes/Code/projects/alanpearce.eu/some-new-repository
77Cloning into '/Volumes/Code/projects/alanpearce.eu/some-new-repository'...
78Initialized empty Git repository in /var/lib/gitolite/repositories/some-new-repository.git/
79warning: You appear to have cloned an empty repository.
80{{< /highlight >}}
81
82The nice URLs come from this piece of my SSH configuration:
83
84```
85Host alanpearce.eu
86 HostName git.alanpearce.eu
87 User gitolite
88```
89
90## Configuring wild repositories
91
92This repository would be private by default, but I can change that by an
93SSH command. Here's how I would do it:
94
95{{< highlight shell-session >}}
96$ ssh alanpearce.eu perms some-new-repository + READERS gitweb
97$ ssh alanpearce.eu perms some-new-repository + READERS daemon
98{{< /highlight >}}
99
100The first command makes it visible in cgit, whilst the second makes it
101clonable via `git://` url. I can make a repository
102publically-clonable, but invisible on cgit by only allowing the `daemon`
103user and not `gitweb`, if I wanted.
104
105I can also add or change the description of a repository shown on cgit like
106so:
107
108{{< highlight shell-session >}}
109$ ssh alanpearce.eu desc some-new-repository 'A new repository'
110{{< /highlight >}}
111
112All the remote commands exposed by gitolite are described in the
113`help` command
114
115{{< highlight shell-session >}}
116$ ssh alanpearce.eu help
117hello alan, this is gitolite@oak running gitolite3 (unknown) on git 2.12.2
118
119list of remote commands available:
120
121 D
122 desc
123 help
124 info
125 motd
126 perms
127 writable
128
129{{< /highlight >}}
130
131## Conclusion
132
133I much prefer creating repositories in this way. It's much simpler
134and allows me to get on with working on the repositories rather than
135going through a multi-step process in a web browser.
136
137With cgit and gitolite, I have a minimal setup, that does exactly what
138I want, without consuming many system resources with daemons.
139
140[gogs]:https://gogs.io/ "Go Git Service"
141[gitolite]:http://gitolite.com/gitolite/
142[cgit]:https://git.zx2c4.com/cgit/
143[NixOS]:http://nixos.org
144[dotfiles-github]:https://github.com/alanpearce/dotfiles
145[wildrepos]:http://gitolite.com/gitolite/wild/
146[ghq]:https://github.com/motemen/ghq
147[using-ghq]:{{< relref "post/repository-management-with-ghq.md" >}} "Repository management with ghq"