無料のSSL認証でサイトをHTTPS化する　macサーバ編


# 前置き
[光の速さのWEBサーバー(nginx)をlet's encryptでSSL化及びHTTP/2化。ついでにセキュリティ評価をA＋にする。](https://qiita.com/sak_2/items/ff835b669c0a7e110b09)
こちらの記事を参考に、自分のwebサイトをHTTPS化しました。
ただ、こちらは記事が古く情報の相違が出てきていることと、自分の場合Macサーバだったのでつまづいた点があったため、記事を書くことにしました。

### Let's Encrypt / certbot
SSL認証を受ける方法はいくつかありますが、無料で行うために、今回はこちらの[Let's Encrypt](https://letsencrypt.org)のサービスを利用します。

Let's Encryptは、インターネットをより安全でプライバシーが守られる場所にすることを目的として、httpsを広めようとする認証機関らしく[^1]、無料でssl認証する手段を提供してくれています。

・日本語ポータル：https://letsencrypt.jp 概要を把握するのに読みやすいです。
・コマンドの使い方（日本語）：https://letsencrypt.jp/command/#nginx あんまり役には立ってないがいつか役にたつかもしれないので載せておく。



認証はサーバ側で、コマンドラインよりLet's Encryptの提供する`certbot`コマンドを利用して行います。
certbot：　https://certbot.eff.org/
（letsencryptコマンドはこのコマンドの旧名です）



推薦される実行方法は`sudo certbot --nginx`らしいですが、自分はsudoすると芋ずる式にsudoしないと通らなくなる[^2]のが嫌なので、sudoなしでインストールしました。
certbotが必要とするのは以下の3つのディレクトリが書き込み可能であること

```
/etc/letsencrypt/
/var/log/letsencrypt/
/var/lib/letsencrypt/
```
（根拠：　https://certbot.eff.org/faq/）
なので、手動で作りました。

```terminal:
$ sudo mkdir /etc/letsencrypt/ /var/log/letsencrypt/ /var/lib/letsencrypt/
$ sudo chown $USER:admin /etc/letsencrypt/ /var/log/letsencrypt/ /var/lib/letsencrypt/
```

### 443ポート解放
自宅サーバなので、ポートを解放するところからやります。
1024番以下は受け取るときにroot権限が必要なので、これを避けます。ルータがわで443をLANで4433（これはなんでもいいです）に転送する設定をして、ルータを再起動で設定を反映します。
nginxには次のように書きます。

```nginx
# 前後略
server {
  listen 4433 ssl;

  server_name (your servername);
  
  # あとはlocationなどの設定。
}
```
参照程度：https://serverfault.com/questions/828130/how-to-run-nginx-ssl-on-non-standard-port


### 後は認証を発行するだけ
一番ハマったのがここ

```
$ certbot --nginx --nginx-server-root /usr/local/etx/nginx
```
certbotは/etc/nginxをnginxのパスだと思って処理をします。しかし、自分はMacサーバのため、brewを使ってnginxを入れており、そのためディレクトリが/usr/local以下になっていました。
最初、ディレクトリを/etc/nginxにコピーしてやればいいや、と思いやっていましたが、証明書は通るのに再起動するとhttpsが動かなくなる。どういうことかと七転八倒し4時間潰した結果、nginx再起動したら/usr/local/etc/nginxからnginx.confが読み込まれるという至極当然のことを世紀の発明のごとく思い至ったわけです。
nginxのパスを/etc/nginxに書き換えるのか、certbotのnginxパス認識を/usr/local/etc/nginxに改めるのか、天秤をかけてみると後者がどうも都合がいいため、以上のような結論になりました。

パス認識変更方法：https://github.com/certbot/certbot/issues/4839#issuecomment-308895712


# 更新を自動化
cronを使うらしい。
cronの書き方：http://www.express.nec.co.jp/linux/distributions/knowledge/system/crond.html
まずはcertbotのマニュアルに従って、renewのテストを行う。

```
certbot renew --dry-run
```
--dry-runを使うことで実際に更新するのではなく確認ができる。
成功したら、自動化するために`certbot renew`をcronに書き込む。

macでは（自分の環境では）`cron`, `crontab`がコマンドとして使えた。
cronが起動しているかどうかをまず確認する。

```terminal
$ sudo cron status
```
起動済みならそのまま、なければ起動する。
cronを操作するためのコマンドはcrontabを使うことで編集する。ログインユーザに対して編集を行うだけなら`$ crontab -e`で十分だろう。
書くべき内容は次の通り：

```
0 5 1 * * (user) certbot renew
```
毎月1日5時に更新チェックするという意味になる。
これでできているはずだが、できているかの確認がよくわからなかった。詳しい人は教えていただけると助かります。
ちなみにmacだからなのか、crondコマンドはなく、cronコマンドだった。`sudo cron status`でrunningと出たからできていると信じたい。


# おまけ
### おまけ1
http://hachibeechan.hateblo.jp/entry/2015/02/04/Nginxでのドメインやhttpsへのリダイレクトの設定はrewriteよ

httpのアクセスをhttpsにリダイレクトする


### おまけ2
リクエストごとに認証していたら計算コストがかかるので、頻度を抑えると良さげ
http://nginx.org/en/docs/http/configuring_https_servers.html


### おまけ3 サブドメインの追加
certbotは今の所（2018年1月現在）ワイルドカードをサポートしていないため、サブドメインは逐次追加する必要があります。（[参照](https://community.letsencrypt.org/t/how-can-i-add-more-subdomains-to-my-ssl-certificate/33711/2)）
その際、nginxでもワイルドカードではなくサブドメイン名をハードコードする必要があるようです。
以上より、必要なコマンドは次のようになります。

```terminal
$ certbot --expand -d existingdomain.com,newsub.existingdomain.com --nginx --nginx-server-root /usr/local/etc/nginx/
```


[^1]: Let's EncryptのAboutページ参照　https://letsencrypt.org/about/
[^2]: sudoによって作られたファイルはsudo権限でしか編集できなくなるので、サーバ再起動を自動化したいときに非常に面倒になる