GCP(GCE)にGitLabを構築してみる

# はじめに

Gitのソース管理やチケットなどのプロジェクト管理を、現状はBacklogのサービスを利用しているのですが、
今後CI/CDや色々な機能と連携させて便利な環境を構築していきたいなということで、とりあえずGitLabでも構築してみようというのが目的です。
まずはGitLabの構築から始め、後々いろいろと機能を連携させる部分もまとめていけたらと。

# 構成

- GCP(GCE)に構築
  AWSではなくGCPを選択したのは単に自分の好みです(笑)
  Google Workspaceを利用しているというのも理由の一つではありますが
- 独自ドメインで運用
- SSL証明書(https)の管理はGCPのロードバランサを利用
- 利用は小規模(50人未満)を想定
- メール送信にはSendGridを利用
- Googleアカウントでログイン可能にする
  Google Workspaceを利用しているので、アカウントは統一したい
- CI/CD(GitLab Runner)を利用する
- GitLab Pagesを有効にする

# 前提(前準備)

GCP(Google Cloud Platform)のアカウントは既に取得済み前提です。

https://cloud.google.com/

まずは今回用のプロジェクトを作成し、管理画面にアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/7edf30eb-e860-b28e-18b5-b01e64ff10d4.png)


# GCE(Google Compute Engine)にGitLabをインストール

## インスタンスの用意

まずはGitLabをインストールするVMをGCEに用意します。

* 東京リージョン(ゾーンは適当)
  →東京は多少割高になるので、他の割安のリージョンを選択するのもありです。
* マシンタイプは`e2-standard-2 (2CPU, 8GB)`
  →Gitとして以外にもいろいろとカスタムしたいので、2CPU/8GBぐらいが最低ラインかなと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/be10d9f6-6925-ab3d-3db7-5a7b3b27bf64.png)

ブートディスクは変更して、`Ubuntu`を利用します。（これは自分の好みｗ

* Ubuntu 20.04 LTS
  →GitLabの推奨インストールとして`18.04 LTS / 20.04 LTS`とあるので、新しいほうで。
* 100GB
  →Gitとして利用するので、容量は多少多めに100GB。（後から拡張できるので、最初はもっと少なくてもいいかも。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/27c05db9-e70c-e5d9-12ea-e1cd3961bca2.png)

この構成での月額は10,605円。(＄75.75×140円)
Backlogのプレミアムプランが、~~年217,800円~~ 年338,580円なのでコスト的には許容範囲。
（というより、かなりコストカットが見込める。初期段階ではですが。）
※2022/10時点で、Backlogの料金値上げが発表されました。(年217,800円→338,580円)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/2bb6d677-e314-affc-a5b4-fd5d135cd13d.png)
これをアイオワ(us-central1)リージョンとかにすると8,249円。
多少割安になります。（あれ？思ったより差があるような？。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/91874bc7-6dae-f511-dc8b-63b933ca9b1a.png)
逆にマシンタイプをE2からN2に変更する(東京リージョンで)と12,006円。
多少割高になります。（N2は最新のCPUを利用するタイプ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/d7f626f4-081a-b264-015a-f2b95a482f81.png)
このあたりは予算と相談してチューニングしてください。

今回はロードバランサを入れる予定なので、外向けのファイアーウォール設定はそのままとします。（チェックしないまま。
※ロードバランサを利用せずに外部から直接GCEにアクセスさせる場合には、HTTP/HTTPSを開けてあげる必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/4e215184-f622-68bf-d649-d93e131cad99.png)

これで作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/c744752d-c0c0-6718-3fb1-e19b357da27a.png)

## インスタンスの設定

SSHの接続を選択し、コンソールを開きます。
まずは`root`ユーザーのパスワードを変更しておきます。
```shell-session
$ sudo passwd root
New password: 
Retype new password: 
passwd: password updated successfully
```

初期状態では時刻がUTCになっているので、日本時刻にしておきます。（ここは好みで。
```shell-session
$ date
Mon Sep  5 13:26:45 UTC 2022
```
```shell-session
$ sudo timedatectl set-timezone Asia/Tokyo
$ date
Mon Sep  5 22:28:56 JST 2022
```

あとはシステムを最新化しておきます。
```shell-session
$ sudo apt update
$ sudo apt upgrade
```

