前一篇:动手搭建开发网站: nginx,  wiki + trac + git (二)

部署Git

git版本管理服务主要涵盖三个方面:

  1. 上传通道
  2. 下载通道
  3. Web界面
上传通道是指git仓库的可写用户将本地仓库变更推送到服务器仓库中。一般基于ssh和http(s)传输协议。
本例中仅部署基于ssh传输协议的上传通道。其中用户的认证机制采用ssh公私钥认证方式,用户的访问控制由gitosis来实现。整合在一起的方案即是gitosis。
本例中召唤一个 改动过的gitosis,与原版相比:
  1. 支持repo
  2. 采用了gitolite风格的配置文件
  3. 支持设置用户名和git仓库描述

下载通道是指才从git仓库中拉取内容,一般基于git,ssh和http(s)传输协议。其中,采用git协议效率较好;采用ssh协议则可以进行认证和访问控制,用于私密的git仓库;而采用http(s)则是为了便于穿透防火墙。
本例中除了ssh传输协议的下载通道,还将部署git daemon来提供git协议的下载支持。

Web界面是网页访问git仓库,方便浏览和代码快照抓取。
本例中召唤了一个 改动过的cgit,与原版相比:
  1. 优化repo显示
  2. 部分filter脚本dash兼容性修正,安装目录的更改。
因此,部署git版本管理服务包含如下步骤:
  1. 部署gitosis
  2. 部署git daemon
  3. 部署cgit

部署gitosis

apt-get install git

unzip cee1-gitosis-hack-443239f.zip
cd cee1-gitosis-hack-443239f
python setup.py install

# 增加用户git
adduser --system \
  --shell /bin/sh \
  --gecos 'git version control' \
  --group \
  --disabled-password \
  --home /home/services/git \
  git

# 准备下管理员的ssh公钥,如果没有,在平时工作机上创建,如下:
ssh-keygen -t rsa

# 拷贝管理员的ssh公钥到服务器上
scp ~/.ssh/id_rsa.pub xxx@example.com

# 初始化gitosis
sudo -H -u git gitosis-init < /path/to/id_rsa.pub
# 修正 post-update 权限:使其可执行
chmod 755 /home/services/git/repositories/gitosis-admin.git/hooks/post-update
使用
在管理员工作机上,
git clone ssh://git@example.com/gitosis-admin.git

cd gitosis-admin
# 将用户公钥放入keydir
cp <userID>.pub keydir
# 编辑gitosis.conf,最后
git add keydir/<userID>.pub
git add gitosis.conf
git commit -m "Add <userID> as owner of repo xxx"
# 将授权配置的改动推送到服务器上
git push origin master

下面介绍一个gitolite风格的gitosis.conf例子:

gitosis
	loglevel	= INFO
	decodeID	= no

# 组以及成员,注意组ID都是以@起头
@gitosis-admin	 = admin
@group1		 = userID1 userID2

# gitosis-admin仓库,管理gitosis本身的仓库。
# 只有@gitosis-admin组成员可以读和写,其他闲杂人等禁止访问
repo gitosis-admin
	RW+	 = @gitosis-admin

repo android.repo
	# 采用正则表达式来访问“android.repo/”子路径下的子仓库
	path_regex = android\.repo/
	description = android repo
	owner	 = userID1
	RW+	 = @group1
	# daemon和gitweb是两个特殊的用户,指示该仓库是否在git协议和Web界面中可访问
	R	 = daemon gitweb

关于选项decodeID

gitosis.conf中userID 与 keydir下的“公钥文件名userID.pub除去扩展名”是一致的。因此userID命名规则受限文件系统。decodeID启用后则:

“userID in gitosis.conf” 对应 “<encoded_userID>.pub”

编码规则如下:

encoded_userID = 'git' + urlsafe_b64encode(userID).replace('=', '.')

下面两个脚本来简化上述操作:

    • do_user.py
      • ./do_user.py -W <encoded_userID>   -- 这个编码的userID是谁呀?
      • ./do_user.py -E <userID>           -- 获取encoded_userID
    • newID.py
      • ./newID.py <encoded_userID>        -- 生成用户公钥和私钥

部署git daemon

让git daemon跑起来:
sudo -u git git daemon --base-path=/home/services/git/repositories &

加到/etc/rc.local让其开机自动运行。同本系列二中uwsgi一样,召唤SingletonLauncher

vi /etc/rc.local
sudo -u git /home/helpers/SingletonLauncher -n git-daemon -dN git daemon --base-path=/home/services/git/repositories &

部署cgit

