Gitosis for kittens
Gitosis is a great way to super-securely provide repository management for teams. However, there's a few points at which it kind of falls on its face.
Creating new repositories requires write-access to gitosis-admin
Forking teammate's repositories basically requires you to write a script to handle adding the
readonly
andwriteable
bits to every existing user's group. Past a team of two, this quickly gets unmaintainable.In my opinion, it tries to do too much. It handles git, it handles auth, it handles what happens when the ssh command comes in from OpenSSH — it's monolithic.
With these points in mind, I set out to chop all of these little pieces of functionality
up into little, single-concern bits. I ended up with three projects, Nappingcat, Kittygit,
and Felix. These projects slice gitosis functionality into two app-level constructs, and
one framework-level project. Nappingcat
is the framework; it provides functionality for
routing SSH commands and hooks for loading a simple auth backend. Kittygit
is the git functionality;
it knows how to speak to git, and provides a few niceties like creation of repositories and forking
of existing repositories over the wire. Felix
is the last (and probably most experimental piece),
providing an authentication backend based around a JSON flat file, and providing over-the-wire
commands for creating new users, adding SSH keys to those users, and granting permissions
to the users.
Introducing Nappingcat
the archetypical cat
Setting things up with nappingcat isn't immensely hard. It basically follows these easy steps:
- Clone the nappingcat repository.
- Run
sudo setup.py install
to provide everyone thenappingcat-serve
command. Create a new user
useradd -m \ # create a home directory -U \ # create a new group for the user -s /bin/bash \ -r \ # it's a system account. git # the name of the user
Clone kittygit and felix into the new user's home directory.
Open up
~/nappingcat.conf
, fill out the following data:[kittyconfig] routers = kittygit.patterns felix.patterns auth = felix.JSONAuth paths = /home/<your git user>/kittygit /home/<your git user>/felix <wherever you installed nappingcat> [kittygit] git = /usr/bin/git repo_dir = ~/repos user = <your git user> host = <the externally accessible url for this server> [jsonauth] file = ~/auth.json
Create a basic auth.json layout using the felix/bin/create_superuser file.
cd ~/felix cat ~/.ssh/id_rsa.pub | python bin/create_superuser.py YOUR_USERNAME > ~/auth.json
Great! Back to your computer. Put this at the end of your
~/.bashrc
, andsource ~/.bashrc
kittygit() { case $1 in create) ssh git@unbearablecomics.com "kitty-git create-repo '$2'" ;; fork) ssh git@unbearablecomics.com "kitty-git fork '$2/$3.git'" ;; grant) ssh git@unbearablecomics.com "add-permission $2 '$3'" ;; revoke) ssh git@unbearablecomics.com "remove-permission $2 '$3'" ;; adduser) ssh git@unbearablecomics.com "add-user $2" ;; addkey) ssh git@unbearablecomics.com "add-key-to-user $2" ;; esac }
Give yourself the right to create repositories:
$ kittygit grant YOUR_USERNAME kittygit::create
creating repos
like a boss
Creating repos is easy enough at this point. It's just kittygit create reponame
. Kittygit will
send you back an beautifully green message saying "oh hey, here's the repo to clone." Go ahead and
clone it. Things are great!
kittygit create garybusey
But oh wait. No one is around to care. Maybe it's time to populate this lonely little cat-themed world. Let's pretend your name is "William Howard Taft", and you have a friend, "Harry Truman."
kittygit adduser harrytruman
cat harry_trumans_id_rsa.pub | kittygit addkey harrytruman
kittygit grant harrytruman kittygit::read::williamhowardtaft/garybusey
Now your friend has access to read your repository. Your friend, we'll call him If he or she installs the kittygit bash function above, working with your code is now as easy as:
kittygit fork williamhowardtaft garybusey
git clone git@example.com:harrytruman/garybusey.git
# BAM INSTANT GARY BUSEY
kittygit grant williamhowardtaft kittygit::read::harrytruman/garybusey
And now Harry Truman can tell Taft — casually over a light lunch, perhaps — that Taft can add his copy of garybusey as a remote.