Implemented SAN via Letsencrypt and Certbot

This commit is contained in:
2025-04-28 16:47:51 +02:00
parent 0fc9c3e495
commit 04deeef385
28 changed files with 411 additions and 224 deletions

View File

@@ -0,0 +1,23 @@
- name: "receive certificate for {{ domain }}"
command: >-
certbot certonly
--agree-tos
--email {{ users.administrator.email }}
--non-interactive
{% if certbot_acme_challenge_method != "webroot" %}
--dns-{{ certbot_acme_challenge_method }}
--dns-{{ certbot_acme_challenge_method }}-credentials {{ certbot_credentials_file }}
--dns-{{ certbot_acme_challenge_method }}-propagation-seconds {{ certbot_dns_propagation_wait_seconds }}
{% else %}
--webroot
-w {{ certbot_webroot_path }}
{% endif %}
{% if wildcard_domain is defined and ( wildcard_domain | bool ) %}
-d {{ primary_domain }}
-d *.{{ primary_domain }}
{% else %}
-d {{ domain }}
{% endif %}
{{ '--test-cert' if mode_test | bool else '' }}
register: certbot_result
changed_when: "'Certificate not yet due for renewal' not in certbot_result.stdout"

View File

@@ -0,0 +1,27 @@
- name: Install certbundle
include_role:
name: pkgmgr-install
vars:
package_name: certbundle
when: run_once_san_certs is not defined
- name: Generate SAN certificate with certbundle
command: >-
certbundle
--domains "{{ all_domains | join(',') }}"
--certbot-email "{{ users.administrator.email }}"
--certbot-acme-challenge-method "{{ certbot_acme_challenge_method }}"
{% if certbot_acme_challenge_method != 'webroot' %}
--certbot-credentials-file "{{ certbot_credentials_file }}"
--certbot-dns-propagation-seconds "{{ certbot_dns_propagation_wait_seconds }}"
{% else %}
--certbot-webroot-path "{{ certbot_webroot_path }}"
{% endif %}
{{ '--mode-test' if mode_test | bool else '' }}
register: certbundle_result
when: run_once_san_certs is not defined
- name: run the san tasks once
set_fact:
run_once_san_certs: true
when: run_once_san_certs is not defined

View File

@@ -0,0 +1,19 @@
- name: "Load wildcard certificate for domain"
include_tasks: "dedicated.yml"
vars:
wildcard_domain: true
when:
- domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain)
- run_once_receive_certificate is not defined
- name: "Load dedicated certificate for domain"
include_tasks: "dedicated.yml"
vars:
wildcard_domain: false
when:
- not (domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain))
- name: run the receive_certificate tasks once
set_fact:
run_once_receive_certificate: true
when: run_once_receive_certificate is not defined

View File

@@ -1,55 +1,5 @@
- name: "receive dedicated certificate for {{ domain }}"
command: >-
certbot certonly
--agree-tos
--email {{ users.administrator.email }}
--non-interactive
{% if certbot_acme_challenge_method != "webroot" %}
--dns-{{ certbot_acme_challenge_method }}
--dns-{{ certbot_acme_challenge_method }}-credentials {{ certbot_credentials_file }}
--dns-{{ certbot_acme_challenge_method }}-propagation-seconds 60
{% else %}
--webroot
-w /var/lib/letsencrypt/
{% endif %}
-d {{ domain }}
{{ '--test-cert' if mode_test | bool else '' }}
register: certbot_result
changed_when: "'Certificate not yet due for renewal' not in certbot_result.stdout"
when:
- not enable_wildcard_certificate | bool or not (domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain))
# Wildcard certificate should not be used
# OR: The domain is not a first-level subdomain of the primary domain
# The following should not work, checkout the Setup.md instructions.
# @see https://chatgpt.com/share/67efa9f0-1cdc-800f-8bce-62b00fc3e6a2
- name: "receive wildcard certificate *{{ primary_domain }} for {{domain}}"
command: >-
certbot certonly
--agree-tos
--email {{ users.administrator.email }}
--non-interactive
{% if certbot_acme_challenge_method != "webroot" %}
--dns-{{ certbot_acme_challenge_method }}
--dns-{{ certbot_acme_challenge_method }}-credentials {{ certbot_credentials_file }}
--dns-{{ certbot_acme_challenge_method }}-propagation-seconds 60
{% else %}
--webroot
-w /var/lib/letsencrypt/
{% endif %}
-d {{ primary_domain }}
-d *.{{ primary_domain }}
{{ '--test-cert' if mode_test | bool else '' }}
register: certbot_result
changed_when: "'Certificate not yet due for renewal' not in certbot_result.stdout"
when:
- enable_wildcard_certificate | bool
# Wildcard certificate is enabled
- domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain)
# AND: The domain is a direct first-level subdomain of the primary domain
- run_once_receive_certificate is not defined
# Ensure this task runs only once for the wildcard certificate
ignore_errors: true
- name: "Include flavor"
include_tasks: "{{ role_path }}/tasks/flavors/{{ certbot_flavor }}.yml"
- name: "Cleanup dedicated cert for {{ domain }}"
command: >-
@@ -57,7 +7,7 @@
when:
- mode_cleanup | bool
# Cleanup mode is enabled
- enable_wildcard_certificate | bool
- certbot_flavor != 'dedicated'
# Wildcard certificate is enabled
- domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain)
# AND: The domain is a direct first-level subdomain of the primary domain
@@ -67,7 +17,15 @@
failed_when: certbot_result.rc != 0 and ("No certificate found with name" not in certbot_result.stderr)
changed_when: certbot_result.rc == 0 and ("No certificate found with name" not in certbot_result.stderr)
- name: run the receive_certificate tasks once
- name: Find SSL cert folder for domain
find_cert_folder:
domain: "{{ domain }}"
certbot_flavor: "{{ certbot_flavor }}"
cert_base_path: "{{ certbot_cert_path }}"
debug: "{{ enable_debug | default(false) }}"
register: cert_folder_result
delegate_to: "{{ inventory_hostname }}"
- name: Set fact
set_fact:
run_once_receive_certificate: true
when: run_once_receive_certificate is not defined
ssl_cert_folder: "{{ cert_folder_result.folder }}"