Elastic Beanstalk（Nodeプラットフォーム）でhttpアクセスをhttpsアクセスにリダイレクトする

## 前提

* Beanstalkを使っている
* Nodeプラットフォームを選択している
* Beanstalkのソフトウェア設定内でプロキシサーバにnginxを設定している
![image.png](https://qiita-image-store.s3.amazonaws.com/0/6061/e97f292e-13aa-2b72-aa1c-8c9664b9f50e.png)
* Beanstalkのロードバランサー設定でhttp / httpsともにポート開放しており、httpsについては証明書設定も完了している（容量設定で環境タイプを負荷分散にしないといけないかも？）
    * httpアクセスもhttpsアクセスも普通にできる状態ができていること
![image.png](https://qiita-image-store.s3.amazonaws.com/0/6061/d52301cd-ddc4-4ae2-483a-02afd48fe1b0.png)

## 設定内容

nginx設定を変更するため、プロジェクトのルートに`.ebebextensions`ディレクトリを作成し、その中に configファイルを用意します。

```.ebextensions/proxy.config
files:
  /etc/nginx/conf.d/proxy.conf:
    mode: "000644"
    owner: root
    group: root
    content: |
      upstream nodejs {
        server 127.0.0.1:8081;
        keepalive 256;
      }
      
      server {
        listen 8080;
      
      
        if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
          set $year $1;
          set $month $2;
          set $day $3;
          set $hour $4;
        }
        access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
        access_log  /var/log/nginx/access.log  main;
      
      
        if ($http_x_forwarded_proto != 'https') {
          rewrite ^(.*) https://$host$1 redirect;
        }
      
        location / {
          proxy_pass  http://nodejs;
          proxy_set_header   Connection "";
          proxy_http_version 1.1;
          proxy_set_header        Host            $host;
          proxy_set_header        X-Real-IP       $remote_addr;
          proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
      
        gzip on;
        gzip_comp_level 4;
        gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
      }

  /opt/elasticbeanstalk/hooks/configdeploy/post/99_kill_default_nginx.sh:
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash -xe
      rm -f /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf
      service nginx stop 
      service nginx start

container_commands:
 removeconfig:
    command: "rm -f /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf"
```

あとはBeanstalkでデプロイすればOK！
httpへのアクセスがhttpsにリライトされるはずです。

## 詳細解説

BeanstalkにデプロイしたアプリケーションはEC2インスタンスに展開されます。
基本的にはEC2インスタンスにログインし、`/etc/nginx/conf.d`あたりを直接見るとデフォルトの設定状況などがよくわかるかと思います。

今回の設定内容の詳細は以下のとおりです。Beanstalkの基本的な設定として`files:`で書かれたファイルがデプロイ時に作成されることは理解しておきましょう。

1. `proxy.config`を作成してEC2の`/etc/nginx/conf.d`以下に配置する
2. デフォルトの設定である`00_elastic_beanstalk_proxy.conf`を削除 → `rm -f /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf`と`removeconfig`あたり
3. nginxの再起動 → `/opt/elasticbeanstalk/hooks/configdeploy/post`はデプロイ時のフック処理という意味です

`proxy.config`の中身の大半は実際には`00_elastic_beanstalk_proxy.conf`であり、以下の数行を追加したのみです。

```
if ($http_x_forwarded_proto != 'https') {
  rewrite ^(.*) https://$host$1 redirect;
}
```

## どうやって試したか

上記設定を確認するためにいちいち`.ebebextensions`内のファイルを編集してデプロイしていたのでは時間がかかりすぎてしまいます。（1デプロイあたりで10分とか？）

そのため自分は、対象のEC2インスタンスに直接sshログインをして直接ファイル編集とnginxの再起動をして動作確認を行い、その内容を`.ebebextensions`内に反映するという方法を取りました。

```bash
# EC２へログイン
$ ssh -i my_ec2_key.pem ec2-user@XX.XX.XX.XX

# EC2上
$ sudo vim /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf
# ↑`rewrite`設定を直書きしてみる
$ sudo nginx -s reload
# アクセスしてみる！できた！→プロジェクトの`.ebebextensions`を変更してデプロイ
```

この方法が正しいのかどうかはわかりませんのでご参考まで...

## 参考資料

実はものすごくハマってしまったのですが、最終的にはAWSの公式ドキュメントとnginxの基本的な設定だけ把握していれば解決できました。

* [プロキシサーバーを設定する](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/nodejs-platform-proxy.htmlv)
* [AWSのELBとNginxでhttpアクセスをhttpsにリダイレクトしたい](https://qiita.com/snoguchi/items/f5ccb67592f87942480d)