Solved bug existed due to difference between mailu domain and hostname difference. also refactored during this to find the bug

This commit is contained in:
2025-08-16 14:29:07 +02:00
parent 1bed83078e
commit 0de26fa6c7
76 changed files with 543 additions and 487 deletions

View File

@@ -1,10 +1,23 @@
- name: "load docker, db and proxy for {{ application_id }}"
include_role:
name: cmp-db-docker-proxy
- name: Ensure MAILU_HOSTNAMES is a list with max 1 entry
ansible.builtin.assert:
that:
- MAILU_HOSTNAMES is iterable
- MAILU_HOSTNAMES is sequence
- MAILU_HOSTNAMES | length <= 1
fail_msg: "MAILU_HOSTNAMES must be a list with at most one entry (only one host is supported). You can set the other ones as alias."
success_msg: "MAILU_HOSTNAMES is valid."
- name: "Include the srv-proxy-6-6-tls-deploy role"
include_role:
name: srv-proxy-6-6-tls-deploy
- name: "Mailu Docker and Webserver Setup"
block:
- name: "load docker, db and proxy for {{ application_id }}"
include_role:
name: cmp-db-docker-proxy
- name: "Include the sys-svc-cert-sync-docker role"
include_role:
name: sys-svc-cert-sync-docker
vars:
domain: "{{ MAILU_HOSTNAME }}"
- name: Flush docker service handlers
meta: flush_handlers
@@ -12,10 +25,8 @@
- name: "Create Mailu accounts"
include_tasks: 02_create-mailu-user.yml
vars:
mailu_compose_dir: "{{ docker_compose.directories.instance }}"
mailu_domain: "{{ PRIMARY_DOMAIN }}"
MAILU_DOCKER_DIR: "{{ docker_compose.directories.instance }}"
mailu_api_base_url: "http://127.0.0.1:8080/api/v1"
mailu_global_api_token: "{{ applications | get_app_conf(application_id, 'credentials.api_token') }}"
mailu_action: >-
{{
(

View File

@@ -1,9 +1,9 @@
- name: "Ensure Mailu user '{{ mailu_user_key }};{{ mailu_user_name }}@{{ mailu_domain }}'' exists"
- name: "Ensure Mailu user '{{ mailu_user_key }};{{ mailu_user_name }}@{{ MAILU_DOMAIN }}'' exists"
command: >
docker compose exec admin flask mailu {{ mailu_action }}
{{ mailu_user_name }} {{ mailu_domain }} '{{ mailu_password }}'
{{ mailu_user_name }} {{ MAILU_DOMAIN }} '{{ mailu_password }}'
args:
chdir: "{{ mailu_compose_dir }}"
chdir: "{{ MAILU_DOCKER_DIR }}"
register: mailu_user_result
failed_when: >
mailu_user_result.rc != 0 and
@@ -15,12 +15,12 @@
when: "'mail-bot' in item.value.roles or 'administrator' in item.value.roles"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "Change password for user '{{ mailu_user_key }};{{ mailu_user_name }}@{{ mailu_domain }}'"
- name: "Change password for user '{{ mailu_user_key }};{{ mailu_user_name }}@{{ MAILU_DOMAIN }}'"
command: >
docker compose exec admin flask mailu password
{{ mailu_user_name }} {{ mailu_domain }} '{{ mailu_password }}'
{{ mailu_user_name }} {{ MAILU_DOMAIN }} '{{ mailu_password }}'
args:
chdir: "{{ mailu_compose_dir }}"
chdir: "{{ MAILU_DOCKER_DIR }}"
when: "'mail-bot' in item.value.roles or 'administrator' in item.value.roles"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"

View File

@@ -3,9 +3,9 @@
command: >-
docker compose exec -T admin \
curl -s -X GET {{ mailu_api_base_url }}/token \
-H "Authorization: Bearer {{ mailu_global_api_token }}"
-H "Authorization: Bearer {{ MAILU_API_TOKEN }}"
args:
chdir: "{{ mailu_compose_dir }}"
chdir: "{{ MAILU_DOCKER_DIR }}"
register: mailu_tokens_cli
changed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
@@ -25,9 +25,9 @@
command: >-
docker compose exec -T admin \
curl -s -X DELETE {{ mailu_api_base_url }}/token/{{ mailu_user_existing_token.id }} \
-H "Authorization: Bearer {{ mailu_global_api_token }}"
-H "Authorization: Bearer {{ MAILU_API_TOKEN }}"
args:
chdir: "{{ mailu_compose_dir }}"
chdir: "{{ MAILU_DOCKER_DIR }}"
when:
- users[mailu_user_key].mailu_token is not defined
- mailu_user_existing_token is not none
@@ -40,7 +40,7 @@
command: >-
docker compose exec -T admin \
curl -s -X POST {{ mailu_api_base_url }}/token \
-H "Authorization: Bearer {{ mailu_global_api_token }}" \
-H "Authorization: Bearer {{ MAILU_API_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{{ {
"comment": mailu_user_key ~ " - ansible.infinito",
@@ -48,7 +48,7 @@
"ip": mailu_token_ip
} | to_json }}'
args:
chdir: "{{ mailu_compose_dir }}"
chdir: "{{ MAILU_DOCKER_DIR }}"
when: users[mailu_user_key].mailu_token is not defined
register: mailu_token_creation
changed_when: mailu_token_creation.rc == 0

View File

