Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/github/workspace/docs/mercure.md:jwt:88
/github/workspace/docs/mercure.md:jwt:90
/github/workspace/docs/mercure.md:jwt:95
Comment thread
dunglas marked this conversation as resolved.
Comment thread
dunglas marked this conversation as resolved.
Comment thread
dunglas marked this conversation as resolved.
Comment thread
dunglas marked this conversation as resolved.
Comment thread
dunglas marked this conversation as resolved.
Comment thread
dunglas marked this conversation as resolved.
2 changes: 2 additions & 0 deletions .markdown-lint.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
MD010: false
MD013: false
MD025:
front_matter_title: ""
MD033: false
MD060: false
5 changes: 5 additions & 0 deletions docs/classic.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: FrankenPHP Classic Mode: Drop-in PHP-FPM Replacement
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.
---

# Using Classic Mode

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.
Expand Down
7 changes: 6 additions & 1 deletion docs/compile.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: Compile FrankenPHP From Sources With PHP as a Library
Comment thread
dunglas marked this conversation as resolved.
Outdated
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.
Comment thread
dunglas marked this conversation as resolved.
Outdated
---

# Compile From Sources

This document explains how to create a FrankenPHP binary that will load PHP as a dynamic library.
Expand Down Expand Up @@ -36,7 +41,7 @@ cd php-*/
Then, run the `configure` script with the options needed for your platform.
The following `./configure` flags are mandatory, but you can add others, for example, to compile extensions or additional features.

#### Linux
#### Linux and FreeBSD

```console
./configure \
Expand Down
9 changes: 7 additions & 2 deletions docs/config.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: Configuring FrankenPHP With Caddyfile, php.ini, and Env Vars
description: Configure FrankenPHP and Caddy via Caddyfile, JSON, or environment variables, including PHP runtime tuning, worker mode, file watching, and module options.
---

# Configuration

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).
Expand Down Expand Up @@ -285,7 +290,7 @@ But when the fix depends on a third party you don't control,
}
```

## Environment Variables
## FrankenPHP Environment Variables

The following environment variables can be used to inject Caddy directives in the `Caddyfile` without modifying it:

Expand All @@ -298,7 +303,7 @@ As for FPM and CLI SAPIs, environment variables are exposed by default in the `$

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.

## PHP config
## PHP Configuration in FrankenPHP
Comment thread
dunglas marked this conversation as resolved.
Outdated

To load [additional PHP configuration files](https://www.php.net/manual/en/configuration.file.php#configuration.file.scan),
the `PHP_INI_SCAN_DIR` environment variable can be used.
Expand Down
13 changes: 9 additions & 4 deletions docs/docker.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: FrankenPHP Docker Image: Build, Configure, Extend
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.
---

# Building Custom Docker Image

[FrankenPHP Docker images](https://hub.docker.com/r/dunglas/frankenphp) are based on [official PHP images](https://hub.docker.com/_/php/).
Expand All @@ -13,7 +18,7 @@ The tags follow this pattern: `dunglas/frankenphp:<frankenphp-version>-php<php-v

[Browse tags](https://hub.docker.com/r/dunglas/frankenphp/tags).

## How to Use The Images
## How to Use the FrankenPHP Docker Images

Create a `Dockerfile` in your project:

Expand All @@ -30,7 +35,7 @@ docker build -t my-php-app .
docker run -it --rm --name my-running-app my-php-app
```

## How to Tweak the Configuration
## How to Tweak the FrankenPHP Docker Configuration

For convenience, [a default `Caddyfile`](https://github.com/php/frankenphp/blob/main/caddy/frankenphp/Caddyfile) containing
useful environment variables is provided in the image.
Expand Down Expand Up @@ -198,14 +203,14 @@ USER ${USER}
Next, set the `SERVER_NAME` environment variable to use an unprivileged port.
Example: `:8000`

## Updates
## FrankenPHP Docker Image Updates

The Docker images are built:

- when a new release is tagged
- daily at 4 am UTC, if new versions of the official PHP images are available

## Hardening Images
## Hardening FrankenPHP Docker Images

To further reduce the attack surface and size of your FrankenPHP Docker images, it's also possible to build them on top of a
[Google distroless](https://github.com/GoogleContainerTools/distroless) or
Expand Down
7 changes: 6 additions & 1 deletion docs/early-hints.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
---
title: Sending HTTP 103 Early Hints from PHP with FrankenPHP
description: FrankenPHP natively supports the HTTP 103 Early Hints status code, letting PHP applications preload assets before the final response is ready.
---

# Early Hints

FrankenPHP natively supports the [103 Early Hints status code](https://developer.chrome.com/blog/early-hints/).
FrankenPHP natively supports the [103 Early Hints status code](https://developer.mozilla.org/docs/Web/HTTP/Reference/Status/103).
Comment thread
dunglas marked this conversation as resolved.
Outdated
Using Early Hints can improve the load time of your web pages by 30%.

```php
Expand Down
18 changes: 12 additions & 6 deletions docs/embed.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: Embedding PHP Apps as Standalone Binaries with FrankenPHP
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.
---

# PHP Apps As Standalone Binaries

FrankenPHP has the ability to embed the source code and assets of PHP applications in a static, self-contained binary.
Expand All @@ -6,7 +11,7 @@ Thanks to this feature, PHP applications can be distributed as standalone binari

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/).

