[{"data":1,"prerenderedAt":191},["ShallowReactive",2],{"seo-verification":3,"blog-cron-vs-systemd-timers-automate-your-linux-vps-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":12,"excerpt":13,"readTime":14,"views":15,"isPinned":16,"publishedAt":17,"category":18,"categories":23,"featuredImage":25,"bgImage":26,"posterImage":27,"relatedSolution":25,"intro":28,"sections":29,"ctaTitle":139,"ctaBody":140,"ctaButton":141,"ctaUrl":142,"relatedPosts":143},230,"cron-vs-systemd-timers-automate-your-linux-vps",{"fr":10,"en":8,"ar":11},"cron-systemd-timers-automatisation-vps","cron-مقابل-systemd-timers-أتمتة-vps-linux","cron vs systemd timers: Automate Your Linux VPS","Practical comparison of cron and systemd timers: syntax, logs, migration and troubleshooting for recurring tasks on a Linux VPS.",10,1,false,"2026-08-06T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},2,"Automation","automatisation","bg-brand-action\u002F10 text-brand-action",[24],{"id":19,"name":20,"slug":21,"color":22,"icon":21},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fcron-systemd-timers-automatisation-vps-poster.svg","On a Linux VPS, automation is not optional: nightly backups, TLS certificate renewal, log cleanup, health checks — these tasks run themselves or they don't run at all. Cron has ruled for decades, but systemd timers offer deeper integration with the service manager. This guide compares both tools, explains when to choose one over the other, and walks you through creating or migrating a systemd timer step by step.",[30,34,44,47,50,90,93,96,115,130,133,136],{"type":31,"title":32,"body":33},"h2","Why automate tasks on a VPS?","A VPS is a server running continuously, often without direct human supervision. That is precisely why automating recurring tasks is essential: nobody will be around at 3 AM to trigger a backup or renew a Let's Encrypt certificate. A forgotten task can mean data loss, an expired certificate taking the site offline, or a disk full because log rotation never ran. The two main tools available on Linux — cron and systemd timers — allow you to schedule these operations reliably.",{"type":35,"title":36,"items":37},"ul","Typical use cases on a VPS",[38,39,40,41,42,43],"**Backups** — MySQL or PostgreSQL dumps, file archiving to remote storage","**TLS certificate renewal** — `certbot renew` or `acme.sh --cron` scheduled twice a day","**Log rotation and cleanup** — deleting files older than 30 days, weekly compression","**Health checks** — verifying a service is listening, auto-restarting if needed","**Data synchronization** — `rsync` to a second node, cache refresh","**Environment cleanup** — deleting expired sessions, emptying temporary directories",{"type":31,"title":45,"body":46},"cron: a quick refresher","Cron is present on virtually every Linux system. To schedule a task, edit the current user's crontab with `crontab -e`. The syntax uses five space-separated fields: minute, hour, day of month, month, day of week, followed by the command. For example, `0 3 * * * \u002Fusr\u002Flocal\u002Fbin\u002Fbackup.sh` runs the script every day at 3 AM. Files placed in `\u002Fetc\u002Fcron.d\u002F` belong to the system and can specify the execution user directly on the line. Cron keeps no native history of past runs and does not handle missed jobs if the machine was off.",{"type":31,"title":48,"body":49},"systemd timers: an introduction","A systemd timer is a pair of two unit files: a `.service` file describing what to run, and a `.timer` file describing when to trigger it. The timer is activated with `systemctl enable --now myservice.timer` and managed by the service manager, exactly like any other systemd service. The `OnCalendar=` directive accepts rich syntax: `daily`, `Mon *-*-* 03:00:00`, `*:0\u002F15` (every 15 minutes). All output goes through journald and is accessible via `journalctl -u myservice.service`. The command `systemctl list-timers` shows all active timers, their next deadline and last activation.",{"type":51,"title":52,"headers":53,"rows":57},"comparison","cron vs systemd timers: comparison table",[54,55,56],"Criterion","cron","systemd timer",[58,62,66,70,74,78,82,86],[59,60,61],"Schedule syntax","5-field `* * * * *`","`OnCalendar=` readable (`daily`, `Mon 03:00`)",[63,64,65],"Logs","Mail output or manual redirect","Native journald, `journalctl -u`",[67,68,69],"Missed jobs (machine off)","Lost (unless `anacron`)","`Persistent=true` replays after reboot",[71,72,73],"Inter-service dependencies","None","`After=`, `Requires=`, `Wants=`",[75,76,77],"Isolation and resource limits","Inherits shell env","Cgroups, `MemoryMax=`, `CPUQuota=`",[79,80,81],"Run as specific user","User field in `\u002Fetc\u002Fcron.d\u002F`","`User=` and `Group=` in `.service`",[83,84,85],"Debugging","Hard without logs","`systemctl status`, `journalctl -xe`",[87,88,89],"Availability","All Unix systems","Systems with systemd (Debian, Ubuntu, RHEL…)",{"type":31,"title":91,"body":92},"When to keep cron?","Cron remains the right choice in several situations. On older or minimal systems without systemd — some containers, BSD, Alpine images — cron is often the only tool available. In a multi-user environment where each user manages their own tasks via `crontab -e`, cron is simpler to delegate without granting root rights. For very simple one-liner scripts, the crontab stays readable and maintainable without creating two unit files. The deciding criterion is the need for logs, dependencies or resource constraints: if you do not need them, cron does the job perfectly.",{"type":31,"title":94,"body":95},"When to switch to systemd timers?","Systemd timers become the clear choice as soon as the task goes beyond a simple isolated command. You need journald to trace every execution, its output and return code without manual plumbing? Systemd timers. Your backup script must only run after PostgreSQL is ready (`After=postgresql.service`)? Systemd timers. You want to cap the memory of a sync job so it does not starve other processes (`MemoryMax=512M`)? Systemd timers. And if the server restarts at 2:58 AM when the 3 AM backup was due, `Persistent=true` guarantees it will run at next boot.",{"type":97,"title":98,"steps":99},"steps","Create a systemd timer from scratch (example: daily backup)",[100,103,106,109,112],{"title":101,"body":102},"Create the service file","Open `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fbackup.service` and enter: `[Unit]`, `Description=Daily PostgreSQL backup`, `After=postgresql.service`, then `[Service]`, `Type=oneshot`, `User=postgres`, `ExecStart=\u002Fusr\u002Flocal\u002Fbin\u002Fbackup.sh`. The `oneshot` type indicates the service exits after the script completes.",{"title":104,"body":105},"Create the timer file","Create `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fbackup.timer` with: `[Unit]`, `Description=Daily trigger for backup`, then `[Timer]`, `OnCalendar=*-*-* 03:00:00`, `Persistent=true`, and `[Install]`, `WantedBy=timers.target`.",{"title":107,"body":108},"Reload systemd and enable the timer","Run `systemctl daemon-reload` so systemd picks up the new files, then `systemctl enable --now backup.timer` to activate and immediately start the timer.",{"title":110,"body":111},"Check the timer","Type `systemctl list-timers --all` to see your timer in the list with its next and last execution dates. Use `systemctl status backup.timer` for timer state, and `systemctl status backup.service` for the result of the last execution.",{"title":113,"body":114},"Read the logs","Access all service output with `journalctl -u backup.service` for the full history, or `journalctl -u backup.service -n 50 --since today` for the last 50 lines today.",{"type":97,"title":116,"steps":117},"Migrate an existing cron job to systemd",[118,121,124,127],{"title":119,"body":120},"Identify the cron job to migrate","List your crontabs with `crontab -l` (current user) and `cat \u002Fetc\u002Fcron.d\u002F*` (system). Note the exact command, the execution user, and the five-field schedule. For example: `30 2 * * 1 root \u002Fusr\u002Fbin\u002Fcertbot renew --quiet` means every Monday at 2:30 AM as root.",{"title":122,"body":123},"Translate the schedule to OnCalendar","The `OnCalendar=` format reads `DayOfWeek Year-Month-Day Hour:Minute:Second`. `30 2 * * 1` becomes `Mon *-*-* 02:30:00`. To test the translation before applying it, use `systemd-analyze calendar 'Mon *-*-* 02:30:00'` which displays the next 10 calculated occurrences.",{"title":125,"body":126},"Create the .service and .timer files","Create `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fcertbot-renew.service` with `Type=oneshot`, `ExecStart=\u002Fusr\u002Fbin\u002Fcertbot renew --quiet`, and `User=root`. Then create `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fcertbot-renew.timer` with `OnCalendar=Mon *-*-* 02:30:00` and `Persistent=true`. Run `systemctl daemon-reload && systemctl enable --now certbot-renew.timer`.",{"title":128,"body":129},"Disable the cron line and validate","Comment out or delete the line in the original crontab. Test immediately with `systemctl start certbot-renew.service` and check the result via `journalctl -u certbot-renew.service -n 20`. Verify the timer appears in `systemctl list-timers`.",{"type":131,"body":132},"tip","For a task that must run a few minutes after boot and then regularly, combine `OnBootSec=5min` and `OnUnitActiveSec=1h` in the `[Timer]` block. The job starts 5 minutes after boot, then every hour from there — without depending on a fixed clock time.",{"type":31,"title":134,"body":135},"Common systemd timer troubleshooting","Three problems come up frequently when setting up timers. First: the timer is active but never triggers. Check with `systemctl list-timers` that the `NEXT` column shows a coherent date, and that `systemctl status backup.timer` shows `active (waiting)`. A forgotten `daemon-reload` after modifying a unit file is the most common cause. Second: the service fails silently. Check `journalctl -u myservice.service -n 50`. Verify that the `ExecStart=` path is absolute. Third: missed tasks are not replayed after reboot. Make sure `Persistent=true` is present in the `[Timer]` block.",{"type":31,"title":137,"body":138},"Conclusion","Cron and systemd timers coexist without issue on the same server — you do not have to migrate everything at once. Keep cron for your simple tasks and existing user scripts, and adopt systemd timers for new automations that benefit from journald logs, inter-service dependencies or cgroup isolation.","A Linux VPS ready for your automations","Our cloud VPS running Ubuntu and Debian include systemd, journald and the full modern stack. Deploy your timers, scripts and backups on reliable infrastructure, with full root access and responsive support.","Launch a Linux VPS","\u002Fvps-cloud",[144,159,173],{"id":145,"slug":146,"slugs":147,"title":150,"excerpt":151,"readTime":152,"views":153,"isPinned":16,"publishedAt":154,"category":155,"categories":156,"featuredImage":25,"bgImage":26,"posterImage":158,"relatedSolution":25},31,"installing-apache-airflow-on-a-vps-self-hosted-automation",{"fr":148,"en":146,"ar":149},"installer-apache-airflow-vps","تثبيت-apache-airflow-على-خادم-vps-أتمتة-ذاتية-الاستضافة","Apache Airflow on VPS: Docker Setup and CVE-2026-58076","Deploy Apache Airflow on a VPS with Docker Compose. Complete guide including the fix for CVE-2026-58076 (CVSS 9.1): update to Airflow 2.10.4 and hardening procedure.",5,0,"2026-05-20T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[157],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Finstaller-apache-airflow-vps-poster.svg",{"id":160,"slug":161,"slugs":162,"title":165,"excerpt":166,"readTime":167,"views":15,"isPinned":16,"publishedAt":168,"category":169,"categories":170,"featuredImage":25,"bgImage":26,"posterImage":172,"relatedSolution":25},212,"woodpecker-ci-and-forgejo-cicd-pipeline-on-a-vps",{"fr":163,"en":161,"ar":164},"woodpecker-ci-pipeline-vps-forgejo","woodpecker-ci-وforgejo-خط-أنابيب-cicd-على-خادم-vps","Woodpecker CI and Forgejo: CI\u002FCD pipeline on a VPS","Deploy Woodpecker CI with Forgejo on your VPS for a self-hosted, lightweight and sovereign open source CI\u002FCD pipeline. Step-by-step Docker guide.",4,"2026-08-02T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[171],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fwoodpecker-ci-pipeline-vps-forgejo-poster.svg",{"id":174,"slug":175,"slugs":176,"title":179,"excerpt":180,"readTime":181,"views":182,"isPinned":16,"publishedAt":183,"category":184,"categories":185,"featuredImage":25,"bgImage":26,"posterImage":187,"relatedSolution":188},29,"installing-kestra-on-a-vps-self-hosted-automation",{"fr":177,"en":175,"ar":178},"installer-kestra-vps","تثبيت-kestra-على-خادم-vps-أتمتة-ذاتية-الاستضافة","Installing Kestra on a VPS: self-hosted automation","Install Kestra on your VPS: orchestration of declarative workflows in YAML for your data and ETL pipelines, self-hosted with Docker.",3,7,"2026-05-22T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[186],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Finstaller-kestra-vps-poster.svg",{"categorySlug":189,"appSlug":190},"automation-workflows","kestra",1787580993966]