Deploy by framework

Symfony

Deploy Symfony with a managed FrankenPHP container and CDN assets.

Nitroship detects Symfony when the deployment root contains bin/console and composer.json depends on symfony/framework-bundle. The managed preset generates the container build and starts your HTTP application with FrankenPHP, a PHP application server.

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.

Set a compute region in the console or in nitroship.json. To select the Symfony preset explicitly:

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

Configure production secrets before deploying, then run:

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

Symfony uses a managed container and requires the hosted builder. Remove --local if it is present. A compute region is required for the PHP runtime.

Build and output

The builder installs production dependencies with composer install --no-dev --no-scripts and builds frontend assets with Node 22 when package.json has a build script. Composer auto-scripts and install hooks, including assets:install public, do not run automatically. Put required asset preparation in your frontend build script or use a custom Dockerfile. FrankenPHP serves the application with public/ as the document root, listening on 0.0.0.0:$PORT with a default port of 3000. Symfony's var/ points to /tmp/nitroship/var for writable cache and logs; cache:warmup runs at startup with runtime environment variables available.

Files with allowed browser-asset extensions under public/ are copied into /nitroship/static in the final image and automatically extracted to the CDN. The CDN serves these assets first; dynamic pages and APIs go to Symfony 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.

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.

PHP and toolchain versions

The preset first reads composer.json's require.php, then falls back to a PHP declaration in .tool-versions. Supported PHP versions are 8.2, 8.3, 8.4, and 8.5; the nearest supported version in the declared major version is selected with a pinned FrankenPHP base/toolchain. Missing or unsupported declarations use the current default, PHP 8.5. Unsupported releases and arbitrary image tags are not installed just because a project requests them.

If your project needs extra PHP extensions, system packages, a custom asset pipeline, or a different startup sequence, use your own Dockerfile. The preset does not adapt custom kernel directory overrides or application code for you.

Production environment

Use Environment variables for runtime configuration and secrets. Do not commit a production .env file. The managed build excludes .env files and sets Symfony's APP_RUNTIME_OPTIONS to {"disable_dotenv":true}, so provide required production values as injected environment variables rather than relying on dotenv files in the image.

VariableWhat to set
APP_ENVprod
APP_DEBUG0
APP_SECRETA stable, securely generated application secret.
DATABASE_URLThe external database connection URL, if your application uses it.
DEFAULT_URIYour public HTTPS URL, if your router configuration references this variable.

Set any additional variables referenced by your Symfony configuration, including mail, Redis, and object-storage credentials. Nitroship does not provision those services or rewrite your app's configuration to use a variable it does not read.

Prefer external session and cache backends when state must be shared between instances or survive replacement. Local cache, logs, and file sessions are ephemeral. Store uploads in S3 or another object store rather than under public/, var/, or /tmp.

Operational limits

The generated container runs as a non-root user. The instance filesystem is ephemeral; /tmp is for temporary writes, not durable data. Direct logs to a suitable external destination when you need long-term retention.

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. Symfony Messenger consumers and other background workers need to run separately. For scheduled HTTP work, see Cron jobs; this preset does not start a scheduler process.

Use your own Dockerfile

If build.framework is not set and your project has a Dockerfile, Nitroship uses the Dockerfile before any preset. How Nitroship chooses a build shows the full detection order.

Setting build.framework: "symfony" does the opposite: the managed preset wins even when a Dockerfile exists. build.framework can't be combined with build.dockerfile, so to use your own image, remove build.framework and follow the Dockerfile guide.

Environment variables · Cron jobs · Dockerfile deployments

On this page