For embedding Laravel applications, [read this specific documentation entry](laravel.md#laravel-apps-as-standalone-binaries).
For embedding Laravel applications, see [the Laravel-specific embedding instructions](laravel.md#laravel-apps-as-standalone-binaries).
Comment thread
dunglas marked this conversation as resolved.
Outdated

## Preparing Your App

Expand Down Expand Up @@ -42,7 +47,7 @@ composer install --ignore-platform-reqs --no-dev -a
composer dump-env prod
```

### Customizing the Configuration
### Customizing the Embedded FrankenPHP Configuration
Comment thread
dunglas marked this conversation as resolved.
Outdated

To customize [the configuration](config.md), you can put a `Caddyfile` as well as a `php.ini` file
in the main directory of the app to be embedded (`$TMPDIR/my-prepared-app` in the previous example).
Expand All @@ -54,6 +59,7 @@ The easiest way to create a Linux binary is to use the Docker-based builder we p
1. Create a file named `static-build.Dockerfile` in the repository of your app:

```dockerfile
# static-build.Dockerfile
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder-gnu
# If you intend to run the binary on musl-libc systems, use static-builder-musl instead

Expand Down Expand Up @@ -97,7 +103,7 @@ EMBED=/path/to/your/app ./build-static.sh

The resulting binary is the file named `frankenphp-<os>-<arch>` in the `dist/` directory.

## Using The Binary
## Using the Embedded FrankenPHP Binary

This is it! The `my-app` file (or `dist/frankenphp-<os>-<arch>` on other OSes) contains your self-contained app!

Expand Down Expand Up @@ -125,18 +131,18 @@ You can also run the PHP CLI scripts embedded in your binary:
./my-app php-cli bin/console
```

## PHP Extensions
## PHP Extensions in the Embedded Binary
Comment thread
dunglas marked this conversation as resolved.
Outdated

By default, the script will build extensions required by the `composer.json` file of your project, if any.
If the `composer.json` file doesn't exist, the default extensions are built, as documented in [the static builds entry](static.md).

To customize the extensions, use the `PHP_EXTENSIONS` environment variable.

## Customizing The Build
## Customizing the Embedded Binary Build

[Read the static build documentation](static.md) to see how to customize the binary (extensions, PHP version...).

## Distributing The Binary
## Distributing the Embedded Binary

On Linux, the created binary is compressed using [UPX](https://upx.github.io).

Expand Down
29 changes: 19 additions & 10 deletions docs/extension-workers.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
---
title: FrankenPHP Extension Workers: Background PHP Thread Pools
description: Use FrankenPHP Extension Workers to run a dedicated PHP thread pool from a Go extension for queues, schedulers, event listeners, and custom protocols.
---

# Extension Workers

Extension Workers enable your [FrankenPHP extension](https://frankenphp.dev/docs/extensions/) to manage a dedicated pool of PHP threads for executing background tasks, handling asynchronous events, or implementing custom protocols. Useful for queue systems, event listeners, schedulers, etc.

## Registering the Worker
## Registering a FrankenPHP Extension Worker
Comment thread
dunglas marked this conversation as resolved.
Outdated

### Static Registration
### Static Worker Registration
Comment thread
dunglas marked this conversation as resolved.
Outdated

If you don't need to make the worker configurable by the user (fixed script path, fixed number of threads), you can simply register the worker in the `init()` function.

```go
// FrankenPHP extension worker static registration
package myextension

import (
Expand All @@ -35,23 +41,24 @@ func init() {

### In a Caddy Module (Configurable by the user)

If you plan to share your extension (like a generic queue or event listener), you should wrap it in a Caddy module. This allows users to configure the script path and thread count via their `Caddyfile`. This requires implementing the `caddy.Provisioner` interface and parsing the Caddyfile ([see an example](https://github.com/dunglas/frankenphp-queue/blob/989120d394d66dd6c8e2101cac73dd622fade334/caddy.go)).
If you plan to share your extension (like a generic queue or event listener), you should wrap it in a Caddy module. This allows users to configure the script path and thread count via their `Caddyfile`. This requires implementing the `caddy.Provisioner` interface and parsing the Caddyfile ([see the frankenphp-queue Caddy module example](https://github.com/dunglas/frankenphp-queue/blob/main/caddy.go)).

### In a Pure Go Application (Embedding)

If you are [embedding FrankenPHP in a standard Go application without caddy](https://pkg.go.dev/github.com/dunglas/frankenphp#example-ServeHTTP), you can register extension workers using `frankenphp.WithExtensionWorkers` when initializing options.

## Interacting with Workers
## Dispatching Tasks to FrankenPHP Extension Workers

Once the worker pool is active, you can dispatch tasks to it. This can be done inside [native functions exported to PHP](https://frankenphp.dev/docs/extensions/#writing-the-extension), or from any Go logic such as a cron scheduler, an event listener (MQTT, Kafka), or a any other goroutine.
Once the worker pool is active, you can dispatch tasks to it. This can be done inside [native functions exported to PHP](https://frankenphp.dev/docs/extensions/#writing-the-extension), or from any Go logic such as a cron scheduler, an event listener (MQTT, Kafka), or any other goroutine.

### Headless Mode : `SendMessage`

Use `SendMessage` to pass raw data directly to your worker script. This is ideal for queues or simple commands.

#### Example: An Async Queue Extension
#### Async Queue Extension Example

```go
// FrankenPHP extension: dispatch raw messages to a worker via SendMessage
// #include <Zend/zend_types.h>
import "C"
import (
Expand Down Expand Up @@ -83,6 +90,7 @@ func my_queue_push(data *C.zval) bool {
Use `SendRequest` if your extension needs to invoke a PHP script that expects a standard web environment (populating `$_SERVER`, `$_GET`, etc.).

```go
// FrankenPHP extension: invoke a worker PHP script via SendRequest (HTTP emulation)
// #include <Zend/zend_types.h>
import "C"
import (
Expand All @@ -109,13 +117,13 @@ func my_worker_http_request(path *C.zend_string) unsafe.Pointer {
}
```

## Worker Script
## FrankenPHP Extension Worker PHP Script

The PHP worker script runs in a loop and can handle both raw messages and HTTP requests.

```php
<?php
// Handle both raw messages and HTTP requests in the same loop
// FrankenPHP extension worker script: handles raw messages and HTTP requests
$handler = function ($payload = null) {
// Case 1: Message Mode
if ($payload !== null) {
Expand All @@ -131,7 +139,7 @@ while (frankenphp_handle_request($handler)) {
}
```

## Lifecycle Hooks
## FrankenPHP Extension Worker Lifecycle Hooks

FrankenPHP provides hooks to execute Go code at specific points in the lifecycle.

Expand All @@ -142,9 +150,10 @@ FrankenPHP provides hooks to execute Go code at specific points in the lifecycle
| **Thread** | `WithWorkerOnReady` | `func(threadID int)` | Per-thread setup. Called when a thread starts. Receives the Thread ID. |
| **Thread** | `WithWorkerOnShutdown` | `func(threadID int)` | Per-thread cleanup. Receives the Thread ID. |

### Example
### Lifecycle Hooks Example

```go
// FrankenPHP extension worker with lifecycle hooks
package myextension

import (
Expand Down
Loading
Loading