The link to the fake certificate is not removed.

This commit is contained in:
Andrea Dell'Amico 2023-06-24 15:55:07 +02:00
parent c3198ab76f
commit bb1f7f5340
Signed by: adellam
GPG Key ID: 147ABE6CEB9E20FF
5 changed files with 253 additions and 168 deletions

View File

@ -1,8 +1,8 @@
--- ---
letsencrypt_acme_install: False letsencrypt_acme_install: false
letsencrypt_acme_sh_install: '{{ letsencrypt_acme_install }}' letsencrypt_acme_sh_install: '{{ letsencrypt_acme_install }}'
letsencrypt_acme_sh_git_install: True letsencrypt_acme_sh_git_install: true
letsencrypt_update_acme_distribution: True letsencrypt_update_acme_distribution: true
letsencrypt_acme_sh_git_url: https://github.com/acmesh-official/acme.sh.git letsencrypt_acme_sh_git_url: https://github.com/acmesh-official/acme.sh.git
letsencrypt_acme_sh_default_ca: 'letsencrypt' letsencrypt_acme_sh_default_ca: 'letsencrypt'
letsencrypt_acme_user: acme letsencrypt_acme_user: acme
@ -17,23 +17,21 @@ letsencrypt_acme_sh_certificates_install_dir: '{{ ansible_fqdn }}'
letsencrypt_acme_sh_certificates_install_base_path: '{{ letsencrypt_acme_sh_user_home }}/live' letsencrypt_acme_sh_certificates_install_base_path: '{{ letsencrypt_acme_sh_user_home }}/live'
letsencrypt_acme_sh_certificates_install_path: '{{ letsencrypt_acme_sh_certificates_install_base_path }}/{{ letsencrypt_acme_sh_certificates_install_dir }}' letsencrypt_acme_sh_certificates_install_path: '{{ letsencrypt_acme_sh_certificates_install_base_path }}/{{ letsencrypt_acme_sh_certificates_install_dir }}'
letsencrypt_acme_sh_log_dir: /var/log/acme letsencrypt_acme_sh_log_dir: /var/log/acme
letsencrypt_acme_sh_install_cron: False letsencrypt_acme_sh_install_cron: false
letsencrypt_acme_sh_log_enabled: True letsencrypt_acme_sh_log_enabled: true
letsencrypt_acme_sh_auto_upgrade: False letsencrypt_acme_sh_auto_upgrade: false
letsencrypt_acme_sh_install_options: '--install' letsencrypt_acme_sh_install_options: '--install'
letsencrypt_acme_sh_test_request: False letsencrypt_acme_sh_test_request: false
letsencrypt_acme_sh_use_syslog: True letsencrypt_acme_sh_use_syslog: true
letsencrypt_acme_sh_syslog_level: 6 letsencrypt_acme_sh_syslog_level: 6
# We only support the PowerDNS API. Adding other ones should be straightforward # We only support the PowerDNS API. Adding other ones should be straightforward
letsencrypt_acme_sh_use_dns_provider: False letsencrypt_acme_sh_use_dns_provider: false
letsencrypt_acme_sh_dns_provider_type: dns_pdns letsencrypt_acme_sh_dns_provider_type: dns_pdns
letsencrypt_acme_sh_dns_api_url: 'http://localhost:8081' letsencrypt_acme_sh_dns_api_url: 'http://localhost:8081'
letsencrypt_acme_sh_dns_api_provider_id: localhost letsencrypt_acme_sh_dns_api_provider_id: localhost
# Use a vault variable for this one # Use a vault variable for this one
letsencrypt_acme_sh_dns_api_token: XXXXXXX letsencrypt_acme_sh_dns_api_token: XXXXXXX
letsencrypt_acme_sh_command: acme.sh letsencrypt_acme_sh_command: acme.sh
# The data directory is created by the acme.sh install # The data directory is created by the acme.sh install
letsencrypt_acme_sh_dirs: letsencrypt_acme_sh_dirs:
@ -47,14 +45,13 @@ letsencrypt_acme_certs_dir: '{{ letsencrypt_acme_sh_certificates_install_path }}
# The various services maintainers need to put the reconfigure/restart scripts there # The various services maintainers need to put the reconfigure/restart scripts there
letsencrypt_acme_services_scripts_dir: /usr/lib/acme/hooks letsencrypt_acme_services_scripts_dir: /usr/lib/acme/hooks
letsencrypt_acme_sh_services_scripts_dir: '{{ letsencrypt_acme_services_scripts_dir }}' letsencrypt_acme_sh_services_scripts_dir: '{{ letsencrypt_acme_services_scripts_dir }}'
letsencrypt_acme_sh_explicitly_install_certs: true
letsencrypt_acme_sh_explicitly_install_certs: True letsencrypt_force_cert_request: false
# ECC is better, but most old distributions fail on them # ECC is better, but most old distributions fail on them
letsencrypt_acme_sh_use_ecc: False letsencrypt_acme_sh_use_ecc: false
letsencrypt_acme_sh_ecc_key_lenght: ec-384 letsencrypt_acme_sh_ecc_key_lenght: ec-384
letsencrypt_acme_sh_rsa_key_lenght: 4096 letsencrypt_acme_sh_rsa_key_lenght: 4096
letsencrypt_acme_sh_ocsp_must_staple: False letsencrypt_acme_sh_ocsp_must_staple: false
# Default: ISRG Root X1 # Default: ISRG Root X1
letsencrypt_acme_sh_specific_root_ca: '--preferred-chain "ISRG Root X1"' letsencrypt_acme_sh_specific_root_ca: '--preferred-chain "ISRG Root X1"'
letsencrypt_acme_email: sysadmin@example.com letsencrypt_acme_email: sysadmin@example.com
@ -82,4 +79,3 @@ letsencrypt_acme_sh_domains_install:
cert_file: '{{ letsencrypt_acme_sh_certificates_install_path }}/cert' cert_file: '{{ letsencrypt_acme_sh_certificates_install_path }}/cert'
key_file: '{{ letsencrypt_acme_sh_certificates_install_path }}/privkey' key_file: '{{ letsencrypt_acme_sh_certificates_install_path }}/privkey'
fullchain_file: '{{ letsencrypt_acme_sh_certificates_install_path }}/fullchain' fullchain_file: '{{ letsencrypt_acme_sh_certificates_install_path }}/fullchain'

