Skip to content
Docs

Deploy a Laravel app

From a GitHub repository to a live Laravel app with its database, queue worker, scheduler and your own domain, in about ten minutes.

Updated 17 Oct 20265 min read

A standard Laravel app deploys on Tanzahost with almost no changes: with MySQL, it needs one line in composer.json (below). We read your composer.json, see Laravel, choose PHP, install your packages, build your assets, and start the app. This page follows Asha, who puts her shop duka online in her project duka, in location UK-01 · United Kingdom.

Before you start

You need your Laravel app in a GitHub repository (or as a ZIP file), and a Tanzahost account with some money in its wallet.

Prepare your repository

Commit composer.json and composer.lock. We know it's Laravel when the code has an artisan file and composer.json requires laravel/framework. Set the PHP version your app needs in composer.json: we use it to choose PHP.

json
{
  "require": {
    "php": "^8.4",
    "ext-pdo_mysql": "*",
    "laravel/framework": "^12.0"
  }
}

We pick the newest PHP we offer that meets what you ask for. Today we offer PHP 8.2, 8.3, 8.4 and 8.5 (8.0 and 8.1 still build, with a warning that they get no more security fixes), so ^8.4 builds with PHP 8.5. To stay on exactly 8.4, choose it in the app's Build and run settings, or in the settings file. With no version asked for, an app gets PHP 8.4.

If package.json has a build script, as Laravel's Vite setup does, we install Node.js and run it too. Extensions your composer.json requires, like ext-intl, are added for you from our list.

MySQL needs the pdo_mysql extension

Laravel reaches MySQL and MariaDB through PHP's pdo_mysql extension, and our PHP doesn't have it until you ask. Add "ext-pdo_mysql": "*" to the require of your composer.json, or tick pdo_mysql under PHP extensions in the app's Build and run settings. For PostgreSQL, ask for pdo_pgsql the same way.

Keep .env out of your repository

Your .env file holds passwords. Leave it out of Git: its settings become encrypted variables, below.

Create a project and add the app

  1. In the dashboard, choose New project, give it a name, and pick its location: the one closest to your visitors.

  2. In the project, choose Add a service, then App.

  3. Name the app (Asha's is web), choose GitHub, and pick your repository and branch.

  4. Set its limits: the most memory and processor time it may use. They cost nothing by themselves, and the rates and an estimate are shown before you deploy.

  5. Choose Deploy.

We show what we found, like "Laravel on PHP 8.5", and you watch the build's log live. See Deploying.

Set your variables

Open your project's Variables tab and choose the app. Values are stored encrypted, shown masked, and given to your app when it starts. To create APP_KEY, run this on your computer:

Terminal
php artisan key:generate --show

Copy the value it prints into APP_KEY. You can also choose Paste a .env file, and every line becomes a variable.

For the database, choose Add a service, then Database, pick MySQL, and tick Add its connection details to web's variables. Asha's variables then look like this:

NameValueSet by
APP_KEYbase64:…You
APP_URLhttps://duka.co.tzYou
DB_CONNECTIONmysqlThe database
DB_HOSTmysql.duka.internalThe database
DB_DATABASEdb_dukaThe database
DB_USERNAMEdb_dukaThe database
DB_PASSWORD••••••••The database

If you leave APP_URL out, we set it to the app's address for you, and change it when the app gets its own domain. An APP_URL you set to your own domain is never changed.

Changes apply on the next deploy

After you change a variable, the page says Redeploy to apply until a deploy uses it. Adding a database fills in its own connection details and redeploys the app.

Run migrations before going live

On the app's page, in the Laravel card, tick Run migrations on each deploy, before the new version goes live. On every deploy, this command runs once, in its own sandbox, after the build and before visitors switch to the new version:

Terminal
php artisan migrate --force
If it fails, nothing changes

The deploy stops, and the version before it keeps running. The deployment shows the command's last lines, so you can see why.

The same card has Run migrations, Storage link, Clear cache, Maintenance on and Maintenance off. Maintenance mode lasts across deploys.

Add a queue worker and the scheduler

On the app's page, under Processes, choose Add a worker or scheduled task. Add a worker with this command. It runs from your app's live version, with its variables, and is charged like an app, for what it uses:

Terminal
php artisan queue:work --tries=3 --max-time=3600

Then add a scheduled task with the timetable * * * * * that runs Laravel's scheduler every minute:

Terminal
php artisan schedule:run

Times are in UTC. A task still running at its next time is skipped, and one running for over an hour is stopped. See Workers and Scheduled tasks.

Connect your domain

Your app is already live on its free address, like duka-7h3k.tanzahost.co. Under the project's Domains tab, add your own: use our nameservers, connect Cloudflare, or add the records we show where your domain is registered.

We check every minute. When the records are right, SSL is issued by itself, and the free address sends visitors to your domain. See Add a domain.

That's it

Every push to your branch now deploys without downtime. If a new version stops by itself within five minutes, visitors go back to the previous one by themselves.

Optional: the settings file

For anything special, add tanzahost.json to the root of your repository. It can choose the PHP version, extensions and PHP settings, the health address, and the folders to keep between deploys. Choices made in the dashboard win over the file.

json
{
  "version": "8.4",
  "health": "/up",
  "php": {
    "extensions": ["intl", "gd"],
    "ini": { "upload_max_filesize": "64M" }
  }
}

Laravel's storage is already kept between deploys. Every field is on The settings file.