Deployment.sh

Laravel hosting on your own servers, with zero downtime releases

Deployment turns any Ubuntu or Debian server into a tuned Laravel host. Connect the server over SSH or create one from your cloud account, point a site at your repository, and every push runs composer, migrations and cache warmup in a fresh release folder before traffic moves over. Horizon, queue workers and the scheduler restart with each release, and a bad deploy rolls back in one click.

Two developers in a small agency office reviewing a deploy log on a laptop, one pointing at the screen with a pen

What Deployment detects in a Laravel repository

When you add a site, Deployment reads the repository before it writes a single config file. The artisan file and laravel/framework in composer.json mark the project as Laravel, and the PHP constraint in composer.json picks the PHP 8.x version for the site. A package.json with a build script adds a Node LTS build step for Vite. laravel/horizon adds a Horizon daemon, laravel/octane offers an Octane process instead of PHP-FPM, and a routes/console.php or console kernel with scheduled tasks adds the scheduler cron line.

  • PHP version from the composer.json constraint, with the matching extensions (mbstring, intl, bcmath, gd, pdo_mysql or pdo_pgsql, redis)
  • Database driver from your environment, with MySQL, MariaDB or PostgreSQL created on the same server or a separate one
  • Frontend build with Vite when a build script exists
  • Horizon, plain queue workers or Octane, depending on the packages you use

What Deployment installs on a Laravel server

Provisioning sets up a firewall that allows only SSH, HTTP and HTTPS, hardens SSH to key login, enables unattended security updates and adds swap. Then it installs nginx or Caddy, PHP-FPM in the version your app needs (several versions can live side by side for different sites), Composer, Node LTS for asset builds, Redis for cache, sessions and queues, and the database engine you pick. Each site gets its own system user, its own PHP-FPM pool and a free Let's Encrypt certificate that renews by itself.

Backend engineer at a workbench beside an open server running a compiled service on a laptop

A Laravel deploy script you can read and edit

Every site has its own deploy script in the panel. Deployment fills it in from what it detected, and you change it like any shell script. It runs inside the new release folder while the current release keeps serving requests.

The shared storage folder and the .env file are linked into every release, so uploads, logs and secrets survive each deploy. Environment variables are encrypted per environment, and the panel shows a diff of what changed before the deploy runs.

bash
cd "$RELEASE_PATH"
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
npm ci && npm run build
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

Horizon, queue workers and the Laravel scheduler

Queue work is where most Laravel deploys go wrong: a worker that keeps old code in memory keeps processing jobs with yesterday's logic. Deployment runs Horizon or queue:work processes under supervisor or systemd and sends them a graceful terminate after the symlink switch, so each worker finishes its current job and starts again on the new release. The scheduler gets one cron entry per site, php artisan schedule:run every minute, and every run lands in the cron log in the panel. If you run Octane with Swoole or RoadRunner, Deployment manages the Octane process and reloads it on deploy instead of restarting PHP-FPM.

Zero downtime Laravel deploys and one-click rollback

Each deploy builds into a new timestamped folder under releases/. Only when composer, the build and migrations succeed and the health check (by default the /up route Laravel ships with) answers 200 does Deployment switch the current symlink and reload PHP-FPM. If anything fails, the old release keeps serving and you get the failing line in the deploy log. You keep the last N releases, and rollback is one click that points the symlink back. Read how the release switch works on zero downtime deployment, and how branches map to environments on deploy from git.

  • Write migrations that work with the old and the new code at the same time (add a column first, remove it in a later release), because rollback switches code, not schema
  • Keep php artisan down out of the script, the release switch makes it unnecessary

MySQL, PostgreSQL and Redis for Laravel

Create MySQL, MariaDB or PostgreSQL databases from the panel, with a separate user and grants per app, and restrict remote access to the IPs you list. Redis is ready for cache, sessions and queues. Scheduled backups of the database and of storage/app go to your own S3-compatible bucket with the retention you set, and restore is one click.

Which plan fits your Laravel hosting

PlanMonthlyYearly, per monthServersSites
Starter49 USD24 USD315
Team199 USD99 USD15100
Agency499 USD249 USD60unlimited within servers
Enterprise1 499 USD749 USD250unlimited within servers

A freelancer with a few Laravel apps is well served by Starter. A product team with a staging server, a production server and a separate database host fits Team, which adds roles and the audit log. Agencies hosting client apps choose Agency. Full details are on PaaS pricing.

Laravel hosting questions

Can I run several PHP versions on one server?

Yes. Each site has its own PHP-FPM pool, so one server can run a PHP 8.2 app next to a PHP 8.4 app, and you change a site's version in the panel.

Does Deployment support Laravel Octane?

Yes. When the repository uses laravel/octane, Deployment runs the Octane server as a managed process behind nginx or Caddy and reloads it gracefully on every deploy.

What happens to queued jobs during a deploy?

Workers finish the job they are processing, then restart on the new release. Jobs waiting in Redis or the database stay in the queue and are picked up by the new workers.

Can I try Deployment before I pay?

Yes. The home page has a free one-time demo: paste a public repository URL and see the detected stack, the server plan and the first lines of the deploy script. Plans start at 49 USD a month, or 24 USD a month billed yearly.

Ship your next Laravel release without downtime

Connect a server, point it at your repository and push.

Try the demo