我需要用git-over-http(smart-http)设置一个git服务器,但在线可用的资源一团糟,混合在其他apache配置中,缺少细节或不够明确。
我自己回答这个问题是基于我发现现有资源缺乏的情况。
首先需要了解git通过http:git和apache有两个组件。这两者通过一个名为githttp后端的脚本连接。挑战在于配置这两个组件之间的接口,以便apache转发对git的http请求。
注意:安全不在本指南的范围内。
-
首先使用发行版的包管理器安装git和apache2。
-
添加apache所需的模块以启用gitoverhttp。这些是cgi、别名和env
$ a2enmod cgi alias env
- 将以下内容复制到
/etc/apache2/httpd.conf
中(不删除其中包含的任何内容)
<VirtualHost *:80>
SetEnv GIT_PROJECT_ROOT /data/git
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
ScriptAliasMatch
"(?x)^/(.*/(HEAD |
info/refs |
objects/(info/[^/]+ |
[0-9a-f]{2}/[0-9a-f]{38} |
pack/pack-[0-9a-f]{40}.(pack|idx)) |
git-(upload|receive)-pack))$"
"/usr/lib/git/git-http-backend/$1"
Alias /git /data/git
<Directory /usr/lib/git>
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
AllowOverride None
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
- 现在,用服务器上git repos的父目录替换
/data/git
的2个实例(如果您还没有任何repos,请不要担心,只需使用您打算放置它/它们的目录)
另外,将/usr/lib/git/git-http-backend
替换为系统上githttp后端的位置,该位置可以使用$ find / -name git-http-backend
找到
可能是在您的系统上,REDIRECT_REMOTE_USER
实际上覆盖了一个有效的REMOTE_USER
。如果完成后此设置不起作用,请尝试删除该行。
根据此来源,对于apache 2.4及更高版本,可能需要用Require all granted
替换Directory标记中的最后两行。
- 重新启动apache服务器:
$ apache2ctl -k graceful
现在apache服务器已经设置好了,但我们还没有完成,设置repo的一些重要部分将影响此设置是否有效。
- 设置回购:
$ mkdir myrepo.git
$ cd myrepo.git
$ git init --bare --shared
$ cp hooks/post-update.sample hooks/post-update
$ git update-server-info
$ chown -R wwwrun:www
在这里,重要的是要理解最后一行将repo的所有者更改为apache2用户。此用户可能与您的系统不同。要查找apache用户,请执行$ ps aux | egrep '(apache|httpd)'
。然后,要查找用户的组名,请执行$ id user-name
。在我的系统上,用户是wwwrun,组是www。相应地更换。
- 使用回购
为了使用repo,您需要知道url。对于此设置,url为http://server.domain/myrepo.git
注意:https将不起作用。
从客户端访问回购时,只需将其添加为远程:
$ git remote add origin http://server.domain/myrepo.git
然后,您可以像其他git回购一样与它进行交互。
具有不同访问权限的多个项目
有gitolite,但复杂。。。一个简单的解决方案是在apache2conf中创建宏,如下所示:
## Git root
SetEnv GIT_PROJECT_ROOT /opt/gitroot
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
SetEnv GITWEB_CONFIG /etc/gitweb.conf
## SMART Http
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
<Directory "/usr/libexec/git-core*">
Options +ExecCGI +Indexes
Order allow,deny
Allow from all
Require all granted
</Directory>
<Macro Project $repository $developers $users>
<LocationMatch "^/git/$repository.*$">
AuthType Basic
AuthName "Git Access"
AuthUserFile /opt/basic_auth
Require $developers $users
</LocationMatch>
<LocationMatch "^/git/$repository/git-receive-pack$">
AuthType Basic
AuthName "Git Access"
AuthUserFile /opt/basic_auth
Require $developers
</LocationMatch>
</Macro>
IncludeOptional /opt/git_access.conf
在/opt/git_access.conf 中
Use Project test1 "admin john" "mike"
Use Project test2 "admin emma" "all granted"
因此,git项目test1将由admin和john进行读/写访问,并由mike进行只读访问。
项目test2将拥有所有经过身份验证的用户的读取访问权限。
git_access.conf可以由您的工具从您的项目和用户的数据库中生成,并通过"服务httpd reload"重新加载。
对于gitweb读取访问的相同配置,请添加/etc/gitweb.conf:
$export_auth_hook = sub {
my $repo = shift;
my $user = $cgi->remote_user;
if($repo =~ s//opt/gitroot///) {
open FILE, '/opt/git_access';
while(<FILE>) {
if ($_ =~ m/Use Project $repo "(.*)" "(.*)"/)
{
my $users = $1 . ' ' . $2;
$users =~ s/all granted/$user/;
$users =~ s/user//;
if ( $users =~ m/$user/ ) {
return 1;
}
}
}
}
return 0;
};
这个小gitweb钩子隐藏(返回0)当前用户没有读取权限的git存储库。
在apache2配置中,经典的gitweb conf:
## Gitweb
Alias /gitweb /var/www/git
<Directory /var/www/git>
AddHandler cgi-script .cgi
DirectoryIndex gitweb.cgi
Options +ExecCGI +Indexes +FollowSymlinks
AllowOverride None
AuthType Basic
AuthName "Git Access"
AuthUserFile /opt/basic_auth
Require valid-user
</Directory>
这是我的配置。