nginxでサーバを運用していますが、今更ながらにHTTPS(SSL)対応しました。
そもそも今までSSL化していなかった理由は、
という思いからでした。
昔、自宅サーバを運用していたときには、勉強を兼ねてオレオレ証明書でHTTPSを使っていました。 その頃は、勉強用の自宅サーバという側面から、自分以外の利用者を想定する必要がなかったのでそれで問題ありませんでしたが、一般公開用のブログとしては不適当だと考えていました。
また、証明書にはお金がかかると思っていたので、収益化できていないブログに対してこれ以上費用をかけてもな…という考えでした。(ドメインにもサーバにも費用がかかってますので)
それでも一応、どれくらいの費用がかかるのだろうと調べてみたところ、Let's Encryptなら0円で証明書が発行できるということを知りました。 費用がかからないのなら、後回しにする理由はない!ということで、HTTPS対応に挑戦してみました。
Let's Encryptとは
無料でHTTPSが使えるとはいっても、怪しい団体の証明書だったらオレオレ証明書と変わらない、いやもっと危ない、と思いLet's Encryptについて調べてみました。
公式サイトによると運営団体は、Internet Security Research Group(ISRG)ということですが、その賛同団体・スポンサーの一覧を見ると、私の耳馴染みのあるものだけでも、mozilla, CISCO, chrome, facebook, GitHub, verizon... と錚々たる企業・ブランドが並んでいますね。
これらの企業の支援のもとで、すべてのサイトをHTTPS化するのを目的として、活動しているようです。
その目的に見合うように、費用がかからないだけでなく手順も非常に簡単になっていました。
それでは実際にHTTPS化してみます
以下のQiita記事がとてもわかり易かったです。 Let's Encrypt で Nginx にSSLを設定する - Qiita
しかしいくつか躓いたところがありましたので、そのあたりを補足しながら手順を書いていきます。
なお、動作環境は次のとおりです。
- OS: CentOS 7.6.1810
- webサーバ: nginx 1.14.2
また、証明書を取得したいドメインで、80番ポートでアクセスできる環境が必要になります。
certbotのインストール
Let's Encryptのクライアントcertbot
をインストールします。
yumあたりでするのかと思ったら、gitで持ってくるようです。
先程のQiita記事に従ってインストールしました。
[user@server ~]$ cd /usr/local/ [user@server local]$ ls bin etc games include lib lib64 libexec sbin share src [user@server local]$ git clone https://github.com/certbot/certbot -bash: git: command not found
ええ、gitが入っていませんでした…。 yumでgitをインストールします。
[user@server local]$ sudo yum install git Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile 中 略 Installed: git.x86_64 0:1.8.3.1-20.el7 Dependency Installed: perl-Error.noarch 1:0.17020-2.el7 perl-Git.noarch 0:1.8.3.1-20.el7 perl-TermReadKey.x86_64 0:2.30-20.el7 Complete!
改めて、git clone します。
[user@server local]$ sudo git clone https://github.com/certbot/certbot Cloning into 'certbot'... remote: Enumerating objects: 29, done. remote: Counting objects: 100% (29/29), done. remote: Compressing objects: 100% (27/27), done. remote: Total 61386 (delta 8), reused 5 (delta 2), pack-reused 61357 Receiving objects: 100% (61386/61386), 20.07 MiB | 8.37 MiB/s, done. Resolving deltas: 100% (44598/44598), done.
これだけでインストールが完了です。 とても手軽!
証明書の取得
ここからは、ドメイン名が出てきます。
example.com
として記載しますので、実際に行う際には適宜置き換えてください。
証明書の取得位は次のコマンドで行います。 ただし、このコマンドを実行する前にWebサーバを停止させる必要があります。私はサーバを停止させずに実行したので、以下の例は失敗例となります。(コマンド自体は同じです)
[user@server local]$ /usr/local/certbot/certbot-auto certonly --standalone -t
このコマンドを実行すると、内部でyumが動作し大量のパッケージがインストールされます。
提供元を使用していないと怖くてしょうがないレベルですね。
yumの定番 Is this ok [y/d/N]: y
で問われますので y と入力しインストールを許可しましょう。
次に、メールアドレスを聞いてきます。
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): user@example.com
その次は利用規約に同意するか問われます。 当然、同意しないと先には進めないのでAgreeのAを入力します。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must agree in order to register with the ACME server at https://acme-v02.api.letsencrypt.org/directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (A)gree/(C)ancel: A
この次が、Qiita記事と違いました。 次のような確認メッセージが出ます。 ざっくり意訳すると、登録したメールアドレス宛にメールマガジンを送るか?といった感じでしょうか。 試しにNoにしてみましたが、証明書取得には問題ありませんでした。 もちろんメールマガジンに興味ある方はYesを選択して良いと思います。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: N
この次は、Qiita記事に合流する感じで、ドメインの入力を求められました。
Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): example.com
ここで、上述したWebサーバを止めていなかったため失敗になりました。
Obtaining a new certificate Performing the following challenges: http-01 challenge for example.com Cleaning up challenges Problem binding to port 80: Could not bind to IPv4 or IPv6. IMPORTANT NOTES: - 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.
赤字部分ですね。 実際のログでは色が変わっていなかったので、最初気づきませんでした。 IMPORTANT NOTESがQiita記事より少ないなぁとは思いましたが、メールマガジン云々同様記事が書かれてからの変化かと流して次のnginx設定に進んでしまい、あとで戻ることになりました。
どうやら、certbotが80番ポートで、認証局側からのアクセスを待ち受けて証明書を作るような動きをしているようです。 そのため、Webサーバなどが80番ポートを使っていると、このエラーが出るようです。
これを解決するため、Webサーバを停止させます。
[user@server local]$ sudo /bin/systemctl stop nginx
改めて証明書作成をします。
コマンドは先程と同じです。先程聞かれたメールアドレスや規約同意の確認などは不要でした。 聞かれるのはドメイン名のみ。
[user@server local]$ /usr/local/certbot/certbot-auto certonly --standalone -t Requesting to rerun ./certbot-auto with root privileges... Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator standalone, Installer None Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): example.com Obtaining a new certificate Performing the following challenges: http-01 challenge for example.com Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/example.com/privkey.pem Your cert will expire on 2019-03-14. 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
これで証明書が取得できました。
Webサーバで使用する証明書の格納場所は、上のメッセージに記載されている以下の2つです。 /etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem
nginxの設定
取得した証明書をnginxが使えるように設定ファイルを書き換えます。 赤字が削除ヶ所、青字が追記箇所です。
Qiita記事での、HTTPSを有効にするために書かれている項目と、更新自動化のために書かれている項目、SSL安全性テストA+が取れるようにした項目を合わせ込んであります。
/etc/nginx/conf.d/default.conf
server { listen 80; listen 443 ssl; server_name localhost example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDH !aNULL !eNULL !SSLv2 !SSLv3'; add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; root /usr/share/nginx/wordpress; index index.php charset utf-8; location / { try_files $uri $uri/ @wordpress; } location ~ \.php$ { try_files $uri @wordpress; fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/wordpress$fastcgi_script_name; include fastcgi_params; } location @wordpress { fastcgi_index index.php; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/wordpress/index.php; include fastcgi_params; } access_log /var/log/nginx/wordpress.access.log main; error_page 404 /error/404.html; error_page 500 502 503 504 /error/50x.html; } server { listen 80; location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /path/to/doc/root/; } location / { # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response. return 301 https://$host$request_uri; } }
このnginx設定でいくつか注意事項があります。
- HTTPに来たアクセスを(certbotの更新を除き)すべてHTTPSにリダイレクトする設定となっています。
- 下部の方にある緑字の
/path/to/doc/root/
は、証明書の更新時に使われるディレクトリとなります。適当なディレクトリを作り、そこを指定すれば良いようです。私は/usr/share/nginx/certbot/
としました。 - 安全性A+にすることで、古いブラウザやプログラムからアクセスできなくなる可能性があります。 その場合は、以下の参考元サイトを参照し適宜修正してください。 Webサーバー nginx における SSL証明書設定の安全性向上 ~SSL Server Test で A+ 判定を目指して~ | SaintSouth.NET
設定ファイル更新が完了したらnginxを立ち上げます。
[user@server local]$ sudo /bin/systemctl start nginx
https://example.com でアクセスできること、http://example.com でアクセスするとhttps://example.com にリダイレクトされること、(環境ができていれば)httpのサブディレクトリやファイルへのアクセスもhttpsにリダイレクトされること、くらいを確認すると良いでしょう。
自動更新設定はまた次回
上記までで、HTTPS対応はひとまず完了です。 しかし、Let's Encryptで取得した証明書は期限が90日なので、油断するとあっという間に期限切れになってしまいます。 自動更新設定をしておくことで、この問題が発生しないようにしておくのがよいでしょう。
Qiita記事に書いてあった更新手順を試してみてはいますが、証明書が新しすぎるため更新がスキップされ成否の判断がまだできていません。
こちらはまた時間が経ったときに試して、まとめてみたいと思います。
自動更新について掲載しました
https://yuuchika.com/lets_encrypt_nginx_renewal/
おまけ - WordPressの設定
HTTPSに切り替えたことで、WordPressに不具合が出ていないかすこし試してみました。 軽く動作を見たところ、特に問題はなさそうです。
一応、設定->一般 から 「WordPressアドレス(URL)」と「サイトアドレス(URL)」をhttpsに変更しましたが、変更前(かつHTTP→HTTPSのリダイレクト設定前)でも問題はありませんでした。