少人数チーム向けに簡易な GitLab を用意する （ver. 17 on AWS EC2 running ubuntu 22.04）

# 概要

GitLab（無料版）を AWS EC2 インスタンスへインストールして利用し，数人程度とリポジトリを共有する環境を用意する．

**前提条件**

- EC2 インスタンスを作成済みでインターネットを介した ssh 接続がきる．システム要件は次節に示す．

**やること**

- AWS EC2 (Ubuntu 22.04) にGitLabをLinuxパッケージでインストール．
- 設定
    - 自己証明で HTTPS (ssl/tls) 対応させる．
    - rootユーザでログインし，一般ユーザ追加をする．
    - メモリ枯渇で動作が不安定である場合の対応をする．

**やらないこと**

- postfixのインストール．（メール認証，MFA対応）
- 本番，大規模運用を意識した構成．（Route53連携，バックアップ，負荷分散など）

# ハードウェア要件

公式ページ [^spec] によるとハードウェア要件は下記である．

| 項目 | 説明 |
| --- | --- |
| ストレージ | リポジトリ全体と同等の空き容量 |
| CPU | 毎秒最大20件のリクエスト（RPS）または1000人のユーザー = 8 vCPU |
| メモリ | 毎秒最大20件のリクエスト（RPS）または1000人のユーザー = 8 GB（最小），16 GB（推奨） |

今回はAWSに構築して常時起動，数人で利用する場合を想定しているため小さめで，お安い **AWS EC2 t3.medium** を利用する．ストレージは64GBとした．

| vCPU | MEM | NET Gbps | Cost USD/Month | EBS |
| --- | --- | --- | --- | --- |
| 2 | 4 | 5 | 39.71 | 64GB |

GitLab はドメイン名を設定する項目があるうえ，ローカルリポジトリのリモートリポジトリ指定でもドメイン名が必要になる．インスタンス起動停止の都度設定を変更は手間なので，EC2 インスタンスには **Elastic IPアドレス**の割り当てをお勧めする．

# インストール

ソフトウェアの要件を次に示す．

| 項目 | 値 |
| --- | --- |
| インスタンス | AWS EC2 t3.medium |
| EBS | 64GB |
| OS (AMI) | Ubuntu 22.04 LTS |
| GitLab | 17.0.2 |

:::note warn
2024-06-19 時点で Ubuntu 24.04 LTS (Noble) へのインストールはできなかったため 22.04LTSを利用．インストール可能かどうかはパッケージのリポジトリ [^ee-package-repo], [^ce-package-repo] を確認する．
:::

次のように公式の手順に従ってLinuxパッケージ (Omnibusパッケージ) を利用してインストール [^install-ubuntu] していく．

まず，依存パッケージのインストール．

```bash
$ sudo apt-get update
$ sudo apt-get install -y curl openssh-server ca-certificates tzdata perl
```

次に，GitLabリポジトリ取得．

```bash
# https://packages.gitlab.com/gitlab/gitlab-ce/install
$ curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
```

GitLab をインストールする．ここでGitLab rootユーザの初期パスワードを指定可能だが省略．

```bash
$ sudo EXTERNAL_URL="http://{FQDN}" apt-get install gitlab-ce

...

       *.                  *.
      ***                 ***
     *****               *****
    .******             *******
    ********            ********
   ,,,,,,,,,***********,,,,,,,,,
  ,,,,,,,,,,,*********,,,,,,,,,,,
  .,,,,,,,,,,,*******,,,,,,,,,,,,
      ,,,,,,,,,*****,,,,,,,,,.
         ,,,,,,,****,,,,,,
            .,,,***,,,,
                ,*,.

     _______ __  __          __
    / ____(_) /_/ /   ____ _/ /_
   / / __/ / __/ /   / __ `/ __ \
  / /_/ / / /_/ /___/ /_/ / /_/ /
  \____/_/\__/_____/\__,_/_.___/

Thank you for installing GitLab!
GitLab should be available at http://xxxxx
```

今回は初期パスワードを指定していないので，初期ROOTユーザ `root` のパスワードは24時間だけ `/etc/gitlab/initial_root_password` に保存される．24時間後には削除されるため直ぐにROOTとしてアクセスしてパスワードを変えるか，別途記録しておくこと．

```bash
$ sudo cat /etc/gitlab/initial_root_password
```

忘れずにセキュリティグループでインバウンドを許可しておく(80番ポート)．後続でhttps化をするので443も許可しておく．ufwなども設定している場合は同様に許可する．この時点で `http://` で接続できるようになっているはずなのでブラウザからアクセスしてみる．

これでインストールが完了した．以降は設定をカスタマイズする．

# 設定

## サインアップ制限

初期状態では誰でもサインアップ可能であるからセキュリティを考慮して，新規サインアップを無効にする [^sign-up-disable] ．

ブラウザでGitLabにアクセスし，次のようにWebUIを操作する．

- 左側サイドバーの下部にある「管理エリア」を押下．左側サイドバーの設定→一般へ移動．
- 新規登録の制限を開いて，「サインアップを有効にする」 のチェックボックスをオフにしてから「変更を保存」を押下．

## https化

自己証明書で https アクセス可能にする．

GitLab サーバで自己証明書の作成をする．パスワードフレーズは指定しない．

```bash
# 確認
$ openssl version
# ディレクトリを作成
$ sudo mkdir -p /etc/gitlab/ssl
$ sudo chmod 755 /etc/gitlab/ssl
$ cd /etc/gitlab/ssl
# 秘密鍵生成
$ sudo opensl genrsa -out /etc/gitlab/ssl/server.key 2048
# CSR (署名要求)
$ sudo openssl req -new -key /etc/gitlab/ssl/server.key -out /etc/gitlab/ssl/server.csr
# CRT (サーバ証明書)(自己証明書)
$ sudo openssl x509 -days 1325 -req -signkey /etc/gitlab/ssl/server.key -in /etc/gitlab/ssl/server.csr -out /etc/gitlab/ssl/server.crt
```

GitLabは`/etc/gitlab/ssl/{FQDN}.key`と`/etc/gitlab/ssl/{FQDN}.crt` を探して利用しようとするので自分のFQDNで作成したファイルのファイル名をリネームする．

```bash
$ mv /etc/gitlab/ssl/server.key /etc/gitlab/ssl/{FQDN}.key
$ mv /etc/gitlab/ssl/server.crt /etc/gitlab/ssl/{FQDN}.crt
```

自己証明書の適用をしていく [^https]．httpsの設定をするため，`/etc/gitlab/gitlab.rb`をつぎのように編集する．

1. `external_url`を `https://{FQDN}` のように設定する．(http を https にする）．
2. 今回は手動の証明書を使うので Let's Encrypt証明書の更新を無効化する`letsencrypt['enable'] = false` ．

```bash
$ sudo vim /etc/gitlab/gitlab.rb

# 設定項目
external_url '{FQDN}'
letsencrypt['enable'] = false
```

設定が完了したら設定を適用する．

```bash
$ sudo gitlab-ctl reconfigure
```

### メールを無効化

https化でも編集した，設定ファイル `/etc/gitlab/gitlab.rb` を開く．今回はpostfixをインストールしておらず，メールを使わないのでメール送信を無効化する．

```bash
$ sudo vim /etc/gitlab/gitlab.rb

# 全てのメール送信を無効化
gitlab_rails['gitlab_email_enabled'] = false
```

設定を適用する．

```bash
$ sudo gitlab-ctl reconfigure
```

### 参考：メンテコマンド

設定ファイルを変更したら更新を忘れずに．

```bash
# Check status
sudo gitlab-ctl status
# Update settings (/etc/gitlab/gitlab.rb)
sudo gitlab-ctl reconfigure
# Start all GitLab components
sudo gitlab-ctl start
# Stop all GitLab components
sudo gitlab-ctl stop
# Restart all GitLab components
sudo gitlab-ctl restart
# Display environmental infomation
sudo gitlab-rake gitlab:env:info

```

### ユーザ登録

Gitlabでのユーザ登録時，メールアドレス登録は必須であり認証や通知で利用される．その為，本番環境ではドメインを取得し Postfix や AWS SMS などを利用する必要がある．しかし，内部の数人で利用する場合は設定が面倒であったりする．

今回は **user@example.fake.com** といった無効なアドレスを入力することでユーザ登録を済ませる．本来はメール認証後パスワード設定をするが，rootユーザで新規ユーザを作成した直後にユーザ情報へアクセスしパスワードを変更して代替する．新規ユーザ初回ログイン時はパスワードの変更が要求される．

ブラウザでGitLabにアクセスし，次のようにWebUIを操作してユーザを作成する．

　管理ユーザでログインし，左側サイドバーの下部にある「管理エリア」を押下．「新規ユーザ」を押下してユーザを作成する．

　このままではパスワードが無いため，再度，左側サイドバーの下部にある「管理エリア」を押下．「ユーザを表示」を押下して該当ユーザの「編集」を押下．初期パスワードを設定する．この情報をユーザに共有して初回ログイン後にパスワードを変更してもらう．

### リポジトリにアクセスする ssh キーの登録

リモートリポジトリにアクセスするため，新規ユーザログイン後はsshキーの登録を勧める．

SSHキーの追加はブラウザでGitLabにアクセスし，次のようにWebUIを操作する．

左側サイドバー→ユーザアイコン→設定→左側サイドバーの「SSHキー」を押下．さらに，「新しいキーを追加」を押下，作成した公開鍵を貼り付けて，任意の名前をつけ「キーを追加」を押下して登録を完了する．このキーは，例えば次のような手順で作成する．

クライアントでsshキーを生成

```bash
$ ssh-keygen -t ed25519  -f "gitlab_aws"
```

クライアントの `~/.ssh/config` にsshの設定を追加する．

```bash
$ vim ~/.ssh/config

...

Host {FQDN}
	User {username or git-username}
	Hostname {hostname(FQDN)}
	IdentityFile ~/.ssh/gitlab_aws
	IdentitiesOnly yes
```

### 動作テスト (ssh経由)

ここまでで，最低限利用可能になったので，リモートリポジトリの操作が問題なく機能するかを確認しておく．問題がなければプロジェクト用のリポジトリを新規作成して利用を開始する．

1. GitLab で適当なプロジェクトを作成する．
2. クライアントでgit clone する．
3. クライアントで適当にファイルを追加してコミットする．
4. リモートリポジトリへ push する．

## メモリ枯渇で動作が不安定

今回のインスタンスはメモリ容量が小さい．GitLabはメモリを消費しすぎると動作が不安定になりブラウザへ502エラーを返してくるようになる場合があるので，設定を変更する．（本番環境では非推奨なのでサーバをスケールアップなどすること）[^memory]

まず，次の手順のいずれかでGitLab を動かしているインスタンスのOSのスワップを有効にする． `$ free -h` などのコマンドで有効になっているか確認できるのですでに設定されている場合はこの手順を無視する．

### スワップ領域の作成例1

```bash
$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ sudo nano /etc/fstab
$ sudo vim /etc/fstab
  xxxx
  /swapfile swap swap defaults 0 0
$ free -h
```

### スワップ領域の作成例2

```bash
# ファイルの作成
$ sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
# パーミッション
$ sudo chmod 600 /swapfile
# スワップファイルとして設定
$ sudo mkswap /swapfile
# スワップ有効化
$ sudo swapon /swapfile
# 確認
$ sudo swapon --show
## または
$ cat /proc/swaps
## または
$ free -h

# 永続化 (<ファイルシステム> <マウントポイント> <ファイルシステムタイプ> <オプション> <ダンプ> <パス>)
# sudo vim /etc/fstab
/swapfile none swap sw 0 0
## または
$ echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab

```

### スワップ目安

スワップの目安は [^swap] を参考に設定．

> How much swap do I need?
> For less than 1GB of physical memory (RAM), it's highly recommended that the swap space should, as a base minimum, be equal to the amount of RAM. Also, it's recommended that the swap space is maximum twice the amount of RAM depending upon the amount of hard disk space available for the system because of diminishing returns.
> For more modern systems (>1GB), your swap space should be at a minimum be equal to your physical memory (RAM) size "if you use hibernation", otherwise you need a minimum of round(sqrt(RAM)) and a maximum of twice the amount of RAM. The only downside to having more swap space than you will actually use, is the disk space you will be reserving for it.
> The "diminishing returns" means that if you need more swap space than twice your RAM size, you'd better add more RAM as Hard Disk Drive (HDD) access is about 10³ slower then RAM access, so something that would take 1 second, suddenly takes more then 15 minutes! And still more than a minute on a fast Solid State Drive (SSD)...


**Example Scenarios** (last 3 columns denote swap space)

```
        RAM   No hibernation    With Hibernation  Maximum
      256MB            256MB               512MB    512MB
      512MB            512MB              1024MB   1024MB
     1024MB           1024MB              2048MB   2048MB

        RAM   No hibernation    With Hibernation  Maximum
        1GB              1GB                 2GB      2GB
        2GB              1GB                 3GB      4GB
        3GB              2GB                 5GB      6GB
        4GB              2GB                 6GB      8GB
        5GB              2GB                 7GB     10GB
        6GB              2GB                 8GB     12GB
        8GB              3GB                11GB     16GB
       12GB              3GB                15GB     24GB
       16GB              4GB                20GB     32GB
       24GB              5GB                29GB     48GB
       32GB              6GB                38GB     64GB
       64GB              8GB                72GB    128GB
      128GB             11GB               139GB    256GB
      256GB             16GB               272GB    512GB
      512GB             23GB               535GB      1TB
        1TB             32GB              1056GB      2TB
        2TB             46GB              2094GB      4TB
        4TB             64GB              4160GB      8TB
        8TB             91GB              8283GB     16TB
```

### その他GitLab設定の追加

ヘルプ[^memory] に従って設定ファイル `/etc/gitlab/gitlab.rb` を開いて設定を末尾に追加してメモリへの負荷を減らす設定を行う．本番環境には推奨されないので注意．

```bash
$ sudo vim /etc/gitlab/gitlab.rb

...

prometheus_monitoring['enable'] = false
gitaly['env'] = {
    'GITALY_COMMAND_SPAWN_MAX_PARALLEL' => '2'
}

gitlab_rails['env'] = {
    'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
}
gitaly['env'] = {
    'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
}

```

これで，インストールと設定は完了．

# GitLabの補足

## 利用形態

提供される製品の区分．それぞれにユーザの階層が存在し利用形態が異なる[^pricing]．

| 名称 | 説明 |
| --- | --- |
| GitLab.com | GitLab 社がホストする SaaS．GitHub のような感じ． |
| Self Managed | 自前のサーバにホストする．今回の利用形態はこれ． |
| GitLab Dedicated | GitLab 社がホストするSaaS．各組織専用のシングルテナントで実行される． |

## ソフトウェアの区分け（特にSelf Managed 版）

| 名称 | 説明 |
| --- | --- |
| Community Edition (CE) | OSS版のGitLabの流れをくむ無料版．[^ce-repo] |
| Enterprise Edition (EE) | エンタープライズ向け．CEの機能を拡張して，一部分が有料ユーザ向けに提供される． |

無料ユーザはCE, EE の違いを考慮する必要ははない．CEにはコア機能が含まれており，EEはそのコア機能に加えて有料ユーザ向けの機能が組み込まれているもの．このコア機能と呼ばれる部分はオープンソースであり，追加部分はプロプライエタリコード（クローズド）である．

無料ユーザはたとえEEをインストールしてもコア機能のみ利用できるため，CE, EEいずれを選択しても問題ない．注意すべきは将来的に有料版へ乗り換えるときCEをインストールしている場合はシステムを変更する必要がある点である．

> **無料のユーザーは**、コミュニティエディション（CE）とエンタープライズエディション（EE）の2つのディストリビューションのいずれかを使用できます。エンタープライズ版は、商用サブスクリプションなしでダウンロード、インストール、および実行できます。この場合、オープンソースライセンスを使用して実行され、オープンソース機能にのみアクセスできます。事実上、サブスクリプションなしのEEとCEはまったく同じ機能を持っています。
　**プレミアムおよびアルティメットのユーザーは、**エンタープライズエディションのみを使用できます。
　無料ユーザーがCEを実行していて、有料ティアにアップグレードしたい場合、再インストールしてEEに移行する必要がありました。EEを無料ユーザーとして使用することの利点は、後で商用サブスクリプションにアップグレードするのがはるかに簡単であることです。必要なのは、ライセンスキーをインストールしてより多くの機能にアクセスすることと、別のディストリビューションを再インストールすることだけです。今日、GitLabの単一ディストリビューションはこれらの利点を維持しています。[^ee-ce]

![ee-ce-img](https://about.gitlab.com/images/blogimages/gitlab-tiers-repos-and-tiers.jpg)
*https://about.gitlab.com/images/blogimages/gitlab-tiers-repos-and-tiers.jpg*


## ドキュメント

| 名称 | 説明 | URL |
| --- | --- | --- |
| GitLab Docs | GitLab ユーザ向けのドキュメント． | [https://docs.gitlab.com](https://docs.gitlab.com/) |
| GitLab 日本語マニュアル | クリエーションライン株式会社さんがGitLab Docs を翻訳して公開してくれているもの． | [https://gitlab-docs.creationline.com](https://gitlab-docs.creationline.com/) |
| GitLab Handbook | GitLab 社の社内方針を示すドキュメント． | [https://handbook.gitlab.com](https://handbook.gitlab.com/) |

利用法を知るには基本的にGitLab Docs 系を参照すれば良い．

# 参考

[^spec]: https://docs.gitlab.com/ee/install/requirements.html

[^install-ubuntu]: https://about.gitlab.com/ja-jp/install/#ubuntu
[^sign-up-disable]: https://docs.gitlab.com/ee/administration/settings/sign_up_restrictions.html
[^https]: https://docs.gitlab.com/omnibus/settings/ssl/index.html#configure-https-manually
[^memory]: https://docs.gitlab.com/omnibus/settings/memory_constrained_envs.html
[^swap]: https://help.ubuntu.com/community/SwapFaq
[^pricing]: https://about.gitlab.com/ja-jp/pricing/
[^ee-ce]: https://handbook.gitlab.com/handbook/marketing/brand-and-product-marketing/product-and-solution-marketing/tiers/#history-of-ce-and-ee-distributions
[^ce-repo]: https://gitlab.com/rluna-gitlab/gitlab-ce
[^ce-package-repo]: https://packages.gitlab.com/gitlab/gitlab-ce
[^ee-package-repo]: https://packages.gitlab.com/gitlab/gitlab-ee