PHP

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
claude · run-zero-examples/php-laravel

> 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

The session that created the live demo, with the real MCP tools.
How it works

Live in five steps.

Each step fixes an error we hit while testing.

  1. 01

    Set web root and server

    project.toml sets BP_PHP_SERVER=nginx and BP_PHP_WEB_DIR=public. Values from run-zero.yaml reach the runtime, not the build.

  2. 02

    Route everything to index.php

    Without this file, nginx answers /api/health with a 404 because there is no such file.

    .nginx.conf.d/laravel-server.conf
    location / {    try_files $uri $uri/ /index.php?$query_string;}
  3. 03

    Load the extensions

    Without this file, openssl is missing in PHP-FPM and every page ends in a 500.

    .php.ini.d/laravel.ini
    extension=openssl.soextension=mbstring.so
  4. 04

    Move writable paths to /tmp

    bootstrap/cache is 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
  5. 05

    Create an account, deploy, set APP_KEY

    Connect your agent, sign in with /mcp and Authenticate, then ask it to deploy.

    • Afterwards set APP_KEY as a secret of the web service, in the dashboard or with runzero_set_secrets.
    • Generate the value locally with php artisan key:generate --show.
    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.

Files

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.

Example on GitHub(opens in a new tab)
php-laravel/project.toml
# 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.

Example on GitHub(opens in a new tab)
php-laravel/.nginx.conf.d/laravel-server.conf
# 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.

Example on GitHub(opens in a new tab)
php-laravel/.php.ini.d/laravel.ini
; Extensions Laravel needs at runtime. The Paketo PHP buildpack loads every .ini in this folder.extension=openssl.soextension=mbstring.so

One page and one JSON route.

Example on GitHub(opens in a new tab)
php-laravel/routes/web.php
<?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',]));
Limits

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 pricing
  • No 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:, storage does 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.php decides, the example got 8.5. Releases with a known vulnerability do not go live.

Operations

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_URL arrives 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.

More guides

All guides

Your code. Live on run.zero.

One website is free, no credit card. Apps with a server, a database and a custom domain come with the Developer plan.