Let's EncryptでサイトをSSL対応にし証明書を自動更新する

  • 22 Feb 2017

このブログをSSLに対応させようと思い、Let's Encryptを試してみました。自動更新まで設定するのも含めちょっと手間取りましたが無事にできたのでご紹介します。

環境

  • Ubuntu 14.04
  • nginx 1.4.6

概要

サイトSSL化と証明書の自動更新設定までを行います。手順は以下の通りです。

  1. cerbotをインストール
  2. SSLのポートを開ける
  3. 証明書の作成・発行
  4. nginxの設定変更
  5. cronへの登録

certbotのインストール

というかダウンロードするだけです。gitからもcloneできますが実行ファイルだけDLするほうが良いそうです(参考:Get Certbot — Certbot 0.12.0.dev0 documentation)。

$ cd ~
$ wget https://dl.eff.org/certbot-auto
$ sudo cp certbot-auto /usr/bin/certbot-auto
$ sudo chmod 700 /usr/bin/certbot-auto
$ sudo chown root:root /usr/bin/certbot-auto

どうしてもgit cloneでやりたい方は以下を(非推奨)。

$ cd ~
$ sudo apt-get install git
$ git clone https://github.com/certbot/certbot
$ sudo cp ./certbot/certbot-auto /usr/bin/certbot-auto
$ sudo chmod 700 /usr/bin/certbot-auto
$ sudo chown root:root /usr/bin/certbot-auto

SSLのポートを開ける

certbotのインストールが終わったら次はSSLのポートを開けます。証明書を発行するときに、Let’sEncrypt側で443ポートの確認しにくるのでこのタイミングで開けておきます。

$ sudo ufw allow 443/tcp
$ sudo ufw status
To                         Action      From
--                         ------      ----
443/tcp                    ALLOW       Anywhere
443/tcp (v6)               ALLOW       Anywhere (v6)

これでcertbot-autoを実行する準備ができました。

certbot-autoを実行

続いて今インストールしたcertbot-autoを実行します。今回はstandaloneモードといって一時的に443ポートのサーバーをcertbotに立ち上げさせて認証する方法でいきます。なお、certbot-auto -hすればその他にどういうモードがあるのか確認できます。

$ sudo certbot-auto -h
  (略)
  --apache          Use the Apache plugin for authentication & installation
  --standalone      Run a standalone webserver for authentication
  --nginx           Use the Nginx plugin for authentication & installation
  --webroot         Place files in a server's webroot folder for authentication
  --manual          Obtain certs interactively, or using shell script hooks
  (略)

では実行します。当然ながら、すでに443ポートを利用しているプロセスがいるとこけるので、もし443ポート使っているプロセスがいて、それを切ることができないのであれば、standaloneモード以外をご利用ください。

$ sudo certbot-auto certonly --standalone

実行するとpythonのモジュールが大量にインストールされると思います。しばらく待ちましょう。余談ですが、certbotはpython2.7に対応しています。それ以外のバージョンのpythonをお使いであればpython2.7をインストールする必要があります。

さて、しばらく待つと以下のようなレスポンスが返ってきます。適宜、回答を入力してください。

Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):[ご自身のメールアドレスを入力してください]

-------------------------------------------------------------------------------
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 # 心が狭くて恐縮です

Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel):[ご自身のサイトのドメインをサブドメイン含めて]

これでうまくいけば以下のようなレスポンスが返ってきます。

Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for wwld.jp
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/wwld.jp/fullchain.pem. Your cert will expire
   on 2017-05-29. 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

どうやら証明書が発行されているようです。念のため確認しましょう。

