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

php_fastcgi

php-fpmなどのPHP FastCGIサーバーにリクエストをプロキシする、独自性の強いディレクティブです。

Caddyのreverse_proxyは、あらゆるFastCGIアプリケーションを処理できますが、このディレクティブは特にPHPアプリ向けに調整されています。このディレクティブは便利なショートカットであり、より長い設定を置き換えるものです。

このディレクティブは、サイトルートにあるindex.phpがルーターとして機能することを想定しています。そうでない場合は、try_filesサブディレクティブを再設定してデフォルトのリライト動作を変更するか、展開形をベースとして、必要に応じてカスタマイズしてください。

以下に示すサブディレクティブに加えて、このディレクティブはreverse_proxyのすべてのサブディレクティブもサポートしています。たとえば、負荷分散やヘルスチェックを有効にすることができます。

ほとんどの現代的なPHPアプリは、追加のサブディレクティブやカスタマイズなしで正常に動作します。サブディレクティブは、通常、特定の例外的なケースやレガシーPHPアプリでのみ使用されます。

構文

php_fastcgi [<matcher>] <php-fpm_gateways...> {
	root <path>
	split <substrings...>
	index <filename>|off
	try_files <files...>
	env [<key> <value>]
	resolve_root_symlink
	capture_stderr
	dial_timeout  <duration>
	read_timeout  <duration>
	write_timeout <duration>

	<any other reverse_proxy subdirectives...>
}
  • <php-fpm_gateways...> は、FastCGIサーバーのアドレスです。通常、TCPソケットまたはunixソケットファイルのいずれかです。

  • root サイトのルートフォルダーを設定します。php_fastcgiと組み合わせてrootディレクティブを常に使用することをお勧めしますが、PHP-FPMアップストリームがCaddyとは異なるルートを使用している場合(を参照)、これをオーバーライドすると役立つことがあります。使用されている場合はrootディレクティブの値にデフォルト設定され、そうでない場合はCaddyの現在の作業ディレクトリにデフォルト設定されます。

  • split URIを2つの部分に分割するためのサブストリングを設定します。最初に一致したサブストリングを使用して、「パス情報」をパスから分割します。最初の部分は一致したサブストリングが接尾辞として付加され、実際のリソース(CGIスクリプト)名として想定されます。2番目の部分は、CGIスクリプトで使用されるPATH_INFOに設定されます。デフォルト: .php

  • index ディレクトリのインデックスファイルとして扱うファイル名を指定します。これは、展開形のファイルマッチャーに影響します。デフォルト: index.php。一致するファイルが見つからない場合にindex.phpへのリライトフォールバックを無効にするには、offに設定できます。

  • try_files デフォルトのtry-filesリライトのオーバーライドを指定します。詳細については、try_filesディレクティブを参照してください。デフォルト: {path} {path}/index.php index.php

  • env 指定された値に環境変数を追加します。複数の環境変数に対して複数回指定できます。デフォルトでは、すべての関連するFastCGI環境変数(HTTPヘッダーを含む)はすでに設定されていますが、必要に応じて変数を追加またはオーバーライドできます。

  • resolve_root_symlink rootディレクトリがシンボリックリンク(symlink)である場合、これを有効にすると、その実際の値に解決されます。これは、シンボリックリンクを別のディレクトリ内の新しいバージョンを指すように切り替えるだけで済む、デプロイ戦略として使用されることがあります。システム呼び出しの繰り返しを避けるため、デフォルトでは無効になっています。

  • capture_stderr アップストリームのfastcgiサーバーからstderrで送信されたメッセージのキャプチャとロギングを有効にします。ロギングは、デフォルトでWARNレベルで行われます。レスポンスのステータスが4xxまたは5xxの場合、代わりにERRORレベルが使用されます。デフォルトでは、stderrは無視されます。

  • dial_timeout アップストリームソケットへの接続時に待機する時間を設定する、期間値です。デフォルト: 3s

  • read_timeout FastCGIアップストリームからの読み取り時に待機する時間を設定する、期間値です。デフォルト: タイムアウトなし。

  • write_timeout FastCGIアップストリームへの送信時に待機する時間を設定する、期間値です。デフォルト: タイムアウトなし。

このディレクティブはリバースプロキシに対する独自性の強いラッパーであるため、reverse_proxyのサブディレクティブを使用してカスタマイズできます。

展開形

php_fastcgiディレクティブ(サブディレクティブなし)は、次の設定と同じです。ほとんどの現代的なPHPアプリはこのプリセットでうまく機能します。そうでない場合は、php_fastcgiショートカットを使用する代わりに、必要に応じてこのプリセットを借用してカスタマイズしてください。

route {
	# Add trailing slash for directory requests
	@canonicalPath {
		file {path}/index.php
		not path */
	}
	redir @canonicalPath {http.request.orig_uri.path}/ 308

	# If the requested file does not exist, try index files
	@indexFiles file {
		try_files {path} {path}/index.php index.php
		split_path .php
	}
	rewrite @indexFiles {file_match.relative}

	# Proxy PHP files to the FastCGI responder
	@phpFiles path *.php
	reverse_proxy @phpFiles <php-fpm_gateway> {
		transport fastcgi {
			split .php
		}
	}
}

