Ubuntu · Laravel deployment

How to deploy Laravel on an Ubuntu VPS

By · Last updated: · free to read, no paywall

A $5–7/month VPS is still the cheapest, most flexible way to run Laravel in production — if you set it up properly. This guide walks through the full production stack, every manual step, the one-command alternative, and the operational habits that keep a server healthy for years.

In this guide
  1. Why a VPS (and when not)
  2. The production stack, explained
  3. The manual setup, step by step
  4. The one-command alternative
  5. Post-deploy operations that matter
  6. Common mistakes to avoid
  7. FAQ

Why a VPS (and when not)

Shared hosting can't run queue workers, WebSockets or Laravel Octane properly, and managed PaaS platforms charge for convenience with usage-based pricing. A VPS from Hetzner, DigitalOcean, Vultr or Linode gives you root access, predictable billing and enough headroom to host several Laravel apps on one machine.

The production stack, explained

Every production Laravel server converges on the same components. Understand what each piece does before you automate any of it:

ComponentRoleNotes
NginxWeb server / reverse proxyServes static assets, proxies PHP requests
PHP-FPM or OctanePHP runtimeFPM is the reliable default; Octane (FrankenPHP) keeps the app booted for high throughput
MariaDB / PostgreSQLDatabaseEither works with Laravel; pick per app
Valkey (Redis-compatible)Cache, sessions, queuesOpen-source Redis fork; drop-in for Laravel
SupervisorProcess managerKeeps queue:work and Horizon alive
CronSchedulerOne entry: artisan schedule:run every minute
UFW + Fail2banFirewall / brute-force protectionDefault-deny, ban repeated SSH failures
CertbotTLS certificatesFree Let's Encrypt certs with auto-renewal
Deployer-style releasesZero-downtime deploysReleases directory + symlink swap

The manual setup, step by step

This is the honest, unabridged checklist. Budget 2–4 hours the first time, and remember you'll own every one of these choices at upgrade time too.

  1. Create a sudo user and lock down SSH. adduser deploy, install your public key, then disable root login and password auth in /etc/ssh/sshd_config.
  2. Enable the firewall. ufw allow OpenSSH http https then ufw enable. Install Fail2ban for SSH brute-force protection.
  3. Install Nginx. apt install nginx.
  4. Install PHP. Add a maintained PHP repository, then install php8.x-fpm with the extensions Laravel needs: mbstring, xml, curl, zip, intl, mysql (or pgsql), redis, gd, opcache.
  5. Tune PHP for production. Enable opcache, set sane memory_limit and upload_max_filesize, turn expose_php off.
  6. Install Composer globally.
  7. Install MariaDB, run mariadb-secure-installation, create a database and a dedicated user per app — never reuse root.
  8. Install Valkey (or Redis) for cache, sessions and queues.
  9. Write the Nginx server block. Document root points at current/public, try_files falls back to index.php, FastCGI passes to the app's PHP-FPM socket.
  10. Ship the code. Clone into a releases/ directory, composer install --no-dev --optimize-autoloader, copy .env, run php artisan key:generate, storage:link, and fix permissions so only storage/ and bootstrap/cache/ are writable.
  11. Migrate and cache. php artisan migrate --force then config:cache, route:cache, view:cache.
  12. Configure Supervisor to run php artisan queue:work (or Horizon) and restart it on every deploy.
  13. Add the scheduler cron: * * * * * php artisan schedule:run.
  14. Issue TLS certificates with Certbot and force HTTPS.

Now multiply by every app you host, and again by every server — and keep PHP, Nginx and the OS patched forever. It's all doable; it's just undifferentiated work.

The one-command alternative

Everything in the previous section is exactly what Cipi automates. On a fresh Ubuntu 24.04/26.04 VPS:

wget -O - https://cipi.sh/setup.sh | bash

In about ten minutes you get the full stack — Nginx, PHP, MariaDB, Valkey, Supervisor, UFW, Fail2ban, Certbot, Deployer — plus hardening you'd otherwise do by hand: root login disabled, key-only SSH for the admin user, and a random root password stored in /etc/cipi/server.json. Then each app is one more command:

cipi app create # add --octane for Laravel Octane on FrankenPHP

That provisions an isolated system user, PHP-FPM pool, Nginx vhost and database per app, connects GitHub or GitLab with deploy keys and webhooks for zero-downtime Git deploys, and wires queue workers and the scheduler. SSL is cipi ssl install; PostgreSQL is cipi db install pgsql. See the getting started guide for the full walkthrough, or the comparison hub if you're evaluating it against Forge, Ploi and friends.

Post-deploy operations that matter

Getting to "it works" is half the job. These habits are what separate a server that lasts years from one that surprises you:

Common mistakes to avoid

Put this into practice with Cipi

Cipi is the free, open-source deploy CLI referenced throughout this guide: one command turns a fresh Ubuntu VPS into a hardened production server for Laravel — Nginx, PHP-FPM or Octane, MariaDB or PostgreSQL, queues, scheduler, SSL and zero-downtime Git deploys included.

wget -O - https://cipi.sh/setup.sh | bash

Frequently asked questions

What are the minimum server requirements for Laravel in production?

A single vCPU with 2 GB RAM runs a typical Laravel app with database, cache and a queue worker comfortably; add swap below 4 GB. Octane, Horizon and heavy build steps benefit from 4 GB. Cipi installs its full stack on any fresh Ubuntu 24.04/26.04 VPS.

Can I host multiple Laravel apps on one VPS?

Yes, and it is usually the most cost-effective setup. The key is isolation: each app should have its own system user, PHP-FPM pool and database credentials so one compromised or misbehaving app cannot touch the others. Cipi provisions exactly that isolation automatically with cipi app create.

Should I use PHP-FPM or Laravel Octane?

PHP-FPM is the boring, reliable default and right for most apps. Octane keeps the framework booted between requests and shines on high-traffic APIs and latency-sensitive endpoints. With Cipi you can run both on the same server and create Octane apps with cipi app create --octane.

How do I keep PHP updated on Ubuntu?

Track a maintained PHP repository and apply security patches promptly rather than waiting for distro upgrades. Cipi manages PHP security patches itself with a weekly check (cipi php upgrade), so servers do not silently fall behind.

Do I still need Laravel Forge if I manage my own VPS?

No. Forge is a paid SaaS that automates the same stack this guide describes. If you want that automation without the subscription or the third-party dependency, Cipi covers the same workflow free and open source — see the detailed Cipi vs Forge comparison.

Keep reading