* Adds filesystem watcher with tests. * Refactoring. * Formatting. * Formatting. * Switches to absolute path in tests. * Fixes race condition from merge conflict. * Fixes race condition. * Fixes tests. * Fixes markdown lint errors. * Switches back to absolute paths. * Reverts back to relative file paths. * Fixes golangci-lint issues. * Uses github.com/dunglas/go-fswatch instead. * Stops watcher before stopping workers. * Updates docs. * Avoids segfault in tests. * Fixes watcher segmentation violations on shutdown. * Adjusts watcher latencies and tests. * Adds fswatch to dockerfiles * Fixes fswatch in alpine. * Fixes segfault (this time for real). * Allows queueing new reload if file changes while workers are reloading. * Makes tests more consistent. * Prevents the watcher from getting stuck if there is an error in the worker file itself. * Reverts changing the image. * Puts fswatch version into docker-bake.hcl. * Asserts instead of panicking. * Adds notice Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update dev.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update alpine.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update alpine.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update dev-alpine.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update dev-alpine.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update dev.Dockerfile Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update docs/config.md Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Runs fswatch version. * Removes .json. * Replaces ms with s. * Resets the channel after closing it. * Update watcher_options.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update watcher_test.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Asserts no error instead. * Fixes a race condition where events are fired after frankenphp has stopped. * Updates docs. * Update watcher_options_test.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Allows queuing events while watchers are reloading. * go fmt * Refactors stopping and draining logic. * Allows extended watcher configuration with dirs, recursion, symlinks, case-sensitivity, latency, monitor types and regex. * Updates docs. * Adds TODOS. * go fmt. * Fixes linting errors. * Also allows wildcards in the longform and adjusts docs. * Adds debug log. * Fixes the watcher short form. * Refactors sessions and options into a struct. * Fixes an overflow in the 'workersReadyWG' on unexpected terminations. * Properly logs errors coming from session.Start(). * go fmt. * Adds --nocache. * Fixes lint issue. * Refactors and resolves race condition on worker reload. * Implements debouncing with a timer as suggested by @withinboredom. * Starts watcher even if no workers are defined. * Updates docs with file limit warning. * Adds watch config unit tests. * Adjusts debounce timings. * go fmt. * Adds fswatch to static builder (test). * Adds a short grace period between stopping and destroying the watcher sessions. * Adds caddy test. * Adjusts sleep time. * Swap to edant/watcher. * Fixes watch options and tests. * go fmt. * Adds TODO. * Installs edant/watcher in the bookworm image. * Fixes linting. * Refactors the watcher into its own module. * Adjusts naming. * ADocker image adjustments and refactoring. * Testing installation methods. * Installs via gcc instead. * Fixes pointer formats. * Fixes lint issues. * Fixes arm alpine and updates docs. * Clang format. * Fixes dirs. * Adds watcher version arg. * Uses static lib version. * Adds watcher to tests and sanitizers. * Uses sudo for copying the shared lib. * Removes unnused func. * Refactoring. * Update .github/workflows/sanitizers.yaml Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Adds fpic. * Fixes linting. * Skips tests in msan. * Resets op_cache in every worker thread after termination * Review fixes part 1. * Test: installing libstc++ instead of gcc. * Test: using msan ignorelist. * Test: using msan ignorelist. * Test: using msan ignorelist. * Allows '/**/' for global recursion and '**/' for relative recursion. * Reverts using the ignorelist. * Calls opcache directly. * Adds --watch to php-server command * Properly free CStrings. * Sorts alphabetically and uses curl instead of git. * Labeling and formatting. * Update .github/workflows/sanitizers.yaml Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update .github/workflows/sanitizers.yaml Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update .github/workflows/tests.yaml Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update .github/workflows/tests.yaml Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update caddy/caddy.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update docs/config.md Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update frankenphp_with_watcher_test.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update watcher/watcher.h Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update frankenphp.c Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update watcher/watcher.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update docs/config.md Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update frankenphp_with_watcher_test.go Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update testdata/files/.gitignore Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update watcher/watcher-c.h Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Update watcher/watcher.c Co-authored-by: Kévin Dunglas <kevin@dunglas.fr> * Fixes test and Dockerfile. * Fixes Dockerfiles. * Resets go versions. * Replaces unsafe.pointer with uintptr_t * Prevents worker channels from being destroyed on reload. * Minimizes the public api by only passing a []string. * Adds support for directory patterns and multiple '**' globs. * Adjusts label. * go fmt. * go mod tidy. * Fixes merge conflict. * Refactoring and formatting. * Cleans up unused vars and functions. * Allows dirs with a dot. * Makes test nicer. * Add dir tests. * Moves the watch directive inside the worker directive. * Adds debug log on special events. * Removes line about symlinks. * Hints at multiple possible --watch flags. * Adds ./**/*.php as default watch configuration. * Changes error to a warning. * Changes the default to './**/*.{php,yaml,yml,twig,env}' and supports the {bracket} pattern. * Fixes linting. * Fixes merge conflict and adjust values. * Adjusts values. --------- Co-authored-by: a.stecher <a.stecher@sportradar.com> Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>
FrankenPHP: Modern App Server for PHP
FrankenPHP is a modern application server for PHP built on top of the Caddy web server.
FrankenPHP gives superpowers to your PHP apps thanks to its stunning features: Early Hints, worker mode, real-time capabilities, automatic HTTPS, HTTP/2, and HTTP/3 support...
FrankenPHP works with any PHP app and makes your Laravel and Symfony projects faster than ever thanks to their official integrations with the worker mode.
FrankenPHP can also be used as a standalone Go library to embed PHP in any app using net/http.
Learn more on frankenphp.dev and in this slide deck:
Getting Started
Docker
docker run -v $PWD:/app/public \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphp
Go to https://localhost, and enjoy!
Tip
Do not attempt to use
https://127.0.0.1. Usehttps://localhostand accept the self-signed certificate. Use theSERVER_NAMEenvironment variable to change the domain to use.
Standalone Binary
If you prefer not to use Docker, we provide standalone FrankenPHP binaries for Linux and macOS containing PHP 8.3 and most popular PHP extensions: Download FrankenPHP
To serve the content of the current directory, run:
./frankenphp php-server
You can also run command-line scripts with:
./frankenphp php-cli /path/to/your/script.php
Docs
- The worker mode
- Early Hints support (103 HTTP status code)
- Real-time
- Configuration
- Docker images
- Deploy in production
- Performance optimization
- Create standalone, self-executable PHP apps
- Create static binaries
- Compile from sources
- Laravel integration
- Known issues
- Demo app (Symfony) and benchmarks
- Go library documentation
- Contributing and debugging

