Amazon Linux + Rails + Nginx環境にLet's Encryptを導入する

テスト環境やステージング環境で、SSLを導入する際に、手軽にLet's Encryptを使うという場面が出てくると思う。今回は、Amazon Linux ＋ Rails + Nginxの環境にLet's Encryptを導入する際にいくつかハマったところがあったのでメモをする。
ちなみに、Amazon Linux2ではcertbotは正式にサポートされていないので、本番環境ではやめたほうがいいかもしれません。ただ、正常に動作しています。

以下の注意文言は、[チュートリアル: Amazon Linux 2 に SSL/TLS を設定する - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2.html#letsencrypt) より。

*Certbot は Amazon Linux 2 で公式にサポートされていませんが、ダウンロードすることができ、
インストールすると正常に機能します。データを保護し、問題を回避するため、次のバックアップを作成しておくことをお勧めします。*



## 環境情報
- Amazon Linux AMI release 2018.03
- Rails 5.2.1
- Nginx 1.14.1

## 導入手順

### certbotの導入

certbotをgitからcloneするだけです。作業用ディレクトリの`/usr/local/`に今回は落としました。

```console
$ cd /usr/local
$ git clone https://github.com/certbot/certbot
```

このcertbotを使うことでSSLの導入を行うことができます。

```console
$ cd certbot
$ ./certbot-auto --help
```

helpコマンドが動作していれば導入は成功です。

SSL証明書の発行をする前に、nginxを落としておきましょう。
なんか証明書の発行がうまくいかなかったので。。。

```console
$ sudo nginx -s stop
```

### SSLの証明書の発行
導入しようとしたら、Let's Encryptが正式にサポートされていないため、バックアップをとってから、`--debug`オプションをつけて実行してくださいとのエラーが出てきました。なので、念の為、AMIでバックアップをとりました。

```console:debugオプションなし時のエラー内容
$ ./certbot-auto certonly --standalone -t

FATAL: Amazon Linux support is very experimental at present...
if you would like to work on improving it, please ensure you have backups
and then run this script again with the --debug flag!
Alternatively, you can install OS dependencies yourself and run this script
again with --no-bootstrap.
```

改めて、Amazon LinuxでLet's Encryptを入れる方はdebugオプションをつけて実行。

```console
$ ./certbot-auto certonly --standalone -t --debug

Creating virtual environment...
Traceback (most recent call last):
  File "<stdin>", line 27, in <module>
  File "<stdin>", line 19, in create_venv
  File "/usr/lib64/python2.7/subprocess.py", line 185, in check_call
    retcode = call(*popenargs, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 172, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib64/python2.7/subprocess.py", line 394, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1047, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
```

今度は、pythonのファイルがない？のかエラーになりました。
どうやら、使用するpythonのバージョンが古かったぽいので、2.7を使うように設定。

```sh
alternatives --set python /usr/bin/python2.7
```

再度、コマンドを実行すると以下のようになります。

```console

$ ./certbot-auto certonly --standalone -t --debug

Creating virtual environment...
Installing Python packages...
Installation succeeded.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' 
```
メールアドレスを入力して、


```
-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A
```

```
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```

ドメインを聞かれるので、ドメインを入力します。

```
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): test.hoge.jp
```

すると、以下のような文言が出てきました。これでどうやら証明書の発行は完了らしい。

```
MPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/test.hoge.jp/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/test.hoge.jp/privkey.pem
   Your cert will expire on 2019-11-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
```

証明書が`/etc/letsencrypt/live/`の下に発行されるので、これを読み込むようにNginxであとは設定するだけ。

### Nginxの設定

443ポートのリクエストを受け付けるように設定して、証明書のパスを記述。
また、Railsの場合は、`proxy_set_header X-FORWARDED_PROTO https;`
を忘れずに。詳しい解説は以下が参考になります。

[Nginx のリバースプロキシ設定のメモ - Qiita](https://qiita.com/HeRo/items/7063b86b5e8a2efde0f4)

```nginx:nginx.conf
server {
    listen 443 ssl default deferred;
    ssl_certificate     /etc/letsencrypt/live/test.hoge.jp/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.hoge.jp/privkey.pem;

    # <中略> # 
}
location /  {
   add_header  Access-Control-Allow-Origin *;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       # httpsの設定をしてあげないとRailsの方でSSL判定できずに無限ループに陥る
       proxy_set_header X-FORWARDED_PROTO https;
       proxy_set_header Host $http_host;
       proxy_redirect off;
       if (!-f $request_filename) {
         proxy_pass http://app;
         break;
       }
}
```

Nginxの設定ができたら、再起動しましょう。

```console
$ sudo service nginx start
```

### Rails側の設定

production環境はデフォルトでSSL設定されていると思いますが、今回はテスト環境だったので、以下を追記。
これにより、httpでアクセスされたものも、Rails側でリダイレクトさせることができます。

```ruby:config/environments/test.rb
config.force_ssl = true
```


上述しましたが、この設定をする場合はnginxのconfni`proxy_set_header X-FORWARDED_PROTO https;`を記述して、
アプリケーション側にhttpsでのアクセスであることを伝えるようにしないと無限ループになりますので、注意です！

## 参考

[チュートリアル: Amazon Linux 2 に SSL/TLS を設定する - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2.html#letsencrypt)

[alternatives で python を 2.7に切り替える - Qiita](https://qiita.com/inouet/items/aa7626aead5e5e41b848)

[Let&#39;s Encrypt で Nginx にSSLを設定する - Qiita](https://qiita.com/HeRo/items/f9eb8d8a08d4d5b63ee9)

[Nginx のリバースプロキシ設定のメモ - Qiita](https://qiita.com/HeRo/items/7063b86b5e8a2efde0f4)

[railsアプリケーションをhttpsでアクセスできるようにするまでのこと。 - Qiita](https://qiita.com/katsumata_ryo/items/29ed22a128c16a113b0d)