How to setup a GIT server with gitosis and gitweb

The goals are:

  • Host several projects with gitand access them via ssh, with the option of adding other developerswith push rights on a per-project basis.
  • Allow anonymous cloning via http and git protocols, andexpose a web interface to browse the repositories.
  • Optionally enable Clean URLs also inside the web interface to the git repository.This is also what git-notifyexpects when creating links to commits.

Our git repositories will be administered using gitosis they will go in /home/git/repositories and ourgitweb interface will be at http://git.example.com.

This guide andthis other oneexplain the process in full detail, I simplified the steps abit and adjusted some configuration to my taste.

Contents

Basic setup

As root:

aptitude install git-core

Use a git user for anything related to git.

sudo adduser \
    --system \
    --shell /bin/bash \
    --gecos 'git SCM user' \
    --group \
    --disabled-password \
    --home /home/git \
    git

Put repositories in /home/git/repositories

sudo -u git mkdir /home/git/repositories

Configuring gitosis

Create a ssh key (anywhere you want) for gitosis administration and copy it on the server, (if youalready have one that will be OK, of course):

ssh-keygen -t rsa
scp /home/myuser/.ssh/id_rsa.pub ${SERVER_IP}:myuser.pub

We assume the myuser user will administer gitosis.

On the server install gitosis and initialize it:

aptitude install gitosis
sudo -H -u git gitosis-init < /path/to/myuser.pub
sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

Then, on a client machine, as the user relative to the key you used before, run:

git clone git@git.example.com:gitosis-admin.git
cd gitosis-admin/

look at the address, the git in front of @ is theuser previously added to the server and git.example.com is theaddress of the machine hosting the git repositories (you can use the IPaddress if you haven't configured the DNS yet), this command will use sshtransport to transfer data, so if you have a firewall on your server it mustallow ssh traffic.

Add more pubkeys in keys/ and/or edit gitosis.conf as needed, see also/usr/share/doc/gitosis/README.rst.gz and/usr/share/doc/gitosis/examples/example.conf for more details.

We now add a test repository and a group of users who can access it, the result is something like:

[gitosis]
gitweb = yes
daemon = yes
 
# Only during testing phase
loglevel = DEBUG
 
[group gitosis-admin]
writable = gitosis-admin
members = myuser
 
[repo gitosis-admin]
gitweb = no
daemon = no
 
[group test-group]
writable = test
# The following means that the public key of the user is
# in keys/myuser.pub file, obviously this can
# be different from the one who initialized gitosis
members = myuser
 
[repo test]
owner = Antonio Ospite
description = Test repository

Commit and push the changes, this will prepare push permissions for arepository named test on the server:

git commit -a
git push

If you get this warning:

warning: You did not specify any refspecs to push, and the current remote
warning: has not configured any push refspecs. The default action in this
warning: case is to push all matching refspecs, that is, all branches
warning: that exist both locally and remotely will be updated.  This may
warning: not necessarily be what you want to happen.
warning: 
warning: You can specify what action you want to take in this case, and
warning: avoid seeing this message again, by configuring 'push.default' to:
warning:   'nothing'  : Do not push anything
warning:   'matching' : Push all matching branches (default)
warning:   'tracking' : Push the current branch to whatever it is tracking
warning:   'current'  : Push the current branch

you can set the default push action in your git client config with:

git config --global push.default matching

Now the user has push rights, but the project does not exist yet.Create the test project, as user myuser:

mkdir test
cd test
git init
# ... do some work: REMEMEBER to "git add" the files
git commit -a
git remote add origin git@git.example.com:test.git
git push origin master:refs/heads/master
git config --add branch.master.remote origin
git config --add branch.master.merge refs/heads/master

The last two lines above set a default merging branch, avoiding the message below when pulling into the directory where the repository was firstly created (taken from http://andr.esmejia.com/posts/28-quick-remider-always-merge-from-master):

You asked me to pull without telling me which branch you
want to merge with, and 'branch.master.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.

If you want your project to be cloned anonymously via http you have to enable the post-update hook on the server:

git@git.example.com$ cd /home/git/repositories/test.git
git@git.example.com$ chmod 755 hooks/post-update
git@git.example.com$ ./hooks/post-update

however, this is not enough for cloning via http, your web server needs to be configured as well, see thegitweb section.

Note: you can skip doing the last step above for every new repository if you change the default template used to init a new git repository, by issuing:

git@git.example.com$ sudo chmod 755 /usr/share/git-core/templates/hooks/post-update

as explained in this discussion on StackOverflow.

Configuring git-daemon

If you want to provide access anonymously with the git protocol, you can use git-daemon, this is not strictly required, but it is more efficient than providing anonymous access via http.

Debian provides the git-daemon-run package based onrunit to start and stop thegit-daemon service, but I prefer a standard init.d script.Put this in /etc/init.d/git-daemon:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          git-daemon
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: git-daemon service
# Description:       git-daemon makes git repositories available via the git
#                    protocol.
### END INIT INFO
 
# Author: Antonio Ospite <ospite@studenti.unina.it>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.
 
# Do NOT "set -e"
 
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/lib/git-core
DESC="git-daemon service"
NAME=git-daemon
DAEMON=/usr/lib/git-core/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
 
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
 
# Fallback options values, we use these when
# the /etc/default/git-daemon file does not exist
RUN=no
USER=gitosis
GROUP=gitosis
REPOSITORIES="/srv/gitosis/repositories/"
 
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
 
# If ADVANCED_OPTS is empty, use a default setting
if [ "x$ADVANCED_OPTS" = "x" ];
then
	ADVANCED_OPTS="--base-path=$REPOSITORIES $REPOSITORIES"
fi
 
DAEMON_ARGS="--syslog --reuseaddr \
             --user=$USER --group=$GROUP \
             $ADVANCED_OPTS"
 
 
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
 
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
 
#
# Function that starts the daemon/service
#
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started
	[ "$RUN" != yes ] && return 2
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
		|| return 1
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --background --make-pidfile -- \
		$DAEMON_ARGS \
		|| return 2
 
  return 0
}
 
#
# Function that stops the daemon/service
#
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred
	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	# Wait for children to finish too if this is a daemon that forks
	# and if the daemon is only ever run from this initscript.
	# If the above conditions are not satisfied then add some other code
	# that waits for the process to drop all resources that could be
	# needed by services started subsequently.  A last resort is to
	# sleep for some time.
	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
	[ "$?" = 2 ] && return 2
	# Many daemons don't delete their pidfiles when they exit.
	rm -f $PIDFILE
	return "$RETVAL"
}
 
