【AWS】LaravelアプリをEC2デプロイ③【ACM / ELB編】

# 0. はじめに
大阪のLaravel初学者サウナーこと、kazumakishimoto([@kazuma_dev](https://twitter.com/kazuma_dev))です！
`ACM`でSSL証明書発行→`ELB(ALB)`でロードバランサーを設置してEC2を配下に登録する方法です！
(※EC2は1つしか作成していないですが、複数サーバーが設置されていることを想定してロードバランサーを作成)

## 0-1. 前回記事
- 【AWS】LaravelアプリをEC2デプロイ【まとめ編】

https://qiita.com/kazumakishimoto/items/e0e109fca443a4acd2a1

- 【AWS】LaravelアプリをEC2デプロイ①【CloudFormation / EC2 / RDS編】

https://qiita.com/kazumakishimoto/items/0859a5a365b226c1b43a

- 【AWS】LaravelアプリをEC2デプロイ②【Route53編】

https://qiita.com/kazumakishimoto/items/825f8c5f94d0160b2364

## 0-2. 全体の流れ
> [1.ACM](#1-acm)
> [2.ELB](#2-elb)
> [3.Route53](#3-route53)
> [4.HTTPS化](#4-https化)
> [補足](#補足)
> [Reference](#reference)
> [次回記事](#次回記事)

## 0-3. 本記事の対象者
- AWSで独自ドメインをSSL化したい方

## 0-4. 事前準備
- AWSアカウント作成済み
- リージョンはアジアパシフィック(東京)ap-northeast-1
- `grfl`や`hoge`はサンプル名なので適宜変更して下さい
- 独自ドメイン取得済み

https://aws.amazon.com/jp/register-flow/

## 0-5. 要件
- ACMでSSL証明書発行
- ELB(ALB)でロードバランサーを設置してEC2を配下に登録
- Route53でAレコードのエイリアスを作成

## 0-6. 本番環境
|ツール|バージョン|
|:--|:--|
|OS|Amazon Linux 2|
|nginx|1.12|
|PHP|7.4.28|
|Laravel|6.20.44|
|MySQL|5.7.37|
|Composer|1.10.26|
|Node.js|13.14.0|

## 0-7. AWS構成図
![aws](https://user-images.githubusercontent.com/68370181/178103075-eec5508a-4d29-409c-84f4-3f687fa9cd5d.png)


# 1. ACM
## 1-1. SSL証明書発行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/216b8749-a14e-fa98-98bc-f348ad915c70.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/c5db62fe-1013-8d21-d05b-ad12fd417884.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/2f98772a-952f-f396-fe54-8bb4e79c664d.png)

## 1-2. CNAMEレコード作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/f371144c-e775-981a-d9e4-5cf489606898.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/4a1c9722-3073-0aea-2156-3e9f5173b19f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/8c767130-0fbf-4fa4-9b87-c0194a3c79be.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/46836eeb-2848-6a0a-c845-e9ec37c9c20f.png)
- `Route53でレコードを作成`ボタンからCNAMEレコードが作成されてから、約30分でステータス`発行済み`に変化

## 1-3. DNS検証
- `検証保留中`からステータスがすぐに変化しなかったため、下記記事を参照にNSレコードの順番変更(※不要だったかもしれません)

https://qiita.com/nossy/items/fd33a8d5dca53e0afc0a

```terminal:ec2-user
$ dig grfl.work +trace
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/9441d34b-cb76-b9d0-838c-93b0527bd882.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/8393183e-3b55-1ac9-8cfd-ae134677084c.png)


# 2. ELB
- `ターゲットグループ/セキュリティグループ/サブネット/ルートテーブル`はELB(ALB)作成中に画面遷移できますが、行ったり来たりが面倒なので先に作成しておきます。

## 2-1. ターゲットグループ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/cbefcea6-dc11-4e46-ff46-da708e9f4598.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/c26b7103-721f-c916-5630-cb32f3e240c0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/8f133e74-899a-9fea-4742-a5cd9c6efa05.png)

## 2-2. セキュリティグループ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/01f6b5ab-3ec5-f64e-dfbc-8afc0a0b269d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/b489a990-570c-40ad-a5ed-ad919084f932.png)

## 2-3. サブネット
- ※CloudFormationにて作成済みのため不要(パブリックサブネットが一つしかない場合は作成)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/fe984c59-2533-54f6-78a9-90a2422083e9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/874c73c6-072f-215a-9af5-f5dccb6f7710.png)

## 2-4. ルートテーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/9c3fe84a-4a22-4e7d-0497-38f63c1e8ee8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/9adc3505-1010-7874-01a8-2f0014a45dfb.png)

## 2-5. ロードバランサー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/fa5b0a6a-faa6-774c-8866-36373069d7a3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/b2fe0d4d-68c7-5953-1f7c-e51a086568c7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/7521035e-f763-4f96-59e3-8b3fa2d9b80a.png)

## 2-6. リスナーの追加と編集
- HTTPS化とHTTPでアクセスした際もHTTPSにリダイレクトするように設定

### 2-6-1. リスナーの追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/5683d617-0d05-f185-e1c8-77dff54207bd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/3fe1db36-bdb2-0d8d-4209-d0ec9a294fa8.png)

### 2-6-2. リスナーの編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/9f5323ae-fe25-d5ff-4269-9c89f336d13f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/7cf67e9c-fc8a-f15a-4078-2db6e94f4cd6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/87185afc-db0b-33cf-0cd6-c91f16ba48b5.png)

## 2-7. ヘルスチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/f6c85684-6561-4948-cb51-3ee4fe236b61.png)


# 3. Route53
- Aレコードエイリアス作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/5fca9d66-684d-8171-8fe5-4fc8c96feb78.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/c4e70e4a-a1a1-ea58-8d75-70648e33e807.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/ee80329e-64db-4d6a-2a0d-9b3db2a518df.png)


# 4. HTTPS化
- 下記bladeだと、Chromeのデベロッパーツールに下記エラーが発生
```php:resources/views/nav.blade.php
<form method="GET" action="{{ route('articles.search') }}" class="d-flex">
```
```
Mixed Content: The page at 'https://grfl.work/' was loaded over a secure connection, but contains a form that targets an insecure endpoint 'http://grfl.work/search'. This endpoint should be made available over a secure connection.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/2d1721af-0e4b-410c-bc05-a2a69c8ed741.png)

## 4-1. .env
```terminal:ec2-user
$ ssh ec2-user@xx.xxx.xxx.xxx -i ~/.ssh/hoge.pem
$ cd /var/www/grfl/src
$ vi .env
```
```diff:.env
- APP_URL=http://xx.xxx.xxx.xxx
- APP_ENV=local
+ APP_URL=https://grfl.work/
+ APP_ENV=production
```

## 4-2. 強制HTTPS化
1. 開発環境で下記編集
2. リモートにpush
3. 本番環境でpull

https://qiita.com/tamakiiii/items/6c31425698660ead643b

https://qiita.com/ghibi/items/cb4faa2d86f5866cbfd4

https://stackoverflow.com/questions/8830060/notice-undefined-index-http-x-forwarded-proto-in-c-users-me-project-index-php

https://qiita.com/wakahara3/items/bb7c8d7a1673b161abe7

### 4-2-1. AppServiceProvider.php
```php:AppServiceProvider.php
public function boot()
{
    if (\App::environment(['production'])) {
        \URL::forceScheme('https');
    }
}
```

### 4-2-2. ForceHttps.php
```php:ForceHttps.php
public function handle($request, Closure $next)
{
  if (\App::environment(['production']) && isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) != 'https') {
    return redirect()->secure($request->getRequestUri());
  }
  return $next($request);
}
```

### 4-2-3. Kernel.php
```php:Kernel.php
protected $middleware = [
  \App\Http\Middleware\ForceHttps::class,
];
```

### 4-2-4. 開発環境でpush
```terminal:local
$ git push origin hoge
// mergeなどしてリモートに反映
```

### 4-2-5. 本番環境でpull
```terminal:ec2-user
$ cd /var/www/grfl
$ git pull origin master
```

## 4-3. migration
```terminal:ec2-user
$ php artisan migrate:refresh --seed
```

## 4-4. 動作確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687994/863d1c73-10d3-c3eb-a240-f129f099f369.png)

## 4-5. エラーハンドリング
- 本番環境でvi編集などしてpull時にコンフリクトが発生した場合は下記で対処

https://dev.classmethod.jp/articles/git-pull-local-change-keep/

# 補足
## 開発環境（FW/ツールのバージョンなど）
|ツール|バージョン|
|:--|:--|
|Vue.js|2.6.14|
|jQuery|3.4.1|
|PHP|7.4.1|
|Laravel|6.20.43|
|MySQL|5.7.36|
|Nginx|1.18.0|
|Composer|2.0.14|
|npm|6.14.6|
|Git|2.33.1|
|Docker|20.10.11|
|docker-compose|v2.2.1|
|PHPUnit|8.0|
|CircleCI|2.1|
|heroku|7.59.4|
|MacBook Air|M1,2020|
|macOS|Monterey 12.3|
|Homebrew|3.3.8|

## ディレクトリ構造
```
【ルートディレクトリ】
├─ .circleci
│   └─ config.yml
├─ aws / CloudFormation
│   └─ ec2.yml
├─ docker
│   └─ mysql
│   └─ nginx
│   └─ php
│   └─ phpmyadmin
├─ src
│   └─ 【Laravelのパッケージ】
└─ docker-compose.yml
```

# Reference
https://www.techpit.jp/courses/11

https://www.techpit.jp/courses/78

https://qiita.com/yuuichimizuta/items/cee204b9e2776056b863

https://qiita.com/yuuichimizuta/items/5d3b9e4872ad8ae1db4f

https://qiita.com/yuuichimizuta/items/61f22085342430a69a32

https://qiita.com/yuuichimizuta/items/d7dabc1b4b21de0e7e60

https://qiita.com/yuuichimizuta/items/23ed28b7518cdd9a7801

https://qiita.com/yyy752/items/355b01c17b440963afe3

https://qiita.com/nakanishi03/items/3a514026acc7abe25977

https://zenn.dev/mn87/articles/90609fffd8c634

https://qiita.com/nossy/items/fd33a8d5dca53e0afc0a

https://qiita.com/hoto17296/items/b097214640bdcc6413e2

https://qiita.com/tamakiiii/items/6c31425698660ead643b

https://qiita.com/ghibi/items/cb4faa2d86f5866cbfd4

https://stackoverflow.com/questions/8830060/notice-undefined-index-http-x-forwarded-proto-in-c-users-me-project-index-php

https://qiita.com/wakahara3/items/bb7c8d7a1673b161abe7

https://dev.classmethod.jp/articles/git-pull-local-change-keep/

# 次回記事
- 【AWS】LaravelアプリをEC2デプロイ④【CircleCI / CodeDeploy編】

https://qiita.com/kazumakishimoto/items/09b84473c44c5899ee57

- 【AWS】LaravelアプリをEC2デプロイ⑤【SNS / Chatbot編】

https://qiita.com/kazumakishimoto/items/b38c34a1275c4e9cd373

- 【AWS】LaravelアプリをEC2デプロイ⑥【S3編】

https://qiita.com/kazumakishimoto/items/d08894711bf59a4e21df

- 【AWS】LaravelアプリをEC2デプロイ⑦【API編】

https://qiita.com/kazumakishimoto/items/fd4afc02f9490ddb89e5

- 【AWS】お役立ちリンク集【随時更新】

https://qiita.com/kazumakishimoto/items/02e53cdf7b9887252040