Q: all doc stuff
This commit is contained in:
parent
efb29ed135
commit
4f7d3d8651
34
doc/add.mkd
Normal file
34
doc/add.mkd
Normal file
|
@ -0,0 +1,34 @@
|
|||
# adding users and repos
|
||||
|
||||
Do NOT add repos directly on the server. Clone the 'gitolite-admin' repo to
|
||||
your workstation, make changes to it, then add, commit, and push. When the
|
||||
push hits the server, the server "acts" upon your changes.
|
||||
|
||||
Full documentation on the conf file is [here][conf].
|
||||
|
||||
Here's a sample sequence, on your workstation, after your install is done
|
||||
|
||||
git clone git@host:gitolite-admin
|
||||
cd gitolite-admin
|
||||
vi conf/gitolite.conf
|
||||
|
||||
# now add lines like these:
|
||||
repo foo
|
||||
RW+ = me
|
||||
RW = alice
|
||||
R = wally
|
||||
# now save the file and add it
|
||||
git add conf
|
||||
|
||||
# add a couple of users; get their pubkeys by email or something, then:
|
||||
cp /some/where/alice.pub keydir
|
||||
cp /else/where/wally.pub keydir
|
||||
git add keydir
|
||||
|
||||
# now commit and push
|
||||
git commit -m 'added repo foo'
|
||||
git push
|
||||
|
||||
# at this point gitolite will create the new repo 'foo' (if it did not
|
||||
# already exist) then update the authorized keys file to include alice and
|
||||
# wally's pubkeys
|
26
doc/commands.mkd
Normal file
26
doc/commands.mkd
Normal file
|
@ -0,0 +1,26 @@
|
|||
# gitolite "commands"
|
||||
|
||||
Gitolite comes with several commands that users can run. Remote user run the
|
||||
commands by saying:
|
||||
|
||||
ssh git@host command-name [args...]
|
||||
|
||||
while on the server you can run
|
||||
|
||||
gitolite command [args...]
|
||||
|
||||
Very few commands are designed to be run both ways, but it can be done, by
|
||||
checking for the presence of env var `GL_USER`.
|
||||
|
||||
You can get a **list of available commands** by using the `help` command.
|
||||
Naturally, a remote user will see only a subset of what the server user will
|
||||
see.
|
||||
|
||||
You add commands to the "allowed from remote" list by adding its name (or
|
||||
uncommenting it if it's already added but commented out) to the COMMANDS hash
|
||||
in the [rc][] file.
|
||||
|
||||
If you write your own commands, put them in src/commands.
|
||||
|
||||
**Note that this is also the place that all triggered programs go**. In fact,
|
||||
all standalone programs related to gitolite go here.
|
31
doc/conf.mkd
Normal file
31
doc/conf.mkd
Normal file
|
@ -0,0 +1,31 @@
|
|||
# the gitolite.conf file
|
||||
|
||||
This file is the crux of all of gitolite's access control. The basic syntax
|
||||
is very simple.
|
||||
|
||||
Note: `<user>+` means one or more user or user group names, `<repo>+` means
|
||||
one or more repo or repo group names, and `<refex>*` means zero or more
|
||||
refexes.
|
||||
|
||||
* [group][group] definitions (optional, for convenience)
|
||||
|
||||
@<group> = <user>+
|
||||
@<group> = <repo>+
|
||||
|
||||
* [repo][repo] definitions and access [rules][]
|
||||
|
||||
repo <repo>+
|
||||
<perm> <refex>* = <user>+
|
||||
# one or more such lines
|
||||
|
||||
* [gitolite options][options] that apply to the repo(s) in the last
|
||||
"repo ..." line, for example:
|
||||
|
||||
option deny-rules = 1
|
||||
|
||||
* [git config][git-config] keys and values that also apply to the last named
|
||||
repo(s), for example:
|
||||
|
||||
config hooks.emailprefix = '[%GL_REPO] '
|
||||
|
||||
In addition, you can also have [include][] statements.
|
23
doc/cust.mkd
Normal file
23
doc/cust.mkd
Normal file
|
@ -0,0 +1,23 @@
|
|||
# customising gitolite
|
||||
|
||||
Here are the ways you can customise gitolite on the server.
|
||||
|
||||
First, learn about:
|
||||
|
||||
* [git hooks][hooks] and [virtual refs][vref]
|
||||
|
||||
* [commands][] for your [users][] to run own][dev-notes]
|
||||
|
||||
* [triggers][] to be run by gitolite as various points in its execution
|
||||
|
||||
* [syntactic sugar][sugar] to change the conf language for your convenience
|
||||
|
||||
For all of the above:
|
||||
|
||||
* [edit the rc file][rc] to enable optional features that are shipped in a
|
||||
disabled state
|
||||
|
||||
* [write your own][dev-notes]
|
||||
|
||||
(Note: "trigger" is the same concept as "hook", applied to gitolite; I just
|
||||
chose a different name to avoid constant ambiguity in documentation).
|
116
doc/dev-notes.mkd
Normal file
116
doc/dev-notes.mkd
Normal file
|
@ -0,0 +1,116 @@
|
|||
# notes for developers
|
||||
|
||||
Gitolite has a huge bunch of existing features that gradually need to moved
|
||||
over. Plus you may want to write your own programs to interact with it.
|
||||
|
||||
Hints for developers wishing to help migrate features over from g2 are
|
||||
[here][dev-hints].
|
||||
|
||||
Here are some random notes on developing hooks, commands, triggers, and sugar
|
||||
scripts.
|
||||
|
||||
## environment variables
|
||||
|
||||
In general, the following environment variables should always be available:
|
||||
|
||||
GL_BINDIR
|
||||
GL_REPO_BASE
|
||||
GL_ADMIN_BASE
|
||||
|
||||
Commands invoked by a remote client will also have `GL_USER` set. Hooks will
|
||||
have `GL_REPO` also set.
|
||||
|
||||
## APIs
|
||||
|
||||
### the shell API
|
||||
|
||||
The following commands exist to help you write shell scripts that interact
|
||||
easily with gitolite. Each of them responds to `h` so please run that for
|
||||
more info.
|
||||
|
||||
* `gitolite access` to check access rights given repo, user, type of access
|
||||
(R, W, ...) and refname (optional). Example use: src/commands/desc
|
||||
|
||||
* `gitolite creator` to get/check the creator of a repo. Example use:
|
||||
src/commands/desc
|
||||
|
||||
* `gitolite git-config` to check gitolite options or git config variables
|
||||
directly from gitolite's "compiled output, (i.e., without looking at the
|
||||
actual `repo.git/config` file or using the `git config` command). Example
|
||||
use: none yet
|
||||
|
||||
* `gitolite query-rc` to check the value of an RC variable. Example use:
|
||||
src/commands/desc.
|
||||
|
||||
In addition, you can also look at the comments in src/Gitolite/Easy.pm (the
|
||||
perl API module) for ideas.
|
||||
|
||||
### the perl API
|
||||
|
||||
...is implemented by Gitolite::Easy; see src/Gitolite/Easy.pm. This is a work
|
||||
in progress; for example it does not yet have the equivalent of `gitolite
|
||||
git-config`. I'll add it when I or someone else needs it.
|
||||
|
||||
## your own hooks
|
||||
|
||||
### anything but the update hook
|
||||
|
||||
If you want to add your own hook, it's easy as long as it's not the 'update'
|
||||
hook. Just add it to `$HOME/.gitolite/hooks/common` and run `gitolite setup`.
|
||||
|
||||
The rest is between you and 'man githooks' :-)
|
||||
|
||||
### update hook
|
||||
|
||||
If you want to add additional `update` hook functionality, do this:
|
||||
|
||||
* write and test your update hook separately from gitolite
|
||||
|
||||
* now add the code to src/VREF. Let's say it is called "foo".
|
||||
|
||||
* to call your new update hook to all accesses for all repos, add this to
|
||||
the end of your conf file:
|
||||
|
||||
repo @all
|
||||
- VREF/foo = @all
|
||||
|
||||
As you probably guessed, you can now make your additional update hooks more
|
||||
selective, applying them only to some repos / users / combinations.
|
||||
|
||||
Note: a normal update hook expects 3 arguments (ref, old SHA, new SHA). A
|
||||
VREF will get those three, followed by at least 4 more. Your VREF should just
|
||||
ignore the extra args.
|
||||
|
||||
## your own commands
|
||||
|
||||
You can add your own commands. You can run them on the server (example,
|
||||
`gitolite access`). Then you can enable certain commands to be allowed to run
|
||||
by a remote user by adding them to the "COMMANDS" hash of the [rc][] file.
|
||||
|
||||
Commands are standalone programs, in any language you like. They simply
|
||||
receive the arguments you append. In addition, the env var `GL_USER` is
|
||||
available if it is being run remotely. src/commands/desc is the best example
|
||||
at present.
|
||||
|
||||
## your own trigger programs
|
||||
|
||||
Trigger programs are just commands whose names have been added to the
|
||||
appropriate list in the [rc][] file. Triggers get specific arguments
|
||||
depending on when they are called; see [here][triggers] for details.
|
||||
|
||||
You can write programs that are both manually runnable as well as callable by
|
||||
trigger events, especially if they don't *need* any arguments.
|
||||
|
||||
Look in the distributed [rc][] file for example programs; at this point there
|
||||
aren't many.
|
||||
|
||||
## your own "sugar"
|
||||
|
||||
Syntactic sugar helpers are NOT complete, standalone, programs. They must
|
||||
include a perl sub called `sugar_script` that takes in a listref, and returns
|
||||
a listref. The listrefs point to a list that contains the entire conf file
|
||||
(with all [include][] processing already done). You create a new list with
|
||||
contents modified as you like and return a ref to it.
|
||||
|
||||
There are a couple of examples in src/syntactic-sugar.
|
||||
|
35
doc/dev-status.mkd
Normal file
35
doc/dev-status.mkd
Normal file
|
@ -0,0 +1,35 @@
|
|||
## #dev-status g3 development status
|
||||
|
||||
Not yet done (will be tackled in this order unless someone asks):
|
||||
|
||||
* detailed documentation for new features
|
||||
* querying the outside world for group info (see gl-get-membership-program
|
||||
in g2)
|
||||
* mirroring
|
||||
* pulling in documentation for things that are the same in g2
|
||||
* "unrestricted arguments" for some ADCs (like git-annexe)
|
||||
* smart http
|
||||
* special features (no-create-repos, shell-access, gl-all-read-all, etc)
|
||||
|
||||
Help needed:
|
||||
|
||||
* I'd like distro packagers to play with it and help with migration advice
|
||||
for distro-upgrades
|
||||
* [rsync][pw2], htpasswd
|
||||
* git-annexe support (but this has a pre-requisite in the previous list)
|
||||
|
||||
Won't be done unless someone asks (saw no evidence that anyone used them in g2
|
||||
anyway!):
|
||||
|
||||
* mob branches
|
||||
* password access
|
||||
* specific ADCs -- there are too many for me to bother without applying
|
||||
Pareto somewhere, so I choose to not do any and wait for people to ask :-)
|
||||
|
||||
Done:
|
||||
|
||||
* core code
|
||||
* test suite
|
||||
* some documentation
|
||||
* distro packaging instructions
|
||||
* migration advice for common cases
|
89
doc/extras/auth.mkd
Normal file
89
doc/extras/auth.mkd
Normal file
|
@ -0,0 +1,89 @@
|
|||
# authentication versus authorisation
|
||||
|
||||
This document will explain why an "ssh issue" is almost never a "gitolite
|
||||
issue", and, indirectly, why I dont get too excited about the former.
|
||||
|
||||
Note: for actual ssh troubleshooting see [this][ssh-troubleshooting].
|
||||
|
||||
Here is a fundamental point: <font color="red">**Gitolite does not do
|
||||
authentication. It only does authorisation**.</font>
|
||||
|
||||
So first, let's loosely define these words:
|
||||
|
||||
> **Authentication** is the process of verifying that you are who you claim
|
||||
> to be. An authentication system will establish that I am the user
|
||||
> "sitaram" on my work system. The one behind gmail will similarly
|
||||
> establish that I am "sitaramc". And so on...
|
||||
|
||||
> **Authorisation** is the process of asking what you want to do and
|
||||
> deciding if you're allowed to do it or not.
|
||||
|
||||
Now, if you managed to read about [gitolite and ssh][gitolite-and-ssh], you
|
||||
know that gitolite is meant to be invoked as:
|
||||
|
||||
/full/path/to/gl-auth-command some-authenticated-gitolite-username
|
||||
|
||||
(where the "gitolite username" is a "virtual" username; it does not have to
|
||||
be, and usually *isn't*, an actual *unix* username).
|
||||
|
||||
As you can see, authentication happens before gitolite is called.
|
||||
|
||||
## but... but... you have all that ssh stuff in there!
|
||||
|
||||
The default mode of using gitolite does use ssh keys, but all it's doing is
|
||||
helping you **setup** ssh-based authentication **as a convenience to you**.
|
||||
|
||||
You don't have to use it, though. And many people don't. The examples I know
|
||||
are [smart http][http], and ldap-backed sshd. In both cases, gitolite has no
|
||||
role to play in creating users, setting up their passwords/keys, etc. There's
|
||||
even a `GL_NO_SETUP_AUTHKEYS` option to make sure gitolite doesn't meddle with
|
||||
the authkeys file in such installations.
|
||||
|
||||
## so you're basically saying you won't support "X"
|
||||
|
||||
(where "X" is some ssh related behaviour change or feature)
|
||||
|
||||
Well, if it's not a security issue I *probably* won't. I'm willing to change
|
||||
my mind if enough people convince me they need it. (There's a mailing list if
|
||||
you want to find others who also need the same thing.)
|
||||
|
||||
While we're on the subject, locking someone out is *not* a security issue.
|
||||
Even if you locked yourself (the admin) out, the docs tell you how to recover
|
||||
from such errors. You do need some password based method to get a shell
|
||||
command line on the server, of course.
|
||||
|
||||
## appendix: how to use other authentication systems with gitolite
|
||||
|
||||
The bottom line in terms of how to invoke gitolite has been described above,
|
||||
and as long as you manage to do that gitolite won't even know how the
|
||||
authentication was done. Which in turn means you can use whatever
|
||||
authentication scheme you want.
|
||||
|
||||
It also expects the `SSH_ORIGINAL_COMMAND` environment variable to contain the
|
||||
full command (typically starting with git-receive-pack or git-upload-pack)
|
||||
that the client sent. Also, when using [smart http][http], things are somewhat
|
||||
different: gitolite uses certain environment variables that it expects httpd
|
||||
to have set up. Even the user name comes from the `REMOTE_USER` environment
|
||||
variable instead of as a command line argument in this case.
|
||||
|
||||
However, it has to be an authentication system that is compatible with sshd or
|
||||
httpd in some form. Why? Because the git *client* accessing the server only
|
||||
knows those 2 protocols to "speak git". (Well, the `git://` protocol is
|
||||
unauthenticated, and `file://` doesn't really apply to this discussion, so
|
||||
we're ignoring those).
|
||||
|
||||
For example, let's say you have an LDAP-based authentication system somewhere.
|
||||
It is possible to make apache use that to authenticate users, so when a user
|
||||
accesses a git url using `http://sitaram:password@git.example.com/repo`, it is
|
||||
LDAP that does the actual authentication. [I wouldn't know how to do it but I
|
||||
know it is possible. Patches to this doc explaining how are welcome!]
|
||||
|
||||
There are also ssh daemons that use LDAP to store the authorised keys (instead
|
||||
of putting them all in `~/.ssh/authorized_keys`). The clients will still need
|
||||
to generate keypairs and send them to the admin, but they can be more
|
||||
centrally stored and perhaps used by other programs or tools simultaneously,
|
||||
which can be useful.
|
||||
|
||||
Finally, gitolite allows you to store *group* information externally too. See
|
||||
[here][ldap] for more on this.
|
||||
|
145
doc/extras/gitolite-and-ssh.mkd
Normal file
145
doc/extras/gitolite-and-ssh.mkd
Normal file
|
@ -0,0 +1,145 @@
|
|||
## #glssh how gitolite uses ssh
|
||||
|
||||
Although other forms of authentications exist (see the document on
|
||||
[authentication versus authorisation][auth]), ssh is the one that most git
|
||||
users use.
|
||||
|
||||
***Therefore, gitolite is (usually) heavily dependent on ssh***.
|
||||
|
||||
Most people didn't realise this, and even if they did they don't know ssh
|
||||
well enough to help themselves. If you don't understand how ssh public key
|
||||
authentication works, or how the `~/.ssh/authorized_keys` file can be used to
|
||||
restrict users, etc., you will have endless amounts of trouble getting
|
||||
gitolite to work, because you'll be attacking the wrong problem.
|
||||
|
||||
So please please please understand this before tearing your hair out and
|
||||
blaming ***git/gitolite*** for whatever is going wrong with your setup :-)
|
||||
|
||||
### ssh basics
|
||||
|
||||
Let's start with some basics, focusing *only* on the pieces relevant to
|
||||
`gitolite`. If this is not detailed enough, please use google and learn more
|
||||
from somewhere, or maybe buy the OReilly ssh book.
|
||||
|
||||
* You can login to an ssh server by typing a password, but ssh can also use
|
||||
***public-private keys*** (also called "key pairs") for authentication.
|
||||
`gitolite` *requires* you to use this mechanism for your users -- they
|
||||
cannot log in using passwords. Hopefully by the time you finish reading
|
||||
this document you will understand why :-)
|
||||
|
||||
The way you set this up is you generate a key pair on your workstation,
|
||||
and give the server the public key. (I need not add that the "private"
|
||||
key must be, well, kept *private*!)
|
||||
|
||||
* **generating a key pair on your workstation** is done by running the
|
||||
command `ssh-keygen -t rsa`. This produces two files in `~/.ssh`. One is
|
||||
`id_rsa`; this is the **private** key -- ***never*** let it out of your
|
||||
machine. The other is `id_rsa.pub`, which is the corresponding public
|
||||
key. This public key is usually just one long line of text.
|
||||
|
||||
* on Windows machines with msysgit installed, you should do this from
|
||||
within a "git bash" window. The command will report the full path where
|
||||
the files have been written; make a note of this, and use those files in
|
||||
any of the description that follows
|
||||
|
||||
* **adding your public key to the server**'s `~/.ssh/authorized_keys`
|
||||
file is how ssh uses pubkeys to authenticate users. Let's say
|
||||
sita@work.station is trying to log in as git@serv.er. What you have to do
|
||||
is take the `~/.ssh/id_rsa.pub` file for user sita on work.station and
|
||||
append its contents (remember it's only one line) to
|
||||
`~/.ssh/authorized_keys` for user git on serv.er.
|
||||
|
||||
The `authorized_keys` file can have multiple public keys (from many
|
||||
different people) added to it so any of them can log in to git@serv.er.
|
||||
|
||||
In the normal case (not gitolite, but your normal everyday shell access),
|
||||
there's a command that does this, `ssh-copy-id`, which also fixes up
|
||||
permissions etc., as needed, since sshd is a little picky about allowing
|
||||
pubkey access if permissions on the server are loose. Or you can do it
|
||||
manually, as long as you know what you're doing and you're careful not to
|
||||
erase or overwrite the existing contents of `~/.ssh/authorized_keys` on
|
||||
the server!
|
||||
|
||||
But in the gitolite case, it's different; we'll get to that in a minute.
|
||||
|
||||
* **troubleshooting pubkey authentication failures**: if you are unable to
|
||||
get ssh access to the server after doing all this, you'll have to look
|
||||
in `/var/log/secure` or `/var/log/auth.log` or some such file on the
|
||||
server to see what specific error `sshd` is complaining about.
|
||||
|
||||
* **restricting users to specific commands** is very important for gitolite.
|
||||
If you read `man sshd` and look for `authorized_keys file format`, you'll
|
||||
see a lot of options you can add to the public key line, which restrict
|
||||
the incoming user in various ways. In particular, note the `command=`
|
||||
option, which means "regardless of what the incoming user is asking to do,
|
||||
forcibly run this command instead".
|
||||
|
||||
Also note that when there are many public keys (i.e., lines) in the
|
||||
`authorized_keys` file, each line can have a *different* set of options
|
||||
and `command=` values.
|
||||
|
||||
Without this `command=` option, the ssh daemon will simply give you a
|
||||
shell, which is not what we want for our gitolite keys (although we may
|
||||
well have other keys which we use to get a shell).
|
||||
|
||||
**This is the backbone of what makes gitolite work; please make sure you
|
||||
understand this**.
|
||||
|
||||
### how does gitolite use all this ssh magic?
|
||||
|
||||
These are two different questions you ought to be having by now:
|
||||
|
||||
* how does it distinguish between me and someone else, since we're all
|
||||
logging in as the same remote user "git"
|
||||
* how does it restrict what I can do within a repository
|
||||
|
||||
#### restricting shell access/distinguishing one user from another
|
||||
|
||||
The answer to the first question is the `command=` we talked about before. If
|
||||
you look in the `authorized_keys` file, you'll see entries like this (I chopped
|
||||
off the ends of course; they're pretty long lines):
|
||||
|
||||
command="[path]/gl-auth-command sitaram",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA18S2t...
|
||||
command="[path]/gl-auth-command usertwo",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArXtCT...
|
||||
|
||||
First, it finds out which of the public keys in this file match the incoming
|
||||
login. That's crypto stuff, and I won't go into it. Once the match has been
|
||||
found, it will run the command given on that line; e.g., if I logged in, it
|
||||
would run `[path]/gl-auth-command sitaram`. So the first thing to note is
|
||||
that such users do not get "shell access", which is good!
|
||||
|
||||
Before running the command, however, sshd sets up an environment variable
|
||||
called `SSH_ORIGINAL_COMMAND` which contains the actual git command that your
|
||||
workstation sent out. This is the command that *would have run* if you did
|
||||
not have the `command=` part in the authorised keys file.
|
||||
|
||||
When `gl-auth-command` gets control, it looks at the first argument
|
||||
("sitaram", "usertwo", etc) to determine who you are. It then looks at the
|
||||
`SSH_ORIGINAL_COMMAND` variable to find out which repository you want to
|
||||
access, and whether you're reading or writing.
|
||||
|
||||
Now that it has a user, repository, and access requested (read/write), gitolite looks
|
||||
at its config file, and either allows or rejects the request.
|
||||
|
||||
But this cannot differentiate between different branches within a repo; that
|
||||
has to be done separately.
|
||||
|
||||
#### restricting branch level actions
|
||||
|
||||
[If you look inside the git source tree, there's a file among the "howto"s in
|
||||
there called `update-hook-example.txt`, which was the inspiration for this
|
||||
part of gitolite.]
|
||||
|
||||
Git allows you to specify many "hooks", which get control as various events
|
||||
happen -- see `git help hooks` for details. One of those hooks is the
|
||||
`update` hook, which, if it is present, is invoked just before a branch or a
|
||||
tag is about to be updated. The hook is passed the name of the branch or tag,
|
||||
the old SHA1 value, and the new SHA1 value, as arguments. Hooks that are
|
||||
called *before* an action happens are allowed to prevent that action from
|
||||
happening by returning an error code.
|
||||
|
||||
When gitolite is told to create a new repository (by the admin), it installs
|
||||
a special update hook. This hook takes all the information presented, looks
|
||||
at the config file, and decides to allow or reject the update.
|
||||
|
||||
And that's basically it.
|
64
doc/extras/nagp.mkd
Normal file
64
doc/extras/nagp.mkd
Normal file
|
@ -0,0 +1,64 @@
|
|||
# not a gitolite problem
|
||||
|
||||
These are issues I do not want to be emailed about. That does not mean you
|
||||
cannot get help -- in all cases, you're welcome to ask on [irc or the mailing
|
||||
list][contact]. Irc especially has people with much more patience than I
|
||||
have, God bless them...
|
||||
|
||||
## specific clients, or specific server OSs
|
||||
|
||||
These are things I can not support. That does not mean they will not work
|
||||
with gitolite -- on the contrary, lots of people are using them.
|
||||
|
||||
But I personally don't use them, and I won't use them, and in my admittedly
|
||||
limited experience they have given me good reason to stay well away.
|
||||
|
||||
Please ask for help on the [mailing list or IRC][contact]. Please do not
|
||||
email me directly.
|
||||
|
||||
* putty/plink
|
||||
* jgit/Eclipse
|
||||
* Mac OS client or server
|
||||
* windows as a server
|
||||
* ...probably some more I forgot; will update this list as I remember...
|
||||
|
||||
## ssh
|
||||
|
||||
The *superstar* of the "not a gitolite problem" category is actually ssh.
|
||||
|
||||
Surprised? It is so common that it has [its own document][auth] to tell
|
||||
you why it is *not* a gitolite problem, while [another one][ssh] tries to
|
||||
help you anyway!
|
||||
|
||||
Everything I know is in that latter link. Please email me about ssh ONLY if
|
||||
you find something wrong or missing in those documents.
|
||||
|
||||
## git
|
||||
|
||||
Example 1: when a first `git push` to a new repo fails, it is not because of
|
||||
gitolite, it is because you need to say `git push origin master` or something.
|
||||
This is a git issue.
|
||||
|
||||
There are several such examples. Gitolite is designed to look like just
|
||||
another bare repo server to a client (except requiring public keys -- no
|
||||
passwords allowed). It is *completely transparent* when there is no
|
||||
authorisation failure (i.e., when the access is allowed, the remote client has
|
||||
no way of knowing gitolite was even installed!)
|
||||
|
||||
Even "on disk", apart from reserving the `update` hook for itself, gitolite
|
||||
does nothing to your bare repos unless you tell it to (for example, adding
|
||||
'gitweb.owner' and such to the config file).
|
||||
|
||||
BEFORE you think gitolite is a problem, try the same thing with a normal bare
|
||||
repo. In most cases you can play with it just by doing something like this:
|
||||
|
||||
mkdir /tmp/throwaway
|
||||
cd /tmp/throwaway
|
||||
git clone --mirror <some repo you have a URL for> bare.git
|
||||
git clone bare.git worktree
|
||||
cd worktree
|
||||
<...try stuff>
|
||||
|
||||
----
|
||||
|
||||
In addition, the original nagp has more funny stuff...
|
34
doc/extras/regex.mkd
Normal file
34
doc/extras/regex.mkd
Normal file
|
@ -0,0 +1,34 @@
|
|||
# extremely brief regex overview
|
||||
|
||||
Regexes are powerful. Gitolite uses that power as much as it can. If you
|
||||
can't handle that power, hire someone who can and become a manager.
|
||||
|
||||
That said, here's a very quick overview of the highlights.
|
||||
|
||||
`^` and `$` are called "anchors". They anchor the match to the beginning and
|
||||
end of the string respectively.
|
||||
|
||||
^foo matches any string starting with 'foo'
|
||||
foo$ matches any string ending with 'foo'
|
||||
^foo$ matches exact string 'foo'.
|
||||
|
||||
To be precise, the last one is "any string starting and ending with *the same*
|
||||
'foo'". "foofoo" does not match.
|
||||
|
||||
`[0-9]` is an example of a character class; it matches any single digit.
|
||||
`[a-z]` matches any lower case alpha, and `[0-9a-f]` is the range of hex
|
||||
characters. You should now guess what `[a-zA-Z0-9_]` does.
|
||||
|
||||
`.` (the period) is special -- it matches any character. If you want to match
|
||||
an actual period, you need to say `\.`.
|
||||
|
||||
`*`, `?`, and `+` are quantifiers. They apply to the previous token. `a*`
|
||||
means "zero or more 'a' characters". Similarly `a+` means "one or more", and
|
||||
`a?` means "zero or one".
|
||||
|
||||
As a result, `.*` means "any number (including zero) of any character".
|
||||
|
||||
The previous token need not be a single character; you can use parens to make
|
||||
it longer. `(foo)+` matches one or more "foo", (like "foo", "foofoo",
|
||||
"foofoofoo", etc.)
|
||||
|
427
doc/extras/ssh-troubleshooting.mkd
Normal file
427
doc/extras/ssh-troubleshooting.mkd
Normal file
|
@ -0,0 +1,427 @@
|
|||
## #sshts ssh troubleshooting
|
||||
|
||||
**This document must be read in full the first time. If you start from some
|
||||
nice looking section in the middle it may not help you unless you're already
|
||||
an expert at ssh**.
|
||||
|
||||
This document should help you troubleshoot ssh-related problems in installing
|
||||
and accessing gitolite.
|
||||
|
||||
### IMPORTANT -- READ THIS FIRST
|
||||
|
||||
#### caveats
|
||||
|
||||
* Before reading this document, it is **mandatory** to read and **completely
|
||||
understand** [this][ssh], which is a very detailed look at how gitolite
|
||||
uses ssh's features on the server side. Don't assume you know all that;
|
||||
if you knew it, you wouldn't be needing *this* document either!
|
||||
|
||||
* This document, and others linked from this, together comprise all the help
|
||||
I can give you in terms of the ssh aspect of using gitolite. If you're
|
||||
installing gitolite, you're a "system admin", like it or not. Ssh is
|
||||
therefore a necessary skill. Please take the time to learn at least
|
||||
enough to get passwordless access working.
|
||||
|
||||
* Please note that authentication is not really gitolite's job at all. I'd
|
||||
rather spend time on actual gitolite features, code, and documentation
|
||||
than authentication (i.e., ssh, in the common case).
|
||||
|
||||
Surprised? [This][auth] might help explain better.
|
||||
|
||||
#### naming conventions used
|
||||
|
||||
* Your workstation is the **client**. Your userid on the client does not
|
||||
matter, and it has no relation to your gitolite username.
|
||||
|
||||
* the server is called **server** and the "hosting user" is **git**. If
|
||||
this is an RPM/DEB install, the hosting user is probably called
|
||||
"gitolite", however we will use "git" in this document.
|
||||
|
||||
#### taking stock -- relevant files and directories
|
||||
|
||||
* the client has a `~/.ssh` containing a few keypairs. It may also have a
|
||||
`config` file.
|
||||
|
||||
* the client also has a clone of the "gitolite-admin" repo, which contains a
|
||||
bunch of `*.pub` files in `keydir`. We assume this clone is in `$HOME`;
|
||||
if it is not, adjust instructions accordingly when needed.
|
||||
|
||||
* The git user on the server has a `~/.ssh/authorized_keys` file that the
|
||||
ssh daemon uses to authenticate incoming users. We often call this file
|
||||
**authkeys** to save typing, and it always means the one on the server
|
||||
(we're not interested in this file on the client side).
|
||||
|
||||
* the server also has a `~/.gitolite/keydir` which contains a bunch of
|
||||
`*.pub` files.
|
||||
|
||||
#### normal gitolite key handling
|
||||
|
||||
Here's how normal gitolite key handling works:
|
||||
|
||||
* (on client) pub key changes like adding new ones, deleting old ones, etc.,
|
||||
are done in the `keydir` directory in the gitolite-admin repo clone. Then
|
||||
the admin `git add`s and `git commit`s those changes, then `git push`es
|
||||
them to the server.
|
||||
|
||||
* (on server) a successful push from the client makes git invoke the
|
||||
post-update hook in the gitolite-admin repo. This hook is installed by
|
||||
gitolite, and it does a bunch of things which are quite transparent to
|
||||
the admin, but we'll describe briefly here:
|
||||
|
||||
* the pubkey files from this push are checked-out into
|
||||
`~/.gitolite/keydir` (and similarly the config files into
|
||||
`~/.gitolite/conf`)
|
||||
|
||||
* the "compile" script then runs, which uses these files to populate
|
||||
`~/.ssh/authorized_keys` on the server
|
||||
|
||||
The authkeys file may have other, (non-gitolite) keys also. Those
|
||||
lines are preserved. Gitolite only touches lines that are found
|
||||
between gitolite's "marker" lines (`# gitolite start` and `# gitolite
|
||||
end`).
|
||||
|
||||
### (Other resources)
|
||||
|
||||
People who think installing gitolite is too hard should take a look at this
|
||||
[tutorial][tut] to **see how simple it *actually* is**.
|
||||
|
||||
### common ssh problems
|
||||
|
||||
Since I'm pretty sure at least some of you didn't bother to read the
|
||||
"IMPORTANT: PLEASE READ FIRST" section above, let me take a minute to point
|
||||
you there again. Especially the first bullet.
|
||||
|
||||
Done? OK, read on...
|
||||
|
||||
The following problem(s) indicate that pubkey access is not working at all, so
|
||||
you should start with [appendix 1][stsapp1_]. If that doesn't fix the problem, continue
|
||||
with the other appendices in sequence.
|
||||
|
||||
* running any git clone/fetch/ls-remote or just `ssh git@server info` asks
|
||||
you for a password.
|
||||
|
||||
The following problem(s) indicate that your pubkey is bypassing gitolite and
|
||||
going straight to a shell. You should start with [appendix 2][stsapp2_] and continue with
|
||||
the rest in sequence. [Appendix 5][stsapp5_] has some background info.
|
||||
|
||||
* running `ssh git@server info` gets you the output of the GNU 'info'
|
||||
command instead of gitolite's version and access info.
|
||||
|
||||
* running `git clone git@server:repositories/reponame` (note presence of
|
||||
`repositories/` in URL) works.
|
||||
|
||||
[A proper gitolite key will only let you `git clone git@server:reponame`
|
||||
(note absence of `repositories/`)]
|
||||
|
||||
* you are able to clone repositories but are unable to push changes back
|
||||
(the error complains about the `GL_RC` environment variable not being set,
|
||||
and the `hooks/update` failing in some way).
|
||||
|
||||
[If you run `git remote -v` you will find that your clone URL included the
|
||||
`repositories/` described above!]
|
||||
|
||||
* conversely, using the correct syntax, `git clone git@server:reponame`
|
||||
(note absence of `repositories/` in the URL), gets you `fatal: 'reponame'
|
||||
does not appear to be a git repository`, and yet you are sure 'reponame'
|
||||
exists, you haven't mis-spelled it, etc.
|
||||
|
||||
### step by step
|
||||
|
||||
Since I'm pretty sure at least some of you didn't bother to read the
|
||||
"IMPORTANT: PLEASE READ FIRST" section above, let me take a minute to point
|
||||
you there again. Especially the first bullet.
|
||||
|
||||
Done? OK, now the general outline for ssh troubleshooting is this:
|
||||
|
||||
* make sure the server's overall setup even *allows* pubkey based login.
|
||||
I.e., check that git fetch/clone/ls-remote commands or a plain `ssh
|
||||
git@server info` do NOT ask for a password. If you do get asked for a
|
||||
password, see [appendix 1][stsapp1_].
|
||||
|
||||
* match client-side pubkeys (`~/.ssh/*.pub`) with the server's authkeys
|
||||
file. To do this, run `sshkeys-lint`, which tells you in detail what key
|
||||
has what access. See [appendix 2][stsapp2_].
|
||||
|
||||
* at this point, we know that we have the right key, and that if sshd
|
||||
receives that key, things will work. But we're not done yet. We still
|
||||
need to make sure that this specific key is being offered/sent by the
|
||||
client, instead of the default key. See [appendix 3][stsapp3_] and [appendix 4][sshhostaliases].
|
||||
|
||||
### random tips, tricks, and notes
|
||||
|
||||
#### giving shell access to gitolite users
|
||||
|
||||
We've managed (thanks to an idea from Jesse Keating) to make it possible for a
|
||||
single key to allow both gitolite access *and* shell access.
|
||||
|
||||
This is done by copying the pubkey (to which you want to give shell access) to
|
||||
the server and running
|
||||
|
||||
gl-tool add-shell-user ~/foo.pub
|
||||
|
||||
**IMPORTANT UPGRADE NOTE**: previous implementations of this feature were
|
||||
crap. There was no easy/elegant way to ensure that someone who had repo admin
|
||||
access would not manage to get himself shell access.
|
||||
|
||||
Giving someone shell access requires that you should have shell access in the
|
||||
first place, so the simplest way is to enable it from the server side only.
|
||||
|
||||
#### losing your admin key
|
||||
|
||||
If you lost the admin key, and need to re-establish ownership of the
|
||||
gitolite-admin repository with a fresh key, get a shell on the server and use
|
||||
the program called `gl-admin-push` that comes with gitolite. See instructions
|
||||
[here][adminpush].
|
||||
|
||||
#### simulating ssh-copy-id
|
||||
|
||||
don't have `ssh-copy-id`? This is broadly what that command does, if you want
|
||||
to replicate it manually. The input is your pubkey, typically
|
||||
`~/.ssh/id_rsa.pub` from your client/workstation.
|
||||
|
||||
* it copies it to the server as some file
|
||||
|
||||
* it appends that file to `~/.ssh/authorized_keys` on the server
|
||||
(creating it if it doesn't already exist)
|
||||
|
||||
* it then makes sure that all these files/directories have go-w perms
|
||||
set (assuming user is "git"):
|
||||
|
||||
/home/git/.ssh/authorized_keys
|
||||
/home/git/.ssh
|
||||
/home/git
|
||||
|
||||
[Actually, `sshd` requires that even directories *above* `~` (`/`, `/home`,
|
||||
typically) also must be `go-w`, but that needs root. And typically
|
||||
they're already set that way anyway. (Or if they're not, you've got
|
||||
bigger problems than gitolite install not working!)]
|
||||
|
||||
#### problems with using non-openssh public keys
|
||||
|
||||
Gitolite accepts public keys only in openssh format. Trying to use an "ssh2"
|
||||
key (used by proprietary SSH software) results in:
|
||||
|
||||
WARNING: a pubkey file can only have one line (key); ignoring YourName.pub
|
||||
|
||||
To convert ssh2-compatible keys to openssh run:
|
||||
|
||||
ssh-keygen -i -f /tmp/ssh2/YourName.pub > /tmp/openssh/YourName.pub
|
||||
|
||||
then use the resulting pubkey as you normally would in gitolite.
|
||||
|
||||
#### windows issues
|
||||
|
||||
On windows, I have only used msysgit, and the openssh that comes with it.
|
||||
Over time, I have grown to distrust putty/plink due to the number of people
|
||||
who seem to have trouble when those beasts are involved (I myself have never
|
||||
used them for any kind of git access). If you have unusual ssh problems that
|
||||
just don't seem to have any explanation, try removing all traces of
|
||||
putty/plink, including environment variables, etc., and then try again.
|
||||
|
||||
Thankfully, someone contributed [contrib/putty.mkd][contrib_putty].
|
||||
|
||||
### #stsapp1_ appendix 1: ssh daemon asks for a password
|
||||
|
||||
> **NOTE**: This section should be useful to anyone trying to get
|
||||
> password-less access working. It is not necessarily specific to gitolite,
|
||||
> so keep that in mind if the wording feels a little more general than you
|
||||
> were expecting.
|
||||
|
||||
You have generated a keypair on your workstation (`ssh-keygen`) and copied the
|
||||
public part of it (`~/.ssh/id_rsa.pub`, by default) to the server.
|
||||
|
||||
On the server you have appended this file to `~/.ssh/authorized_keys`. Or you
|
||||
ran something, like the `gl-setup` step during a gitolite install, which
|
||||
should have done that for you.
|
||||
|
||||
You now expect to log in without having to type in a password, but when you
|
||||
try, you are being asked for a password.
|
||||
|
||||
This is a quick checklist:
|
||||
|
||||
* make sure you're being asked for a password and not a pass*phrase*. Do
|
||||
not confuse or mistake a prompt saying `Enter passphrase for key
|
||||
'/home/sitaram/.ssh/id_rsa':` for a password prompt from the remote
|
||||
server!
|
||||
|
||||
When you create an ssh keypair using `ssh-keygen`, you have the option of
|
||||
protecting it with a passphrase. When you subsequently use that keypair
|
||||
to access a remote host, your *local* ssh client needs to unlock the
|
||||
corresponding private key, and ssh will probably ask for the passphrase
|
||||
you set when you created the keypair.
|
||||
|
||||
You have two choices to avoid this prompt every time you try to use the
|
||||
private key. The first is to create keypairs *without* a passphrase (just
|
||||
hit enter when prompted for one). **Be sure to add a passphrase later,
|
||||
once everything is working, using `ssh-keygen -p`**.
|
||||
|
||||
The second is to use `ssh-agent` (or `keychain`, which in turn uses
|
||||
`ssh-agent`) or something like that to manage your keys. Other than
|
||||
discussing one more potential trouble-spot with ssh-agent (see below),
|
||||
further discussion of ssh-agent/keychain is out of scope of this document.
|
||||
|
||||
* ssh is very sensitive to permissions. An extremely conservative setup is
|
||||
given below, but be sure to do this on **both the client and the server**:
|
||||
|
||||
cd $HOME
|
||||
chmod go-rwx .
|
||||
chmod -R go-rwx .ssh
|
||||
|
||||
* actually, every component of the path to `~/.ssh/authorized_keys` all the
|
||||
way upto the root directory must be at least `chmod go-w`. So be sure to
|
||||
check `/` and `/home` also.
|
||||
|
||||
* while you're doing this, make sure the owner and group info for each of
|
||||
these components are correct. `ls -ald ~ ~/.ssh ~/.ssh/authorized_keys`
|
||||
will tell you what they are.
|
||||
|
||||
* you may also want to check `/etc/ssh/sshd_config` to see if the "git" user
|
||||
is allowed to login at all. For example, if that file contains an
|
||||
`AllowUsers` config entry, then only users mentioned in that line are
|
||||
allowed to log in!
|
||||
|
||||
* some OSs/distributions require that the "git" user should have a password
|
||||
and/or not be a locked account. You may want to check that as well.
|
||||
|
||||
* if all that fails, log onto the server as root, `cd /var/log`, and look
|
||||
for a file called `auth.log` or `secure` or some such name. Look inside
|
||||
this file for messages matching the approximate time of your last attempt
|
||||
to login, to see if they tell you what is the problem.
|
||||
|
||||
### #stsapp2_ appendix 2: which key is which -- running sshkeys-lint
|
||||
|
||||
Follow these steps on the client:
|
||||
|
||||
* get a copy of `~/.ssh/authorized_keys` from the server and put it in
|
||||
`/tmp/foo` or something
|
||||
|
||||
* cd to `~/.ssh`
|
||||
|
||||
* run `sshkeys-lint *.pub < /tmp/foo`
|
||||
|
||||
This tells you, for each pubkey, what type of access (if any) it has to the
|
||||
server.
|
||||
|
||||
Note that it is not trying to log in or anything -- it's just comparing bits
|
||||
of text (the contents of STDIN taken as an authkeys file, and the contents of
|
||||
each of the `*.pub` files one by one).
|
||||
|
||||
> Note: It's also a stand-alone program, so even if your gitolite version is
|
||||
> old, you can safely bring over just this program from a more recent
|
||||
> gitolite and use it, without having to upgrade gitolite itself.
|
||||
|
||||
If the pubkey file you're interested in appears to have the correct access to
|
||||
the server, you're done with this step.
|
||||
|
||||
Otherwise you have to rename some keypairs and try again to get the effect you
|
||||
need. Be careful:
|
||||
|
||||
* do not just rename the ".pub" file; you will have to rename the
|
||||
corresponding private key also (the one with the same basename but without
|
||||
an extension)
|
||||
|
||||
* if you're running ssh-agent, you may have to delete (using `ssh-add -D`)
|
||||
and re-add identities for it to pick up the renamed ones correctly
|
||||
|
||||
#### typical cause(s)
|
||||
|
||||
The admin often has passwordless shell access to `git@server` already, and
|
||||
then used that same key to get access to gitolite (i.e., copied that same
|
||||
pubkey as YourName.pub and ran `gl-setup` on it).
|
||||
|
||||
As a result, the same key appears twice in the authkeys file now, and since
|
||||
the ssh server will always use the first match, the second occurrence (which
|
||||
invokes gitolite) is ignored.
|
||||
|
||||
To fix this, you have to use a different keypair for gitolite access. The
|
||||
best way to do this is to create a new keypair, copy the pubkey to the server
|
||||
as YourName.pub, then run `gl-setup YourName.pub` on the server. Remember to
|
||||
adjust your agent identities using ssh-add -D and ssh-add if you're using
|
||||
ssh-agent, otherwise these new keys may not work.
|
||||
|
||||
### #stsapp3_ appendix 3: ssh client may not be offering the right key
|
||||
|
||||
* make sure the right private key is being offered. Run ssh in very
|
||||
verbose mode and look for the word "Offering", like so:
|
||||
|
||||
ssh -vvv user@host pwd 2> >(grep -i offer)
|
||||
|
||||
If some keys *are* being offered, but not the key that was supposed to be
|
||||
used, you may be using ssh-agent (next bullet). You may also need to
|
||||
create some host aliases in `~/.ssh/config` ([appendix 4][sshhostaliases]).
|
||||
|
||||
* (ssh-agent issues) If `ssh-add -l` responds with either "The agent has no
|
||||
identities." or "Could not open a connection to your authentication
|
||||
agent.", then you can skip this bullet.
|
||||
|
||||
However, if `ssh-add -l` lists *any* keys at all, then something weird
|
||||
happens. Due to a quirk in ssh-agent, ssh will now *only* use one of
|
||||
those keys, *even if you explicitly ask* for some other key to be used.
|
||||
|
||||
In that case, add the key you want using `ssh-add ~/.ssh/YourName` and try
|
||||
the access again.
|
||||
|
||||
### F=sshhostaliases appendix 4: host aliases
|
||||
|
||||
(or "making git use the right options for ssh")
|
||||
|
||||
The ssh command has several options for non-default items to be specified.
|
||||
Two common examples are `-p` for the port number if it is not 22, and `-i` for
|
||||
the public key file if you do not want to use just `~/.ssh/id_rsa` or such.
|
||||
|
||||
Git has two ssh-based URL syntaxes, but neither allows specifying a
|
||||
non-default public key file. And a port number is only allowed in one of
|
||||
them. (See `man git-clone` for details). Finally, hosts often have to be
|
||||
referred with IP addresses (such is life), or the name is very long, or hard
|
||||
to remember.
|
||||
|
||||
Using a "host" para in `~/.ssh/config` lets you nicely encapsulate all this
|
||||
within ssh and give it a short, easy-to-remember, name. Example:
|
||||
|
||||
host gitolite
|
||||
user git
|
||||
hostname a.long.server.name.or.annoying.IP.address
|
||||
port 22
|
||||
identityfile ~/.ssh/id_rsa
|
||||
|
||||
Now you can simply use the one word `gitolite` (which is the host alias we
|
||||
defined here) and ssh will infer all those details defined under it -- just
|
||||
say `ssh gitolite` and `git clone gitolite:reponame` and things will work.
|
||||
|
||||
(By the way, the 'port' and 'identityfile' lines are needed only if you have
|
||||
non-default values, although I put them in anyway just to be complete).
|
||||
|
||||
If you have *more than one* pubkey with access to the *same* server, you
|
||||
**must** use this method to make git pick up the right key. There is no other
|
||||
way to do this, as far as I know.
|
||||
|
||||
[tut]: http://sites.google.com/site/senawario/home/gitolite-tutorial
|
||||
|
||||
### #stsapp5_ appendix 5: why bypassing gitolite causes a problem
|
||||
|
||||
When you bypass gitolite, you end up running your normal shell instead of the
|
||||
special gitolite entry point script `gl-auth-command`.
|
||||
|
||||
This means commands (like 'info') are interpreted by the shell instead of
|
||||
gitolite.
|
||||
|
||||
It also means git operations look for repos in `$HOME`.
|
||||
|
||||
However, gitolite places all your repos in a subdirectory pointed to by
|
||||
`$REPO_BASE` in the rc file (default: `repositories`), and internally prefixes
|
||||
this before calling the actual git command you invoked. Thus, the pathname of
|
||||
the repo that you use on the client is almost never the correct pathname on
|
||||
the server. (This is by design. Don't argue...)
|
||||
|
||||
This means that, you get 2 kinds of errors if you bypass gitolite
|
||||
|
||||
* when you use `git@server:reponame` with a key that bypasses gitolite
|
||||
(i.e., gets you a shell), this prefixing does not happen, and so the repo
|
||||
is not found. Neither a clone/fetch nor a push will work.
|
||||
|
||||
* conversely, consider `git@server:repositories/reponame.git`. The clone
|
||||
operation will work -- you're using the full Unix path, (assuming default
|
||||
`$REPO_BASE` setting), and so the shell finds the repo where you said it
|
||||
would be. However, when you push, gitolite's **update hook** kicks in,
|
||||
and fails to run because some of the environment variables it is expecting
|
||||
are not present.
|
11
doc/extras/ssh.mkd
Normal file
11
doc/extras/ssh.mkd
Normal file
|
@ -0,0 +1,11 @@
|
|||
# ssh
|
||||
|
||||
There are two documents you need to read, in order:
|
||||
|
||||
* [gitolite and ssh][glssh] -- this explains how gitolite uses openssh's
|
||||
features to provide any number of virtual users over just one actual
|
||||
(unix) user, and so on
|
||||
|
||||
* [ssh troubleshooting][sshts] -- this is a rather long document but as far
|
||||
as I know almost every known ssh related issue is in here. If you find
|
||||
something missing, send me an email with details.
|
6
doc/extras/unique.mkd
Normal file
6
doc/extras/unique.mkd
Normal file
|
@ -0,0 +1,6 @@
|
|||
# unique setups
|
||||
|
||||
This page is for unique setups that I support. At present there is only one
|
||||
-- Fedora.
|
||||
|
||||
|
10
doc/g2alt.mkd
Normal file
10
doc/g2alt.mkd
Normal file
|
@ -0,0 +1,10 @@
|
|||
## #g2alt alternate implementations for some g2 features
|
||||
|
||||
The following g2 features have been dropped but suitable (or better)
|
||||
alternatives exist.
|
||||
|
||||
### gl-time for performance measurement
|
||||
|
||||
Take a look at the 'cpu-time' program that you can set to run from the
|
||||
`POST_GIT` trigger. Just set it to run as the last program in that sequence
|
||||
so it covers all previous programs.
|
2
doc/g2dropped.mkd
Normal file
2
doc/g2dropped.mkd
Normal file
|
@ -0,0 +1,2 @@
|
|||
## #g2dropped g2 features dropped
|
||||
|
35
doc/g2incompat.mkd
Normal file
35
doc/g2incompat.mkd
Normal file
|
@ -0,0 +1,35 @@
|
|||
## #g2incompat compatibility with g2
|
||||
|
||||
The following incompatibilities exist, in vaguely decreasing order of
|
||||
severity. **The ones in the first section are IMPORTANT because they allow
|
||||
access that was previously not allowed -- please fix your config before using
|
||||
the new gitolite!**
|
||||
|
||||
### fallthru in NAME rules
|
||||
|
||||
Fallthru on all VREFs is "success" now, so any NAME/ rules you have **MUST**
|
||||
change the ruleset in some way. The simplest is to add the following line to
|
||||
the end of each repo's rule list:
|
||||
|
||||
- NAME/ = @all
|
||||
|
||||
### subconf command in admin repo
|
||||
|
||||
(This is also affected by the previous issue, 'fallthru in NAME rules'; please
|
||||
read that as well).
|
||||
|
||||
If you're using delegation in your admin conf setup, please add the following
|
||||
lines to the end of the gitolite-admin rules in your conf/gitolite.conf file:
|
||||
|
||||
repo gitolite-admin
|
||||
- NAME/ = @all
|
||||
|
||||
subconf "fragments/*.conf"
|
||||
|
||||
The first part compensates for fallthru now being a success when processing
|
||||
[VREF][vref] rules (NAME rules are just one specific VREF). Although,
|
||||
**ideally**, you should change your ruleset so that you no longer require that
|
||||
line. As the [vref documentation][vref] says:
|
||||
|
||||
> **Virtual refs are best used as additional "deny" rules**, performing
|
||||
> extra checks that core gitolite cannot.
|
122
doc/g2migr.mkd
Normal file
122
doc/g2migr.mkd
Normal file
|
@ -0,0 +1,122 @@
|
|||
## #g2migr migrating from g2
|
||||
|
||||
<font color="red">
|
||||
|
||||
**This document is a *MUST* read if you are currently using g2 and want to
|
||||
move to g3.**
|
||||
|
||||
</font>
|
||||
|
||||
First things first: g2 will be supported for a good long time. My current
|
||||
*expert* users do not cause me any load anyway.
|
||||
|
||||
Migration should be straightforward, but it is not automatic. When you first
|
||||
run "gitolite setup [...]", gitolite3 will try to detect at least the big
|
||||
problems. However, converting the RC file and the conf files is (as of now)
|
||||
still a manual exercise, though not very difficult.
|
||||
|
||||
You must first read about [incompatible][g2incompat] features and
|
||||
[dropped][g2dropped] features. Some features have been replaced with
|
||||
[alternatives][g2alt].
|
||||
|
||||
Since the majority of changes are in the rc file, we list them all here.
|
||||
|
||||
### rc file differences
|
||||
|
||||
**DROPPED** variables (possible high impact): these could be show-stoppers for
|
||||
migration, at least for now.
|
||||
|
||||
* `BIG_INFO_CAP` -- if you think you must have this, try it without and see
|
||||
if there's a difference. If you *know* you need this, convince me.
|
||||
|
||||
* `GL_ALL_READ_ALL` -- same
|
||||
|
||||
* `GL_NO_CREATE_REPOS` -- if you think you need this, email me. I know one
|
||||
group who does need this so I will be putting it in eventually but not
|
||||
right away.
|
||||
|
||||
* `HTPASSWD_FILE`, `RSYNC_BASE`, `SVNSERVE` -- need work. Email me if you
|
||||
are using any of these.
|
||||
|
||||
* `GL_GET_MEMBERSHIPS_PGM` -- is on my todo list
|
||||
|
||||
* `GL_LOGT` -- is now fixed; you can't change it. Email me if this is a
|
||||
problem.
|
||||
|
||||
**DROPPED** variables (medium impact): these have alternative implementations
|
||||
or mechanisms, but you have to do some setup work.
|
||||
|
||||
* `GL_ADMINDIR` -- this is now at a fixed location: `~/.gitolite`. If you
|
||||
want it somewhere else go ahead and move it, then place a symlink from the
|
||||
assumed location to the real one.
|
||||
|
||||
* `REPO_BASE` -- this is now at a fixed location: `~/repositories`. If you
|
||||
want it somewhere else go ahead and move it, then place a symlink from the
|
||||
assumed location to the real one.
|
||||
|
||||
* `PROJECTS_LIST` -- it's called `GITWEB_PROJECTS_LIST` now, but more
|
||||
importantly, it is only used by update-gitweb-access-list in
|
||||
src/commands/post-compile. This variable now has nothing to do with
|
||||
gitolite core, and the rc is just helping to store settings for external
|
||||
programs like that one.
|
||||
|
||||
`WEB_INTERFACE` and `GITWEB_URI_ESCAPE` are also gone; patches to the
|
||||
update program to directly do those things are welcome.
|
||||
|
||||
* `GL_NO_DAEMON_NO_GITWEB` -- uncomment the appropriate lines in the rc
|
||||
file, in both the `POST_COMPILE` and `POST_CREATE` trigger sections.
|
||||
|
||||
* `NICE_VALUE` -- use the `PRE_GIT` trigger to attach a program that renices
|
||||
the pid given by $GL_TID (that's the pid of the initial gitolite entry
|
||||
point, usually gitolite-shell, and propagates from there once set).
|
||||
|
||||
You may have to add this list to the rc file; if you don't know perl use
|
||||
one of the others as a model or ask me.
|
||||
|
||||
* `GIT_PATH` -- gone, not needed. Just add these lines to the end of the rc
|
||||
file:
|
||||
|
||||
$ENV{PATH}="...whatever you want...";
|
||||
1;
|
||||
|
||||
* `GL_NO_SETUP_AUTHKEYS` -- comment out the lines that call ssh-authkeys, in
|
||||
the rc file.
|
||||
|
||||
* `GL_WILDREPOS_DEFPERMS` -- if you need this, add a `POST_CREATE` script
|
||||
that does it. Or email me and I will write it for you.
|
||||
|
||||
* `UPDATE_CHAINS_TO` -- use a [vref][] instead. You can directly use the
|
||||
chained-to script as a VREF; it'll work.
|
||||
|
||||
* `ADMIN_POST_UPDATE_CHAINS_TO` -- add your script to the `POST_COMPILE`
|
||||
trigger chain. You won't be getting any arguments but for the admin repo
|
||||
the only argument that ever comes in is "refs/heads/master" anyway.
|
||||
|
||||
* `GL_ADC_PATH` -- obsolete; use [commands][] or add [your own][dev-notes].
|
||||
|
||||
* `GL_ALL_INCLUDES_SPECIAL` -- obsolete; @all always includes gitweb and
|
||||
daemon now. Use [deny-rules][] if you want to say `R = @all` but not have
|
||||
it be visible to gitweb or daemon.
|
||||
|
||||
* `GL_PERFLOGT` -- see the entry for "gl-time" in the [alternative
|
||||
implementations][g2alt] page.
|
||||
|
||||
**DROPPED** variables (no impact/low impact): these variables should not
|
||||
actually affect anything anyway, so even if you had them set you should not
|
||||
feel their loss.
|
||||
|
||||
* `GL_CONF`, `GL_KEYDIR`, and `GL_CONF_COMPILED` -- you had no business
|
||||
touching these anyway; if you did, move them into the expected default
|
||||
locations before attempting to run `gitolite setup`
|
||||
* `GL_PACKAGE_HOOKS` -- not needed anymore, but check if you had any custom
|
||||
hooks set there and copy them across.
|
||||
* `GL_WILDREPOS` -- dropped; this feature is default now.
|
||||
* `GL_BIG_CONFIG` -- dropped; this feature is default now.
|
||||
|
||||
**RENAMED** variables (no impact): these are functionally the same but are
|
||||
renamed.
|
||||
|
||||
* `REPO_UMASK` is now `UMASK`
|
||||
* `GL_GITCONFIG_KEYS` is now `GITCONFIG_KEYS`
|
||||
* `GL_WILDREPOS_PERM_CATS` is now the ROLES hash in the rc file
|
||||
* `GL_SITE_INFO` is not `SITE_INFO`
|
97
doc/g3why.mkd
Normal file
97
doc/g3why.mkd
Normal file
|
@ -0,0 +1,97 @@
|
|||
# why a completely new version?
|
||||
|
||||
Gitolite started life as 400 lines of perl written on a weekend because I was
|
||||
quickly losing control of my projects at work, exacerbated by git newbies
|
||||
doing all the wrong things. I really needed it!
|
||||
|
||||
That little 400 line thing is now a huge bunch of programs that do all sorts
|
||||
of things (I mean, rsync access control in a git related program? WTF!),
|
||||
because it kinda just *grew* while I wasn't looking.
|
||||
|
||||
So, briefly, here are the advantages of g3:
|
||||
|
||||
* compile versus everything else
|
||||
|
||||
g2's "compile" script was doing way, way too much. For example, dealing
|
||||
with gitweb and git-daemon was a good chunk of code in g2. In contrast,
|
||||
here's how g3 generates gitweb's projects.list file:
|
||||
|
||||
(
|
||||
gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
|
||||
gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
|
||||
) |
|
||||
cut -f1 | sort -u | sed -e 's/$/.git/' > $plf
|
||||
|
||||
* core versus non-core
|
||||
|
||||
That's just the tip of the iceberg. The commands above run from a script
|
||||
that is itself outside gitolite, and can be enabled and disabled from the
|
||||
rc file. There are six different "events" within gitolite that can
|
||||
trigger external programs, with specific arguments passed to them, much
|
||||
like git's own hooks. The example you saw is called from the
|
||||
"POST_COMPILE" trigger.
|
||||
|
||||
And as you can see, these programs be in any language.
|
||||
|
||||
* get/set perms/desc, and ADCs
|
||||
|
||||
I've always wanted to kick setperms out of core and make it an ADC.
|
||||
Sadly, it couldn't be done because when you update your repo's permissions
|
||||
using setperms, that can affect gitweb/daemon access, which -- you guessed
|
||||
right -- feeds back into the main code in complex ways. It *had* to be an
|
||||
"inside job".
|
||||
|
||||
But now, the new 'perms' program is quite external to gitolite. And how
|
||||
does it fix up gitweb/daemon permissions after it is done updating the
|
||||
"gl-perms" file?
|
||||
|
||||
system("gitolite", "trigger", "POST_CREATE");
|
||||
|
||||
* syntax versus semantics
|
||||
|
||||
I got tired of people asking things like "why can't I have
|
||||
backslash-escaped continuation lines?" I designed it differently because
|
||||
I don't like them but perhaps it's reasonable for some people.
|
||||
|
||||
Someone else wanted to use subdirectories of 'keydir' as group names. Why
|
||||
not?
|
||||
|
||||
G3 comes with a stackable set of "syntactic sugar" helpers. And you can
|
||||
write your own, though they do have to be in perl (because they're not
|
||||
standalone programs).
|
||||
|
||||
Once the code is written and placed in the right place, all a site has to
|
||||
do to enable it is to uncomment some lines in the rc file:
|
||||
|
||||
# these will run in sequence during the conf file parse
|
||||
SYNTACTIC_SUGAR =>
|
||||
[
|
||||
# 'continuation-lines',
|
||||
# 'keysubdirs-as-groups',
|
||||
<etc>
|
||||
|
||||
* roll your own
|
||||
|
||||
Having a decent shell API helps enormously. You saw an example above but
|
||||
how about if your boss asks you "I need a list of everyone who *currently*
|
||||
has read access to the 'foo' repo"?
|
||||
|
||||
Sure you could look in conf/gitolite.conf, all its include files (if you
|
||||
have any), and if the repo is user-created, then in its gl-perms.
|
||||
|
||||
Or you could do something like this:
|
||||
|
||||
gitolite list-users | gitolite access foo % R any | cut -f1
|
||||
|
||||
* over-engineered
|
||||
|
||||
g2 was, to some extent, over-engineered. One of the best examples is the
|
||||
documentation on hook-propagation in g2, which required even a *picture*
|
||||
to make clear (always a bad sign). In g3, the [hooks][] section is 4
|
||||
sentences.
|
||||
|
||||
Anyway you get the idea.
|
||||
|
||||
The point is not that you can do all these cool tricks. The point is they are
|
||||
possible because of the redesign. There is no way on God's green earth I
|
||||
could have done this with the old code.
|
32
doc/group.mkd
Normal file
32
doc/group.mkd
Normal file
|
@ -0,0 +1,32 @@
|
|||
# parts of the conf file
|
||||
|
||||
## #group group definitions
|
||||
|
||||
You can group repos or users for convenience. The syntax is the same for both
|
||||
and does not distinguish; until you *use* the group name it could really be
|
||||
either.
|
||||
|
||||
Here's an example:
|
||||
|
||||
@developers = dilbert alice wally
|
||||
|
||||
Group definitions accumulate; this is the same as the above:
|
||||
|
||||
@developers = dilbert
|
||||
@developers = alice
|
||||
@developers = wally
|
||||
|
||||
You can use one group in another group definition; the values will be expanded
|
||||
right there (meaning later additions will not appear in the second group).
|
||||
|
||||
@developers = dilbert alice
|
||||
@interns = ashok
|
||||
@staff = @interns @developers
|
||||
@developers = wally
|
||||
|
||||
# wally is NOT part of @staff
|
||||
|
||||
### special group `@all`
|
||||
|
||||
`@all` is a special group name that is often convenient to use if you really
|
||||
mean "all repos" or "all users".
|
9
doc/hooks.mkd
Normal file
9
doc/hooks.mkd
Normal file
|
@ -0,0 +1,9 @@
|
|||
# hooks and gitolite
|
||||
|
||||
Gitolite uses the `update` hook for all repos. In addition, it uses the
|
||||
`post-update` hook for the gitolite-admin repo.
|
||||
|
||||
If you want to add your own hook, it's easy as long as it's not the 'update'
|
||||
hook. Just add it to `$HOME/.gitolite/hooks/common` and run `gitolite setup`.
|
||||
|
||||
The rest is between you and 'man githooks' :-)
|
67
doc/index.mkd
Normal file
67
doc/index.mkd
Normal file
|
@ -0,0 +1,67 @@
|
|||
# Hosting git repositories
|
||||
|
||||
Gitolite allows you to setup git hosting on a central server, with
|
||||
fine-grained access control and many more powerful features.
|
||||
|
||||
Here's more on [what][] it is and [why][] you might need it.
|
||||
|
||||
For current gitolite (call it "g2" for convenience) users,
|
||||
|
||||
* [Why][g3why] I rewrote gitolite.
|
||||
* Development [status][dev-status] (**should change often for a while**)
|
||||
* Specific migration [issues and steps][g2migr].
|
||||
|
||||
Quick links:
|
||||
|
||||
* [Minimum requirements][minreq].
|
||||
* Here's how to [get started][qi] installing and setting it up
|
||||
* Don't know ssh well enough? [Learn][ssh]. It's **IMPORTANT**.
|
||||
* [Add users and repos][add].
|
||||
* Learn about fine-grained access control with the [conf][] file
|
||||
* Explain gitolite to your [users][].
|
||||
|
||||
Not so "quick" links:
|
||||
|
||||
* The "master table of contents" link at the top of each page is the
|
||||
**first** place you should check when looking for anything.
|
||||
|
||||
* Want to do more than just add users and repos and control their access?
|
||||
Here's how to [customise][cust] your server installation.
|
||||
|
||||
Additional reading for Unix newbies:
|
||||
|
||||
* [Regular Expressions][regex]
|
||||
|
||||
## #what What is gitolite?
|
||||
|
||||
Gitolite is an access control layer on top of git. Here are the features that
|
||||
most people see:
|
||||
|
||||
* use a single unix user ("real" user) on the server
|
||||
* provide access to many gitolite users
|
||||
* they are not "real" users
|
||||
* they do not get shell access
|
||||
* control access to many git repositories
|
||||
* read access controlled at the repo level
|
||||
* write access controlled at the branch/tag/file/directory level,
|
||||
including who can rewind, create, and delete branches/tags
|
||||
* can be installed without root access, assuming git and perl are already
|
||||
installed
|
||||
* authentication is most commonly done using sshd, but you can also use
|
||||
httpd if you prefer (this may require root access).
|
||||
|
||||
## #contact contact
|
||||
|
||||
* author: sitaramc@gmail.com, sitaram@atc.tcs.com
|
||||
* mailing list: gitolite@googlegroups.com
|
||||
* list subscribe address : gitolite+subscribe@googlegroups.com
|
||||
* IRC: #git and #gitolite on freenode. Note that I live in India (UTC+0530
|
||||
time zone).
|
||||
|
||||
## #license license
|
||||
|
||||
The gitolite *code* is released under GPL v2. See COPYING for details.
|
||||
|
||||
The gitolite documentation is provided under a [Creative Commons
|
||||
Attribution-NonCommercial-ShareAlike 3.0 Unported
|
||||
License](http://creativecommons.org/licenses/by-nc-sa/3.0/).
|
58
doc/install.mkd
Normal file
58
doc/install.mkd
Normal file
|
@ -0,0 +1,58 @@
|
|||
# different ways to install gitolite
|
||||
|
||||
Gitolite has only one server side "command" now, much like git itself. And
|
||||
it's been designed so that you don't even really have to *install* it, as you
|
||||
will see.
|
||||
|
||||
## simplest
|
||||
|
||||
1. Put all of `src` in one place, doesn't matter where; let's call it
|
||||
/foo/bar.
|
||||
|
||||
2. Use the full path to run any gitolite commands, for example:
|
||||
|
||||
/foo/bar/gitolite setup -pk sitaram.pub
|
||||
|
||||
## almost as simple
|
||||
|
||||
1. (same as above)
|
||||
|
||||
2. Symlink /foo/bar/gitolite to some directory that is on your PATH. For
|
||||
example:
|
||||
|
||||
ln -sf /foo/bar/gitolite ~/bin
|
||||
|
||||
Now you can just say
|
||||
|
||||
gitolite setup -pk sitaram.pub
|
||||
|
||||
## packagers
|
||||
|
||||
1. Put src/Gitolite in `/usr/share/perl5/vendor_perl` or some such place.
|
||||
|
||||
2. Put the rest of src anywhere your distro policy allows. (Fedora keeps
|
||||
git's 150 executables in /usr/libexec/git-core, so maybe
|
||||
/usr/libexec/gitolite?)
|
||||
|
||||
3. Symlink 'gitolite' to /usr/bin or something, similar to step 2 above,
|
||||
|
||||
OR
|
||||
|
||||
Put it directly in /usr/bin, and hardcode `GL_BINDIR` into it to tell it
|
||||
where the others are. I'd prefer it if you did not do this but you can.
|
||||
|
||||
----
|
||||
|
||||
Bottom line:
|
||||
|
||||
* `GL_BINDIR` must point to a place that contains `commands`, `VREF`, and
|
||||
`syntactic-sugar` (so they must all be sibling directories).
|
||||
* The `Gitolite` directory can also be there, or it can be anywhere in
|
||||
perl's `@INC` path.
|
||||
|
||||
## upgrading
|
||||
|
||||
Just put the new version on top of wherever you kept the old one. That's it.
|
||||
|
||||
If you feel it should require a little more effort, pretend I said "you have
|
||||
to then run `gitolite setup`". Can't hurt...
|
43
doc/list
Normal file
43
doc/list
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
index.mkd
|
||||
why.mkd
|
||||
|
||||
g3why.mkd
|
||||
dev-status.mkd
|
||||
g2migr.mkd
|
||||
g2incompat.mkd
|
||||
g2dropped.mkd
|
||||
g2alt.mkd
|
||||
|
||||
minreq.mkd
|
||||
qi.mkd
|
||||
install.mkd
|
||||
add.mkd
|
||||
conf.mkd
|
||||
users.mkd
|
||||
|
||||
rc.mkd
|
||||
cust.mkd
|
||||
|
||||
group.mkd
|
||||
repo.mkd
|
||||
rules.mkd
|
||||
refex.mkd
|
||||
write-types.mkd
|
||||
|
||||
dev-notes.mkd
|
||||
commands.mkd
|
||||
hooks.mkd
|
||||
triggers.mkd
|
||||
sugar.mkd
|
||||
vref.mkd
|
||||
|
||||
misc.mkd
|
||||
pw.mkd
|
||||
testing.mkd
|
||||
extras/auth.mkd
|
||||
extras/nagp.mkd
|
||||
extras/regex.mkd
|
||||
extras/ssh.mkd
|
||||
extras/gitolite-and-ssh.mkd
|
||||
extras/ssh-troubleshooting.mkd
|
32
doc/minreq.mkd
Normal file
32
doc/minreq.mkd
Normal file
|
@ -0,0 +1,32 @@
|
|||
# minimum requirements for gitolite
|
||||
|
||||
**Client**:
|
||||
|
||||
* git 1.6.6 or greater
|
||||
* an ssh client that can talk to an openssh server, and can generate keys in
|
||||
openssh's default format (the pubkey is just one long line). Gitolite
|
||||
will [not currently][pw1] convert such keys.
|
||||
|
||||
For people still using Windows, msysgit works fine. If you're using
|
||||
[putty/plink][ens], God bless you. (It'll work, but I still want him to bless
|
||||
you).
|
||||
|
||||
TODO: when smart http support works, ssh will no longer be a *requirement*,
|
||||
merely a *strong* suggestion :-)
|
||||
|
||||
**Server**
|
||||
|
||||
* git 1.6.6 or greater
|
||||
* perl 5.8.8 or greater
|
||||
* an ssh server compatible with openssh, especially it's authorized keys
|
||||
file format and features.
|
||||
* any Unix or Unix like OS. That said, I've occasionally had some weird
|
||||
reports from [Mac OSX servers][ens]; good luck.
|
||||
* a single, dedicated, userid to host it (usually 'git' or 'gitolite').
|
||||
|
||||
These version numbers are subject to fine-tuning as I get feedback and make
|
||||
fixes where possible and needed.
|
||||
|
||||
Sshd must be configured so that each users authkeys file is in the user's
|
||||
`$HOME`, inside `.ssh/authorized_keys`, and not in some central
|
||||
/var/something.
|
80
doc/misc.mkd
Normal file
80
doc/misc.mkd
Normal file
|
@ -0,0 +1,80 @@
|
|||
# odds and ends
|
||||
|
||||
Most of these items don't fit anywhere or fit in more than one place or are of
|
||||
the nature of background information.
|
||||
|
||||
## #include 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 "conf" directory.
|
||||
|
||||
Details:
|
||||
|
||||
* You can also use a glob (`include "*.conf"`), or put your include files
|
||||
into subdirectories of "conf" (`include "foo/bar.conf"`), or both
|
||||
(`include "repos/*.conf"`).
|
||||
|
||||
* Included files are always searched relative to the gitolite-admin repo's
|
||||
"conf/" directory.
|
||||
|
||||
* If you ended up recursing, 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>
|
||||
|
||||
## #deny-rules applying deny rules at the pre-git access check
|
||||
|
||||
The access [rules][] rules section describes the problem. To recap, you want
|
||||
this:
|
||||
|
||||
@staff = alice bob wally ashok
|
||||
|
||||
repo foo
|
||||
RW+ = alice # line 1
|
||||
RW+ dev = bob # line 2
|
||||
- = wally # line 3
|
||||
RW temp/ = @staff # line 4
|
||||
|
||||
to deny Wally even *read* access.
|
||||
|
||||
The way to do this is to add this line to the repo:
|
||||
|
||||
option deny-rules = 1
|
||||
|
||||
If you want this for all your repos, just add this somewhere at the top of
|
||||
your conf file
|
||||
|
||||
repo @all
|
||||
option deny-rules = 1
|
||||
|
||||
## #rule-accum rule accumulation
|
||||
|
||||
Gitolite was meant to collect rules from multiple places and apply them all.
|
||||
For example, this:
|
||||
|
||||
repo foo
|
||||
RW = u1
|
||||
|
||||
@gr1 = foo bar
|
||||
|
||||
repo @gr1
|
||||
RW = u2
|
||||
R = u3
|
||||
|
||||
repo @all
|
||||
R = gitweb
|
||||
|
||||
is effectively the same as this, for repo foo:
|
||||
|
||||
repo foo
|
||||
RW = u1
|
||||
RW = u2
|
||||
R = u3
|
||||
R = gitweb
|
||||
|
||||
This extends to patterns also, but I'll leave an example for later.
|
88
doc/mkdoc
Executable file
88
doc/mkdoc
Executable file
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
my $MKD = "$ENV{HOME}/Markdown.pl";
|
||||
|
||||
# run this like so:
|
||||
|
||||
# $0 *.mkd >mt.mkd 2>mf
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
chomp(@ARGV = `cat list`) if not @ARGV;
|
||||
@ARGV = grep { $_ ne 'master-toc.mkd' and /./ } @ARGV;
|
||||
my @save = @ARGV;
|
||||
my $css = join("", <DATA>);
|
||||
|
||||
my $mt = "# gitolite master table of contents/index\n";
|
||||
my $mf = '';
|
||||
my $fh;
|
||||
|
||||
while (<>) {
|
||||
$ARGV =~ /^(?:.*\/)?([^\/]+)\.mkd$/;
|
||||
my $b = $1;
|
||||
|
||||
if (/^(#+) (?:#(\S+) )?(.*)/) {
|
||||
if ( length($1) == 1 ) {
|
||||
$mt .= "\n";
|
||||
$mt .= " * [$3][$b]\n";
|
||||
$mf .= "[$b]: $b.html\n";
|
||||
} else {
|
||||
$mt .= " " x ( 4 * ( length($1) - 1 ) );
|
||||
$mt .= " * ";
|
||||
$mt .= (
|
||||
$2
|
||||
? "[$3][$2]"
|
||||
: "$3"
|
||||
);
|
||||
$mt .= "\n";
|
||||
$mf .= "[$2]: $b.html#$2\n" if $2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open($fh, ">", "master-toc.mkd")
|
||||
and print $fh $mt
|
||||
and close $fh;
|
||||
|
||||
# after this, do this for every mkd (including the master-toc.mkd)
|
||||
|
||||
# cat $css_block > $base.html
|
||||
# cat $base.mkd $mf | $MKD >> $base.html
|
||||
|
||||
for my $mkd ("master-toc.mkd", @save) {
|
||||
$mkd =~ /^(?:.*\/)?([^\/]+)\.mkd$/;
|
||||
my $b = $1;
|
||||
|
||||
open($fh, ">", "../html/$b.html")
|
||||
and print $fh $css
|
||||
and close $fh;
|
||||
|
||||
my $mkt = `cat $mkd`;
|
||||
$mkt =~ s/^(#+) #(\S+) /$1 <a name="$2"><\/a> /mg;
|
||||
open($fh, "|-", "$MKD >> ../html/$b.html")
|
||||
and print $fh $mkt, $mf
|
||||
and close $fh;
|
||||
}
|
||||
|
||||
__DATA__
|
||||
|
||||
<head><style>
|
||||
body { background: #fff; margin-left: 40px; font-size: 0.9em; font-family: sans-serif; max-width: 800px; }
|
||||
h1 { background: #ffb; margin-left: -30px; border-top: 5px solid #ccc; }
|
||||
h2 { background: #ffb; margin-left: -20px; border-top: 3px solid #ddd; }
|
||||
h3 { background: #ffb; margin-left: -10px; }
|
||||
h4 { background: #ffb; }
|
||||
code { font-size: 1.1em; background: #ddf; }
|
||||
pre { margin-left: 2em; background: #ddf; }
|
||||
pre code { font-size: 1.1em; background: #ddf; }
|
||||
</style></head>
|
||||
|
||||
<p style="text-align:center">
|
||||
<a href="master-toc.html">master TOC</a>
|
||||
|
|
||||
<a href="index.html">main page</a>
|
||||
|
|
||||
<a href="index.html#license">license</a>
|
||||
</p>
|
45
doc/pw.mkd
Normal file
45
doc/pw.mkd
Normal file
|
@ -0,0 +1,45 @@
|
|||
# patches welcome :-)
|
||||
|
||||
These are places where I could use some help, with hints about how you would
|
||||
go about it. In addition, any of the items in [dev-status][] are up for
|
||||
grabs, if you wish to jump in. But let me know before you start, and how you
|
||||
plan to go about it.
|
||||
|
||||
## #pw2 rsync
|
||||
|
||||
The crux of the old rsync ADC was an access check to a repo whose name starts
|
||||
with EXTCMD. g2 would treat repos whose names start with EXTCMD as "don't
|
||||
create this repo". g3 makes no such distinctions, but you can get the same
|
||||
effect by using a repo group name that does not exist:
|
||||
|
||||
repo @rsync-set1
|
||||
...rules...
|
||||
|
||||
and check that in the script. (It might mean adding one more function to
|
||||
Gitolite::Easy but that's... easy!)
|
||||
|
||||
## #pw1 converting non-openssh pubkeys automatically
|
||||
|
||||
Gitolite's [triggers][] has can be used to fix this. Here's pseudo-code:
|
||||
|
||||
chdir $(gitolite query-rc -n GL_ADMIN_BASE)/keydir
|
||||
for each *.pub file in this directory and its subdirectories
|
||||
detect its format and convert it
|
||||
# just overwrite it; the original is saved in git anyway
|
||||
|
||||
Let's say the program is called "convert-non-openssh-keys". You send it to me
|
||||
and I add it to src/commands/post-compile/. Then I update the default rc file
|
||||
to look at least like this instead
|
||||
|
||||
POST_COMPILE =>
|
||||
[
|
||||
# 'post-compile/convert-non-openssh-keys',
|
||||
'post-compile/ssh-authkeys',
|
||||
...
|
||||
...
|
||||
],
|
||||
|
||||
making sure to place it *before* ssh-authkeys, and anyone who needs it can
|
||||
just uncomment it.
|
||||
|
||||
Done!
|
26
doc/qi.mkd
Normal file
26
doc/qi.mkd
Normal file
|
@ -0,0 +1,26 @@
|
|||
# getting started
|
||||
|
||||
The quickest install, assuming your `$PATH` contains `$HOME/bin`, is:
|
||||
|
||||
* get the software
|
||||
|
||||
git clone git://github.com/sitaramc/gitolite
|
||||
|
||||
# (until this becomes "master")
|
||||
cd gitolite
|
||||
git checkout -f g3
|
||||
|
||||
* install it
|
||||
|
||||
ln -sf $PWD/src/gitolite $HOME/bin
|
||||
|
||||
If you don't like that, there are [other install methods][install].
|
||||
|
||||
Once the install is done, setup:
|
||||
|
||||
gitolite setup -pk your-name.pub
|
||||
|
||||
And that's it.
|
||||
|
||||
Next steps are usually [adding][add] users and repos and learning about
|
||||
[access control][conf].
|
20
doc/rc.mkd
Normal file
20
doc/rc.mkd
Normal file
|
@ -0,0 +1,20 @@
|
|||
# the "rc" file ($HOME/.gitolite.rc)
|
||||
|
||||
The rc file for g3 is quite different from that of g2. It has been designed
|
||||
to be (a) the only thing unique to your site, for most installations and (b)
|
||||
easy to extend when new needs show up, without having to touch core gitolite.
|
||||
|
||||
g2 had a nasty rc file where every variable had to be declared. As a result,
|
||||
ADCs that needed their own settings could not use it.
|
||||
|
||||
Now it's a perl hash, and you can add any keys you want.
|
||||
|
||||
Please look at the rc file that gets installed when you setup gitolite. As
|
||||
you can see there are 3 types of variables in it:
|
||||
|
||||
* simple variables (like UMASK)
|
||||
* lists (like `POST_COMPILE`, `POST_CREATE`)
|
||||
* hashes (like `ROLES`, `COMMANDS`)
|
||||
|
||||
Their purposes are to be found in each of their individual documentation files
|
||||
around; start with [customising gitolite][cust].
|
30
doc/refex.mkd
Normal file
30
doc/refex.mkd
Normal file
|
@ -0,0 +1,30 @@
|
|||
## #refex matching a ref and a refex
|
||||
|
||||
A refex is a word I made up to mean "a regex that matches a ref". If you know
|
||||
[regular expressions][regex] you're halfway there.
|
||||
|
||||
The only extra info you need is:
|
||||
|
||||
* for convenience, a refex not starting with `refs/` is assumed to start
|
||||
with `refs/heads/`. This means normal branches can be referred to like
|
||||
this:
|
||||
|
||||
RW master = alice
|
||||
# becomes 'refs/heads/master' internally
|
||||
|
||||
while tags will need to be fully qualified
|
||||
|
||||
RW refs/tags/v[0-9] = bob
|
||||
|
||||
* a refex is implicitly anchored at the start, but not at the end. In
|
||||
regular expression lingo, a `^` is assumed at the start (but no `$` at the
|
||||
end is assumed). So a refex of `master` will allow all these:
|
||||
|
||||
refs/heads/master
|
||||
refs/heads/master1
|
||||
refs/heads/master2
|
||||
refs/heads/master/full
|
||||
|
||||
If you want to restrict to just the one specific ref, use
|
||||
|
||||
RW master$ = alice
|
23
doc/repo.mkd
Normal file
23
doc/repo.mkd
Normal file
|
@ -0,0 +1,23 @@
|
|||
## #repo repo definitions
|
||||
|
||||
Example:
|
||||
|
||||
repo gitolite tsh gitpod
|
||||
RW+ = sitaram
|
||||
RW dev = alice bob
|
||||
R = @all
|
||||
|
||||
The "repo" line can have any number of repo names or repo group names in it.
|
||||
However, it can only be one line; this will not work
|
||||
|
||||
repo foo
|
||||
repo bar # WRONG; 'foo' is now forgotten
|
||||
RW = alice
|
||||
|
||||
If you have too many, use a group name:
|
||||
|
||||
@myrepos = foo
|
||||
@myrepos = bar
|
||||
|
||||
repo @myrepos
|
||||
RW = alice
|
82
doc/rules.mkd
Normal file
82
doc/rules.mkd
Normal file
|
@ -0,0 +1,82 @@
|
|||
## #rules access rules
|
||||
|
||||
This is arguably the most complex part of day-to-day gitolite. There are
|
||||
several interconnected ideas that make this hard to lay out easily if you're
|
||||
totally new to this, so read carefully.
|
||||
|
||||
We will use this as a running example:
|
||||
|
||||
@staff = dilbert alice wally bob
|
||||
|
||||
repo foo
|
||||
RW+ = dilbert # line 1
|
||||
RW+ dev = alice # line 2
|
||||
- = wally # line 3
|
||||
RW temp/ = @staff # line 4
|
||||
R = ashok # line 5
|
||||
|
||||
### when does gitolite check access
|
||||
|
||||
The "pre-git" check is before git is invoked. Gitolite knows the repo name,
|
||||
user name, and attempted access (R or W), but no ref name.
|
||||
|
||||
The "update" check is only for write operations, and it is just before git
|
||||
updates a ref. This time gitolite knows the refname also.
|
||||
|
||||
### how is a particular rule line matched
|
||||
|
||||
For the **pre-git check**, any permission that contains "R" matches a read
|
||||
operation, and any permission that contains "W" matches a write operation.
|
||||
This is because we simply don't know enough to make finer distinctions at this
|
||||
point.
|
||||
|
||||
In addition, *gitolite ignores deny rules during the pre-git check*. <font
|
||||
color="gray">(You can [change this][deny-rules] if you wish, though it's
|
||||
rarely needed)</font>. This means line 3 is ignored, and so Wally in our
|
||||
example will pass the pre-git check.
|
||||
|
||||
For the **update check**, git gives us all the information we need. Then:
|
||||
|
||||
* all the rules for a repo are [accumulated][rule-accum]
|
||||
|
||||
* then the rules pertaining to this repo *and* this user (or to a group to
|
||||
which they belong, respectively) are kept; the rest are ignored
|
||||
|
||||
* these rules are examined *in the sequence they appeared in the conf file*.
|
||||
For each rule:
|
||||
|
||||
* if the ref does not match the [refex][], the rule is skipped
|
||||
* if it's a deny rule (the permissions field is a `-`), access is
|
||||
**rejected** and the matching stops
|
||||
* if the permission field matches the specific [type of
|
||||
write][write-types] operation, access is **allowed** and the matching
|
||||
stops
|
||||
|
||||
* if no rule ends with a decision, ("fallthru"), access is **rejected**.
|
||||
|
||||
Now you need to understand how [refex][] matching happens and how the
|
||||
permissions match the various [types of write operations][write-types].
|
||||
|
||||
Using these, you can see, in our example, that:
|
||||
|
||||
* everyone, even wally, can read the repo.
|
||||
* dilbert can push, rewind, or delete any ref.
|
||||
* alice can push, rewind, or delete any ref whose name starts with 'dev';
|
||||
see [refex][] for details.
|
||||
* alice can also push (but not rewind or delete) any ref whose name starts
|
||||
with 'temp/'. This applies to bob also.
|
||||
* if it weren't for line 3, the previous statement would apply to wally
|
||||
also.
|
||||
|
||||
Interestingly, wally can get past the pre-git check because gitolite ignores
|
||||
deny rules for pre-git, but having got past it, he can't actually do anything.
|
||||
That's by design, and as I said if you don't like it you can ask gitolite to
|
||||
[deny at pre-git][deny-rules].
|
||||
|
||||
### summary of permissions
|
||||
|
||||
The full set of permissions, in regex syntax: `-|R|RW+?C?D?M?`. This expands
|
||||
to one of `-`, `R`, `RW`, `RW+`, `RWC`, `RW+C`, `RWD`, `RW+D`, `RWCD`, or
|
||||
`RW+CD`, all but the first one optionally followed by an `M`. And by now you
|
||||
know what they all mean.
|
||||
|
11
doc/sugar.mkd
Normal file
11
doc/sugar.mkd
Normal file
|
@ -0,0 +1,11 @@
|
|||
# syntactic sugar
|
||||
|
||||
Sugar scripts help you change the perceived syntax of the conf language. The
|
||||
base syntax of the language is as described [here][conf], so sugar scripts
|
||||
take something *else* and convert it into that.
|
||||
|
||||
That way, the admin sees additional features (like allowing continuation
|
||||
lines), while the parser in the core gitolite engine does not change.
|
||||
|
||||
If you want to write your own sugar scripts, please read the "your own sugar"
|
||||
section in [dev-notes][] first then email me.
|
31
doc/testing.mkd
Normal file
31
doc/testing.mkd
Normal file
|
@ -0,0 +1,31 @@
|
|||
# testing gitolite
|
||||
|
||||
Here's how to *run* the tests:
|
||||
|
||||
git clone git://github.com/sitaramc/gitolite
|
||||
cd gitolite
|
||||
git checkout -f g3
|
||||
|
||||
# if you're not ok with your ~/.ssh getting clobbered
|
||||
prove
|
||||
|
||||
# if you're ok with your ~/.ssh getting clobbered
|
||||
# prove t/*.t t/ssh*
|
||||
|
||||
Gitolite's test suite is mostly written using [tsh][] -- the "testing shell".
|
||||
Take a look at some of the scripts and you will see what it looks like. It
|
||||
has a few quirks and nuances; if you really care, email me.
|
||||
|
||||
[tsh]: http://github.com/sitaramc/tsh
|
||||
|
||||
The tests also use a somewhat convoluted system of environment variables in
|
||||
order to run *entirely* as a local user, without going through ssh at all.
|
||||
This lets a complete test suite run in about a fifth or less of the time it
|
||||
would otherwise take.
|
||||
|
||||
If you think that defeats the purpose of the testing, you haven't read
|
||||
[this][auth] yet.
|
||||
|
||||
There are 2 specific tests that deal with ssh though, which are run only on
|
||||
request, as you can see above, because they clobber your `~/.ssh`. You have
|
||||
been warned.
|
90
doc/triggers.mkd
Normal file
90
doc/triggers.mkd
Normal file
|
@ -0,0 +1,90 @@
|
|||
# gitolite triggers
|
||||
|
||||
## intro and sample rc excerpt
|
||||
|
||||
Gitolite fires off external commands at six different times. The [rc][] file
|
||||
specifies what commands to run at each trigger point, but for illustration,
|
||||
here's an excerpt:
|
||||
|
||||
%RC = (
|
||||
|
||||
<...several lines later...>
|
||||
|
||||
# comment out or uncomment as needed
|
||||
# these will run in sequence after post-update
|
||||
POST_COMPILE =>
|
||||
[
|
||||
'post-compile/ssh-authkeys',
|
||||
'post-compile/update-git-configs',
|
||||
'post-compile/update-gitweb-access-list',
|
||||
'post-compile/update-git-daemon-access-list',
|
||||
],
|
||||
|
||||
# comment out or uncomment as needed
|
||||
# these will run in sequence after a new wild repo is created
|
||||
POST_CREATE =>
|
||||
[
|
||||
'post-compile/update-git-configs',
|
||||
'post-compile/update-gitweb-access-list',
|
||||
'post-compile/update-git-daemon-access-list',
|
||||
],
|
||||
|
||||
(As you can see, post-create runs 3 programs that also run from post-compile.
|
||||
This is perfectly fine, by the way)
|
||||
|
||||
## manually firing triggers
|
||||
|
||||
...from the server command line is easy. For example:
|
||||
|
||||
gitolite trigger POST_COMPILE
|
||||
|
||||
However if the triggered code depends on arguments (see next section) this
|
||||
won't work. (The `POST_COMPILE` trigger programs all just happen to not
|
||||
require any arguments, so it works).
|
||||
|
||||
## triggers and arguments
|
||||
|
||||
All triggers receive the name of the trigger as a string (example,
|
||||
`"POST_COMPILE"`) as the first argument, so they can know who invoked them.
|
||||
(This allows you to write the same program and fire it from more than one
|
||||
trigger, as above). In addition, they may receive other arguments pertaining
|
||||
to the event that happened.
|
||||
|
||||
* `ACCESS_CHECK`: this fires once after each access check. The first is
|
||||
just before invoking git-receive-pack or git-upload-pack. The second,
|
||||
which only applies to "write" operations, is from git's own 'update' hook.
|
||||
|
||||
Arguments: repo name, user name, [attempted access][perm], the ref being
|
||||
updated, and the result of the access check.
|
||||
|
||||
The 'ref' is `any` for the first check, because at that point we don't
|
||||
know what the actual ref is. For the second check it could be, say,
|
||||
`refs/heads/master` or some such.
|
||||
|
||||
The result is a text field that the `access()` function returned.
|
||||
Programmatically, the only thing you should rely on is that if it contains
|
||||
the upper case word "DENIED" then access was denied, otherwise it was
|
||||
allowed.
|
||||
|
||||
* `PRE_GIT`: before running the git command.
|
||||
|
||||
Arguments: repo name, user name, [attempted access][perm], the string
|
||||
`any`, and the git command ('git-receive-pack', 'git-upload-pack', or
|
||||
'git-upload-archive') being invoked.
|
||||
|
||||
* `POST_GIT`: after the git command returns.
|
||||
|
||||
Arguments: same as for `PRE_GIT`, followed by the output of the perl
|
||||
function "times" (i.e., 4 CPU times: user, system, cumulative user,
|
||||
cumulative system)
|
||||
|
||||
* `POST_COMPILE`: after an admin push has successfully "compiled" the config
|
||||
file. By default, the next thing is to update the ssh authkeys file, then
|
||||
all the 'git-config's, gitweb access, and daemon access.
|
||||
|
||||
Programs run by this trigger receive no extra arguments.
|
||||
|
||||
* `PRE_CREATE` and `POST_CREATE`: before and after a new "[wild][]" repo is
|
||||
created by user action.
|
||||
|
||||
Arguments: repo name, user name.
|
96
doc/users.mkd
Normal file
96
doc/users.mkd
Normal file
|
@ -0,0 +1,96 @@
|
|||
# what users (not admins) need to know about gitolite
|
||||
|
||||
...written for the one guy in the world no one will think of as "just a normal
|
||||
user" ;-)
|
||||
|
||||
This document has some text, and a lot of links. Most of this info *is*
|
||||
available in the rest of the documentation, but it's scattered and sparse.
|
||||
Collecting all of it, or at least links to it, in one place sounds useful.
|
||||
|
||||
## accessing gitolite
|
||||
|
||||
The most common setup is based on ssh, where your admin asks you to send him
|
||||
your public key, and uses that to setup your access.
|
||||
|
||||
Your actual access is either a git command (like `git clone
|
||||
git@server:reponame`, and we won't be discussing these any more in this
|
||||
document), or an ssh command (like `ssh git@server info`).
|
||||
|
||||
Note that you do *not* get a shell on the server -- the whole point of
|
||||
gitolite is to prevent that!
|
||||
|
||||
## #info the info command
|
||||
|
||||
The only command that is *always* available to every user is the `info`
|
||||
command (run `ssh git@host info -h` for help), which tells you what version of
|
||||
gitolite and git are on the server, and what repositories you have access to.
|
||||
The list of repos is very useful if you have doubts about the spelling of some
|
||||
new repo that you know was setup.
|
||||
|
||||
## digression: two kinds of repos
|
||||
|
||||
Gitolite has two kinds of repos. Normal repos are specified by their full
|
||||
names in the config file. "Wildcard" repos are specified by a regex in the
|
||||
config file. Try the [`info` command][info] and see if it shows any lines
|
||||
that look like regex patterns, (with a "C" permission in addition to the "R"
|
||||
and the "W").
|
||||
|
||||
If you see any, it means you are allowed to create brand new repos whose names
|
||||
fit that pattern. When you create such a repo, your "ownership" of it (as far
|
||||
as gitolite is concerned) is *automatically* recorded by gitolite.
|
||||
|
||||
## other commands
|
||||
|
||||
### #perms set/get additional permissions for repos you created
|
||||
|
||||
The gitolite config may have several permissions lines for your repo, like so:
|
||||
|
||||
repo pub/CREATOR/..*
|
||||
RW+ = CREATOR
|
||||
RW = user1 user2
|
||||
R = user3
|
||||
|
||||
If that's all it had, you really can't do much. Any changes to access must be
|
||||
done by the administrator. (Note that "CREATOR" is a reserved word that gets
|
||||
expanded to your userid in some way, so the admin can literally add just the
|
||||
first two lines, and *every* authenticated user now has his own personal repo
|
||||
namespace, starting with `pub/<username>/`).
|
||||
|
||||
To give some flexibility to users, the admin could add rules like this:
|
||||
|
||||
RW = WRITERS
|
||||
R = READERS
|
||||
|
||||
(he could also add other roles but then he needs to read the documentation).
|
||||
|
||||
Once he does this, you can then use the `perms` command (run `ssh git@host
|
||||
perms -h` for help) to set permissions for other users by specifying which
|
||||
users are in the list of "READERS", and which in "WRITERS".
|
||||
|
||||
If you think of READERS and WRITERS as "roles", it will help. You can't
|
||||
change what access a role has, but you *can* say which users have that role.
|
||||
|
||||
**Note**: there isn't a way for you to see the actual rule set unless you're
|
||||
given read access to the special 'gitolite-admin' repo. Sorry. The idea is
|
||||
that your admin will tell you what "roles" he added into rules for your repos,
|
||||
and what permissions those roles have.
|
||||
|
||||
### #desc adding a description to repos you created
|
||||
|
||||
The `desc` command is extremely simple. Run `ssh git@host desc -h` for help.
|
||||
|
||||
## "site-local" commands
|
||||
|
||||
The main purpose of gitolite is to prevent you from getting a shell. But
|
||||
there are commands that you often need to run on the server (i.e., cannot be
|
||||
done by pushing something to a repo).
|
||||
|
||||
To enable this, gitolite allows the admin to setup scripts in a special
|
||||
directory that users can then run. Gitolite comes with a set of working
|
||||
scripts that your admin may install, or may use as a starting point for his
|
||||
own, if he chooses.
|
||||
|
||||
Think of these commands as equivalent to those in `COMMAND_DIR` in `man
|
||||
git-shell`.
|
||||
|
||||
You can get a list of available commands by running `ssh git@host help`.
|
254
doc/vref.mkd
Normal file
254
doc/vref.mkd
Normal file
|
@ -0,0 +1,254 @@
|
|||
# virtual refs
|
||||
|
||||
Here's an example to start you off.
|
||||
|
||||
repo r1
|
||||
RW+ = lead_dev dev2 dev3
|
||||
- VREF/COUNT/9 = dev2 dev3
|
||||
- VREF/COUNT/3/NEWFILES = dev2 dev3
|
||||
|
||||
Now dev2 and dev3 cannot push changes that affect more than 9 files at a time,
|
||||
nor those that have more than 3 new files.
|
||||
|
||||
Another example is detecting duplicate pubkeys in a push to the admin repo:
|
||||
|
||||
repo gitolite-admin
|
||||
# ... normal rules ...
|
||||
- VREF/DUPKEYS = @all
|
||||
|
||||
----
|
||||
|
||||
## rule matching recap
|
||||
|
||||
You won't get any joy out of this if you don't understand at least
|
||||
[refex][]es and how [rules][] are processed.
|
||||
|
||||
But VREFs have one **very important difference** from normal rules. With
|
||||
VREFs, a **fallthru results in success**. You'll see why this is more
|
||||
convenient as you read on.
|
||||
|
||||
----
|
||||
|
||||
## what is a virtual ref
|
||||
|
||||
A ref like `refs/heads/master` is the main property of a push that gitolite
|
||||
uses to make its yes/no decision. I call this a "real" ref.
|
||||
|
||||
Any *other* property of the push that you want to use to help in the decision
|
||||
is therefore a *virtual* ref. This could be a property that git knows about,
|
||||
like in the example above, or comes from outside git like, say, the current
|
||||
time; see examples section later for some ideas.
|
||||
|
||||
## fallthru is success here
|
||||
|
||||
Notice that you didn't need to add an `RW+ VREF/...` rule for user `lead_dev`
|
||||
in our example. This section explains why.
|
||||
|
||||
**Virtual refs are best used as additional "deny" rules**, performing extra
|
||||
checks that core gitolite cannot.
|
||||
|
||||
Making fallthru be a "fail" forces you to add rules for all users, instead of
|
||||
just the ones who should have those extra checks. Worse, since every virtual
|
||||
ref involves calling an external program, many of these calls may be wasted.
|
||||
|
||||
There's another advantage to doing it this way: a VREF can choose to simply
|
||||
die if things look bad, and it will have the same effect, assuming you used
|
||||
the VREF only in [deny][] rules.
|
||||
|
||||
This in turn means any existing update hook can be used as a VREF *as-is*, as
|
||||
long as it (a) prints nothing on success and (b) dies on failure. See the
|
||||
email-check and dupkeys examples later.
|
||||
|
||||
## how it works -- overview
|
||||
|
||||
Briefly, a refex starting with `VREF/FOO` triggers a call to a program called
|
||||
`FOO` in `$GL_BINDIR/VREF`.
|
||||
|
||||
That program is expected to print zero or more lines to its STDOUT; each line
|
||||
is taken by gitolite as a new "ref" to be matched against all the refexes for
|
||||
this user in the config. Including the refex that caused the vref call, of
|
||||
course.
|
||||
|
||||
Normally, you send back the refex itself, if the test determines that the rule
|
||||
should be matched, otherwise nothing. So, in our example, we print
|
||||
`VREF/COUNT/9` if the count was indeed greater than 9. Otherwise we just
|
||||
exit.
|
||||
|
||||
## how it works -- details
|
||||
|
||||
* the VREF code is only called if there are any VREF rules for the user,
|
||||
which means when the lead developer pushes, the VREF is not called at all.
|
||||
|
||||
Side note: this is enormously more efficient than adding additional
|
||||
`update` hooks, which will get executed whether they are needed or not,
|
||||
for every repo and every user!
|
||||
|
||||
* when dev2 or dev3 push, gitolite first checks the real ref
|
||||
(`ref/heads/master` or whatever). After this it looks at VREF rules, and
|
||||
calls an external program for every one it finds. Specifically, in a line
|
||||
like
|
||||
|
||||
- VREF/COUNT/3/NEWFILES = user
|
||||
|
||||
COUNT is the vref name, so the program called is
|
||||
`$GL_BINDIR/VREF/COUNT`.
|
||||
|
||||
The program is passed **nine arguments** in this case (see next section
|
||||
for details).
|
||||
|
||||
* the script can print anything it wants to STDOUT; the first word in each
|
||||
such line will be treated as a virtual ref to be matched against all the
|
||||
rules, while the rest, if any, is a message to be added to the standard
|
||||
"...DENIED..." message that gitolite prints if that refex matches.
|
||||
|
||||
Usually it only makes sense to either
|
||||
|
||||
* print nothing -- if you don't want the rule that triggered it to match
|
||||
(ie., whatever condition being tested was not violated; like if the
|
||||
count of changed files did not exceed 9, in our earlier example)
|
||||
* print the refex itself (plus an optional message), so that it matches
|
||||
the line which invoked it
|
||||
|
||||
### arguments passed to the vref code
|
||||
|
||||
* arguments **1, 2, 3**: the 'ref', 'oldsha', and 'newsha' that git passed
|
||||
to the update hook (see 'man githooks')
|
||||
|
||||
This, combined with the fact that non-zero exits are detected, mean that
|
||||
you can simply use an existing update.secondary as a new VREF as-is, no
|
||||
changes needed.
|
||||
|
||||
* arguments **4 and 5**: the 'oldtree' and 'newtree' SHAs. These are the
|
||||
same as the oldsha and newsha values, except if one of them is all-0.
|
||||
(indicating a ref creation or deletion). In that case the corresponding
|
||||
'tree' SHA is set (by gitolite, as a courtesy) to the special SHA
|
||||
`4b825dc642cb6eb9a060e54bf8d69288fbee4904`, which is the hash of an empty
|
||||
tree.
|
||||
|
||||
(None of these shenanigans would have been needed if `git diff $oldsha
|
||||
$newsha` would not error out when passed an all-0 SHA.)
|
||||
|
||||
* argument **6**: the attempted access flag. Typically `W` or `+`, but
|
||||
could also be `C`, `D`, or any of these 4 followed by `M`. If you have to
|
||||
ask what they mean, you haven't read enough gitolite documentation to be
|
||||
able to make virtual refs work.
|
||||
|
||||
* argument **7**: is the entire refex; in our example
|
||||
`VREF/COUNT/3/NEWFILES`.
|
||||
|
||||
* arguments **8 onward**: are the split out (by `/`) portions of the refex,
|
||||
excluding the first two components. In our example they would be `3`
|
||||
followed by `NEWFILES`.
|
||||
|
||||
Yes, argument 7 is redundant if you have 8 and 9. It's meant to make it easy
|
||||
to write vref scripts in any language. See script examples in source.
|
||||
|
||||
## what (else) can the vref code pass back
|
||||
|
||||
Actually, the vref code can pass anything back; each line in its output will
|
||||
be matched against all the rules as usual (with the exception that fallthru is
|
||||
not failure).
|
||||
|
||||
For example, you could have a ruleset like this:
|
||||
|
||||
repo r1
|
||||
# ... normal rules ...
|
||||
|
||||
- VREF/TIME/WEEKEND = @interns
|
||||
- VREF/TIME/WEEKNIGHT = @interns
|
||||
- VREF/TIME/HOLIDAY = @interns
|
||||
|
||||
and you could write the TIME vref code to passback any or all
|
||||
of the times that match. Then if an intern tried to access the system, each
|
||||
rule would trigger a call to gl-bindir/VREF/TIME.
|
||||
|
||||
The script should send back any of the applicable times (even more than one,
|
||||
or none at all, as the case may be). So even if it was invoked using the
|
||||
first rule, it might pass back (to gitolite) a virtual ref saying
|
||||
'VREF/TIME/HOLIDAY', which would promptly cause the request to be denied.
|
||||
|
||||
## VREFs shipped with gitolite
|
||||
|
||||
### number of new files
|
||||
|
||||
If a dev pushes more than 2 *new* files, the top commit needs to have a
|
||||
signed-off by line in its commit message. For example if he has 4 new files
|
||||
this text should be:
|
||||
|
||||
4 new files signed-off by: <top commit author's email>
|
||||
|
||||
The config entry for this is below (`NO_SIGNOFF` applies only to, and thus
|
||||
implies, `NEWFILES`):
|
||||
|
||||
RW+ VREF/COUNT/2/NO_SIGNOFF = sitaram
|
||||
- VREF/COUNT/2/NO_SIGNOFF = @all
|
||||
|
||||
Notice how the refex in both cases is *exactly* the same. If you make it
|
||||
different (even change the number on my access line), things won't work.
|
||||
|
||||
Junior devs can't push more than 10 new files, even with a signed-off by line:
|
||||
|
||||
- VREF/COUNT/10/NEWFILES = @junior_devs
|
||||
|
||||
### advanced filetype detection
|
||||
|
||||
Note: this is more for illustration than use; it's rather specific to one of
|
||||
the projects I manage but the idea is the important thing.
|
||||
|
||||
Sometimes a file has a standard extension (that cannot be 'gitignore'd), but
|
||||
it is actually automatically generated. Here's one way to catch it:
|
||||
|
||||
- VREF/FILETYPE/AUTOGENERATED = @all
|
||||
|
||||
You can look at `src/VREF/FILETYPE` to see how it handles the
|
||||
'AUTOGENERATED' option. You could also have a more generic option, like
|
||||
perhaps BINARY, and handle that in the FILETYPE vref too.
|
||||
|
||||
### checking author email
|
||||
|
||||
Some people want to ensure that "you can only push your own commits".
|
||||
|
||||
If you force it on everyone, this is a very silly idea (see "Philosophical
|
||||
Notes" section of `src/VREF/EMAIL-CHECK`).
|
||||
|
||||
But there may be value in enforcing it just for the junior developers.
|
||||
|
||||
The neat thing is that the existing `contrib/update.email-check` was just
|
||||
copied to `src/VREF/EMAIL-CHECK` and it works, because VREFs get
|
||||
the same first 3 arguments and those are all that it cares about. (Note: you
|
||||
have to change one subroutine in that script if you want to use it)
|
||||
|
||||
### catching duplicate pubkeys
|
||||
|
||||
We covered this as a teaser example at the start.
|
||||
|
||||
## other ideas -- code welcome!
|
||||
|
||||
### "no non-merge first-parents"
|
||||
|
||||
Shruggar on #gitolite wanted this. Possible code to implement it would be
|
||||
something like this (untested)
|
||||
|
||||
[ -z "$(git rev-list --first-parent --no-merges $2..$3)" ]
|
||||
|
||||
This can be implemented using `src/VREF/MERGE-CHECK` as a model.
|
||||
That script does what the 'in core' feature called [merge check][mergecheck]
|
||||
does, although the syntax to be used in conf/gitolite will be quite different.
|
||||
|
||||
### other ideas for VREFs
|
||||
|
||||
Here are some more ideas:
|
||||
|
||||
* number of commits (`git rev-list --count $old $new`)
|
||||
* number of binary files in commit (currently I only know to count
|
||||
occurrences of ` Bin ` in the output of `git diff --stat`
|
||||
* number of *new* binary files (count ` Bin 0 ->` in `git diff --stat`
|
||||
output)
|
||||
* time of day/day of week (see example snippet somewhere above)
|
||||
* IP address
|
||||
* phase of the moon
|
||||
|
||||
Note that pretty much anything that involves `$oldsha..$newsha` will have to
|
||||
deal with the issue that when you push a new tag or branch, the "old" part
|
||||
is all 0's, and unless you consider `--all` existing branches and tags it
|
||||
becomes meaningless in terms of "number of new files" etc.
|
46
doc/why.mkd
Normal file
46
doc/why.mkd
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Why is gitolite needed?
|
||||
|
||||
Gitolite is separate from git, and needs to be installed and configured. So...
|
||||
why do we bother?
|
||||
|
||||
Gitolite is useful in any server that is going to host multiple git
|
||||
repositories, each with many developers, where some sort of access control is
|
||||
required.
|
||||
|
||||
In theory, this can be done with plain old Unix permissions: each user is a
|
||||
member of one or more groups, each group "owns" one or more repositories, and
|
||||
using unix permissions (especially the setgid bit -- `chmod g+s`) you can
|
||||
allow/disallow users access to repos.
|
||||
|
||||
But there are several disadvantages here:
|
||||
|
||||
* every user needs a userid and password on the server. This is usually a
|
||||
killer, especially in tightly controlled environments
|
||||
* adding/removing access rights involves complex `usermod -G ...` mumblings
|
||||
which most admins would rather not deal with
|
||||
* *viewing* (aka auditing) the current set of permissions requires running
|
||||
multiple commands to list directories and their permissions/ownerships,
|
||||
users and their group memberships, and then correlating all these manually
|
||||
* auditing historical permissions or permission changes is pretty much
|
||||
impossible without extraneous tools
|
||||
* errors or omissions in setting the permissions exactly can cause problems
|
||||
of either kind: false accepts or false rejects
|
||||
* without going into ACLs it is not possible to give some people read-only
|
||||
access while some others have read-write access to a repo (unless you make
|
||||
it world-readable). Group access just doesn't have enough granularity
|
||||
* it is absolutely impossible to restrict pushing by branch name or tag
|
||||
name.
|
||||
|
||||
Gitolite does away with all this:
|
||||
|
||||
* it uses ssh magic to remove the need to give actual unix userids to
|
||||
developers
|
||||
* it uses a simple but powerful config file format to specify access rights
|
||||
* access control changes are affected by modifying this file, adding or
|
||||
removing user's public keys, and "compiling" the configuration
|
||||
* this also makes auditing trivial -- all the data is in one place, and
|
||||
changes to the configuration are also logged, so you can audit them.
|
||||
* finally, the config file allows distinguishing between read-only and
|
||||
read-write access, not only at the repository level, but at the branch
|
||||
level within repositories.
|
||||
|
31
doc/write-types.mkd
Normal file
31
doc/write-types.mkd
Normal file
|
@ -0,0 +1,31 @@
|
|||
## #write-types different types of write operations
|
||||
|
||||
Git supplies enough information to the update hook to be able to distinguish
|
||||
several types of writes.
|
||||
|
||||
The most common are:
|
||||
|
||||
* `RW` -- create a ref or fast-forward push a ref. No rewinds or deletes.
|
||||
* `RW+` -- create, fast-forward push, rewind push, or delete a ref.
|
||||
|
||||
Sometimes you want to allow people to push, but not *create* a ref. Or
|
||||
rewind, but not *delete* a ref. The `C` and `D` qualifiers help here.
|
||||
|
||||
* when a rule specifies `RWC` or `RW+C`, then *rules that do NOT have the C
|
||||
qualifier will no longer permit **creating** a ref*
|
||||
|
||||
<font color="gray">Please do not confuse this with the standalone `C`
|
||||
permission that allows someone to [create][] a **repo**</font>
|
||||
|
||||
* when a rule specifies `RWD` or `RW+D`, then *rules that do NOT have the C
|
||||
qualifier will no longer permit **deleting** a ref*
|
||||
|
||||
Note: These two can be combined, so you can have `RWCD` and `RW+CD` as well.
|
||||
|
||||
One very rare need is to reject merge commits (a commit series that is not a
|
||||
straight line of commits). The `M` qualifier helps here:
|
||||
|
||||
* When a rule has `M` appended to the permissions, *rules that do NOT have
|
||||
it will reject a commit sequence that contains a merge commit* (i.e., they
|
||||
only accept a straight line series of commits).
|
||||
|
31
dot.pl
Normal file
31
dot.pl
Normal file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my @a = `grep -r use.Gitolite . | grep -i '^./gitolite'`;
|
||||
|
||||
# chomp(@a);
|
||||
open( my $fh, "|-", "tee module-tree.gv | dot -Tpng | tee module-tree.png | display" );
|
||||
|
||||
@a = map {
|
||||
print $fh "#$_";
|
||||
s/^\.\/gitolite\///i;
|
||||
s/-/_/g;
|
||||
s/\.\///;
|
||||
s/\//_/g;
|
||||
s/\.pm:/ -> /;
|
||||
s/use Gitolite:://;
|
||||
s/::/_/g;
|
||||
s/:/ -> /;
|
||||
s/;//;
|
||||
s/^(\S+) -> \1$//;
|
||||
s/.* -> Rc//;
|
||||
s/.* -> Common//;
|
||||
$_;
|
||||
} @a;
|
||||
|
||||
# open(my $fh, "|-", "cat > /tmp/junkg3");
|
||||
print $fh "digraph G {\n";
|
||||
print $fh $_ for @a;
|
||||
print $fh "}\n";
|
||||
close $fh;
|
Loading…
Reference in a new issue