Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

402 lines (278 sloc) 14.085 kB

% gitolite cookbook

@@gray((a.k.a. "shut up with all the rambling and just tell me the bare minimum I need to finish this!"))@@

include sidebar-toc

@@box-r(Note: This page has several [forward references][fr]. Skip it, or maybe skim through it, on a first reading. It's more of a "look at it when I have a specific need" page anyway.)@@

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.

administration {#cb-admin}

separating "key admin" from "repo admin"

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 :-)

.#d

.#! conf/vim-color 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"

.end

.#d

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":

.#t

access {#cb-access}

looking up repo access from external tools

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][gitweb-daemon]. Some notes:

  • be sure to read the comments in the code to learn exactly how to adapt it to your needs
  • in place of the 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
    ...

@@gray(If your gitolite is older than v3.6, you must use the full ref name; just 'master' won't do.)@@

allowing access by other programs

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][rc], because that's the only setting that gitolite controls; every thing else is pure Unix.

commands {#cb-commands}

adding your own commands

To add a command, say foo, do this:

  1. 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",
    
  2. copy the program foo into $HOME/local/commands. (Don't forget the chmod +x!)

making commands available to remote users

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.

hooks {#cb-hooks}

The main documentation for this feature starts [here][hooks].

adding your own update hooks

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:

  1. 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",
    
  2. copy your update hook to a subdirectory called VREF under this directory, giving it a suitable name (let's say "crlf"):

    # log on to server
    cd $HOME
    mkdir -p local/VREF
    cp your-crlf-update-hook local/VREF/crlf
    chmod +x local/VREF/crlf
    
  3. 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: .#! conf/vim-color repo @all - VREF/crlf = @all .end

    Either way, add/commit/push the change to the gitolite-admin repo.

adding other (non-update) hooks

Say you want other hooks, like a post-receive hook. Here's how:

  1. 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",
    
  2. put your hooks into that directory, in a sub-sub-directory called "hooks/common":

    # log on to server
    cd $HOME
    mkdir -p local/hooks/common
    cp your-post-receive-hook local/hooks/common/post-receive
    chmod +x local/hooks/common/post-receive
    
  3. run gitolite setup to have the hooks propagate to existing repos (repos created after this will get them anyway).

variation: maintain these hooks in the gitolite-admin repo

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:

  1. 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!

  2. 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".

  3. 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.

@@gray((v3.6+))@@ variation: repo-specific hooks

Until now, the non-update hooks you specified apply to all repos. Here's how to apply them only to certain repos:

  1. 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",
    
  2. 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][addtrig] for more on all this.

  3. 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).

  4. 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
    
  5. add, commit, and push the admin repo.

VREFs {#cb-vrefs}

adding your own VREFs

Adding VREFs is the same as adding the update hook, so please see the section on "adding your own update hooks" above.

example VREFs

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][vref-args] as you look at these.

example 1: restricting by day of week

Here's the conf extract to say "junior devs can only push on weekdays":

.#! conf/vim-color repo foo - VREF/DAY/Sat = @junior-devs - VREF/DAY/Sun = @junior-devs .end

The code for this VREF is ridiculously simple:

.#! conf/vim-color #!/bin/bash echo VREF/DAY/date +%a # vim: set ft=sh .end

On encountering the VREF rules (i.e., when a junior dev tries to access 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 access is denied.

example 2: restricting by source IP address

This one restricts junior developers to access 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:

.#! conf/vim-color repo foo RW+ VREF/FROM/192.168.48.0/23 = @junior-devs - VREF/FROM = @junior-devs .end

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).

.#! conf/vim-color #!/bin/bash

# exit if no arguments were supplied to the VREF.  This covers the
# second VREF rule in the conf above
[ -n "$8" ] || exit 0

from=${SSH_CONNECTION%% *}

eval `ipcalc -n $from/$9`       # sets env var "NETWORK"

echo VREF/FROM/$NETWORK/$9
# vim: set ft=sh

.end

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 access.

(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).

wild repos

making exceptions for specific instances of a wild repo

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:

.#! conf/vim-color repo foo/..* C = blah blah RW+ = CREATOR RW = WRITERS R = READERS

# this does NOT work
repo foo/special-1
    RW+                 =   sitaram
    option  foo.bar     =   baz

.end

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:

.#! conf/vim-color # this will work repo foo/special-[1] RW+ = sitaram option foo.bar = baz .end

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][accum].

moving stuff around {#cb-move}

moving a gitolite install from one machine to another

See [moving servers][moving].

Jump to Line
Something went wrong with that request. Please try again.