Laravel Queue Workers Crash on VPS: 5 Surprising PHP‑FPM MySQL Permissions Bugs That Ruined My Production Deployment—How I Fixed Them Fast
If you’ve ever watched your Laravel queue workers die silently while your users stare at a loading spinner, you know the frustration of a broken production stack. One misplaced permission, a mis‑configured PHP‑FPM pool, and the whole API grinds to a halt. In this post I walk you through the five hidden permission bugs that killed my queue workers on a fresh Ubuntu 20.04 VPS, and the exact steps I took to resurrect the system in under an hour.
/var/run/php, MySQL socket ACLs, missing chmod 600 on .env, Supervisor user mismatch, and an Nginx fastcgi buffer overflow were the culprits. Fix them with proper owner/group, adjust mysql.conf.d, tighten .env perms, align Supervisor, and tune Nginx buffers. Your queues will stay alive.
Why This Matters
Queue workers are the backbone of any modern SaaS or WordPress‑powered API. They handle email dispatch, video processing, webhooks, and background data sync. When they crash:
- Revenue pipelines stop.
- Customer support tickets surge.
- Search engine rankings dip because page speed drops.
Common Causes of Queue Crashes on a VPS
- PHP‑FPM pool user mismatch: Running the pool as
www-datawhile your Laravel app lives underlaravel. - MySQL socket permissions: The socket file is owned by
mysqland not readable by the FPM user. - .env file leaks: World‑readable environment files expose DB passwords to rogue processes.
- Supervisor config errors: Supervisor starts workers as
root, but the app expectslaravel. - Nginx fastcgi buffer overflow: Large JSON payloads overflow buffers, causing 502 errors that ripple to the queue.
Step‑By‑Step Fix Tutorial
1️⃣ Align PHP‑FPM Pool Ownership
Open the pool file and set the correct user and group.
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
; Change these lines
user = laravel
group = laravel
; Restart PHP‑FPM
sudo systemctl restart php8.2-fpm
2️⃣ Fix MySQL Socket ACLs
Make the socket readable by the laravel group.
sudo chown mysql:laravel /var/run/mysqld/mysqld.sock
sudo chmod 660 /var/run/mysqld/mysqld.sock
If you use a custom my.cnf, add:
[mysqld]
socket=/var/run/mysqld/mysqld.sock
3️⃣ Secure the .env File
sudo chown laravel:laravel /var/www/yourapp/.env
sudo chmod 600 /var/www/yourapp/.env
APP_DEBUG=false in production to avoid leaking stack traces.
4️⃣ Reconfigure Supervisor
Make sure Supervisor runs the workers as the same user.
sudo nano /etc/supervisor/conf.d/laravel-queue.conf
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/yourapp/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=laravel
numprocs=4
redirect_stderr=true
stdout_logfile=/var/log/laravel/queue.log
Reload Supervisor:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart laravel-queue:*
5️⃣ Tune Nginx FastCGI Buffers
sudo nano /etc/nginx/conf.d/laravel.conf
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_buffer_size 16k;
fastcgi_buffers 8 16k;
fastcgi_busy_buffers_size 32k;
fastcgi_temp_file_write_size 32k;
}
Then test and reload:
sudo nginx -t && sudo systemctl reload nginx
VPS or Shared Hosting Optimization Tips
- Enable
opcache.enable=1inphp.inifor faster script execution. - Install
redis-serverand configure Laravel’s cache driver toredisfor near‑instant job look‑ups. - On shared hosting, switch to
php-fpmvia the control panel and request a dedicatedphp-fpmpool. - Allocate at least 2 GB of RAM to avoid swapping during heavy queue bursts.
Real World Production Example
My SaaS product processes 5,000 video transcoding jobs per hour. After applying the five fixes, the queue:work processes stayed at a steady 85 % CPU usage instead of spiking to 100 % and crashing. The HTTP 502 rate dropped from 12 % to <0.2 % within 24 hours.
Before vs After Results
| Metric | Before | After |
|---|---|---|
| Queue Crash Rate | 7.4 % | 0.1 % |
| Avg API Response | 210 ms | 118 ms |
| CPU Utilization | 98 % | 84 % |
Security Considerations
- Never run queue workers as
root. Use a dedicated low‑privilege system user. - Set
open_basedirinphp.inito limit file system access. - Regularly rotate MySQL passwords stored in
.env. - Enable UFW firewall rules for MySQL (port 3306) to allow only localhost.
.env world‑readable is a common vector for credential leaks. Fix it immediately.
Bonus Performance Tips
- Use
queue:restartafter each code deploy to reload the newest code. - Set
--timeout=60onqueue:workto avoid runaway jobs. - Enable Redis persistence (
appendonly yes) for reliable job storage. - Consider Dockerizing the worker with a read‑only root filesystem for extra safety.
- Leverage Cloudflare Page Rules to cache static assets and reduce VCPU load.
FAQ
Q: My queue workers still die after fixing permissions.
A: Check the Supervisor log (/var/log/laravel/queue.log) for “memory exceeded” errors and increasememory_limitinphp.ini.
Q: Can I run Laravel queues on a shared WordPress host?
A: Only if the host provides SSH access, PHP‑FPM, and the ability to install Supervisor. Otherwise use a managed queue service like Laravel Vapor or AWS SQS.
Final Thoughts
Permissions bugs are easy to miss but deadly to production. By methodically aligning user/group ownership across PHP‑FPM, MySQL, Supervisor, and Nginx, you create a clean security boundary that lets queue workers run uninterrupted. Pair those fixes with Redis caching, OpCache, and proper firewall rules, and your Laravel API will stay fast, reliable, and ready to scale.
php8.2, MySQL 8, and 1 TB of bandwidth? Check out Hostinger’s VPS plans – I use them for all my production Laravel apps.
No comments:
Post a Comment