説明

  • 最初のセクションは、リクエストパスの正規化を扱います。目標は、ディスク上のディレクトリをターゲットとするリクエストに、リクエストパスに末尾のスラッシュ/が追加されるようにし、そのディレクトリへのリクエストに対して単一のURLのみが有効になるようにすることです。

    これは、スラッシュで終わらないリクエストであり、ディスク上にindex.phpファイルを含むディレクトリにマップされるリクエストのみを照合するリクエストマッチャーを使用することで実行されます。一致した場合、末尾のスラッシュを追加してHTTP 308リダイレクトを実行します。たとえば、ディスク上に/foo/index.phpが存在する場合、パスが/fooのリクエストを/foo/にリダイレクトします(/を追加して、ディレクトリへのパスを正規化します)。

  • 次のセクションでは、一致するファイルがディスク上に存在するかどうかに基づいてパスリライトを実行します。これにより、リクエストパスに.phpが含まれている場合、.php以降のパスの部分を記憶するという副作用もあります。これは、CaddyがFastCGI環境変数を正しく設定するために重要です。

    • 最初に、{path}がディスク上に存在するファイルであるかどうかを確認します。存在する場合は、そのパスにリライトします。これにより、本質的に残りの処理を短絡し、ディスク上に存在するファイルへのリクエストが、それ以外の場合はリライトされないようにします(以下の次のステップを参照)。たとえば、ディスク上に/js/app.jsファイルがある場合、そのパスへのリクエストは同じままになります。

    • 次に、{path}/index.phpがディスク上に存在するファイルであるかどうかを確認します。存在する場合は、そのパスにリライトします。/foo/のようなディレクトリへのリクエストの場合、/foo//index.php/foo/index.phpに正規化されます)を検索し、存在する場合はそのパスにリライトします。この動作は、Webルートのサブディレクトリで別のPHPアプリを実行している場合に役立つことがあります。

    • 最後に、index.phpが存在する場合(最新のPHPアプリではほとんどの場合存在する必要があります)、それにリライトします。これにより、PHPアプリは、ディスク上のファイルにマップされないパスに対するリクエストを、index.phpスクリプトをエントリポイントとして使用して処理できます。

  • そして最後に、最後のセクションでは、PHPコードを実際に実行するために、PHP FastCGI(またはPHP-FPM)サービスにリクエストを実際にプロキシします。リクエストマッチャーは.phpで終わるリクエストのみに一致するため、PHPスクリプトではなく、ディスク上に存在するファイルは、このディレクティブでは処理されず、フォールスルーされます。

php_fastcgiディレクティブだけでは通常不十分です。ディスク上のファイルの場所を設定するためには、ほとんどの場合、rootディレクティブ(最新のPHPアプリでは、/var/www/html/publicになる可能性があります。ここで、publicディレクトリにはindex.phpが含まれています)と、このディレクティブで処理されず、フォールスルーした静的ファイル(JS、CSS、画像など)を提供するためのfile_serverディレクティブと組み合わせて使用する必要があります。

127.0.0.1:9000でリッスンしているFastCGIレスポンダにすべてのPHPリクエストをプロキシする

php_fastcgi 127.0.0.1:9000

同じですが、/blog/以下のリクエストのみに適用

php_fastcgi /blog/* localhost:9000

unixソケット経由でリッスンしているPHP-FPMを使用する場合

php_fastcgi unix//run/php/php8.2-fpm.sock

rootディレクティブは、ほとんどの場合、PHPスクリプトを含むディレクトリを指定するために使用され、file_serverディレクティブは静的ファイルを提供するために使用されます

example.com {
	root * /var/www/html/public
	php_fastcgi 127.0.0.1:9000
	file_server
}

Caddyで複数のPHPアプリを提供する場合、各アプリのWebルートは、Caddyが静的ファイルを個別に読み取り、提供し、PHPファイルが存在するかどうかを検出できるように、異なっている必要があります。

Dockerを使用している場合、多くの場合、PHP-FPMコンテナは同じルートにファイルをマウントします。その場合、解決策は、Caddyコンテナに異なるディレクトリにファイルをマウントし、rootサブディレクティブを使用して各コンテナのルートを設定することです

app1.example.com {
	root * /srv/app1/public
	php_fastcgi app1:9000 {
		root /var/www/html/public
	}
	file_server
}

app2.example.com {
	root * /srv/app2/public
	php_fastcgi app2:9000 {
		root /var/www/html/public
	}
	file_server
}

index.phpをエントリポイントとして使用しないPHPサイトの場合、代わりに404エラーを発生させるようにフォールバックできます。エラーは、handle_errorsディレクティブでキャッチして処理できます

example.com {
	php_fastcgi localhost:9000 {
		try_files {path} {path}/index.php =404
	}

	handle_errors {
		respond "{err.status_code} {err.status_text}"
	}
}