Deploy a Laravel app.
The PHP buildpack detects composer.json, installs your packages and serves public with nginx and PHP-FPM. On top come a few config files and APP_KEY as a secret.
Not suited to Laravel with a database today: the build image lacks libpq, pdo_pgsql does not load, and PHP cannot use the Postgres addon.
Needs the Developer plan, the free plan only covers websites. Pricing · Check the limits first
- Laravel 13 on PHP 8.5 tested
- nginx and PHP-FPM
- Composer at build time
> Deploy the php-laravel folder to run.zero.
runzero_create_appdoneexample-laravel
runzero_push_filesdoneone commit
runzero_deploydoneservices created
runzero_set_secretsdoneAPP_KEY
runzero_wait_for_builddonelive
live at https://web-example-laravel-8c606360.run-zero.de
- Live demoRunning on run.zero(opens in a new tab)
- Example codeMIT, on GitHub(opens in a new tab)
- BuildpacksNode, Python, Go, PHP, Java
- Hosted in GermanyHetzner, Nuremberg
Live in five steps.
Each step fixes an error we hit while testing.
- 01
Set web root and server
project.tomlsetsBP_PHP_SERVER=nginxandBP_PHP_WEB_DIR=public. Values fromrun-zero.yamlreach the runtime, not the build. - 02
Route everything to index.php
Without this file, nginx answers
/api/healthwith a 404 because there is no such file..nginx.conf.d/laravel-server.conf location / { try_files $uri $uri/ /index.php?$query_string;} - 03
Load the extensions
Without this file,
opensslis missing in PHP-FPM and every page ends in a 500..php.ini.d/laravel.ini extension=openssl.soextension=mbstring.so - 04
Move writable paths to /tmp
bootstrap/cacheis read-only at runtime. Caches and compiled views go to/tmp.run-zero.yaml version: "1"services: web: port: 8080 env: APP_ENV: production APP_DEBUG: "false" LOG_CHANNEL: stderr SESSION_DRIVER: cookie CACHE_STORE: array VIEW_COMPILED_PATH: /tmp APP_SERVICES_CACHE: /tmp/services.php APP_PACKAGES_CACHE: /tmp/packages.php - 05
Connect Claude Code claude mcp add --transport http \ -s user run-zero \ https://api.run-zero.de/mcp \ --client-id runzero-cli \ --callback-port 53761
After 1 to 3 minutes the app is live at https://web-<app>.run-zero.de. Check a route of your app, in the example /api/health. If the build is red, runzero_get_build_logs tells you why.
What makes Laravel ready.
The config from the steps and one sample route. The rest is the Laravel skeleton.
Tells the buildpack at build time: nginx as server, public as web root.
# Build settings for the Paketo PHP buildpack: nginx plus PHP-FPM, Laravel's public/ as web root.[_]schema-version = "0.2"[[io.buildpacks.build.env]]name = "BP_PHP_SERVER"value = "nginx"[[io.buildpacks.build.env]]name = "BP_PHP_WEB_DIR"value = "public"Sends every route that is not a file to index.php.
# Included into the server block of the Paketo nginx config: send every route that is not a file to Laravel.location / { try_files $uri $uri/ /index.php?$query_string;}Loads openssl and mbstring for PHP-FPM.
; Extensions Laravel needs at runtime. The Paketo PHP buildpack loads every .ini in this folder.extension=openssl.soextension=mbstring.soOne page and one JSON route.
Example on GitHub(opens in a new tab)<?phpuse Illuminate\Support\Facades\Route;// One page and one JSON route that prove PHP and Laravel run on run.zero.Route::get('/', fn () => view('run-zero', [ 'php' => PHP_VERSION, 'laravel' => app()->version(),]));Route::get('/api/health', fn () => response()->json([ 'status' => 'ok', 'runtime' => 'php '.PHP_VERSION, 'laravel' => app()->version(), 'platform' => 'run.zero',]));What does not work today.
Honest, before you commit.
Needs the Developer plan
Free has no server apps and no Postgres, a deploy stops with an error.
See pricingNo Postgres from PHP
The build image lacks
libpq. Use Postgres from a Node or Python service, not from Laravel.No persistent storage folder
Without
volumes:,storagedoes not survive a restart, and Laravel with a volume is untested. Keep sessions in a cookie and logs on stderr.PHP version from composer.json
require.phpdecides, the example got 8.5. Releases with a known vulnerability do not go live.
What you stop doing yourself.
Builds, HTTPS, the database and backups run on the platform.
Data stays in Germany
Servers and backups at Hetzner in Nuremberg. With a data processing agreement.
HTTPS by default
Every service gets an address on
run-zero.de, custom domains a Let’s Encrypt certificate.Postgres as an addon
One entry in
run-zero.yaml,DATABASE_URLarrives as an environment variable.No lock-in
Your code stays in your repo, the database is a dump you can download.
Questions.
About PHP and Laravel.
Can Laravel use the Postgres addon?
Not today. The build image lacks libpq, so pdo_pgsql does not load and the build stops.
Does plain PHP work without Laravel?
The buildpack detects composer.json, and according to its docs it serves the htdocs folder without project.toml. We only tested Laravel.
Why not put APP_KEY in run-zero.yaml?
run-zero.yaml lives in the repo. Secret values belong in the service’s secrets, which the platform sets as environment variables.
Do queue workers run?
We have not tested that, the example only shows the web process.