最近在整理自己過去寫的各種程式碼,真是又多又雜 版本分支多
打算自己建立一台 Git Server 來管理
也打算把近期維護的 VB.NET 的程式碼也一併使用 Git 管理版本
找一了一下的教學,才發現 Virtual Studio 不支援 SSH 僅支援 HTTP 協定
動手弄了台主機就開始搞了,前後花了三個晚上才搞定
SSH 沒搞太久幾乎都是卡在 HTTP 的部份,爬文爬到 Chrome 分頁都快40個了
環境說明:
- CentOS 7 (1511) x64
- Apache 2.4.6
我自己的要求:
- 該主機也會是開發測試環境
- Git 主要自己要使用而已,但要預留將來提供他人使用可能性
- SSH 和 HTTP 兩種模式要能維護同一份 Repository
- HTTP 需要權限驗證,SSH 不需要輸入帳號密碼
- 不使用 WebDAV 協定
實做方式:
新增一個 git 帳號,home 指定為 /home/git
統一透過這個帳號維護所有的 Repository
SSH 的部份比較簡單
透過 git 帳號的 ~/.ssh/authorized_keys 來做授權處理
Apache 不將 User 和 Group 設定為 git,而是預設的 Apache 或多數人慣用的 nobody
然後 suexec 不透過 mod_userdir 實現
而是使用 VirtualHost 透過 SuexecUserGroup 切換為 git 身份
但是套用 suexec 後一直失敗,陸續修改設定不停測試
大部分的時間都是卡在 “End of script output before headers” 這個錯誤訊息
爬了不少文,走了很多冤枉路後,才確定問題出在 suexec 本身…
先來看一下 apache 原本的 suexec
1 2 3 4 5 6 7 8 9 10 11 |
[root@centos ~]# which suexec /usr/sbin/suexec [root@centos ~]# /usr/sbin/suexec -V -D AP_DOC_ROOT="/var/www" -D AP_GID_MIN=100 -D AP_HTTPD_USER="apache" -D AP_LOG_SYSLOG -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=500 -D AP_USERDIR_SUFFIX="public_html" |
問題就出在 AP_DOC_ROOT 這行,指定的路徑是 “/var/www”
然而我的 git 帳號的 home 設定為 /home/git
多數的 virtualhost 也都是放在 /home 下面,方便進行維護
所以我們需要重新編譯一個 suexec 出來,將其 AP_DOC_ROOT 設定為 /home
先安裝 yum-utils 用來直接下載 SOURCE RPM 檔案
1 2 3 4 5 6 7 8 |
# 安裝 yum-utils [root@centos ~]# yum install yum-utils # 下載 Apache 的 source rpm [root@centos ~]# yumdownloader --source httpd # 安裝 srpm ,相關檔案會被安裝到操作時使用者帳號的 ~/rpmbuild 下 [root@centos ~]# rpm -i httpd-2.4.6-40.el7.centos.4.src.rpm |
安裝 rpm build 相關工具,嘗試 build rpm 檔案並解決檢查相依性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# 安裝 rpmdevtools [root@centos ~]# yum install rpmdevtools # 切換到 source 目錄 [root@centos ~]# cd ~/rpmbuild/SOURCES # 先以 tarball 方式建立 rpm 檔案,用來檢查相依性 [root@centos SOURCES]# rpmbuild -tb httpd-2.4.6.tar.bz2 error: Failed build dependencies: zlib-devel is needed by httpd-2.4.6-1.x86_64 libselinux-devel is needed by httpd-2.4.6-1.x86_64 libuuid-devel is needed by httpd-2.4.6-1.x86_64 apr-devel >= 1.4.0 is needed by httpd-2.4.6-1.x86_64 apr-util-devel >= 1.4.0 is needed by httpd-2.4.6-1.x86_64 pcre-devel >= 5.0 is needed by httpd-2.4.6-1.x86_64 openldap-devel is needed by httpd-2.4.6-1.x86_64 lua-devel is needed by httpd-2.4.6-1.x86_64 libxml2-devel is needed by httpd-2.4.6-1.x86_64 distcache-devel is needed by httpd-2.4.6-1.x86_64 openssl-devel is needed by httpd-2.4.6-1.x86_64 # 安裝相關套件 [root@centos SOURCES]# yum install zlib-devel libselinux-devel libuuid-devel \ apr-devel apr-util-devel pcre-devel openldap-devel \ lua-devel libxml2-devel distcache-devel openssl-devel # 再一次 [root@centos SOURCES]# rpmbuild -tb httpd-2.4.6.tar.bz2 error: Failed build dependencies: distcache-devel is needed by httpd-2.4.6-1.x86_64 |
發現 distcache-devel 並沒有被安裝,也下載不到 SOURCE RPM,所以上網找了一下
1 2 3 4 5 6 7 8 9 10 11 |
# 下載 distcache 的 source rpm [root@centos SOURCES]# wget -P /tmp https://kojipkgs.fedoraproject.org/packages/distcache/1.4.5/23/src/distcache-1.4.5-23.src.rpm # 直接 rebuild 安裝用的 rpm # 如果有相依性的問題就 yum 安裝一下,鸚鵡是沒遇到 [root@centos SOURCES]# rpmbuild --rebuild /tmp/distcache-1.4.5-23.src.rpm # 安裝,我沒有使用 rpm 安裝,而是使用 yum 來安裝 [root@centos SOURCES]# yum install \ ~/rpmbuild/RPMS/x86_64/distcache-1.4.5-23.x86_64.rpm \ ~/rpmbuild/RPMS/x86_64/distcache-devel-1.4.5-23.x86_64.rpm |
繼續重製 httpd 套件,跑一段時間後應該會發生錯誤
不用理會 因為我們的目的是 suexec 檔案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# 這次應該就可以正常開始了 [root@centos SOURCES]# rpmbuild -tb httpd-2.4.6.tar.bz2 ... ... RPM build errors: Installed (but unpackaged) file(s) found: /usr/lib64/httpd/modules/mod_proxy_wstunnel.so # 最後發生錯誤,忽略 # 然後看一下 suexec 的資訊 [root@centos SOURCES]# ~/rpmbuild/BUILDROOT/httpd-2.4.6-1.x86_64/usr/sbin/suexec -V -D AP_DOC_ROOT="/var/www" -D AP_GID_MIN=100 -D AP_HTTPD_USER="apache" -D AP_LOG_EXEC="/var/log/httpd/suexec.log" -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=500 -D AP_USERDIR_SUFFIX="public_html" # 刪除目前的 suexec [root@centos SOURCES]# rm ~/rpmbuild/BUILDROOT/httpd-2.4.6-1.x86_64/usr/sbin/suexec # 編輯 ~/rpmbuild/SPECS/httpd.spec 異動兩個地方 # 1. 在檔案開頭最後一個 %define 後面新增一行加上 "%define homedir /home" # 2. 搜尋 "--with-suexec-docroot=%{contentdir} \" # 取代為 "--with-suexec-docroot=%{homedir} \" # 存檔後,改使用 spec 檔案重製 [root@centos SOURCES]# rpmbuild -bb ~/rpmbuild/SPECS/httpd.spec # 依然會出錯,但是 suexec 應該已經又被編譯出來 [root@centos SOURCES]# ~/rpmbuild/BUILDROOT/httpd-2.4.6-1.x86_64/usr/sbin/suexec -V -D AP_DOC_ROOT="/home" -D AP_GID_MIN=100 -D AP_HTTPD_USER="apache" -D AP_LOG_EXEC="/var/log/httpd/suexec.log" -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=500 -D AP_USERDIR_SUFFIX="public_html" |
到這邊,已經編譯出我們需要的 suexec 檔案,置換掉原本的並設定權限
1 2 3 4 5 6 7 8 |
# 備份 suexec [root@centos SOURCES]# mv /usr/sbin/suexec /usr/sbin/suexec.orig # 改用新編譯出來的 [root@centos SOURCES]# cp ~/rpmbuild/BUILDROOT/httpd-2.4.6-1.x86_64/usr/sbin/suexec /usr/sbin/suexec # 處理權限 [root@centos SOURCES]# chmod u+s /usr/sbin/suexec |
原本的 suexec 是設定 AP_LOG_SYSLOG
現在的 suexec 是設定 AP_LOG_EXEC=”/var/log/httpd/suexec.log”
所以我們也要處理一下紀錄檔案的部份
1 2 3 4 5 6 7 8 9 |
# 建立檔案 [root@centos SOURCES]# touch /var/log/httpd/suexec.log # 如果 apache 以其他身份執行就修改成其他身份,例如: nobody [root@centos SOURCES]# chown apache:apache /var/log/httpd/suexec.log # 處理 logrotate # 開啟 "/etc/logrotate.d/httpd" 後在 postrotate 前面新增一行 "create" # 存檔離開 |
最後重新啟動 httpd 即完成了置換 suexec 的動作
Git 官方官方 blog 中的 Smart HTTP Transport 提到的設定方式
1 2 |
SetEnv GIT_PROJECT_ROOT /homt/git SetEnv GIT_HTTP_EXPORT_ALL |
由於使用了 suexec 的關係,在 httpd.conf 中設定了上面兩個設定值將不會作用生效
這是因為 suexec 使用比較嚴格的安全性管控,只會傳遞安全名單中的環境變數
所以要運用一點小技巧來實現
在 /home/git 下新增一個 suexec-git-httpd-backend 檔案
1 2 3 4 5 6 |
# 建立檔案 [root@centos SOURCES]# touch ~git/suexec-git-http-backend # 變更所有人以及權限 [root@centos SOURCES]# chmod 755 ~git/suexec-git-http-backend [root@centos SOURCES]# chown git.git ~git/suexec-git-http-backend |
檔案內容如下
1 2 3 4 5 6 |
#!/bin/bash export GIT_PROJECT_ROOT=/home/git export GIT_HTTP_EXPORT_ALL=true /usr/libexec/git-core/git-http-backend |
而 Apache 的 httpd.conf 中新增以下設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<Directory "/home/git"> Options All AllowOverride All Require all granted </Directory> <VirtualHost *> ServerName YOUR_DOMAIN DocumentRoot /home/git ScriptAlias / /home/git/suexec-git-http-backend/ SuexecUserGroup git git <Location /> AuthType Basic AuthName "Git Access" AuthUserFile /home/git/git.htpasswd Require valid-user </Location> </VirtualHost> |
重新啟動 httpd,使用 htaccess 對 /home/git/git.htpasswd 檔案新增權限
到此,鸚鵡自己的要求已經完成
新增 Git repository: HelloWorld
路徑:/home/git/HelloWorld.git
1 2 3 4 |
mkdir /home/git/HelloWorld.git cd /home/git/HelloWorld.git git init --bare --shared chown -R git.git /home/git/HelloWorld.git |
HTTP URL: http://YOUR_DOMAIN/HelloWorld.git
SSH:git@YOUR_DOMAIN:/home/git/HelloWorld.git
相關參考資料: