Documentation is meant to be as complete as possible, which means it attempts to cover all situations and scenarios. That makes it harder to read.
However, if you make some assumptions, remove the rationale, justification, exceptions and special cases, etc., and generally just say what is to be done rather than explain why, many tasks can be described very easily.
Or, if the main documentation already does that, a cookbook may help you find it faster, simply because it's organised differently.
Maybe this will help. If you run into problems, please check the main documentation before asking for help.
In gitolite, the person who controls the keys is the most critical in terms of security -- because he can always add his own key in your name :-)
Traditionally, the same person also administers repos and permissions. But sometimes you want to separate them.
To separate those roles, put the following in conf/gitolite.conf, and let the repo-manager manage everything through "actual.conf":
```gitolite repo gitolite-admin RW+ = key-manager repo-manager
RW+ VREF/NAME/ = key-manager
- VREF/NAME/keydir/ = @all
- VREF/NAME/conf/gitolite.conf = @all
include "actual.conf" ```
There are two supported interfaces for this, one in perl and one in shell. Other languages should probably use the shell mode. (The shell mode has a very convenient "batch" mode if you need to check many repos at once).
Perl interface: A good intro to this, including a link to code, using gitweb as an example can be found by looking for 'repo-specific authorisation in gitweb' in the page on allowing access to gitweb and git-daemon. Some notes:
can_read
function in that code, you can of course use
can_write
. In fact, reading the comments in "Easy.pm" (look for it in
the source) shows you several other interesting tests you can make, like
is_admin
, in_group
, and owns
.Shell interface: If you want to do this from shell, it's even easier. The same "Easy.pm" source contains comments that show shell equivalents for each of the functions it exports, but here's a sample:
if gitolite access -q reponame username W
then
...
You can even test for access to specific branches:
if gitolite access -q reponame username W master
then
...
If your gitolite is older than v3.6, you must use the full ref name; just 'master' won't do.
Giving external tools (like apache) access to gitolite repositories involves making sure that the unix owner/group and permissions settings allow this. This is all described in the UMASK section in the page on the rc file, because that's the only setting that gitolite controls; every thing else is pure Unix.
To add a command, say foo
, do this:
add this line in the rc file, within the %RC
block, if it's not already
present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$ENV{HOME}/local",
copy the program foo
into $HOME/local/commands
. (Don't forget the
chmod +x
!)
Once you do the above, foo
is available as gitolite foo
. To make it
available to remote users (as ssh git@host foo
), add the line:
`foo`,
(including the comma at the end) to the ENABLE list in the rc file.
Note: the main documentation for this feature starts here.
You have some update hooks (for example crlf checking) that you want to
include in gitolite. Assuming the hook itself is tested and works as a normal
git update hook does (i.e., conforms to what man githooks
says an update
hook should do), here's how to do this:
add this line in the rc file, within the %RC
block, if it's not already
present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$ENV{HOME}/local",
copy your update hook to a subdirectory called VREF under this directory, giving it a suitable name (let's say "crlf"):
# log on to gitolite hosting user on the server, then:
cd $HOME
mkdir -p local/VREF
cp your-crlf-update-hook local/VREF/crlf
chmod +x local/VREF/crlf
in your gitolite-admin clone, edit conf/gitolite.conf and add lines like this:
- VREF/crlf = @all
to each repo that should have that "update" hook.
Alternatively, you can simply add this at the end of the gitolite.conf file:
gitolite
repo @all
- VREF/crlf = @all
Either way, add/commit/push the change to the gitolite-admin repo.
Say you want other hooks, like a post-receive hook. Here's how:
add this line in the rc file, within the %RC
block, if it's not already
present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$ENV{HOME}/local",
put your hooks into that directory, in a sub-sub-directory called "hooks/common":
# log on to gitolite hosting user on the server, then:
cd $HOME
mkdir -p local/hooks/common
cp your-post-receive-hook local/hooks/common/post-receive
chmod +x local/hooks/common/post-receive
run gitolite setup
to have the hooks propagate to existing repos (repos
created after this will get them anyway).
!!! danger "Important security note:"
**If you enable this, anyone who can push changes to the admin repo will
effectively be able to run any arbitrary command on the server.** See
[gitolite admin and shell access][privesc] for more background.
If you want to maintain these update hooks (VREFs) or non-update hooks (post-update, pre-receive, post-receive) in the gitolite-admin repo, instead of having to log on to the server and make changes, the procedure is almost the same except for the following differences:
add this line in the rc file, within the %RC
block, if it's not already
present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local",
Notice "local" is not in $HOME
like in the previous examples!
the hooks/scripts are to be added inside your gitolite-admin clone, not on
the server. That is, whereever the above two sections say cd $HOME
,
you should read it as "cd /path/to/your/gitolite-admin-clone".
(The directory local
will be within this clone of course, not in
$HOME
.)
add/commit/push as usual.
For update hooks, you will of course need to add VREF rule lines to appropriate repos in the conf file. For non-update hooks, you don't need to run 'gitolite setup' on the server; the push takes care of that.
Until now, the non-update hooks you specified apply to all repos. Here's how to apply them only to certain repos:
add this line in the rc file, within the %RC
block, if it's not already
present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local",
uncomment the 'repo-specific-hooks' line in the rc file or add it to the ENABLE list if it doesn't exist.
If your rc file does not have an ENABLE list, you need to add this to the POST_COMPILE and the POST_CREATE lists. Click here for more on all this.
put your hooks into your gitolite-admin clone, as follows:
# on your workstation
cd /path/to/your/gitolite-admin-clone
mkdir -p local/hooks/repo-specific
Now add your hooks to that directory, but instead of using the git "standard" names (pre-receive, post-receive, post-update), you use descriptive names (e.g. "deploy", "RSS-post", etc).
For pre-receive or pre-auto-gc you should not use more than one hook. If you really need more than one, ask on the mailing list.
add them to the repos you want them to be active in, in your conf file. For example:
repo foo
option hook.post-update = jenkins
repo bar @baz
option hook.post-update = deploy RSS-post
add, commit, and push the admin repo.
First, write your trigger code, using the documentation here. Note especially the sections "common arguments" and "trigger-specific arguments". Look in the shipped triggers for ideas.
!!! danger "Note:"
If your trigger is a perl module, as opposed to a standalone script or
executable, please see the section on [adding a perl module as a
trigger][addtrigp].
Let's say your trigger is called foo
, and it will be a PRE_GIT
trigger.
add this line in the rc file, within the %RC
block, if it's not already
present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$ENV{HOME}/local",
copy the program foo
into $HOME/local/triggers
. (Don't forget the
chmod +x
!)
edit ~/.gitolite.rc
again, and look for a PRE_GIT
section. If it
exists, add 'foo',
(note the trailing comma!) to it. If it does not
exist, add this block just before the ENABLE
section:
PRE_GIT =>
[
'foo'
],
(again, note the trailing comma at the end of the block!)
After saving the file, test that this worked by running gitolite query-rc PRE_GIT
;
your foo
should be in the output list. If it's not, back up
and double check your work.
That should be it.
Adding VREFs is the same as adding the update hook, so please see the section on "adding your own update hooks" above.
However, writing a proper VREF is not the same as writing a normal git "update hook". A proper VREF does more than just take 3 arguments, do something, and exit with a non-zero exit code for failure.
A VREF is called with at least 4 more arguments after the 3 that git itself defines for an update hook, plus usually at least one or two more. It also returns a lot more meaningful results via STDOUT.
Here are some examples. I also advise you to keep a browser tab open to the doc on VREF arguments as you look at these.
!!! danger "Important:"
**VREFs only come into play for push operations. When we say "access" in
this section, we mean only write access.** If you want to restrict it
even for reads, you can do this in a `PRE_GIT` trigger; there's an example
in `contrib/triggers/IP-check` in the gitolite source tree that may be
useful as a template.
Here's the conf extract to say "junior devs can only push on weekdays":
gitolite
repo foo
- VREF/DAY/Sat = @junior-devs
- VREF/DAY/Sun = @junior-devs
The code for this VREF is ridiculously simple:
```sh
echo VREF/DAY/date +%a
```
On encountering the VREF rules (i.e., when a junior dev tries to push to this repo), gitolite calls the "DAY" VREF-maker. The code within the VREF maker simply echoes something like "VREF/DAY/Mon", where the last part is whatever the actual day of the week happens to be.
This output is then treated as a virtual ref and matched against the rules. On a Monday to Friday, nothing happens, because the VREFs generated do not match any deny rules (or indeed any rules at all). On weekends, they do match, and the push is denied.
This one restricts junior developers to push to this repo only from a specific network block. The conf file here is slightly different. We know that the VREF-maker will return with some network address (as you'll see in the code later), so we set it up so that the correct network block is allowed and anything else is disallowed:
gitolite
repo foo
RW+ VREF/FROM/192.168.48.0/23 = @junior-devs
- VREF/FROM = @junior-devs
The code is not that complex. We take the user's actual IP address (this is
available as the first word in $SSH_CONNECTION
for ssh users, and for
smart-http users, gitolite fakes it and creates that variable!). We then
treat the "23" in the VREF rule, which appears to the code as $9
, as the
number of bits in the network address, then compute the network address for
the users IP with that number of bits.
This network address is then sent back. (The $9
is added back at the end,
but this is only to enable it to match the VREF rule).
```sh
[ -n "$8" ] || exit 0
from=${SSH_CONNECTION%% *}
eval ipcalc -n $from/$9
# sets env var "NETWORK"
echo VREF/FROM/$NETWORK/$9 ```
For a source IP of 192.168.49.97, this runs ipcalc -n 192.168.49.97/23
,
which gives the network address 192.168.48.0. The echo then just sends back
VREF/FROM/192.168.48.0/23. This VREF matches the RW+ line.
But if the IP is, say, 192.168.45.67, running ipcalc -n 192.168.45.67/23
gives you 192.168.44.0. The echo then send back VREF/FROM/192.18.44.0/23,
which won't match the RW+ line, but will match the next one and thus deny
the push.
(One thing that may not be obvious in this specific example is that you have
to be careful when constructing the VREF rule. For any VREF/FROM/A/B, the
result of running ipcalc -n A/B
must be A, otherwise this won't work. That
is, the bits of the network address after the network bits must be zero).
Sometimes you want to specify rules or config for specific instances of a wild repo, while still leaving it to be created by a user in the normal way.
This will not work:
```gitolite repo foo/..* C = blah blah RW+ = CREATOR RW = WRITERS R = READERS
repo foo/special-1 RW+ = sitaram option foo.bar = baz ```
The repo will be created as a normal (not wild) repo as soon as you push, which means you can't run the perms command on it to add people to the READERS and WRITERS roles, or do other things that wild repos allow.
The mental nudge you need to deal with this is to think what you would do if you had to write the same rule for more than one repo, say, any repo starting with "foo/special-" followed by a number. You'd use a pattern. And a pattern prevents an ordinary repo from being created.
So do this:
```gitolite
repo foo/special-[1] RW+ = sitaram option foo.bar = baz ```
Using a pattern for just one repo might sound like a kludge, but it's perfectly valid and supported.
Note that you do NOT need a "C" rule in there, since the pattern is a subset
of the previous one (foo/..*
), everything there applies to this repo also.
If you're not sure why that is, you may need to read up on rule
accumulation.
See moving servers.