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.
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.
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.
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 downout 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
| Plan | Monthly | Yearly, per month | Servers | Sites |
|---|---|---|---|---|
| Starter | 49 USD | 24 USD | 3 | 15 |
| Team | 199 USD | 99 USD | 15 | 100 |
| Agency | 499 USD | 249 USD | 60 | unlimited within servers |
| Enterprise | 1 499 USD | 749 USD | 250 | unlimited 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.
$ git push origin main
✓ build release 20261019-142210
✓ health check 200
✓ switch current 0.4 s
$