Repository navigation
fix(caddy): show DDEV 404 page without index.php on Caddy v2.11.8 - #77
Merged
Merged
Conversation
## Short Summary (TL;DR) Caddy v2.11.8 sends every missing path to `index.php`, even when the docroot has no `index.php`, so FrankenPHP returned a PHP fatal error with status 200. Without `index.php`, the Caddyfile now serves files directly and returns 404 for missing PHP scripts, so the DDEV 403 and 404 pages show again. ## The Issue The scheduled tests for PHP 8.6 fail on all four jobs: https://github.com/ddev/ddev-frankenphp/actions/runs/41799786933 In a project without `index.php`, such as a new project with an empty docroot, every request returns status 200 with this output instead of the DDEV error page: ```text Warning: Unknown: Failed to open stream: No such file or directory in Unknown on line 0 Fatal error: Failed opening required '/var/www/html/index.php' (include_path='.:') in Unknown on line 0 ``` The PHP 8.6.0RC5 FrankenPHP package from https://debs.henderkes.com/ is the first one built with Caddy v2.11.8. That Caddy release changes the `first_exist_fallback` try policy, which `php_server` uses, so that the last entry (`index.php`) always matches, even when the file doesn't exist (GHSA-f278-mgc7-46j3, see https://github.com/caddyserver/caddy/releases/tag/v2.11.8). FrankenPHP doesn't return 404 for a missing script, so PHP fails with status 200. The packages for PHP 8.2 to 8.5 still use Caddy v2.11.7, and they will get the same change when they are rebuilt. ## How This PR Solves The Issue When `index.php` doesn't exist in the docroot, `common_config` handles the request before `php_server`: | Request | Result | | --- | --- | | A path that doesn't end in `.php` | `file_server` serves it, or returns 403 or 404, which show the DDEV error pages | | A `.php` path that doesn't exist | 404 with the DDEV error page | | A `.php` file that exists | `php_server` runs it, as before | Nothing changes when `index.php` exists. The change works with Caddy v2.11.7 and v2.11.8. With Caddy v2.11.8, a docroot without `index.php` returns the DDEV 404 page for `/`. ## Manual Testing Instructions Use PHP 8.6, because only its FrankenPHP package has Caddy v2.11.8 for now: ```bash mkdir -p ~/tmp/frankenphp-no-index && cd ~/tmp/frankenphp-no-index ddev config --project-type=php --php-version=8.6 ddev add-on get ddev/ddev-frankenphp --pr 77 ddev restart ddev exec 'frankenphp version' # Expect Caddy v2.11.8 in the output curl -s -o /dev/null -w '%{http_code}\n' https://frankenphp-no-index.ddev.site/missing.html # Expect 404, and the DDEV 404 page in a browser curl -s -o /dev/null -w '%{http_code}\n' https://frankenphp-no-index.ddev.site/missing.php # Expect 404, and the DDEV 404 page in a browser echo '<?php echo "ok";' > index.php curl -s https://frankenphp-no-index.ddev.site/some/route # Expect "ok", because index.php gets all missing paths again ddev delete -Oy frankenphp-no-index ``` Repeat with `--php-version=8.5` to check the same results with Caddy v2.11.7. ## Automated Testing Overview The health checks now also request a missing `.php` file without `index.php`, and expect the DDEV 404 page. Claude Code ran `bats tests --filter-tags php86 --filter-tags php85 --filter-tags php84` on Linux with Docker on amd64, and all 5 tests passed. That covers Caddy v2.11.8 (PHP 8.6), Caddy v2.11.7 (PHP 8.4 and 8.5), worker mode, and a custom docroot. Nobody ran it on arm64 or with DDEV HEAD, which CI covers. 🤖 Developed with assistance from [Claude Code](https://claude.ai/code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Short Summary (TL;DR)
Caddy v2.11.8 sends every missing path to
index.php, even when the docroot has noindex.php, so FrankenPHP returned a PHP fatal error with status 200. Withoutindex.php, the Caddyfile now serves files directly and returns 404 for missing PHP scripts, so the DDEV 403 and 404 pages show again.The Issue
The scheduled tests for PHP 8.6 fail on all four jobs: https://github.com/ddev/ddev-frankenphp/actions/runs/41799786933
In a project without
index.php, such as a new project with an empty docroot, every request returns status 200 with this output instead of the DDEV error page:The PHP 8.6.0RC5 FrankenPHP package from https://debs.henderkes.com/ is the first one built with Caddy v2.11.8. That Caddy release changes the
first_exist_fallbacktry policy, whichphp_serveruses, so that the last entry (index.php) always matches, even when the file doesn't exist (GHSA-f278-mgc7-46j3, see https://github.com/caddyserver/caddy/releases/tag/v2.11.8). FrankenPHP doesn't return 404 for a missing script, so PHP fails with status 200. The packages for PHP 8.2 to 8.5 still use Caddy v2.11.7, and they will get the same change when they are rebuilt.How This PR Solves The Issue
When
index.phpdoesn't exist in the docroot,common_confighandles the request beforephp_server:.phpfile_serverserves it, or returns 403 or 404, which show the DDEV error pages.phppath that doesn't exist.phpfile that existsphp_serverruns it, as beforeNothing changes when
index.phpexists. The change works with Caddy v2.11.7 and v2.11.8.With Caddy v2.11.8, a docroot without
index.phpreturns the DDEV 404 page for/.Manual Testing Instructions
Use PHP 8.6, because only its FrankenPHP package has Caddy v2.11.8 for now:
Repeat with
--php-version=8.5to check the same results with Caddy v2.11.7.Automated Testing Overview
The health checks now also request a missing
.phpfile withoutindex.php, and expect the DDEV 404 page.Claude Code ran
bats tests --filter-tags php86 --filter-tags php85 --filter-tags php84on Linux with Docker on amd64, and all 5 tests passed. That covers Caddy v2.11.8 (PHP 8.6), Caddy v2.11.7 (PHP 8.4 and 8.5), worker mode, and a custom docroot. Nobody ran it on arm64 or with DDEV HEAD, which CI covers.🤖 Developed with assistance from Claude Code