$ sudo ls -al /etc/letsencrypt/live/[domain]/
total 12
drwxr-xr-x 2 root root 4096 Feb 28 19:07 .
drwx------ 3 root root 4096 Feb 28 19:07 ..
lrwxrwxrwx 1 root root   31 Feb 28 19:07 cert.pem -> ../../archive/[domain]/cert1.pem
lrwxrwxrwx 1 root root   32 Feb 28 19:07 chain.pem -> ../../archive/[domain]/chain1.pem
lrwxrwxrwx 1 root root   36 Feb 28 19:07 fullchain.pem -> ../../archive/[domain]/fullchain1.pem
lrwxrwxrwx 1 root root   34 Feb 28 19:07 privkey.pem -> ../../archive/[domain]/privkey1.pem
-rw-r--r-- 1 root root  543 Feb 28 19:07 README

無事にできてますね。

ちなみに、もし以下のようなエラーが返ってきたらLet’s Encryptが443ポートにアクセスできていない可能性があります。もう一度ファイアーウォール周りを確認してみてください。

Failed authorization procedure. wwld.jp (tls-sni-01): urn:acme:error:connection :: 
The server could not connect to the client to verify the domain :: Failed to connect to xxx.xxx.xxx.xxx:443 for TLS-SNI-01 challenge

nginxを設定

次にnginxを設定します。

$ sudo vim /etc/nginx/sites-available/wwld.jp

まずは既存のブロックには手を付けずにSSL部分だけ記述します。

# 既存のhttpの記述(まだ触れない)
server {
        listen       80;
        server_name  wwld.jp;
        ...
}

# 新規に追加したhttpsの記述
server {
        listen                443;
        server_name           wwld.jp;
        ssl                   on;
        ssl_certificate       /etc/letsencrypt/live/wwld.jp/fullchain.pem;
        ssl_certificate_key   /etc/letsencrypt/live/wwld.jp/privkey.pem;
        root                  /type/your/site/dir;
        access_log            /type/your/log/path.log;
        index                 index.html;

        location / {
                try_files $uri $uri/ =404;
        }
}

ssl_certificateのところはcert.pemを読ませるという話も散見されますが、それだとandroidで安全ではない警告・エラーがでてしまいます。 証明書+中間CA証明書であるfullchain.pemを読ませる方が無難です。

reloadします。

$ sudo service nginx configtest
$ sudo service nginx reload

実際にhttpsでアクセスして問題ないか確認します。 問題なければ、httpからのリダイレクトを設定します。

なおSSLの設定についてはキャッシュなど効かせることもできますが、ここでは混乱を防ぐためその手の設定内容は割愛しています。

server {
        listen       80;
        server_name  wwld.jp;
		# リダイレクトの設定を追加
        return  301 https://wwld.jp$request_uri;
}

server {
        listen                443;
        server_name           wwld.jp;
        ssl                   on;
        ssl_certificate       /etc/letsencrypt/live/wwld.jp/fullchain.pem;
        ssl_certificate_key   /etc/letsencrypt/live/wwld.jp/privkey.pem;
        root                  /type/your/site/dir;
        access_log            /type/your/log/path.log;
        index                 index.html;

        location / {
                try_files $uri $uri/ =404;
        }
}

reloadします。

$ sudo service nginx configtest
$ sudo service nginx reload

これでhttpでアクセスしてもhttpsにリダイレクトされるはずです。

自動更新設定を行う

最後に証明書の自動更新を設定します。Let’sEncryptは90日で期限がきれるので自動で更新する設定を入れておかないといけません。cronに更新設定をしておきましょう。

(追記) まず、現在のままだとstandloneモードで更新が行われてしまうので、その変更から行います。すでに443ポートは利用されてしまっているので、standaloneモード自体が動作できません。そこでこの設定をwebrootモードに変更します。

$ sudo crontab -e 
0 1 * * 0 certbot-auto renew --post-hook "service nginx reload" 1 > /dev/null 2 > /dev/null

日曜の1時に証明書の更新を試みるようにしておきます。certbotは証明書の期限が一か月を切らないとrenewを実行しないようになっています。ですので毎週コマンド自体は実行し、期限一か月切ったら本当にに更新が行われる、という寸法です。

以上です。

参考