{"id":4826,"date":"2026-08-29T18:50:33","date_gmt":"2026-08-29T09:50:33","guid":{"rendered":"https:\/\/donguri3.net\/server-tech\/systemd-timer-setup-2\/"},"modified":"2026-08-29T18:50:34","modified_gmt":"2026-08-29T09:50:34","slug":"systemd-timer-setup","status":"publish","type":"post","link":"https:\/\/donguri3.net\/en\/server-tech\/n8n-automation\/systemd-timer-setup\/","title":{"rendered":"Creating an Automated Script That Runs Every Midnight! ~ Migrating from crontab to systemd Timer ~"},"content":{"rendered":"<p>This time, we will explain how to migrate from using <code>crontab<\/code> to <code>systemd Timer<\/code>, based on the crontab script we used for updating Let&#8217;s Encrypt certificates!<\/p>\n<hr \/>\n<h2>The Objective<\/h2>\n<p>We want to run a script every day at midnight (00:00) to renew our SSL certificate!<br \/>\nOriginally, it was running with the following <code>crontab<\/code> configuration:<\/p>\n<div class=\"contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950\">\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism undefined-numbers lang-plain\" data-lang=\"Plain Text\"><code>0 0 * * * bash \/tmp\/letsencrypt.sh<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>We will change this configuration to <code>systemd Timer<\/code> to enable more flexible and convenient management.<\/p>\n<hr \/>\n<h2>Procedure: Setting up using a Timer<\/h2>\n<h3>Creating the Service File<\/h3>\n<p>First, create a &#8220;service file&#8221; to execute the script. Save the following content with the name <code>\/etc\/systemd\/system\/letsencrypt-renew.service<\/code>.<\/p>\n<div class=\"contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950\">\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism undefined-numbers lang-plain\" data-lang=\"Plain Text\"><code>[Unit]\nDescription=Run Let's Encrypt renewal script\nWants=letsencrypt-renew.timer\n\n[Service]\nType=oneshot\nExecStart=\/bin\/bash \/tmp\/letsencrypt.sh\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<h3>Creating the Timer File<\/h3>\n<p>Next, create a &#8220;timer file&#8221; that defines the execution schedule. Write the following content to <code>\/etc\/systemd\/system\/letsencrypt-renew.timer<\/code>.<\/p>\n<div class=\"contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950\">\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism undefined-numbers lang-plain\" data-lang=\"Plain Text\"><code>[Unit]\nDescription=Run Let's Encrypt renewal script daily at midnight\n\n[Timer]\nOnCalendar=*-*-* 00:00:00\nPersistent=true\n\n[Install]\nWantedBy=timers.target<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>Here, <code>OnCalendar=*-*-* 00:00:00<\/code> specifies execution at &#8220;midnight every day.&#8221;<\/p>\n<h3>Applying the Settings and Enabling the Timer<\/h3>\n<p>Run the following commands in order to apply the configuration.<\/p>\n<div class=\"contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950\">\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism undefined-numbers lang-bash\" data-lang=\"Bash\"><code>sudo systemctl daemon-reload\nsudo systemctl enable letsencrypt-renew.timer\nsudo systemctl start letsencrypt-renew.timer<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p>To verify that the settings have been applied correctly, run the following:<\/p>\n<div class=\"contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950\">\n<div class=\"overflow-y-auto p-4\" dir=\"ltr\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism undefined-numbers lang-bash\" data-lang=\"Bash\"><code>sudo systemctl list-timers --all<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<hr \/>\n<h2>Complete!<\/h2>\n<p>Now, the Let&#8217;s Encrypt certificate renewal script will automatically run every day at midnight! Using <code>systemd Timer<\/code> is very convenient because it makes retrying after failures and checking logs much easier.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This time, we will explain how to migrate from using crontab to systemd Timer, based on the crontab script we  [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":1071,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"en_US","_original_post":"https:\/\/donguri3.net\/?p=133","footnotes":""},"categories":[1167],"tags":[97],"class_list":["post-4826","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-n8n-automation","tag-ssl","en-US"],"_links":{"self":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/4826","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/comments?post=4826"}],"version-history":[{"count":1,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/4826\/revisions"}],"predecessor-version":[{"id":4829,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/4826\/revisions\/4829"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media\/1071"}],"wp:attachment":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media?parent=4826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/categories?post=4826"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/tags?post=4826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}