gitlab之webhook自動部署
轉自:https://www.jianshu.com/p/00bc0323e83f
動機
前段時間st0rm23在自己的伺服器上搭好了自己的gitlab,現在我準備開搞自己的web專案了。但是如果每次寫完都要用一些檔案傳輸的工具上傳到自己的伺服器就顯得很低效是吧,也會降低自己寫程式碼的動力。現在st0rm23就藉著自己的gitlab,用一個webhook就可以自動將自己的gitlab上的程式碼部署到web目錄下了。那麼這樣我們只要push一下程式碼到master上就可以自動生效了,用瀏覽器重新訪問下網站就可以看了勒( •̀ ω •́ )y。
原理介紹
1、配置gitlab當push動作的時候,訪問伺服器上的一個連結比如xxx.example.com/boot.php
2、boot.php裡面寫著一行程式碼,會讓伺服器git pull相應專案的程式碼到web目錄。
3、pull結束,程式碼就在web目錄了,我們只要重新訪問網站就可以了。
核心就是push的時候,gitlab會呼叫伺服器上的指令碼,伺服器上的指令碼就會從git重新拉取專案檔案。當然有一些安全性的設計,下面就來詳細地說明。
位置
啥?有同學找不到webhook,進入到某個專案中,然後點配置按鈕(有個小齒輪),裡面就有一個webhook配置,需要填連結地址和token。
webhook位置
配置服務端
先在服務端生成一對你的SSH金鑰,因為之後伺服器要用ssh方式免賬號密碼從gitlab上pull程式碼。用ssh-keygen在伺服器上生成金鑰,或者你已經有金鑰了就跳過這一步。
$ ssh-keygen
有了金鑰之後,複製你的公鑰,在你的gitlab profile個人資料裡,找到SSH的目錄,貼上儲存進去就可以了。這樣gitlab上就有了你web伺服器的公鑰了,就可以正常SSH了。
$ cat ~/.ssh/xx.pub ;這個可以看到公鑰,xx.pub就是公鑰檔案(xx替換成你的檔名),把輸出的東西複製到gitlab中
gitlab新增公鑰
接著在服務端的相應目錄下clone gitlab上的專案。這樣就可以將這個資料夾對應到gitlab上的專案。後續的指令碼就要根據這個對應關係來用指令碼驅動這個git pull。
比如我在/var/www/的目錄下git clone了gitlab上的專案,得到了/var/www/html/目錄,然後將自己的web伺服器nginx解析到/var/www/html/主目錄(修改完配置檔案之後,記得restart,不然不會生效的)。
git clone [your project address]
服務端指令碼
服務端簡易php指令碼,只要php指令碼在被訪問的時候,執行git pull操作就可以從伺服器pull程式碼了。
exec("cd /var/www/html/; git pull"); //先定位到相應目錄,然後git pull
當然這個指令碼太過簡易了,被人惡意訪問了怎麼辦,我們還是要加上一些驗證。首先是token驗證,訪問的時候要有特定的token,我們才可以讓這個訪問生效,一般這個token可以在gitlab填,這樣gitlab訪問這個指令碼的時候就會帶上這個token就能識別出來了。有token還不夠,被人知道了咋辦,我們還要限制IP訪問,只有gitlab伺服器的ip我們才可以允許執行。修正完就成了下面這個樣子。
<?php
$valid_token = 'secret_token';
$valid_ip = array('127.0.0.1'); //這裡填你的gitlab伺服器ip
$client_token = $_SERVER['HTTP_X_GITLAB_TOKEN'];
$client_ip = $_SERVER['REMOTE_ADDR'];
if ($client_token !== $valid_token) die('Token mismatch!');
if (!in_array($client_ip, $valid_ip)) die('Ip mismatch!');
exec("cd /var/www/html/; git pull origin master");
//exec("cd /var/www/html/; git pull origin master 2>&1", $output);
//var_dump($output); 這樣可以用瀏覽器除錯輸出
?>
我們儲存成/var/www/script/test.php。/var/www/script/這個目錄等下我們是要公開給外部訪問的。
服務端指令碼地址
我們有了這個指令碼之後,要部署到合適的位置。一般不是簡單地放在web目錄下(這個邏輯上也說不通是不是)。我們在web伺服器上開一個埠4567來專門為這個指令碼服務。下面以nginx為例。在/etc/nginx/sites-available/default的配置檔案末尾加上這段
server {
listen 4567;
listen [::]:4567;
server_name example.com;
root /var/www/script;
index index.html;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location / {
try_files $uri $uri/ =404;
}}
然後後檢測完,重啟一下nginx。
$ nginx -t
$ /etc/init.d/nginx restart
好,這時候就可以愉快地訪問example.com:4567/test.php了。如果有東西返回了(一般是token mismatch因為我們根本沒填token來訪問的),那說明這個指令碼架好了。
gitlab配置
好,我們現在已經有訪問的指令碼連結了,我們現在填到gitlab專案中的webhook一欄,儲存下來就可以用了。
gitlab上的webhook配置介面
記得你的secret_token要和你test.php裡面的配置一樣哦,還有valid_ip地址的地方也要記得填對。如果你都填對了,你就在你本地的專案裡新建一個檔案,然後push到master分支,就可以在你的伺服器web目錄下愉快地看到你的專案檔案了。這樣一個自動部署環境就建好了,愉快地寫程式碼吧少年。
賬號許可權
s0tm23我一開始興致滿滿,覺得這樣就可以了呀。結果一試,發現失敗了。也不知道為啥,本著白盒測試的心態,程式碼在手,天下我有,那就手工除錯輸出看一下什麼原因好了。結果發現是因為自己全程操作是在root使用者下的,而nginx是執行在www使用者下的。這TM就尷尬了,www的許可權不夠,不但無法訪問.git檔案(因為是root建立的),訪問不到root的金鑰連不上git,也無法修改root建立的專案檔案。蛋疼死了,那就要用www使用者重新走一遍流程。但是之前都做了那麼多工作了,於是st0rm23就改了一下許可權,讓www使用者也能正常使用。
找到web伺服器執行使用者
首先,我們要先找到nginx伺服器用的是哪一隻使用者。先看一下配置檔案,就可以看見第一行郝然寫著使用者是user www;這樣我們就知道了exec裡面的指令是由www使用者執行的。
$ vi /etc/nginx/nginx.conf
如果在nginx.conf的第一行把執行使用者改成user root;那麼nginx就以root來運行了,所有問題就解決了。但是安全性太差了,人家要是掛個一句話木馬什麼的估計要樂死了,一進來就是root。所以不能用root呀,我們還是老實地給www配許可權吧。
修改目錄所有者
我之前一直都是用root操作的,結果www對.git的訪問沒有許可權,/var/www/下的檔案也沒有修改的許可權,這就TM尷尬了,這還怎麼部署。所以我直接把整個/var/www/的所有權移交給www使用者了,反正這個目錄就是www的主目錄(後面會提到這是怎麼知道的),我們用chown指令修改一下就好了
$ chown -R www:www /var/www/
這樣目錄就可以移交給www使用者了,現在www使用者可以訪問.git檔案了,但是不幸的是www還是沒有許可權訪問gitlab,因為它訪問不到之前root的ssh金鑰,我們就要切換到www使用者,重新配置一下金鑰。
切換到執行使用者
接著我們我們切換到www使用者
$ su www
結果顯示“This account is currently not available.”,啥?這不讓我登入?別急,這是因為linux連他們登入shell的權利都給剝奪了,我們暫時給www權利就好了。到/etc/passwd中,把www使用者的配置修改一下,讓他的登入shell變成/bin/bash
;www:x:22:22:www:/var/www:/usr/sbin/nologin
www:x:22:22:www:/var/www:/bin/bash
我們還可以觀察到,www的使用者是屬於www使用者組的,他的主目錄為/var/www。記一下,待會有用的。然後www使用者就有許可權了。我們用su www重新切換一次,就會發現你現在是以www使用者登入了。
重建金鑰
之前生成的金鑰是root的,www使用者根本訪問不到這個金鑰,所有它連不上gitlab,提示沒有許可權訪問。我們要重新生成一個,生成的步驟和本文開篇一致,不在綴述。有了金鑰體系之後,還要嘗試訪問一下gitlab,讓www記下對方的機器簽名(之前我忘了這一步,匪夷所思了半天為啥我有金鑰了還顯示沒有許可權訪問)。然後你會愉快地發現,www使用者可以正常從gitlab訪問資料了。再試一試指令碼就可以正常使用了。
恢復執行使用者的nologin
不要忘了在/etc/passwd中,把www使用者的nologin選項恢復回去喲
www:x:22:22:www:/var/www:/usr/sbin/nologin
最後
哈哈哈,這回真的是可以用了,辛苦死寶寶了。