RedmineとGitLabをNFSで連携させる

Redmineには[バージョン管理システムとの連携機能](http://redmine.jp/tech_note/subversion/)がありますが、Redmineはリモートのリポジトリにアクセスすることができないため、Redmineのサーバーの外にリポジトリがある場合、連携機能が使えません。
某所でリポジトリ管理をGitLabで行っているのですが、GitLabとRedmineがそれぞれ別のサーバーにあるため、上記の通りRedmineの連携機能が使えませんでした。

このままではいろいろと不便なので、NFSを使ってGitLabサーバー上のリポジトリをネットワーク越しにローカルファイルシステムにマウントするようにして、Redmineのバージョン管理システム連携を使えるようにしてみました。

# GitLabサーバー側の準備

## NFSの設定

NFSサーバーに必要なパッケージをインストールします。

### パッケージのインストール

```shell-session
# yum install -y nfs-utils
```

### /etc/exports の設定

`/etc/exports` にNFSで共有するディレクトリを設定します。
共有先は `192.168.0.205` （RedmineサーバーのプライベートIP）に限定します。
読み込みのみ許可(ro)、UID/GID を 501 に固定 (all_squash,anonuid=501,anongid=501) に設定します。
なお、UID は GitLab の実行ユーザ *git* の UID に合わせています。

`/home/git/repositories` は、GitLabが管理しているGitリポジトリが保存されているディレクトリです。
これを外部からマウントすれば、GitLabが持つGitリポジトリに直接アクセスすることが可能になります。

```text:/etc/exports
/home/git/repositories 192.168.0.205/32(ro,sync,all_squash,anonuid=501,anongid=501)
```

### /etc/sysconfig/nfs の設定

NFSは動的にリッスンポートを変えるため、ファイアウォールとの相性がよろしくない場合があります。
`/etc/sysconfig/nfs` を以下のように変更して、ポートを固定にします。

```bash:/etc/sysconfig/nfs
# TCP port rpc.lockd should listen on.
LOCKD_TCPPORT=32803

# UDP port rpc.lockd should listen on.
LOCKD_UDPPORT=32769

# Port rpc.mountd should listen on.
MOUNTD_PORT=892

# Port rpc.statd should listen on.
STATD_PORT=662
```

## ファイアウォールの設定

NFSは複数のポートをリッスンするので、`iptables` の設定で以下のようにポートを開放しておく必要があります。
念のため、共有先のIPを制限しています。

```bash
# NFS (Redmineサーバに対してのみ共有)
# rpcbind/sunrpc
iptables -A INPUT -p tcp -s 192.168.0.205 --dport 111 -j ACCEPT
iptables -A INPUT -p udp -s 192.168.0.205 --dport 111 -j ACCEPT
# nfslock
iptables -A INPUT -p tcp -s 192.168.0.205 --dport 32803 -j ACCEPT
iptables -A INPUT -p udp -s 192.168.0.205 --dport 32769 -j ACCEPT
# mountd
iptables -A INPUT -p tcp -s 192.168.0.205 --dport 892 -j ACCEPT
iptables -A INPUT -p udp -s 192.168.0.205 --dport 892 -j ACCEPT
# statd
iptables -A INPUT -p tcp -s 192.168.0.205 --dport 662 -j ACCEPT
iptables -A INPUT -p udp -s 192.168.0.205 --dport 662 -j ACCEPT
```

# Redmineサーバー側の準備

## /etc/fstab の設定

マウントできるように、`/etc/fstab` に以下を追記します。

```text:/etc/fstab
192.168.0.208:/home/git/repositories /gitlab-repos nfs   ro,nosuid,noexec,auto,nouser  0 0
```

`192.168.0.208` はGitLabのプライベートIPです。
これを `/gitlab-repos` にマウントするようにしています。

## ユーザーの設定

`/gitlab-repos` をマウントすると、すべてのファイル・ディレクトリがUID:501になっています。これはGitLabサーバーのユーザー *git* のUIDです。
RedmineサーバーでもUID:501でユーザー *git* を作成しておきます。GIDも同様です。

GID:501 にグループ *git* を割り当てたら、ユーザー *redmine* の補助グループにグループ *git* を追加します。
これでGitLabサーバーのリポジトリを、Redmineから読み込めるようになります。

# Redmine での設定

Redmineでバージョン管理連携を有効にするには、プロジェクトの設定画面のリポジトリのパスに `/gitlab-repos/<GitLab上のリポジトリのパス>` を設定します。

あとは `git commit -m "fixes #9999 @1.0h"` などすれば、チケットのクローズや作業時間の記録がgitのコミット操作から可能になります。便利！

## リポジトリの自動更新

何もしないとRedmineはメニューの「リポジトリ」のリンクを開くまで、リポジトリの情報を更新しません。
したがって、チケットのクローズや作業時間の記録をコミットログから行っても、リポジトリのリンクを開くまでは反映されません。

これはめんどくさいので、`crontab` に以下のコマンドを仕掛けて、15分おきに全リポジトリの更新情報を取得するようにしました。

```text
*/15 * * * * curl -L 'http://redmine.example.com/sys/fetch_changesets?key=<RedmineのAPIキー>' > /dev/null
```

`key` パラメータはRedmineの管理設定→リポジトリから取得可能です。

# まとめ

- GitLabサーバーにNFSサーバーを設定しました
- RedmineサーバーからGitLabのリポジトリをネットワーク経由でマウントできるようにしました
- マウントしたNFSボリュームにRedmineがアクセスできるように設定し、バージョン管理連携機能が使えるようにしました
- ついでにリポジトリの自動更新も設定しました

# おわりに

NFSとかの設定は面倒なのでRedmineとGitLabは同じサーバーに入れとくのがベストプラクティスだと思いました。