2 分で読了 #devops
このページの目次

Caddy 操作マニュアル

Caddy は Go で書かれた Web サーバー/リバースプロキシです。主な特徴は、自動 TLS(ACME + Let's Encrypt のゼロコンフィグ)と、簡潔な Caddyfile 構文による設定です。設定ファイルの場所はインストール方法によって異なります。パッケージマネージャーでインストールした場合は通常 /etc/caddy/Caddyfile に、手動デプロイした場合は ./Caddyfile に配置されます。

設定

静的ファイルサーバー

example.com {
    root * /var/www/html                 # * はすべてのパスにマッチします
    file_server                          # 静的ファイルサービス(ディレクトリリストを自動生成)
    encode gzip zstd                     # 応答の圧縮
}

リバースプロキシ

grafana.example.com {
    reverse_proxy 127.0.0.1:3000 {
        # バックエンドに渡されるヘッダー(バックエンドのログで実際のクライアント IP を確認可能)
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
        header_up Host {upstream_hostport}
    }
}

複数のバックエンド(ロードバランシング)

api.example.com {
    reverse_proxy backend-1:8080 backend-2:8080 backend-3:8080 {
        lb_policy least_conn               # round_robin / least_conn / random
        health_uri /health                  # ヘルスチェックのエンドポイント
        health_interval 30s
    }
}

mTLS(双方向認証)

otlp.example.com {
    tls /etc/caddy/certs/server.crt /etc/caddy/certs/server.key {
        client_auth {
            mode require_and_verify
            trusted_ca_cert_file /etc/caddy/certs/ca.crt     # 信頼する CA
            trusted_leaf_cert_file /etc/caddy/certs/revoked.caddy  # 失効リスト
        }
    }
    # 特定パスのみを許可し、それ以外は 403 を返す
    @otlp path /api/v1/otlp/*
    reverse_proxy @otlp 127.0.0.1:4318
    respond 403
}

リロードとホットアップデート

# 設定構文の検証(Caddyfile を変更した後は、リロード前に検証してください)
caddy validate --config /etc/caddy/Caddyfile
# → "Valid configuration" またはエラー詳細が出力されます

# ホットリロード(既存の接続を中断せず、新しい接続には新しい設定を使用)
systemctl reload caddy
# または caddy reload --config /etc/caddy/Caddyfile

# 最終的に生成される JSON 設定を確認(Caddy は内部で Caddyfile を JSON に変換します)
caddy adapt --config /etc/caddy/Caddyfile

# 現在読み込まれている設定を確認
caddy fmt --overwrite /etc/caddy/Caddyfile   # Caddyfile のフォーマット

証明書管理

Caddy はデフォルトで Let's Encrypt 証明書を自動管理します。初回起動時に ACME HTTP-01 または TLS-ALPN-01 チャレンジを通じて証明書を発行し、有効期限が近づく前に自動的に更新します。

# 管理されている証明書の一覧を表示
caddy list-certificates

# データディレクトリ(証明書 + OCSP staple + アカウントキー):
# /var/lib/caddy/.local/share/caddy/

# 静的証明書を使用(Let's Encrypt を自動発行しない): tls ディレクティブでファイルパスを指定します
tls /etc/caddy/certs/example.crt /etc/caddy/certs/example.key

# 複数ドメイン対応の SAN 証明書
example.com, *.example.com {
    tls /etc/caddy/certs/wildcard.crt /etc/caddy/certs/wildcard.key
    ...
}

ログ

# デフォルトでは JSON 形式で stderr に出力(systemd journal によって収集されます)
journalctl -u caddy -f

# または Caddyfile でファイルへの出力を設定することも可能です:
# log {
#     output file /var/log/caddy/access.log {
#         roll_size 100mb
#         roll_keep 5
#     }
#     format json
# }

トラブルシューティング

# 起動に失敗した場合
caddy validate --config /etc/caddy/Caddyfile   # まず構文を確認
journalctl -u caddy --since "5 min ago" --no-pager | tail -50

# TLS 証明書のエラー
curl -vI https://example.com 2>&1 | grep -E 'SSL|cert|verify'
# → 証明書の期限切れ / ドメイン不一致 / ACME チャレンジの失敗(journalctl で詳細を確認)

# 502 Bad Gateway(バックエンドに到達できない)
# → Caddy はアップストリームに接続できますか?
curl -I http://127.0.0.1:3000
# → バックエンドのヘルス状態を確認: systemctl status <backend>

# HTTP/3 が動作しない
# → Caddy はデフォルトで h3 を有効にしていますが、以下の条件が必要です:
#   - 443 番ポートの UDP がファイアウォールで許可されていること
#   - Caddy の内部ポートが外部ポートと一致していること(一致しない場合、alt-svc ポートが正しくなくなります)