Install and Configure a Public git Repository

url:http://tjworld.net/wiki/Howto/GitPublicRepositoryInstallAndConfigure

This explains how to install and configure a public git server that can host multiple projects providing read-only anonymous access and read/write for authenticated commiters, along with the gitweb web-browser interface.

Install

On Ubuntu this is quite simple:

sudo apt-get install git-core git-daemon-run gitweb

You might want to update to the latest version from git's own repository:

git clone git://git.kernel.org/pub/scm/git/git.git
cd git

Build the latest release

Easy way to ensure build dependencies are installed for stand-alone source that has an earlier Ubuntu/Debian package:

sudo apt-get build-dep git-core

Build using the same options as the Ubuntu package uses (extracted from Ubuntu build logs):

/usr/bin/make all test \
CC='gcc' CFLAGS='-g -Wall -O2' NO_OPENSSL=1 GITWEB_CONFIG=/etc/gitweb.conf \
prefix=/usr mandir=/usr/share/man INSTALLDIRS=vendor WITH_P4IMPORT=1 \
PYTHON_PATH=/usr/bin/python TCLTK_PATH=/usr/bin/wish8.4

/usr/bin/make -CDocumentation man ASCIIDOC8=YesPlease

/usr/bin/make -CDocumentation man html ASCIIDOC8=YesPlease

Install using the same options

::
usr/bin/make install install-doc CC='gcc' CFLAGS='-g -Wall -O2' NO_OPENSSL=1 GITWEB_CONFIG=/etc/gitweb.conf prefix=/usr mandir=/usr/share/man INSTALLDIRS=vendor WITH_P4IMPORT=1 PYTHON_PATH=/usr/bin/python TCLTK_PATH=/usr/bin/wish8.4

Configure Firewall

These rules need adding to the netfilters/iptables start-up scripts (usually in /etc/iptables.up.rules).

Allow access to port 9418 for TCP

# git-daemon -A INPUT -p tcp -m tcp --dport 9418 -j ACCEPT

To provide secure encrypted authenticated access for commiters you might want to ensure SSH (port 22) is allowed. (However, in some circumstances it is better to leave port 22 closed on public interfaces and only provide SSH access through a virtual private network tunnel using OpenVPN or similar):

# For git over ssh (allows push) -A INPUT -p tcp -m tcp -s 84.12.34.240/29 --dport 22 -j ACCEPT

Ensure the firewall rules are being enabled when the network starts. Usually that is using a post-up rule in the network configuration.

/etc/network/interfaces

# The first network card - this entry was created during the Debian installation # (network, broadcast and gateway are optional) iface eth0 inet static

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 75)

Unexpected indentation.
address 10.1.2.3 netmask 255.255.255.0 gateway 10.1.2.254 post-up iptables-restore < /etc/iptables.up.rules

git-daemon ¶

The git-daemon-run package installs a runit service in /etc/sv/git-daemon/. Edit the run file and set the paths for virtual hosting. Because I provide for a git repository for each domain account I use the interpolated-path option to extract the hostname the git client connected to and build the path based on it. This is rather like apache's VirtualHost where the site presented is determined by checking the Host: header. In this case it is git repositories not web sites that can share the same IP address:

/etc/sv/git-daemon/run

#!/bin/sh exec 2>&1 echo 'git-daemon starting.' exec git-daemon --verbose --base-path=/home --interpolated-path=/home/%H/git%D

Create per-account directories ¶

First create 'base' directories in all home directories with correct ownership:

sudo su

awk -F: '$3 > 999 && substr($6,1,5) == "/home" {print $3,$4,$6}' /etc/passwd | while read account;
do AUID=${account%% * /home*}; AGUID=$(expr "${account}" : '.* ([0-9]+) .*'); DIR=${account##* }; [ ! -e ${DIR}/git ] && mkdir ${DIR}/git && chown $AUID:$AGUID ${DIR}/git; done

exit

Or, if doing it manually for each user account:

cd ~ mkdir git

Create repositories ¶

Create empty repository and make it ready for public access. Set ${HOST_DOMAIN} and ${PROJECT} appropriately:

export GIT_DIR="/home/${HOST_DOMAIN}/git/${PROJECT}.git" git-init

Enable public access ¶

To enable a repository to be available to anonymous public access:

touch $GIT_DIR/git-daemon-export-ok

Enable gitweb ¶

The Perl git-web script allows web-browsing of the repository. After following these instructions it will be available at http://${HOST_DOMAIN}/perl/gitweb.cgi ==== Name the repository ==== To avoid gitweb reporting the project name as:

Unnamed repository; edit this file to name it for gitweb.

Edit the repository's description file and make it more descriptive:

echo "Experimental branch" > ${GIT_DIR}/description

Install Perl prerequisites ¶

Some preparation is required to support gitweb fully. The primary issue is that if the apache VirtualHost is using suexec to impose security it is not possible to pass environment variables to CGI scripts, and therefore gitweb can't be told to use a per-account configuration using GITWEB_CONFIG. An additional issue is that by default all Perl scripts will be handled by the cgi-bin handler mod_cgid. For performance it would be better to have mod_perl installed.

Install mod_perl and supporting Perl bundles needed by apache:

sudo apt-get install libapache2-mod-perl2

Create a server-wide apache Perl configuration that expects Perl scripts in the directory /perl/ of each VirtualHost. As root create this file:

/etc/apache2/mods-available/perl.conf

PerlModule ModPerl::Registry <Location /perl/>

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 145)

Unexpected indentation.
SetHandler perl-script PerlHandler ModPerl::Registry Options +ExecCGI PerlSendHeader On allow from all

System Message: WARNING/2 (data/howto-install-and-configure-git-public-repository.txt, line 150)

