GitLabにwebhookを設定し、mainブランチにpushがあった際にwebサーバーへ反映させる

AlmaLinux9
GitLab

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キーにしておきます
入力が終わったら「キーを追加」をクリックします

スクリプト作成

スクリプトは簡易的に作成しました
下記サイトを参考にさせていただきました

GitLab + WebHook で自動デプロイ - なつねこメモ
GitLab と WebHook を使って、 GitLab に push したタイミングで、 自動的にデプロイを行う方法のメモ。 GitHub や、 GitLab などで Web サイトやアプリを管理している時、 いい感じに push した...
GitlabのWebhookを使って簡易デプロイ(Webサーバへ)をしてみた - Qiita
以前、bitbucket-syncを使ってサーバ自動化をしてみたをやって簡易デプロイを行なう方法を公開しましたが、GitlabのWebhookがうまくいきませんでした。cronを使いGitlabリポ…


スクリプトの内容は、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アドレスとなるのでエラーが出てしまうようです

Allow `allow_local_requests_from_hooks_and_services` to be set via API (#25867) · Issues · GitLab.org / GitLab · GitLab
Summary After I update my GitLab to 11.5.3, the error 422 error Invalid url given occurred while I create webhook.

ローカルネットワークへの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

参考

本文中に記載した以外で参考にしたサイトです

GitLabからwebhook+PHPで超簡易自動デプロイシステムを作る - Qiita
GitLabのreleaseブランチにpushイベントがあったとき(⊃ マージされた時)にreleaseブランチに自動反映できるようにします。GitLab CI等のCIツールを入れるほどじゃない小…
GitlabのWebhookを使って簡易デプロイ(Webサーバへ)をしてみた - Qiita
以前、bitbucket-syncを使ってサーバ自動化をしてみたをやって簡易デプロイを行なう方法を公開しましたが、GitlabのWebhookがうまくいきませんでした。cronを使いGitlabリポ…

コメント

タイトルとURLをコピーしました