How to Deploy Laravel on a VPS in 2026: Nginx, PHP-FPM, Queues and Zero-Downtime Releases

Laravel runs happily on shared hosting for small projects, but once you need queues, scheduled jobs, Redis, WebSockets or simply predictable performance, a VPS is the natural next step. This guide shows a clean, production-ready way to deploy a Laravel application on a Linux VPS: the stack, the web server configuration, queue workers, the scheduler and a release process that does not take your site down.
The stack
OS: Ubuntu 24.04 LTS or Debian 12.
Web server: Nginx in front of PHP-FPM (PHP 8.3 or newer).
Database: MySQL 8 or PostgreSQL 16 on the same server for small apps, or a separate server as you grow.
Cache and queues: Redis.
TLS: Let's Encrypt via Certbot, or Caddy as the front proxy.
For most Laravel apps, 2 vCPU and 4 GB RAM is a good start; add memory first if you run queues and a database on the same machine. A Linux VPS with NVMe and full root access fits this well.
Step 1: Prepare the server
Create a deploy user, disable password SSH logins, enable a firewall that allows only SSH, HTTP and HTTPS, and install PHP-FPM with the extensions Laravel needs: mbstring, xml, curl, zip, bcmath, intl, plus the driver for your database and redis. Install Composer globally.
Step 2: Configure Nginx
The document root must point to Laravel's public directory, never to the project root, otherwise your .env file could be downloadable.
server {
listen 80;
server_name app.example.com;
root /var/www/app/current/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}Run Certbot to add HTTPS and an automatic redirect from HTTP.
Step 3: Use a release-based folder layout
Instead of pulling new code into the live folder, deploy each release into its own directory and switch a symlink when it is ready:
/var/www/app/releases/<timestamp>for each deployed version./var/www/app/sharedfor.envandstorage, symlinked into every release./var/www/app/current, a symlink to the active release.
Switching a symlink is atomic, so visitors never see a half-deployed site, and rolling back is as simple as pointing the symlink at the previous release.
Step 4: The deploy steps
cd /var/www/app/releases/2026-10-03
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
ln -sfn /var/www/app/releases/2026-10-03 /var/www/app/current
sudo systemctl reload php8.3-fpm
php artisan queue:restartCaching config, routes and views gives a noticeable speed boost in production. Remember that after config:cache, the env() helper only works inside config files, so read settings through config() in your code.
Step 5: Run queue workers under a supervisor
Queue workers are long-running processes and must be restarted automatically if they crash. Use systemd or Supervisor to run php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600. The --max-time option makes each worker exit and restart periodically, which prevents slow memory growth. After each deploy, php artisan queue:restart tells workers to finish their current job and reload the new code.
Step 6: Enable the scheduler
Laravel's scheduler needs a single cron entry for the deploy user:
* * * * * cd /var/www/app/current && php artisan schedule:run >> /dev/null 2>&1Step 7: Permissions
The web server user needs write access to storage and bootstrap/cache only. Everything else should be owned by the deploy user and read-only for PHP-FPM. That limits the damage if a vulnerability is ever exploited.
Step 8: Production settings that matter
APP_ENV=productionandAPP_DEBUG=false. Debug mode in production leaks configuration and stack traces.Enable OPcache in PHP for a large performance gain.
Use Redis for cache, sessions and queues instead of the file or database drivers.
Send logs to a daily file with rotation, or to an external log service.
Step 9: Backups and monitoring
Back up the database daily with mysqldump or pg_dump, plus the storage/app directory if users upload files, and keep copies off the server. Monitor an application endpoint externally, and alert on failed jobs and queue length, not just server uptime. If you host on an IM HOST Cloud VPS, the free automatic server backup every 72 hours adds a second layer of protection on top of your own dumps.
Shared hosting or VPS for Laravel?
Shared hosting is fine for small Laravel sites without queues. Once you need background workers, Redis, custom PHP settings or SSH-based deployments, move to a VPS. IM HOST offers both, with free migration if you are moving from another provider. Compare Linux VPS and Cloud VPS plans, or start on shared hosting and upgrade when you need to.
More from our blog
Discover more practical guides and product insights from the IM Host team.
View all articles