NoctisNode
← ガイドセキュリティ2026-10-2310 分

Caddy の自動 HTTPS:Caddy の自動 TLS の仕組みとトラブル対処

Caddy は設定内のすべてのドメインについて、ACME で TLS 証明書を取得・更新します。HTTP-01、TLS-ALPN-01、DNS-01 によるワイルドカード、オンデマンド TLS、よくある失敗例を解説します。

結論:Caddy は、公開ドメイン名をサイトアドレスに指定すると自動的に HTTPS を有効にします。ACME(デフォルトは Let's Encrypt または ZeroSSL)で証明書を要求し、ポート 80 と 443 上の HTTP-01 または TLS-ALPN-01 チャレンジでドメインの管理権を証明し、HTTP を HTTPS にリダイレクトし、期限切れ前に証明書を更新します。追加の設定は一切不要です。

Caddy リバースプロキシとは、Caddy がその HTTPS 接続を終端し、`reverse_proxy` ディレクティブで別のポート、コンテナ、ホスト上のアプリへリクエストを転送するだけのものです。数行で TLS とプロキシを両立できるこの組み合わせこそ、Caddy が選ばれる最大の理由です。

3行で SSL 付きリバースプロキシ

DNS がサーバーを指し、ポート 80 と 443 に到達できる状態なら、この Caddyfile だけで2つのホスト名に対応した完全な HTTPS リバースプロキシになります。Caddy は起動時に両方の名前の証明書を取得し、HTTP/1.1、HTTP/2、HTTP/3 で配信し、`X-Forwarded-For`、`X-Forwarded-Proto`、`X-Forwarded-Host` をバックエンドに渡します。`email` オプションは任意ですが、指定しておくと期限切れや失効した証明書について CA から連絡を受けられます。

公式 apt リポジトリからのインストールと systemd の基本はCaddy リバースプロキシガイドで、コンテナについてはDocker リバースプロキシとしての Caddyで解説しています。変更は `sudo systemctl reload caddy` で反映します。

# /etc/caddy/Caddyfile
{
	email [email protected]
}

example.com, www.example.com {
	reverse_proxy 127.0.0.1:8080
}

Caddy の自動 TLS の内部動作

Caddy は設定を読み込むと、サイトアドレスからすべてのホスト名を集め、それぞれの証明書を誰が発行すべきかを判断します。公開ドメインは公開 ACME 発行者へ、`localhost`、IP アドレス、内部専用の名前は Caddy 自身のローカル CA から証明書を受け取ります(`tls internal` と書くのと同じです)。証明書、鍵、ACME アカウントは Caddy のデータディレクトリに保存されます。apt パッケージでは `/var/lib/caddy/.local/share/caddy`、公式 Docker イメージでは `/data` です。

更新は期限切れのかなり前にバックグラウンドで行われ、CA が対応していれば Caddy は OCSP レスポンスをステープリングします。発行に失敗すると、Caddy は指数バックオフで再試行し、本番のレート制限を消費しないよう再試行には CA のステージングエンドポイントを使います。同じストレージを共有する複数の Caddy インスタンスは連携し、特定の証明書を要求するのは1台だけになります。

チャレンジCA が確認する内容必要なものワイルドカード
HTTP-01`http://domain/.well-known/acme-challenge/` で配信されるトークンインターネットからポート 80 に到達できること不可
TLS-ALPN-01TLS ハンドシェイクで提示される特殊な証明書インターネットからポート 443 に到達できること不可
DNS-01`_acme-challenge.domain` の TXT レコードDNS プロバイダーの API トークンと、そのプロバイダーモジュールを含む Caddy ビルド可

DNS-01 によるワイルドカード証明書

`*.example.com` のようなワイルドカード証明書は、DNS-01 チャレンジでしか発行できません。標準の Caddy バイナリには DNS プロバイダーのプラグインが含まれていないため、xcaddy でビルドする(または公式ダウンロードページでプロバイダーを選ぶ)必要があり、そのゾーンの DNS 編集だけに権限を絞った API トークンを Caddy に渡します。DNS-01 は、内部専用サーバーなどポート 80 と 443 にインターネットから到達できない場合にも使えます。

トークンは Caddyfile に書かないでください。systemd ユニットが使う環境ファイルに置き(`sudo systemctl edit caddy` を実行し、`[Service]` の下に `EnvironmentFile=/etc/caddy/caddy.env`)、`chmod 600` でファイルのアクセスを制限します。

# Build Caddy with a DNS provider module (example: Cloudflare)
xcaddy build --with github.com/caddy-dns/cloudflare

# Caddyfile: one wildcard certificate for all subdomains
*.example.com {
	tls {
		dns cloudflare {env.CF_API_TOKEN}
	}

	@app host app.example.com
	handle @app {
		reverse_proxy 127.0.0.1:3000
	}

	handle {
		respond "Unknown host" 404
	}
}

オンデマンド TLS とステージング

オンデマンド TLS を使うと、Caddy は初めて見るホスト名について、最初の TLS ハンドシェイク中に証明書を取得します。顧客が自分のドメインをあなたのサーバーに向けるようなプラットフォーム向けの機能です。必ず `ask` エンドポイントを設定してください。Caddy は `?domain=name` を付けてそれを呼び出し、200 応答の場合にのみ処理を続けます。これがないと、誰でも適当な名前をあなたの IP に向けて、レート制限に到達させることができてしまいます。

試行錯誤している間は、グローバルオプション `acme_ca` で Let's Encrypt のステージング CA に切り替えましょう。ステージングの証明書はブラウザに信頼されませんが、制限がはるかに緩いので、自由に壊して直せます。作業が終わったらオプションを削除し、必要に応じてデータディレクトリからステージング証明書を削除してください。

{
	on_demand_tls {
		ask http://127.0.0.1:5555/allowed
	}
}

https:// {
	tls {
		on_demand
	}
	reverse_proxy 127.0.0.1:8080
}