Block quote ends without a blank line; unexpected unindent.

</Location>

Create a symbolic link to it so apache reads it at start-up:

sudo su cd /etc/apache2/mods-enabled ln -s ../mods-available/perl.conf perl.conf exit

Per-account gitweb configuration ¶

In the user directory create a directory to hold Perl scripts and then link to the Perl gitweb.cgi:

cd ~ mkdir perl ln -s /usr/lib/cgi-bin/gitweb.cgi perl/gitweb.cgi

Copy the default configuration file so the site settings can be customised:

cp /etc/gitweb.conf git/gitweb.conf

Edit git/gitweb.conf and set values for the user account. Set the path to the supporting files to something other than the root of the web site to avoid clutter. Comment out the favicon setting if the site is using its own. Replace ${HOST_DOMAIN} with the correct path:

# path to git projects (<project>.git) $projectroot = "/home/${HOST_DOMAIN}/git";

# directory to use for temp files $git_temp = "/tmp";

# target of the home link on top of all pages $home_link = $my_uri;

# html text to include at home page $home_text = "indextext.html";

# file with project list; by default, simply scan the projectroot dir. $projects_list = $projectroot;

# stylesheet to use $stylesheet = "/style/gitweb.css";

# logo to use $logo = "/media/git-logo.png";

# the 'favicon' # $favicon = "/media/git-favicon.png";

Create the new web-site directories and link to the gitweb files (ensures any package updates will be reflected immediately).

cd ~ mkdir public_html/style public_html/media ln -s /var/www/gitweb.css public_html/style/gitweb.css ln -s /var/www/git-logo.png public_html/media/git-logo.png ln -s /var/www/git-favicon.png public_html/media/git-favicon.png

Add the GITWEB_CONFIG environment variable to the web-site's configuration file so that gitweb uses per-site configuration rather than the global configuration set in /etc/gitweb.conf. Replace ${HOST_DOMAIN} with the correct path.

/etc/apache2/sites-available/${HOST_DOMAIN}.conf

SetEnv GITWEB_CONFIG /home/${HOST_DOMAIN}/git/gitweb.conf

Use ¶ Updating the Public Repository ¶

To push your local private repository to the remote public repository there are several options. If you have enabled SSH access then:

To update the remote branch master from the local branch of the same name:

cd /home/all/Projects/packeteer

git push ssh://tjworld.net@tjworld.net/~tjworld.net/git/packeteer.git master Password: Counting objects: 21, done. Compressing objects: 100% (21/21), done. Writing objects: 100% (21/21), 5.47 MiB | 42 KiB/s, done. Total 21 (delta 2), reused 0 (delta 0) refs/heads/master: 0000000000000000000000000000000000000000 -> f499ede17792694ddcd25fed589e794a72ee35fa To ssh://tjworld.net@tjworld.net/~tjworld.net/git/packeteer.git

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 228)

Unexpected indentation.
  • [new branch] master -> master

If you don't use public ssh but have a VPN connection then you might do something like this:

cd ~ mkdir remote # mount remote server in local file-system sshfs tjworld.net@vpn.lan.tjword.net ~/remote

cd /home/all/Projects/packeteer

git status # On branch master nothing to commit (working directory clean)

git push ~/remote/git/packeteer.git master

Note: This method of using an sshfs mount seems to confuse git. It seems to take much longer to push the change, and it creates a new local branch entry that matches the remote repository path. For that reason it is better to use the ssh protocol but to the private VPN host:

git push ssh://tjworld.net@vpn.lan.tjworld.net/~tjworld.net/git/packeteer.git master

Cloning Public Repository by Other Developers ¶

Anyone who wants a copy of the public repository does a simple clone:

git clone git://tjworld.net/packeteer.git

Collaborating ¶

If another developer has a clone of the public repository already and you have published a change, they update using:

git fetch

If you are testing experimental code you might have a branch for it:

git branch experimental git checkout experimental Switched to branch "experimental"

echo "Editing files for experimental code" >> changelog

git add changelog git commit -a -s -m "Experimental commit" Created commit 98bc7fa: Experimental commit

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 272)

Unexpected indentation.
1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 changelog

git push ~/remote/git/packeteer.git experimental Counting objects: 4, done. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 357 bytes, done. Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. To ~/remote/git/packeteer.git

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 282)

Unexpected indentation.
  • [new branch] experimental -> experimental

The other developer might then update their clone:

git fetch remote: Counting objects: 4, done. remote: Compressing objects: 100% (2/2)remote: , done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From git://tjworld.net/packeteer.git

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 292)

Unexpected indentation.
  • [new branch] experimental -> origin/experimental
git branch -r
origin/HEAD origin/experimental origin/master

git checkout origin/experimental Note: moving to "origin/experimental" which isn't a local branch If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example:

System Message: ERROR/3 (data/howto-install-and-configure-git-public-repository.txt, line 303)

Unexpected indentation.
git checkout -b <new_branch_name>

System Message: WARNING/2 (data/howto-install-and-configure-git-public-repository.txt, line 304)

Block quote ends without a blank line; unexpected unindent.

HEAD is now at 98bc7fa... Experimental commit

git log -1 commit 98bc7fa8777160f0849b4e78f8522a9ae9ce2497 Author: TJ <linux@tjworld.net> Date: Sun Apr 20 20:24:30 2008 +0100

Experimental commit

Signed-off-by: TJ <linux@tjworld.net>

Quickly Create New Public Project Repository ¶

GIT_DIR="/home/${HOST_DOMAIN}/git/${PROJECT}.git" git-init touch $GIT_DIR/git-daemon-export-ok echo "Project Name" > ${GIT_DIR}/description