## GitLabのインストール

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

GitLabのインストールに必要なパッケージをインストールしておきます。

```shell-session
$ sudo apt install curl openssh-server ca-certificates
```

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

> Community EditionとEnterprise Editionの違い
> GitLab Enterprise Editionをインストールしてライセンスを未登録のまま使用することと、GitLab Community Editionをインストールして使用することに表面的な違いはありません。
> *https://www.gitlab.jp/install/ce-or-ee/*

ということらしく`Enterprise Edition`のインストールが推奨されていたので、`Community Edition`ではなく`Enterprise Edition`を利用します。

公式の手順では、`EXTERNAL_URL`で運用するドメインを指定してのインストールとなっていますが、ここではあえて指定せずにインストールします。
ここで`https://`のURLを指定すると、自動的にSSLの設定が有効になってしまうからです。
今回はGCPのロードバランサでSSLの設定を行う為、運用ドメインの設定は後から変更します。

```shell-session
$ curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
$ sudo apt install gitlab-ee

Thank you for installing GitLab!
GitLab was unable to detect a valid hostname for your instance.
Please configure a URL for your GitLab instance by setting `external_url`
configuration in /etc/gitlab/gitlab.rb file.
Then, you can start your GitLab instance by running the following command:
  sudo gitlab-ctl reconfigure
```

これでインストールは完了ですが、`EXTERNAL_URL`を指定しなかったので起動はしていません。
`external_url`を設定して`sudo gitlab-ctl reconfigure`してねと案内が出てるはず。

ヘルスチェックにアクセスしてみても、下記の通りエラーとなります。

```
$ curl http://localhost/-/health
curl: (7) Failed to connect to localhost port 80: Connection refused
```

というわけで、`/etc/gitlab/gitlab.rb`を編集します。
該当の項目を下記の通り書き換えます。

```ruby:/etc/gitlab/gitlab.rb
# 運用するドメイン
external_url 'https://gitlab.xxx.com'

# Let's Encryptは無効
letsencrypt['enable'] = false

# Nginxの設定
nginx['enable'] = true
nginx['listen_port'] = 80
nginx['listen_https'] = false

# プロキシ追加ヘッダー
nginx['proxy_set_headers'] = {
  'X-Forwarded-Proto' => 'https',
}

# ヘルスチェックの許可IP
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '::1/128', '130.211.0.0/22', '35.191.0.0/16']
```

変更点としては下記。

* 運用するドメインの設定 - external_url
  ここは外部アクセスする際のアドレスなので、httpsのアドレスを設定します。
* nginxの設定 - nginx[]
  Nginxを利用し、ポート80(http)で受付するように設定します。
* ヘルスチェックの許可IP - gitlab_rails['monitoring_whitelist']
  後ほどロードバランサからのヘルスチェックを設定するので、ヘルスチェック元のIPアドレスをホワイトリストに追加します。
  `130.211.0.0/22, 35.191.0.0/16`
  ヘルスチェック元のIPアドレスは下記参照。
  *https://cloud.google.com/load-balancing/docs/https/#firewall-rules*

設定ファイルの編集が終わったら下記コマンドでGitLabを再構築します。

```shell-session
$ sudo gitlab-ctl reconfigure
...
Notes:
Default admin account has been configured with following details:
Username: root
Password: You didn't opt-in to print initial root password to STDOUT.
Password stored to /etc/gitlab/initial_root_password. This file will be cleaned up in first reconfigure run after 24 hours.

NOTE: Because these credentials might be present in your log files in plain text, it is highly recommended to reset the password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

gitlab Reconfigured!
```

rootユーザーの初期パスワードが`/etc/gitlab/initial_root_password`に出力されているので、控えておきます。

```shell-session
$ sudo cat /etc/gitlab/initial_root_password
```

再構築が完了したら、再度ヘルスチェックにアクセスしてみます。
正常に起動していれば、下記のように`GitLab OK`が返却されます。

```shell-session
$ curl http://localhost/-/health
GitLab OK
```

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

無事にGitLabが起動出来たら、ロードバランサからアクセス可能なようにファイアーウォールの設定をしておきます。
VPCネットワーク > ファイアウォールと進み、ファイアーウォール ルールを作成を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/1a964297-b2d2-1115-3efb-bbda5bd17da6.png)

