This is an old revision of the document!
Caddyfile:
{
# Enable FrankenPHP
frankenphp
order php_server before file_server
}
localhost {
# Enable compression (optional)
encode zstd br gzip
# Execute PHP files in the current directory and serve assets
php_server
}
Configure worker mode:
In this example FrankenPHP starts 2 workers per CPU
{
# ...
frankenphp {
worker ./public/index.php 2
}
# ...
}
Allow the browser to download resources or preconnect to a site before the final response was sent.
header('Link: </style.css>; rel=preload; as=style');
headers_send(103);
// Do sluggish stuff 🐌
Caddyfile example configuration:
localhost {
# ...
# Enable Mercure hub
mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
# Allow anonymous subscribers (double-check that it's what you want)
anonymous
# Enable the subscription API (double-check that it's what you want)
subscriptions
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
# Development only, enables the mercure UI
# demo
}
}
Publish a message to all clients
$hubUrl = 'https://localhost:8788/.well-known/mercure'; $jwt = '<JWT>'; $defaults = HttpClientInterface::OPTIONS_DEFAULTS; $client = HttpClient::create($defaults); $hub = new Hub($hubUrl, new StaticTokenProvider($jwt), null, null, $client); // The topic you want to publish to $topic = '/chat/messages'; $update = new Update($topic, 'MESSAGE TO ALL CLIENTS'); $hub->publish($update);
Receive the message:
let endpoint = "https://localhost:8788/.well-known/mercure"
let topic = "/chat/messages";
let jwtToken = "<JWT>"
let eventSource = new EventSource(`${endpoint}?topic=${encodeURIComponent(topic)}`, {
headers: {
Authorization: `Bearer ${jwtToken}`,
},
});
let eventSource.onmessage = (event) => {
console.log("Received event:", event.data);
};
Enable it in the Caddyfile:
{
# ...
servers {
metrics
}
# ...
}
The exporter is available under http://localhost:2019/metrics
Example metric:
# HELP caddy_http_request_duration_seconds Histogram of round-trip request durations.
# TYPE caddy_http_request_duration_seconds histogram
caddy_http_request_duration_seconds_bucket{code="200",handler="subroute",method="GET",server="srv0",le="0.005"} 564
...
Restart without interrupting current users connection.
frankenphp reload -c Caddyfile
Wrap your PHP application into a self-contained binary.
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder # Copy your app WORKDIR /go/src/app/dist/app COPY . . # Build the static binary WORKDIR /go/src/app/ RUN EMBED=dist/app/ ./build-static.sh
Create the self-contained binary using Docker:
docker build -t static-app -f static-build.Dockerfile . --load
Extract the binary (frankenphp-mac-arm64)
docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp
Docker:
docker run -v $PWD:/app/public \ -p 80:80 -p 443:443 -p 443:443/udp \ dunglas/frankenphp
Standalone Binary
./frankenphp run -c Caddyfile
Standalone Binary - CLI
Does not require additional PHP to be installed!
./frankenphp php-cli /path/to/your/script.php