subversion時代に、trunkへコミットがあった際にwebサーバーへwebhookで反映するように設定していました
同じようなことをgitでもやりたかったのでやってみました
前提
実現したいこと
リポジトリ名 “test” のmainブランチにpushがあった際にwebサーバーの公開用ディレクトリへ自動で更新(pull)されるようにします
サーバー環境
GitLab(Self-Managed版)とwebサーバーは同一のサーバーで運用しております
- サーバーOS:AlmaLinux9
- webサーバー:apache2.4
- GitLab(Self-Managed版)v17.2.1-ee
- リポジトリ名:test
- ブランチ名(web反映用のブランチ):main
サーバーは外部からはアクセスできない社内ネットワーク内での運用を想定しておりますので、全体的に手順内のセキュリティ設定は緩めになっています
※ webサーバー公開用ディレクトリも社内公開用のwebディレクトリと捉えていただければと思います
本文中で注意書きも入れるよう心がけておりますが、環境によってはもちろん設定したほうが良いので、その点ご了承の上で本手順をご参考ください
ディレクトリ構成
/var/www/html
/test ← webサーバー公開用ディレクトリ
/gitlab_webhook ← webhookスクリプト配置先
webhookディレクトリの作成
webhookのスクリプトを配置するディレクトリを作成します
# mkdir /var/www/html/gitlab_webhook # chown root. /var/www/html/gitlab_webhook
apacheのconfファイルを新規作成します
社内ネットワーク内なのでRequire all grantedにしてますが、IPアドレス制限をしたい場合は Require ip 192.168.xxx.xxx/24 などに変更してください
# vi /etc/httpd/conf.d/gitlab_webhook.conf alias /gitlab_webhook/ /var/www/html/gitlab_webhook/ <Directory /var/www/html/gitlab_webhook/> AllowOverride all Require all granted </Directory>
SSHキーの設定
スクリプトで実施するコマンドのgit pullはhttpかSSH経由で実施しますが、SSHのが推奨されてるっぽいのでSSHを使用します
その際に、公開鍵と秘密鍵を設定せずに実施すると「Permission denied」が発生して失敗するので、それを回避するためにGitLabのSSHキーを登録します
まず鍵を作成する必要があるのでssh-keygenコマンドで鍵を作成します
# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa Your public key has been saved in /root/.ssh/id_rsa.pub The key fingerprint is: SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx@xx The key's randomart image is:
作成した鍵を/usr/share/httpdにコピーし、所有者とグループをapacheに変更します
この作業を実施しておかないと、git pullコマンド実行時にエラー(Warning: Identity file /usr/share/httpd/.ssh/id_rsa not accessible: No such file or directory.)が出てしまい、pullに失敗します
# cp -rp /root/.ssh /usr/share/httpd/ # chown -R apache. /usr/share/httpd/.ssh/
公開鍵の中身を表示します
表示したら中身すべて(ssh-rsaから最後の文字列まで)をコピーします
# cat /root/.ssh/id_rsa.pub ssh-rsa 文字列~
GitLabにアクセスします
[左上のユーザーアイコン]-[プロファイルの編集]-[SSHキー]をクリックします
「キー」欄に先ほどコピーした内容を貼り付けます
タイトルは何でも良いです、今回はtestキーにしておきます
入力が終わったら「キーを追加」をクリックします
スクリプト作成
スクリプトは簡易的に作成しました
下記サイトを参考にさせていただきました
スクリプトの内容は、mainブランチが更新されたときだけweb公開ディレクトリに移動して、git pullする簡単なコマンドです
参考にしたサイトでは、シークレットキーを設定しGitLab以外からのリクエストは受付しない用にしているみたいなので、必要に応じて設定してください(本環境は社内の閉鎖ネットワーク内想定なので省きました)
# vi /var/www/html/gitlab_webhook/webhook.php <?php $json = json_decode(file_get_contents('php://input'), true); if(isset($json)){ if($json['ref'] != 'refs/heads/main') { // mainブランチが更新されたときのみ実施する exit(); } } exec('cd /var/www/html/test/ ; git -c core.sshCommand="ssh -i ~/.ssh/id_rsa -F /dev/null" pull'); exit(); ?>
GitLabでwebhookの設定
GitLabへアクセスし、webhookを設定します
プロジェクトから対象のリポジトリ(本環境では”test”)を開きます
左ペインから[設定]-[webhooks]をクリックします
「新しいWebhookを追加」をクリックします
URLを入力します
http://192.168.xxx.xxx/gitlab_webhook/webhook.php
※ ホスト名は環境に合わせて変更してください
トリガーは「プッシュイベント」「すべてのブランチ」にチェックを入れます
すべてのブランチに対してイベント有効にすると、開発ブランチも対象になってしまうのではないかと思うかもしれないですが、スクリプト内のif分岐でmainブランチの時のみ実行にしているので大丈夫です
シークレットトークンは、セキュリティ的には設定したほうが良いですが、先ほど申し上げた通り本環境は社内閉鎖ネットワーク内想定のため、設定しませんでした
上記を設定したら「Webhook を追加」をクリックします
下記のように作成したwebhookが表示されればOKです
URLに指定したアドレスによっては「Invald url given」が出て、webhookの追加に失敗することがあります
その場合は、次の「Invald url givenのエラーが出た場合」の手順を実施して「アウトバウンドリクエスト」の設定変更を実施します
Invald url givenのエラーが出た場合
Webhooksを追加クリック後、Invald url givenのエラーが出ることがあります
原因はローカルネットワークからのWebhookを無効に設定しているためです
本環境ではwebサーバーとGitLabを同一サーバーで運用しており、URLのホスト名が自身のIPアドレスとなるのでエラーが出てしまうようです
ローカルネットワークへのWebhookを有効にすることで、事象は回避できます
[Admin area]-[設定]-[ネットワーク]の[アウトバウンドリクエスト]項目を展開します
「ウェブフックとインテグレーションからローカルネットワークへの要求を許可する」にチェックを入れて、「変更を保存」をクリックします
設定変更後、先ほどと同じ手順でWebhookを追加するとエラーが出なくなりました
webサーバー公開用ディレクトリにリポジトリをクローンする
今の状態だとwebサーバー公開ディレクトリはまだgit管理下に置かれていないので、pullすることができません
git管理下に置いたうえで、リモートリポジトリにはすでにいくつかファイルを作成してありますのでそれらをクローンします
プロジェクトから対象のリポジトリ(本環境では”test”)を開きます
「コード」をクリックし、SSHでクローンのURLをコピーします
リポジトリを作成したいディレクトリに移動の上、git clone をコマンドで実行します
リポジトリ名の”test”がそのままディレクトリとして作成されますので、/var/www/html/testではなく/var/www/htmlに移動しています
(もし/var/www/html/testと指定してしまうと/var/www/html/test/testになります)
clone の後ろには、複製する既存リポジトリを指定します(先ほどコピーした内容を貼り付けます)
# cd /var/www/html # git clone git@192.168.xxx.xxx:root/test.git
リポジトリが作成されていることを確認します
git管理下に置かれている場合、ディレクトリに.gitが作成されていますので、aオプションを付けて確認します
# ll -a /var/www/html/test 合計 40 drwxr-xr-x 4 root root 242 8月 5 14:49 . drwxr-xr-x 11 root root 302 8月 5 14:49 .. drwxr-xr-x 8 root root 163 8月 5 14:49 .git ← git管理下であることがわかる -rw-r--r-- 1 root root 33 8月 5 14:49 20240801.txt -rw-r--r-- 1 root root 6160 8月 5 14:49 README.md
testディレクトリはweb公開用にしたいので所有者とグループを変更します
# chown -R apache. /var/www/html/test
git cloneではなく、git init とgit remote addコマンドではダメなのか?と思う方いらっしゃるかもしれませんが、結論ダメではないです!
pull先であるwebサーバー公開ディレクトリの方にすでにファイルを置いてある場合はgit cloneではなく、git init とgit remote addコマンドを使うほうがよさそうです
https://qiita.com/komi-21/items/5d3ffe7e27b40e976e6b
今回はwebサーバー公開ディレクトリにはまだファイルがなかったので、git cloneの方が楽に出来そうだったのでこちらを採用しました
webhookの実行確認
試しに新しいファイルをmainにプッシュし、スクリプトが動くか実行してみます
GitLabのプロジェクトから対象のリポジトリ(本環境では”test”)を開きます
[+]-[新しいファイル]をクリックします
ファイル名と中身を適当に設定して、「変更をコミットする」をクリックします
web公開用ディレクトリに追加したファイルが表示されているか確認します
# ll /var/www/html/test
webhookが動かなかった場合
下記のようにスクリプトで実行しているコマンドをプロンプト上で実行し、動作するか確認します
cdコマンドは失敗しないと思いますので、おそらくpullコマンドの方で何かしらエラーが表示されるかと思いますので、そのエラーの内容をもとに原因を調査してみてください
web公開ディレクトリの所有者はapacheなので、sudo -uでapacheユーザーでコマンド実行する必要があるので注意してください
# cd /var/www/html/test # sudo -u apache git -c core.sshCommand="ssh -i ~/.ssh/id_rsa -F /dev/null" pull
参考
本文中に記載した以外で参考にしたサイトです
コメント