View File

@ -1,25 +1,26 @@
galaxy_info: galaxy_info:
author: Andrea Dell'Amico author: Andrea Dell'Amico
description: Systems Architect namespace: adellam
role_name: letsencrypt_acme_sh_client
description: Role to installs and configure the acme.sh Letsencrypt client
company: ISTI-CNR company: ISTI-CNR
issue_tracker_url: https://redmine-s2i2s.isti.cnr.it/projects/provisioning
license: EUPL 1.2+ license: EUPL 1.2+
min_ansible_version: "2.9"
min_ansible_version: 2.8
# To view available platforms and versions (or releases), visit: # To view available platforms and versions (or releases), visit:
# https://galaxy.ansible.com/api/v1/platforms/ # https://galaxy.ansible.com/api/v1/platforms/
# #
platforms: platforms:
- name: Ubuntu - name: Ubuntu
versions: versions:
- xenial
- bionic - bionic
- focal
- jammy
- name: EL - name: EL
versions: versions:
- 7 - "7"
- 8 - "8"
- "9"
galaxy_tags: galaxy_tags:
- letsencrypt - letsencrypt

View File

@ -1,10 +1,16 @@
--- ---
- block: - name: Actions on Debian-like distributions
tags: ['letsencrypt', 'letsencrypt_acme_sh']
block:
- name: Install the socat utility, needed when using the http protocols to request the certificates - name: Install the socat utility, needed when using the http protocols to request the certificates
apt: pkg=socat state=present cache_valid_time=1800 ansible.builtin.apt:
pkg: socat
state: present
cache_valid_time: 1800
- name: Install the git client if we are installing using git - name: Install the git client if we are installing using git
apt: pkg=git state=present cache_valid_time=1800 ansible.builtin.apt:
pkg: git
state: present
cache_valid_time: 1800
when: letsencrypt_acme_sh_git_install when: letsencrypt_acme_sh_git_install
tags: [ 'letsencrypt', 'letsencrypt_acme_sh' ]

