Setup your own git hosting service

Last modification on

This article assumes you use OpenBSD for the service files and OS-specific examples.

Why

A good reason to host your own git repositories is because of having and keeping control over your own computing infrastructure.

Some bad examples:

The same thing can happen with Github, Atlassian Bitbucket or other similar services. After all: they are just a company with commercial interests. These online services also have different pricing plans and various (arbitrary) restrictions. When you host it yourself the restrictions are the resource limits of the system and your connection, therefore it is a much more flexible solution.

Always make sure you own the software (which is Free or open-source) and you can host it yourself, so you will be in control of it.

Creating repositories

For the hosting it is recommended to use a so-called "bare" repository. A bare repository means no files are checked out in the folder itself. To create a bare repository use git init with the --bare argument:

$ git init --bare

I recommend to create a separate user and group for the source-code repositories. In the examples we will assume the user is called "src".

Login as the src user and create the files. To create a directory for the repos, in this example /home/src/src:

$ mkdir -p /home/src/src
$ cd /home/src/src
$ git init --bare someproject
$ $EDITOR someproject/description

Make sure the git-daemon process has access permissions to these repositories.

Install git-daemon (optional)

Using git-daemon you can clone the repositories publicly using the efficient git:// protocol. An alternative without having to use git-daemon is by using (anonymous) SSH, HTTPS or any public shared filesystem.

When you use a private-only repository I recommend to just use SSH without git-daemon because it is secure.

Install the git package. The package should contain "git daemon":

# pkg_add git

Enable the daemon:

# rcctl enable gitdaemon

Set the gitdaemon service flags to use the src directory and use all the available repositories in this directory. The command-line flags "--export-all" exports all repositories in the base path. Alternatively you can use the "git-daemon-export-ok" file (see the git-daemon man page).

# rcctl set gitdaemon flags --export-all --base-path="/home/src/src"

To configure the service to run as the user _gitdaemon:

# rcctl set gitdaemon user _gitdaemon

To run the daemon directly as the user _gitdaemon (without dropping privileges from root to the user) set the following flags in /etc/rc.d/gitdaemon:

daemon_flags="--user=_gitdaemon"

Which will also avoid this warning while cloning:

"can't access /root/.git/config"

Now start the daemon:

# rcctl start gitdaemon

Cloning and fetching changes

To test and clone the repository do:

$ git clone git://yourdomain/someproject

if you skipped the optional git-daemon installation then just clone via SSH:

$ git clone ssh://youraccount@yourdomain:/home/src/src/someproject

When cloning via SSH make sure to setup private/public key authentication for security and convenience.

You should also make sure the firewall allows connections to the services like the git daemon, HTTPd or SSH, for example using OpenBSD pf something like this can be set in /etc/pf.conf:

tcp_services="{ ssh, gopher, http, https, git }"
pass in on egress proto tcp from any to (egress) port $tcp_services

Pushing changes

Add the repository as a remote:

$ git remote add myremote ssh://youraccount@yourdomain:/home/src/src/someproject

Then push the changes:

$ git push myremote master:master

Git history web browsing (optional)

Sometimes it's nice to browse the git history log of the repository in a web browser or some other program without having to look at the local repository.

It's also possible with these tools to generate an Atom feed and then use a RSS/Atom reader to track the git history:

My sfeed program can be used as a RSS/Atom reader.

Setting up git hooks (optional)

Using git hooks you can setup automated triggers, for example when pushing to a repository. Some useful examples can be: