AWS CDKで格安GitLabサーバーを構築！月額$37で企業レベルのGit環境を手に入れる方法

## なぜGitLabサーバーを自作することになったのか

こんにちは！都内IT企業でエンジニアをしている者です。

会社でGitリポジトリの管理について悩んでいました...

### 抱えていた課題
- **GitHubのプライベートリポジトリ**：チーム規模だと月額$4×人数で結構な費用
- **GitLab Cloud**：Premium planだと月額$19×人数でさらに高額
- **オンプレミス**：サーバー管理の知識が不足、運用が不安

特に困っていたのは、**Dockerコンテナレジストリ**が使いたいのに、GitHubのContainer Registryは料金が別途かかること。CI/CDパイプラインでDockerイメージをプッシュ・プルしまくると、通信料金もバカになりません。

「自社でGitLabサーバーを運用できれば、固定費用で使い放題になるのでは？」

そこで、AWSの勉強も兼ねて、**月額$37程度で運用できるGitLabサーバー**を構築してみました！

## 今回作ったものの特徴

この記事では、以下の特徴を持つGitLabサーバーをAWSに構築する方法を紹介します：

✅ **HTTPSアクセス**：Let's Encrypt SSL証明書で無料のHTTPS対応  
✅ **Dockerレジストリ**：コンテナイメージの保存・管理が可能  
✅ **月額$37で運用**：自動起動・停止機能でコストを大幅削減  
✅ **パスワード管理**：AWS Secrets Managerで安全に管理  
✅ **簡単ログイン**：SSHキー不要でブラウザからアクセス可能  
✅ **メール通知**：AWS SESでGitの通知メールを受信  
✅ **省エネ運用**：平日の営業時間のみ自動稼働（土日は停止）

### 🎯 結果的に実現できたこと

- **コスト削減**：GitLab Cloud Premium（月額$19×5人=$95）→ 自社サーバー（月額$37）
- **容量無制限**：Gitリポジトリもコンテナレジストリも自由に使用
- **学習効果**：AWSの各サービスの理解が深まった
- **運用自動化**：ほぼメンテナンスフリーで稼働

## 初心者でも大丈夫！必要な前提知識

この記事は以下のレベルの方を想定しています：

### ✅ 必要な知識（これがあればOK）
- Gitの基本的な使い方（clone、push、pullなど）
- AWSアカウントを持っている（無料枠でも可）
- コマンドプロンプトやターミナルの基本操作
- ドメイン名の概念（example.comなど）

### 👌 知らなくても大丈夫（記事で説明します）
- AWS CDKって何？
- EC2、Route53、Secrets Managerなどの各AWSサービス
- Let's Encrypt SSL証明書の仕組み
- Infrastructure as Codeの概念

### 💰 必要な費用
- **AWSアカウント**：無料枠でも可能（ただし運用時は課金されます）
- **ドメイン名**：年額$10-15程度（AWSのRoute53で取得）
- **運用費用**：月額約$37（詳細は後述）

## 完成版のソースコード

まずは完成版をご覧ください！GitHubで全コードを公開しています：

https://github.com/yukkes/aws-cdk-gitlab-on-ec2

**🚀 急いでいる方へ**：このリポジトリをクローンして、`.env`ファイルを設定すれば、5分でデプロイできます！

## システム構成図（初心者向け解説）

```
インターネット
     │
     ▼
┌─────────────────────────────────┐
│        あなたのドメイン名        │ ← Route53でDNS管理
│    (例: gitlab.mycompany.com)   │
└─────────────────────────────────┘
     │ HTTPS (443ポート, 5050ポート)
     ▼
┌─────────────────────────────────┐
│         AWS EC2サーバー          │
│                                 │
│  ┌─────────────────────────────┐│
│  │        GitLab本体           ││ ← Webブラウザでアクセス
│  │       (HTTPS:443)           ││
│  └─────────────────────────────┘│
│                                 │
│  ┌─────────────────────────────┐│
│  │      コンテナレジストリ       ││ ← Dockerイメージ保存
│  │       (HTTPS:5050)          ││
│  └─────────────────────────────┘│
│                                 │
│  + 自動SSL証明書取得・更新        │
│  + 毎日自動バックアップ           │
│  + 平日のみ自動起動・停止         │
└─────────────────────────────────┘
```

### 🔧 使われているAWSサービス（簡単解説）

| サービス名 | 役割 | 初心者向け説明 |
|-----------|------|----------------|
| **EC2** | サーバー本体 | GitLabが動くLinuxサーバー |
| **Route53** | DNS管理 | ドメイン名とサーバーを紐付け |
| **Secrets Manager** | パスワード保管庫 | ログインパスワードを安全に保存 |
| **EventBridge** | スケジューラー | 決まった時間にサーバーを起動・停止 |
| **Session Manager** | リモートアクセス | SSHキー不要でサーバーに接続 |

## 主要機能をわかりやすく解説

### 1. 🔒 HTTPS対応（Let's Encrypt）

**何ができるの？**  
`https://gitlab.yourcompany.com`のように、安全な暗号化通信でGitLabにアクセスできます。

**どうやって実現？**  
Let's Encryptという無料SSL証明書サービスを使って、自動で証明書を取得・更新します。

```ruby
# GitLabの設定ファイル（gitlab.rb）に以下が自動で設定されます
external_url 'https://gitlab.yourcompany.com'
letsencrypt['enable'] = true                    # Let's Encryptを有効化
letsencrypt['contact_emails'] = ['admin@yourcompany.com']  # 連絡先メール
letsencrypt['auto_renew'] = true               # 自動更新を有効化
```

**初心者ポイント💡**  
- SSL証明書は通常、年額数万円かかりますが、Let's Encryptなら完全無料！
- 3ヶ月ごとに自動更新されるので、手動メンテナンス不要

### 2. 💰 コスト削減（自動起動・停止）

**何ができるの？**  
平日の営業時間（8時〜22時）のみサーバーが稼働し、夜間・土日は自動停止してコストを削減。

**どのくらい安くなるの？**  
通常の24時間稼働と比較して、約**58%のコスト削減**が可能！

```typescript
// 平日8:00 AM（日本時間）に自動起動
const startRule = new events.Rule(this, 'GitLabStartRule', {
  schedule: events.Schedule.cron({
    minute: '0',
    hour: '23',      // UTC時間（日本時間-9時間）
    weekDay: 'SUN-THU'  // 日曜〜木曜（日本時間の月曜〜金曜）
  })
});

// 平日10:00 PM（日本時間）に自動停止
const stopRule = new events.Rule(this, 'GitLabStopRule', {
  schedule: events.Schedule.cron({
    minute: '0',
    hour: '13',      // UTC時間
    weekDay: 'MON-FRI'  // 月曜〜金曜
  })
});
```

**初心者ポイント💡**  
- AWSは「使った分だけ課金」なので、停止中は料金がかかりません
- 緊急時は手動で起動することも可能です

### 3. 🔐 安全なパスワード管理

**何ができるの？**  
GitLabの管理者パスワードを、AWSの金庫（Secrets Manager）で安全に保管。

**なぜ安全なの？**  
- パスワードは32文字のランダム文字列で自動生成
- AWS内部で暗号化されて保存
- アクセスには特別な権限が必要

```typescript
// 32文字のランダムパスワードを自動生成
const gitlabRootPassword = new secretsmanager.Secret(this, 'GitLabRootPassword', {
  description: 'GitLab root user password',
  generateSecretString: {
    secretStringTemplate: JSON.stringify({ username: 'root' }),
    generateStringKey: 'password',
    excludeCharacters: '"@/\\',    // 紛らわしい文字は除外
    passwordLength: 32,
  },
});
```

**初心者ポイント💡**  
- 「password123」のような簡単なパスワードは危険！
- Secrets Managerなら、安全で覚えやすいパスワード管理が可能

### 4. 🖥️ サーバーの種類選択（コスト最適化）

**どんなサーバーを使うの？**  
AWSの「Graviton」プロセッサ搭載サーバーで、従来より最大20%安価！

```bash
# 設定例：コスト重視
INSTANCE_TYPE=t4g.large    # Gravitonプロセッサ（ARM系）
ARCHITECTURE=arm64         # プロセッサの種類
DISK_SIZE_GB=100          # ストレージ容量

# 性能重視の場合
INSTANCE_TYPE=t3.large     # Intel/AMDプロセッサ（x86系）
ARCHITECTURE=x86_64        # プロセッサの種類
```

**初心者ポイント💡**  
- `t4g`系 = 新しいARM系プロセッサ（安い・省電力）
- `t3`系 = 従来のIntel/AMD系プロセッサ（互換性重視）
- どちらを選んでも、設定ファイルで自動調整されます！

## 設定ファイルの準備（コピペでOK！）

### ステップ1: 基本設定をコピペ

プロジェクトをダウンロードしたら、`.env`ファイルに以下をコピペして、あなたの環境に合わせて変更してください：

```bash
# ===== 基本設定（必須）=====
# あなたが持っているVPCのID（AWSコンソールで確認）
VPC_ID=vpc-xxxxxxxxx

# どのIPアドレスからアクセスを許可するか
# 0.0.0.0/0 = 全世界からアクセス可能（テスト用）
# 会社のIPアドレスのみに制限したい場合は、そのアドレスを入力
ALLOWED_HTTPS_CIDR=0.0.0.0/0
ALLOWED_REGISTRY_CIDR=0.0.0.0/0

# ===== サーバー設定 =====
# サーバーの性能（コスト重視 or 性能重視）
INSTANCE_TYPE=t4g.large      # コスト重視（月額約$25）
# INSTANCE_TYPE=t3.large     # 性能重視（月額約$30）

ARCHITECTURE=arm64           # t4g系の場合
# ARCHITECTURE=x86_64        # t3系の場合

DISK_SIZE_GB=100            # ストレージ容量（GB）

# ===== ドメイン設定 =====
# Route53で管理しているドメインの設定
HOSTED_ZONE_ID=ZXXXXXXXXXXXXX           # Route53のホストゾーンID
DOMAIN_NAME=gitlab.yourcompany.com      # GitLabにアクセスするURL

# ===== メール設定（AWS SES）=====
# GitLabからの通知メール用
SMTP_ADDRESS=email-smtp.ap-northeast-1.amazonaws.com
SMTP_PORT=587
SMTP_USER_NAME=your-smtp-username       # AWS SESで取得
SMTP_PASSWORD=your-smtp-password        # AWS SESで取得
SMTP_DOMAIN=yourcompany.com
EMAIL_FROM=noreply@yourcompany.com
LETSENCRYPT_EMAIL=admin@yourcompany.com  # SSL証明書の連絡先

# ===== AWSリージョン =====
AWS_REGION=ap-northeast-1               # 東京リージョン
```

### ステップ2: 値の設定方法

