LoginSignup
13
11

More than 3 years have passed since last update.

[Rails][Nginx][AWS] Let's EncryptをEC2上のRailsに入れてHttpsにする

Last updated at Posted at 2019-05-01

Amazon linux 2 の場合はこちら


EC2にssh接続しているとします。
まず、certbotをクローンします。

terminal
cd /usr/local
sudo git clone https://github.com/certbot/certbot
cd certbot

次に、証明書の作成を申請します。

申請するにあたって、Let's Encryptが認証するためのディレクトリを作成します。
(他の記事では/var/www/htmlなどとしている場合が多いですが、Amazon Linuxではデフォルトでそのようなディレクトリはないので、新たに作成します。)

terminal
# ディレクトリ名は自由ですが、今回は letsencrypt-webroot とします。
sudo mkdir /var/www/letsencrypt-webroot

さらに、nginxの設定を追加します。

terminal
# 【】は置き換えてください
sudo vi 【nginxの設定ファイルのパス(例:/etc/nginx/conf.d/myconf.conf)】
nginxの設定ファイル
server {
  listen 80;

  ...

  # 以下を追加(^~は前方一致です)
  location ^~ /.well-known/acme-challenge/ {
      root /var/www/letsencrypt-webroot;
    }
}

その後、nginxを再起動します。

sudo service nginx restart

次に、以下のコマンドで認証可能かどうかを確認します。
(認証申請が1時間に5回Failすると、一定時間申請できなくなります(Rate Limits - Let's Encrypt - Free SSL/TLS Certificates)。そのため、先に認証可能かどうかを確認します。)

terminal
# 【】の所は置き換えてください
/usr/local/certbot/certbot-auto certonly --webroot --agree-tos --debug -m 【メールアドレス(例:○○@○○.com)】 -d 【ドメイン名(例:○○.com)】 -w /var/www/letsencrypt-webroot --dry-run

以下が出たら認証可能です。

IMPORTANT NOTES:
 - The dry run was successful.

上のコマンドの--dry-runを外して認証申請をします。
(登録されたメールアドレスには、Let's Encryptからの通知(認証の有効期限が近づいてきた時の通知など)が届きます。)

terminal
/usr/local/certbot/certbot-auto certonly --webroot --agree-tos --debug -m 【メールアドレス(例:○○@○○.com)】 -d 【ドメイン名(例:○○.com)】 -w /var/www/letsencrypt-webroot

以下が出たら認証成功です。

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/○○.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/○○.com/privkey.pem
   Your cert will expire on 2019-07-30. 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

証明書が発行されたかを確認します。

terminal
# 【】は置き換えてください。
sudo ls -lrth /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/

以下が表示されればOKです。

total 4.0K
-rw-r--r-- 1 root root 692 May  1 11:41 README
lrwxrwxrwx 1 root root  51 May  1 11:41 privkey.pem -> ../../archive/【ドメイン名(例:○○.com)】/privkey1.pem
lrwxrwxrwx 1 root root  53 May  1 11:41 fullchain.pem -> ../../archive/【ドメイン名(例:○○.com)】/fullchain1.pem
lrwxrwxrwx 1 root root  49 May  1 11:41 chain.pem -> ../../archive/【ドメイン名(例:○○.com)】/chain1.pem
lrwxrwxrwx 1 root root  48 May  1 11:41 cert.pem -> ../../archive/【ドメイン名(例:○○.com)】/cert1.pem

次に、nginxの設定ファイルをSSL用に更新します。

terminal
# 【】は置き換えてください
sudo vi 【nginxの設定ファイルのパス(例:/etc/nginx/conf.d/myconf.conf)】
nginxの設定ファイル
# 【】は置き換えてください。

# 1. server{}の中を以下の様に書きかえてください。
server {
  # listenを80から443に変更
  # listen 80;
  listen 443 ssl;

  location @app {
    ...

    # 以下を追記
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
  }

  # 以下を追記
  ssl_certificate /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/privkey.pem;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}

# 2. 以下を追加してください。
server {
  listen      80;
  server_name 【ドメイン名(例:○○.com)】;
  return      301 https://$host$request_uri;
}

nginxを再起動します。

terminal
sudo service nginx restart

以上でSSLの設定は完了です。
ブラウザからこのサイトにアクセスしてみましょう。https接続になるはずです。
また、http://として接続した場合でも、自動でhttps接続になるはずです。


Let's Encryptの有効期間は3カ月と短いです。
自動で更新されるように、crontabで設定しておきましょう。

terminal
sudo crontab -e # rootでcrontabを編集すれば、設定コマンド内でsudoを使わなくて済みます。
crontab
0 4 * * * /usr/local/certbot/certbot-auto renew --no-self-upgrade --debug --post-hook "service nginx restart"

--no-self-upgradeを付ける事で、自動でバージョアップするのを防いでいます。(AWSドキュメントより)

--debugを付けているのは、下記のエラーが出ないようにするためです。

--post-hookで証明書更新後にNginxも再起動する様にしています。

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.

この例では、毎日午前4時に自動で更新チェックがかかるようになります。

設定後、cronデーモンを再起動します。

terminal
sudo service crond restart

Amazon Linux 2の場合

上記の方法では Amazon Linux 2 でエラーが出ます。この場合は、こちらを行なったあと、Nginxの設定ファイルに以下の追記をしてください。(【ドメイン名(例:○○.com)】は置き換えてください。)その後、sudo service nginx restartをしてください。

nginxの設定ファイル
server {
  # listen 80 のようになっていると思います。これを以下のように変えてください。
  listen 443 ssl;

 # ドメイン名は変更してください!
  server_name 【ドメイン名(例:○○.com)】;

  location @app {

    ...

    # 以下を追記 ------------------------------------
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    # ---------------------------------------------
  }

  # 以下を追記 ------------------------------------
  # ドメイン名は変更してください!(2箇所)
  ssl_certificate /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/【ドメイン名(例:○○.com)】/privkey.pem
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  # ---------------------------------------------
}

# 以下を追記 ------------------------------------
# httpでのアクセスをhttpsに転送する設定です。 
# ドメイン名は変更してください!
server {
  listen      80;
  server_name 【ドメイン名(例:○○.com)】;
  return      301 https://$host$request_uri;
}
# ----------------------------------------------

追記

上記の参照サイトでのcrontabの設定は、以下のように書き換えても良いかもしれません。rootを消して(私の環境では動かなかったため)、service nginx restartを追加しています。

crontab
# before
0 0,12 * * * root certbot renew --no-self-upgrade

# after
0 0,12 * * *      certbot renew --no-self-upgrade && service nginx restart

追記

crontabのコマンドをさらに改変しても良いでしょう。
- 0,12 時に実行4時に実行(1回で十分なので)
- post-hookとしてservice nginx restartを設定して、証明書の更新が行われた時だけNginxも更新する様にする。

crontab
0 4 * * * certbot renew --no-self-upgrade --post-hook "service nginx restart"

参考

Nginx Rails unicorn HTTPS SSL 対応 - Qiita
【Ruby on Rails】Nginxとunicornを使ってHTTPS(SSL)対応する方法 | Y-hilite
Let's Encrypt で Nginx にSSLを設定する - Qiita

13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11