FrankenPHP application runtime
Overview
FrankenPHP is a fast and modern server for PHP developed by Kevin Dunglas built on top of the Caddy web server. It’s a seamless drop-in replacement for PHP-FPM or Apache with mod_php, designed to enhance your PHP applications with advanced capabilities.
It comes with many extensions and features such as early hints (HTTP 103), real-time capabilities with its built-in Mercure hub. FrankenPHP can also make your Laravel and Symfony projects faster than ever through their official integrations with the worker mode. Deploying PHP applications with FrankenPHP on Clever Cloud is straightforward and requires no complex configuration, nor Docker container.
FrankenPHP is a new runtime
Help us to improve it by reporting any issue or suggestion on the Clever Cloud Community
Create your FrankenPHP application
To create a new FrankenPHP application, use the Clever Cloud Console or Clever Tools:
clever create --type frankenphpFrankenPHP applications can’t be deployed on a pico instance, XS is the default instance type
Configure your FrankenPHP application
Mandatory needs
FrankenPHP runtime only requires a working web application, with an index.php or index.html file. If you need to serve files from a specific directory, set the CC_WEBROOT environment variable, relative to the root of your project (default: /).
FrankenPHP version and tools
FrankenPHP currently deployed version on Clever Cloud is 1.13.1 based on PHP 8.5.12 and Caddy server 2.11.7. Virtual machine image includes multiple tools from the PHP ecosystem such as Composer or Symfony CLI. The php command available in hooks and scripts uses frankenphp php-cli under the hood.
FrankenPHP uses this version whatever the value of CC_PHP_VERSION.
Composer native support
If a composer.json file is detected at the root of your project, it will be used to install dependencies during building phase with --no-interaction --no-progress --no-scripts --no-dev flags. To override the base flags (--no-interaction --no-progress --no-scripts), set the CC_PHP_COMPOSER_FLAGS environment variable.
To install development dependencies, set the CC_PHP_DEV_DEPENDENCIES environment variable to install. This removes the --no-dev flag independently of CC_PHP_COMPOSER_FLAGS.
Use a local Composer version
If you put a composer.phar file at the root of your project, it will be used to install dependencies.
Private Composer repositories
Composer can authenticate with private package repositories through the COMPOSER_AUTH environment variable. Its value is a JSON object containing Composer authentication settings, such as HTTP Basic, OAuth or an access token.
For example, to use Private Packagist, add its repository to your composer.json, replacing ORGANISATION with its short name:
{
"repositories": [
{
"type": "composer",
"url": "https://repo.packagist.com/ORGANISATION"
},
{
"packagist.org": false
}
]
}Then define COMPOSER_AUTH for your application with the username and token provided by Private Packagist:
{
"http-basic": {
"repo.packagist.com": {
"username": "PACKAGIST_USERNAME",
"password": "PACKAGIST_TOKEN"
}
}
}Composer reads this variable automatically during composer install. Never commit credentials to your repository. If you use a local auth.json file, add it to .gitignore. See the Composer authentication documentation for other providers and authentication methods. For a private Git repository accessed over SSH, configure a private SSH key instead.
Custom PHP configuration
To load your own PHP configuration directives, put a php.ini file at the root of your project. FrankenPHP will automatically use it.
FrankenPHP and Materia KV
Materia KV is Clever Cloud’s distributed serverless key-value store based on FoundationDB, compatible with existing ecosystems such as Redis®, with TTL for sessions support and JSON commands.
To manage Materia KV data with FrankenPHP, use the included redis extension in your PHP code and configure it with your add-on URL, port and token as password. For now, you need to use the tcp mode and 6378 port.
Worker mode
With FrankenPHP worker mode, a script of your project is kept in memory to handle incoming requests in a few milliseconds. Define the path to this script, relative to the root of your project, with the CC_FRANKENPHP_WORKER environment variable (e.g. /public/worker.php). The worker script must be located within the webroot directory. It’s supported by design by Laravel Octane and Symfony Runtime projects.
- Learn more about FrankenPHP worker mode
- Learn more about Laravel Octane
- Learn more about Symfony Runtime
Configurable port
By default, FrankenPHP listens on port 8080. If you want to change it, set the CC_FRANKENPHP_PORT environment variable to your desired port. This is useful if you want to run a service in front of FrankenPHP, such as Redirection.io for example.
Custom FrankenPHP run command
To override the default server behavior, set the CC_RUN_COMMAND environment variable. When defined, it completely replaces the default frankenphp php-server command. Use it to define flags such as --debug, --mercure or --no-compress:
CC_RUN_COMMAND="frankenphp php-server --listen 0.0.0.0:8080 --debug --mercure"You can also use it to load a custom Caddyfile:
CC_RUN_COMMAND="frankenphp run --config /path/to/Caddyfile"Use FrankenPHP to execute PHP scripts as Clever Tasks
FrankenPHP can be used to execute PHP scripts. On Clever Cloud, to run such workloads as Clever Tasks, configure an application as Tasks from the Information panel in the Console or with Clever Tools:
clever create --type frankenphp --task "frankenphp php-cli path/to/task.php"
clever deploy # or clever restart if there is no code changeIncluded extensions
FrankenPHP on Clever Cloud comes with a set included PHP extensions: amqp,apcu,ast,bcmath,brotli,bz2,calendar,ctype,curl,dba,deepclone,dom,exif,fileinfo,filter,ftp,gd,gettext,gmp,iconv,igbinary,imagick,intl,ldap,lz4,mbregex,mbstring,memcached,mysqli,mysqlnd,opcache,openssl,parallel,password-argon2,pcntl,pdo,pdo_mysql,pdo_pgsql,pdo_sqlite,pgsql,phar,posix,protobuf,readline,redis,session,shmop,simplexml,soap,sockets,sodium,sqlite3,ssh2,sysvmsg,sysvsem,sysvshm,tidy,tokenizer,xlswriter,xml,xmlreader,xmlwriter,xsl,xz,yaml,zip,zlib,zstd
Enable health check during deployment
The healthcheck allows you to limit downtimes. Indeed, you can provide Clever Cloud with paths to check. If these paths don’t return a 2xx response code, the deployment fails.
Add one (or several) environment variable as such:
CC_HEALTH_CHECK_PATH=/my/awesome/pathOr
CC_HEALTH_CHECK_PATH_0=/my/awesome/path
CC_HEALTH_CHECK_PATH_1=/my/other/pathThe deployment process checks all paths. All of them must reply with a 2xx response code, such as 200 OK or 204 No Content. Clever Cloud retries with an increasing delay before it marks the deployment as failed, so an application that needs some time to start isn’t rejected on the first attempt.
When no health check path is configured, Clever Cloud requests the root path / and accepts any response code from 200 to 499: a 404 or a 401 means your application is up and answering. For Java applications, the deploy.pingPaths of the clevercloud/*.json file also count as configured paths.
Before any HTTP request, Clever Cloud checks that a service listens on the public port, 8080, on a public interface. Depending on your configuration, it’s your application, the port Docker maps from CC_DOCKER_EXPOSED_HTTP_PORT, or the first Request Flow middleware. A service on this port bound only to localhost or 127.0.0.1 makes the deployment fail with Your application is listening on localhost instead of publicly: listen on 0.0.0.0 instead.
On runtimes supporting Request Flow, when middleware runs in front of your application, Clever Cloud also checks that each middleware port and your application port are listening. With CC_REQUEST_FLOW="block", Clever Cloud only checks the service answering on the public port, not your application.
Example
With the preceding paths, here are the logs of a failing health check:
Checking public port (8080) is listening as expected
Response from GET /my/awesome/path is 200 (within expected range 200...300)
Response from GET /my/other/path is 500, expected 200...300
Error while checking /my/awesome/path, /my/other/pathIn this example, the first path is OK, but the second one failed. This gives you a hint on what failed in your application.
Best practice for healthcheck endpoints
To make the most of a healthcheck endpoint, have it check your critical dependencies. For example:
- execute
SELECT 1 + 1;on your database - retrieve a specific Cellar file
- ping a specific IP through a VPN
Request Flow: Varnish, Redirection.io, OAuth2 Proxy, custom proxy
Request Flow automatically chains reverse proxies between port 8080 (public) and your application, allocating middleware ports automatically. Some services are detected from your configuration, while others must be listed explicitly in CC_REQUEST_FLOW:
- Otoroshi Challenge: set
OTOROSHI_CHALLENGE_SECRET - Varnish: add a
clevercloud/varnish.vclfile or setCC_VARNISH_FILE - Redirection.io: set
CC_REDIRECTIONIO_PROJECT_KEY - OAuth2 Proxy: set
CC_REQUEST_FLOW=oauth2-proxyand itsOAUTH2_PROXY_*settings
Multiple services can run simultaneously. Setting CC_REQUEST_FLOW replaces automatic detection, so list every service you need in order (e.g. oauth2-proxy,varnish). To add a custom middleware, include custom in the chain and define CC_REQUEST_FLOW_CUSTOM with @@LISTEN_PORT@@ and @@FORWARD_PORT@@ placeholders. To block public access, set CC_REQUEST_FLOW=block.
If your application manages its own HTTP server, configure it to listen on port 9000 instead of 8080 when at least one middleware is active. Clever Cloud handles this automatically for runtimes with a managed web server.