Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
9 changes: 7 additions & 2 deletions docs/compile.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Compile From Sources
---
title: Compile FrankenPHP from Sources with libphp.so
description: Build FrankenPHP from source on Linux, macOS and FreeBSD, linking PHP as a shared library via xcaddy or go build, and add custom Caddy modules and extensions.
---

# Compile from Sources

This document explains how to create a FrankenPHP binary that will load PHP as a dynamic library.
This is the recommended method.
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
21 changes: 12 additions & 9 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 @@ -48,7 +53,7 @@ RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
RUN cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini
```

## RPM and Debian packages
## RPM and Debian Packages

FrankenPHP:

Expand All @@ -60,7 +65,7 @@ PHP:
- `php.ini`: `/etc/php-zts/php.ini` (a `php.ini` file with production presets is provided by default)
- additional configuration files: `/etc/php-zts/conf.d/*.ini`

## Static binary
## Static Binary

FrankenPHP:

Expand Down Expand Up @@ -243,7 +248,7 @@ where the FrankenPHP process was started. You can instead also specify one or mo

The file watcher is based on [e-dant/watcher](https://github.com/e-dant/watcher).

## Matching the Worker To a Path
## Matching the Worker to a Path

In traditional PHP applications, scripts are always placed in the public directory.
This is also true for worker scripts, which are treated like any other PHP script.
Expand All @@ -266,7 +271,7 @@ and otherwise forward the request to the worker matching the path pattern.
}
```

## Restarting Threads After a Number of Requests (Experimental)
## Restarting Threads after a Number of Requests (Experimental)

FrankenPHP can automatically restart PHP threads after they have handled a given number of requests.
When a thread reaches the limit, it is fully restarted,
Expand Down Expand Up @@ -298,11 +303,11 @@ 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 Config

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.
When set, PHP will load all the file with the `.ini` extension present in the given directories.
When set, PHP will load all the files with the `.ini` extension present in the given directories.

You can also change the PHP configuration using the `php_ini` directive in the `Caddyfile`:

Expand All @@ -323,7 +328,7 @@ You can also change the PHP configuration using the `php_ini` directive in the `

### Disabling HTTPS

By default, FrankenPHP will automatically enable HTTPS using for all the hostnames, including `localhost`.
By default, FrankenPHP will automatically enable HTTPS for all the hostnames, including `localhost`.
If you want to disable HTTPS (for example in a development environment), you can set the `SERVER_NAME` environment variable to `http://` or `:80`:

Alternatively, you can use all other methods described in the [Caddy documentation](https://caddyserver.com/docs/automatic-https#activation).
Expand Down Expand Up @@ -441,5 +446,3 @@ Add-Content -Path $PROFILE -Value '. (Join-Path (Split-Path $PROFILE) "frankenph
```

You will need to start a new shell for this setup to take effect.

You will need to start a new shell for this setup to take effect.
17 changes: 11 additions & 6 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 @@ -82,7 +87,7 @@ RUN CGO_ENABLED=1 \

FROM dunglas/frankenphp AS runner

# Replace the official binary by the one contained your custom modules
# Replace the official binary with the one containing your custom modules
COPY --from=builder /usr/local/bin/frankenphp /usr/local/bin/frankenphp
```

Expand Down Expand Up @@ -149,7 +154,7 @@ volumes:

## Running as a Non-Root User

FrankenPHP can run as non-root user in Docker.
FrankenPHP can run as a non-root user in Docker.

Here is a sample `Dockerfile` doing this:

Expand All @@ -170,7 +175,7 @@ EOF
USER ${USER}
```

### Running With No Capabilities
### Running with No Capabilities

Even when running rootless, FrankenPHP needs the `CAP_NET_BIND_SERVICE` capability to bind the
web server on privileged ports (80 and 443).
Expand Down Expand Up @@ -198,7 +203,7 @@ 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:

Expand Down
5 changes: 5 additions & 0 deletions docs/early-hints.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
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/).
Expand Down
14 changes: 10 additions & 4 deletions docs/embed.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# PHP Apps As Standalone Binaries
---
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 Down Expand Up @@ -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 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 @@ -132,11 +138,11 @@ If the `composer.json` file doesn't exist, the default extensions are built, as

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

## Customizing The Build
## Customizing the Build

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

## Distributing The Binary
## Distributing the Binary

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

Expand Down
23 changes: 16 additions & 7 deletions docs/extension-workers.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
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.
Expand All @@ -9,6 +14,7 @@ Extension Workers enable your [FrankenPHP extension](https://frankenphp.dev/docs
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 @@ -33,25 +39,26 @@ func init() {
}
```

### In a Caddy Module (Configurable by the user)
### 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

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`
### 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 All @@ -78,11 +85,12 @@ func my_queue_push(data *C.zval) bool {
}
```

### HTTP Emulation :`SendRequest`
### HTTP Emulation: `SendRequest`

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 Down Expand Up @@ -115,7 +123,7 @@ The PHP worker script runs in a loop and can handle both raw messages and HTTP r

```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 Down Expand Up @@ -145,6 +153,7 @@ FrankenPHP provides hooks to execute Go code at specific points in the lifecycle
### Example

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

import (
Expand Down
Loading
Loading