Let's Encrypt で HTTPS な nginx 構築

おおまかな流れ

nginx を HTTPS 対応するおまかな流れは以下の通りです。

  • Let's Encript が提供するツール "Certbot" のインストール
  • 上記ツールを利用して SSL/TSL 証明書を取得
  • 取得した証明書を nginx に設定して HTTPS に対応

ちなみに、Let's Encript のサイトはこちらです。

letsencrypt.org

また、日本語ポータルサイトもあるので、適宜参考にすること。

letsencrypt.jp

Certbot のインストール

基本的には、Certbot 本家サイトに従えばインストールできます。

certbot.eff.org

自分のサイトは、OS:Ubuntu 16.04(Xenial) 、Webサーバ:nginx である。この場合、インストール手順は下記のとおり(本家サイトの説明通り)。

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx 

証明書取得

ここからは、Certbot 本家のサイトに書いてあるのとちょっと違う。なぜなら、nginxサーバが Dockerコンテナの入っていたりゴニュゴニュしているためです。*1

今回は、3つのサーバに対応した証明書を発行してもらいます。具体的には、"-d" オプションで複数のサーバ名を指定すればOK。これについては、以下のサイトが参考になります。

tnamao.hatenablog.com

また、"--standalone" オプションを指定。これにより、Certbot クライアントに内蔵されている簡易的なウェブサーバが機能が一時的に使われるため、自分サイトの nginx は一旦停止しておく必要があります。

ともあれ、実行したコマンドのログを貼り付けておきます。

### 証明書の取得 ###

$ sudo certbot certonly --standalone -d my-domain.jp -d www.my-domain.jp -d app.my-domain.jp

### メールアドレスの指定(初回のみらしい) ###

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):mysccount@my-domain.jp

### なんか同意する ###

-------------------------------------------------------------------------------
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 EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: N

### 証明書が発行される!! ###

Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for my-domain.jp
tls-sni-01 challenge for www.my-domain.jp
tls-sni-01 challenge for app.my-domain.jp
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/my-domain.jp/fullchain.pem. Your cert
   will expire on 2017-11-11. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - 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/letsencript/live/[domein name]/" の下に証明書ファイルが生成されているはず。 ちなみに、証明書はいくつかのファイルがあり、それぞれシンボリックリンクされている。

# cd /etc/letsencrypt/live/my-domain.jp

# ls -l
lrwxrwxrwx 1 root root   44 Aug 13 12:57 cert.pem -> ../../archive/my-domain.jp/cert1.pem
lrwxrwxrwx 1 root root   45 Aug 13 12:57 chain.pem -> ../../archive/my-domain.jp/chain1.pem
lrwxrwxrwx 1 root root   49 Aug 13 12:57 fullchain.pem -> ../../archive/my-domain.jp/fullchain1.pem
lrwxrwxrwx 1 root root   47 Aug 13 12:57 privkey.pem -> ../../archive/my-domain.jp/privkey1.pem
-rw-r--r-- 1 root root  543 Aug 13 12:57 README

nginx 設定

証明書を入手できたので、これを nginx に仕込みます。
具体的には、次の2つを設定すれば OK です。

  • listen のポートを 443 にする
  • "ssl_certificate" と ”ssl_certificate_key" に証明書ファイルを指定する

ということで、以下のような感じになりました。

server {
    listen  443 ssl;
    server_name  my-domain.jp www.my-domain.jp;
    ssl_certificate         /etc/letsencrypt/live/my-domain.jp/cert.pem;
    ssl_certificate_key     /etc/letsencrypt/live/my-domain.jp/privkey.pem;

    access_log  /var/log/nginx/default.ssl.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    error_page  404              /404.html;
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

以上です。さらに、80番ポートでアクセスされた場合は、443ポートにリダイレクトするような設定を追加するとバッチリかと思います。

今後の運用

Let's Encript 証明書の有効期限は 90日間なので、今後は、90日ごとに更新手続きを行う必要があります。こちらについても、"Certbot" を使って簡単に実行できますので、そのころまたレポートを追加したいと思います。

2017年10月29日 追記: 証明書を更新しました

この記事を書いた時から3ヶ月くらい経ったので、Let's encript 証明書を更新しました。更新手順はざっくり以下の通りです。

  1. Nginx などwebサーバを止める
  2. Let's encript 証明書を更新
  3. Nginx などwebサーバを再起動

ここで、"2. Let's encript 証明書を更新" は次のコマンドを投入するだけでOKです。

$ sudo certbot renew

### コマンドを投入するといろいろ処理メッセージが出ます
Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/my-domain.jp.conf
-------------------------------------------------------------------------------
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
tls-sni-01 challenge for my-domain.jp
tls-sni-01 challenge for www.my-domain.jp
tls-sni-01 challenge for app.my-domain.jp
Waiting for verification...
Cleaning up challenges

-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/my-domain.jp/fullchain.pem
-------------------------------------------------------------------------------

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/my-domain.jp/fullchain.pem (success)

以上で完了です。とてもシンプルです。
次回からは、自動的に更新処理が実行されるよう cron に登録するといいですね。

*1:ノーマルな nginx サーバであれば、本家 Certbot のサイトに書いてあるように、"sudo certbot --nginx" もしくは "sudo certbot --nginx certonly" とやれば、自サイトの nginx 設定を見ながらいい感じに証明書を発行してくれるようです。