【ポート開放なし】MyDNS.JPのワイルドカード証明書を簡単に取得する【Docker】

誰でも無料でSSL証明書が取得できるLet's Encryptですが、80番ポートが使える環境でない場合はDNS-01チャレンジでドメインの所有者であることを確認する方法が使えます。
前に[WindowsリモートデスクトップをLet's EncryptでSSL証明書を発行して使う](https://qiita.com/SogoK/items/518f8c5b2200befab1da)の記事を書きましたが、この時は[acme.sh](https://github.com/acmesh-official/acme.sh)を使ってDNS-01チャレンジをクリアしました。が、最近なぜかうまくいかなくなってしまったので、[MyDNS.JP本家のスクリプト](https://github.com/disco-v8/DirectEdit/)をお借りし、CertbotでDNS-01チャレンジをクリアしたいと思います。

## 前提

- x86_64
- Linux
- Dockerがインストール済み

[MyDNS.JP本家のスクリプト](https://github.com/disco-v8/DirectEdit/)はPHPが必要ですが、なるべく環境を汚したくないのでDockerでいきます。
Certbotの公式イメージを使いますが、`arm64`には対応していなかったので注意。

### 筆者の検証環境

- Ubuntu 20.04 (WSL2)
- Docker 20.10.5

### ソースコード

[Certbot-Docker-MyDNSJP](https://github.com/norocchi/Certbot-Docker-MyDNSJP)

## 手順
手順1, 2をすっ飛ばしたい方は上記ソースコードを使ってください。

1. [MyDNS.JP本家のスクリプト](https://github.com/disco-v8/DirectEdit/)のダウンロード && 編集
1. スクリプトの作成
1. 証明書ゲット！

## 1. MyDNS.JP本家のスクリプトのダウンロード && 編集
本家の通りです。

```sh
cd /your/domain/directory/
wget 'https://github.com/disco-v8/DirectEdit/archive/master.zip' -O DirectEdit-master.zip
unzip ./DirectEdit-master.zip
```

お好みのエディタで `./DirectEdit-master/txtedit.conf` を編集します。
`$MYDNSJP_MASTERID`、`$MYDNSJP_MASTERPWD`、`$MYDNSJP_DOMAIN`の値を書き換えてください。

```php:txtedit.conf
<?php
// ------------------------------------------------------------
//
// txtedit.conf
//
// ------------------------------------------------------------
?>
<?php
    $MYDNSJP_URL       = 'https://www.mydns.jp/directedit.html';
    $MYDNSJP_MASTERID  = 'your-masterid';
    $MYDNSJP_MASTERPWD = 'your-password';
    $MYDNSJP_DOMAIN = 'your-domain';
?>
```

## 2. スクリプトの作成
`Dockerfile`を下記の内容で作成します。

```Dockerfile:Dockerfile
FROM certbot/certbot

RUN apk update \
 && apk add php7 php7-fpm php7-opcache php7-openssl php7-mbstring

COPY ./DirectEdit-master/* /var/DirectEdit-master/
RUN chmod 700 /var/DirectEdit-master/*.php \
 && chmod 600 /var/DirectEdit-master/*.conf
```

次に、`issue_cert.sh`を作成します。
`your-domain`、`*.your-domain`、`your-mail-address`の部分を書き換えます。

```sh:issue_cert.sh
#!/bin/bash

docker image build . -t certbot

docker run -it --rm --name certbot \
       -v "/etc/letsencrypt:/etc/letsencrypt" \
       -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
       certbot certonly --manual \
       --preferred-challenges=dns \
       --manual-auth-hook /var/DirectEdit-master/txtregist.php \
       --manual-cleanup-hook /var/DirectEdit-master/txtdelete.php \
       -d your-domain -d *.your-domain \
       --server https://acme-v02.api.letsencrypt.org/directory \
       --agree-tos -m your-mail-address \
       --manual-public-ip-logging-ok
```

## 3. 証明書ゲット！
先ほど作成したスクリプトに実行権限を与えて実行します。

```sh
chmod u+x issue_cert.sh
./issue_cert.sh
```

`Congratulations!`と出ていれば成功です！
`Your certificate and chain have been saved at:`、`Your key file has been saved at:`に表示されているホスト側のディレクトリを見ると証明書とキーがそれぞれ入っているはずです。

最後に、更新用のスクリプトをcronに登録しておきましょう。1週間に一度実施すればよいと思います。

```sh:renew_cert.sh
#!/bin/bash

docker run -it --rm --name certbot \
       -v "/etc/letsencrypt:/etc/letsencrypt" \
       -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
       certbot renew
```

```sh
chmod u+x renew_cert.sh
```


## 参考文献

[disco-v8 / DirectEdit](https://github.com/disco-v8/DirectEdit/)
[Certbot - Get Certbot - Running with Docker](https://certbot.eff.org/docs/install.html#running-with-docker)