Laravel provides a convenient way to define scheduled tasks using its task scheduler. Instead of creating a separate Linux cron entry for every Laravel command, you can define your scheduled tasks inside the Laravel application and let Laravel handle when each task should run.
On Ubuntu, the most common approach is to use CronTab to execute Laravel’s schedule:run command every minute.
This article focuses on two practical ways to run Laravel’s scheduler:
- Using Ubuntu CronTab with
www-data - Using Supervisor as an alternative to CronTab
1. Configure CronTab for the www-data User
For a Laravel application hosted by Apache or Nginx, PHP processes commonly run as the www-data user.
It is therefore a good practice to run Laravel’s scheduler as the same user that owns or operates the application.
Open the www-data user’s crontab:
sudo crontab -u www-data -e
This opens the CronTab specifically for the www-data user.
Add the following entry:
* * * * * cd /var/www/website.com && php artisan schedule:run >> /var/www/website.com/storage/cron.log 2>&1
This runs every minute.
Check the Cron Configuration
After saving the crontab, verify it:
sudo crontab -u www-data -l
You should see:
* * * * * cd /var/www/website.com && php artisan schedule:run >> /var/www/website.com/storage/cron.log 2>&1
You can then monitor the Laravel scheduler log:
sudo tail -f /var/www/website.com/storage/cron.log
If Laravel’s scheduled commands produce output, it will be written to this file.
2. Alternative: Running schedule:run Using Supervisor
CronTab is the traditional approach, but another option is to use Supervisor to keep the Laravel scheduler process running.
First, install Supervisor:
sudo apt update
sudo apt install supervisor
Create a Supervisor configuration:
sudo nano /etc/supervisor/conf.d/laravel-scheduler.conf
Add:
[program:laravel-scheduler]
process_name=%(program_name)s
command=/usr/bin/php /var/www/website.com/artisan schedule:run
directory=/var/www/website.com
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/website.com/storage/cron.log
stopwaitsecs=3600
Then reload Supervisor:
sudo supervisorctl reread
sudo supervisorctl update
Start the scheduler:
sudo supervisorctl start laravel-scheduler
Check its status:
sudo supervisorctl status
You should see something similar to:
laravel-scheduler RUNNING
Important Difference
There is an important distinction between CronTab and Supervisor.
With CronTab:
* * * * * cd /var/www/website.com && php artisan schedule:run >> /var/www/website.com/storage/cron.log 2>&1
the operating system starts schedule:run every minute.
With Supervisor, the configured command is kept running and Supervisor restarts it if the process exits.
However, php artisan schedule:run is designed as a short-lived scheduler invocation: it checks which tasks are due and then exits. Because of that, using Supervisor directly with schedule:run can cause it to repeatedly restart the process.
For a continuously running Laravel scheduler, Laravel’s long-running scheduling command is generally a better fit where supported by the Laravel version.
For example:
command=/usr/bin/php /var/www/website.com/artisan schedule:work
This keeps Laravel’s scheduler running continuously, while Supervisor handles process monitoring and automatic restarts.
The configuration would then be:
[program:laravel-scheduler]
process_name=%(program_name)s
command=/usr/bin/php /var/www/website.com/artisan schedule:work
directory=/var/www/website.com
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/website.com/storage/cron.log
stopwaitsecs=3600
After changing the configuration:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart laravel-scheduler
CronTab vs Supervisor
| Feature | CronTab | Supervisor |
|---|---|---|
| Setup | Simple | More configuration |
schedule:run | Excellent fit | Not ideal as a persistent process |
schedule:work | Not required | Good fit |
| Process monitoring | No | Yes |
| Automatic restart | No | Yes |
| Log handling | Shell redirection | Supervisor logging |
| Recommended for basic scheduling | Yes | Optional |
Recommended Setup
For most Laravel applications on Ubuntu, the simplest setup is:
sudo crontab -u www-data -e
Then:
* * * * * cd /var/www/website.com && php artisan schedule:run >> /var/www/website.com/storage/cron.log 2>&1
This is lightweight, easy to troubleshoot, and follows Laravel’s traditional scheduler deployment model.
If you specifically want a continuously running process with process supervision, use Supervisor with:
php artisan schedule:work
rather than repeatedly restarting:
php artisan schedule:run
The key principle is simple:
CronTab triggers Laravel’s scheduler; Laravel decides which scheduled tasks should actually run.
