certbotでWebサイトをHTTPS化してみた【Nginx/EC2】

certbotでWebサイトをHTTPS化してみた【Nginx/EC2】

こんにちは、えびかずきです。

最近、個人作成したWebサイトの公開をしたのですが、サイトのHTTPS化に少し手間取ったので、備忘録として記事に残しておこうと思います。

この記事をみてくれた方が、スムーズに作業ができるよう少しでも参考になればと思います。

開発環境

OS:Amazon Linux 2(AWS EC2仮想マシン)
Webサーバーシステム:Nginx(エンジンエックス)
WSGI:Gunicorn
Python:3.7.3
Django:2.2.2
PostgreSQL:10.4
ネームサーバー:XSERVER
暗号化:certbot(旧Let’s Encrypt)

作業の概要

今回おこなう作業はWebサイトのHTTPS化です。

要するに『http://~』でアクセスしていたWebサイトを『https://~』に変更して、暗号化を使った安全な通信ができるようにします。

作業の概要は下図に示しました。

青色が作業前の状況をあわらしていて、赤色が作業後の状況をあらわしています。

AWS-EC2で運用している開発者側の運用サーバーにcertbotを入れて、暗号通信を行います。

certbotの導入

まず、開発環境(私の場合AWS-EC2上)へcertbotを導入します。

作業ユーザーのホームディレクトリに、以下とおりgithubから複製します。

$ git clone https://github.com/certbot/certbot

保存できたかどうかの確認は『ls -l』コマンドでディレクトリ内のファイルリストを確認してみてください。

Amazon Linux2の場合、短縮コマンドの『ll』も使えます。

$ ll
合計 8
drwxrwxr-x 30 app_admin app_admin 4096  7月 16 15:19 certbot
-rw-r--r--  1 app_admin app_admin    0  7月 18 13:00 cron.log
drwxrwxr-x  6 app_admin app_admin   95  7月 15 01:45 py373_django_test_env
-rw-r--r--  1 app_admin app_admin  262  7月 15 01:04 requirements.txt

python-virtualenvのインストール

続いて、certbotの実行で使われるpython-virtualenvをインストールします。

以下のようにしてインストールします。

$ sudo yum -y install python-virtualenv

SSL証明書と秘密鍵の発行

HTTPS化の準備として、SSL証明書と秘密鍵の発行をおこないます。

1.Nginx設定ファイル(Nginx.conf)をエディタで開く。

$ sudo vi /etc/nginx/nginx.conf

2.「i」キーを押してinsertモードにして、location設定を追加。

これは、SSL証明書を発行するためにおこなうチャレンジ用の設定です。

編集が終われば、「esc」キーを押して「:wq」で保存して終了。

server {
   (略)
  #追加
  location /.well-known/acme-challenge {
   root /usr/share/nginx/html;
  }
   (略)
}
えびかずき
えびかずき

locationとrootの後はスペースが入ることに注意。

3.設定を有効にするためにNginxをリロードする。

Amazon Linux2の場合は以下のようにサービス管理コマンド『systemctl』で以下のようにする。

$ sudo systemctl reload nginx.service

4.SSL証明書と秘密鍵の発行

以下コマンドでチャレンジを実施してSSL証明書をcertbotに発行してもらいます。

$ sudo ~/certbot/certbot-auto --no-bootstrap certonly --webroot -w /usr/share/nginx/html -d <ドメイン> -m <メールアドレス> --agree-tos

『-m』で指定したメールアドレスは証明書の期限切れなどの通知を受けるためのものです。

すると下のように、メールを管理組織で共有して情報通知のために使って良いですか?というような内容の質問文がくるので、『y』キーYesと回答します。

Would you be willing, once your first certificate is successfully issued, 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.

(Y)es/(N)o:


チャレンジとは?
ここでは、指定されたドメイン(xxx.comなど)が本当に作業者のものであるかどうかを確認してからSSL証明書が発行されています。

上のコマンドでは、『-w』で指定したサーバーのディレクトリに確認用のワンタイムトークンを設置するように指示して、それをcertbotがhttp://<DOMAIN>/.well-known/acme-challenge/<TOKEN>というURLで外部からアクセスして問題なくレスポンスが得られれば、OKというわけです。

詳しくはこちら(Let’s Encrypt公式):https://letsencrypt.org/ja/docs/challenge-types/


5−a.チャレンジに成功した場合は以下の文が表示されます。

IMPORTANT NOTES:
– Congratulations!
Your certificate and chain have been saved at:
   /etc/letsencrypt/live/<DOMAIN>/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/<DOMAIN>/privkey.pem
   Your cert will expire on 2020-10-15. 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”

