systemd timers instead of cron

A cron job that fails writes to a mail spool nobody reads, has no record of when it last ran, and starts a second copy if the first is still going. A timer unit fixes all three because the job is a service.

# shop-export.timer
[Timer]
OnCalendar=*-*-* 02:00:00
RandomizedDelaySec=300
Persistent=true

[Install]
WantedBy=timers.target

Persistent=true runs a missed occurrence after a reboot, which cron cannot do at all. The service unit it triggers gets journal logging, a failure state visible in systemctl, and — because a service is either running or not — no overlapping second copy. RandomizedDelaySec is worth setting on a fleet, or every machine hits the same endpoint at 02:00:00.