ドキュメント
a プロジェクト

Caddyfile のコンセプト

このドキュメントは HTTP Caddyfile の詳細について学ぶのに役立ちます。

  1. 構造
  2. グローバルオプション
  3. アドレス
  4. マッチャ
  5. プレースホルダー
  6. スニペット
  7. 名前付きルート
  8. コメント
  9. 環境変数

構造

Caddyfile の構造は視覚的に説明できます

Caddyfile structure

重要なポイント

  • オプションの グローバルオプションブロック は、ファイルの最初の行になります。

  • スニペット または 名前付きルート が次にオプションで表示される場合があります。

  • それ以外の場合は、Caddyfile の最初の行は 常に サービスを提供するサイトの アドレス です。

  • すべての ディレクティブマッチャ必ず サイトブロックに入れる必要があります。サイトブロック間でグローバルなスコープや継承はありません。

  • サイトブロックが 1 つしかない場合は、中括弧{ } はオプションです。

Caddyfile は 1 つ以上のサイトブロックで構成され、サイトの アドレス で必ず始まります。アドレスの前に表示されるディレクティブは、パーサーにとって混乱します。

ブロック

ブロック の開始と終了は中括弧で行われます

... {
	...
}
  • 開始中括弧 { は行の最後になければならず、スペースが先行する必要があります。

  • 終了中括弧 } は行自体に表示する必要があります。

サイトブロックが 1 つしかない場合は、中括弧 (およびインデント) はオプションです。これは、1 つのサイトを素早く定義するために便利なもので、たとえばこれです

localhost

