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:

  1. Using Ubuntu CronTab with www-data
  2. 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

FeatureCronTabSupervisor
SetupSimpleMore configuration
schedule:runExcellent fitNot ideal as a persistent process
schedule:workNot requiredGood fit
Process monitoringNoYes
Automatic restartNoYes
Log handlingShell redirectionSupervisor logging
Recommended for basic schedulingYesOptional

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.