All docs

PHP and Laravel

The one stack Marina configures for you: the app key it generates, and the cache it clears so your app boots.

A composer.json or an index.php at the root makes it a PHP app. An artisan file makes it a Laravel one, and Laravel is the only framework Marina configures on your behalf.

marina vessels create shop --repo acme/shop

You get an app server rather than a bare process. For Laravel the document root becomes public/, and if the repo has a package.json its dependencies are installed and its build scripts run, so Vite and Mix assets are built as part of the deploy.

Your app key

Laravel refuses to boot without APP_KEY, so Marina generates one when the app is created and puts it in your config vars.

It is generated once and never rotated. Rotating an app key makes every encrypted column, signed URL and session your app has already written unreadable. If you set your own before or during create, Marina keeps it, which is what you want when you are moving an existing app in.

Your config reaches the app

Laravel caches its config at build time, and a cached config beats the environment. Marina clears that cache immediately before your app starts, so the app key and every variable an attached database injects are the values your app actually reads.

There is nothing to configure. Declaring your own web in marina.toml replaces the start command, and the clear still runs in front of whatever you declared.

Migrations

Laravel apps migrate when they start. There is a switch in the app’s deploy settings in the dashboard to turn that off, for when you would rather run migrations yourself:

marina run -- php artisan migrate --force

That switch is the one place it changes; there is no CLI command for it yet.

Attaching a database

marina db create shop-db --engine mysql
marina db attach shop-db

The variables arrive in the shape Laravel actually reads, DB_CONNECTION through DB_PASSWORD, not just a connection URL, so config/database.php needs no editing. The app restarts once to pick them up.

Two limits worth knowing before you design around it. Only the first database attached gets those variables, because Laravel has one default connection and a second attachment would silently repoint a working app; later ones still get a URL variable you can wire up yourself. And managed SQLite is not one of the options here: Marina’s SQLite is reached over HTTPS rather than as a file on disk, which Laravel’s sqlite driver cannot open. Use Postgres or MySQL.

The port

Marina sets PORT and the app server binds it. Nothing to do.

If you bring a Dockerfile

None of the above happens. A repo with a Dockerfile at the root is built from it, and you own the runtime end to end: your own PHP image, your own document root, your own app key, and no cache clearing. That is the right choice when you need a specific extension or version, and the wrong one if you just want Laravel to work.