Caddy 操作手册

7 分で読了
このページの目次

入口・match・path 変換・upstream の順に一つの request を調べる。Caddyfile の解析成功、読込成功、期待通りの応答をそれぞれ確認する。

やりたいこと参照先
proxy 404・path 不良route と prefix
設定の反映検証・再読込・実測
TLS・client 証明書証明書管理と mTLS

upstream が受け取る path は変わり得る

図を準備しています
prefix 除去後に upstream が見る path

handle は path を保持し handle_path は /api を除去する。/api 単体は /api/* に一致せず fallback へ進む。

完全な site 例:static file と /api/* を分ける。実 Caddyfile に統合し domain・root・上流を変更する。

example.com {
    handle_path /api/* {
        reverse_proxy 127.0.0.1:3000
    }
    handle {
        root * /srv/www
        file_server
    }
    log
}

例では /api/users が /users になる。アプリが prefix を期待するなら handle を使う。/api/* は /api 単体には一致しない。handle は排他的で fallback が残りを処理する。directory listing は明示的 browse が必要。

Caddy の環境から上流へ直接接続する

# Caddy ホストから書換後の上流 path を要求する
curl -v http://127.0.0.1:3000/users

コンテナ内の loopback は自身。同じ network namespace から実到達先を試し、状態・本文を確認する。

# 指定入口経由で外向け path と TLS を検証する
curl -v --resolve example.com:443:127.0.0.1 https://example.com/api/users

--resolve は名前・port・IP。同じ resource の二経路を比較し、/api/・裸 /api・static も確認する。

# request 時刻付近の Caddy 診断を読む
journalctl -u caddy -b -n 100 --no-pager

runtime log と access log を分ける。出力先が file の場合もある。502 の upstream error から protocol/network を調べる。

変換後の同じ資源を比較する。--resolve は URL の名前・SNI を保って入口 IP を指定する。Host header だけでは SNI は変わらない。-k で TLS 問題を隠さない。

現象確認
502upstream address・protocol・namespace・TLS を Caddy 側から確認
404応答元・matcher・prefix・root・権限
403ファイル権限・認証・upstream log。code だけで原因を決めない

複数 backend では request を受けられる状態を表す health endpoint を使う。probe 成功は全依存の保証ではなく、同一 host の複数 port は host 障害への冗長化ではない。

別 site 例:全 site を複数上流へ転送する。前の同 domain block を置き換える。/api/* のみなら matcher を保持する。

example.com {
    reverse_proxy 127.0.0.1:3000 127.0.0.1:3001 {
        lb_policy round_robin
        health_uri /health
        health_interval 10s
    }
}

adapt・validate 後に実 service を再読込

binary・設定 path・実行主体を確認する

# 設定構文に対応する版を確認する
caddy version

plugin は caddy list-modules で確認する。別 binary を入れても service が使うとは限らない。

# ExecStart・ExecReload・User・設定場所を読む
systemctl cat caddy.service

実 path に合わせ、旧 file を保存して編集する。例は独立の方式で、同じ domain block をそのまま連結しない。

# file を書かず整形差分を確認する
caddy fmt --diff /etc/caddy/Caddyfile

確認後、必要なら別途 --overwrite。整形と意味検証は別。

# Caddyfile から変換された JSON を読む
caddy adapt --config /etc/caddy/Caddyfile --adapter caddyfile --pretty

route 順・match・rewrite を読む。adapt は待ち受けを起動せず、機密設定を含み得る。

# module 設定を検証し、稼働 service はまだ置換しない
caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile

可能なら service と同じ主体・環境で file access も検証する。失敗を直してから reload。

# 確認した ExecReload で新設定を反映する
sudo systemctl reload caddy.service

reload 対応で実 file を参照する unit が前提。終了・log を読み、拒否時は旧設定の稼働を確認する。

# service 状態の後に実 route を再テストする
systemctl status caddy.service --no-pager

API・裸 prefix・static・health を個別検証する。戻す場合は旧 file を復元し validate/reload と同じ request を行う。

fmt は整形、adapt は JSON 生成、validate は module 初期化まで行うが全実依存を試験しない。service の権限と ExecReload の参照先を確認する。旧設定を保持し失敗時の稼働版を確認する。

reload でも全長時間接続の無停止は保証されない。WebSocket 等の close 方針を検証する。Admin GET /config は機密を含み得るため公開しない。標準 list-certificates ではなく配信 TLS と storage 設定を調べる。

証明書の管理主体を一つにする

自動 HTTPS は DNS・challenge または DNS plugin 権限と永続 storage が前提。issuer は変更可能。手動証明書には外部更新・配置・reload が必要。証明書参照。HTTP/3 は UDP と client 対応も要る。

独立 mTLS site:client CA file が存在し service から読めること。上節の検証・reload で配備する。

internal.example.com {
    tls {
        client_auth {
            mode require_and_verify
            trust_pool file /etc/caddy/client-ca.pem
        }
    }
    reverse_proxy 127.0.0.1:3000
}

trust_pool 対応版を使う。client-ca.pem は client 発行 CA で失効リストではない。mTLS はアプリ認可を代替しない。既定の転送 header 処理を理解し既知前段だけ trusted_proxies に設定する。

mTLS は拒否・許可の両方を試す

上記の mTLS 設定を読込後、client 証明書なしの拒否と承認済み identity の成功を試す。CA・秘密鍵は承認されたものを使う。

# client 証明書なしで mTLS 必須を確認する
curl -v https://internal.example.com/

TLS 拒否が期待結果。正常応答なら別入口・client_auth 未反映を疑う。私有 server CA は --cacert を使い -k にしない。

# 承認済み client 証明書でアクセスを検証する
curl -v --cert client.crt --key client.key https://internal.example.com/

TLS 成功後もアプリの認可を確認する。信頼された証明書でも全業務権限とは限らない。

handle_path · reverse_proxy · CLI · TLS

edge 入口の実設定は WildWindStudio EdgeOne runbook を参照。