修正点
6/28 再度試したところ、letsencryptで証明書を取得するところの選択肢1,2が逆転していました・・・十分注意して確認の上操作していただければと思います。
3/14 letsencryptの証明書を取得するときの引数が一つ抜けていたので修正。大変失礼致しました。
はじめに
前回の続きでnginxコンテナをhttps化対応させます。
証明書はみんな大好きLet's encryptを利用します。
構成
構成の検討
- はじめはローカルにクライアントソフトを入れて、とか考えてたんですが、DockerイメージでLet's encryptの証明書を取得できる物があるようなので、それを利用する事を考えます。
- let's encryptで証明書を取得する時、そのホストが該当するDNS名でアクセスできる必要があります。
- アクセスするポートは80番か、443番でいいようなので、80番をlet's encrypt用、443をnginx用となるように構成を変更します。
構成イメージ
設計
フォルダ構造
項目 | 値 | 備考 |
---|---|---|
コンフィグの置き場所 | $(pwd)/nginx/etc/nginx/ | 以下にconf.dをフォルダを用意しておき、マウントさせます。 |
証明書の置き場所 | /etc/letsencrypt | このディレクトリ以下に取得した証明書を配置します。 |
コンテンツの置き場所 | $(pwd)/www | コンテンツはカレントディレクトリ直下のwwwディレクトリに配置します。 |
nginx
- あまり難しい設定は実施せず、最低限のもののみ投入します。
項目 | 値 | 備考 |
---|---|---|
listen | 443 ssl default_server | 80番はlistenせず、443のみ待ち受けるものとします。 |
ssl_certificate | /etc/letsencrypt/live/ドメイン名/fullchain.pem | 証明書のパスを指定します |
ssl_certificate_key | /etc/letsencrypt/live/ドメイン名/privkey.pem | 証明書のパスを指定します。 |
server_name | ドメイン名 | 指定したドメイン名で待ち受けるようにします。 |
root | /usr/share/nginx/html | コンテナ内のドキュメントルートを/usr/share/nginx/htmlとします。 |
index | index.html | インデックスファイルはindex.htmlのみとします。 |
Docker
- 同様に最低限のものとします。(前回書いた共通の項目はここには記載しません)
項目 | 値 | 備考 |
---|---|---|
-v | $(pwd)/nginx/etc/nginx/conf.d:/etc/nginx/conf.d:ro | conf.dディレクトリをマウントします。 |
-v | $(pwd)/www:/usr/share/nginx/html:ro | カレントディレクトリ直下にあるwwwディレクトリを/usr/share/nginx/htmlにマウントします。 |
-v | /etc/letsencrypt:/etc/letsencrypt:ro | let's encryptで取得した証明書ディレクトリをコンテナ側にマウントします。 |
設定
let's encrypt証明書の取得
- 一旦nginxコンテナを止めた上で、該当するDNS名が設定されているホスト上で下記を実行します。
$ docker run -it --rm -p 80:80 --name letsencrypt ¥
-v "/etc/letsencrypt:/etc/letsencrypt" ¥
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" ¥
quay.io/letsencrypt/letsencrypt:latest certonly --preferred-challenges http-01
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Failed to find apache2ctl in PATH: /opt/certbot/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
How would you like to authenticate with the ACME CA?
-------------------------------------------------------------------------------
1: Place files in webroot directory (webroot)
2: Spin up a temporary webserver (standalone)
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
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 対象のドメイン名
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/対象のドメイン名/fullchain.pem. Your
cert will expire on 2017-06-08. 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"
- 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/letsencrypt配下に証明書が生成されてますね!
-
ちなみに更新するときは、下記でいけるようです。(実際には期限が来ていないのでまだ更新はできていません。)
$ docker run -it --rm -p 80:80 --name letsencrypt ¥
-v "/etc/letsencrypt:/etc/letsencrypt" ¥
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" ¥
quay.io/letsencrypt/letsencrypt:latest renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/対象のドメイン名.conf
-------------------------------------------------------------------------------
Cert not yet due for renewal
The following certs are not due for renewal yet:
/etc/letsencrypt/live/対象のドメイン名/fullchain.pem (skipped)
No renewals were attempted.
- 自動更新のcronを仕込んでも良いのですが、初回は手動でやりたいので、一旦は仕込みません。
nginxの設定
- /etc/nginx/conf.d/default.confは下記のような設定とします。
server {
listen 443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;
server_name ドメイン名;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
コンテナの起動
- --logXXX系のオプションは前回のfluentdの名残なので、不要であれば消して貰えればと思います。
$ docker run --name nginx -v /etc/localtime:/etc/localtime:ro ¥
-p 443:443 -v $(pwd)/nginx/etc/nginx/conf.d:/etc/nginx/conf.d:ro ¥
-v $(pwd)/www:/usr/share/nginx/html:ro ¥
-v /etc/letsencrypt:/etc/letsencrypt:ro ¥
--log-driver=fluentd --log-opt=fluentd-address=XX.XX.XX.YY:24224 ¥
--log-opt=tag=docker.{{.FullID}} -d nginx
最後に
- 簡単に証明書の取得ができるletsencryptは素晴らしいですね。
- 今回はDockerホストが1つだったため考慮してませんが、実際には証明書をnfs等に配置しておいて、ホストがコケたときは別のホスト上でnginxを再起動することなどを考慮したほうが良いかと思います。