DeployxaDocs Portal
CLI v1.0.4
Deploy Laravel App (PHP 8.3)
Framework guide · Laravel

Deploy a Laravel app (PHP)

Deploy Laravel with a Composer build, Nginx and PHP-FPM serving public/, route and view caching, migrations on release, a managed MySQL or PostgreSQL database and HTTPS.

Prerequisites

  • Laravel 11 or newer on PHP 8.2+, with artisan and composer.json at the root directory.
  • A committed composer.lock (and package-lock.json if you build assets with Vite).
  • An APP_KEY: run php artisan key:generate --show locally and keep the output.

How Deployxa detects Laravel

artisan next to composer.json selects the Laravel preset: PHP-FPM behind Nginx, with public/ as the web root. There is no start command to set; Nginx serves the app on port 80.

SettingValue
Build commandcomposer install --no-dev --optimize-autoloader
Web root (output)public
Releasephp artisan migrate --force
RuntimePHP-FPM with Nginx
Port80

Required config

APP_KEY and production flags

Set APP_KEY to the base64:… value you generated. Without it Laravel throws "No application encryption key has been specified" on every request. Keep it stable: changing it logs everyone out and breaks encrypted values.

Build: caches and assets

shell
composer install --no-dev --optimize-autoloader \
  && npm ci && npm run build \
  && php artisan route:cache && php artisan view:cache

Leave out the npm part if the app has no Vite assets (or if Node is not available in your build, commit public/build or use a Dockerfile). Route and view caches do not depend on environment variables, so they are safe at build time. config:cache freezes whatever environment exists when it runs: only add it to the build if your production variables are available during the build, and only call env() inside config/*.php, never in app code.

Trust the HTTPS proxy

php
// bootstrap/app.php (Laravel 11+)
->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: '*');
})

Without this, url(), asset() and redirects produce http:// links and browsers block mixed content.

Environment variables

KeyPurposeExample
APP_KEYEncryption key from key:generate --showbase64:…
APP_ENVApplication environmentproduction
APP_DEBUGKeep detailed errors offfalse
APP_URLPublic URL, used for generated linkshttps://example.com
DB_CONNECTIONDatabase drivermysql or pgsql
LOG_CHANNELSend logs to stdout so they show in Deployxa logsstderr

Databases and migrations

In the wizard's Configure step, set Database to MySQL or PostgreSQL. The connection string is injected into the app as DATABASE_URL, so nothing needs to be committed. Choose SQLite only for small apps: it lives on a persistent volume and has no server.

Laravel reads a connection URL from DB_URL. Point it at the injected value in config/database.php so you do not have to copy credentials:

php
// config/database.php, inside the 'mysql' (or 'pgsql') connection
'url' => env('DB_URL', env('DATABASE_URL')),

Migrations run with php artisan migrate --force during the release. If a migration fails the deploy stops and the previous release keeps serving traffic. Uploaded files in storage/app need a persistent volume or S3-compatible storage (FILESYSTEM_DISK=s3).

Queues and the scheduler

Add a WORKER service on the Environment Canvas with start command php artisan queue:work --tries=3 --max-time=3600, and a Scheduled Task that runs php artisan schedule:run every minute. The Laravel + MySQL & queues tutorial walks through both.

Deploy

From the dashboard

  1. 1
    Source

    Open Dashboard → Projects → New project (/dashboard/projects/new). Pick the GitHub repository and branch, or upload a .zip archive of the project.

  2. 2
    Configure

    Leave the framework preset on Auto-detect or choose Laravel. Check the fields under advanced settings:

    • Build command: composer install --no-dev --optimize-autoloader
    • Output directory: public
    • Root directory: ./, or the sub-folder that holds the app in a monorepo
    • Database: MySQL or PostgreSQL
  3. 3
    Environment

    Add APP_KEY, APP_ENV=production, APP_DEBUG=false, APP_URL and DB_CONNECTION.

  4. 4
    Deploy

    Start the deploy and watch the build log. When the release passes its health check it is served over HTTPS on its Deployxa URL.

From the CLI

shell
$ npm install -g @deployxa/cli
$ deployxa login
$ cd my-app
$ deployxa link            # pick an existing project, or skip: deploy creates one
$ deployxa env set APP_KEY "base64:…"
$ deployxa deploy
$ deployxa logs --live     # stream build and runtime logs
$ deployxa open            # open the live URL

If the folder is not linked, deployxa deploy creates a project named after the folder and links it (the link is saved in .deployxa/config.json). Later runs deploy the linked project. deployxa status shows the latest deployment and deployxa rollback previous returns to the release before it.

Warning: deployxa deploy packages the folder exactly as it is on disk; it does not read .gitignore. Delete local node_modules, virtualenvs, build output and real .env files first, or deploy from a clean clone. Set secrets with deployxa env set instead of shipping them in the archive.
Warning: From the CLI, delete the local vendor/ and node_modules/ folders and keep your local .env out of the folder you deploy; set production values with deployxa env set.

Custom domain

Go to Dashboard → Domains, choose Connect a domain you already own and pick this project. Deployxa then shows the DNS records to create at your DNS provider:

RecordUse it forValue
AAn apex domain such as example.com85.17.244.184 (DNS only on Cloudflare)
CNAMEA subdomain such as www or appcname.deployxa.com (DNS only on Cloudflare)
TXTOnly when a CDN or proxy (for example Cloudflare orange-cloud) hides the origin recordHost _deployxa-challenge.<your-domain>, value deployxa-verification=…

DNS changes can take several minutes to propagate; use Retry verification once they have. A Let's Encrypt certificate is issued after the domain verifies. From a linked folder you can do the same with the CLI:

shell
$ deployxa domains add app.example.com
$ deployxa dns             # Waiting → Verified → SSL Active
$ deployxa domains list

After the domain verifies, update APP_URL and redeploy so cached config picks it up.

Common errors and fixes

SymptomFix
500 error: No application encryption key has been specifiedSet APP_KEY and redeploy.
Your requirements could not be resolved (composer)The lock file needs a newer PHP or extension; run composer install locally on PHP 8.2+ and commit composer.lock.
SQLSTATE[HY000] [2002] Connection refusedNo database attached, or DB_URL / DATABASE_URL not wired into config/database.php.
Mixed content / http:// asset URLsAdd trustProxies(at: '*') and set APP_URL to the https URL.
Env change has no effectConfig was cached with config:cache before the change. Redeploy, or drop config:cache from the build.
Vite manifest not foundRun npm ci && npm run build in the build command.

Start with deployxa logs --live (or the deployment's log view in the dashboard): the build log shows dependency and compile failures, the runtime log shows crashes and bind errors. See also Troubleshooting.