Deploying Laravel requires more than copying files. Production setups cache configuration, compile routes, run migrations safely, and supervise queue workers for reliable background processing.
Pre-Deploy Optimization
Prepare the application for production with composer install, asset builds, and Artisan optimize commands.
Set APP_DEBUG=false and APP_ENV=production before any public traffic hits the server.
Step 1: Install production dependencies
Run composer install –no-dev –optimize-autoloader on the server or in CI artifacts.
Dev dependencies like PHPUnit should never ship to production—they increase attack surface and size.
composer install --no-dev --optimize-autoloader
Step 2: Build frontend assets
Execute npm ci && npm run build so Vite outputs hashed files to public/build.
Verify public/build/manifest.json exists. Missing assets cause blank styles in production.
npm ci && npm run build
Step 3: Cache config, routes, and views
Run php artisan config:cache, route:cache, and view:cache during deploy.
After .env changes, rerun config:cache. Stale config cache is a frequent post-deploy issue.
php artisan config:cache
php artisan route:cache
php artisan view:cache
Step 4: Run migrations with maintenance mode
php artisan down –secret="token" during schema changes. php artisan migrate –force applies pending migrations.
Bring up with php artisan up after smoke tests pass.
php artisan down --secret="deploy-token"
php artisan migrate --force
php artisan up
Web Server and PHP-FPM
Nginx or Apache forwards PHP requests to PHP-FPM. Point the document root to public/, not the project root.
OPcache and realpath_cache tuning significantly improve Laravel throughput.
Step 1: Configure Nginx server block
Set root /var/www/myapp/public; and try_files $uri $uri/ /index.php?$query_string; for pretty URLs.
Pass PHP to unix socket: fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; with standard fastcgi_params.
root /var/www/myapp/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
Step 2: Set correct permissions
Web server user needs read on codebase and write on storage and bootstrap/cache.
chown -R deploy:www-data storage bootstrap/cache && chmod -R 775 storage bootstrap/cache.
chown -R deploy:www-data storage bootstrap/cache
Step 3: Enable OPcache
In php.ini set opcache.enable=1, opcache.validate_timestamps=0 in production, and adequate memory consumption.
Reload PHP-FPM after ini changes. OPcache avoids recompiling PHP on every request.
opcache.enable=1
opcache.memory_consumption=256
Step 4: Configure SSL with Certbot
Use certbot –nginx -d example.com for free TLS certificates with auto-renewal.
Force HTTPS in AppServiceProvider or middleware and set SESSION_SECURE_COOKIE=true.
sudo certbot --nginx -d example.com
Queues, Horizon, and Zero-Downtime
Supervisor manages queue workers and Horizon. Zero-downtime deploy tools symlink new releases atomically.
Health checks and rollback plans complete a production-ready pipeline.
Step 1: Supervise queue workers
Configure Supervisor program: php artisan queue:work –sleep=3 –tries=3 –max-time=3600.
Restart workers after deploy so they load new code: php artisan queue:restart.
php artisan queue:restart
Step 2: Deploy with Laravel Forge or Envoyer
Forge provisions servers and runs deploy scripts. Envoyer zero-downtime symlinks releases and runs hooks.
Hook example: php artisan migrate –force && php artisan horizon:terminate.
php artisan horizon:terminate
Step 3: Set up health endpoint
Laravel 11 includes /up health route. Monitor it with uptime services and load balancer checks.
Extend health checks to verify database and Redis connectivity for accurate status.
curl -f https://example.com/up
Step 4: Automate deploys from CI
GitHub Actions SSH deploy on main branch tags after tests pass. Store secrets in repository settings.
Keep deploy scripts idempotent and log each step for post-mortems.
php artisan test && ./deploy.sh
Aadyanex builds production-ready Laravel applications with clean architecture, secure APIs, and long-term support.
