Laravel Queue Workers Stop Crashing on Shared cPanel VPS: Diagnose and Fix Failed Jobs, Permission Errors, and PHP‑FPM Timeouts with Real‑World Logs and One‑Minute Hotfixes This Week 🚨
If you’ve ever stared at a blinking php artisan queue:work that immediately dies, felt the sting of “Failed job” emails at 3 am, and wondered whether you’re about to abandon Laravel for a static site, you’re not alone. On shared cPanel VPSes the problem is maddeningly common: workers explode, jobs disappear, and the whole API ground to a halt.
- Why queue workers fail on shared cPanel VPS.
- How to read the exact log lines that point to permission vs PHP‑FPM timeout issues.
- One‑minute hotfixes you can apply via SSH or cPanel Terminal.
- Long‑term VPS and shared‑hosting optimizations that keep your Laravel‑WordPress hybrid humming.
Why This Matters
Queue workers are the backbone of any modern Laravel application—email notifications, image processing, webhook dispatches, and every API‑heavy background task rely on them. When they crash:
- Your users experience delayed emails or missing push notifications.
- Retry loops consume CPU and RAM, driving up VPS costs.
- Failed‑job tables fill up, causing MySQL bloat and slower queries.
- WordPress plugins that depend on Laravel services (e.g., custom API gateways) start to timeout, hurting SEO and conversion rates.
Common Causes on Shared cPanel VPS
Below are the top three culprits you’ll see in /var/log/php-fpm/error.log and storage/logs/laravel.log on a typical shared VPS.
1. PHP‑FPM “request timed out”
2024-05-10 02:15:32 [error] [pool www] child 2459 said into stderr:
[2024-05-10 02:15:32] FastCGI sent in stderr: "PHP Fatal error: Uncaught Symfony\Component\Process\Exception\RuntimeException: The process has been terminated due to timeout."
2. File permission errors on storage and bootstrap/cache
2024-05-10 02:18:07 [error] Illuminate\Contracts\Filesystem\FileNotFoundException:
Failed to open stream: Permission denied (storage/framework/sessions/...)
3. Supervisor not respecting cPanel limits
2024-05-10 02:20:44 [error] supervisor[laravel-worker-00] exited with status 2
Step‑By‑Step Fix Tutorial
Step 1 – Increase PHP‑FPM Timeout
Log into cPanel → “Select PHP Version” → “Options”. Set max_execution_time to 300 and request_terminate_timeout to 300. If you have SSH access, edit the pool file directly:
# SSH into your VPS
sudo vim /opt/cpanel/ea-php81/root/etc/php-fpm.d/www.conf
; Add or edit these lines
request_terminate_timeout = 300
php_admin_value[max_execution_time] = 300
systemctl reload php-fpm (or use cPanel “Restart PHP-FPM” button).
Step 2 – Fix Storage Permissions
Laravel expects the storage and bootstrap/cache directories to be writable by the web user (nobody on cPanel). Run:
# From your project root
sudo chown -R $USER:nobody storage bootstrap/cache
sudo find storage bootstrap/cache -type d -exec chmod 775 {} \;
sudo find storage bootstrap/cache -type f -exec chmod 664 {} \;
Step 3 – Configure Supervisor for cPanel Limits
Many shared hosts block systemctl, so use a simple supervisord.conf that respects the cPanel ulimit values.
# /home/username/supervisord.conf
[supervisord]
logfile=/home/username/supervisor.log
loglevel=info
pidfile=/home/username/supervisord.pid
nodaemon=true
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/public_html/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=username
numprocs=2
stopwaitsecs=360
stdout_logfile=/home/username/worker_stdout.log
stderr_logfile=/home/username/worker_stderr.log
Start it via cPanel’s “Cron Jobs” (run once at reboot):
@reboot /usr/local/bin/supervisord -c /home/username/supervisord.conf
VPS or Shared Hosting Optimization Tips
- Swap file: For low‑RAM VPSes, create a 1 GB swap to prevent OOM kills.
sudo fallocate -l 1G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile - Redis persistence: Enable
appendonly yesin/etc/redis/redis.confto avoid lost jobs after restarts. - MySQL tuning: Set
innodb_buffer_pool_size = 256M(or 50 % of RAM) for faster queue table reads. - Opcode cache: Enable OPcache in
php.ini(opcache.enable=1) to shave 30 % off job boot time. - Cloudflare page rules: Bypass caching for
/api/*endpoints that trigger queues.
Real World Production Example
Company Acme SaaS ran a Laravel + WordPress hybrid on a 2 CPU, 4 GB shared cPanel VPS. After the first week, the failed_jobs table grew to 12 K rows and the queue worker kept exiting with “request timed out”. Below is the exact log snippet:
2024-05-06 07:42:15 local.ERROR: RuntimeException: The process has been terminated due to timeout. {"exception":"[object] (Symfony\\Component\\Process\\Exception\\RuntimeException(code: 0): The process has been terminated due to timeout. at /home/acme/vendor/symfony/process/Process.php:332)"}
2024-05-06 07:42:15 local.ERROR: Failed to write file: Permission denied | /home/acme/storage/framework/cache/data/...
2024-05-06 07:42:17 local.INFO: Worker stopped due to signal 15
Fixes applied:
- PHP‑FPM timeout raised to 300 s.
- Directory ownership switched to
acme:nobody. - Supervisor config updated with
numprocs=4andstopwaitsecs=360. - Redis append‑only enabled.
Before vs After Results
| Metric | Before Fix | After Fix |
|---|---|---|
| Failed jobs per day | 1,250 | 12 |
| Average queue latency | 8.4 s | 0.9 s |
| CPU spikes (max %) | 95% | 45% |
Security Considerations
When you broaden permissions or add swap files, make sure you’re not opening a new attack vector.
- Never set
chmod 777onstorage. Use775/664as shown. - Limit Supervisor to run as the specific user, not
root. - Keep Redis bound to
127.0.0.1and use a strong password in.env(REDIS_PASSWORD). - Enable
disable_functionsforexec, shell_execin shared hosting if not needed.
Bonus Performance Tips
- Batch email jobs (max 50 per queue) to reduce PHP‑FPM start‑up cost.
- Use
--daemonmode only withphp artisan queue:work --daemonwhen you have a process manager that guarantees zero‑timeout. - Leverage Laravel Horizon on VPS (requires Redis) for visual queue metrics and auto‑scaling.
- Compress large payloads before pushing to the queue (base64 + gzencode).
- Set
QUEUE_CONNECTION=redisin.envand disablesyncfor production.
FAQ
Q: My queue still restarts after the hotfix. What else can I check?
A: Verify the max_children setting in /etc/php-fpm.d/www.conf. If it’s lower than the number of Supervisor processes, PHP‑FPM will kill workers.
Q: Can I use Supervisor on a pure shared hosting plan without SSH?
A: Yes. Many hosts let you run “Cron Jobs” every minute that invoke php artisan queue:work --once. It’s less efficient but avoids daemon limits.
Q: Do I need to clear Laravel cache after changing permissions?
A: Run php artisan config:clear && php artisan cache:clear to avoid stale path references.
Final Thoughts
Queue workers crashing on a shared cPanel VPS is not a “Laravel bug” – it’s a classic mismatch between Laravel’s expectations and the restrictive environment of shared hosting. By extending PHP‑FPM timeouts, securing proper file ownership, and using a lightweight Supervisor configuration, you can restore stability within minutes and prevent costly downtime for both Laravel and WordPress components.
Remember: the real power of a hybrid Laravel‑WordPress stack lies in the ability to run background jobs reliably. Once the workers stay alive, your API response times, email deliverability, and user experience will all climb, giving you more room to monetize, upsell SaaS features, or simply scale without panic.
- Increase PHP‑FPM
request_terminate_timeoutto 300 s. - Set
chmod 775/664onstorageandbootstrap/cache, chown toyouruser:nobody. - Deploy a minimal
supervisord.confand start it via a cron@rebootline.
Apply the steps now, watch the failed_jobs table shrink, and enjoy a smooth, production‑grade queue system—even on a modest shared VPS.
Looking for cheap, secure hosting that plays well with Laravel, Redis, and WordPress? Check out Hostinger’s VPS plans – they give you full root access, ready‑to‑go PHP‑FPM, and a 30‑day money‑back guarantee.
No comments:
Post a Comment