#### 🏠 VPC_IDの確認方法
1. [AWSコンソール](https://console.aws.amazon.com) → VPC
2. 「VPC」メニューで、既存のVPCのIDをコピー
3. `vpc-xxxxxxxxx`のような形式

#### 🌐 ドメイン設定（Route53）
1. AWSコンソール → Route53
2. 「ホストゾーン」で、あなたのドメインを選択
3. ホストゾーンIDをコピー（`ZXXXXXXXXXXXXX`のような形式）

#### 📧 SMTP設定（AWS SES）
1. AWSコンソール → Simple Email Service (SES)
2. 「SMTP設定」→「SMTP認証情報の作成」
3. ユーザー名とパスワードをメモ

**💡 初心者向けヒント**
- ドメインを持っていない場合：AWS Route53で取得（年額約$10-15）
- AWS SESの設定が複雑な場合：まずはSMTP設定をスキップして、後で追加も可能

## 実際にデプロイしてみよう！

### ステップ1: プロジェクトの準備

```bash
# GitHubからプロジェクトをダウンロード
git clone https://github.com/yukkes/aws-cdk-gitlab-on-ec2.git
cd aws-cdk-gitlab-on-ec2

# 必要なツールをインストール
npm install

# 設定ファイルをコピー
cp .env.example .env
```

### ステップ2: 設定ファイルの編集

上で説明した`.env`ファイルを編集してください。最低限、以下の4つは必須です：

```bash
VPC_ID=vpc-xxxxxxxxx                    # あなたのVPC ID
HOSTED_ZONE_ID=ZXXXXXXXXXXXXX           # Route53のホストゾーンID
DOMAIN_NAME=gitlab.yourcompany.com      # GitLabのURL
LETSENCRYPT_EMAIL=admin@yourcompany.com # SSL証明書の連絡先
```

### ステップ3: デプロイ実行（ワンクリック！）

#### Windows（PowerShell）の場合：
```powershell
.\deploy.ps1
```

#### Mac/Linux（Bash）の場合：
```bash
chmod +x deploy.sh
./deploy.sh
```

#### 手動でやりたい場合：
```bash
# AWS CDKの初期設定（初回のみ）
npx cdk bootstrap

# GitLabサーバーをデプロイ
npx cdk deploy
```

### ステップ4: 完了を待つ（コーヒータイム☕）

デプロイが始まったら、以下の手順で進みます：

1. **AWSリソース作成**（5-10分）
   - EC2サーバー、セキュリティグループなどを作成

2. **GitLab初期設定**（10-15分）
   - サーバー内でGitLabをインストール・設定

3. **SSL証明書取得**（2-5分）
   - Let's EncryptからHTTPS証明書を取得

**🎉 完了の合図**  
コンソールに以下のメッセージが表示されたら完了！

```
✅ GitLabStack

Outputs:
GitLabStack.EIPAddress = 52.xxx.xxx.xxx
GitLabStack.GitLabURL = https://gitlab.yourcompany.com
GitLabStack.SecretArn = arn:aws:secretsmanager:...
```

## 初回ログイン方法

### ステップ1: パスワードを取得

デプロイ完了後、GitLabの管理者パスワードを取得します：

#### Windows（PowerShell）：
```powershell
# デプロイ出力で表示されたSecretArnを使用
.\get-password.ps1 -SecretArn "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:..."
```

#### Mac/Linux：
```bash
# AWS CLIでパスワードを取得
aws secretsmanager get-secret-value --secret-id "arn:aws:secretsmanager:..." --query SecretString --output text | grep -o '"password":"[^"]*"' | cut -d'"' -f4
```

### ステップ2: GitLabにアクセス

1. ブラウザで `https://gitlab.yourcompany.com` にアクセス
2. 以下でログイン：
   - **ユーザー名**: `root`
   - **パスワード**: 上で取得したパスワード

### ステップ3: 初期設定

ログイン後、以下を設定することをお勧めします：

1. **管理者パスワード変更**
   - 右上のアバター → Preferences → Password

2. **新しいユーザー追加**
   - Admin Area → Users → New User

3. **新しいプロジェクト作成**
   - "+" → New project → Create blank project

**🎉 おめでとうございます！**  
これでGitLabサーバーが使えるようになりました！

## 日常的な管理方法（初心者でも簡単）

### 便利な管理コマンド集

プロジェクトに含まれているPowerShellスクリプトで、簡単に管理できます：

```powershell
# GitLabの状態を確認
.\gitlab-utils.ps1 -Action status -InstanceId "i-1234567890abcdef0"

# 手動でサーバーを起動（緊急時）
.\gitlab-utils.ps1 -Action start-instance -InstanceId "i-1234567890abcdef0"

# 手動でサーバーを停止（メンテナンス時）
.\gitlab-utils.ps1 -Action stop-instance -InstanceId "i-1234567890abcdef0"

# GitLabのバックアップを作成
.\gitlab-utils.ps1 -Action backup -InstanceId "i-1234567890abcdef0"

# サーバーのログを確認（トラブル時）
.\gitlab-utils.ps1 -Action get-logs -InstanceId "i-1234567890abcdef0"
```

### サーバーへの直接アクセス方法

SSHキー不要で安全にサーバーにアクセスできます：

#### AWSコンソール経由（初心者向け）：
1. AWSコンソール → EC2 → インスタンス
2. GitLabサーバーを選択
3. 「接続」→「Session Manager」→「接続」

#### コマンドライン経由：
```bash
# AWS CLIでサーバーに接続
aws ssm start-session --target i-1234567890abcdef0
```

### よく使うGitLabコマンド

サーバーに接続した後、以下のコマンドが便利です：

```bash
# GitLabの状態確認
sudo gitlab-ctl status

# GitLabの再起動
sudo gitlab-ctl restart

# GitLabの設定を再読み込み
sudo gitlab-ctl reconfigure

# バックアップ作成
sudo gitlab-backup create

# ディスク使用量確認
df -h
```

## 実際にかかる費用（詳細版）

### 月額料金の内訳

| 項目 | 費用 | 説明 |
|------|------|------|
| **EC2サーバー（t4g.large）** | $25.20 | 58%稼働時間での計算 |
| **EBSストレージ（100GB）** | $8.00 | GP3ボリューム |
| **Elastic IP** | $3.60 | 固定IPアドレス |
| **Route53 DNS** | $0.50 | ドメイン管理 |
| **Secrets Manager** | $0.40 | パスワード保管 |
| **データ転送** | $0-2.00 | 使用量による |
| **合計** | **約$37-39/月** | |

### 比較：他のサービスとの費用対比

| サービス | 5人チームの月額 | 制限事項 |
|----------|----------------|----------|
| **GitLab Cloud Premium** | ＄95 (＄19×5人) | 容量制限あり |
| **GitHub Team** | ＄100 ($20×5人) | プライベートリポジトリ制限 |
| **自社GitLabサーバー** | ＄37 | 容量無制限！ |

**💰 年間で約$60万円の節約！**（5人チームの場合）

### コスト削減のポイント

#### 1. 自動スケジューリング効果
```
通常稼働（24時間）: $59.50/月
自動停止（58%稼働）: $25.20/月
削減額: $34.30/月（約58%削減）
```

#### 2. Gravitonプロセッサ効果
```
従来型（t3.large）: $30.24/月
Graviton（t4g.large）: $25.20/月
削減額: $5.04/月（約17%削減）
```

#### 3. ストレージサイズ調整
```
50GB: $4.00/月（最小構成）
100GB: $8.00/月（推奨構成）
200GB: $16.00/月（大容量構成）
```

### 節約テクニック

1. **開発環境用途なら**：平日のみ稼働で十分
2. **小規模チームなら**：50GBストレージでも可能
3. **大規模チームなら**：Reserved Instanceで更に20%削減可能

## 困った時の解決方法（初心者向け）

### よくあるトラブルと解決法

#### 🚨 問題1: GitLabにアクセスできない

**症状**: ブラウザで `https://gitlab.yourcompany.com` にアクセスしても表示されない

**解決手順**:
```bash
# 1. サーバーが起動しているか確認
aws ec2 describe-instances --instance-ids i-xxxxxxxxxxxx

# 2. DNS設定が正しいか確認
nslookup gitlab.yourcompany.com

# 3. セキュリティグループ設定を確認
aws ec2 describe-security-groups --group-ids sg-xxxxxxxxxxxx
```

**チェックポイント**:
- サーバーは起動していますか？（State: running）
- ドメインのDNS設定は正しいですか？
- セキュリティグループでHTTPS（443番ポート）は開いていますか？

#### 🚨 問題2: パスワードでログインできない

**症状**: `root`ユーザーでログインしようとするとエラーになる

**解決手順**:
```bash
# GitLabの初期設定が完了しているか確認
aws ssm start-session --target i-xxxxxxxxxxxx

# サーバーに接続後、以下を実行
sudo tail -f /var/log/cloud-init-output.log
# "GitLab configuration completed successfully!" が表示されるまで待つ
```

**チェックポイント**:
- GitLabの初期設定は完了していますか？（15-20分かかります）
- Secrets Managerから正しいパスワードを取得していますか？

#### 🚨 問題3: SSL証明書が取得できない

**症状**: `https://`でアクセスできず、「安全でない接続」エラーが出る

**解決手順**:
```bash
# Let's Encryptのログを確認
sudo tail -f /var/log/gitlab/nginx/current

# DNSの伝播状況を確認
dig gitlab.yourcompany.com
```

**チェックポイント**:
- ドメインのAレコードは正しく設定されていますか？
- DNS伝播は完了していますか？（最大48時間かかる場合があります）
- Let's Encryptのレート制限に引っかかっていませんか？（同一ドメインで週5回まで）

#### 🚨 問題4: コンテナレジストリが使えない

**症状**: `docker push gitlab.yourcompany.com:5050/...` でエラーになる

**解決手順**:
```bash
# GitLabのコンテナレジストリ設定を確認
sudo gitlab-rails console
# GitLabコンソール内で以下を実行
puts Gitlab.config.registry.enabled
```

**チェックポイント**:
- ポート5050がセキュリティグループで開いていますか？
- SSL証明書は正しく取得できていますか？

### サポートが必要な時

#### 1. ログの確認方法
```bash
# GitLabのログ確認
sudo gitlab-ctl tail

# システムログ確認
sudo journalctl -f

# Cloud-initログ確認（初期設定）
sudo tail -f /var/log/cloud-init-output.log
```

#### 2. GitLab公式ドキュメント
- [GitLab CE Documentation](https://docs.gitlab.com/ee/)
- [Let's Encrypt Troubleshooting](https://letsencrypt.org/docs/)

#### 3. AWSサポートリソース
- [AWS Systems Manager Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html)
- [Amazon EC2 User Guide](https://docs.aws.amazon.com/ec2/)

## まとめ：実際に使ってみた感想

### 🎯 導入前後の変化

#### **Before（GitLab Cloud使用時）**
- 月額費用：$95（5人チーム）
- ストレージ制限：10GBまで
- コンテナレジストリ：別料金
- カスタマイズ：制限あり

#### **After（自社GitLabサーバー）**
- 月額費用：$37（固定）
- ストレージ制限：なし（100GB〜自由に拡張）
- コンテナレジストリ：無制限使用
- カスタマイズ：自由自在

### 📈 予想以上によかった点

1. **学習効果が大きい**
   - AWS CDKの理解が深まった
   - Infrastructure as Codeの概念を実践できた
   - GitLabの内部構造を理解できた

2. **運用が思ったより簡単**
   - 自動起動・停止でほぼメンテナンスフリー
   - Let's Encrypt自動更新で証明書管理不要
   - PowerShellスクリプトで管理作業が簡単

3. **コスト削減効果が顕著**
   - 年間約$70万円の節約（5人チームの場合）
   - Gravitonプロセッサで更なるコスト削減
   - 無制限使用で安心感がある

### ⚠️ 注意すべき点

1. **初期設定の学習コスト**
   - AWS各サービスの基本知識が必要
   - 初回デプロイ時のトラブルシューティング

2. **自己責任での運用**
   - バックアップは自分で管理
   - セキュリティ設定も自己責任

3. **緊急時対応**
   - 深夜・休日の障害時は自分で対応

### 🚀 こんな人におすすめ

- **スタートアップ・中小企業**：コスト削減効果が大きい
- **学習意欲のあるエンジニア**：AWSの実践的な知識が身につく
- **DevOpsに興味がある人**：Infrastructure as Codeを体験できる
- **コンテナ開発チーム**：Docker Registryを無制限で使える

### 📝 今後の改善予定

1. **監視機能の強化**：CloudWatchでより詳細な監視
2. **バックアップ自動化**：S3への定期バックアップ
3. **マルチAZ対応**：可用性向上のための冗長化
4. **CI/CDパイプライン**：GitLab Runnerの自動セットアップ

## 最後に

GitLabの自社運用は、想像以上に簡単で効果的でした。特に**コスト削減効果**と**学習効果**の両方を得られるのが大きなメリットです。

AWS CDKを使うことで、Infrastructure as Codeの実践も体験でき、今後のクラウド開発に活かせる知識も身につきました。

スタートアップや中小企業で、GitLabの運用コストに悩んでいる方は、ぜひチャレンジしてみてください！

---

**何か質問や改善提案があれば、コメントお待ちしています！**

## リポジトリ

完全なソースコードとドキュメント：

https://github.com/yukkes/aws-cdk-gitlab-on-ec2

## 最後まで読んで頂いた人へ
最後まで読んで頂き、ありがとうございます。
本記事はGitHubリポジトリを生成AIが読み取って生成しています。
生成AIが書いた文章だと気づいた人はいましたでしょうか？
以下のようなプロンプトを用いているので、よかったら参考にしてください。
- エディタ：VSCode
- ツール：GitHub Copilot Agentモード
- 生成AI：Claude Sonnet 4
```
現在のAWS CDKの内容をもとに、技術系ブログQiitaに投稿する内容を作成して。
以下のGitHubを参照するようにリンクして。このリポジトリと同一です。
https://github.com/yukkes/aws-cdk-gitlab-on-ec2
```