Redmine 4.2 と Gitolite (gitolite3) 連携
Redmine 4.2 移行の続き。今回は Git サーバー構築と Redmine 連携を実施する。
サーバーのドメインは xxxx.vs.sakura.ne.jp
、作業用ユーザーは akabeko
としておく。本記事を参考にする場合、この箇所を自身のドメインへ置き換えること。
Gitolite
Git 公式サーバー Gitolite 環境を構築してゆく。基本手的に以下の記事を踏襲。
はじめにローカル環境で Gitolite 用の公開鍵認証ファイルを生成。
$ ssh-keygen -f gitolite
これで秘密鍵 gitolite
と公開鍵 gitolite.pub
ファイルを得られる。秘密鍵を ~/.ssh
内へ移動したら ~/.ssh/config
に以下の設定を追加。HOSTNAME
部分はサーバーに割り当てたドメインか IP アドレスにすること。この例ではドメインにしている。
HOST gitolite-admin
HOSTNAME xxxx.vs.sakura.ne.jp
USER gituser
PORT 22
IDENTITYFILE ~/.ssh/gitolite
公開鍵を Redmine/Git サーバーにアップロードしておく。場所は作業用ユーザーのホーム。これでサーバー側に ~/gitolite.pub
が置かれた状態となるはず。
Gitolite 管理ユーザーを追加。名前は gituser
とした。
$ sudo useradd --shell /bin/bash --home /home/gituser gituser
アップロードしておいた SSH 接続用の公開鍵を gituser の HOME へ移動して所有者とパーミッションを変更。
$ cd
$ sudo mv gitolite.pub /home/gituser
$ sudo chown gituser:gituser /home/gituser/gitolite.pub
$ sudo chmod 644 /home/gituser/gitolite.pub
$ sudo ls -l /home/gituser/
total 4
-rw-r--r-- 1 gituser gituser 405 Aug 19 15:03 gitolite.pub
Gitolite のインストールと初期設定。dnf
を利用するが CentOS 8 Stream の標準リポジトリーには存在しない。
$ sudo dnf search gitolite
Last metadata expiration check: 1:13:18 ago on Thu 19 Aug 2021 02:05:00 PM JST.
No matches found.
そのため EPEL リポジトリーを追加してからインストールする。前回の記事で済ませていると思われるが、念の為にここでも追加コマンドを掲載しておく。
Gitolite のパッケージ名は gitolite
ではなく gitolite3
なので注意すること。
$ sudo dnf install epel-release
$ sudo dnf --enablerepo=epel install gitolite3
Gitoite の初期化。
ユーザーを gituser
に変更してから gitolite setup
コマンドに公開鍵ファイルを指定して実行。
$ sudo su - gituser
$ gitolite setup -pk gitolite.pub
Initialized empty Git repository in /home/gituser/repositories/gitolite-admin.git/
Initialized empty Git repository in /home/gituser/repositories/testing.git/
WARNING: /home/gituser/.ssh missing; creating a new one
(this is normal on a brand new install)
WARNING: /home/gituser/.ssh/authorized_keys missing; creating a new one
(this is normal on a brand new install)
表示されている警告は .ssh
ディレクトリーが存在しないため、公開鍵と一緒に作成しましたというもの。実際に vi
で ~/.ssh/authorized_keys
を開くと、公開鍵の内容が転載されていることを確認できるはず。
公開鍵はもう必要ないので消しておく。
$ cd
$ rm gitolite.pub
gituser
から抜ける。
$ exit
ローカルから Redmine/Git サーバーの Gitolite へ SSH 接続するため、設定ファイルを開く。
$ sudo vi /etc/ssh/sshd_config
設定ファイルの AllowUsers
に gituser
を追加。もしこの設定がなければ項目ごとファイル末尾へ追加しておく。内容は SSH 接続したいユーザーを半角スペース区切りで列挙。いつも SSH 接続してログインしているユーザーを akabeko
として gituser
を追加した場合は以下のようになる。
# AllowUsers
AllowUsers akabeko gituser
編集が完了したらファイルを保存して SSH デーモン再起動。
$ sudo systemctl restart sshd
実験としてリポジトリーをローカルに clone してみる。Gitolite はテスト用に testing
というリポジトリーを用意しているのでこれを対象とした。リポジトリーのサーバーとして指定するのはローカルの ~/.ssh/config
に設定した名前になるので注意すること。この名前に続けて :リポジトリー名
としたものが clone 元となる。
$ git clone gitolite-admin:testing
Cloning into 'testing'...
エラーが出る場合はここまでの設定を見直すこと。
リポジトリー移行、失敗編
事前に新サーバーの作業ユーザー HOME へバックアップしておいた旧サーバーの repositories.zip
を転送してから展開済しておくこと。これはリポジトリーの実体となる。
$ unzip repositories.zip
ローカルに新 Gitlolite の gitolite-admin
を git clone
してから、旧 Gitolite の gitolite-admin
にある conf/
と keydir/
の中身を gitolite.pub
以外、新 Gitolite 側へコピー。これで新 Gitolite 側に管理しているリポジトリーとユーザー情報の設定が移行されたので、このまま commit
してから push
。
ユーザーを gituser
に切り替えて中身を確認。
$ sudo su gituser
$ cd
$ ls -l repositories/
...ここに空のリポジトリー一覧が表示されるはず
リポジトリーのディレクトリーをリネームしてから gituser
を抜ける。
$ mv repositories/ _repositories
$ exit
作業ユーザーでリポジトリーの実体を移動してからパーミッションを変更。
$ sudo mv repositories/ /home/gituser/
$ sudo chown -R gituser:gituser /home/gituser/repositories
これでいけるかと思ったのだが、試しに testing
を改めて clone
するとエラーになった。
FATAL: split conf set, gl-conf not present for 'testing'
fatal: Could not read from remote repository.
どうやら Gitolite v2 と v3 間で破壊的な変更がおこなわれたようだ。公式サイトに移行方法を掲載したページが公開されている。
手順を読むとかなり面倒。危険そうな手動のファイル操作もある。なので一旦、新 Gitolite のリポジトリーに戻す。
$ sudo su gituser
$ mv repositories/ __repositories
$ mv _repositories/ repositories
これで gitolite-admin
に初設定が push
された状態となった。
リポジトリー移行、成功編
失敗編では旧リポジトリーの実データをそのままサーバー上で置き換えようとした。これがダメだったので正攻法というか標準の git
コマンド操作でリポジトリーを移行してみる。
まずは対象リポジトリーをメモ。さきほど戻した gituser
の repositories
内にあるものがそれにあたるので ls -1
で名前だけ縦に並べてコピペしておく。リポジトリーのディレクトリー末尾には .git
が付いている。これは後述する git clone
ではあってもなくてもよいのだが、私としてはいつも無しで指定しているため除去しておいた。これに加えて以下の準備が済んでいることを前提とする。
- ローカルの
~/.ssh/config
に新旧 Gitolite サーバーの SSH 接続設定を登録すみ- ここではわかりやすくそれぞれ
gitolite-old
とgitolite-new
としておく
- ここではわかりやすくそれぞれ
- ローカルで
git
コマンドを利用可能
ローカルに適当なディレクトリーを作成して、そこで移行作業をしてゆく。例えば対象リポジトリーが sample
なら以下のようにコマンドを実行。
$ git clone --mirror gitolite-old:sample sample
$ cd sample
$ git remote set-url --push origin gitolite-new:sample
$ git push --mirror
$ cd ../
$ rm -rf sample
順番に解説する。
--mirror
として旧サーバーからリポジトリーをgit clone
- リポジトリーのリモート URL を
git remote set-url
で新サーバーに変更 - リモートが新サーバーを指すようになったので
git push
により全履歴を送信
これを繰り返してゆけばよい。もしもリポジトリーの数が多くて面倒ならシュエル スクリプトで処理するのもありだ。新サーバー側から git clone
し直してみて全履歴があれば成功。
Redmine 連携の準備
サーバーに SSH 接続後、Gitolite 管理下のリポジトリ本体からミラーリングして Redmine から参照するための Git リポジトリ用ディレクトリーを作成して移動。
$ sudo mkdir /var/lib/git
$ sudo cd /var/lib/git
リポジトリーを clone
してゆく。
$ sudo git clone --mirror /home/gituser/repositories/testing
オーナー設定。Gitolite ユーザーを設定しておく。面倒なので /var/lib/git
ごと変更してから、このディレクトリーを root
に戻している。
$ sudo chown -R gituser:gituser /var/lib/git
$ sudo chown root:root /var/lib/git
この時点で clone
された各リポジトリーのパーミッションは 755
のはず。もしそうなっていないとしたら変更しておくこと。
$ sudo chmod -R 755 /var/lib/git/testing.git/
Git サーバーへ push
された際に上記リポジトリーへ同期するための設定。作業用ユーザーをユーザー グループ gituser
へ追加。id
コマンドで gituser
へ所属していることを確認。
$ sudo gpasswd -a akabeko gituser
Adding user akabeko to group gituser
$ id akabeko
uid=1000(akabeko) gid=1000(akabeko) groups=1000(akabeko),1001(gituser)
これで Redmine 稼働ユーザーを作業用ユーザー akabeko
にすれば、ここを参照可能になったはず。ただしミラーリング元からこのリポジトリに対して git push --mirror
が実行された場合 testing.git/objects
などにディレクトリが追加されるのだがパーミッションは 700
になる。つまり所有者しかアクセスできない。というわけで以下の記事を参考にリポジトリー毎の config
ファイルの設定を変更する。
$ cd /var/lib/git/testing.git
$ sudo git config core.sharedRepository group
push
をフックしてミラーへ同期
Git フックを利用して Gitolite 上のリポジトリに push がおこなわれたらミラーリング リポジトリ側にも反映されるようにする。
はじめに hook 時のパーミッション設定を変更。gituser の HOME にある .gitolite.rc
の REPO_UMASK を編集する。gituser になってからファイルを開く。
$ sudo su gituser
$ cd
$ vi .gitolite.rc
かつて REPO_UMASK
だった設定は gitolite3 だと UMASK
になっているのでこれを探す。デフォルトのパーミッション 0077
を 0027
に変更してからファイルを保存。この作業は一度だけ実施すればよい。
# default umask gives you perms of '0700'; see the rc file docs for
# how/why you might change this
UMASK => 0027,
リポジトリー毎にフックを設定してゆく。gituser
で例えば testing.git
内の hooks ディレクトリに post-receive というファイルを新規作成。
$ sudo su - gituser
$ cd repositories/testing.git/hooks
$ vi post-receive
このファイルにはシェル スクリプトとして記述できる。今回はミラーリング リポジトリとなる /var/lib/git/testing.git
に変更を git push --mirror
として反映する処理を書いて保存。
...とゆきたいところだが gitolite3
では UMASK
を 0027
にしても mirror 側のパーミッションが共有にならず、Redmine から参照すると 404 になるようだ。そのためスクリプトからパーミッションを明示的に変更する。
#!/bin/sh
/usr/bin/git push --mirror /var/lib/git/testing.git
find /var/lib/git/testing.git/ -type d -print | xargs chmod 755
find /var/lib/git/testing.git/ -type f -print | xargs chmod 644
/var/lib/git
は所有権を gituser:gituser
に設定しているため、その配下なら gituser
が実行するスクリプトで自由にパーミッション設定可能。これを利用して mirror 側のリポジトリーについて、ディレクトリーとファイルすべてを全共有にしている。もっと細かく厳密に権限を設定したければスクリプトをいじってもよい。
スクリプトに実行属性を付けておく。
$ chmod 700 post-receive
正しく設定できているなら testing.git
へ push
が行われるたびにミラー側へも変更が反映されるはず。私の環境では Redmine 上のリポジトリー画面で push
した結果を確認できた。
おわりに
これにて Redmine/Git サーバーの移行は完了。2022/3 現在も特に問題なく動作している。
最近は Linux 系ミドルウェアを Docker 利用で済ませているが、たまにはこうして素のミドルウェアへ触れてみるのも楽しいものだ。次に Redmine/Git サーバーを移行するのは相当に先となりそうだが、その際に今回の記事が参考になればと願っている。