unzip cee1-cgit-hack-242aa8c.zip
# C代码,故需要编译。编译需要安装编译环境,不建议在服务器上这么做。
# 可以找个和服务器环境一致的虚拟机上编译
cd cee1-cgit-hack-242aa8c
make
make DESTDIR=`pwd`/cgit-binary install

mkdir /home/services/git/web
cp -a cgit-binary/* /home/services/git/web
修改cgitrc
在此 模板cgitrc基础上改动:
vi /home/services/git/web/etc/cgitrc
...
commit-filter=/home/services/git/web/lib/filters/commit-links.sh
# 代码高亮显示,需要安装highlight:apt-get install highlight
source-filter=/home/services/git/web/lib/filters/syntax-highlighting.sh

...
# 缓存所在目录,手动建立并确保可读写
# mkdir -p /var/cache/cgit && chown www-data.www-data /var/cache/cgit
cache-root=/var/cache/cgit

...
clone-prefix=git://example.com ssh://git@example.com
css=/cgit/data/cgit.css
logo=/cgit/data/cgit.png
root-title=Git Repository Browser -- example

...
snapshots=zip
section-from-path=1
project-list=/home/services/git/gitosis/projects.list
scan-path=/home/services/git/repositories
配置url

cgit是个C语言实现的cgit程序,然而nginx并不支持cgi,nginx主要将匹配url的请求按照规则处理,对于动态网页,通以fastcgi/scgi/uwsgi协议扔给某个socket。此处召唤cgi-bridge.wsgi,仍然利用前述uwsgi池 -- cgi-bridge.wsgi来调用实际的cgit程序,其作为一座桥,跨于wsgi和cgi之间。

mkdir -p /home/helpers/uwsgi
cp cgi-bridge.wsgi /home/helpers/uwsgi
chmod 755 /home/helpers/uwsgi/cgi-bridge.wsgi
cgit需要访问/home/services/git/repositories,正常情况下没有权限,于是绕一下:
  • vi /home/helpers/uwsgi/uwsgi.ini,加入一行“gid = git”
  • 重新载入uwsgi:uwsgi --reload /run/uwsgi-www-data/uwsgi.pid

将www.example.com/cgit分配给cgit程序:

  • ln -ds /home/services/git/web /home/sites/default/cgit
  • vi /etc/nginx/sites-enabled/default
       location ~ /cgit/data/ {}
       location ~ ^/cgit(/.*)?$ {
                include uwsgi_params;
                uwsgi_pass unix:///run/uwsgi-www-data/uwsgi.sock;
                uwsgi_param SCRIPT_NAME /cgit;
                uwsgi_modifier1 30;
                uwsgi_param UWSGI_SETENV SCRIPT_FILE=/home/sites/default/cgit/bin/cgit;
                uwsgi_param UWSGI_SETENV CGI_BRG_OUT_BLKSZ=512k;
                uwsgi_param UWSGI_SETENV CGI_BRG_LATENCY=50;
                uwsgi_param UWSGI_SETENV CGIT_CONFIG=/home/sites/default/cgit/etc/cgitrc;
                uwsgi_param UWSGI_FILE /home/helpers/uwsgi/cgi-bridge.wsgi;
        }

至此,网站搭建完成, 全部配置文件模板

后记:吐槽&广告时间

nginx与动态网页程序之间通过socket接口来通信,这样就允许nginx和动态网页程序运行在不同的环境中,即不同的uid,gid...甚至不同的(虚拟)服务器上。动态网页程序往往是一个线程/进程池,遇请求就拖出一个线程/进程来执行,同时监管是否没响应了或是异常退出。
本站搭建用到了两个池:php-fpm和uwsgi,均以www-data身份跑着。代码和公用配置文件均为root所有以防止闲杂人等更改。为了进一步安全期间,可以多建几个池,分别跑不同身份,当然:
  1. 自主访问控制这种小把戏不能满足你的野心的话,当然要整个强制访问控制罗。不过目前的强制访问控制技术不是能大规模实用。在包管理器层面来规划并结合强制访问控制是笔者的一个心愿,如果这句话触动了你,进一步阅读Four aspects of making a Great consumer Operating System
  2. uwsgi花样蛮多的,就是显得有点小气。让systemd出面的话,为服务准备运行环境,例如“布置定义名空间,设置系统调用过滤,强制访问控制规则载入...”,安全手段更多且大气些。
最后,想要进一步了解git,请拨 0;想要备份,请拨 1


第一篇:动手搭建开发网站: nginx, wiki + trac + git (一)

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