Manage Background Processes on VPS with Supervisor
Supervisor is a process control system written in Python designed to monitor and control background processes on Unix/Linux. It's commonly used for Laravel Queue Workers, Celery workers, Python bots, or services that don't have a systemd unit file. This article shows you how to set up Supervisor to manage processes that need to run continuously.
Installing Supervisor
sudo apt update
sudo apt install supervisor -y
sudo systemctl enable --now supervisor
# Check status
sudo supervisorctl status
Adding Program Config
Create a config file in /etc/supervisor/conf.d/ for each program:
sudo nano /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/myapp/artisan queue:work redis --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/log/supervisor/laravel-worker.log
stopwaitsecs=3600
# Python worker example
[program:celery-worker]
command=/home/ubuntu/myapp/venv/bin/celery -A myapp worker --loglevel=info
directory=/home/ubuntu/myapp
user=ubuntu
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/celery.log
stderr_logfile=/var/log/supervisor/celery-error.log
supervisorctl Commands
# Reload config
sudo supervisorctl reread
sudo supervisorctl update
# View all status
sudo supervisorctl status
# start/stop/restart
sudo supervisorctl start laravel-worker:*
sudo supervisorctl stop laravel-worker:*
sudo supervisorctl restart laravel-worker:*
# View logs in real-time
sudo supervisorctl tail -f laravel-worker:laravel-worker_00
numprocs=4 creates 4 processes named laravel-worker_00 to laravel-worker_03. Use the wildcard laravel-worker:* to control all processes at once.
Supervisor Web Interface
sudo nano /etc/supervisor/supervisord.conf
# Add to [inet_http_server]
[inet_http_server]
port = 127.0.0.1:9001 # bind to localhost only
username = admin
password = SecurePassword123
sudo supervisorctl reload
# Access http://localhost:9001 via SSH tunnel
Verify Supervisor is Working Correctly
# Check if supervisord is running
systemctl status supervisor
# View all processes
sudo supervisorctl status
# Get PID of a process
sudo supervisorctl pid laravel-worker:laravel-worker_00
# View logs
sudo tail -f /var/log/supervisor/laravel-worker.log
startretries=3, after retries are exhausted, the status becomes FATAL.
Common Issues & Troubleshooting
supervisorctl status shows STOPPED or FATAL
The command in the config is wrong, or the user lacks permission to run it. Check the logs to find the error:
# View process logs
sudo tail -50 /var/log/supervisor/laravel-worker.log
# Test run the command directly
sudo -u www-data php /var/www/myapp/artisan queue:work redis --once
New config not loading
You must run reread and update after editing config, not just reload:
sudo supervisorctl reread # Read new config
sudo supervisorctl update # Apply changes
sudo supervisorctl status # Check result
Process consuming increasing memory (memory leak)
Set max_memory_mb in the config to auto-restart when memory exceeds limit (requires superlance plugin):
# Or set restart based on job count (for Laravel queue)
command=php artisan queue:work --max-jobs=500 # restart after 500 jobs
# Or
command=php artisan queue:work --max-time=3600 # restart every 1 hour
Process doesn't stop gracefully
The signal sent when stopping is TERM by default. Some processes require a different signal:
[program:myworker]
...
stopsignal=INT # Send SIGINT (Ctrl+C) instead of SIGTERM
stopwaitsecs=60 # Wait 60 seconds before SIGKILL
Frequently Asked Questions
How is Supervisor different from systemd? Which should I use?
systemd is Linux' init system and works with any service. Supervisor is a Python application best suited for managing multiple similar processes (like multiple worker copies) with simpler configuration than systemd. For single main services, systemd is better. For worker pools, Supervisor is more convenient.
How quickly does Supervisor detect a process crash?
Supervisor monitors using an event loop that detects process exit immediately (no polling needed). So restart happens almost instantly, within 1-2 seconds.
How do I restart Supervisor processes after deploying new code?
For queue workers, always restart after deploy since old code still loads in memory. Add this to your deploy script: supervisorctl restart laravel-worker:*. Or for Laravel, use php artisan queue:restart and Supervisor will detect the worker exit and restart automatically.