reverse_proxy /api/* localhost:9001
file_server

に相当します

localhost {
	reverse_proxy /api/* localhost:9001
	file_server
}

サイトブロックが 1 つしかない場合は、好みによってどちらか一方を使用できます。

同じ Caddyfile で複数のサイトを設定するには、それぞれのサイトの設定を区別するため、各サイトの周囲に中括弧を使用する 必要 があります

example1.com {
	root * /www/example.com
	file_server
}

example2.com {
	reverse_proxy localhost:9000
}

リクエストが複数のサイトブロックに一致する場合、最も具体的に一致するアドレスを含むサイトブロックが選択されます。リクエストは他のサイトブロックにカスケード的に伝わりません。

ディレクティブ

ディレクティブ は、サイトのサービス方法をカスタマイズする機能的なキーワードです。これらはサイトブロックに 必ず 表示される必要があります。たとえば、完全なファイルサーバーの設定は次のようになる場合があります

localhost {
	file_server
}

またはリバースプロキシ

localhost {
	reverse_proxy localhost:9000
}

これらの例では file_serverreverse_proxy はディレクティブです。ディレクティブとはサイトブロックの行で最初にくる単語です。

2 番目の例では、localhost:9000 はディレクティブの後に同じ行に登場するため、引数です。

ディレクティブは、独自のブロックを開くことができます。サブディレクティブはディレクティブブロック内の各行の先頭に表示されます

localhost {
	reverse_proxy localhost:9000 localhost:9001 {
		lb_policy first
	}
}

ここでは、lb_policyreverse_proxy のサブディレクティブです(バックエンド間で使用するロードバランシングポリシーを設定します)。

別途記載されていない限り、ディレクティブは他のディレクティブブロック内で使用できません。たとえば、basicauthfile_server 内では使用できません。これはファイルサーバーが認証方法を知らないためです。一方、 routehandle、および handle_path ブロックではディレクティブを使用できます。これらは特にディレクティブをグループ化するように設計されています。

HTTP の Caddyfile が調整されると、HTTP ハンドラディレクティブは特定のデフォルト ディレクティブの順序 に沿って並べ替えられます(route ブロック内を除く)。したがって、ディレクティブの表示順は route ブロックを除くすべてのブロックにおいて無関係です。

トークンと引用符

Caddyfile は、構文解析される前にトークンに解析されます。トークンは空白で区切られているため、Caddyfile では空白が重要です。

多くの場合、ディレクティブは特定数の引数を必要とします。1 つの引数が空白を含む値を持つ場合、2 つの個別トークンとして解析されます

directive abc def

これは問題を引き起こし、エラーや予期しない動作が発生する可能性があります。

abc def が単一引数の値であると想定される場合は、引用符で囲む必要があります

directive "abc def"

引用符で囲まれたトークンで引用符を使用する必要がある場合は、引用符をエスケープできます

directive "\"abc def\""

引用符のエスケープを回避するには、代わりにバックスペース ` ` を使用してトークンを囲みます。たとえば

directive `{"foo": "bar"}`

引用符で囲まれたトークン内では、スペース、タブ、改行を含む他のすべての文字がそのまま処理されます。したがって、複数行のトークンを使用できます

directive "first line
	second line"

ヒアドキュメント もサポートされています:

example.com {
	respond <<HTML
		<html>
		  <head><title>Foo</title></head>
		  <body>Foo</body>
		</html>
		HTML 200
}

ヒアドキュメントの開始マーカーは << で始まり、任意のテキスト(大文字が推奨)が続きます。ヒアドキュメントの終了マーカーは同じテキスト(上の例では HTML)にする必要があります。必要に応じて、開始マーカーを \<< でエスケープしてヒアドキュメントの構文解析を防止できます。

終了マーカーをインデントすると、テキストの各行からインデントが取り除かれます(PHP から着想)。これは、ブロック 内で可読性を向上させるのに適していますが、トークンテキスト内の空白を十分に制御できます。末尾の改行も削除されますが、終了マーカーの前に空白行を追加することで保持できます。

終了マーカーの後に追加のトークンをディレクティブの引数として続けることができます(上の例ではステータスコード 200)。

グローバルオプション

Caddyfile は、キーを持たない特殊なブロック(グローバルオプションブロック)で始まる場合があります

{
	...
}

存在する場合は、設定ファイルの最初のブロックである必要があります。

グローバルに適用されるオプション、または特定のサイトに適用されないオプションを設定するために使用されます。内部では、グローバルオプションのみを設定できます。通常のサイトディレクティブは使用できません。

たとえば、トラブルシューティングのために冗長ログを出力するために一般的に使用される debug グローバルオプションを有効にするには

{
	debug
}

グローバルオプションページ で詳細をご確認ください

アドレス

アドレスは常にサイトブロックの先頭に表示され、通常は Caddyfile の最初の項目です。

以下は有効なアドレスの例です

アドレス 効果
example.com 管理対象公開信用証明書のHTTPS
*.example.com 管理対象ワイルドカード公開信用証明書のHTTPS
localhost 管理対象ローカル信用証明書のHTTPS
http:// http_portの影響を受ける、HTTPのキャッチオール
https:// https_portの影響を受ける、HTTPSのキャッチオール
http://example.com Hostマッチャーを使用した明示的なHTTP
example.com:443 https_portのデフォルトにマッチするためにHTTPS
:443 https_portのデフォルトにマッチするためにHTTPSのキャッチオール
:8080 非標準ポートのHTTP、Hostマッチャーなし
localhost:8080 有効なドメインを持つため、非標準ポートのHTTPS
https://example.com:443 HTTPSだが、https://:443の両方が冗長
127.0.0.1 ローカル信用IP証明書のHTTPS
http://127.0.0.1 IPアドレスHostマッチャーのHTTP(localhostを拒否)

アドレスから、Caddyはサイトのスキーム、ホスト、ポートを推測できます。アドレスにポートがない場合、Caddyfileは指定されている場合はスキームに一致するポートを選択するか、またはデフォルトポートの443が想定されます。

ホスト名を指定した場合、一致するHostヘッダーを持つリクエストのみが有効になります。言い換えると、サイトアドレスがlocalhostの場合、Caddyは127.0.0.1へのリクエストと一致しません。

ワイルドカード(*)を使用できますが、ホスト名のラベルを正確に1つのみ表す必要があります。たとえば、*.example.comfoo.example.comと一致しますがfoo.bar.example.comとは一致せず、*localhostとは一致しますがexample.comとは一致しません。ワイルドカード証明書パターンで実際的な例を参照してください。

全ホストをキャッチするには、アドレスからホスト部分を省略します。たとえば、単にhttps://のようにします。これはオンデマンドTLSを使用する場合に、事前にドメインがわかっていない場合に便利です。

複数のサイトが同じ定義を共有する場合は、スペースまたはコンマを使用してすべてのサイトを一緒にリストできます。次の3つの例は同等です。

# Comma separated site addresses
localhost:8080, example.com, www.example.com {
	...
}

または

# Space separated site addresses
localhost:8080 example.com www.example.com {
	...
}

または

# Comma and new-line separated site addresses
localhost:8080,
example.com,
www.example.com {
	...
}

アドレスは一意である必要があります。同じアドレスを複数回指定することはできません。

プレースホルダーはアドレスでは使用できませんが、それらにCaddyfileスタイルの環境変数を使用できます

{$DOMAIN:localhost} {
	...
}

デフォルトでは、サイトはすべてのネットワークインターフェイスにバインドされます。これをオーバーライドする場合は、bindディレクティブまたはdefault_bindグローバルオプションを使用します。

マッチャ

HTTPハンドラディレクティブは、デフォルトですべてのリクエストに適用されます(他に記載がない限り)。

リクエストマッチャーを使用して、特定の基準によってリクエストを分類できます。マッチャーを使用すると、特定のディレクティブが適用されるリクエストを正確に指定できます。

マッチャーをサポートするディレクティブでは、ディレクティブの後の最初の引数がマッチャートークンです。例を次に示します。

root *           /var/www  # matcher token: *
root /index.html /var/www  # matcher token: /index.html
root @post       /var/www  # matcher token: @post

次の引数がパスマッチャーのように見えない場合は、マッチャートークンを完全に省略してすべてのリクエストと一致させることができます。

リクエストマッチャープールを読み、詳細を確認してください。

プレースホルダー

CaddyfileでCaddyプレースホルダーを使用できますが、利便性のために同等の省略形を使用することもできます。

省略形 置き換え
{cookie.*} {http.request.cookie.*}
{client_ip} {http.vars.client_ip}
{dir} {http.request.uri.path.dir}
{err.*} {http.error.*}
{file_match.*} {http.matchers.file.*}
{file.base} {http.request.uri.path.file.base}
{file.ext} {http.request.uri.path.file.ext}
{file} {http.request.uri.path.file}
{header.*} {http.request.header.*}
{host} {http.request.host}
{hostport} {http.request.hostport}
{labels.*} {http.request.host.labels.*}
{method} {http.request.method}
{path.*} {http.request.uri.path.*}
{path} {http.request.uri.path}
{port} {http.request.port}
{query.*} {http.request.uri.query.*}
{query} {http.request.uri.query}
{re.*.*} {http.regexp.*.*}
{remote_host} {http.request.remote.host}
{remote_port} {http.request.remote.port}
{remote} {http.request.remote}
{rp.*} {http.reverse_proxy.*}
{scheme} {http.request.scheme}
{tls_cipher} {http.request.tls.cipher_suite}
{tls_client_certificate_der_base64} {http.request.tls.client.certificate_der_base64}
{tls_client_certificate_pem} {http.request.tls.client.certificate_pem}
{tls_client_fingerprint} {http.request.tls.client.fingerprint}
{tls_client_issuer} {http.request.tls.client.issuer}
{tls_client_serial} {http.request.tls.client.serial}
{tls_client_subject} {http.request.tls.client.subject}
{tls_version} {http.request.tls.version}
{upstream_hostport} {http.reverse_proxy.upstream.hostport}
{uri} {http.request.uri}
{vars.*} {http.vars.*}

スニペット

() で囲まれた名前を付けることで、スニペットと呼ばれる特別なブロックを定義できます。

(logging) {
	log {
		output file /var/log/caddy.log
		format json
	}
}

その後、特別な import ディレクティブを使用すると、必要な場所に再利用できます。

example.com {
	import logging
}

www.example.com {
	import logging
}

import ディレクティブは、他のファイルをその場所に含めるために使用することもできます。引数が定義されたスニペットと一致しない場合、ファイルとして試行されます。また、複数のファイルをインポートするためのグロブもサポートしています。特殊なケースとして、サイトブロックの外側など、Caddyfile の任意の場所 (別のディレクティブへの引数として使用する場合を除く) に表示できます。

{
	email admin@example.com
}

import sites/*

インポートされた構成 (スニペットまたはファイル) に引数を渡して、次のように使用できます。

(snippet) {
	respond "Yahaha! You found {args[0]}!"
}

a.example.com {
	import snippet "Example A"
}

b.example.com {
	import snippet "Example B"
}

import ディレクティブのページを読んで、詳細をご確認ください。

名前付きルート

⚠️ 試作品

名前付きルートでは、スニペット とよく似た構文を使用します。これは、&( で始まり、) で終わる、サイトブロックの外側で定義された特別なブロックであり、その間に名前があります。

&(app-proxy) {
	reverse_proxy app-01:8080 app-02:8080 app-03:8080
}

その後、この名前付きルートを任意のサイト内で再利用できます。

example.com {
	invoke app-proxy
}

www.example.com {
	invoke app-proxy
}

これは、同じルートが多くの異なるサイトで必要とされる場合、または同じルートを呼び出すために複数の異なるマッチャー条件が必要な場合に、メモリ使用量を削減するために特に役立ちます。

invoke ディレクティブのページを読んで、詳細をご確認ください。

コメント

コメントは # で始まり、行末まで続きます。

# Comments can start a line
directive  # or go at the end

コメントのハッシュ文字 # はトークンの途中で表示できません (つまり、スペースの前にあるか、行の先頭に表示する必要があります)。これにより、URI やその他の値内のハッシュを、引用符を必要とせずに使用できます。

環境変数

構成が環境変数に依存する場合、Caddyfile で使用できます。

{$ENV}

この形式の環境変数は Caddyfile の解析が始まる前に置換されるため、空の値 (つまり "")、部分トークン、完全トークン、または複数のトークンと行にまで展開できます。

例えば、環境変数 UPSTREAMS="app1:8080 app2:8080 app3:8080" は複数の トークン に展開されます。

example.com {
	reverse_proxy {$UPSTREAMS}
}

変数名の後に : を区切り文字として置くと、環境変数が検出されなかった場合の既定値を指定できます。

{$DOMAIN:localhost} {

}

環境変数の置換をランタイムまで遅らせたい場合は、標準的な{env.*}プレースホルダーを使用できます。ただし、モジュール開発者は置換を実行するコード行を追加する必要があるため、すべての構成パラメーターがこのプレースホルダーをサポートしているわけではありません。機能していないと思われる場合は、問題をファイルしてサポートをリクエストしてください。

たとえば、caddy-dns/cloudflareプラグイン をインストール済みで、DNSチャレンジを構成したい場合は、次のようにCLOUDFLARE_API_TOKEN環境変数をプラグインに渡すことができます

{
	acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}

Caddyをsystemdサービスとして実行している場合は、この手順を参照して、サービスオーバーライドを設定して環境変数を定義してください。