GitLab CEの設定ファイルをGitLab CE上でGit管理する

# はじめに

タイトルでGitって3回も言ってる。
この記事は、「[GitLab Advent Calendar 2020](https://qiita.com/advent-calendar/2020/gitlab)」8日目の記事です。

## 概要

GitLabの設定ファイルである下記の2ファイルをGitLab CE上でGit管理する手順をまとめました。

- `/etc/gitlab/gitlab.rb`
- `/etc/gitlab/gitlab-secrets.json`

また、同様の手順で、GitLab Runnerの設定ファイルも管理可能です。
私はrunnerのconfig.tomlのリポジトリは分けてGit管理しています。

- `/etc/gitlab-runner/config.toml`

## 前提

記事の内容は下記の環境を前提としています。

- OSはAmazon Linux (RHEL系)
- GitLab CE v12.9
  - Omnibus GitLab 

また、Gitリポジトリを置くプロジェクトの名前などは下記として説明します。
脳内でお好きな名前に置き換えてください。

- グループ名： **YOUR_GROUP**
- プロジェクト名: **PROJECT_NAME**
- ユーザー名(git push/pull用): **GITLAB_CONFIG_USER**

私はリポジトリ名は`gitlab-config`とか`gitlab-runner-config`という名前にしましたが、お好きな名前にしてください。

## 何ができるようになるか

### 設定の更新/反映はどんな操作になるか

下記のようになります。

- 設定の更新
  - ローカルのPCなどで設定ファイルの変更をGitリポジトリのmasterブランチにpush
- 設定の反映
  - GitLabサーバー上で設定ファイルの変更をgit pullして反映(スクリプトで一発でpullできるようにします)
  - `sudo gitlab-ctl reconfigure`など（いつものやつ）

### 最終成果物の構造の概要の説明

たとえば、/etc/gitlab/gitlab.rbをGit管理する時……

- サーバー上の`/etc/gitlab/`にローカルリポジトリがある状態になる。つまり、`/etc/gitlab/.git`がローカルリポジトリ。
- 手元のMacbookなどにも、cloneしてきたローカルリポジトリがある。
- bareリポジトリ（親のリポジトリ）は他のプロジェクトと同様にGitLab上で管理する。
  - つまり、`/var/opt/gitlab/git-data/repositories/YOUR_GROUP/PROJECT_NAME.git`みたいなパスの下にbareリポジトリが自動で管理されるはず。

# 手順

## サーバー上で操作をする前の準備

### GitLab上で普通のプロジェクトを作成する

リポジトリの置き先となる場所を作っておきましょう。
**YOUR_GROUP**の下に配置して、名前は**PROJECT_NAME**とします。

### git pullするためのGitLabユーザーを作成する

なぜユーザーを作るかというと、git pullやgit pushをする時にユーザーに紐付いたsshの秘密鍵が必要だからです。
別に普段使っている個人のユーザーの秘密鍵でも動かすことはできますが、そのユーザーが退職した時に、サーバー上でのgit pullがいきなりできなくなっては困るはずなので、専用のユーザーを作っておきましょう。
名前は**GITLAB_CONFIG_USER**とします。

このユーザーは**PROJECT_NAME**のメンバーにして、権限はMaintainerにしておきましょう。

### GitLabユーザーの公開鍵・秘密鍵を発行する

上で設定した**GITLAB_CONFIG_USER**にログインして鍵を発行しておきましょう。後でサーバーに配置するのは秘密鍵の方です。

## サーバー上の既存の設定をgit下に置く

GitLabサーバー上での作業です。

```sh
# rootとして作業
sudo su -
cd /etc/gitlab

git init

# 一応 --local でこのリポジトリだけの設定にしておく
git config --local user.name "あなたの名前を入れてください"
git config --local user.email "あなたのメールアドレスを入れてください"

# (重要！ 初回コミット前に .gitignore を作成し、ignoreしたいファイルやディレクトリを書いておきましょう)
# ".gitignoreについて"の項目に一応例を載せておきました。

git add -A
git commit -m "Initial commit"
```

## GitLab管理下に置くためにpushする

ローカルリポジトリへのコミットは終わったので、ここからはリモートリポジトリにpushするための準備です。（リモートとは言っても、localhost上にgitのサーバーはありますが……）

```sh
sudo su -
cd /etc/gitlab

# 同一サーバー上にリモートリポジトリがあるので、ホストはlocalhostにしておく
git remote add origin git@localhost:YOUR_GROUP/PROJECT_NAME.git
# 間違えてしまって再設定する場合は
# git remote set-url origin git@localhost:YOUR_GROUP/PROJECT_NAME.git

# （GITLAB_CONFIG_USERのGitLab push用秘密鍵を~/.sshに設置）
# (もちろんchmodして使えるようにしておいてください)

# push前の準備
eval "$(ssh-agent)"
ssh-add -k ~/.ssh/GITLAB_CONFIG_USERの秘密鍵

git push -u origin master
```

ここまでできたら、もうプロジェクト側に反映されたので簡単です。
後はローカルにgit cloneして色々変更を加えていきましょう。

## git pullを簡単にできるようにするスクリプトをリポジトリに追加する

サーバーでgit pullするたびにいちいち`sudo su -`して`eval "$(ssh-agent)"`して……という作業は面倒くさいので、スクリプトにしてリポジトリに追加します。

```sh:git-pull.sh（これをリポジトリに追加する）
#!/bin/sh

# git pullを楽にするためのスクリプト。
# rootで実行する必要がある。

# GitLab側で認証できる秘密鍵がないとgit pullできない
eval "$(ssh-agent)"
ssh-add -k ~/.ssh/GITLAB_CONFIG_USERの秘密鍵

# git pull。もしgitlab-runner側の場合は"/etc/gitlab/"のところが"/etc/gitlab-runner/"になる
/usr/bin/git -C /etc/gitlab/ pull
```

## 動作確認

まずはサーバー内でスクリプトをpullしてきます。

```sh
sudo su -
cd /etc/gitlab

eval "$(ssh-agent)"
ssh-add -k ~/.ssh/GITLAB_CONFIG_USERの秘密鍵

git pull
```

無事pullできたら、一旦ログアウトしましょう。
ec2-userなどから、下記のコマンドでpullが問題なくできればOKです。

```
sudo /etc/gitlab/git-pull.sh
```

後はプロジェクトのREADME.mdに、説明を書いてあげると親切になると思います。お疲れ様でした！

# 注意点

最後に一つだけ注意すべき点を挙げておきます。

- `/etc/gitlab/gitlab-secrets.json`

gitlab-secrets.jsonは、GitLabのアップデートがあった時に勝手に書き変わる可能性があるようです。アップデートで変更があったらサーバーの方からまた設定をcommitしてpushする必要があるので、それだけ覚えておきましょう。
Maintainerはmasterに直接pushできるようにしておいてもいいかもしれません。

# 付録

## .gitignoreについて

私はこんな設定にしてみたという一例です。今のディレクトリの状態にもよると思うので、参考程度にしてください。

### /etc/gitlab側

```:.gitignore
config_backup/
ssl/
trusted-certs/
```

### /etc/gitlab-runner側

```:.gitignore
config.toml.lock
```