Cloud Foundry PHP Buildpack
Join us on Slack
A buildpack to deploy PHP applications to Cloud Foundry based systems, such as a cloud provider or your own instance.
Buildpack User Documentation
Official buildpack documentation can be found here: php buildpack docs.
Developer Documentation:
- docs/ - Architecture and implementation guides
Building the Buildpack
To build this buildpack, run the following commands from the buildpack's directory:
-
Source the .envrc file in the buildpack directory.
source .envrc
To simplify the process in the future, install direnv which will automatically source .envrc when you change directories.
-
Install buildpack-packager
go install github.com/cloudfoundry/libbuildpack/packager/buildpack-packager@latest
-
Build the buildpack
buildpack-packager build [ --cached ]
Alternatively, use the package script:
./scripts/package.sh [ --cached ]
-
Use in Cloud Foundry
Upload the buildpack to your Cloud Foundry and optionally specify it by name
cf create-buildpack [BUILDPACK_NAME] [BUILDPACK_ZIP_FILE_PATH] 1
cf push my_app [-b BUILDPACK_NAME]
Contributing
Find our guidelines here.
Testing
Buildpacks use the Switchblade framework for running integration tests against Cloud Foundry. Before running the integration tests, you need to login to your Cloud Foundry using the cf cli:
cf login -a https://api.your-cf.com -u name@example.com -p pa55woRD
Note that your user requires permissions to run cf create-buildpack and cf update-buildpack. To run the integration tests, run the following commands from the buildpack's directory:
-
Source the .envrc file in the buildpack directory.
source .envrc
To simplify the process in the future, install direnv which will automatically source .envrc when you change directories.
-
Run unit tests
./scripts/unit.sh
-
Run integration tests
./scripts/integration.sh
More information can be found on Github switchblade.
Project Structure
The project is broken down into the following directories:
bin/ - Executable shell scripts for buildpack lifecycle: detect, supply, finalize, release, start
src/php/ - Go source code for the buildpack
detect/ - Detection logic
supply/ - Dependency installation (PHP, HTTPD, Nginx)
finalize/ - Final configuration and setup
release/ - Release information
extensions/ - Extension system (composer, newrelic, appdynamics, sessions)
config/ - Configuration management
options/ - Options parsing
hooks/ - Lifecycle hooks (dynatrace integration)
integration/ - Integration tests
unit/ - Unit tests
defaults/ - Default configuration files
fixtures/ - Test fixtures and sample applications
scripts/ - Build and test scripts
Understanding the Buildpack
This buildpack uses Cloud Foundry's libbuildpack framework and is written in Go. The buildpack lifecycle consists of:
Build-Time Phases
-
Detect (bin/detect → src/php/detect/) - Determines if the buildpack should be used by checking for PHP files or composer.json
-
Supply (bin/supply → src/php/supply/) - Installs dependencies:
- Downloads and installs PHP
- Downloads and installs web server (HTTPD or Nginx)
- Runs extensions in "configure" and "compile" phases
- Installs PHP extensions
- Runs Composer to install application dependencies
-
Finalize (bin/finalize → src/php/finalize/) - Final configuration:
- Configures web server (HTTPD or Nginx)
- Sets up PHP and PHP-FPM configuration
- Copies start binary to
.bp/bin/
- Processes configuration files to replace build-time placeholders with runtime values
- Generates preprocess scripts that will run at startup
- Prepares runtime environment
-
Release (bin/release → src/php/release/) - Provides process types and metadata
Runtime Phases
- Start (
bin/start → src/php/start/cli/) - Process management:
- Runs preprocess commands
- Handles dynamic runtime variables (PORT, TMPDIR) via sed replacement
- Launches all configured services (PHP-FPM, web server, etc.) from
.procs file
- Monitors all processes
- If any process exits, terminates all others and restarts the application
Configuration Placeholders
The buildpack uses a two-tier placeholder system for configuration files:
Build-Time Placeholders (@{VAR})
These placeholders are replaced during the finalize phase (staging/build time) with known values:
@{HOME} - Replaced with dependency or app directory path
@{DEPS_DIR} - Replaced with /home/vcap/deps
@{WEBDIR} - Replaced with web document root (default: htdocs)
@{LIBDIR} - Replaced with library directory (default: lib)
@{PHP_FPM_LISTEN} - Replaced with PHP-FPM socket/TCP address
@{TMPDIR} - Converted to ${TMPDIR} for runtime expansion
@{PHP_EXTENSIONS} - Replaced with extension directives
@{ZEND_EXTENSIONS} - Replaced with Zend extension directives
@{PHP_FPM_CONF_INCLUDE} - Replaced with fpm.d include directive
Example (php.ini):
; Before finalize:
extension_dir = "@{HOME}/php/lib/php/extensions"
include_path = "@{HOME}/@{LIBDIR}"
; After finalize:
extension_dir = "/home/vcap/deps/0/php/lib/php/extensions"
include_path = "/home/vcap/deps/0/lib"
Runtime Variables (${VAR})
These are standard environment variables expanded at runtime:
${PORT} - HTTP port assigned by Cloud Foundry (dynamic)
${TMPDIR} - Temporary directory (can be customized)
${HOME} - Application directory
${HTTPD_SERVER_ADMIN} - Apache admin email
Supported by:
- Apache HTTPD - Native variable interpolation for any
${VAR}
- Bash scripts - Standard shell expansion for any
${VAR}
- Nginx/PHP configs - Only
${PORT} and ${TMPDIR} via sed replacement
Example (httpd.conf):
Listen ${PORT} # Expanded by Apache at runtime
ServerRoot "${HOME}/httpd" # Expanded by Apache at runtime
DocumentRoot "${HOME}/htdocs" # Expanded by Apache at runtime
Note: Custom placeholders are not supported. To use custom configuration values, either:
- Use environment variables with
${VAR} syntax (works with Apache/bash)
- Set values directly in your code instead of using placeholders
Extensions
The buildpack includes several built-in extensions written in Go:
Extension Architecture
Extensions implement the Extension interface defined in src/php/extensions/extension.go:
type Extension interface {
Name() string
ShouldCompile(ctx *Context) (bool, error)
Configure(ctx *Context) error
Compile(installer Installer) error
PreprocessCommands(ctx *Context) ([]string, error)
ServiceCommands(ctx *Context) (map[string]string, error)
ServiceEnvironment(ctx *Context) (map[string]string, error)
}
Extension Lifecycle:
- Configure - Called early to modify buildpack configuration (e.g., set PHP version, add extensions)
- Compile - Main extension logic, downloads and installs components
- ServiceEnvironment - Contributes environment variables
- ServiceCommands - Contributes long-running services
- PreprocessCommands - Contributes commands to run before services start
For examples, see the built-in extensions in src/php/extensions/.
User Extensions
The buildpack supports user-defined extensions through the .extensions/ directory. This allows you to add custom startup commands, environment variables, and services without modifying the buildpack itself.
Creating a User Extension
Create a directory .extensions/<name>/ in your application with an extension.json file:
myapp/
├── .extensions/
│ └── myext/
│ └── extension.json
├── index.php
└── .bp-config/
└── options.json
{
"name": "my-custom-extension",
"preprocess_commands": [
"echo 'Running setup'",
["./bin/setup.sh", "arg1", "arg2"]
],
"service_commands": {
"worker": "php worker.php --daemon"
},
"service_environment": {
"MY_VAR": "my_value",
"ANOTHER_VAR": "another_value"
}
}
Fields:
name - Extension identifier (defaults to directory name)
preprocess_commands - Commands to run at container startup before PHP-FPM starts. Each command can be a string or array of arguments.
service_commands - Map of long-running background services (name → command)
service_environment - Environment variables to set for services
Additional Configuration Options
ADDITIONAL_PREPROCESS_CMDS
Run custom commands at container startup before PHP-FPM starts. Useful for migrations, cache warming, or other initialization tasks.
Configuration (.bp-config/options.json):
{
"ADDITIONAL_PREPROCESS_CMDS": [
"php artisan migrate --force",
"php artisan config:cache",
["./bin/setup.sh", "arg1", "arg2"]
]
}
Commands can be:
- A string:
"echo hello" - runs as a single command
- An array:
["script.sh", "arg1"] - arguments joined with spaces
Standalone PHP Mode (APP_START_CMD)
For CLI/worker applications that don't need a web server or PHP-FPM, you can run a PHP script directly.
Configuration (.bp-config/options.json):
{
"WEB_SERVER": "none",
"APP_START_CMD": "worker.php"
}
Auto-detection: If WEB_SERVER is set to "none" and APP_START_CMD is not specified, the buildpack searches for these entry point files:
app.php
main.php
run.php
start.php
If none are found, it defaults to running PHP-FPM only (for custom proxy setups).
Example worker script:
<?php
// worker.php - Long-running background worker
echo "Worker started\n";
while (true) {
// Process jobs from queue
processNextJob();
sleep(1);
}
Note: Standalone apps on Cloud Foundry may need special health check configuration since they don't have an HTTP endpoint.
Help and Support
Join the #buildpacks channel in our Slack community
Reporting Issues
This project is managed through GitHub. If you encounter any issues, bug or problems with the buildpack please open an issue.
Active Development
The project backlog is on Pivotal Tracker