# Global options block for testing
{
	email [email protected]
	# Test against Let's Encrypt staging; remove when everything works
	acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

Caddy の TLS でよくある失敗と対処法

  1. 01.DNS が向いていない:A または AAAA レコードがない、まだ古いサーバーを指している、あるいはキャッシュされている。CA は IPv6 があればそちらを優先するため、古い AAAA レコードは典型的な落とし穴です。`dig` で両方を確認しましょう。
  2. 02.ポート 80 または 443 が閉じている:ホストのファイアウォール、クラウドのファイアウォール、ルーターが受信トラフィックをブロックしているため、HTTP-01 も TLS-ALPN-01 も完了できません。80/tcp と 443/tcp(HTTP/3 用に 443/udp も)を開放します。
  3. 03.ポートが使用中:Apache、nginx、別のコンテナが 80 や 443 を使っているため、Caddy が待ち受けできません。他のサービスを停止するか、Caddy の背後に移します。
  4. 04.前段に CDN プロキシがある:オレンジ雲タイプのプロキシが Caddy より先に TLS を終端し、TLS-ALPN-01 が失敗することがあります。DNS-01 を使うか、発行中はレコードを DNS のみに設定します。
  5. 05.レート制限:失敗を繰り返したりデータディレクトリを消去したりすると、CA の制限に達します(Let's Encrypt は、ホスト名ごと1時間あたりの検証失敗回数と、1週間あたりの重複証明書数を制限しています)。根本原因を直し、ステージングを使い、データディレクトリを永続化してください。
  6. 06.CAA レコード:別の CA のみを許可する CAA レコードは発行をブロックします。`letsencrypt.org` と `sectigo.com`(ZeroSSL が使用)を許可するか、制限を削除します。
# Does the name resolve to this server (both IPv4 and IPv6)?
dig +short A example.com
dig +short AAAA example.com
curl -4 -s https://ifconfig.me ; echo

# Are ports 80 and 443 open in the host firewall?
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp

# Is something else already bound to 80/443?
sudo ss -ltnp '( sport = :80 or sport = :443 )'

# What does Caddy say?
sudo journalctl -u caddy --no-pager -n 100

バックエンドへの通信も HTTPS に

同じホスト上のバックエンドの多くは localhost で平文 HTTP を話しますが、それで問題ありません。上流が別のマシンにある場合や TLS を必須とする場合は、`https://` の上流を使い、検証する名前と信頼する CA を Caddy に指定します。`tls_insecure_skip_verify` は、プロキシとバックエンド間の盗聴に対する保護がなくなるため、簡単なテスト以外では避けてください。サーバー間の通信には、バックエンドの証明書を管理するより、プライベートなWireGuard トンネルの方がシンプルなことが多いです。

フル root 権限と専用 IPv4 アドレスを備えた NoctisNode のVPSでは、一般的な構成は次のとおりです。A レコードをサーバーに向け(サーバーに IPv6 がない限り AAAA は設定しない)、80 と 443 を開放し、残りは Caddy に任せます。HTTP 以外のトラフィックを転送する必要がある場合は、Caddy による TCP と SSH のプロキシを参照してください。

example.com {
	reverse_proxy https://10.0.0.5:8443 {
		transport http {
			tls_server_name backend.internal
			tls_trust_pool file /etc/caddy/backend-ca.pem
		}
	}
}

よくある質問

QCaddy リバースプロキシとは何ですか?

ACaddy Web サーバーがクライアントの接続を受け付け、通常は HTTPS を終端し、`reverse_proxy` ディレクティブで1つ以上のバックエンドサービスへリクエストを転送するものです。そのための TLS 証明書は Caddy が自動で取得・更新します。

QCaddy は証明書を自動で更新しますか?

Aはい。ドメインが引き続きサーバーを指し、チャレンジ用ポートに到達できる限り、Caddy は期限切れのかなり前にバックグラウンドで証明書を更新し、再起動なしで読み込み直します。

QCaddy が証明書を取得できないのはなぜですか?

A最も多い原因は、DNS レコードが別の場所を指している(古い AAAA レコードを含む)、ポート 80 と 443 がブロックされている、別のプログラムがそれらのポートを使っている、失敗の繰り返しでレート制限に達した、のいずれかです。`journalctl -u caddy` で正確な ACME エラーを確認できます。

QCaddy はワイルドカード証明書を発行できますか?

Aはい。ただし DNS-01 チャレンジ経由のみで、お使いの DNS プロバイダーのモジュールを含む Caddy ビルドと、そのゾーン用の API トークンが必要です。

QCaddy の自動 HTTPS を無効にするには?

A特定のサイトだけなら `http://` のサイトアドレスを使い、全体ならグローバルオプション `auto_https off` を設定します。`auto_https disable_redirects` を使えば、証明書は維持したまま HTTP から HTTPS へのリダイレクトだけを止めることもできます。

Caddy の自動 HTTPS:Caddy の自動 TLS の仕組みとトラブル対処 · NoctisNode