Skip to content
Laravel deploy guide

Laravel hosting in the EU

Deploy Laravel from Git to EU infrastructure: Composer install, PHP version from composer.json, Postgres or MySQL drivers built in, migrations before traffic switches.

Laravel needs a PHP with the right extensions, Composer, somewhere writable for compiled views, and a database. HostStack’s Laravel preset sets that up on the official PHP image, keeps logs on stderr where the platform collects them, and lets you run php artisan migrate before each release goes live — all in Helsinki, under an EU company.

What HostStack detects and builds

  • Laravel is recognised from artisan plus composer.json, and builds on the official PHP image with Composer copied in.
  • The PHP version comes from composer.json — config.platform.php, then require.php — or .tool-versions; with none, the newest release.
  • pdo_pgsql, pdo_mysql, zip and bcmath are compiled into the image, so Postgres, MySQL and MariaDB work without a Dockerfile.
  • LOG_CHANNEL=stderr and VIEW_COMPILED_PATH=/tmp/views are set, because the root filesystem is read-only. Your own variables override both.
  • The app is served by PHP’s built-in server through php artisan serve. There is no php-fpm, nginx or FrankenPHP in the generated image.
StepDefault when you leave it empty
Installcomposer install --no-dev --optimize-autoloader
Build— (none)
Startphp artisan serve --host=0.0.0.0 --port=$PORT
EnvironmentLOG_CHANNEL=stderr VIEW_COMPILED_PATH=/tmp/views

There is deliberately no config:cache at build time: the build has no access to your secrets, and caching an empty config into the image breaks the app.

hoststack.yaml for Laravel

Optional. Commit it next to your code and every deploy applies it; leave a key out and the service keeps its dashboard value. It configures a service that already exists — it never creates one. The full schema and hoststack validate are in the docs.

hoststack.yaml
services:
  web:
    install:
      command: composer install --no-dev --optimize-autoloader
    start:
      command: php artisan serve --host=0.0.0.0 --port=$PORT
    healthCheck:
      path: /up
    env:
      APP_ENV: production
      APP_DEBUG: "false"
      DB_CONNECTION: pgsql
      SESSION_DRIVER: database
      CACHE_STORE: database

/up is the health route Laravel 11 and later ship with. Quote "false" so it stays a string. APP_KEY is a secret: set it on the service, never in this file.

Database and environment variables

Link the database with the alias DB and HostStack injects DB_URL, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME and DB_PASSWORD — exactly the variables config/database.php reads. Set DB_CONNECTION to pgsql or mysql to match the engine.

bash
hoststack db create --project prj_... --name app-db --engine postgres --plan micro
hoststack db link db_... --service svc_... --alias DB
hoststack env set svc_... APP_KEY=base64:... --secret
hoststack services update svc_... --pre-deploy-command "php artisan migrate --force"

Secrets belong on the service, not in the file — see environment variables and databases.

Deploy Laravel step by step

  1. 1Create a web service from your repository. With the CLI — hoststack services create --name web --type web_service --project prj_... --repo acme/app — the runtime is detected as PHP; in the dashboard, set the runtime to PHP yourself.
  2. 2Commit the hoststack.yaml above.
  3. 3Create a managed Postgres or MySQL and link it with --alias DB, so the DB_* variables Laravel reads are injected.
  4. 4Generate a key with php artisan key:generate --show and set it as the secret APP_KEY.
  5. 5Set php artisan migrate --force as the pre-deploy command.
  6. 6Push to deploy, then add your domain and set APP_URL to it.

Hosted in Europe, by a European company

Laravel powers a lot of European SaaS, shops and agency builds — the kind of app where a client’s procurement asks where the data lives and who the processor is. Here the answer is Finland and a Danish company, with the DPA signed at signup.

Every service, database and backup runs in Helsinki, Finland, on Hetzner, and HostStack is operated by MICCI, a Danish company — so the US CLOUD Act has no hold on it, the GDPR data processing agreement is signed at signup on every plan, and the invoice is in EUR. Why that differs from a US platform's EU region is on EU data residency.

Things that catch people out

The dashboard pre-fills Node.js for a Laravel repo.

Its repo check does not know composer.json, and a Laravel repo usually has a package.json for Vite. Set the runtime to PHP under Settings → General → Runtime. A service created with the CLI and no --runtime is detected as PHP at deploy time.

Vite assets are not built.

The PHP image has no Node.js, so npm run build does not run. Commit public/build, or build from your own Dockerfile with a Node stage and set the service’s Dockerfile path.

Nothing under storage/ is writable.

Use the database or Redis for sessions, cache and queues, not the file drivers. Uploads belong on object storage, or on a persistent disk mounted at /app/storage/app.

artisan serve is a small server.

It is fine for most apps. For heavy traffic, ship a Dockerfile with Octane, FrankenPHP or php-fpm behind nginx, and point the service at it.

Frequently asked questions

Where can I host Laravel in the EU?

HostStack runs Laravel apps in Helsinki, Finland, on Hetzner, and is operated by MICCI, a Danish company. It builds from your Git repository with Composer, links a managed Postgres, MySQL or MariaDB database, and runs your migrations before each release takes traffic.

Which PHP version does HostStack use for Laravel?

The one composer.json asks for: config.platform.php first, then the require.php constraint, then .tool-versions or mise.toml. With nothing declared it builds on the newest PHP release, and the build log names the version it chose and where it read it.

How do I run queue workers and the scheduler?

Create a Worker service from the same repo with php artisan queue:work as its start command, and a Cron Job service that runs php artisan schedule:run every minute. Both share the database link and environment variables you set on them.

Can I use MySQL instead of Postgres?

Yes. Create the database with --engine mysql or --engine mariadb, link it with --alias DB, and set DB_CONNECTION=mysql. The pdo_mysql extension is already in the image.

Other stacks

All guides are on the deploy guides index. Moving an existing Laravel app? The Heroku and Render guides have the cutover order.

Deploy your Laravel app

Free tier, no card: one service and one Postgres, in the EU.

Essential cookies only — for login sessions. No tracking. Details