Pingclairfile は読み込み時に一度だけコンパイルされ、サーバーが実際に実行する状態になります。そこから 2 つの帰結が生まれ、このプロジェクトの挙動のほとんどを説明します。設定が決められることは最初のリクエストより前に済みます。そして満たせない設定は、リクエスト時に妥協するのではなく、サーバーを停止させます。

## 🗂️ ファイル構造

ファイルは省略可能な global options ブロックと、それに続く 1 つ以上の site block で構成されます。

```caddyfile
{
    email admin@example.com
}

example.com {
    encode zstd gzip
    reverse_proxy 10.0.0.10:8080 10.0.0.11:8080
}

:8080 {
    file_server ./public
}
```

- **Global options** はファイル先頭の名前のないブロックに書き、サイト単位ではない状態を設定します。ACME アカウントのメールアドレス、Admin API、自動 HTTPS の挙動、trusted proxies、ホスト名上流の DNS 再解決などです。利用できるオプションは[ディレクティブ一覧](/ja/reference/directives/#global-options)にあります。
- **Site block** はアドレスで名前を付けます。ホスト、ポート、またはその両方です。ポートは独立したディレクティブではなくアドレスの一部なので、両者の一致を保つ場所は 1 か所で済みます。
- **ディレクティブ**は site block 内の文です。引数リストを取るもの、ネストしたブロックを取るもの、両方を取るものがあります。
- **コメント**は `#` から行末までです。
- **空白を含む値は引用符で囲みます。** 時間の長さには単位が必要です。`30s` は 30 秒で、長さが求められる場所に裸の `30` を書くと拒否されます。

## 🧭 マッチャー

マッチャーは、あるディレクティブをどのリクエストに適用するかを選びます。名前付きマッチャーは `@name` で宣言し、名前で参照します。

```caddyfile
example.com {
    @api path /api/*
    header @api Cache-Control "no-store"

    @assets path /assets/*
    header @assets Cache-Control "public, max-age=31536000, immutable"
}
```

`handle` ブロックはルートごとに挙動をまとめ、マッチャーを伴わないフォールバックも書けます。

```caddyfile
example.com {
    handle /assets/* {
        file_server ./assets
    }

    handle {
        respond "Page Not Found" 404
    }
}
```

## 🧩 スニペットと import

スニペットは再利用可能な断片で、`(name) { ... }` として宣言し、`import name` で取り込みます。呼び出し側からブロックを受け取り、スニペット内の `{block}` の位置に挿入することもできます。

```caddyfile
(site) {
    https://{args[0]} {
        {block}
    }
}

import site example.com {
    reverse_proxy 127.0.0.1:3000
}
```

import されたファイルで定義されたスニペットは、それより後の import から参照できます。引数リストの中に置かれたプレースホルダーは拒否されます。ディレクティブ木は、挿入後にその行をトークン層のように再解析できないためです。

## 🛡️ 検証

`pingclair validate` はファイルをコンパイルし、意味的な検査を行います。ディレクティブの引数、マッチャーの構文、証明書と鍵のパス、そして「どの対端がクライアント識別ヘッダーを主張できるか」といったポリシー制約です。

失敗は明示的で、閉じた方向に倒れます。

- **未実装の名前は名前で拒否されます。** 形式が定義する名前はすべて認識され、実装がないものは「機能が存在しない」というメッセージを出します。綴り間違いとして扱われることも、無視されることもありません。それを含む設定は起動しません。
- **満たせないオプションは拒否され、降格しません。** たとえば `encode` に Brotli を指定するとコンパイルエラーになります。プロキシにストリーミングの Brotli エンコーダーがないためで、黙って gzip を配信することはありません。
- **構文が正しくても、存在しないものを参照するファイルは拒否されます。** リポジトリの `examples/full_featured.pingclair` は正しい Caddyfile 構文ですが、依然として拒否されます。そこに書かれた証明書パスが、検査を実行するマシンに存在しないからで、拒否は正しい判断です。

同じ検査は読み込み時にも実行されるため、再読み込みで検証に失敗しても直前の状態は保たれます。

## 🔁 再読み込み

`pc service reload` はプロセスを再起動せずに設定を読み直します。`trusted_proxies` のように起動時に確立されるプロセス全体のポリシーは、再起動後に反映されます。
