You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: add SEO frontmatter, llms.txt, and code-block hygiene
Add YAML frontmatter (title, description) to every English doc under
docs/*.md, rename generic headings (## Setup, ## Configuration, etc.)
to topic-specific ones, fix code-block language tags where wrong, and
add filename or purpose comments on blocks that represent a real file.
Add a root llms.txt index pointing AI agents at the canonical English
docs (Core Concepts, Setup and Build, Worker Mode and Extensions,
Frameworks, Real-Time and Performance, Production and Observability).
Translations under docs/<lang>/ are intentionally left untouched and
should be regenerated by running docs/translate.php.
description: Run FrankenPHP in classic mode as a drop-in replacement for PHP-FPM or Apache mod_php, with a fixed or autoscaling thread pool serving PHP files directly.
4
+
---
5
+
1
6
# Using Classic Mode
2
7
3
8
Without any additional configuration, FrankenPHP operates in classic mode. In this mode, FrankenPHP functions like a traditional PHP server, directly serving PHP files. This makes it a seamless drop-in replacement for PHP-FPM or Apache with mod_php.
Copy file name to clipboardExpand all lines: docs/compile.md
+6-1Lines changed: 6 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,8 @@
1
+
---
2
+
title: Compile FrankenPHP From Sources With PHP as a Library
3
+
description: Build FrankenPHP from source on Linux, macOS and FreeBSD, link PHP as a dynamic library via xcaddy or go build, and add custom Caddy modules and extensions.
4
+
---
5
+
1
6
# Compile From Sources
2
7
3
8
This document explains how to create a FrankenPHP binary that will load PHP as a dynamic library.
@@ -36,7 +41,7 @@ cd php-*/
36
41
Then, run the `configure` script with the options needed for your platform.
37
42
The following `./configure` flags are mandatory, but you can add others, for example, to compile extensions or additional features.
Copy file name to clipboardExpand all lines: docs/config.md
+21-2Lines changed: 21 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,8 @@
1
+
---
2
+
title: Configuring FrankenPHP With Caddyfile, php.ini, and Env Vars
3
+
description: Configure FrankenPHP and Caddy via Caddyfile, JSON, or environment variables, including PHP runtime tuning, worker mode, file watching, and module options.
4
+
---
5
+
1
6
# Configuration
2
7
3
8
FrankenPHP, Caddy as well as the [Mercure](mercure.md) and [Vulcain](https://vulcain.rocks) modules can be configured using [the formats supported by Caddy](https://caddyserver.com/docs/getting-started#your-first-config).
@@ -9,6 +14,7 @@ You can specify a custom path with the `-c` or `--config` option.
9
14
A minimal `Caddyfile` to serve a PHP application is shown below:
10
15
11
16
```caddyfile
17
+
# Caddyfile
12
18
# The hostname to respond to
13
19
localhost
14
20
@@ -39,6 +45,7 @@ PHP:
39
45
- You should copy an official template provided by the PHP project:
40
46
41
47
```dockerfile
48
+
# Dockerfile
42
49
FROM dunglas/frankenphp
43
50
44
51
# Production:
@@ -80,6 +87,7 @@ The `php_server` or the `php` [HTTP directives](https://caddyserver.com/docs/cad
80
87
Minimal example:
81
88
82
89
```caddyfile
90
+
# Caddyfile
83
91
localhost {
84
92
# Enable compression (optional)
85
93
encode zstd br gzip
@@ -91,6 +99,7 @@ localhost {
91
99
You can also explicitly configure FrankenPHP using the [global option](https://caddyserver.com/docs/caddyfile/concepts#global-options)`frankenphp`:
92
100
93
101
```caddyfile
102
+
# Caddyfile
94
103
{
95
104
frankenphp {
96
105
num_threads <num_threads> # Sets the number of PHP threads to start. Default: 2x the number of available CPUs.
@@ -116,6 +125,7 @@ You can also explicitly configure FrankenPHP using the [global option](https://c
116
125
Alternatively, you may use the one-line short form of the `worker` option:
117
126
118
127
```caddyfile
128
+
# Caddyfile
119
129
{
120
130
frankenphp {
121
131
worker <file> <num>
@@ -128,6 +138,7 @@ Alternatively, you may use the one-line short form of the `worker` option:
128
138
You can also define multiple workers if you serve multiple apps on the same server:
129
139
130
140
```caddyfile
141
+
# Caddyfile
131
142
app.example.com {
132
143
root /path/to/app/public
133
144
php_server {
@@ -155,6 +166,7 @@ it's a PHP file or not. Read more about it in the [performance page](performance
155
166
Using the `php_server` directive is equivalent to this configuration:
156
167
157
168
```caddyfile
169
+
# Caddyfile
158
170
route {
159
171
# Add trailing slash for directory requests
160
172
@canonicalPath {
@@ -178,6 +190,7 @@ route {
178
190
The `php_server` and the `php` directives have the following options:
179
191
180
192
```caddyfile
193
+
# Caddyfile
181
194
php_server [<matcher>] {
182
195
root <directory> # Sets the root folder to the site. Default: `root` directive.
183
196
split_path <delim...> # Sets the substrings for splitting the URI into two parts. The first matching substring will be used to split the "path info" from the path. The first piece is suffixed with the matching substring and will be assumed as the actual resource (CGI script) name. The second piece will be set to PATH_INFO for the script to use. Default: `.php`
@@ -205,6 +218,7 @@ Workers can instead be restarted on file changes via the `watch` directive.
205
218
This is useful for development environments.
206
219
207
220
```caddyfile
221
+
# Caddyfile
208
222
{
209
223
frankenphp {
210
224
worker {
@@ -223,6 +237,7 @@ where the FrankenPHP process was started. You can instead also specify one or mo
@@ -254,6 +269,7 @@ The following example will always serve a file in the public directory if presen
254
269
and otherwise forward the request to the worker matching the path pattern.
255
270
256
271
```caddyfile
272
+
# Caddyfile
257
273
{
258
274
frankenphp {
259
275
php_server {
@@ -278,14 +294,15 @@ But when the fix depends on a third party you don't control,
278
294
`max_requests` provides a pragmatic and hopefully temporary workaround for production:
279
295
280
296
```caddyfile
297
+
# Caddyfile
281
298
{
282
299
frankenphp {
283
300
max_requests 500
284
301
}
285
302
}
286
303
```
287
304
288
-
## Environment Variables
305
+
## FrankenPHP Environment Variables
289
306
290
307
The following environment variables can be used to inject Caddy directives in the `Caddyfile` without modifying it:
291
308
@@ -298,7 +315,7 @@ As for FPM and CLI SAPIs, environment variables are exposed by default in the `$
298
315
299
316
The `S` value of [the `variables_order` PHP directive](https://www.php.net/manual/en/ini.core.php#ini.variables-order) is always equivalent to `ES` regardless of the placement of `E` elsewhere in this directive.
300
317
301
-
## PHP config
318
+
## PHP Configuration in FrankenPHP
302
319
303
320
To load [additional PHP configuration files](https://www.php.net/manual/en/configuration.file.php#configuration.file.scan),
304
321
the `PHP_INI_SCAN_DIR` environment variable can be used.
@@ -307,6 +324,7 @@ When set, PHP will load all the file with the `.ini` extension present in the gi
307
324
You can also change the PHP configuration using the `php_ini` directive in the `Caddyfile`:
308
325
309
326
```caddyfile
327
+
# Caddyfile
310
328
{
311
329
frankenphp {
312
330
php_ini memory_limit 256M
@@ -338,6 +356,7 @@ has been read. (for example: [Mercure](mercure.md), WebSocket, Server-Sent Event
338
356
This is an opt-in configuration that needs to be added to the global options in the `Caddyfile`:
description: Build custom FrankenPHP Docker images, install PHP extensions and Caddy modules, run as non-root, harden with distroless, and enable worker mode by default.
4
+
---
5
+
1
6
# Building Custom Docker Image
2
7
3
8
[FrankenPHP Docker images](https://hub.docker.com/r/dunglas/frankenphp) are based on [official PHP images](https://hub.docker.com/_/php/).
@@ -13,11 +18,12 @@ The tags follow this pattern: `dunglas/frankenphp:<frankenphp-version>-php<php-v
Copy file name to clipboardExpand all lines: docs/early-hints.md
+6-1Lines changed: 6 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,11 @@
1
+
---
2
+
title: Sending HTTP 103 Early Hints from PHP with FrankenPHP
3
+
description: FrankenPHP natively supports the HTTP 103 Early Hints status code, letting PHP applications preload assets before the final response is ready.
4
+
---
5
+
1
6
# Early Hints
2
7
3
-
FrankenPHP natively supports the [103 Early Hints status code](https://developer.chrome.com/blog/early-hints/).
8
+
FrankenPHP natively supports the [103 Early Hints status code](https://developer.mozilla.org/docs/Web/HTTP/Reference/Status/103).
4
9
Using Early Hints can improve the load time of your web pages by 30%.
Copy file name to clipboardExpand all lines: docs/embed.md
+12-6Lines changed: 12 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,8 @@
1
+
---
2
+
title: Embedding PHP Apps as Standalone Binaries with FrankenPHP
3
+
description: How to package a PHP application (including Symfony or Laravel) as a self-contained static binary with FrankenPHP, the PHP interpreter, PHP extensions and Caddy.
4
+
---
5
+
1
6
# PHP Apps As Standalone Binaries
2
7
3
8
FrankenPHP has the ability to embed the source code and assets of PHP applications in a static, self-contained binary.
@@ -6,7 +11,7 @@ Thanks to this feature, PHP applications can be distributed as standalone binari
6
11
7
12
Learn more about this feature [in the presentation made by Kévin at SymfonyCon 2023](https://dunglas.dev/2023/12/php-and-symfony-apps-as-standalone-binaries/).
8
13
9
-
For embedding Laravel applications, [read this specific documentation entry](laravel.md#laravel-apps-as-standalone-binaries).
14
+
For embedding Laravel applications, see [the Laravel-specific embedding instructions](laravel.md#laravel-apps-as-standalone-binaries).
10
15
11
16
## Preparing Your App
12
17
@@ -42,7 +47,7 @@ composer install --ignore-platform-reqs --no-dev -a
42
47
composer dump-env prod
43
48
```
44
49
45
-
### Customizing the Configuration
50
+
### Customizing the Embedded FrankenPHP Configuration
46
51
47
52
To customize [the configuration](config.md), you can put a `Caddyfile` as well as a `php.ini` file
48
53
in the main directory of the app to be embedded (`$TMPDIR/my-prepared-app` in the previous example).
@@ -54,6 +59,7 @@ The easiest way to create a Linux binary is to use the Docker-based builder we p
54
59
1. Create a file named `static-build.Dockerfile` in the repository of your app:
55
60
56
61
```dockerfile
62
+
# static-build.Dockerfile
57
63
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder-gnu
58
64
# If you intend to run the binary on musl-libc systems, use static-builder-musl instead
0 commit comments