EC2,Docker,NginxでLet’s Encryptを使ってSSLを導入する方法

こんにちは!

今回は、Amazon EC2で動かしているDockerにNginxコンテナにLet’s Encryptを使ってSSLを導入する方法を紹介します。

また、certbotを使って自動更新をする方法も合わせて紹介します。

Let’s Encryptとは?

Let’s Encryptとは、Internet Security Research Groupが運営しているサービスです。

Let’s Encryptを使用することで、無料でSSL証明書を取得できます。

公式サイトはこちら

SSL化の手順

1.Dockerfileにopenssl,certbotの記述を追加
2.certbotで証明書の発行
3.NginxのSSL設定
4.let’s encryptの更新スクリプトの作成

Dockerfileにopenssl,certbotの記述を追加

まずは、opensslとcertbotをDockerfileに記述します。

記述ができたら、今度は下記の記述を追加します。

「sites/」以下にある、今回SSLを反映するファイルに下記の部分を追加します。

記述ができたら、この構成でDokcerを停止しましょう。

停止したら、buildコマンドでbuildを掛けます。

buildを掛けたら、またDokcerを起動しましょう。

これでopensslとcertbotを使用できるようになりました。

certbotで証明書の発行

opensslとcertbotを使用できるようになったら、nginxのワークスペースに下記のコマンドで入り、SSLで使用する証明書を発行します。

Niginxのコンテナに入ったら、下記のコマンドを使ってSSL証明書を発行します。

コマンドの説明

使用しているコマンドのオプションについて紹介します。

certonlyについて

SSL/TLS証明書の取得のみを行いますという意味です。

–agree-tos について

ACME 利用規約に同意するという意味です。

–webrootについて

このオプションを追加することで、稼働中のサービスを落とさずにSSL証明書の発行や更新ができるようになります。

-wについて

ここには、紐付けるルートを指定します。

ドメインが紐付いている場所を指定しましょう。

-dについて

発行したSSL/TLS証明書を使用するドメインを指定します。

もし、下記のようにエラーが表示された場合は指定したドメイン名が有効でない可能性があります。

指定したドメインが有効かどうかを確認するようにしましょう。

Non-ASCII domain names not supported. To issue for an Internationalized Domain Name, use Punycode

うまくコマンドが動作すると下記のように質問が飛んできます。

質問1

How would you like to authenticate with the ACME CA?
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Select the appropriate number [1-2] then [enter] (press ‘c’ to cancel):

ここは「2」を選択します。

質問2

Enter email address (used for urgent renewal and security notices) (Enter ‘c’ to
cancel):

ここには、緊急連絡先として送信したいメールアドレスを入力します。

質問3

– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
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.
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –

CertbotやLet’s Encryptに対してのニュースレターを受け取りますか?

というメッセージが表示されます。

Yes、Noで好きなように答えましょう。

もしエラーが出たら

もし、コマンドを入力する中で下記のようなエラーが出た場合は、下記のコマンドで指定したドメインとドキュメントルートにアクセスできるかどうかを確認しましょう。

NginxのSSL設定

証明書の発行ができたら、Nginxでhttpsで表示するために必要な設定を行っていきます。

sites/以下にある、今回SSL化を設定した「.conf」ファイルの中に下記のように記述が加えられている箇所があると思います。

上記を下記のように変更します。

ちなみに他にも、ここで使えるSSLのmoduleは下記の公式サイトに記載されています。

Module ngx_http_ssl_moduleリスト

記述を変更できたら、この構成でDokcerを停止しましょう。

停止したら、buildコマンドでbuildを掛けます。

buildを掛けたら、またDokcerを起動しましょう。

これで「http」にアクセスしたら、「https」にリダイレクトされるようになります。

let’s encryptの更新スクリプトの作成

let’sencryptの証明書は90日で期限があり、それを過ぎるとhttpsでアクセスできなくなります。

そのため最後にlet’sencryptを自動で更新するスクリプトを、cronジョブに仕込んでおきます。

これで、let’secnryptの期限が切れても、自動で更新されるようになります。

certbotでlet’s encryptを自動更新するには、DokcerのNginxコンテナ内で下記のコマンドを入力します。

このコマンドを定期的に実行されるようにcrontabでcrongジョブとして登録します。

cronは下記の2つのステップで実行しましょう。

(作業時のユーザーレベルはrootで行います。)

1.DockerのNginxに証明書更新のshファイルを作成
2.AWSで作成したshファイルを実行するように記述

DockerのNginxに証明書更新のshファイルを作成

まずは、下記のコマンドでDockerのnginxのコンテナに入ります。

入ったら、「/var/cronjob/」のディレクトリを作成しましょう。

ディレクトリの作成ができたら、今度はコンテナ内部のPATHを下記のコマンドで確認しておきます。

表示されたパスは後で使うので、コピーします。

パスの確認ができたら、「/var/cronjob/certbot.sh」という名前でファイルを作ります。

ファイルの中身は次の内容で記述します。

PATH=というようにしておかないとエラーが出てしまうため、PATHを記述するようにします。

AWSで作成したshファイルを実行するように記述

「/var/cronjob/certbot.sh」にファイルが作れたら、今度はEC2側でcronジョブの登録を行います。

まずは、下記のコマンドでcronが動いているかチェックします。

動いていたら、「crond (pid ) を実行中…」のように表示されると思います。

動いていなかったら、下記のコマンドで起動しましょう。

今度はcronのプロセスをチェックします。

チェックするには、下記のコマンドを入力します。

下記のように2~5が「on」になっていたらOKっぽいです。

それぞれチェックができたら、cronジョブを登録しましょう。

cronジョブを登録するには、下記のコマンドを入力します。

入力ができたら、下記のように入力します。

上記のコードでは、次のような手順で処理を行っています。

1.docker execでNginxのコンテナに入る。

2.コンテナ内部の「certbot.sh」を実行。

3.デバッグできるように結果を、EC2内部の「/var/log/certbot_job.log」にログに出力

ちなみに「* *」は左から「分」「時」「日」「月」「曜日」となっています。

* * * * * 実行するコマンド

上記のコマンドだと「00 04 01 * *」なので、「00分」「AM4時」「毎月」「曜日していなし」にジョブを実行という意味になります。

ちなみに、テストをする場合は、下記のように設定すると良いかと思います。

設定したcronを削除するには、もう一度下記のコマンドを実行していらないcronジョブを削除するにようにしましょう。

うまく動作していると証明書を作りたての場合、下記のような内容が「certbot_job.log」内に出力されいていると思います。

まとめ

最後までお読み頂き、ありがとうございます。

今回はDockerで動かしているNginxにLet’s Encryptを使ってSSLを導入する方法を紹介しました。

この記事があなたの役に立てば幸いです。

もし、cronが動かないといった場合はサーバー内部の時間なども確認してみてください。

もしかすると、cronで設定している時間とサーバー内部の時間にズレがあるため、動作しないといったこともありえます。

(時計をみたら14:00だけど、サーバー内部は04:00とか。)

この記事を書いた人

南 健太郎

1991年生まれ。都内でエンジニアをしています。
このブログでは、個人開発や日々の技術に関する情報などを発信していきます。