ここで作成するのは、ロードバランサからポート80でのアクセスを許可する設定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/cdcb53c3-4dc7-9235-1826-11c8e9f5bb11.png)
ターゲットタグは後ほど使用するので、覚えておいてください。
送信元IPはヘルスチェックの許可設定でも指定した`130.211.0.0/22, 35.191.0.0/16`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/d43f3353-a378-1b52-8284-f8249791555b.png)
この通り、`http-server-lb`が追加されればOKです。
ちなみに元から登録されている`http-server`と`https-server`は全てのIPに対してポート80と443を開放する設定で、
VMインスタンス作成時のファイアーウォール設定で「HTTP/HTTPS トラフィックを許可する」にチェックを入れると利用されるものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/5b9d4d0f-0184-0b0a-9ed3-e7f0ba561f71.png)
ファイアーウォール ルールの作成ができたら、それをVMインスタンスに設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/97e4943f-a554-dd9b-7e35-39f22a7b2203.png)
VMインスタンスの編集に進み、ネットワークタグに先ほど作成した`http-server-lb`を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ccda33bd-e920-39d5-9e20-510a6630e09a.png)
これで、VMインスタンスにロードバランサからのみアクセスできるようになりました。

## ロードバランサの作成

VMインスタンスのほうの準備が整ったので、ロードバランサを設定します。
ただその前に、ロードバランサを設定するにはVMインスタンス単独ではダメなので、インスタンスグループを作成してあげます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/eaffa257-1abd-182a-94e9-beece69373c5.png)
既存のVMインスタンスをグルーピングするだけなので、「New unmanaged instance group」を利用します。
リージョンとゾーンを選択すると、作成したVMインスタンスが選択できるようになるので選択して作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/dba5d17b-1200-bc74-dc14-f13226fc6b9b.png)
インスタンスグループが作成出来たら、ロードバランサの作成に移ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/dd234228-b074-77e4-6270-4fe44ad13e63.png)
インターネットからHTTPSの為のロードバランサなので下記の通り選択、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/e488a54e-bef1-4bc7-2950-5e231f43605f.png)
まずはフロントエンドの構成です。
名前を設定し、プロトコルでHTTPSを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/c2eb3212-54c2-9ef3-b76d-f517cf92dfac.png)
IP addressがエフェメラル(一時的なIP)になっているので、固定のIPを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/f3221e29-5187-6286-c86c-e6a2ec75ed63.png)
SSL証明書を設定する必要があるので、作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ad50f25d-e8db-9fd9-b58c-bd1284388761.png)
証明書の作成＆管理はGCPにお任せするので、「Google マネージドの証明書を作成する」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/6e3a945b-74c5-0ae8-704a-f8845523b61a.png)
フロントエンドの設定は下記の通りになります。
「HTTPからHTTPSへのリダイレクトを有効にする」を選択しておくと、httpでアクセスが来た際に自動でhttpsにリダイレクトしてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/91cc6b53-8e4f-12bb-0c54-1cdafa7db161.png)
次にバックエンドの設定です。
バックエンドサービスの作成を選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/3315f464-8d16-da3e-92a3-939ad0ef4f08.png)
名前を設定し、設定は下記の通り、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/323ac2e9-ff17-196e-0279-df1ecaf07a5a.png)
バックエンドとして先ほど作成したインスタンスグループを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/b6df295c-c964-43d9-5918-08be5dd22a63.png)
ヘルスチェックを作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ce8ad01a-5918-4290-75a3-d2f7a0643923.png)
ヘルスチェックの設定は下記の通り。
ヘルス条件は少しチューニングしても良いかと思います。（下記はデフォルトです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/9828d4c4-111c-74f9-d43f-df334e95869f.png)
ルーティングルールはこの通り、これで作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/95600268-ce10-0786-2c28-74e539dcd0a0.png)

これでロードバランサの設定まで完了です。
ここでは記載しませんが、ドメインとIPのDNS設定は別途行ってください。
設定したドメイン(`https://gitlab.xxx.com`など)して下記の通りログイン画面が表示されるはずです。
rootユーザーと初期パスワードでログインしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/03e075f1-bf2e-f764-18d5-09af7a91aeae.png)

ログインができたら成功です！
初期パスワードを変更しておきましょう。

# GitLabの設定変更

