gitolite/doc/gitolite.conf.mkd
Sitaram Chamarty 5e3a051a95 "deny" rules for entire repo
- strictly speaking, this should be phrased: "deny" rules for the
    first level access check

  - requires a gitolite option to be set, like so:

        config gitolite-options.deny-repo = 1
2011-10-10 14:18:49 +05:30

613 lines
23 KiB
Markdown

# the access control file `gitolite.conf`
In this document:
* <a href="#_syntax">syntax</a>
* <a href="#_continuation_lines">continuation lines</a>
* <a href="#_include_files">include files</a>
* <a href="#_basic_access_control">basic access control</a>
* <a href="#_how_rules_are_matched">how rules are matched</a>
* <a href="#_branches_tags_and_specifying_refex_es">branches, tags, and specifying "refex"es</a>
* <a href="#_groups">groups</a>
* <a href="#_the_special_all_group">the special `@all` group</a>
* <a href="#_advanced_access_control">advanced access control</a>
* <a href="#_creating_and_deleting_branches">creating and deleting branches</a>
* <a href="#_deny_rules">"deny" rules</a>
* <a href="#_warnings_and_required_reading">warnings and required reading</a>
* <a href="#_deny_rules_for_refs_in_a_repo">"deny" rules for refs in a repo</a>
* <a href="#_deny_rules_for_the_entire_repo">"deny" rules for the entire repo</a>
* <a href="#_summary_permissions">summary: permissions</a>
* <a href="#_virtual_ref_types">virtual "ref"-types</a>
* <a href="#_other_tips">other tips</a>
* <a href="#_personal_branches">personal branches</a>
* <a href="#_splitting_up_rules_into_rulesets">splitting up rules into rulesets</a>
* <a href="#_gitweb_and_daemon">gitweb and daemon</a>
* <a href="#_repo_specific_git_config_commands">repo specific `git config` commands</a>
* <a href="#_repo_owner_description_line_for_gitweb">repo owner/description line for gitweb</a>
Gitolite has an advanced access control language that is designed to be
powerful but easy to use. Other objectives were that it should be even easier
to read, review and audit the rules, and it should scale to thousands of repos
and users. There was also, in the author's mind, a desperate need to create
something as different as possible from the brain-dead, nausea-inducing
"Windows INI" style syntax that some other popular tools seem to favour.
This document describes the syntax and semantics of the access control rules
and other configuration directives in the `gitolite.conf` file.
<a name="_syntax"></a>
### syntax
In general, everything is **space separated**; there are no commas,
semicolons, etc., in the syntax.
**Comments** are in the usual shell-ish style.
**User names** and **repo names** are as simple as possible; they must start
with an alphanumeric, but after that they can also contain `.`, `_`, or `-`.
Usernames can optionally be followed by an `@` and a domainname containing at
least one `.` (this allows you to use an email address as someone's username).
Reponames can contain `/` characters (this allows you to put your repos in a
tree-structure for convenience)
<a name="_continuation_lines"></a>
#### continuation lines
There are no continuation lines -- gitolite does not process C-style
backslash-escaped newlines as anything special. However, the section on
"groups" will tell you how you can break up large lists of names in a group
definition into multiple lines.
<a name="_include_files"></a>
#### include files
Gitolite allows you to break up the configuration into multiple files and
include them in the main file for convenience.
include "foo.conf"
will include the contents of the file "foo.conf" from the same directory as
the main config file. You can also use an absolute path if you like, although
in the interests of cloning the admin-repo sanely you should avoid doing this!
You can also use a glob, as in:
include "*.conf"
which will include all the ".conf" files from the directory in which the main
config file exists.
Files that have been already processed once are skipped, with a warning.
<font color="gray">Advanced users: `subconf`, a command that is very closely
related to `include`, is documented [here][subconf].</font>
[subconf]: http://sitaramc.github.com/gitolite/doc/delegation.html#_the_subconf_command
<a name="_basic_access_control"></a>
### basic access control
Here's a very basic set of rules:
repo gitolite-admin
RW+ = sitaram
repo testing
RW+ = @all
repo gitolite simplicity
RW+ = sitaram dilbert
RW = alice ashok
R = wally
It should be easy to guess what most of this means:
* `R` means "read" permission
* `RW` means "read and write", but no rewind
* `RW+` means "read and write", with rewind allowed
A "rewind" is more often called a "non-fast forward push"; see git docs for
what that is. The `+` was chosen because it is part of the "git push" syntax
for non-ff pushes.
Note that *tags* are generally considered "write once", so they are treated
specially by gitolite: you need rewind permission (`RW+`) to *overwrite* a
tag with a new value.
In a later section you'll see some more advanced permissions.
<font color="gray">
Side note: apparently it needs to be spelled out that "R" permissions can only
apply to the entire repo and not to individual branches/tags. Mention was
made of a certain popular Linux distribution named after animals with
adjectives, chosen merely for alliterative purposes, prefixed to their names,
and of their users not being clueful enough to know that this (the "read"
thing, not the alliterative adjective thing, in case you lost track) is an
inherent git characteristic.
Meanwhile, people who *desperately* need this are directed to gerrit, which
can do this because they have their own git stack and dont use the one written
by Linus and currently maintained by Junio.
</font>
<a name="_how_rules_are_matched"></a>
#### how rules are matched
It's important to understand that there're two levels at which access control
happens. Please see [this][l2] for details, especially about the first level
check. Much of the complexity applies only to the second level check, so that
is all we will be discussing here. This check is done by the update hook, and
determines whether the push succeeds or fails.
[l2]: http://sitaramc.github.com/gitolite/doc/3-faq-tips-etc.html#_two_levels_of_access_rights_checking
For basic permissions like this, matching is simple. Gitolite already knows:
* the user
* the repo
* the branch or tag ("ref") being pushed
* whether it is a normal (ff) push or a rewind (non-ff) push.
Gitolite goes down the list of rules matching the user, repo, and the ref.
The first matching rule that has the permission you're looking for (`W` or
`+`), results in success. A fallthrough results in failure.
<a name="_branches_tags_and_specifying_refex_es"></a>
#### branches, tags, and specifying "refex"es
One of the original goals of gitolite was to allow access control at the
branch/tag (aka "ref") level. The git source code contains a sample update
hook that has the following in it:
# from Documentation/howto/update-hook-example.txt:
refs/heads/master junio
+refs/heads/pu junio
refs/heads/cogito$ pasky
refs/heads/bw/.* linus
refs/heads/tmp/.* .*
refs/tags/v[0-9].* junio
If you did this in gitolite, this is what the equivalents would be:
repo git
RW master$ = junio # line 1
RW+ pu$ = junio # line 2
RW cogito$ = pasky # line 3
RW bw/ = linus # line 4
RW tmp/ = @all # line 5
RW refs/tags/v[0-9] = junio # line 6
The following points will help you understand these rules. (Git recap:
branches and tags together are called "ref"s in git. A branch ref usually
looks like "refs/heads/foo", while a tag ref looks like "refs/tags/bar")
* the general syntax of a paragraph of rules is:
# start line:
repo [one or more repos and/or repo groups]
# followed by one or more permissions lines:
[permission] [zero or more refexes] = [one or more users]
* a **refex** is a *perl regex* that matches a ref. When you try to push a
commit to a branch or a tag, that "ref" is matched against the refex part
of each rule.
* if the refex does not start with `refs/`, gitolite assumes a prefix of
`refs/heads/`. This is useful because *branch* matching is the most
common case, as you can see this applies to lines 1 through 5 here.
* if no refex appears, the rule applies to all refs in that repo (as if you
had specified `refs/.*` as the refex).
* refexes are prefix-matched (they are internally anchored with `^` before
being used). This means only the beginning of the actual ref needs to
match the refex, unless the refex has an explicit `$` meta-character at
the end (like the first 3 lines in our example do).
Line 5, for instance, allows anyone to push a branch inside the "tmp/"
namespace, while line 6 provides the ability to push version tags; "v1",
"v1.0", "v2.0rc1", all match the criterion specified by `v[0-9]` because
this is a prefix match only.
<a name="_groups"></a>
#### groups
Gitolite allows you to define **groups** of repos. users, or even refexes. A
group is semantically (but *not* syntactically) like a `#define` in C. Here
is an example of each kind:
@oss_repos = gitolite linux git perl rakudo entrans vkc
@staff = sitaram some_dev another-dev
@important = master$ QA_done refs/tags/v[0-9]
The syntax of a group definition is simply:
@groupname = [one or more names]
A group can *accumulate* values. For example:
@staff = sitaram some_dev another-dev
@staff = au.thor
is the same as
@staff = sitaram some_dev another-dev au.thor
This is more convenient than continuation lines, because it allows you to add
to a group anywhere. Many people generate their gitolite.conf itself from
some *other* database, and it is very useful to be able to do this sort of
thing.
Groups can include other groups, and the included group will be expanded to
whatever value it *currently* has:
@staff = sitaram some_dev another-dev # line 1
@staff = au.thor # line 2
@interns = indy james # line 3
@alldevs = bob @interns @staff # line 4
"@alldevs" expands to 7 names now. However, remember that the config file is
parsed in a single-pass, so later *additions* to a group name cannot affect
earlier *uses* of it. If you moved line 2 to the end, "@alldevs" would only
have 6 names in it.
<a name="_the_special_all_group"></a>
##### the special `@all` group
There's a special group called `@all` that includes all authenticated users
when used as a username; you've seen examples of it earlier.
[Advanced users: also see the entry for `GL_ALL_INCLUDES_SPECIAL` in
[doc/gitolite.rc.mkd][rcdoc].]
When used as a reponame, it includes all repos.
<a name="_advanced_access_control"></a>
### advanced access control
The previous section is sufficient for most common needs, but gitolite can go
a lot further than that.
<a name="_creating_and_deleting_branches"></a>
#### creating and deleting branches
Since the beginning of gitolite, `RW` gave the ability, not only to update,
but to *create* a branch (that matched the refex). Similarly, `RW+` meant
being able to not only rewind, but also delete a ref. Conceptually, a rewind
is almost the same as a delete+push (the only difference I can see is if you
had core.logAllRefUpdates set, which is *not* a default setting).
However, there seem to be cases where it is useful to distinguish these cases.
Arguments can be made on all sides if you're dealing with new users, so
gitolite supports that.
We'll look at the delete/rewind case in detail first:
* if the rules for a repo do not contain a `D` anywhere, then `RW+` will
allow both rewind and delete operations. Apart from being more convenient
if you don't need this separation, this also ensures backward
compatibility for setups created before this separation feature was added
to gitolite).
* if, however, *any* of the rules for a repo contains a `D` (example: `RWD`,
`RW+D`, etc) then `RW+` by itself will permit only a rewind, not a delete
The same thing applies to create/push, where if you have a permissions like
`RWC` or `RW+C` anywhere, a simple `RW` or `RW+` can no longer *create* a new
ref.
You can combine the `C` and `D` also. Thus, the set of permissions you now
know about are, in regex syntax: `R|RW+?C?D?`. See a later section for the
full set of permissions possible.
Some usage hints:
* if you find that `RW+` no longer allows creation/deletion but you can't
see a `C`/`D` permission in the rules, remember that gitolite allows a
repo config to be specified in multiple places for convenience, included
delegated or included files. Be sure to search everywhere :)
* a quick way to make this the default for *all* your repos is:
repo @all
RWCD dummy-branch = foo
where foo can be either the administrator, or if you can ignore the
warning message when you push, a non-existant user.
<a name="_deny_rules"></a>
#### "deny" rules
<a name="_warnings_and_required_reading"></a>
##### warnings and required reading
Gitolite performs access checks at 2 levels. The first check is performed for
both read *and* write operations, while the second one happens only for write
operations.
**Required reading**: [this section][two_l] of the documentation.
[two_l]: http://sitaramc.github.com/gitolite/doc/3-faq-tips-etc.html#_two_levels_of_access_rights_checking
**Warning**: When using deny rules, the order of your rules matters, where
earlier it did not. If you're just starting to add a deny rule to an existing
ruleset, it's a good idea to review the entire ruleset once, to make sure
you're doing it right.
<a name="_deny_rules_for_refs_in_a_repo"></a>
##### "deny" rules for refs in a repo
You can use "deny" rules for the second check, to prevent people pushing
branches or tags that they should not be allowed to.
Take a look at the following snippet, which *seems* to say that "bruce" can
write versioned tags (anything containing `refs/tags/v[0-9]`), but the other
staffers can't:
@staff = bruce whitfield martin
[... and later ...]
RW refs/tags/v[0-9] = bruce
RW refs/tags = @staff
But that's not how the matching works. As long as any refex matches the
refname being updated, it's a "yes". Since the second refex (which says
"anything containing `refs/tags`") is a superset of the first one, it lets
anyone on `@staff` create versioned tags, not just Bruce.
So how do we say "these people can create any tags except tags that look like
this pattern"?
One way to fix this is to allow "deny" rules. We make a small addition to the
permissions syntax, and define a more rigorous, ordered, interpretation.
Let's recap the **existing semantics**:
> The first matching refex that has the permission you're looking for (`W`
> or `+`), results in success. A fallthrough results in failure.
Here are the **new semantics**, with changes from the "main" one in bold:
> The first matching refex that has the permission you're looking for (`W`
> or `+`) **or a minus (`-`)**, results in success **or failure,
> respectively**. A fallthrough **also** results in failure.
So the example we started with becomes, if you use "deny" rules:
RW refs/tags/v[0-9] = bruce
- refs/tags/v[0-9] = @staff
RW refs/tags = @staff
And here's how it works:
* for non-version tags, only the 3rd rule matches, so anyone on staff can
push them
* for version tags by bruce, the first rule matches so he can push them
* for version tags by staffers *other than bruce*, the second rule matches
before the third one, and it has a `-` as the permission, so the push
fails
<a name="_deny_rules_for_the_entire_repo"></a>
##### "deny" rules for the entire repo
The previous section described deny rules for the second check, which is a
fairly common need. However, gitolite does not process deny rules for the
first check -- it's usually simple enough to make sure your config file does
not allow the particular user/repo combindation at all.
But there's one case where this becomes cumbersome: when you want to create
exceptions to uses of `@all`.
For example, if you want gitweb to show `@all` repos except the special
'gitolite-admin' repo, you must manually (and laboriously) maintain a list of
all your repos (except gitolite-admin) and use that in place of `@all`. Oh
joy...
But now you can do this:
repo gitolite-admin
- = gitweb daemon
[... other access rules ...]
config gitolite-options.deny-repo = 1
repo @all
R = gitweb daemon
Here are some notes on how/why this works:
* The order is important -- the deny rule must come first.
* The 'config' line is what tells git to behave differently, i.e., apply
deny rules for the first check also.
* Since there is no "ref" to match against the refexes in the rules,
gitolite just ignores the refexes, and simply looks at the permission (R,
RW, "-", etc) and the user list.
<a name="_summary_permissions"></a>
### summary: permissions
The full set of permissions, in regex syntax: `-|R|RW+?C?D?`. This expands to
one of `-`, `R`, `RW`, `RW+`, `RWC`, `RW+C`, `RWD`, `RW+D`, `RWCD`, or
`RW+CD`. and by now you know what they all mean.
[Side note: There is one more very important permissions to be dealt with --
the standalone `C`, which is not really a "ref" level permission and can be
found in doc/wildcard-repositories.mkd.]
<a name="_virtual_ref_types"></a>
### virtual "ref"-types
This is a highly advanced topic; see [doc/virtualrefs-and-scoring.mkd][vs] for
details.
[vs]: http://sitaramc.github.com/gitolite/doc/virtualrefs-and-scoring.html
<a name="_other_tips"></a>
### other tips
<a name="_personal_branches"></a>
#### personal branches
Gitolite lets you define a "personal" or "scratch" namespace prefix for each
developer (for example, `refs/personal/<devname>/*`); see the "personal
branches" section in `doc/3-faq-tips-etc.mkd` for details.
<a name="_splitting_up_rules_into_rulesets"></a>
#### splitting up rules into rulesets
Gitolite lets you specify access rules for a repo in bits and pieces. This
can be very convenient sometimes. Let's say you have a mix of open source and
closed source projects, and "bosses" should have read access to all projects,
and everyone should have read access to open source projects. Assuming the
appropriate group definitions, this would work:
# all bosses have read access to all projects
repo @open @closed @topsecret
R = @bosses
# everyone has read access to "open" projects
repo @open
R = @bosses @devs @interns
If you notice that `@bosses` are given read access to `@open` via both rules,
don't worry that this causes some duplication or inefficiency. It doesn't :-)
Elsewhere in the file, you would specify access for individual repos (like RW,
RW+, etc). Gitolite combines all of these access rules, maintaining the
textual order in which they occur, when authorising a push.
And although this example used groups, you can use reponames as well, or mix
and match them. You can even distribute rulesets across multiple "include"
files if you wish.
Just remember that if you use [deny rules][dr] anywhere then the *order of the
rules matters*!
[dr]: http://sitaramc.github.com/gitolite/doc/gitolite.conf.html#_deny_rules
This feature also helps people who generate their gitolite.conf itself from
some *other* database -- it allows them much more flexibility in how they
generate rules.
<a name="_gitweb_and_daemon"></a>
#### gitweb and daemon
Gitolite allows you to specify access for git-daemon and gitweb. See
[this][gwd] for more on this.
[gwd]: http://sitaramc.github.com/gitolite/doc/2-admin.html#gwd
<a name="_repo_specific_git_config_commands"></a>
#### repo specific `git config` commands
(Thanks to teemu dot matilainen at iki dot fi)
> ----
> **Note**: this won't work unless the rc file has the right settings;
> please see `$GL_GITCONFIG_KEYS` in [doc/gitolite.rc.mkd][rcdoc] for
> details and security information.
> ----
Sometimes you want to specify `git config` settings for your repos.
For example, say you have a custom post-receive hook that sends an email when
a push happens, and this hook looks in the config for whom to send the email
to, etc.
You can set these git config values within a "repo" paragraph:
repo gitolite
config hooks.mailinglist = gitolite-commits@example.tld
config hooks.emailprefix = "[gitolite] "
config foo.bar = ""
config foo.baz =
The syntax is simple:
config sectionname.keyname = [optional value_string]
This does either a plain "git config section.key value" (for the first 3
examples above) or "git config --unset-all section.key" (for the last
example). Other forms of the `git config` command (`--add`, the
`value_regex`, etc) are not supported.
> ----
> **WARNING**: simply deleting the config line from the `conf/gitolite.conf`
> file will *not* delete the variable from `repo.git/config`. The syntax in
> the last example is the *only* way to make gitolite execute a
> `--unset-all` operation on the given key.
> ----
You can repeat the 'config' line as many times as you like, and the last
occurrence will be the one in effect. This allows you to override settings
just for one project, as in this example:
repo @all
config gitolite.mirror.master = "frodo"
config gitolite.mirror.slaves = "sam gollum"
repo top-secret-project
# only sam, because we don't trust gollum
config gitolite.mirror.slaves = "sam"
The "delete config variable" syntax can also be used, if you wish:
repo highlander # there can be only one!
config gitolite.mirror.master =
config gitolite.mirror.slaves =
As you can see, the general idea is to place the most generic ones (`repo
@all`, or repo patterns like `repo foo.*`) first, and place more specific ones
later to override the generic settings.
[rcdoc]: http://sitaramc.github.com/gitolite/doc/gitolite.rc.html
<a name="_repo_owner_description_line_for_gitweb"></a>
#### repo owner/description line for gitweb
You can include owner/description information in the conf file, and gitolite
will put it in places where gitweb will pick it up. For example, suppose this
software (gitolite) itself was being hosted on a gitolite server and intended
to be shown on gitweb, I'd use a line like this:
gitolite "Sitaram Chamarty" = "fast, secure, access control for git"
The general syntax is very simple, just use one of:
reponame = "some description string in double quotes"
reponame "owner name" = "some description string in double quotes"
Note: setting a description also gives gitweb access; you do not have to give
gitweb access explicitly (as described or linked above) if you're specifying a
description.