Golem provides an easy way to host and manage access to git repositories on a server under a single user.

Gem and library name

The library name is Golem, but the gem is called gitgolem. After installing you could require either 'golem' or 'gitgolem'.

How it works

Golem's main goals are:

Golem is not designed to handle complex access rules, altough it may be extended to achieve that. If you need more refined rules, like per-branch or per-path control you should check out gitolite, which has far superior features in this regard.

The git flow that golem supports is:


Golem supports the following configuration variables:

Git and .ssh/authorized_keys

Git supports SSH as the transport protocol for pulling and pushing, and assumes SSH for remotes like user@server:/path/to/project.git. With ssh remotes git executes remote commands, like git-receive-pack '/path/to/project.git' (this is stored in SSH_ORIGINAL_COMMAND environment variable for the curious) when doing something like git clone user@server:/path/to/project.git. Golem authorizes users so it must act before the actual git command runs. Key-based authentication is very popular and the .ssh/authorized_keys file allows a few possibilities to achieve what golem tries to do, so it seems a natural fit. Please note: golem won't work without key-based authentication, as it relies content placed in the .ssh/authorized_keys file.

Golem by default requires that you (control your SSHD's options and) set the users shell to golem-shell (wherever it is installed) that is "hosting" the repositories. With that setup golem can simply place lines like environment="GOLEM_USER=username" ssh-dss AAA... (where AAA... is the key) in the .ssh/authorized_keys file and golem-shell simply reads that environment variable. (Please note: SSHD by default does not permit changing environment variables, you have to enable it with setting PermitUserEnvironment to yes.) However this needs that the user's shell is set to golem-shell, so golem provides a configuration variable, if you can't or simply don't want to change the user's shell. When keys_file_use_command is true golem writes lines like command="/path/to/golem auth 'username'" ssh-dss AAA... instead. Please note:

Golem supports another configuration variable called keys_file_ssh_opts, which is simply placed after the environment="" or command="" block. If keys_file_use_command is false (using environment="") golem simply injects the string into the lines, however if keys_file_use_command is true and keys_file_ssh_opts is not set (is nil) golem uses Golem::Command::UpdateKeysFile::SSH_OPTS_COMMAND_DEFAULT (if it is not nil golem uses the configuration value). The reasoning behind this distinction is golem assumes you control your SSHD's settings if using environment="", but you may not (want to) set (global) restrictions when using command="". The final line looks something like environment="GOLEM_USER=username",ssh,opts ssh-dss AAA... or command="/path/to/golem auth 'username'",ssh,opts ssh-dss AAA....

Please note: golem does not overwrite the whole .ssh/authorized_keys file.

Access control

Golem's access control by default is very simple. It assumes a repository belongs to a single user, so it grants access to a given repository only to its owner. For a very basic setup this should be enough. However for more complex setup golem does not want to assume how you want to store your users and repositories, so it simply doesn't. You can fine tune your environment to suit your specific needs with overriding Golem::Access.check (its arguments are the username, the repository name and the git command to run (e.g. one of upload-pack, upload-archive and receive-pack)).

Golem's access control is done at the very beginning, before git-shell is run, so it's not suitable for per-branch or per-directory control. This can be achieved by hooks. You should check out gitolite, which supports exactly that (and more). If you want you can place gitolite's hooks in golem's hooks_dir and achieve the same results (this requires deeper understanding of git, so please be aware).

Public access

Golem does not support providing public (read-only anonymous) access to git repositories as it relies on SSH's key-based authentication. However there are a couple of alternatives to solve this, with each having its pros and cons: serving the repository as a static website, using GitWeb or using Git Daemon.


Golem currently supports postgres and a static databases only, but it should be trivial to extend it (contributions are always welcome). At least users and repositories should have names, keys should have an attribute named key that is the whole key (e.g. cat id_rsa.pub).

The static database is suitable for small installations (where an rdbms would be an overkill), to use it simply write:

Golem.configure do |cfg|
  cfg.db = 'static'
  Golem::DB.setup do |db|
    db.add_user 'test_user'
    db.add_repository 'test_repository', 'test_user'
    db.add_key 'test_user', 'test_key'

The postgres database stores data in 3 tables (users, repositories, keys) by default, and can be used with setting the db variable to the postgres url (e.g. postgres://user:pw@host/db). A sample schema can be found in lib/golem/db/postgres.sql, and it is imported by Golem::DB::Pg#setup (please note: Golem::DB.setup forwards to it, should be called only once). A minimal setup for postgres would be:

Golem.configure do |cfg|
  cfg.db = "postgres://user:pwd@host/dbname"
  cfg.bin_dir = "/usr/local/bin"

A more complex setup with collaborators:

Golem.configure do |cfg|
  Golem::DB::Pg.class_eval do
    #add method to query collaborators
    def collaborators(opts = {})
      opts[:table] = "collaborators join users on collaborators.user_name=users.name"

    #add method to check if user is a collaborator of a given repository
    def collaborator?(user, repo)
      collaborators(:user_name => user, :repository_name => repo, :fields => :name).length > 0

    #override setup to add our collaborators table
    alias_method :setup_orig, :setup
    def setup
      @connection.exec("CREATE TABLE collaborators (user_name varchar(32) NOT NULL REFERENCES users (name), repository_name varchar(32) NOT NULL REFERENCES repositories (name), PRIMARY KEY (user_name, repository_name));")
  Golem::DB.class_eval do
    #add method proxy to check collaborator status
    def self.collaborator?(user, repo)
      db.collaborator?(user, repo)
  Golem::Access.class_eval do
    #override check to grant access to collaborators
    class << self; alias_method :check_orig, :check end
    def self.check(user, repo, gitcmd)
      Golem::DB.collaborator?(user, repo) || check_orig(user, repo, gitcmd)
  cfg.db = 'postgres://user:pwd@host/dbname'


Golem provides an executable, and supports a few commands to easily automate the administration:

You can get details about commands running golem -h or --help.

Golem provides another executable called golem-shell, which is a convenience script that calls golem auth.

Contributing to golem


Copyright (c) 2011 PoTa. See LICENSE.txt for further details.