Following laravel deployment best practices is the difference between a smooth launch and a midnight firefighting session. Whether you're deploying your first Laravel app or your fiftieth, having a reliable checklist ensures nothing gets missed — no forgotten environment variables, no debug mode left on, no exposed credentials.
This guide gives you a complete, copy-paste-ready deployment checklist for getting Laravel into production on a VPS.
Pre-Deployment: Local Preparation
Before touching your server, make sure your local setup is production-ready.
1. Environment Configuration
# Copy .env.example and configure for production
cp .env.example .env.production
Critical settings to change:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
LOG_CHANNEL=stack
LOG_LEVEL=warning
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=your_production_db
DB_USERNAME=your_db_user
DB_PASSWORD=your_strong_password
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
Never set APP_DEBUG=true in production. It exposes your entire configuration, database credentials, and stack traces to anyone who triggers an error.
2. Optimize Autoloading
composer install --optimize-autoloader --no-dev
The --no-dev flag removes development dependencies (PHPUnit, Debugbar, etc.), reducing your deployment size and attack surface. The --optimize-autoloader flag generates a class map for faster class loading.
3. Run Tests
php artisan test
Never deploy code that hasn't passed its test suite. If you don't have tests yet, at least verify the app boots without errors.
Server Setup: The Foundation
4. Server Requirements
For a Laravel 11 application, ensure your server has:
- PHP 8.2 or higher
- Required extensions: BCMath, Ctype, cURL, DOM, Fileinfo, JSON, Mbstring, OpenSSL, PCRE, PDO, Tokenizer, XML
- Composer
- Node.js and npm (for frontend assets)
- MySQL 8.0+ or PostgreSQL 15+
- Redis (recommended for caching and queues)
Install everything on Ubuntu:
sudo apt update
sudo apt install php8.2-fpm php8.2-mysql php8.2-redis php8.2-xml \
php8.2-mbstring php8.2-curl php8.2-zip php8.2-bcmath php8.2-gd \
nginx mysql-server redis-server nodejs npm -y
5. Directory Permissions
Laravel needs write access to specific directories:
sudo chown -R www-data:www-data /var/www/yourapp
sudo chmod -R 755 /var/www/yourapp
sudo chmod -R 775 /var/www/yourapp/storage
sudo chmod -R 775 /var/www/yourapp/bootstrap/cache
Getting permissions wrong is one of the most common laravel deployment best practices violations. Too permissive (777) is a security risk. Too restrictive and Laravel can't write logs or cache files.
6. Nginx Configuration
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/yourapp/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Important: The root must point to the /public directory, not the application root. This prevents direct access to your .env file, config files, and application code.
Deployment Steps
7. Clone and Configure
cd /var/www
git clone git@github.com:youruser/yourapp.git
cd yourapp
# Install dependencies
composer install --optimize-autoloader --no-dev
# Copy environment file
cp .env.production .env
# Generate application key
php artisan key:generate
8. Run Migrations
php artisan migrate --force
The --force flag is required in production because Laravel asks for confirmation by default. If you're using seeders for initial data:
php artisan db:seed --force
9. Laravel Deployment Best Practices: Cache Everything
This is where many developers skip steps. Caching these files significantly improves performance:
# Cache configuration (merges all config files into one)
php artisan config:cache
# Cache routes (compiles routes into a single file)
php artisan route:cache
# Cache views (pre-compiles Blade templates)
php artisan view:cache
# Cache events (if using event discovery)
php artisan event:cache
Warning: After running config:cache, Laravel ignores your .env file and reads only from the cached config. If you change .env, you must run config:cache again.
10. Build Frontend Assets
npm ci
npm run build
Use npm ci instead of npm install in production — it's faster and ensures exact versions from your lock file.
11. SSL Certificate
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Post-Deployment: Production Essentials
12. Set Up Queue Workers
If your app uses queues (emails, notifications, jobs), set up Supervisor to keep workers running:
sudo apt install supervisor -y
Create /etc/supervisor/conf.d/laravel-worker.conf:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/yourapp/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/yourapp/storage/logs/worker.log
stopwaitsecs=3600
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
13. Set Up the Scheduler
Add Laravel's scheduler to cron:
sudo crontab -u www-data -e
Add this line:
* * * * * cd /var/www/yourapp && php artisan schedule:run >> /dev/null 2>&1
14. Configure Log Rotation
Prevent logs from filling your disk:
sudo nano /etc/logrotate.d/laravel
/var/www/yourapp/storage/logs/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
}
Common Deployment Mistakes
Forgetting to cache config after .env changes — Your app uses stale values. Always run php artisan config:cache after changing environment variables.
Leaving debug mode on — Exposes your entire stack. One error page can reveal database passwords, API keys, and file paths.
Not setting up queue workers — Emails don't send, notifications don't fire, jobs pile up silently.
Deploying without --no-dev — Dev dependencies bloat your app and may introduce security vulnerabilities.
Wrong file permissions — Either too open (security risk) or too restrictive (app crashes with permission errors).
No backup strategy — Always have automated database backups before deploying updates.
Quick Deployment Script
Combine everything into a reusable script:
#!/bin/bash
# deploy.sh
set -e
cd /var/www/yourapp
echo "Pulling latest code..."
git pull origin main
echo "Installing dependencies..."
composer install --optimize-autoloader --no-dev
echo "Running migrations..."
php artisan migrate --force
echo "Building assets..."
npm ci && npm run build
echo "Clearing and rebuilding caches..."
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
echo "Restarting queue workers..."
php artisan queue:restart
echo "✅ Deployment complete!"
Deploy Laravel with Confidence on DeployBase
Following laravel deployment best practices ensures your application runs smoothly, securely, and performantly in production. A reliable server makes all the difference.
At DeployBase, our VPS plans come with PHP 8.2+, MySQL, Redis, and Nginx pre-configured — everything Laravel needs out of the box. Starting at $5/month with NVMe SSD storage, full root access, and 24/7 support, you can deploy your Laravel app with confidence.
Get your VPS at DeployBase → — optimized hosting for Laravel applications.




