diff --git a/README.md b/README.md index 2d91e957d95e9ce876b7e539139da878c7f7c803..20c56149829852283d1657a1a73bfe272dfe9341 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,95 @@ -ansible-certbot -========= +# hdacloud.certs -Deploy certbot and enable auto-renew. +Role to obtain certificates from Let's Encrypt using either [certbot][certbot] or [lego-acme][lego-acme]. +Refer to the variables below to obtain certificates. -Role Variables --------------- +## Role Variables + +The role variables are split up into three categories. A general one and two specialized sets of variables +depending on whether or not you are using `dns_challenge` or not. + +### General Settings + +| Variable | Description | Type | Default | +|---|---|---|---| +| `cert_fqdns` | List of FQDNs the certificate should be valid for | `List<string>` | `[]` | +| `admin_email` | Email for expiry notifications | `string` | `''` | +| `dns_challenge` | Whether to use a dns challenge for obtaining certificates. Refer to 'DNS challenge settings' if true, otherwise to section 'WebServer Settings' | `boolean` | `false` | +| `renewal_hook_file_name` | Filename of the renewal script file | `string` | `''` | +| `renewal_hook` | Contents of the renewal script. this should be used to restart services after a new certificate has been obtained. | `string` | `''` | + + +### DNS Challenge: `true` + +These settings need to be provided when a DNS challenge is used. + +| Variable | Description | Type | Default | +|---|---|---|---| +| `lego_version` | The version of the [lego-acme][lego-acme] client binary to be used. | `string` | `4.11.0` | +| `lego_extra_flags` | Additional arguments / flags to be passed to the `lego` command. | `List<string>` | `[]` | +| `lego_dns_provider` | The DNS provider to be used for the DNS challenge. A full list of the supported providers can be found [here][lego-dns-providers]. | `string` | `designate` | +| `dns_provider_auth_env_variables` | Dictionary of environment variables used by the selected DNS provider. | `Dictionary<string, string>` | `{}` | -```yaml ---- -# certbot settings -certbot_dns_challenge: false # default use webserver, true to obtain certificate using dns challenge -certbot_lego_version: "4.11.0" # version of LEGO client -certbot_dns_provider: "designate" # list of available providers https://go-acme.github.io/lego/dns/ -dns_provider_auth_env_variables: # variables required to authenticate dns provider - OS_AUTH_URL: "https://openstack.example.org" - OS_REGION_NAME: "RegionOne" - OS_AUTH_TYP: "v3applicationcredential" # default is to use application credential rather than password - OS_APPLICATION_CREDENTIAL_ID: "{{ vault_os_application_credential_id }}" - OS_APPLICATION_CREDENTIAL_SECRET: "{{ vault_os_application_credential_secret }}" - - -certbot_fqdn: - - example.de -certbot_admin_email: "admin@example.de" -# certbot_webroot: "/var/www/example" # if undefined use --standalone - -# application settings -# certbot_application: "example" # if defined copy certs to application dir and setup deploy hooks -certbot_application_dir: "/etc/{{ certbot_application }}" -certbot_application_deploy_hook: | - #!/bin/sh - - cp {{ certbot_live_dir }}/fullchain.pem {{ certbot_application_dir }} - cp {{ certbot_live_dir }}/privkey.pem {{ certbot_application_dir }} - - systemctl restart {{ certbot_application }}.service -``` -Example Playbook ----------------- +### DNS Challenge: `false` + +These settings optionally need to be provided when no DNS challenge is used. + +| Variable | Description | Type | Default | +|---|---|---|---| +| `certbot_webroot` | If you are already running a web server on your instance provide a path that is served on port `80` here, to allow the HTTP challenge to be completed when obtaining the certificate. | `string` | `undefined` | + +## Example Playbook ```yaml # requirements.yaml roles: - - name: hdacloud.certbot + - name: hdacloud.certs src: git+https://code.fbi.h-da.de/hdacloud/ansible_certbot version: main ``` +#### Example using DNS challenge with designate provider ```yaml - hosts: all - roles: - - hdacloud.certbot + tasks: + - name: Obtain certificate + ansible.builtin.import_role: + name: hdacloud.certs + vars: + cert_fqdns: + - "{{ my_fqdn }}" + admin_email: "admin@example.org" + dns_challenge: true + lego_version: "4.11.0" + lego_dns_provider: "designate" + dns_provider_auth_env_variables: + OS_AUTH_URL: "https://h-da.cloud:13000" + OS_REGION_NAME: "eu-central" + OS_AUTH_TYP: "v3applicationcredential" + OS_APPLICATION_CREDENTIAL_ID: "{{ os_application_credential_id }}" + OS_APPLICATION_CREDENTIAL_SECRET: "{{ os_application_credential_secret }}" + renewal_hook: | + #!/usr/bin/env bash + systemctl restart httpd +``` + +### Info when using DNS challenge + +In some cases you might need the certificates split up into the cert itself and a separate fullchain certificate +chain. For this case you need to add the `--no-bundle` option to the `lego_extra_flags` array. Then add the +following to the `renewal_hook` script (replacing variables accordingly): + +```sh +rm -f /var/lib/lego/fullchain.pem +cat /var/lib/lego/certificates/<cert_fqdns_first>.crt >> <wherever>/fullchain.pem && +cat /var/lib/lego/certificates/<cert_fqdns_first>.issuer.crt >> <wherever>/fullchain.pem ``` -License -------- +# License See [LICENSE](LICENSE) + +[lego-acme]: https://go-acme.github.io/lego/ 'LEGO ACME' +[certbot]: https://certbot.eff.org/ 'EFF Certbot' +[lego-dns-providers]: https://go-acme.github.io/lego/dns/#dns-providers 'LEGO: DNS Providers' diff --git a/defaults/main.yml b/defaults/main.yml index 43d75cc8713c356bc6ac167c2017eeb40f026d8e..ab9861e95758a5a2695a0e9701050c364d600b4f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,28 +1,28 @@ --- -# certbot settings -certbot_dns_challenge: false # default use webserver, true to obtain certificate using dns challenge -certbot_lego_version: "4.11.0" # lego version - Let's Encrypt client -certbot_dns_provider: "designate" # list of available providers https://go-acme.github.io/lego/dns/ -dns_provider_auth_env_variables: # variables required to authenticate dns provider - OS_AUTH_URL: "https://openstack.example.org" - OS_REGION_NAME: "RegionOne" - OS_AUTH_TYP: "v3applicationcredential" # default is to use application credential rather than password - OS_APPLICATION_CREDENTIAL_ID: "{{ vault_os_application_credential_id }}" - OS_APPLICATION_CREDENTIAL_SECRET: "{{ vault_os_application_credential_secret }}" +# Packages / timer names based on Distribution +certbot_pkg_name: + CentOS: "certbot" + Debian: "certbot" + Ubuntu: "certbot" + Fedora: "certbot" +# TODO: Might need to change +certbot_timer_name: + CentOS: "certbot-renew.timer" + Debian: "certbot.timer" + Ubuntu: "snap.certbot-renew.timer" + Fedora: "certbot-renew.timer" -certbot_fqdn: - - example.de -certbot_admin_email: "admin@example.de" -# certbot_webroot: "/var/www/example" # if undefined use --standalone +# certbot settings +dns_challenge: false # default use webserver, true to obtain certificate using dns challenge +lego_version: "4.11.0" # lego version - Let's Encrypt client +lego_dns_provider: "designate" # list of available providers https://go-acme.github.io/lego/dns/ +dns_provider_auth_env_variables: {} # variables required to authenticate dns provider -# application settings -# certbot_application: "example" # if defined copy certs to application dir and setup deploy hooks -certbot_application_dir: "/etc/{{ certbot_application }}" -certbot_application_deploy_hook: | - #!/bin/sh +cert_fqdns: + - example.de +admin_email: "admin@example.de" - cp {{ certbot_live_dir }}/fullchain.pem {{ certbot_application_dir }} - cp {{ certbot_live_dir }}/privkey.pem {{ certbot_application_dir }} - systemctl restart {{ certbot_application }}.service +# LEGO Settings +lego_extra_flags: [] diff --git a/tasks/CentOS-packages-webserver.yml b/tasks/CentOS-packages-webserver.yml deleted file mode 100644 index 4915865bff78928e93c539c4911dd3565e7d8f54..0000000000000000000000000000000000000000 --- a/tasks/CentOS-packages-webserver.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- name: Install Certbot - ansible.builtin.package: - name: # sadly doesn't as a list - - "{{ item }}" - state: present - loop: - - epel-release - - certbot - become: true diff --git a/tasks/CentOS-timer-webserver.yml b/tasks/CentOS-timer-webserver.yml deleted file mode 100644 index 78b2674c34b706766557eb7528b9510457556136..0000000000000000000000000000000000000000 --- a/tasks/CentOS-timer-webserver.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Enable Letsencrypt Renew Timer - ansible.builtin.systemd: - name: certbot-renew.timer - state: started - enabled: true - become: true diff --git a/tasks/Debian-packages-webserver.yml b/tasks/Debian-packages-webserver.yml deleted file mode 100644 index 42ad8f174eba9e90aba720960a8da0b8f6db0434..0000000000000000000000000000000000000000 --- a/tasks/Debian-packages-webserver.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install Certbot - ansible.builtin.apt: - name: certbot - state: present - update_cache: true - become: true diff --git a/tasks/Debian-timer-webserver.yml b/tasks/Debian-timer-webserver.yml deleted file mode 100644 index 519207159281893a5774a0892983a368dbedb600..0000000000000000000000000000000000000000 --- a/tasks/Debian-timer-webserver.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Enable Letsencrypt Renew Timer - ansible.builtin.systemd: - name: certbot.timer - state: started - enabled: true - become: true diff --git a/tasks/Fedora-packages-webserver.yml b/tasks/Fedora-packages-webserver.yml deleted file mode 100644 index 5c319309c8e50fa596ada8363c324d5d9a5ae117..0000000000000000000000000000000000000000 --- a/tasks/Fedora-packages-webserver.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: Install Certbot - ansible.builtin.package: - name: certbot - state: present - become: true diff --git a/tasks/Fedora-timer-webserver.yml b/tasks/Fedora-timer-webserver.yml deleted file mode 100644 index 78b2674c34b706766557eb7528b9510457556136..0000000000000000000000000000000000000000 --- a/tasks/Fedora-timer-webserver.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Enable Letsencrypt Renew Timer - ansible.builtin.systemd: - name: certbot-renew.timer - state: started - enabled: true - become: true diff --git a/tasks/Ubuntu-packages-webserver.yml b/tasks/Ubuntu-packages-webserver.yml deleted file mode 100644 index 42ad8f174eba9e90aba720960a8da0b8f6db0434..0000000000000000000000000000000000000000 --- a/tasks/Ubuntu-packages-webserver.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Install Certbot - ansible.builtin.apt: - name: certbot - state: present - update_cache: true - become: true diff --git a/tasks/Ubuntu-timer-webserver.yml b/tasks/Ubuntu-timer-webserver.yml deleted file mode 100644 index 519207159281893a5774a0892983a368dbedb600..0000000000000000000000000000000000000000 --- a/tasks/Ubuntu-timer-webserver.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Enable Letsencrypt Renew Timer - ansible.builtin.systemd: - name: certbot.timer - state: started - enabled: true - become: true diff --git a/tasks/application.yml b/tasks/application.yml deleted file mode 100644 index b9bf4b4841d33071aba2d4ae942bca6c5cdf8036..0000000000000000000000000000000000000000 --- a/tasks/application.yml +++ /dev/null @@ -1,34 +0,0 @@ ---- -- name: Ensure Application Certificate Directory exists - ansible.builtin.file: - path: "{{ certbot_application_dir }}" - state: directory - owner: root - group: root - mode: "0755" - become: true - -- name: Check Whether Application Cert Exists - ansible.builtin.stat: - path: "{{ certbot_application_dir }}/fullchain.pem" - register: leoacert - become: true - -- name: Setup Application Deploy Hook - ansible.builtin.copy: - dest: "/etc/letsencrypt/renewal-hooks/deploy/{{ certbot_application }}" - content: "{{ certbot_application_deploy_hook }}" - mode: "0755" - become: true - -- name: Copy Application Cert If Necessary - ansible.builtin.copy: - src: "{{ item }}" - dest: "{{ certbot_application_dir }}" - remote_src: true - mode: "0644" - loop: - - "{{ certbot_live_dir }}/fullchain.pem" - - "{{ certbot_live_dir }}/privkey.pem" - when: not leoacert.stat.exists - become: true diff --git a/tasks/dns-challenge.yml b/tasks/dns-challenge.yml index 15b94bb6864c8d917a7617032fa305b00445197f..9ea5d7d8eb3071027501d57d2719800aa945a959 100644 --- a/tasks/dns-challenge.yml +++ b/tasks/dns-challenge.yml @@ -1,85 +1,51 @@ - name: Fetch Binary ansible.builtin.get_url: - url: "https://github.com/go-acme/lego/releases/download/v{{ certbot_lego_version }}/lego_v{{ certbot_lego_version }}_linux_amd64.tar.gz" - dest: "/tmp/lego_v{{ certbot_lego_version }}_linux_amd64.tar.gz" + url: "https://github.com/go-acme/lego/releases/download/v{{ lego_version }}/lego_v{{ lego_version }}_linux_amd64.tar.gz" + dest: "/tmp/lego_v{{ lego_version }}_linux_amd64.tar.gz" mode: "0644" - name: Unpack Archive ansible.builtin.unarchive: - src: "/tmp/lego_v{{ certbot_lego_version }}_linux_amd64.tar.gz" + src: "/tmp/lego_v{{ lego_version }}_linux_amd64.tar.gz" dest: "/tmp" remote_src: true - name: Copy Binary ansible.builtin.copy: src: /tmp/lego - dest: /usr/bin/lego + dest: /usr/local/bin/lego owner: root group: root mode: '0755' remote_src: true become: true -- name: Check Whether Cert Exists - ansible.builtin.stat: - path: "{{ certbot_live_dir }}/fullchain.pem" - register: lecert +- name: Create lego directories become: true - -- name: Ensure Deploy Hook Dir Exists ansible.builtin.file: - path: "{{ item }}" state: directory + path: "{{ lego_path }}/renewal-hooks" # all intermediate subdirectories will be created mode: "0755" owner: root group: root - loop: - - /etc/letsencrypt/renewal-hooks - - /etc/letsencrypt/renewal-hooks/deploy - become: true -- name: Render deploy hook script - ansible.builtin.template: - src: templates/renew-hook.sh.j2 - dest: /etc/letsencrypt/renewal-hooks/deploy/create-fullchain.sh - mode: '0755' +- name: Check Whether Cert Exists + ansible.builtin.stat: + path: "{{ lego_path }}/certificates/{{ cert_fqdns_first }}.crt" + register: lego_cert become: true - name: Request Cert If Necessary - DNS Challenge - when: not lecert.stat.exists + when: not lego_cert.stat.exists become: true - block: - - name: Request Cert - ansible.builtin.command: >- - lego -a --dns {{ certbot_dns_provider }} - --email {{ certbot_admin_email }} -d {{ lego_dflag }} - --path {{ certbot_live_dir }} - run --no-bundle - environment: "{{ dns_provider_auth_env_variables }}" - register: lego - changed_when: lego.rc == 0 - - - name: Mirror Letsencrypt Structure - block: - - name: Copy cert and key files - ansible.builtin.copy: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: root - group: root - mode: '0600' - remote_src: true - loop: - - { src: "{{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.crt", dest: "{{ certbot_live_dir }}/cert.pem" } - - { src: "{{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.key", dest: "{{ certbot_live_dir }}/privkey.pem" } - - - name: Build fullchain.pem file - ansible.builtin.shell: - cmd: >- - cat "{{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.crt" >> "{{ certbot_live_dir }}/fullchain.pem" && - cat "{{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.issuer.crt" >> "{{ certbot_live_dir }}/fullchain.pem" - changed_when: false - + ansible.builtin.command: >- + lego -a --dns {{ lego_dns_provider }} + --email {{ admin_email }} -d {{ lego_dflag }} + --path {{ lego_path }} + run {% for f in lego_extra_flags %}{{ f }} {% endfor %} + environment: "{{ dns_provider_auth_env_variables }}" + register: lego + changed_when: lego.rc == 0 - name: Render Systemd Files become: true @@ -93,18 +59,18 @@ - name: Render Systemd Service File ansible.builtin.template: src: templates/dns-challenge.service.j2 - dest: /lib/systemd/system/dns-challenge.service + dest: /etc/systemd/system/dns-challenge.service mode: "0644" - name: Render Systemd Timer File ansible.builtin.template: src: templates/dns-challenge.timer.j2 - dest: /lib/systemd/system/dns-challenge.timer + dest: /etc/systemd/system/dns-challenge.timer mode: "0644" -- name: Setup Certbot With Application - ansible.builtin.include_tasks: "application.yml" - when: certbot_application is defined +- name: Setup renewal hook + ansible.builtin.include_tasks: "renewal-hook.yml" + when: renewal_hook is defined - name: Enable LEGO Renew Timer ansible.builtin.systemd: diff --git a/tasks/main.yml b/tasks/main.yml index a97d708121d71398f8e54f12ca9ae0962ee188e1..cb686c25063f58d063c56d28d28a8ef52cb5db85 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,8 +1,8 @@ --- - name: Obtain Cert Using Web Server ansible.builtin.include_tasks: "webserver.yml" - when: not certbot_dns_challenge + when: not dns_challenge - name: Obtain Cert DNS Challenge ansible.builtin.include_tasks: "dns-challenge.yml" - when: certbot_dns_challenge + when: dns_challenge diff --git a/tasks/renewal-hook.yml b/tasks/renewal-hook.yml new file mode 100644 index 0000000000000000000000000000000000000000..5eb30f89cecad84e3a80270ce8cda2c0dc6dee82 --- /dev/null +++ b/tasks/renewal-hook.yml @@ -0,0 +1,7 @@ +--- +- name: Setup Renewal Hook + ansible.builtin.copy: + dest: "{{ dns_challenge | ternary(lego_path + '/renewal-hooks/', '/etc/letsencrypt/renewal-hooks/deploy/') }}{{ renewal_hook_file_name }}" + content: "{{ renewal_hook }}" + mode: "0755" + become: true diff --git a/tasks/webserver.yml b/tasks/webserver.yml index 96e60749ca9688e3a8a7d841435aad74a88a8051..f2e96f89ead8980de72f13c2dd97e61c4f061ff3 100644 --- a/tasks/webserver.yml +++ b/tasks/webserver.yml @@ -1,5 +1,24 @@ +--- - name: Install Packages Based On Distribution - ansible.builtin.include_tasks: "{{ ansible_facts.distribution }}-packages-webserver.yml" + become: true + block: + - name: Install epel-release on CentOS + when: ansible_facts.distribution == "CentOS" + ansible.builtin.yum: + name: epel-release + state: present + + - name: Install certbot + ansible.builtin.package: + name: "{{ certbot_pkg_name[ansible_facts.distribution] }}" + state: present + + - name: Disable 'epel' again + when: ansible_facts.distribution == "CentOS" + ansible.builtin.yum_repository: + name: epel + state: absent + - name: Check Whether Cert Exists ansible.builtin.stat: @@ -9,20 +28,17 @@ - name: Ensure Deploy Hook Dir Exists ansible.builtin.file: - path: "{{ item }}" + path: /etc/letsencrypt/renewal-hooks/deploy state: directory mode: "0755" owner: root group: root - loop: - - /etc/letsencrypt/renewal-hooks - - /etc/letsencrypt/renewal-hooks/deploy become: true - name: Request Cert If Necessary - Standalone ansible.builtin.command: >- certbot certonly --standalone --noninteractive --agree-tos - --email {{ certbot_admin_email }} -d {{ certbot_dflag }} + --email {{ admin_email }} -d {{ certbot_dflag }} when: not lecert.stat.exists and not certbot_webroot is defined register: cbstandalone changed_when: cbstandalone.rc == 0 @@ -40,15 +56,19 @@ - name: Request Cert If Necessary - Webroot ansible.builtin.command: >- certbot certonly --webroot --webroot-path {{ certbot_webroot }} --noninteractive --agree-tos - --email {{ certbot_admin_email }} -d {{ certbot_dflag }} + --email {{ admin_email }} -d {{ certbot_dflag }} when: not lecert.stat.exists and certbot_webroot is defined register: cbwebroot changed_when: cbwebroot.rc == 0 become: true -- name: Setup Certbot With Application - ansible.builtin.include_tasks: "application.yml" - when: certbot_application is defined +- name: Setup Certbot renewal hook + ansible.builtin.include_tasks: "renewal-hook.yml" + when: renewal_hook is defined - name: Enable Letsencrypt Renew Timer Based On Distribution - ansible.builtin.include_tasks: "{{ ansible_facts.distribution }}-timer-webserver.yml" + become: true + ansible.builtin.systemd: + name: "{{ certbot_itmer_name[ansible_facts.distribution] }}" + state: started + enabled: true diff --git a/templates/dns-challenge.service.j2 b/templates/dns-challenge.service.j2 index 107dbe91e385459eb1ba05a7154e1369882de0b7..433f085812c2a3ba9e73ad74218f05235a316dbe 100644 --- a/templates/dns-challenge.service.j2 +++ b/templates/dns-challenge.service.j2 @@ -5,8 +5,5 @@ Description=LEGO DNS challenge [Service] Type=oneshot -ExecStart=/usr/bin/lego -a --dns {{ certbot_dns_provider }} --email {{ certbot_admin_email }} -d {{ lego_dflag }} --path {{ certbot_live_dir }} renew --no-bundle --renew-hook /etc/letsencrypt/renewal-hooks/deploy/create-fullchain.sh -ExecStartPost=cp {{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.crt {{ certbot_live_dir }}/cert.pem -ExecStartPost=cp {{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.key {{ certbot_live_dir }}/privkey.pem -{{ "ExecStartPost=/etc/letsencrypt/renewal-hooks/deploy/" + certbot_application if certbot_application is defined else "" }} +ExecStart=/usr/local/bin/lego -a --dns {{ lego_dns_provider }} --email {{ admin_email }} -d {{ lego_dflag }} --path {{ lego_path }} renew {% for f in lego_extra_flags %}{{ f }} {% endfor %} {{ '--renew-hook ' + lego_path + '/renewal-hooks/' + renewal_hook_file_name if renewal_hook is defined else ''}} EnvironmentFile=/etc/default/dns-challenge.env diff --git a/templates/renew-hook.sh.j2 b/templates/renew-hook.sh.j2 deleted file mode 100644 index 820e87a1721bd09017a9278c96560789f5f05e0a..0000000000000000000000000000000000000000 --- a/templates/renew-hook.sh.j2 +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -cat {{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.crt >> {{ certbot_live_dir }}/fullchain.pem -cat {{ certbot_live_dir }}/certificates/{{ certbot_fqdn_first }}.issuer.crt >> {{ certbot_live_dir }}/fullchain.pem \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml index e55bd962c4da69fa300b421949e5cbbc31ccc611..2c1154e6a275cee553bc16cec29225e684703c20 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,11 +1,16 @@ --- -certbot_fqdn_first: >- +cert_fqdns_first: >- {{ - certbot_fqdn + cert_fqdns | first | replace("*.", "") | trim(".") }} -certbot_live_dir: "/etc/letsencrypt/live/{{ certbot_fqdn_first }}" -certbot_dflag: "{{ certbot_fqdn | map('trim', '.') | join(',') }}" -lego_dflag: "{{ certbot_fqdn | map('trim', '.') | join(' -d ') }}" + +# Certbot +certbot_live_dir: "/etc/letsencrypt/live/{{ cert_fqdns_first }}" +certbot_dflag: "{{ cert_fqdns | map('trim', '.') | join(',') }}" + +# LEGO (when DNS challenge) +lego_path: /var/lib/lego +lego_dflag: "{{ cert_fqdns | map('trim', '.') | join(' -d ') }}"