## 誰でも新規ユーザ登録できる機能を無効にする

GitLabは初期設定では、誰でもログイン画面からユーザ登録ができる状態になっています。
その為、初回ログイン時に下記の通り警告(誰でも登録できる状態です)が表示されると思いますので、「Turn off」ボタンをクリックして設定に飛びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ab326057-2219-4d83-498e-778e84fc3a9f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/bff2e6d9-4809-3604-4549-26663bc15e8a.png)
「Sign-up enabled」にチェックが入っていると思いますので、**チェックを外して**おきましょう。
これで設定を保存すれば、この機能は無効となります。

## GitLabを日本語表示にする

言語の設定はユーザーごとの設定になるので、ユーザーの「Preferences」を選択し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/b69b5dd3-262f-c3fd-9474-c6c8bd238875.png)
Localizationで日本語を選択します。（とはいえ、翻訳は32%ほどみたいですが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/1933f344-0e36-cbdd-d433-04246cdb7632.png)

# GitLabからのメール送信の設定(SendGrid)

GitLabからメール送信ができるようにメール送信の設定をします。
今回はSendGrid(の無料プラン)を利用してみようと思います。

Marketplaceで「sendgrid」と検索して、「SendGrid Email API」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/9a721d6f-209b-e6f3-5c3f-391e48e40d39.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/2aaad6d8-6fa5-b974-1623-4a01736865de.png)
そして無料プラン(Free)を購入します。(購入といっても無料プランなので費用はかかりません)　
無料プランでも月12,000通のメールが送れるので、小規模な運用であれば十分かと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/f4c15e86-8472-4802-a966-a3c09b4e227b.png)
購入が完了すると「プロバイダで管理」のボタンが表示されるようになりますので、そこからSendGridの設定を行うことになります。

今回はドメイン認証を行う「Authenticate a domain instead」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/ae77ce1f-b345-b7f5-416b-769c678a1b94.png)
ドメイン認証を行う為の情報を入力します。
利用しているDNSサービスが一覧にある場合には選択します。（DNS設定の例が、サービス用で表示されるようになります。
一覧にない場合は選択不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/5c7a4af4-16c1-6e82-e239-6ed7d83f63eb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/bee9ce22-308a-f65d-d0b2-271f15280e9d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/b37b54a2-a97d-f117-7b76-421ddff3a080.png)

ドメイン認証が完了したら、GitLabに設定するAPI Keyを作成します。
サイドメニュー > Settings > API Keys から「Create API Key」をクリック。
今回はメール送信ができれば良いので、機能を制限する「Restricted Access」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/82b7f42c-1eb3-a1a3-87ad-3a048ff7fad7.png)
「Mail Send」をFull Accessに設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/427af666-a5d5-b3a9-6640-f446453857f6.png)
発行したAPI Keyは大切に保管してください。（このページから離れると再度確認することはできなくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/385d1897-ebaa-78ad-776f-a516ec0eeafa.png)

発行したAPI KeyをGitLabに設定するために、`/etc/gitlab/gitlab.rb`を下記の通り編集します。
`the_api_key_you_created`にAPI Keyを設定し、`gitlab_email_from`、`gitlab_email_reply_to`にメールアドレスを設定します。
```ruby:/etc/gitlab/gitlab.rb
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.sendgrid.net"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "apikey"
gitlab_rails['smtp_password'] = "the_api_key_you_created"
gitlab_rails['smtp_domain'] = "smtp.sendgrid.net"
gitlab_rails['smtp_authentication'] = "plain"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false
gitlab_rails['gitlab_email_from'] = 'auto@gitlab.xxx.com'
gitlab_rails['gitlab_email_reply_to'] = 'noreply@gitlab.xxx.com'
```

設定が完了したら、GitLabを再構築します。
```shell-session
$ sudo gitlab-ctl reconfigure
```

これでGitLabの運用に必要な最低限の設定は完了したと思います。

# 関連記事

## Googleアカウントでのログイン

https://qiita.com/kamina/items/c2f22d9b609f4bf96a6f

## CI/CD GitLab Runnerの設定

https://qiita.com/kamina/items/bc4b20c6bbc47b98557c

## GitLab Pagesを有効にする(GCPのロードバランサにワイルドカードSSL証明書を利用する)

https://qiita.com/kamina/items/671928576545417b179e