← Back to blog

Managing Laravel queue workers with Supervisor on Ubuntu

laravellinuxdevopshow to

If you’ve ever SSH’d into a server, run php artisan queue:work, and then watched it die the moment your session closes — Supervisor is the fix. It keeps long-running processes alive, restarts them on failure, and gives you a clean interface to manage them.


What is Supervisor

Supervisor is a process control system for Linux. You give it a config file describing a program, and it makes sure that program stays running. If the process crashes, Supervisor restarts it automatically. It’s the standard tool for running Laravel queue workers, Horizon, websocket servers, or anything that needs to stay alive in the background.


Installing Supervisor

On Ubuntu, it’s a single command:

sudo apt update && sudo apt install supervisor -y

Supervisor runs as a system service out of the box. Confirm it’s active:

sudo systemctl status supervisor

You should see active (running). If not:

sudo systemctl enable supervisor
sudo systemctl start supervisor

Creating a config for Laravel queue:work

Supervisor config files live in /etc/supervisor/conf.d/. Each .conf file defines one or more programs to manage.

Create a new config:

sudo nano /etc/supervisor/conf.d/laravel-worker.conf

Paste the following:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/your-app/artisan queue:work --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/your-app/storage/logs/worker.log
stopwaitsecs=3600

Note: Replace /var/www/your-app with the actual path to your Laravel project, and adjust user to match whoever owns your app files (often www-data on Ubuntu with Nginx/Apache).


Config breakdown

DirectiveWhat it does
process_nameNames each process instance. The %(process_num)02d suffix gives each one a unique number.
commandThe actual command Supervisor will run and keep alive.
autostartStart the process when Supervisor starts (e.g. on boot).
autorestartRestart the process if it exits unexpectedly.
stopasgroup / killasgroupEnsures child processes are also stopped/killed — important for PHP workers.
userThe OS user the process runs as.
numprocsHow many parallel worker processes to run. Scale this based on your workload.
redirect_stderrSends error output to the same log file as stdout.
stdout_logfileWhere logs are written.
stopwaitsecsHow long Supervisor waits for a graceful shutdown before killing the process. Match this to --max-time.

Loading and starting the workers

After saving the config, tell Supervisor to pick it up:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

reread detects new or changed config files. update applies the changes. start kicks off the processes.


Common Supervisor commands

# Check status of all managed processes
sudo supervisorctl status

# Restart your workers (e.g. after a deploy)
sudo supervisorctl restart laravel-worker:*

# Stop workers
sudo supervisorctl stop laravel-worker:*

# Tail the worker log in real time
sudo supervisorctl tail -f laravel-worker:laravel-worker_00

# Reload all configs and restart everything
sudo supervisorctl reload

Restarting workers on deploy

When you deploy new code, your queue workers are still running the old code in memory. You need to restart them. Add this to your deploy script:

sudo supervisorctl restart laravel-worker:*

Or, if you prefer a graceful approach, use Laravel’s built-in signal:

php artisan queue:restart

This tells workers to finish their current job and then exit. Supervisor sees the exit and spawns a fresh process with the new code. This is the cleaner option because no jobs get interrupted mid-execution.


Troubleshooting

If workers aren’t starting, check the Supervisor log first:

sudo tail -f /var/log/supervisor/supervisord.log

Then check your worker log:

sudo tail -f /var/www/your-app/storage/logs/worker.log

Common issues:

  • Permission denied — the user in your config doesn’t have access to the project directory or the PHP binary.
  • Command not found — use the full path to PHP if needed: /usr/bin/php instead of just php.
  • Workers keep restarting — your app is throwing a fatal error on startup. Check storage/logs/laravel.log.

Quick reference

# Install
sudo apt install supervisor -y

# Create config
sudo nano /etc/supervisor/conf.d/laravel-worker.conf

# Apply config
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

# Check status
sudo supervisorctl status

# Restart after deploy
sudo supervisorctl restart laravel-worker:*

# Or graceful restart via Laravel
php artisan queue:restart

More posts at noukeosombath.com