Language Frankfurt, Germany

Deploy PHP on Nodion

Nodion recognizes a PHP app by its composer.json. The PHP buildpack installs your dependencies with Composer and serves the app with FrankenPHP from public/; if you prefer, php-fpm runs behind nginx or Apache instead. The app runs in Frankfurt, next to a managed MySQL or PostgreSQL database if you need one.

Deploy to Nodion ›

from 1 EUR / month

Up to 15 € credit when signing up

Detected by
composer.json in the base directory
Web server
FrankenPHP (default), nginx or Apache with php-fpm
PHP
8.2 to 8.5, default 8.3
Region
EU Central (Frankfurt)

Deploy PHP step by step

  1. Add composer.json and commit composer.lock Nodion detects PHP by composer.json. A repository with only an index.php is not detected; if you have no composer.json yet, a small one like this is enough. The build runs composer install --no-dev --optimize-autoloader, so everything the app needs at runtime belongs in require, not require-dev. Commit composer.lock so the build installs the versions you tested. composer.json
    {
      "require": {
        "php": "8.4.*"
      }
    }
  2. Keep public files in public/ FrankenPHP uses public/ as the document root. Without it, Nodion takes web/, and without both, the repository root. Put index.php and your assets into public/ and keep vendor/, configuration and source code next to it, so only files meant for the web are served.
    composer.json
    composer.lock
    src/
    public/
      index.php
  3. Choose the web server FrankenPHP is the default and needs no setup. For php-fpm behind nginx or Apache httpd, add BP_PHP_SERVER with the value nginx or apache on the Environment tab and tick Build. Apache also reads your .htaccess files. Any other value fails the build.
  4. Create the app and attach a database In the dashboard, create an application from your GitHub, GitLab, Bitbucket or Gitea repository, pick the branch and the region EU Central, and keep the build strategy on Buildpacks. Then create a MySQL or PostgreSQL database in the same region and attach it on the Environment tab: the app gets DATABASE_URL on the next deploy, at runtime only. Mark passwords and API keys as secret.
  5. Run migrations on every deploy A release: line in a Procfile runs once per build, after the build and before the new version starts. If it fails, the deploy stops and the running version stays live. Keep the migration tool, for example Doctrine Migrations or Phinx, in require. Procfile
    release: vendor/bin/doctrine-migrations migrate --no-interaction

Good to know

  • Pin the PHP versionNodion reads .php-version first, then require.php in composer.json; without either you get PHP 8.3. A range picks the newest matching release, so "^8.2" gets PHP 8.5. To stay on one line, write 8.3 into .php-version or require "8.3.*".
  • SymfonyNodion recognizes Symfony by bin/console plus symfony.lock, runs bin/console cache:warmup --env=prod during the build and sets APP_ENV=prod and APP_DEBUG=0 at runtime. Add APP_ENV=prod with the Build flag as well, so the Composer scripts that run during the install do not use dev from your .env. Nodion does not run asset-map:compile; with AssetMapper, add it to the auto-scripts in composer.json. For Encore or Vite builds, use a Dockerfile.
  • WorkersFor a queue worker, add a line such as worker: php bin/worker.php to the Procfile together with an explicit web: line, because without one the first Procfile entry other than release: becomes the default command. The build log shows the default start command; for FrankenPHP, web: frankenphp php-server --listen :$PORT --root public/ works. Then add a process named worker without a port on the Processes tab.
  • Health check pathTraffic moves to a new release once / answers with 2xx or 3xx. If / answers 401 or 404, set a health check path that returns 200 in the app settings.

What Nodion runs for you

  • Deploys without downtime Push to your branch and Nodion builds a new release. Traffic switches once the new instances answer their health check; a failed release leaves the running one in place. Apps with a local volume restart instead, because the disk belongs to one instance.
  • Databases next to the app Managed PostgreSQL, pgvector, MySQL, Valkey and ClickHouse in the same region. Attached databases arrive as DATABASE_URL, REDIS_URL or CLICKHOUSE_URL.
  • Previews per pull request Turn on previews and pull requests from your repository get their own app with its own URL and fresh, empty databases, created automatically or by hand. Forks and bot pull requests are skipped.
  • Workers, cron jobs and scaling Run workers as extra processes of the same app, schedule jobs on the Cron tab, and scale every process to up to 16 instances.
  • Release step With buildpacks, a Procfile release: line runs with every new build. Dockerfile apps, and redeploys or rollbacks to an earlier image, use a release command set on the app itself, which also takes precedence over the Procfile line. On static sites a release step runs in an image that holds only the built files.
  • Logs and metrics Build, release and runtime logs plus CPU, memory, disk and network metrics for every instance in the dashboard.
  • Domains and HTTPS A default hostname with HTTPS from the first deploy; your own domains get certificates automatically.

Further reading

PHP on Nodion: questions and answers

Do I need a composer.json for a plain PHP site?

Yes. Nodion detects PHP only by composer.json; a file that requires nothing but PHP is enough. Put the PHP files you want to serve into public/.

Can I use nginx or Apache instead of FrankenPHP?

Yes. Set BP_PHP_SERVER=nginx or BP_PHP_SERVER=apache as a Build variable and Nodion runs php-fpm behind nginx or Apache httpd. Without the variable, FrankenPHP serves the app.

Which PHP versions can I use?

PHP 8.2, 8.3, 8.4 and 8.5, with 8.3 as the default. Pin one in .php-version or composer.json. If you ask for a version Nodion no longer offers, the build fails with a clear message instead of switching silently.

Do I need a Dockerfile for PHP?

No. The PHP buildpack installs PHP, Composer and the web server for you. If your repository has a Dockerfile, the create form picks that strategy and Nodion builds the Dockerfile instead.

Where does my PHP app run?

In the EU Central region in Frankfurt, Germany. Build, registry, the app and its databases, volumes, buckets, logs and metrics stay in that region, and Nodion's API and control plane are hosted in Germany. Nodion GmbH is based in Stuttgart.

Can I use PHP in line with the GDPR?

Nodion provides the basis for it: Nodion GmbH is based in Stuttgart, Germany, in the Frankfurt region the app, its databases and volumes run in Germany, and you conclude the data processing agreement (DPA) under Art. 28 GDPR electronically in the dashboard. Whether your setup complies also depends on how you configure and use the app.

How much does it cost to run PHP on Nodion?

An app instance starts at 1 EUR per month. The setup in the cost box costs 2 EUR per month: App 2 EUR. Prices are net and billed per second, and you pick bigger sizes or more instances whenever you need them.

Can I use my own domain for my PHP app?

Yes. Every app gets a default hostname with HTTPS. Add your own domain on the app's Domains tab; the TLS certificate is issued and renewed automatically.

Give your agent a cloud.

Earn up to 15 € in credit when signing up.

Continue with GitHub

or with email

Stay in the loop.

Product news, no spam. Unsubscribe anytime.