From 086bfba7d321fad23f03284091751594a42c7819 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Sat, 28 Sep 2024 22:22:42 +0200 Subject: [PATCH] use systemd for renew job --- handlers/main.yml | 7 +++ tasks/main.yml | 46 +++++++++++-------- templates/cron-lego-renew.sh.j2 | 13 ------ templates/etc/sysconfig/lego.j2 | 6 +++ .../etc/systemd/system/lego-renew.service.j2 | 17 +++++++ .../etc/systemd/system/lego-renew.timer.j2 | 9 ++++ 6 files changed, 67 insertions(+), 31 deletions(-) create mode 100644 handlers/main.yml delete mode 100644 templates/cron-lego-renew.sh.j2 create mode 100644 templates/etc/sysconfig/lego.j2 create mode 100644 templates/etc/systemd/system/lego-renew.service.j2 create mode 100644 templates/etc/systemd/system/lego-renew.timer.j2 diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..452e151 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: Restart lego renew + ansible.builtin.service: + state: restarted + daemon_reload: True + name: lego-renew.service + listen: __lego_restart diff --git a/tasks/main.yml b/tasks/main.yml index c436c24..70c092b 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -10,7 +10,7 @@ - name: Create lego base dir ansible.builtin.file: - path: "{{ __lego_base_dir }}/bin" + path: "{{ __lego_base_dir }}/hooks" state: directory owner: root group: root @@ -28,7 +28,7 @@ - name: Create hook scripts ansible.builtin.copy: content: "{{ item.hook }}" - dest: "{{ __lego_base_dir }}/bin/hook-{{ item.name }}.sh" + dest: "{{ __lego_base_dir }}/hooks/{{ item.name }}.sh" owner: root group: root mode: "0700" @@ -47,7 +47,7 @@ --dns="cloudflare" {{ '--dns.resolvers="' + lego_dns_resolvers | join(',') + '"' if lego_dns_resolvers | length > 0 else '' }} run - {{ '--run-hook="' + __lego_base_dir + '/bin/hook-' + item.name + '.sh"' if item.hook is defined else '' }} + {{ '--run-hook="' + __lego_base_dir + '/hooks/' + item.name + '.sh"' if item.hook is defined else '' }} args: creates: "{{ __lego_base_dir }}/.lego/certificates/{{ item.domains[0] }}.crt" environment: @@ -59,20 +59,30 @@ loop_control: label: "{{ item.name }}" -- name: Add cron scipt to renew certificates +- name: Write environment file ansible.builtin.template: - dest: "{{ __lego_base_dir }}/bin/cron-lego-renew.sh" - mode: "0700" - owner: root - group: root - src: cron-lego-renew.sh.j2 + src: etc/sysconfig/lego.j2 + dest: /etc/sysconfig/lego + mode: "0600" + notify: __lego_restart -- name: Add cron job to renew certificates - ansible.builtin.cron: - name: "lego-renew" - cron_file: "lego-renew" - job: "{{ __lego_base_dir }}/bin/cron-lego-renew.sh >> {{ __lego_base_dir }}/cron_lego_renew.log 2>&1" - hour: "{{ lego_cron_hour }}" - minute: "{{ lego_cron_minute }}" - user: root - state: "{{ 'present' if lego_cron_enabled | bool else 'absent' }}" +- name: Write timer file + ansible.builtin.template: + src: etc/systemd/system/lego-renew.timer.j2 + dest: /etc/systemd/system/lego-renew.timer + mode: "0644" + notify: __lego_restart + +- name: Write service file + ansible.builtin.template: + src: etc/systemd/system/lego-renew.service.j2 + dest: /etc/systemd/system/lego-renew.service + mode: "0644" + notify: __lego_restart + +- name: Ensure renew timer is up and running + ansible.builtin.service: + name: lego-renew.timer + daemon_reload: True + enabled: True + state: started diff --git a/templates/cron-lego-renew.sh.j2 b/templates/cron-lego-renew.sh.j2 deleted file mode 100644 index 2e82c51..0000000 --- a/templates/cron-lego-renew.sh.j2 +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# run this script daily to renew any letsencrypt certs that need renewing -# renew cert if it expires within 30 days - -export LEGO_SERVER="{{ lego_acme_server }}/directory" -export LEGO_PATH="{{ __lego_base_dir }}/.lego" -export CLOUDFLARE_DNS_API_TOKEN="{{ lego_cloudflare_api_token }}" - -{% for cert in lego_certificates %} -echo "$(date) checking for cert update for {{ ', '.join(cert.domains) }}." -{{ __lego_bin_file }} --email="{{ lego_acme_account_email }}" --domains {{ ' --domains '.join(cert.domains) }} --key-type="{{ lego_key_type }}" --dns="cloudflare" {{ '--dns.resolvers="' + lego_dns_resolvers | join(',') + '"' if lego_dns_resolvers | length > 0 else '' }} renew {{ '--renew-hook="' + __lego_base_dir + '/bin/hook-' + cert.name + '.sh"' if cert.hook is defined else '' }} --days 30 - -{% endfor %} diff --git a/templates/etc/sysconfig/lego.j2 b/templates/etc/sysconfig/lego.j2 new file mode 100644 index 0000000..abd4014 --- /dev/null +++ b/templates/etc/sysconfig/lego.j2 @@ -0,0 +1,6 @@ +#jinja2:lstrip_blocks: True +{{ ansible_managed | comment }} +LEGO_SERVER="{{ lego_acme_server }}/directory" +LEGO_PATH="{{ __lego_base_dir }}/.lego" +CLOUDFLARE_DNS_API_TOKEN="{{ lego_cloudflare_api_token }}" +ARGS=--dns=cloudflare {{ '--dns.resolvers="' + lego_dns_resolvers | join(',') + '"' if lego_dns_resolvers | length > 0 else '' }} --key-type="{{ lego_key_type }}" diff --git a/templates/etc/systemd/system/lego-renew.service.j2 b/templates/etc/systemd/system/lego-renew.service.j2 new file mode 100644 index 0000000..ba254ae --- /dev/null +++ b/templates/etc/systemd/system/lego-renew.service.j2 @@ -0,0 +1,17 @@ +#jinja2:lstrip_blocks: True +{{ ansible_managed | comment }} +[Unit] +Description=Lego renew +Requires=network-online.target +After=network-online.target + +[Service] +Type=oneshot +EnvironmentFile=/etc/sysconfig/lego + +{% for cert in lego_certificates %} +ExecStart={{ __lego_bin_file }} --email="{{ lego_acme_account_email }}" --domains {{ ' --domains '.join(cert.domains) }} $ARGS renew {{ '--renew-hook="' + __lego_base_dir + '/hooks/' + cert.name + '.sh"' if cert.hook is defined else '' }} --days 30 +{% endfor %} + +[Install] +WantedBy=multi-user.target diff --git a/templates/etc/systemd/system/lego-renew.timer.j2 b/templates/etc/systemd/system/lego-renew.timer.j2 new file mode 100644 index 0000000..fbe547b --- /dev/null +++ b/templates/etc/systemd/system/lego-renew.timer.j2 @@ -0,0 +1,9 @@ +[Unit] +Description=Lego renew + +[Timer] +OnCalendar={{ lego_renew_interval }} +Persistent=true + +[Install] +WantedBy=timers.target