View File

@ -1,13 +1,24 @@
- block: - name: Packages in EL derivatives
tags: ['letsencrypt', 'letsencrypt_acme_sh']
block:
- name: Install the socat utility, needed when using the http protocols to request the certificates - name: Install the socat utility, needed when using the http protocols to request the certificates
yum: pkg=socat state=present ansible.builtin.yum:
pkg: socat
state: present
- name: Install the git client if we are installing using git - name: Install the git client if we are installing using git
yum: pkg=git state=present ansible.builtin.yum:
pkg: git
state: present
when: letsencrypt_acme_sh_git_install when: letsencrypt_acme_sh_git_install
- name: Activate the firewalld rule for the http, if we require certificates using the http protocol - name: Activate the firewalld rule for the http, if we require certificates using the http protocol
firewalld: service=http zone={{ firewalld_default_zone }} permanent=True state=enabled immediate=True ansible.posix.firewalld:
service: http
zone: "{{ firewalld_default_zone }}"
permanent: true
state: enabled
immediate: true
with_items: '{{ letsencrypt_acme_sh_domains }}' with_items: '{{ letsencrypt_acme_sh_domains }}'
when: when:
- item.standalone is defined - item.standalone is defined
@ -15,10 +26,13 @@
- letsencrypt_firewalld_http_enabled_on_default_zone - letsencrypt_firewalld_http_enabled_on_default_zone
- name: Custom firewalld rule for http - name: Custom firewalld rule for http
firewalld: service={{ item.service}} zone={{ item.zone }} permanent={{ item.permanent | default(True) }} state={{ item.state }} immediate=True ansible.posix.firewalld:
with_items: '{{ letsencrypt_firewalld_services }}' service: "{{ item.service}}"
zone: "{{ item.zone }}"
permanent: "{{ item.permanent | default(true) }}"
state: "{{ item.state }}"
immediate: true
loop: '{{ letsencrypt_firewalld_services }}'
when: when:
- firewalld_enabled is defined and firewalld_enabled - firewalld_enabled is defined and firewalld_enabled
- not letsencrypt_firewalld_http_enabled_on_default_zone - not letsencrypt_firewalld_http_enabled_on_default_zone
tags: [ 'letsencrypt', 'letsencrypt_acme_sh' ]

View File

