はじめに
Dockerのコンテナにて、リバースプロキシを構築しましたが、次に
Let’s Encryptを利用し、外部・リバースプロキシ間をSSL化します。
Let’s Encryptにて証明書の発行、更新できるように構築にはいくつかの方式があります。そのうち一番シンプルなのがStandalone方式と呼ばれる一時的に停止が発生してしまう方式です。これはCertbotが一時的に独自のWebサーバを立ち上げてACMEチャレンジを行う方法で、80、443ポートを使用してポート競合を起こすため停止が必要となります。
無停止で更新するチャレンジ方法は、HTTP-01、DNS-01チャレンジなどいくつかありますが、今回は一般的なHTTP-01チャレンジ(Webroot方式)を行います。
CertbotがACMEチャレンジ用のファイルをWebrootディレクトリに配置後、CertbotからのリクエストによりLet’s Encryptサーバがhttp://<YOUR_DOMAIN>/.well-known/acme-challenge/<TOKEN>
を取得します。
この検証により、正当なレスポンスがあれば証明書の発行されます。
https://letsencrypt.org/ja/docs/challenge-types/
本記事の注意事項
エディタの都合上、以下文字列に続くパスを全角スラッシュにしてあります。
コピーして使用される際は半角スラッシュに変更してご使用ください。
/etc
Certbotを使ってHTTP-01 チャレンジする
今回は、初回証明書発行のところまで記します。
構成は以下の画像の通りです。
簡略化していますが、docker-composeでreverse-proxy.ymlとwebapp01.ymlを作成し、それぞれコンテナを稼働させます。外部からの80/443リクエストはreverse-proxyで受け特定ドメインのリクエストのときにwebapp01のwebサービスに転送します。
SSLの範囲は、外部とreverse-proxy間のみです。
ボリュームにおいては、ACMEチャレンジディレクトリや証明書及びシンボリックリンク元ディレクトリをバインドマウントしています。
それでは、認証までの方法を順に記します。
Certbotのインストール
CertbotとはSSL証明書を取得するための機能をもつソフトで、
Let’sEncryptにも対応をしています。
今回は、Certbotを使用しますので、まずはCertbotのパッケージをインストールを行います。
sudo apt install certbot
今回は、Webrootを使用した証明書の取得・更新を行うためWebソフト(Apache、Nginx等)の追加プラグインは不要です。
例:sudo apt install python3-certbot-nginx
認証のためにdocker-compose.ymlへ記述
まず、ACMEチャレンジを行うためのディレクトリを作成します。
今回は/home/dockerをプロジェクトフォルダとして、
それぞれcomposeごとにディレクトリを作成します。
SSL化するのは、リバースプロキシサーバのためリバースプロキシを構成している
コンテナに記述していきます。
・/home/docker/reverse-proxy/docker-compose.yml
services: reverse-proxy: image: nginx:alpine ports: - "80:80" volumes: - ./conf.d:/etc/nginx/conf.d - ./certbot/www:/var/www/certbot - ./certbot/conf:/etc/letsencrypt - ./certbot/conf/archive:/etc/letsencrypt/archive
ネットワークや一部設定は省いていますが、上記の通りです。
volumesについては、バインドマウントしており、それぞれ
・ホストの/home/docker/reverse-proxy/conf.dをコンテナ内の/etc/nginx/conf.dに配置=>nginxの設定ファイルを読み込んでいます。
・ホストの/home/docker/reverse-proxy/certbot/wwwをコンテナ内で/var/www/certbotに配置=>ACMEディレクトリを配置します。
・ホストの/home/docker/reverse-proxy/certbot/confをコンテナ内の/etc/letsencryptに配置=>証明書のシンボリックリンクを配置しています。
・ホストの/certbot/conf/archiveをコンテナ内で/etc/letsencrypt/archiveに配置=>証明書が保管されます。
ACMEチャレンジ用のディレクトリを作成
次に、ACMEチャレンジ用のディレクトリを作成します。
/home/docker/reverse-proxy/certbot/www
に.well-known/acme-challenge/
を作成します。
confファイルへパスの記述をする
既にある、もしくは新規作成するreverse-proxy(任意).confを/home/docker/reverse-proxy/conf.d
に配置し以下を追記します。これによりexample/.well-known/acme-challengeのリクエストは、/var/www/certbot
に関連付けることができます。
server { listen 80; server_name example(domain); location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { 省略.... } }
–dry-runオプションを使用して検証
証明書を発行、更新を行うコマンドは、Let’sEncryptにリクエストを行いますが、一定時間リクエストリミットがあります。
そのため、検証段階では、dry-runオプションを付与すると、証明書の発行や更新のシミュレーションを行うことができます。(リミットなし)
sudo certbot certonly --webroot -w /home/docker/reverse-proxy/certbot/www -d example(domain) --dry-run
証明書を発行する
以下は、Webroot方式で、証明書の発行のみ行うコマンドです。対象ドメインをexampleとしています。
Webrootディレクトリ指定は、/home/docker/reverse-proxy/certbot/www/
です。
このときは、ホストのパスを指定します。ここで誤ると404エラーで取得できません。
検証で問題なければ、dry-runを外して証明書を発行します。
sudo certbot certonly --webroot -w /home/docker/reverse-proxy/certbot/www/ -d example(domain)
エラーが発報されず、指定した場所に証明書が発行されていれば成功です。
おわりに
私は、本工程を完了するのに時間がかかりました。
証明書発行のコマンドを実行すると404でエラーが発報され、原因の切り分けをしたわけですが、/.well-known/acme-challenge/
にテストファイルを(.html)を入れると問題なく表示されたのにエラーは継続し、あまりcertbotの挙動を把握していなかったこともあり、autoindex on;
やdefault_type text/plain;
、権限周りを重点的に探っていました。
結論、certbotのコマンドでコンテナ側のディレクトリを指定していたことが原因でした。
certbotはホストで実行するので、ホストのディレクトリを指定するんですね。
参考文献
関連記事
https://it.hasethblog.com/archives/286
コメント