case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  restart|force-reload)
	#
	# If the "reload" option is implemented then remove the
	# 'force-reload' alias
	#
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
	exit 3
	;;
esac
 
:

And make it executable:

chmod 755 /etc/init.d/git-daemon

You can adjust the options passed to git-daemon in /etc/default/git-daemon, here's an example

# Defaults for the git-daemon initscript
 
# Uncomment the following line to start git-daemon on boot
RUN=yes
 
# Set to the user and group git-daemon should run as
USER=git
GROUP=git
 
# Set the base path and the directory where the repositories are.
REPOSITORIES="/home/git/repositories"
 
# Provide a way to have custom setup.
#
# Note, when ADVANCED_OPTS is defined the REPOSITORIES setting is ignored,
# so take good care to specify exactly what git-daemon have to do.
#
# Here is an example from the man page:
#ADVANCED_OPTS="--verbose --export-all \
#               --interpolated-path=/pub/%IP/%D \
#               /pub/192.168.1.200/software \
#               /pub/10.10.220.23/software"

And install SystemV start and stop links with:

update-rc.d git-daemon defaults

Open TCP port 9418 on your firewall if needed, in my case (I have ain-new chain for new connections) the rule looks like this one:

$IPT -A in-new -p tcp -m tcp --dport 9418 --syn -j ACCEPT

Configuring gitweb

We are installing custom config for gitweb in/home/git/gitosis as suggested in/usr/share/doc/gitosis/examples/gitweb.conf

Install gitweb:

aptitude install gitweb

Copy and edit the config file:

cp /usr/share/doc/gitosis/examples/gitweb.conf /home/git/gitosis/
$EDITOR /home/git/gitosis/gitweb.conf

My configuration is:

# Include the global configuration, if found.
do "/etc/gitweb.conf" if -e "/etc/gitweb.conf";
 
# Point to projects.list file generated by gitosis.
# Here gitosis manages the user "git", who has a
# home directory of /home/git
$projects_list = "/home/git/gitosis/projects.list";
 
# Where the actual repositories are located.
$projectroot = "/home/git/repositories";
 
# By default, gitweb will happily let people browse any repository
# they guess the name of. This may or may not be what you want.
# I prefer to set these, to allow exactly the repositories in
# projects.list to be browsed.
$export_ok = "";
$strict_export = "true";
 
# A list of base urls where all the repositories can be cloned from.
# Easier than having per-repository cloneurl files.
@git_base_url_list = ('git://git.example.com', 'http://git.example.com');
 
$home_text = "$projectroot/indextext.html";
 
# Just for a little more security
$prevent_xss = true;
 
# turn off potentially CPU-intensive features
$feature{'search'}{'default'} = [undef];
$feature{'blame'}{'default'} = [undef];
$feature{'pickaxe'}{'default'} = [undef];
$feature{'grep'}{'default'} = [undef];
 
# nicer-looking URLs
$feature{'pathinfo'}{'default'} = [1];
 
$my_uri = "http://git.example.com";
$home_link = "http://git.example.com";
 
$site_name = "git.example.com";

with this setup the server description is taken from /home/git/repositories/indextext.html

The Apache VirtualHost configuration is:

<VirtualHost *:80>
  ServerAdmin webmaster@localhost
  ServerName git.example.com
 
  SetEnv  GITWEB_CONFIG   /home/git/gitosis/gitweb.conf
 
  Alias /gitweb.css /usr/share/gitweb/gitweb.css
  Alias /git-logo.png /usr/share/gitweb/git-logo.png
  Alias /git-favicon.png /usr/share/gitweb/git-favicon.png
 
  ScriptAlias /cgi-bin /usr/lib/cgi-bin
 
  DocumentRoot /home/git/repositories
  <Directory /home/git/repositories>
    Options Indexes FollowSymlinks ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
 
    DirectoryIndex /cgi-bin/gitweb.cgi
 
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^.* /cgi-bin/gitweb.cgi/$0 [L,PT]
  </Directory>
 
  ErrorLog /var/log/apache2/git.example.com.error.log
  CustomLog /var/log/apache2/git.example.com.access.log combined
</VirtualHost>

Now test the setup pointing the browser to git.example.com, if you get a404 - No projects found there could be some filesystem permissionissues, gitosis sets mode 0750 on projects dirs, you can add thewww-data user to the git group, so gitweb can accessthe git repositories in read only mode.

adduser www-data git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值