mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-10-31 18:29:21 +00:00 
			
		
		
		
	Optimized DKIM and DNS for mailu
This commit is contained in:
		| @@ -6,7 +6,7 @@ Use the following tools to monitor your domain and email deliverability: | ||||
|  | ||||
| - [Google Postmaster](https://postmaster.google.com/) - Analyzes deliverability and spam issues for Gmail. | ||||
| - [Yahoo Postmaster](https://postmaster.yahooinc.com) - Provides insights and delivery reports for Yahoo. | ||||
| - [mxtoolbox.com](https://mxtoolbox.com) | ||||
| - [MXToolbox](https://mxtoolbox.com) | ||||
|  | ||||
| ## Blacklist Check 🚫 | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								roles/docker-mailu/tasks/TODO.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								roles/docker-mailu/tasks/TODO.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| # Todos | ||||
| - Check if DKIM generation works on new setups | ||||
							
								
								
									
										13
									
								
								roles/docker-mailu/tasks/generate-and-read-dkim.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								roles/docker-mailu/tasks/generate-and-read-dkim.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| - name: Generate DKIM key | ||||
|   command: > | ||||
|     docker compose exec -T antispam | ||||
|     rspamadm dkim_keygen -s dkim -d {{ applications[application_id].domain }} -k {{ applications[application_id].domain }}.dkim.key | ||||
|   register: dkim_keygen_output | ||||
|   chdir: "{{ docker_compose.directories.instance }}" | ||||
|  | ||||
| - name: Extract DKIM record from parentheses | ||||
|   set_fact: | ||||
|     mailu_dkim_public_key: >- | ||||
|       {{ dkim_keygen_output.stdout | ||||
|          | regex_search('(?s)\((.*?)\)', '\\1') | ||||
|          | default('') }} | ||||
| @@ -42,7 +42,26 @@ | ||||
|     loop_var: item | ||||
|   when: run_once_docker_mailu is not defined | ||||
|  | ||||
| - name: Run the docker_mailu tasks once | ||||
| - name: "Load Mailu DNS variables" | ||||
|   include_vars: vars/mailu-dns.yml | ||||
|   when: dns_provider == 'cloudflare' | ||||
|  | ||||
| - name: Generate DKIM public key | ||||
|   include_tasks: generate-and-read-dkim.yml | ||||
|   when: | ||||
|     - not applications[application_id].credentials.dkim_public_key is defined | ||||
|  | ||||
| - name: Set DKIM public key | ||||
|   set_fact: | ||||
|     mailu_dkim_public_key: >- | ||||
|       {{ applications[application_id].credentials.dkim_public_key }} | ||||
|   when: applications[application_id].credentials.dkim_public_key is defined | ||||
|  | ||||
| - name: Set Mailu DNS records | ||||
|   include_tasks: set-mailu-dns-records.yml | ||||
|   when: dns_provider == 'cloudflare' | ||||
|  | ||||
| - name: Run the docker_mailu roles once | ||||
|   set_fact: | ||||
|     run_once_docker_mailu: true | ||||
|   when: run_once_docker_mailu is not defined | ||||
							
								
								
									
										80
									
								
								roles/docker-mailu/tasks/set-mailu-dns-records.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								roles/docker-mailu/tasks/set-mailu-dns-records.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| - name: "Set A record for mail server" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: A | ||||
|     name: "{{ domain }}" | ||||
|     content: "{{ mailu_dns_ip }}" | ||||
|     proxied: false | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
|  | ||||
| - name: "Set CNAME record for autoconfig" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: CNAME | ||||
|     name: "autoconfig.{{ mailu_dns_zone }}" | ||||
|     value: "{{ domain }}" | ||||
|     proxied: false | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
|  | ||||
| - name: "Set MX record" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: MX | ||||
|     name: "{{ mailu_dns_zone }}" | ||||
|     value: "{{ domain }}" | ||||
|     priority: 10 | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
|  | ||||
| - name: "Set SRV records" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: SRV | ||||
|     name: "_{{ item.key }}._tcp" | ||||
|     data: | ||||
|       service: "_{{ item.key }}" | ||||
|       proto: "_tcp" | ||||
|       name: "{{ mailu_dns_zone }}" | ||||
|       priority: "{{ item.value.priority }}" | ||||
|       weight: "{{ item.value.weight }}" | ||||
|       port: "{{ item.value.port }}" | ||||
|       target: "{{ domain }}" | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
|   loop: "{{ mailu_dns_srv_records | dict2items }}" | ||||
|  | ||||
| - name: "Set SPF TXT record" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: TXT | ||||
|     name: "{{ mailu_dns_zone }}" | ||||
|     value: "v=spf1 mx a:{{ domain }} ~all" | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
|  | ||||
| - name: "Set DMARC TXT record" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: TXT | ||||
|     name: "_dmarc.{{ mailu_dns_zone }}" | ||||
|     value: "v=DMARC1; p=reject; ruf=mailto:{{ mailu_dmarc_ruf }}; adkim=s; aspf=s" | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
|  | ||||
| - name: "Set DKIM TXT record" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ cloudflare_record_api_token }}" | ||||
|     zone: "{{ mailu_dns_zone }}" | ||||
|     type: TXT | ||||
|     name: "dkim._domainkey.{{ mailu_dns_zone }}" | ||||
|     value: "{{ mailu_dkim_public_key }}" | ||||
|     ttl: 3600 | ||||
|     state: present | ||||
							
								
								
									
										38
									
								
								roles/docker-mailu/vars/mailu-dns.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								roles/docker-mailu/vars/mailu-dns.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| # vars/mailu-dns.yml | ||||
|  | ||||
| mailu_dns_zone: "{{ applications[application_id].domain }}" | ||||
| mailu_dns_ip:   "{{ networks.internet.ip4 }}" | ||||
|  | ||||
| cloudflare_record_api_token: "{{ certbot_dns_api_token }}" | ||||
|  | ||||
| mailu_dmarc_ruf: "{{ applications[application_id].users.administrator.email }}" | ||||
|  | ||||
| mailu_dns_srv_records: | ||||
|   submission: | ||||
|     port: 587 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
|   submissions: | ||||
|     port: 465 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
|   imaps: | ||||
|     port: 993 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
|   imap: | ||||
|     port: 143 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
|   pop3s: | ||||
|     port: 995 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
|   pop3: | ||||
|     port: 110 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
|   autodiscover: | ||||
|     port: 443 | ||||
|     priority: 20 | ||||
|     weight: 1 | ||||
| @@ -5,6 +5,12 @@ | ||||
|   notify: restart nginx | ||||
|   when: run_once_letsencrypt is not defined | ||||
|  | ||||
| - name: "Set CAA records for all base domains" | ||||
|   include_tasks: set-caa-records.yml | ||||
|   when: | ||||
|     - dns_provider == 'cloudflare' | ||||
|     - run_once_letsencrypt is not defined | ||||
|  | ||||
| - name: flush nginx service | ||||
|   meta: flush_handlers | ||||
|   when: run_once_letsencrypt is not defined | ||||
|   | ||||
							
								
								
									
										28
									
								
								roles/letsencrypt/tasks/set-caa-records.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								roles/letsencrypt/tasks/set-caa-records.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| --- | ||||
| # tasks/main.yml | ||||
| # Creates and sets CAA records (issue, issuewild, iodef) for all base domains | ||||
|  | ||||
| - name: "Define CAA entries" | ||||
|   set_fact: | ||||
|     caa_entries: | ||||
|       - tag: issue | ||||
|         value: "letsencrypt.org" | ||||
|       - tag: issuewild | ||||
|         value: "letsencrypt.org" | ||||
|       - tag: iodef | ||||
|         value: "mailto:{{ users.administrator.email }}" | ||||
|  | ||||
| - name: "Ensure all CAA records are present" | ||||
|   community.general.cloudflare_dns: | ||||
|     api_token: "{{ certbot_dns_api_token }}" | ||||
|     zone:     "{{ item.0 }}" | ||||
|     record:   "@" | ||||
|     type:     CAA | ||||
|     flag:     0 | ||||
|     tag:      "{{ item.1.tag }}" | ||||
|     value:    "{{ item.1.value }}" | ||||
|     ttl:      1 | ||||
|     state:    present | ||||
|   loop: "{{ base_sld_domains | product(caa_entries) | list }}" | ||||
|   loop_control: | ||||
|     label: "{{ item.0 }} → {{ item.1.tag }}" | ||||
| @@ -71,6 +71,10 @@ | ||||
|           + (redirect_domain_mappings | map(attribute='source') | list) | ||||
|         }} | ||||
|  | ||||
|   - name: Extract sld.tld from base_domains | ||||
|     set_fact: | ||||
|       base_sld_domains: "{{ base_domains | map('regex_replace', '^(?:.*\\.)?([^.]+\\.[^.]+)$', '\\1') | list | unique | sort }}" | ||||
|  | ||||
|   - name: Initialise all_domains as empty list | ||||
|     set_fact: | ||||
|       all_domains: [] | ||||
|   | ||||
| @@ -319,7 +319,9 @@ defaults_applications: | ||||
|  | ||||
|   mailu: | ||||
|     version:                          "2024.06"                                   # Docker Image Version | ||||
|     setup:                            false                                       # Set true in inventory file to execute the setup and initializing procedures | ||||
|     users: | ||||
|       adminsitrator: | ||||
|         email:                        "{{users.administrator.email}}"             # Administrator Email for DNS Records | ||||
|     oidc: | ||||
|       email_by_username:              true                                        # If true, then the mail is set by the username. If wrong then the OIDC user email is used | ||||
|       enable_user_creation:           true                                        # Users will be created if not existing | ||||
| @@ -329,6 +331,7 @@ defaults_applications: | ||||
| #     database_password:                                                          # Needs to be set in inventory file | ||||
| #     api_token:                                                                  # Configures the authentication token. The minimum length is 3 characters. This is a mandatory setting for using the RESTful API. | ||||
| #     initial_administrator_password:                                             # Initial administrator password for setup  | ||||
| #     dkim_public_key:                                                            # Must be set in inventory file | ||||
| {% endraw %}{{ features.render_features({ | ||||
|   'matomo':   true, | ||||
|   'css':      true, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user