5−b.チャレンジに失敗した場合は例えば以下のようは表示になります。

IMPORTANT NOTES:
– The following errors were reported by the server:
 Domain: <ドメイン名>
Type:   unauthorized
Detail: Invalid response from
http://<DOMAIN>/.well-known/acme-challenge/<TOKEN>
[IPアドレス]: 400
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain contain(s) the right IP address.


このエラー文では不正なレスポンスです。DNSレコードを確認してくださいというとうな内容が書かれています。

私の場合は、Nginx.confの編集で、rootと/usr/~をスペースなしでくっつけて入力していたという凡ミスでエラーが出ましたが、そこを修正するとチャレンジに成功しました。

チャレンジに失敗する場合、以下の記事なども参考になると思います。

話題の無料SSL証明書!Let’s Encryptで証明書の取得に失敗したときに確認すること

HTTPS化

SSL証明書と秘密鍵を入手することができたので、あとはNginxの設定をすれば完了です。

私の場合は、HTTP用の80番はhttps://<ホスト名>へリダイレクトするように設定して、HTTPS用の443番に、SSL情報と元々40番に書いていたloction情報をコピペしました。

  server {
        listen       80;
        server_name  <Elastic IP>;
        return 301 https://$host$request_uri;
    }

server {
        listen       443 ssl;
        server_name  <Elastic IP>;
        root         /usr/share/nginx/html;

        ssl_certificate "/etc/letsencrypt/live/<DOMAIN>/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/<DOMAIN>/privkey.pem";

        location /static {
          alias /usr/share/nginx/html/static;
        }

        location /media {
          alias /usr/share/nginx/html/media;
        }

        location /.well-known/acme-challenge {
          root /usr/share/nginx/html;
        }

        location / {
          proxy_set_header Host $http_host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;

          proxy_pass http://127.0.0.1:8000;
        }
  
          error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

これで設定完了のはずが、私の場合はHTTPS化はおろか、Webサイトにアクセスできなってしまいました。。。

まず『status』コマンドでnginxの状況を確認してみたところ、どうもエラーがあるようです。

$ systemctl status nginx.service
 Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since 金 2020-07-17 12:10:07 JST; 1min 45s ago
  Process: 9484 ExecReload=/bin/kill -s HUP $MAINPID (code=exited, status=0/SUCCESS)
  Process: 9538 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
  Process: 9537 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 28954 (code=exited, status=0/SUCCESS)

『nginx -t』コマンドでエラー内容を確認してみると、どうもSSL証明書にアクセスできていないようです。

nginx -t
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2020/07/17 13:28:44 [warn] 9977#0: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:5
2020/07/17 13:28:44 [emerg] 9977#0: BIO_new_file("/etc/letsencrypt/live/<DOMAIN>/fullchain.pem") failed (SSL: error:0200100D:system library:fopen:Permission denied:fopen('/etc/letsencrypt/live/<DOMAIN>/fullchain.pem','r') error:2006D002:BIO routines:BIO_new_file:system lib)
nginx: configuration file /etc/nginx/nginx.conf test failed

ということで、以下の内容をいろいろ試行錯誤してみたところ、無事HTTPS化に成功しました。

①Nginx.confの再編集
②『$ sudo su -』でスーパーユーザーに切り替え、『chmod』コマンドで問題のファイルのアクセス権を広げた。
③NginxとGunicornを一度落として、再起動した。

①〜③をいろいろやっている内に、https://~でアクセスできるようになりました。
エラー文からして②があやしい?

なにはともあれ、やりたいことは完了しました。

SSL証明書の自動更新設定

最後におまけとして、SSL証明書の自動更新設定についてです。

SSL証明書は90日で有効期限が切れてしまうので、更新が必要です。

下のようにして設定します。

1.下コマンドでcron設定画面を開く。

 $ sudo crontab -e

2.内容を編集(「i」→編集→「esc」→:wq)

※下の設定の場合、毎月1日の午前2時に更新することになる。
※設定は『分 時 日 月 曜日』の順。

  0 2 1 * * /home/<ユーザー名>/certbot/certbot-auto renew -q --renew-hook "usr/bin/systemctl reload nginx.service"

まとめ

今回はWebサイトのHTTPS化の手順について説明しました。

実際に自分がつまずいたところも書き足していったので、かなり長い記事になってしまいました。

この記事が誰かの参考になればうれしいです。

参考書籍

この記事は下の書籍を参考にさせていただきました。

動かして学ぶ!Python Django開発入門(kindle版)

Web開発カテゴリの最新記事