When a systemd timer for a backup job stops after a kernel update: the `Persistent=true` fix

The underlying problem

When a systemd timer stops firing after a kernel upgrade, the first thing that comes to mind is “something broke during the reboot.” In reality the timer is still in the unit files; it’s the time‑keeping that gets reset. The kernel’s real‑time clock (RTC) is re‑synchronised, and any timers that were scheduled for a time in the past are dropped unless you tell systemd to treat them as persistent.

A timer unit (*.timer) is just a wrapper around a service. When the timer fires, systemd starts the associated service. The schedule lives in OnCalendar= or OnActiveSec=. For example:

[Timer]
OnCalendar=weekly
Persistent=true
Unit=backup.service

With Persistent=true, systemd will catch up on missed activations that happened while the machine was powered off. Without it, any activations that were scheduled during downtime are discarded.

During a kernel upgrade the system reboots, re‑initialises its timekeeping, and if the machine was off longer than the interval between timer activations, systemd treats the missed activations as “in the past” and drops them unless Persistent=true is set. On most distributions the default is Persistent=false, so a weekly backup scheduled for 02:00 UTC will not run if the machine was down from 01:00 UTC to 03:00 UTC. The timer file remains, but systemd simply ignores the missed run.


Reproducing the issue

  1. Create a test timer that runs a harmless script every minute.

    sudo tee /etc/systemd/system/test.timer > /dev/null <<'EOF'
    [Unit]
    Description=Minute‑interval test timer
    
    [Timer]
    OnCalendar=*-*-* *:*:00
    Unit=test.service
    
    [Install]
    WantedBy=timers.target
    EOF
    
    sudo tee /etc/systemd/system/test.service > /dev/null <<'EOF'
    [Unit]
    Description=Test service
    
    [Service]
    ExecStart=/usr/bin/echo "Timer fired at $(date)" >> /var/log/test.log
    EOF
    
  2. Enable and start the timer.

    sudo systemctl enable --now test.timer
    
  3. Verify it runs.

    tail -f /var/log/test.log
    

    You should see a new line every minute.

  4. Simulate a kernel upgrade by rebooting the machine.

    sudo reboot
    
  5. After the reboot, check the log again. If the machine was down for more than a minute, you’ll notice that the log stops growing. The timer unit is still active (systemctl list-timers will show it), but systemd has dropped the missed activations.


The Persistent=true directive

Adding Persistent=true tells systemd to remember that the timer should have fired even if the machine was off. When the machine comes back online, systemd will start the service immediately to “catch up.” After that, it resumes the normal schedule.


See also