テスト環境やステージング環境で、SSLを導入する際に、手軽にLet's Encryptを使うという場面が出てくると思う。今回は、Amazon Linux + Rails + Nginxの環境にLet's Encryptを導入する際にいくつかハマったところがあったのでメモをする。
ちなみに、Amazon Linux2ではcertbotは正式にサポートされていないので、本番環境ではやめたほうがいいかもしれません。ただ、正常に動作しています。
以下の注意文言は、チュートリアル: Amazon Linux 2 に SSL/TLS を設定する - Amazon Elastic Compute Cloud より。
Certbot は Amazon Linux 2 で公式にサポートされていませんが、ダウンロードすることができ、
インストールすると正常に機能します。データを保護し、問題を回避するため、次のバックアップを作成しておくことをお勧めします。
環境情報
- Amazon Linux AMI release 2018.03
- Rails 5.2.1
- Nginx 1.14.1
導入手順
certbotの導入
certbotをgitからcloneするだけです。作業用ディレクトリの/usr/local/
に今回は落としました。
$ cd /usr/local
$ git clone https://github.com/certbot/certbot
このcertbotを使うことでSSLの導入を行うことができます。
$ cd certbot
$ ./certbot-auto --help
helpコマンドが動作していれば導入は成功です。
SSL証明書の発行をする前に、nginxを落としておきましょう。
なんか証明書の発行がうまくいかなかったので。。。
$ sudo nginx -s stop
SSLの証明書の発行
導入しようとしたら、Let's Encryptが正式にサポートされていないため、バックアップをとってから、--debug
オプションをつけて実行してくださいとのエラーが出てきました。なので、念の為、AMIでバックアップをとりました。
$ ./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オプションをつけて実行。
$ ./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を使うように設定。
alternatives --set python /usr/bin/python2.7
再度、コマンドを実行すると以下のようになります。
$ ./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;
を忘れずに。詳しい解説は以下が参考になります。
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の設定ができたら、再起動しましょう。
$ sudo service nginx start
Rails側の設定
production環境はデフォルトでSSL設定されていると思いますが、今回はテスト環境だったので、以下を追記。
これにより、httpでアクセスされたものも、Rails側でリダイレクトさせることができます。
config.force_ssl = true
上述しましたが、この設定をする場合はnginxのconfniproxy_set_header X-FORWARDED_PROTO https;
を記述して、
アプリケーション側にhttpsでのアクセスであることを伝えるようにしないと無限ループになりますので、注意です!
参考
チュートリアル: Amazon Linux 2 に SSL/TLS を設定する - Amazon Elastic Compute Cloud
alternatives で python を 2.7に切り替える - Qiita