Skip to navigation

Timer

timer "cleanup" {
user = "root"
command = ["/usr/local/bin/example-cleanup"]
on_calendar = "*-*-* 03:15:00"
persistent = true
randomized_delay = "5m"
accuracy = "1s"
enabled = true
}

A timer runs a command on a schedule using systemd. Rivet writes two units to /etc/systemd/system: a .timer and the oneshot .service it starts, both root-owned with mode 0644. name sets the unit name; without it, Rivet derives a stable name from the resource’s address. Other resources can’t manage either unit file, and unmanaged drop-ins, masks, or aliases for them are refused so nothing overrides the job.

Schedule and command

A present timer needs a command, as a list of arguments with an absolute executable, and at least one trigger:

  • on_calendar: a systemd calendar expression, checked on the host with systemd-analyze calendar.
  • on_boot, on_active, on_unit_active, on_unit_inactive: durations relative to boot, timer activation, or the service’s last start or stop.

Several triggers combine the way systemd combines them. Durations are positive integers with ms, s, m, or h; randomized_delay also accepts 0s. persistent = true runs a missed calendar job at the next opportunity and needs on_calendar.

The command runs as user (default root), with optional group, cwd (default /), environment, and umask (default 0022). Arguments are passed as-is: systemd % specifiers are escaped, and there is no shell or variable expansion; to use a shell, make it the command, as in ["/bin/sh", "-c", "..."].

Enabling and updating

enabled = true means the timer is active now and starts at boot. false stops and disables it but keeps its unit files. When a definition changes, Rivet stops the timer, writes the new units, reloads systemd, and restores the requested state. Unchanged units aren’t rewritten, and Rivet never runs the job itself or stops a job that is running. Systemd prevents overlapping runs of the job.

ensure = "absent" disables the timer, removes both units, and reloads systemd. It refuses while the job is running. Systemd’s record of past runs is kept.

If a run is interrupted, the next one restores both units and the timer’s state without running the job.

Attributes

AttributeDefaultBehavior
nameDerived from logical IDNormalized .timer name; owns the paired same-stem .service.
ensurepresentpresent or absent.
enabledtrueActive now and enabled at boot; false stops and disables scheduling.
commandRequired when presentNonempty argv with an absolute executable.
userrootLocal account name.
groupUser’s primary groupOptional local group name; null omits it.
cwd/Absolute working directory.
environmentEmptyString-valued environment map.
umask0022Octal string.
on_calendarOmittedNative calendar schedule, checked on the target.
on_bootOmittedDuration since boot.
on_activeOmittedDuration since timer activation.
on_unit_activeOmittedDuration since the paired service last activated.
on_unit_inactiveOmittedDuration since the paired service last became inactive.
persistentfalseCalendar catch-up policy; requires on_calendar.
randomized_delay0sRandom delay; 0s is allowed.
accuracy1sPositive schedule accuracy duration.

user and group take names, not numeric IDs, and managed users and groups are ordered before the timer. All common metadata applies, but timers can’t be notification targets.

The default timeout is 120 seconds. Timers need timer.systemd.v1 and refresh.journal.v1. Static exports are name, ensure, and meta.sensitive. There is no cron resource; use timers instead.