Language Frankfurt, Germany
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.
composer.json in the base directorycomposer.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.*"
}
} 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 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. DATABASE_URL on the next deploy, at runtime only. Mark passwords and API keys as secret. 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 .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.*".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.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./ answers with 2xx or 3xx. If / answers 401 or 404, set a health check path that returns 200 in the app settings.DATABASE_URL, REDIS_URL or CLICKHOUSE_URL. 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. 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/.
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.
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.
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.
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.
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.
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.
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.
Earn up to 15 € in credit when signing up.
or with email
Product news, no spam. Unsubscribe anytime.
Successfully subscribed.