サブディレクトリホスティングのGitLabでglabを使う方法
はじめに
glab CLIのセットアップをしていたら意外とハマった。
原因が分かりにくく、まとまった日本語情報も見当たらなかったため、調査結果と対処方法をメモとして残します。
環境構成
すべてEC2にDockerで構築しています。
| ツール | バージョン | 備考 |
|---|---|---|
| GitLab | CE 17.11.7 |
http://<ホスト>/gitlab/でホスティング |
| GitLab Runner | 17.11.1 | |
| postgres | 14.9 | GitLab用のDB |
| Apache | 2.4.57 | リバースプロキシ |
Collaborageで構築したのち、バージョンをアップデートしたものです。
docker-compose.ymlはこれ
手順
Step 1:glab auth login を通す
--hostname にはドメイン名(またはIPアドレス)のみ、--api-host にサブディレクトリ付きで指定します。
glab auth login \
--hostname <ホスト> \
--api-host <ホスト>/gitlab \
--api-protocol http \
--token <Personal Access Token> \
--git-protocol http
認証が通ったか確認をします。
$ glab auth status
26.x.x.x
✓ Logged in to 26.x.x.x as username (GITLAB_TOKEN)
✓ Git operations for 26.x.x.x configured to use http protocol.
✓ API calls for 26.x.x.x are made over http protocol.
✓ REST API Endpoint: http://26.x.x.x/gitlab/api/v4/
✓ GraphQL Endpoint: http://26.x.x.x/api/graphql/
✓ Token found: **************************
全ての項目にチェックがついていればOKです。環境によってはgitlab.comの結果も出るかもしれませんが、今回は使わないので気にしないでください。
Step 2: glab-resolved を手動修正する
glab auth statusは通るようになりましたが、サブディレクトリホスティングの場合はもう少し設定が必要です。
glab-resolved は、glabが.git/configに設定して、内部的に利用する値です。glabはこの値をもとにAPI呼び出し先のプロジェクトを特定します。
glabはホスト直下にホスティングするケースを前提としているようで、サブディレクトリホスティングの場合、自動生成される値にサブディレクトリ部分が余計に含まれてしまいます。
# 壊れた状態(自動生成)
[remote "origin"]
glab-resolved = base:gitlab/GROUPNAME/PROJECTNAME
手動でサブディレクトリ部分を除去します。
# 手動修正後
[remote "origin"]
glab-resolved = base:GROUPNAME/PROJECTNAME
Step 3:リバースプロキシ(Apache)の設定修正
最後に、リバースプロキシの設定です。
Apacheの ProxyPass はデフォルトでURLを正規化(canonicalize)するため、URL エンコードされた / (%2F)が実体の / として解釈されます。
GitLab API では、パスパラメータに %2F を含めたリクエストを行うケースがあり、この正規化によって意図しないパスに変換されます。
私の環境ではプロキシ起因でAPIリクエストが失敗していたので、Apacheの設定を修正しました。
GitLabのProjects APIの仕様を見てみると、パスパラメータ:idの説明に以下のように書かれています。
The ID or URL-encoded path of the project.
2種類の形式が認められているようですが、glabは後者のURL-encoded path of the project形式でリクエストパスを構築するようです。
この値は具体的にはGROUP/PROJECTのようになるのですが、区切りの/がURLデコードされると:idをうまく解釈できず、404エラーになってしまいます。
以下のように %2F を含むAPIリクエストを送ると、nocanon なしでは404エラーが返ります。
# プロジェクトパスを%2Fでエンコードして直接APIを叩く
$ curl "http://<ホスト>/gitlab/api/v4/projects/<グループ>%2F<プロジェクト>" \
-H "PRIVATE-TOKEN: <トークン>"
Apacheの設定ファイル(例:/usr/local/apache2/conf/httpd.conf)の GitLab 用 ProxyPass ディレクティブに nocanon オプションを追加します。
<Location /gitlab>
ProxyPass http://gitlab/gitlab nocanon
ProxyPassReverse http://gitlab/gitlab
</Location>
設定を反映後、同じcurlコマンドを再度実行して200でプロジェクト情報のJSONが返ればOKです。
nocanonはURLの正規化を無効にするため、セキュリティリスクが高まる可能性があります。
信頼できるネットワーク内での利用や、バックエンド側での適切なバリデーションが前提となります。
Step4: glabの動作確認
最後にglabの動作確認です。これでマージリクエストの一覧が標準出力に出ればOKです。
$ glab mr list
Showing 2 open merge requests on group/repositoryname. (Page 1)
!305 group/repositoryname!305 Draft: glab導入 (develop) ← (fe...
!304 group/repositoryname!304 202602定期リリース (main) ← (develop)