动手搭建开发网站: nginx, wiki + trac + git (三)
前一篇:动手搭建开发网站: nginx, wiki + trac + git (二)部署Gitgit版本管理服务主要涵盖三个方面:上传通道下载通道Web界面上传通道是指git仓库的可写用户将本地仓库变更推送到服务器仓库中。一般基于ssh和http(s)传输协议。本例中仅部署基于ssh传输协议的上传通道。其中用户的认证机制采用ssh公私钥认证方式,用户的访问控制由git
前一篇:动手搭建开发网站: nginx, wiki + trac + git (二)
部署Git
git版本管理服务主要涵盖三个方面:
- 上传通道
- 下载通道
- Web界面
本例中仅部署基于ssh传输协议的上传通道。其中用户的认证机制采用ssh公私钥认证方式,用户的访问控制由gitosis来实现。整合在一起的方案即是gitosis。
本例中召唤一个 改动过的gitosis,与原版相比:
- 支持repo
- 采用了gitolite风格的配置文件
- 支持设置用户名和git仓库描述
本例中除了ssh传输协议的下载通道,还将部署git daemon来提供git协议的下载支持。
Web界面是网页访问git仓库,方便浏览和代码快照抓取。
本例中召唤了一个 改动过的cgit,与原版相比:
- 优化repo显示
- 部分filter脚本dash兼容性修正,安装目录的更改。
- 部署gitosis
- 部署git daemon
- 部署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> -- 生成用户公钥和私钥
- do_user.py
部署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基础上改动:
配置urlvi /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
cgit是个C语言实现的cgit程序,然而nginx并不支持cgi,nginx主要将匹配url的请求按照规则处理,对于动态网页,通以fastcgi/scgi/uwsgi协议扔给某个socket。此处召唤cgi-bridge.wsgi,仍然利用前述uwsgi池 -- cgi-bridge.wsgi来调用实际的cgit程序,其作为一座桥,跨于wsgi和cgi之间。
cgit需要访问/home/services/git/repositories,正常情况下没有权限,于是绕一下:mkdir -p /home/helpers/uwsgi cp cgi-bridge.wsgi /home/helpers/uwsgi chmod 755 /home/helpers/uwsgi/cgi-bridge.wsgi
- 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所有以防止闲杂人等更改。为了进一步安全期间,可以多建几个池,分别跑不同身份,当然:
- 自主访问控制这种小把戏不能满足你的野心的话,当然要整个强制访问控制罗。不过目前的强制访问控制技术不是能大规模实用。在包管理器层面来规划并结合强制访问控制是笔者的一个心愿,如果这句话触动了你,进一步阅读Four aspects of making a Great consumer Operating System
- uwsgi花样蛮多的,就是显得有点小气。让systemd出面的话,为服务准备运行环境,例如“布置定义名空间,设置系统调用过滤,强制访问控制规则载入...”,安全手段更多且大气些。
更多推荐
所有评论(0)