🔐

Caddy + Cloudflare で動的リバースプロキシを設定する

2024/09/19に公開

Caddy

dns.providers.cloudflare モジュールが入ってる Caddy をビルドまたはダウンロードする。手順は公式ドキュメントにある。

Cloudflare

ワイルドカード証明書を発行したいので、DNS-01 チャレンジを用いるためドキュメントの指示に従って Cloudflare API トークンを発行する。

適宜 /lib/systemd/system/caddy.service を編集して環境変数に Cloudflare API トークンを入れる。

Caddyfile

https://*.domain.tld {
    tls email@example.com {
        dns cloudflare {env.CF_API_TOKEN}
    }
    reverse_proxy {
        to {http.request.host.labels.2}.backend.tld
        header_up Host {http.request.host.labels.2}.backend.tld
        tranpsort http {
            tls
        }
    }
}

参考

  • reverse_proxy (Caddyfile directive) — Caddy Documentation

    If the address is not a URL (i.e. does not have a scheme), then placeholders can be used, but this makes the upstream dynamically static, meaning that potentially many different backends act as a single, static upstream in terms of health checks and load balancing. We recommend using a dynamic upstreams module instead, if possible. When using placeholders, a port must be included (either by the placeholder replacement, or as a static suffix to the address).

  • Proxy Upstream Placeholders - Help - Caddy Community

    Oof this is a hard problem. I’m looking at the code, and the way the Caddyfile parser works, it would be very tricky to generally integrate placeholders here because currently we parse the address to handle special cases in the scheme (like srv+ to support SRV DNS lookups).

    In your case, you specify http://. It seems like you don’t hit the code path that triggers the parsing error if you skip specifying the scheme entirely. If you need https://, then instead set a transport block like this as a reverse_proxy subdirective:

    transport http {
        tls
    }
    
  • Get subdomain from host - Help - Caddy Community

    You can use the {http.request.host.labels.2} placeholder to get your subdomain.

    See here: apps/http - JSON Config Structure - Caddy Documentation

  • apps/http - JSON Config Structure - Caddy Documentation

    {http.request.host.labels.*}
    Request host labels (0-based from right); e.g. for foo.example.com: 0=com, 1=example, 2=foo

Discussion