@@ -1,108 +1,125 @@
- name: "Load Mailu DNS variables"
include_vars: vars/mailu-dns.yml
- name: Generate DKIM public key
include_tasks: 05_generate-and-read-dkim.yml
- name: "Set A record for mail server"
# A/AAAA record for the mail host in the **Hostname Zone**
- name: "Set A record for Mailu host"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_HOSTNAME_DNS_ZONE }}"
type: A
name: "{{ domain }}"
content: "{{ mailu_dns_ip }}"
name: "{{ MAILU_HOSTNAME }}" # Fully Qualified Domain Name of the mail host
content: "{{ MAILU_IP4_PUBLIC }}"
proxied: false
ttl: 1
state: present
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "Set AAAA record for Mailu host"
community.general.cloudflare_dns:
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_HOSTNAME_DNS_ZONE }}"
type: AAAA
name: "{{ MAILU_HOSTNAME }}"
content: "{{ MAILU_IP6_PUBLIC }}"
proxied: false
ttl: 1
state: present
when: MAILU_IP6_PUBLIC is defined and MAILU_IP6_PUBLIC | length > 0
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
# Autoconfig CNAME record in the **Mail Domain Zone**
- name: "Set CNAME record for autoconfig"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_DOMAIN_DNS_ZONE }}"
type: CNAME
name: "autoconfig.{{ mailu_dns_zone }}"
value: "{{ domain }}"
name: "autoconfig.{{ MAILU_DOMAIN_DNS_ZONE }}"
value: "{{ MAILU_HOSTNAME }}" # Points to the Mailu host FQDN
proxied: false
ttl: 1
state: present
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
# MX record in the **Mail Domain Zone**
- name: "Set MX record"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_DOMAIN_DNS_ZONE }}"
type: MX
name: "{{ mailu_dns_zone }}"
value: "{{ domain }}"
name: "{{ MAILU_DOMAIN }}" # Root mail domain
value: "{{ MAILU_HOSTNAME }}" # Points to the Mailu host
priority: 10
ttl: 1
state: present
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
# SRV records in the **Mail Domain Zone**
- name: "Set SRV records"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_DOMAIN_DNS_ZONE }}"
type: SRV
service: "_{{ item.key }}"
proto: "_tcp"
priority: "{{ item.value.priority }}"
weight: "{{ item.value.weight }}"
port: "{{ item.value.port }}"
value: "{{ domain }}"
value: "{{ MAILU_HOSTNAME }}" # Target = Mailu host FQDN
ttl: 1
state: present
loop: "{{ mailu_dns_srv_records | dict2items }}"
name: "{{ MAILU_DOMAIN }}"
loop: "{{ MAILU_DNS_SRV_RECORDS | dict2items }}"
ignore_errors: true
#register: srv_result
#failed_when: srv_result.rc != 0 and ("An identical record already exists" not in srv_result.stdout)
#changed_when: srv_result.rc == 0 and ("An identical record already exists" not in srv_result.stdout)
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
# SPF TXT record in the **Mail Domain Zone**
- name: "Set SPF TXT record"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_DOMAIN_DNS_ZONE }}"
type: TXT
name: "{{ mailu_dns_zone }}"
value: "v=spf1 mx a:{{ domain }} ~all"
name: "{{ MAILU_DOMAIN }}"
value: "v=spf1 mx a:{{ MAILU_HOSTNAME }} ~all"
ttl: 1
state: present
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
# DMARC TXT record in the **Mail Domain Zone**
- name: "Set DMARC TXT record"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_DOMAIN_DNS_ZONE }}"
type: TXT
name: "_dmarc.{{ mailu_dns_zone }}"
value: "v=DMARC1; p=reject; ruf=mailto:{{ mailu_dmarc_ruf }}; adkim=s; aspf=s"
name: "_dmarc.{{ MAILU_DOMAIN_DNS_ZONE }}"
value: "v=DMARC1; p=reject; ruf=mailto:{{ MAILU_DMARC_RUF }}; adkim=s; aspf=s"
ttl: 1
state: present
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
# DKIM TXT record in the **Mail Domain Zone**
- name: "Set DKIM TXT record"
community.general.cloudflare_dns:
api_token: "{{ cloudflare_record_api_token }}"
zone: "{{ mailu_dns_zone }}"
api_token: "{{ MAILU_CLOUDFLARE_API_TOKEN }}"
zone: "{{ MAILU_DOMAIN_DNS_ZONE }}"
type: TXT
name: "dkim._domainkey.{{ mailu_dns_zone }}"
name: "dkim._domainkey.{{ MAILU_DOMAIN_DNS_ZONE }}"
value: "{{ mailu_dkim_public_key }}"
ttl: 1
state: present
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"

View File

@@ -1,7 +1,7 @@
- name: Check if DKIM private key file exists in the antispam container
command: >
docker compose exec -T antispam
test -f {{ mailu_dkim_key_path }}
test -f {{ MAILU_DKIM_KEY_PATH }}
register: dkim_key_file_stat
failed_when: false
changed_when: false
@@ -11,7 +11,7 @@
- name: Generate DKIM key
command: >
docker compose exec -T antispam
rspamadm dkim_keygen -s dkim -d {{ applications | get_app_conf(application_id, 'domain', True) }} -k {{ mailu_dkim_key_path }}
rspamadm dkim_keygen -s dkim -d {{ MAILU_DOMAIN }} -k {{ MAILU_DKIM_KEY_PATH }}
register: dkim_keygen_output
when: dkim_key_file_stat.rc != 0
args:
@@ -21,7 +21,7 @@
- name: Fetch DKIM private key from antispam container
shell: >
docker compose exec -T antispam
cat {{ mailu_dkim_key_path }}
cat {{ MAILU_DKIM_KEY_PATH }}
args:
chdir: "{{ docker_compose.directories.instance }}"
register: dkim_priv_content