@ -1,48 +1,89 @@
--- ---
- import_tasks: acmetool_deb.yml - name: Import the deb tasks
ansible.builtin.import_tasks: acmetool_deb.yml
when: ansible_distribution_file_variety == "Debian" when: ansible_distribution_file_variety == "Debian"
- import_tasks: acmetool_rh.yml - name: Import the RH and derivatives
ansible.builtin.import_tasks: acmetool_rh.yml
when: ansible_distribution_file_variety == "RedHat" when: ansible_distribution_file_variety == "RedHat"
- block: - name: Prepare the acme.sh environment
when: letsencrypt_acme_sh_install | bool
tags: ['letsencrypt', 'letsencrypt_acme_sh']
block:
- name: Create the letsencrypt acme user - name: Create the letsencrypt acme user
user: name={{ letsencrypt_acme_sh_user }} home={{ letsencrypt_acme_sh_user_home }} createhome=no shell=/usr/sbin/nologin system=yes ansible.builtin.user:
tags: [ 'letsencrypt', 'letsencrypt_user' ] name: "{{ letsencrypt_acme_sh_user }}"
home: "{{ letsencrypt_acme_sh_user_home }}"
createhome: false
shell: /usr/sbin/nologin
system: true
tags: ['letsencrypt', 'letsencrypt_user']
- name: Create the letsencrypt acme home, if it does not exist already. In a separate step because it could be already there. - name: Create the letsencrypt acme home, if it does not exist already. In a separate step because it could be already there.
file: dest={{ letsencrypt_acme_sh_user_home }} owner={{ letsencrypt_acme_sh_user }} group={{ letsencrypt_acme_sh_user }} state=directory recurse=yes ansible.builtin.file:
dest: "{{ letsencrypt_acme_sh_user_home }}"
owner: "{{ letsencrypt_acme_sh_user }}"
group: "{{ letsencrypt_acme_sh_user }}"
state: directory
mode: 0755
recurse: true
- name: Create a directory where to put the cron job and hooks logs - name: Create a directory where to put the cron job and hooks logs
file: dest={{ letsencrypt_acme_sh_log_dir }} state=directory owner={{ letsencrypt_acme_sh_user }} group={{ letsencrypt_acme_sh_user }} mode=0750 ansible.builtin.file:
dest: "{{ letsencrypt_acme_sh_log_dir }}"
state: directory
owner: "{{ letsencrypt_acme_sh_user }}"
group: "{{ letsencrypt_acme_sh_user }}"
mode: 0750
- name: Install the acme.sh environment variables file - name: Install the acme.sh environment variables file
template: src=acme_sh_request_env.j2 dest=/etc/default/acme_sh_request_env owner=root group=root mode=0444 ansible.builtin.template:
src: acme_sh_request_env.j2
dest: /etc/default/acme_sh_request_env
owner: root
group: root
mode: 0444
register: acme_sh_issue register: acme_sh_issue
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_env' ] tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_env', 'letsencrypt_req_cert']
- name: Install the script that initializes the acme.sh environment - name: Install the script that initializes the acme.sh environment
copy: src=acme-sh-install dest=/usr/local/bin/acme-sh-install owner=root group=acme mode=0750 ansible.builtin.copy:
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts' ] src: acme-sh-install
dest: /usr/local/bin/acme-sh-install
owner: root
group: "{{ letsencrypt_acme_user }}"
mode: 0750
tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts']
- name: Install a script that issues the certificates - name: Install a script that issues the certificates
template: ansible.builtin.template:
src: acme-sh-request-cert.sh.j2 src: acme-sh-request-cert.sh.j2
dest: /usr/local/bin/acme-sh-request-cert dest: /usr/local/bin/acme-sh-request-cert
owner: root owner: root
group: acme group: "{{ letsencrypt_acme_user }}"
mode: 0750 mode: 0750
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts' ] tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts']
- name: Install a script that installs the issued certificates - name: Install a script that installs the issued certificates
copy: src=acme-sh-install-certs dest=/usr/local/bin/acme-sh-install-certs owner=root group=acme mode=0750 ansible.builtin.copy:
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts' ] src: acme-sh-install-certs
dest: /usr/local/bin/acme-sh-install-certs
owner: root
group: "{{ letsencrypt_acme_user }}"
mode: 0750
tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts']
- name: Install the script that will run the services hooks when a certificate is installed - name: Install the script that will run the services hooks when a certificate is installed
template: src=acme-services-hook.j2 dest=/usr/local/bin/acme-services-hook owner=root group=acme mode=0750 ansible.builtin.template:
src: acme-services-hook.j2
dest: /usr/local/bin/acme-services-hook
owner: root
group: "{{ letsencrypt_acme_user }}"
mode: 0750
- name: Install the scripts that will be run as a cron job - name: Install the scripts that will be run as a cron job
template: ansible.builtin.template:
src: '{{ item }}.sh.j2' src: '{{ item }}.sh.j2'
dest: '/usr/local/bin/{{ item }}' dest: '/usr/local/bin/{{ item }}'
owner: root owner: root
@ -51,20 +92,20 @@
loop: loop:
- acme-sh-cron-script - acme-sh-cron-script
- acme-sh-cron-command - acme-sh-cron-command
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts' ] tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts']
- name: Remove the cron job under spool if it exists - name: Remove the cron job under spool if it exists
cron: ansible.builtin.cron:
name: "Letsencrypt certificate renewal" name: "Letsencrypt certificate renewal"
day: '{{ letsencrypt_acme_cron_day_of_month }}' day: '{{ letsencrypt_acme_cron_day_of_month }}'
hour: '{{ letsencrypt_acme_cron_hour }}' hour: '{{ letsencrypt_acme_cron_hour }}'
minute: '{{ letsencrypt_acme_cron_minute }}' minute: '{{ letsencrypt_acme_cron_minute }}'
job: "/usr/local/bin/acme-sh-cron-script > {{ letsencrypt_acme_sh_log_dir }}/acme-cron.log 2>&1" job: "/usr/local/bin/acme-sh-cron-script > {{ letsencrypt_acme_sh_log_dir }}/acme-cron.log 2>&1"
state: absent state: absent
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts' ] tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts']
- name: Install a daily cron job to renew the certificates when needed. It runs as root - name: Install a daily cron job to renew the certificates when needed. It runs as root
cron: ansible.builtin.cron:
name: "Letsencrypt certificate renewal" name: "Letsencrypt certificate renewal"
cron_file: letsencrypt_renew_certificates cron_file: letsencrypt_renew_certificates
user: root user: root
@ -72,64 +113,91 @@
hour: '{{ letsencrypt_acme_cron_hour }}' hour: '{{ letsencrypt_acme_cron_hour }}'
minute: '{{ letsencrypt_acme_cron_minute }}' minute: '{{ letsencrypt_acme_cron_minute }}'
job: "/usr/local/bin/acme-sh-cron-script > {{ letsencrypt_acme_sh_log_dir }}/acme-cron.log 2>&1" job: "/usr/local/bin/acme-sh-cron-script > {{ letsencrypt_acme_sh_log_dir }}/acme-cron.log 2>&1"
tags: [ 'letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts' ] tags: ['letsencrypt', 'letsencrypt_cron', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_scripts']
- name: Acme.sh distribution
become: true
become_user: '{{ letsencrypt_acme_sh_user }}'
when: letsencrypt_acme_sh_install | bool when: letsencrypt_acme_sh_install | bool
tags: [ 'letsencrypt', 'letsencrypt_acme_sh' ] tags: ['letsencrypt', 'letsencrypt_acme_sh']
block:
- block:
- name: Download the acme.sh distribution - name: Download the acme.sh distribution
git: repo={{ letsencrypt_acme_sh_git_url }} dest={{ letsencrypt_acme_git_dest_dir }} recursive=yes update=yes ansible.builtin.git:
repo: "{{ letsencrypt_acme_sh_git_url }}"
dest: "{{ letsencrypt_acme_git_dest_dir }}"
recursive: true
update: true
when: letsencrypt_update_acme_distribution when: letsencrypt_update_acme_distribution
- name: Create the letsencrypt acme.sh directory tree - name: Create the letsencrypt acme.sh directory tree
file: dest={{ item }} state=directory mode=0755 ansible.builtin.file:
dest: "{{ item }}"
state: directory
mode: 0755
with_items: '{{ letsencrypt_acme_sh_dirs }}' with_items: '{{ letsencrypt_acme_sh_dirs }}'
- name: Run the installation command for acme.sh - name: Run the installation command for acme.sh
shell: /usr/local/bin/acme-sh-install ansible.builtin.command: /usr/local/bin/acme-sh-install
args: args:
creates: '{{ letsencrypt_acme_sh_user_home }}/bin/acme.sh' creates: '{{ letsencrypt_acme_sh_user_home }}/bin/acme.sh'
- name: Create the letsencrypt acme.sh account configuration - name: Create the letsencrypt acme.sh account configuration
template: src=account.conf.j2 dest={{ letsencrypt_acme_sh_base_data_dir }}/data/account.conf mode=0640 ansible.builtin.template:
tags: [ 'letsencrypt', 'letsencrypt_account_conf', 'letsencrypt_acme_sh' ] src: account.conf.j2
dest: "{{ letsencrypt_acme_sh_base_data_dir }}/data/account.conf"
owner: root
group: "{{ letsencrypt_acme_user }}"
mode: 0640
tags: ['letsencrypt', 'letsencrypt_account_conf', 'letsencrypt_acme_sh']
become: True - name: Certificates management
become_user: '{{ letsencrypt_acme_sh_user }}'
when: letsencrypt_acme_sh_install | bool when: letsencrypt_acme_sh_install | bool
tags: [ 'letsencrypt', 'letsencrypt_acme_sh' ] tags: ['letsencrypt', 'letsencrypt_acme_sh', 'letsencrypt_req_cert']
block:
- block:
- name: Remove the ok_certificate_issued file when the env file has been changed so that we can force a new request - name: Remove the ok_certificate_issued file when the env file has been changed so that we can force a new request
file: dest={{ letsencrypt_acme_sh_base_data_dir }}/data/ok_certificate_issued state=absent ansible.builtin.file:
when: acme_sh_issue is changed dest: "{{ letsencrypt_acme_sh_base_data_dir }}/data/ok_certificate_issued"
state: absent
when: (acme_sh_issue is changed) or letsencrypt_force_cert_request
- name: Request the certificates. - name: Request the certificates.
shell: /usr/local/bin/acme-sh-request-cert ansible.builtin.command: /usr/local/bin/acme-sh-request-cert
args: args:
creates: '{{ letsencrypt_acme_sh_base_data_dir }}/data/ok_certificate_issued' creates: '{{ letsencrypt_acme_sh_base_data_dir }}/data/ok_certificate_issued'
register: acme_sh_certificate_issued register: acme_sh_certificate_issued
- name: Check if the certificates install path is a link
ansible.builtin.stat:
path: "{{ letsencrypt_acme_sh_certificates_install_path }}"
register: cert_install_path
- name: Remove the certificates install path if it is a link
ansible.builtin.file:
dest: "{{ letsencrypt_acme_sh_certificates_install_path }}"
state: absent
when: cert_install_path.stat.islink is defined and cert_install_path.stat.islink
- name: Create the certificates installation directory - name: Create the certificates installation directory
file: dest={{ letsencrypt_acme_sh_certificates_install_path }} state=directory owner=root group=root mode=0755 ansible.builtin.file:
dest: "{{ letsencrypt_acme_sh_certificates_install_path }}"
state: directory
owner: root
group: root
mode: 0755
- name: Install the certificates - name: Install the certificates
shell: /usr/local/bin/acme-sh-install-certs ansible.builtin.command: /usr/local/bin/acme-sh-install-certs
when: when:
- letsencrypt_acme_sh_explicitly_install_certs | bool - letsencrypt_acme_sh_explicitly_install_certs | bool
- acme_sh_certificate_issued is defined - acme_sh_certificate_issued is defined
- acme_sh_certificate_issued is changed - acme_sh_certificate_issued is changed
- name: Fix the http port in the configuration. Needed when we renew using the http protocol and we are behind a web server - name: Fix the http port in the configuration. Needed when we renew using the http protocol and we are behind a web server
lineinfile: ansible.builtin.lineinfile:
path: '{{ letsencrypt_acme_sh_certs_data_path }}/{{ letsencrypt_acme_sh_certs_data_prefix }}.conf' path: '{{ letsencrypt_acme_sh_certs_data_path }}/{{ letsencrypt_acme_sh_certs_data_prefix }}.conf'
create: no create: false
state: present state: present
regexp: "^Le_HTTPPort=" regexp: "^Le_HTTPPort="
line: "Le_HTTPPort='{{ letsencrypt_acme_standalone_port }}'" line: "Le_HTTPPort='{{ letsencrypt_acme_standalone_port }}'"
when: not letsencrypt_acme_sh_use_dns_provider | bool when: not letsencrypt_acme_sh_use_dns_provider | bool
tags: [ 'letsencrypt', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_http_port' ] tags: ['letsencrypt', 'letsencrypt_acme_sh', 'letsencrypt_acme_sh_http_port', 'letsencrypt_req_cert']
when: letsencrypt_acme_sh_install | bool
tags: [ 'letsencrypt', 'letsencrypt_acme_sh' ]