Well, I don’t currently really have a good reason to replace a working cron job with systemd-timer beside practicing it.

The following is the existing cron task for www-data user. I want to convert this cron to a systemd-timer:

$ sudo crontab -l -u www-data

# m h  dom mon dow   command
*/5 * * * * php -f /var/www/nextcloud/cron.php

The above output indicates that the command php -f /var/www/nextcloud/cron.php is run at every 5th minute, of course by www-data user.

Let’s see the equivalent of the systemd-timer version. To use systemd-timer, we need 2 services with the same name, but different suffixes. I’m going to name this systemd service nextcloud-cron, so the 2 correspondence service are: nextcloud-cron.service and nextcloud-cron.timer.

First, let’s create the service unit /etc/systemd/system/nextcloud-cron.service. Note that I need to provide /usr/bin/php full path instead of just specifying php.

[Unit]
Description=Nextcloud internal processes 
background jobs on demand
Wants=nextcloud-cron.timer

[Service]
Type=oneshot
User=www-data
ExecStart=/usr/bin/php -f /var/www/nextcloud/cron.php

[Install]
WantedBy=multi-user.target

Next, we create the /etc/systemd/system/nextcloud-cron.timer, where we define the time when the nextcloud-cron.serice is triggered. The systemd-timer, at least at this time of writing, we can’t specify */5 to denote the timer to go off every 5 minutes. A work around is to list all possible minutes divisible by 5.

[Unit]
Description=Nextcloud internal processes background jobs on demand
Requires=nextcloud-cron.service

[Timer]
Unit=nextcloud-cron.service
OnCalendar=*-*-* *:5,10,15,20,25,30,35,40,45,50,55:00

[Install]
WantedBy=timers.target

Finally, we reload the systemd daemon, and start/enable the nextcloud-cron.timer (not the .service, this will be triggered by the .timer one).

$ sudo systemctl daemon-reload

$ sudo systemctl enable --now nextcloud-cron.timer
Created symlink /etc/systemd/system/timers.target.wants/nextcloud-cron.timer → /etc/systemd/system/nextcloud-cron.timer.

$ sudo systemctl status nextcloud-cron.timer
● nextcloud-cron.timer - Nextcloud internal processes background jobs on demand
     Loaded: loaded (/etc/systemd/system/nextcloud-cron.timer; enabled; preset: enabled)
     Active: active (waiting) since Tue 2024-09-03 08:10:14 UTC; 28s ago
    Trigger: Tue 2024-09-03 08:15:00 UTC; 4min 16s left
   Triggers: ● nextcloud-cron.service

$ sudo systemctl status nextcloud-cron.service
○ nextcloud-cron.service - Nextcloud internal processes background jobs on demand
     Loaded: loaded (/etc/systemd/system/nextcloud-cron.service; disabled; preset: enabled)
     Active: inactive (dead) since Tue 2024-09-03 08:15:00 UTC; 1min 3s ago
TriggeredBy: ● nextcloud-cron.timer
    Process: 107502 ExecStart=/usr/bin/php -f /var/www/nextcloud/cron.php (code=exited, status=0/SUCCESS)
   Main PID: 107502 (code=exited, status=0/SUCCESS)
        CPU: 245ms

Sep 03 08:15:00 totoro systemd[1]: Starting nextcloud-cron.service - Nextcloud internal processes background jobs on demand...
Sep 03 08:15:00 totoro systemd[1]: nextcloud-cron.service: Deactivated successfully.
Sep 03 08:15:00 totoro systemd[1]: Finished nextcloud-cron.service - Nextcloud internal processes background jobs on demand...

Of course, don’t forget to disable the existing cron task (cron -u www-data -e) to avoid duplication of this task running by both cron and systemd-timer.

References: