Fedora 20上架设Git服务器

最近,项目上需要帮客户托管Git代码仓库,用了Apache+LDAP+Gitolite+cgit+Git 1.9.0在RHEL 6.5上做了实施。这是个中规中矩中规中矩的方案。不足之处是当访问用户数量增大时,Apache不能很好的应付。Apache默认的prefork机制并发处理能力比较弱,当有并发访问量比较大时,它会fork很多apache进程,导致系统负荷巨大。另外,RHEL 6.5上还没有Gitolite,cgit和git最新版本的RPM包。需要手工安装,比较麻烦。另外一点是Apache CGI进程访问Git仓库的权限设置问题。Git仓库的所有文件的属主是git。为了解决Apache CGI进行访问Git仓库文件,最简单的方法是让Apache CGI进程以git的身份运行,这样就不需要对Git仓库做复杂权限设置了。幸好Apache有suexec功能可满足此需求。但是,suexec要求CGI程序必须在docroot的子目录里,这个docroot是编译时的固定死的,可以用suexec -V获知具体值,在Redhat系统上一般是/var/www。

总之,该方案不太完美,安装设置比较费事,还有一些莫名其妙的限制。有没有更好一点的解决方案呢。

 

如果把视线从Apache转移到其它web服务器上,近些年大红大紫的非nginx莫属。nginx也称Engine X。直译就是X发动机或X引擎。有人把Apache比作本田(Honda)家轿,nginx就是保时捷(Porsche)跑车。在我看来nginx主要优点是能使用比较小的系统资源处理大量并发请求,并提供优异响应速度。于是,萌生了在Fedora 20上用nginx架设Git服务器想法。

选用Fedora 20的理由是,它的RPM仓库里提供了很多和上游版本接近的RPM包,比如Git, gitolite, cgit都有很很新的包。另外,它是支持systemd比较领先的发行版,听说RHEL 7要引入Fedora这些功能。

选择nginx和Fedora20实际上给方案增加了很多技术挑战。第一个是nginx不支持传统的cgi程序,它支持FastCGI,如果要运行传统的CGI,比如cgit和gitolite-shell,就必须要使用一个转换工具,幸好正好有这样的工具(fcgiwrap)。第二个是在Fedora里整合各个工具,使它们一起协同工作。这个要比之前的RHEL 5.x, 6.x要困难得多。主要原因是,Fedora20默认设置比较严格,它启用了selinux,设置了限制重重的防火墙,初始化系统更换成systemd也让很多新手满头雾水。那么,怎么在Fedora20下用nginx架设一个http协议的Git仓库加上cgit web界面呢?以下是整个解决方案的概要:

  • 用nginx源下载nginx-1.4.7的SPRM,并下在nginx-auth-ldap第三方扩展以支持LDAP认证,然后修改nginx-1.4.7的spec文件使它包nginx-auth-ldap扩展。修改后的spec文件在此。然后,创建带LDAP认证功能的nginx的RPM包,并安装。
  • 用yum install -y gitolite3软件包安装gitolite,如果不喜欢该RPM用gitolite作为Git仓库文件的属主,可以通过修改gitolite3 spec文件来定制你需要的属主,一般用git比较常见。本人的定制gitolite3 spec文件在此。
  • 用yum install -y git cgit安装git和cgit
  • 官方的fcgiwrap只有debian的包,没有现成的rpm包,但我为它做了个spec文件,生成的RPM包可以支持systemd socket activation,省去了再安装一个spawn-fcgi的麻烦。构建fcgiwrap的rpm包,请参考这里。另外,我的修改已经提交给原作者,也许不久的将来,rpm包会被原生支持。有了fcgiwrap的RPM包后用rpm -Uhv 命令安装号fcgiwrap。

安装完上述软件包后,需要配置,主要的工作是:

  • 以Git仓库属主的身份运行gitolite setup -pk admin.pub,这将初始化gitolite的管理仓库。有了它就可以添加任意多的Git仓库。
  • 修改fcgiwrap.service的unit文件,使它以git,git的身份运行。
  • 创建nginx配置文件提供git http和cgit服务,这些服务都是转发给fcgiwrap服务,由它来启动相应gitolite-shell或者cgit这些cgi程序,示例配置文件在此
  • 用firewall-cmd --add-service打开防火墙http, https端口
  • 增加selinux规则使得nginx可以连接,读写fcgiwrap的unix domain socket “/run/fcgiwrap.sock"该规则如下:
module mypol 1.0;

require {
	type var_run_t;
	type httpd_t;
	type init_t;
	class sock_file write;
	class unix_stream_socket connectto;
}

#============= httpd_t ==============
allow httpd_t init_t:unix_stream_socket connectto;
allow httpd_t var_run_t:sock_file write;
 经历了这几道关卡后,就可以看到胜利的曙光了。

你可能感兴趣的:(fedora)