Gitano – git hosting with ACLs and other shininess
3 minutes read

gitano is not entirely unlike the non-web, server side of github. It allows you to create and manage users and their SSH keys, groups and repositories from the command line. Repositories have ACLs associated with them. Those can be complex (“allow user X to push to master in the doc/ subtree) or trivial (“admin can do anything”). Gitano is written by Daniel Silverstone, and I’d like to thank him both for writing it and for holding my hand as I went stumbling through my initial gitano setup.

Getting started with Gitano can be a bit tricky, as it’s not yet packaged and fairly undocumented. Until it is packaged, it’s install from source time. You need luxio, lace, supple, clod, gall and gitano itself.

luxio needs a make install LOCAL=1, the others will be installed to /usr/local with just make install.

Once that is installed, create a user to hold the instance. I’ve named mine git, but you’re free to name it whatever you would like. As that user, run gitano-setup and answer the prompts. I’ll use as the host name and john as the user I’m setting this up for.

To create users, run ssh user add john John Doe, then add their SSH key with ssh as john sshkey add workstation < /tmp/

To create a repository, run ssh repo create myrepo. Out of the box, this only allows the owner (typically “admin”, unless overridden) to do anything with it. To change ACLs, you’ll want to grab the refs/gitano/admin branch. This lives outside of the space git usually use for branches, so you can’t just check it out. The easiest way to check it out is to use git-admin-clone. Run it as git-admin-clone ~/myrepo-admin and then edit in ~/myrepo-admin. Use git to add, commit and push as normal from there.

To change ACLs for a given repo, you’ll want to edit the rules/main.lace file. A real-world example can be found in the NetSurf repository and the lace syntax might be useful. A lace file consists of four types of lines:

  • Comments, start with – or #
  • defines, look like define name conditions
  • allows, look like allow "reason" definition [definition…]
  • denials, look like deny "reason" definition [definition…]

Rules are processed one by one, from the top and terminate whenever a matching allow or deny is found.

Conditions can either be matches to an update, such as ref refs/heads/master to match updates to the master branch. To create groupings, you can use the anyof or allof verbs in a definition. Allows and denials are checked against all the definitions listed and if all of them match, the appropriate action is taken.

Pay some attention to what conditions you group together, since a basic operation (is_basic_op, aka op_read and op_write) happens before git is even involved and you don’t have a tree at that point, so rules like:

define is_master ref refs/heads/master
allow "Devs can push" op_is_basic is_master

simply won’t work. You’ll want to use a group and check on that for basic operations and then have a separate rule to restrict refs.

Back to posts