Deploy by framework

PHP

Deploy a PHP application with a managed FrankenPHP container.

Nitroship's generic PHP preset detects composer.json or index.php at the deployment root when a more specific PHP framework has not matched. Laravel, Symfony, and WordPress have their own higher-priority presets.

The generic preset runs your HTTP application with FrankenPHP, a PHP application server. It does not infer another framework's setup commands, migrations, cache directories, or environment-variable conventions.

Deploy

Install the CLI

curl -fsSL https://nitroship.co/install.sh | bash
ntro login

Already installed? Skip ahead. Full options, PATH setup, and updates: Install the CLI.

Choose a compute region and optionally select PHP explicitly:

nitroship.json
{
  "build": {"framework": "php"},
  "compute": {"regions": ["kr-icn"]}
}

Set your application's production environment variables, then deploy:

ntro apps create my-php-app
ntro deploy . --prod

The managed PHP container requires the hosted builder. Remove --local if it is present. A compute region is required because PHP requests run on compute, not as static files.

Document root and output

If your project contains public/, that directory is the document root. Otherwise the deployment root is the document root. Prefer public/ to separate web-facing files from application code, Composer files, and configuration. Review what the web server can expose when using the root; CDN source exclusion does not replace a safe application layout.

When composer.json is present, the builder installs production dependencies with composer install --no-dev. A package.json with a build script also triggers a frontend build with Node 22. FrankenPHP listens on 0.0.0.0:$PORT, with 3000 as the default port.

Files with allowed browser-asset extensions under the document root are copied into /nitroship/static in the generated image and automatically extracted to the CDN. The CDN serves these assets first; dynamic pages and APIs run in the PHP container on compute. No build.outputDirectory setting is needed.

The extension allowlist is .css, .js, .mjs, .html, .txt, .webmanifest, .png, .jpg, .jpeg, .gif, .webp, .avif, .ico, .svg, .woff, .woff2, .ttf, .otf, .eot, .mp4, .webm, and .pdf. PHP files, symlinks, hidden paths, and the document root's vendor/ and node_modules/ are not copied.

The filter also skips directories named app, bootstrap, config, resources, routes, storage, src, templates, tests, test, bin, parts, or patterns; JS/MJS filenames containing config or server; *.blade.html and *.twig.html; and filenames beginning with readme, license, or changelog. When the deployment root is the document root, JS/MJS extraction is further limited to assets/, js/, static/, wp-includes/js/, wp-admin/js/, and wp-content/. This additional JS/MJS path restriction does not apply to a public/ document root.

Extraction filters paths and extensions, not file contents. Keep server source, templates, secrets, and build configuration outside the public document root: a nonpublic file with an allowed extension can otherwise be published to the CDN. This is especially important when the deployment root is also the document root.

PHP and toolchain versions

The preset reads composer.json's require.php first, then falls back to the PHP declaration in .tool-versions. It chooses the nearest supported PHP version in the declared major version, using pinned FrankenPHP bases for PHP 8.2, 8.3, 8.4, or 8.5. Missing or unsupported declarations use the current default, PHP 8.5; a declaration does not install arbitrary image tags or unsupported PHP releases.

The managed image includes common database, GD, intl, and zip extensions and installs declared Composer ext-* requirements as supported by its extension toolchain. If your application needs a different runtime, unsupported extensions, system packages, or custom build/start commands, use your own Dockerfile rather than assuming the generic preset will configure them.

Production configuration and storage

Set the variables your PHP code actually reads through Environment variables. For example, database credentials, application secrets, and a public URL only have an effect if your application consumes them. Disable debug output using your application's production settings. The generic preset does not map environment variables to framework configuration automatically or provision a database.

Use an external database and external session/cache backends when state needs to survive instance replacement or be shared between instances. The generated container runs as a non-root user. Its instance filesystem is ephemeral; use /tmp for temporary writes and configure your application's writable cache, logs, and session paths accordingly. Do not rely on writes to source directories for durable state.

Store uploads in S3 or another object store. Runtime uploads are not part of build-time CDN extraction, and files stored on an instance are not shared or durable.

Operational limits

Nitroship does not automatically run database migrations, queue workers, or schedulers. Run migrations from CI or your local machine with the external database's production credentials. Run background workers separately. For scheduled HTTP work, see Cron jobs.

The preset serves one HTTP application; it does not discover application-specific startup commands or keep a second worker process running for you. Apps requiring a custom web server, filesystem layout, or startup preparation should use their own Dockerfile.

Use your own Dockerfile

Without build.framework, selection starts with the configured build.dockerfile, then Dockerfile.nitroship, then Dockerfile. Next.js comes next, followed by the highest-priority detected managed preset, then generic static output.

build.framework: "php" explicitly selects the generic preset, overriding auto-detection and an automatically discovered Dockerfile. build.framework cannot coexist with build.dockerfile. Remove build.framework to use a custom image and follow the Dockerfile guide.

Laravel · Symfony · WordPress · Environment variables · Cron jobs · Dockerfile deployments

On this page